diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 000000000..39e9367b0 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,19 @@ +# Set default behaviour, in case users don't have core.autocrlf set. +* text=auto + +# Explicitly declare text files we want to always be normalized and converted +# to native line endings on checkout. +*.css text +*.html text +*.java text +*.js text +*.md text +*.py text +*.tmpl text +*.txt text +SCons* text + +# Denote all files that are truly binary and should not be modified. +*.gif binary +*.jar binary +*.png binary diff --git a/.gitignore b/.gitignore index d343b0aa5..aff5502f7 100644 --- a/.gitignore +++ b/.gitignore @@ -1,8 +1,14 @@ -*.log -*.log.1 -*.log.2 -*.log.3 -*.log.4 -*.log.5 -*.pyc -__pycache__ +*.log +*.log.1 +*.log.2 +*.log.3 +*.log.4 +*.log.5 +*.pyc +__pycache__ +.sconsign.dblite +test_report_*.xml + + +*.vcd +/software/openApps/ietf90client/*.config diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 000000000..daf893fe0 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,20 @@ +language: python +python: + - "2.7" + +# Install dependencies +before_install: + - sudo apt-get update -qq + - sudo apt-get install -qq python-tk +install: pip install -r requirements.txt --use-mirrors + +# Whitelist +#branches: +# only: +# - develop + +# Command to run tests +script: + - cd software/openvisualizer/ + - scons unittests + - scons docs \ No newline at end of file diff --git a/README.md b/README.md index c3228645e..268e56b65 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,20 @@ -openwsn-sw -========== - -OpenWSN software: stuff that runs on a computer +OpenWSN software: stuff that runs on a computer. Part of UC Berkeley's OpenWSN project, http://www.openwsn.org/. + +Build status +------------ + +| builder | build | outcome +| ------------------------------------------------------------------------------------ | --------------------- | ------- +| [Travis](https://travis-ci.org/openwsn-berkeley/openwsn-sw) | unit tests | [![Build Status](https://travis-ci.org/openwsn-berkeley/openwsn-sw.png?branch=develop)](https://travis-ci.org/openwsn-berkeley/openwsn-sw) +| [OpenWSN builder](http://builder.openwsn.org/job/OpenVisualizer%20Unit%20Tests/) | unit tests | [![Build Status](http://builder.openwsn.org/buildStatus/icon?job=OpenVisualizer Unit Tests)](http://builder.openwsn.org/job/OpenVisualizer%20Unit%20Tests/) +| [OpenWSN builder](http://builder.openwsn.org/job/OpenVisualizer%20Docs/) | build documentation | [![Build Status](http://builder.openwsn.org/buildStatus/icon?job=OpenVisualizer Docs)](http://builder.openwsn.org/job/OpenVisualizer%20Docs/) +| [OpenWSN builder](http://builder.openwsn.org/job/OpenVisualizer%20Docs%20Publisher/) | publish documentation | [![Build Status](http://builder.openwsn.org/buildStatus/icon?job=OpenVisualizer Docs Publisher)](http://builder.openwsn.org/job/OpenVisualizer%20Docs%20Publisher/) + + +Documentation +------------- + +- overview: https://openwsn.atlassian.net/wiki/ +- source code: http://openwsn-berkeley.github.io/openvisualizer/ diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 000000000..d169ae4ab --- /dev/null +++ b/requirements.txt @@ -0,0 +1,4 @@ +pyserial==2.6 +PyDispatcher==2.0.3 +bottle==0.11.6 +Sphinx==1.1.3 diff --git a/software/installtest/test_python_installation.py b/software/installtest/test_python_installation.py index eae2f90d8..61dd4d131 100644 --- a/software/installtest/test_python_installation.py +++ b/software/installtest/test_python_installation.py @@ -1,47 +1,47 @@ -import sys - -boiler = "================================\n" -boiler += "Python installation test script \n" -boiler += "Thomas Watteyne, August 2010 \n" -boiler += "================================" -print boiler - -#================== Python - -print "\nTesting Python...", -print "works!" - -#================== PySerial - -print "\nTesting PySerial...", - -try: - import serial -except: - err = sys.exc_info() - sys.stderr.write("Error: %s (%s) \n" % (str(err[0]), str(err[1]))) -else: - print "works!" - -#================== TkInter - -print "\nTesting TkInter...", - -def releaseAndQuit(): - root.quit() - sys.exit() - -try: - import Tkinter - root=Tkinter.Tk() - root.title("Testing TkInter") - root.protocol("WM_DELETE_WINDOW",releaseAndQuit) - root.resizable(0,0) -except: - err = sys.exc_info() - sys.stderr.write("Error: %s (%s) \n" % (str(err[0]), str(err[1]))) -else: - print "works!\n(make sure you can see the window titled \"Testing TkInter\")" - -raw_input("\nPress return to close this window...") - +import sys + +boiler = "================================\n" +boiler += "Python installation test script \n" +boiler += "Thomas Watteyne, August 2010 \n" +boiler += "================================" +print boiler + +#================== Python + +print "\nTesting Python...", +print "works!" + +#================== PySerial + +print "\nTesting PySerial...", + +try: + import serial +except: + err = sys.exc_info() + sys.stderr.write("Error: %s (%s) \n" % (str(err[0]), str(err[1]))) +else: + print "works!" + +#================== TkInter + +print "\nTesting TkInter...", + +def releaseAndQuit(): + root.quit() + sys.exit() + +try: + import Tkinter + root=Tkinter.Tk() + root.title("Testing TkInter") + root.protocol("WM_DELETE_WINDOW",releaseAndQuit) + root.resizable(0,0) +except: + err = sys.exc_info() + sys.stderr.write("Error: %s (%s) \n" % (str(err[0]), str(err[1]))) +else: + print "works!\n(make sure you can see the window titled \"Testing TkInter\")" + +raw_input("\nPress return to close this window...") + diff --git a/software/openApps/6tusCli/sixtusCli.py b/software/openApps/6tusCli/sixtusCli.py new file mode 100644 index 000000000..7021a10ef --- /dev/null +++ b/software/openApps/6tusCli/sixtusCli.py @@ -0,0 +1,119 @@ + + + +''' +Created on 02/05/2013 + +@author: xvilajosana +''' +import logging +class NullHandler(logging.Handler): + def emit(self, record): + pass +log = logging.getLogger('sixtusCli') +log.setLevel(logging.DEBUG) +log.addHandler(NullHandler()) + + +import sys +import os +import threading + +if __name__=='__main__': + cur_path = sys.path[0] + sys.path.insert(0, os.path.join(cur_path, '..', '..','..','..','coap','coap')) # coap/ + sys.path.insert(0, os.path.join(cur_path, '..', '..','openvisualizer','eventBus','PyDispatcher-2.0.3'))# PyDispatcher-2.0.3/ + sys.path.insert(0, os.path.join(cur_path, '..', '..', 'openCli')) # openCli/ + + +from OpenCli import OpenCli + +from sixtusCoap import sixtusCoap + +class sixtusCli(OpenCli): + + + def __init__(self): + + # initialize parent class + OpenCli.__init__(self,"6tus client",self.quit_cb) + + self.sixtusCoap = sixtusCoap() + # add commands + # 1415:923b::009e 7 2 0 11 + self.registerCommand('create_link', + 'c', + 'create a link', + ['dst_url','target_addr','slot_num','slot_type','shared','ch_offset'], + self._handlerCreateLink) + + self.registerCommand('update_link', + 'u', + 'updates a link', + ['dst_url','target_addr','slot_num','slot_type','shared','ch_offset'], + self._handlerUpdateLink) + + # add commands + self.registerCommand('read_link', + 'r', + 'reads a link from the schedule', + ['dst_url','target_addr','slot_num',], + self._handlerReadLink) + # add commands + self.registerCommand('delete_link', + 'd', + 'deletes a link from the schedule', + ['dst_url','target_addr','slot_num',], + self._handlerDeleteLink) + + + + #example query from terminal: c BBBB::1415:920b:0301:00f2 BBBB::1415:920b:0301:00e9 7 2 0 11 + def _handlerCreateLink(self,params): + print 'CREATE_LINK: ' + ' '.join(params) + log.debug('CREATE_LINK: ' + ' '.join(params)) + self.sixtusCoap.CREATE_LINK(params[0],params[1],params[2],params[3],params[4],params[5]) + + def _handlerUpdateLink(self,params): + print 'UPDATE_LINK: ' + ' '.join(params) + log.debug('UPDATE_LINK: ' + ' '.join(params)) + self.sixtusCoap.UPDATE_LINK(params[0],params[1],params[2],params[3],params[4],params[5]) + + #the url will look like coap://[2001:0470:48b8:aaaa:1415:920b:0301:00e9]:5683/6tus/1/1/1415923b0000009e/3 + #the command to issue: r BBBB::1415:923b:0301:00e9 1415:923b::009e 7 + def _handlerReadLink(self,params): + print 'READ_LINK: ' + ' '.join(params) + log.debug('READ_LINK: ' + ' '.join(params)) + self.sixtusCoap.READ_LINK(params[0],params[1],params[2]) + + + def _handlerDeleteLink(self,params): + print 'DELETE_LINK: ' + ' '.join(params) + log.debug('DELETE_LINK: ' + ' '.join(params)) + self.sixtusCoap.DELETE_LINK(params[0],params[1],params[2]) + #===== helpers + + def quit_cb(self): + print "quit" + +#this initializes everything +def main(): + + cli = sixtusCli() + cli.start() + +#============================ application logging ============================= +import logging +import logging.handlers +logHandler = logging.handlers.RotatingFileHandler('sixtusCli.log', + maxBytes=2000000, + backupCount=5, + mode='w') +logHandler.setFormatter(logging.Formatter("%(asctime)s [%(name)s:%(levelname)s] %(message)s")) +for loggerName in ['sixtusCli','sixtusCoap']: + temp = logging.getLogger(loggerName) + temp.setLevel(logging.DEBUG) + temp.addHandler(logHandler) + +if __name__=="__main__": + main() \ No newline at end of file diff --git a/software/openApps/6tusCli/sixtusCoap.py b/software/openApps/6tusCli/sixtusCoap.py new file mode 100644 index 000000000..d1052bc5b --- /dev/null +++ b/software/openApps/6tusCli/sixtusCoap.py @@ -0,0 +1,170 @@ +''' +Created on 03/05/2013 + +@author: xvilajosana +''' + +import logging +class NullHandler(logging.Handler): + def emit(self, record): + pass +log = logging.getLogger('sixtusCoap') +log.setLevel(logging.DEBUG) +log.addHandler(NullHandler()) + + +from coap import * +import coapDefines as d + +class sixtusCoap(object): + + CREATE_LINK_TYPE = 0 + READ_LINK_TYPE = 1 + UPDATE_LINK_TYPE = 2 + DELETE_LINK_TYPE = 3 + + CELLTYPE_OFF = 0 + CELLTYPE_ADV = 1 + CELLTYPE_TX = 2 + CELLTYPE_RX = 3 + CELLTYPE_TXRX = 4 + CELLTYPE_SERIALRX = 5 + CELLTYPE_MORESERIALRX = 6 + RESOURCE = "6tus" + + def __init__(self): + #get my address from interface?? + self.src = "BBBB::1" + #self.dst = "coap://[BBBB::1415:923b:0301:00e9]/6tus" + self.coap = coap(self.src) + # store params + + #======================== public ========================================== + + def CREATE_LINK(self,dst_url,target_addr,slot_num,slot_type,shared,ch_offset): + params = [] + params += [self.CREATE_LINK_TYPE] + params += [1] #one link + target_addr=self._convertAddress2bytes(target_addr) + params += target_addr + params += [int(slot_type)] + params += [int(shared)] + #2bytes slotnum: + slotnum=int(slot_num) + byte1=(slotnum>>8)&0x00FF + byte2=(slotnum)&0x00FF + params += [byte2] + params += [byte1] + params += [int(ch_offset)] + + log.debug('Following PUT command entered:'+ ",".join( str(c) for c in params)) + + url='coap://[{0}]:{1}/{2}/'.format(dst_url,d.DEFAULT_UDP_PORT,self.RESOURCE) + try: + self.coap.PUT(uri=url,payload=params) + except Exception as err: + log.error("Cannot access the resource {0}:{1}".format(url,err)) + print "Cannot access the resource {0}:{1}".format(url,err) + + + + def UPDATE_LINK(self,dst_url,target_addr,slot_num,slot_type,shared,ch_offset): + params = [] + params += [self.UPDATE_LINK_TYPE] + params += [1] #one link + target_addr=self._convertAddress2bytes(target_addr) + params += target_addr + params += [int(slot_type)] + params += [int(shared)] + #2bytes slotnum: + slotnum=int(slot_num) + byte1=(slotnum>>8)&0x00FF + byte2=(slotnum)&0x00FF + params += [byte2] + params += [byte1] + params += [int(ch_offset)] + log.debug('Following UPDATE command entered:'+ ",".join( str(c) for c in params)) + + url='coap://[{0}]:{1}/{2}/'.format(dst_url,d.DEFAULT_UDP_PORT,self.RESOURCE) + try: + self.coap.PUT(uri=url,payload=params) + except Exception as err: + log.error("Cannot access the resource {0}:{1}".format(url,err)) + print "Cannot access the resource {0}:{1}".format(url,err) + + def READ_LINK(self,dst_url,target_addr,slot_num): + target_addr=self._convertAddress2bytes(target_addr) + url='coap://[{0}]:{1}/{2}/{3}/{4}/{5}/{6}'.format(dst_url,d.DEFAULT_UDP_PORT,self.RESOURCE,self.READ_LINK_TYPE,1,target_addr,slot_num) + log.debug('Following GET command entered:'+ url) + print url + try: + res=self.coap.GET(uri=url) + return res + except Exception as err: + log.error("Cannot access the resource {0}:{1}".format(url,err)) + print "Cannot access the resource {0}:{1}".format(url,err) + + def DELETE_LINK(self,dst_url,target_addr,slot_num): + params = [] + params += [self.DELETE_LINK_TYPE] + params += [1] #one link + target_addr=self._convertAddress2bytes(target_addr) + params += target_addr + #2bytes slotnum: + slotnum=int(slot_num) + byte1=(slotnum>>8)&0x00FF + byte2=(slotnum)&0x00FF + params += [byte2] + params += [byte1] + url='coap://[{0}]:{1}/{2}/'.format(dst_url,d.DEFAULT_UDP_PORT,self.RESOURCE) + log.debug('Following DELETE command entered:'+ ",".join( str(c) for c in params)) + try: + res=self.coap.DELETE(uri=url,payload=params) + except Exception as err: + log.error("Cannot access the resource {0}:{1}".format(url,err)) + print "Cannot access the resource {0}:{1}".format(url,err) + + def quit(self): + raise NotImplementedError() + + + + + + #======================== public ========================================== + + + + + #======================== private ========================================= + + def hex2buf(self,s): + ''' + \brief Convert a string of hex caracters into a byte list. + + That is: 'abcdef00' -> [0xab,0xcd,0xef,0x00] + + \param[in] s The string to convert + + \returns A list of integers, each element in [0x00..0xff]. + ''' + assert type(s)==str + assert len(s)%2 == 0 + + returnVal = [] + + for i in range(len(s)/2): + realIdx = i*2 + returnVal.append(int(s[realIdx:realIdx+2],16)) + + return returnVal + + def _convertAddress2bytes(self,target_addr): + #format target so i can travel in the payload + try: + target_addr=target_addr.split("::")[1] + except:#if it does not have :: nothing happens + pass + newstr = target_addr.replace(":", "") + return self.hex2buf(newstr) + \ No newline at end of file diff --git a/software/openApps/README.txt b/software/openApps/README.txt new file mode 100644 index 000000000..66498fc06 --- /dev/null +++ b/software/openApps/README.txt @@ -0,0 +1 @@ +This folder contains applications that make use OpenWSN. \ No newline at end of file diff --git a/software/openApps/ietf90client/ietf90client.py b/software/openApps/ietf90client/ietf90client.py new file mode 100644 index 000000000..cdf03b387 --- /dev/null +++ b/software/openApps/ietf90client/ietf90client.py @@ -0,0 +1,476 @@ +import os +import sys +import Tkinter +import tkMessageBox +import re +import time +import struct +import threading + +if __name__=='__main__': + here = sys.path[0] + sys.path.insert(0, os.path.join(here, '..','..','..','..','coap')) + +from coap import coap +from coap import coapDefines as d + +CONFIG_FILENAME = '{0}.config'.format(os.path.basename(__file__).split('.')[0]) +DFLT_IPv6 = 'bbbb::' +DFLT_PERIOD = 10 +GUI_REFRESH_MS = 500 + +class ThreadDeferrer(threading.Thread): + def __init__(self,cmd,args=[],kwargs={},cb_ok=None,cb_fail=None): + self.cmd = cmd + self.args = args + self.kwargs = kwargs + self.cb_ok = cb_ok + self.cb_fail = cb_fail + threading.Thread.__init__(self) + self.start() + def run(self): + try: + response = self.cmd(*self.args,**self.kwargs) + except Exception as err: + if self.cb_fail: + self.cb_fail(err) + else: + if self.cb_ok: + self.cb_ok(response) + +class IETF90Client(object): + + #=== singleton pattern start === + _instance = None + _init = False + def __new__(cls, *args, **kwargs): + if not cls._instance: + cls._instance = super(IETF90Client, cls).__new__(cls, *args, **kwargs) + return cls._instance + #=== singleton pattern stop === + + def __init__(self): + + #=== singleton pattern start === + if self._init: + return + self._init = True + #=== singleton pattern stop === + + # local variables + self.dataLock = threading.RLock() + self.coap = coap.coap() + self.busy = False + self.statusBusy = False + self._status = '' + self.statusStart = None + self.period = None + + #===== getStormPeriod + + def getStormPeriod(self,ipv6): + with self.dataLock: + if self.busy: + self.statusBusy = True + return + + uri = 'coap://[{0}]/storm'.format(ipv6) + with self.dataLock: + self.busy = True + self.statusBusy = False + self.status = 'GET {0}'.format(uri) + self.statusStart = time.time() + + ThreadDeferrer( + cmd = self.coap.GET, + args = [uri], + kwargs = {}, + cb_ok = self.getStormPeriod_cb_ok, + cb_fail = self.getStormPeriod_cb_fail, + ) + + def getStormPeriod_cb_ok(self,response): + try: + period = struct.unpack('>H',''.join([chr(c) for c in response]))[0] + except Exception as err: + with self.dataLock: + self.status = 'Failed: {0}'.format(err) + else: + with self.dataLock: + self.status = 'GET success' + self.period = period + finally: + with self.dataLock: + self.busy = False + self.statusBusy = False + self.statusStart = None + + def getStormPeriod_cb_fail(self,err): + with self.dataLock: + self.busy = False + self.statusBusy = False + self.status = 'GET failed: {0}'.format(err) + self.statusStart = None + + #===== setStormPeriod + + def setStormPeriod(self,ipv6,period): + with self.dataLock: + if self.busy: + self.statusBusy = True + return + + uri = 'coap://[{0}]/storm'.format(ipv6) + + with self.dataLock: + self.busy = True + self.statusBusy = False + self.status = 'PUT {0} period={1}'.format(uri,period) + self.statusStart = time.time() + ThreadDeferrer( + cmd = self.coap.PUT, + args = [uri], + kwargs = {'payload': [ ord(c) for c in struct.pack('>H',period) ]}, + cb_ok = self.setStormPeriod_cb_ok, + cb_fail = self.setStormPeriod_cb_fail, + ) + + def setStormPeriod_cb_ok(self,response): + with self.dataLock: + self.busy = False + self.statusBusy = False + self.status = 'PUT success' + self.statusStart = None + + def setStormPeriod_cb_fail(self,err): + with self.dataLock: + self.busy = False + self.statusBusy = False + self.status = 'PUT failed: {0}'.format(err) + self.statusStart = None + + #===== add6topCell + + def add6topCell(self,ipv6): + with self.dataLock: + if self.busy: + self.statusBusy = True + return + + uri = 'coap://[{0}]/6t'.format(ipv6) + with self.dataLock: + self.busy = True + self.statusBusy = False + self.status = 'PUT {0}'.format(uri) + self.statusStart = time.time() + + ThreadDeferrer( + cmd = self.coap.PUT, + args = [uri], + kwargs = {}, + cb_ok = self.add6topCell_cb_ok, + cb_fail = self.add6topCell_cb_fail, + ) + + def add6topCell_cb_ok(self,response): + with self.dataLock: + self.busy = False + self.statusBusy = False + self.status = 'PUT success' + self.statusStart = None + + def add6topCell_cb_fail(self,err): + with self.dataLock: + self.busy = False + self.statusBusy = False + self.status = 'PUT failed: {0}'.format(err) + self.statusStart = None + + #===== delete6topCell + + def delete6topCell(self,ipv6): + with self.dataLock: + if self.busy: + self.statusBusy = True + return + + uri = 'coap://[{0}]/6t'.format(ipv6) + with self.dataLock: + self.busy = True + self.statusBusy = False + self.status = 'DELETE {0}'.format(uri) + self.statusStart = time.time() + + ThreadDeferrer( + cmd = self.coap.DELETE, + args = [uri], + kwargs = {}, + cb_ok = self.delete6topCell_cb_ok, + cb_fail = self.delete6topCell_cb_fail, + ) + + def delete6topCell_cb_ok(self,response): + with self.dataLock: + self.busy = False + self.statusBusy = False + self.status = 'DELETE success' + self.statusStart = None + + def delete6topCell_cb_fail(self,err): + with self.dataLock: + self.busy = False + self.statusBusy = False + self.status = 'DELETE failed: {0}'.format(err) + self.statusStart = None + + #===== getters + + def getStatus(self): + with self.dataLock: + returnVal = [] + if self.statusBusy: + returnVal += ['[busy] '] + returnVal += [self.status] + if self.statusStart!=None: + returnVal += [' ({0}s)'.format(int(time.time()-self.statusStart))] + returnVal = ''.join(returnVal) + return returnVal + + def getPeriod(self): + with self.dataLock: + returnVal = self.period + self.period = None + return returnVal + + #===== getters + + @property + def status(self): + with self.dataLock: + return self._status + + @status.setter + def status(self,value): + print value + with self.dataLock: + self._status = value + + #===== admin + + def close(self): + self.coap.close() + self._instance = None + self._init = False + +class IETF90ClientGUI(object): + + def __init__(self): + + #=== read configuration from file + (ipv6,period) = self._readConfigFile() + + #=== local variable + self.guiroot = Tkinter.Tk() + self.guiroot.resizable(False,False) + self.ipv6_addr = Tkinter.StringVar() + self.ipv6_addr.set(ipv6) + self.period = Tkinter.IntVar() + self.period.set(period) + self.status = Tkinter.StringVar() + self.status.set('') + + #=== create GUI interface + + # close button + self.guiroot.protocol("WM_DELETE_WINDOW", self._cb_close) + + # title + self.guiroot.wm_title("IETF90 CoAP client - OpenWSN") + + # row: ipv6 + f = Tkinter.Frame(self.guiroot,padx=5,pady=5) + Tkinter.Label(f,text="coap://[").pack(side=Tkinter.LEFT,expand=Tkinter.NO) + Tkinter.Entry(f,textvariable=self.ipv6_addr,width=40).pack(side=Tkinter.LEFT,expand=Tkinter.YES,fill=Tkinter.X) + Tkinter.Label(f,text="]/").pack(side=Tkinter.LEFT,expand=Tkinter.NO) + f.pack(side=Tkinter.TOP,expand=Tkinter.YES,fill=Tkinter.X) + + # row: separator + f = Tkinter.Frame(self.guiroot,height=2,bd=1,relief=Tkinter.SUNKEN,padx=5,pady=5) + f.pack(side=Tkinter.TOP,fill=Tkinter.X) + + # row: /storm + f = Tkinter.Frame(self.guiroot,padx=5,pady=5) + Tkinter.Label(f,text="/storm period=").pack(side=Tkinter.LEFT,expand=Tkinter.NO) + self.guiPeriod = Tkinter.Entry(f,textvariable=self.period,width=10) + self.guiPeriod.pack(side=Tkinter.LEFT,expand=Tkinter.NO) + self.guiPeriod.after(GUI_REFRESH_MS,self._refresh_period) + Tkinter.Button(f,text="PUT",width=10,command=self._cb_storm_PUT,default=Tkinter.ACTIVE).pack(side=Tkinter.RIGHT,expand=Tkinter.NO) + Tkinter.Button(f,text="GET",width=10,command=self._cb_storm_GET,default=Tkinter.ACTIVE).pack(side=Tkinter.RIGHT,expand=Tkinter.NO) + f.pack(side=Tkinter.TOP,expand=Tkinter.YES,fill=Tkinter.X) + + # row: separator + f = Tkinter.Frame(self.guiroot,height=2,bd=1,relief=Tkinter.SUNKEN,padx=5,pady=5) + f.pack(side=Tkinter.TOP,fill=Tkinter.X) + + # row: /6t + f = Tkinter.Frame(self.guiroot,padx=5,pady=5) + Tkinter.Label(f,text="/6t").pack(side=Tkinter.LEFT,expand=Tkinter.NO) + Tkinter.Button(f,text="DELETE",width=10,command=self._cb_6t_DELETE,default=Tkinter.ACTIVE).pack(side=Tkinter.RIGHT,expand=Tkinter.NO) + Tkinter.Button(f,text="PUT",width=10,command=self._cb_6t_PUT,default=Tkinter.ACTIVE).pack(side=Tkinter.RIGHT,expand=Tkinter.NO) + f.pack(side=Tkinter.TOP,expand=Tkinter.YES,fill=Tkinter.X) + + # row: separator + f = Tkinter.Frame(self.guiroot,height=2,bd=1,relief=Tkinter.SUNKEN,padx=5,pady=5) + f.pack(side=Tkinter.TOP,fill=Tkinter.X) + + # row: status + f = Tkinter.Frame(self.guiroot,padx=5,pady=5) + self.guiStatus = Tkinter.Label(f,textvariable=self.status,anchor=Tkinter.W) + self.guiStatus.pack(side=Tkinter.LEFT,expand=Tkinter.YES,fill=Tkinter.X) + self.guiStatus.after(GUI_REFRESH_MS,self._refresh_status) + f.pack(side=Tkinter.TOP,expand=Tkinter.YES,fill=Tkinter.X) + + #=== start GUI + self.guiroot.mainloop() + + #======================== GUI refreshers ================================== + + def _refresh_period(self): + newPeriod = IETF90Client().getPeriod() + if newPeriod!=None: + self.period.set(newPeriod) + self.guiPeriod.after(GUI_REFRESH_MS,self._refresh_period) + + def _refresh_status(self): + newStatus = IETF90Client().getStatus() + self.status.set(newStatus) + self.guiStatus.after(GUI_REFRESH_MS,self._refresh_status) + + #======================== GUI helpers ===================================== + + def _get_ipv6_entry(self): + ipv6 = self.ipv6_addr.get().strip() + self.ipv6_addr.set(ipv6) + return ipv6 + + #======================== GUI callbacks =================================== + + def _cb_close(self): + IETF90Client().close() + self.guiroot.destroy() + + def _cb_storm_GET(self, event=None): + try: + self._validate_entry_ipv6() + except ValueError as err: + tkMessageBox.showwarning('Oops!',str(err)) + return + + ipv6 = self._get_ipv6_entry() + IETF90Client().getStormPeriod(ipv6) + + self._writeConfigFile() + + def _cb_storm_PUT(self, event=None): + try: + self._validate_entry_ipv6() + self._validate_entry_period() + except ValueError as err: + tkMessageBox.showwarning('Oops!',str(err)) + return + + ipv6 = self._get_ipv6_entry() + period = self.period.get() + IETF90Client().setStormPeriod(ipv6,period) + + self._writeConfigFile() + + def _cb_6t_PUT(self, event=None): + try: + self._validate_entry_ipv6() + except ValueError as err: + tkMessageBox.showwarning('Oops!',str(err)) + return + + ipv6 = self._get_ipv6_entry() + IETF90Client().add6topCell(ipv6) + + self._writeConfigFile() + + def _cb_6t_DELETE(self, event=None): + try: + self._validate_entry_ipv6() + except ValueError as err: + tkMessageBox.showwarning('Oops!',str(err)) + return + + ipv6 = self._get_ipv6_entry() + IETF90Client().delete6topCell(ipv6) + + self._writeConfigFile() + + #======================== format validation =============================== + + def _validate_entry_ipv6(self): + + # http://stackoverflow.com/questions/53497/regular-expression-that-matches-valid-ipv6-addresses + IPv6_PATTERN = r"\b(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|" + \ + r"([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|" + \ + r"([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|" + \ + r"([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|" + \ + r":((:[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|" + \ + r"::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]).){3,3}(25[0-5]|" + \ + r"(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|(2[0-4]|" + \ + r"1{0,1}[0-9]){0,1}[0-9]).){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]))\b" + + ipv6 = self._get_ipv6_entry() + + if not re.match(IPv6_PATTERN, ipv6): + raise ValueError("Invalid IPv6 address") + + def _validate_entry_period(self): + try: + period = self.period.get() + except: + raise ValueError("Invalid number for period") + + if (period<0x0000) or (period>0xffff): + raise ValueError("Invalid range for period [0x0000-0xffff]") + + #======================== file interaction ================================ + + def _writeConfigFile(self): + + output = [] + output += ['ipv6={0}'.format(self.ipv6_addr.get().strip())] + output += ['period={0}'.format(self.period.get())] + output = '\n'.join(output) + + with open(CONFIG_FILENAME,'w') as f: + f.write(output) + + def _readConfigFile(self): + + ipv6 = DFLT_IPv6 + period = DFLT_PERIOD + + try: + with open(CONFIG_FILENAME,'r') as f: + for line in f: + m = re.search('ipv6=(\S+)', line) + if m: + ipv6 = m.group(1).strip() + m = re.search('period=([0-9]+)', line) + if m: + period = m.group(1).strip() + except Exception as err: + pass + + return (ipv6,period) + +def main(): + IETF90Client() + IETF90ClientGUI() + +if __name__=="__main__": + main() diff --git a/software/opensim/SimCli/SimCli.py b/software/openCli/SimCli.py similarity index 92% rename from software/opensim/SimCli/SimCli.py rename to software/openCli/SimCli.py index 2313cb53a..bd7cab0c4 100644 --- a/software/opensim/SimCli/SimCli.py +++ b/software/openCli/SimCli.py @@ -3,8 +3,6 @@ import sys import threading import logging -import binascii -import time class NullLogHandler(logging.Handler): def emit(self, record): @@ -111,7 +109,8 @@ def run(self): params = raw_input('> ') - self.log.debug('Following command entered:'+params) + if self.log.isEnabledFor(logging.DEBUG): + self.log.debug('Following command entered:'+params) params = params.split() if len(params)<1: @@ -166,9 +165,27 @@ def _handleBootall(self,params): self._printUsageFromName('bootall') return - for moteId in range(self.engine.getNumMotes()): - moteHandler = self.engine.getMoteHandler(moteId) - moteHandler.hwSupply.switchOn() + # pause the simulation engine + if self.engine.isRunning(): + resumeAfterBooting = True + self.engine.pause() + else: + resumeAfterBooting = False + + # boot all motes + now = self.engine.timeline.getCurrentTime() + for rank in range(self.engine.getNumMotes()): + moteHandler = self.engine.getMoteHandler(rank) + self.engine.timeline.scheduleEvent( + now, + moteHandler.getId(), + moteHandler.hwSupply.switchOn, + moteHandler.hwSupply.INTR_SWITCHON + ) + + # resume the simulation engine + if resumeAfterBooting: + self.engine.resume() print 'OK' @@ -318,6 +335,9 @@ def _handleQuit(self,params): self._printUsageFromName('quit') return + # pause the engine + self.engine.pause() + # this thread quits sys.exit(0) diff --git a/software/openUI/__init__.py b/software/openCli/__init__.py similarity index 100% rename from software/openUI/__init__.py rename to software/openCli/__init__.py diff --git a/software/openEndPoint/bin/EpLayerdebugCli/EpLayerdebugCli.py b/software/openEndPoint/bin/EpLayerdebugCli/EpLayerdebugCli.py index 251b529e4..e7063f48a 100644 --- a/software/openEndPoint/bin/EpLayerdebugCli/EpLayerdebugCli.py +++ b/software/openEndPoint/bin/EpLayerdebugCli/EpLayerdebugCli.py @@ -1,66 +1,66 @@ -import os -import sys -if __name__=='__main__': - cur_path = sys.path[0] - sys.path.insert(0, os.path.join(cur_path, '..', '..', '..', 'openCli')) # openCli/ - sys.path.insert(0, os.path.join(cur_path, '..', '..')) # openEndPoint/ - -import logging -import logging.handlers - -from engine import EndPointCli -from engine import EndPoint -from listener import ListenerUdp -#from epparser import ParserOneNum -from epparser import ParserCoap -from epparser import ParserPayload -from publisher import PublisherScreen,PublisherCoapCSV - -UDP_PORT = 5683 - -class EpLayerdebugCli(EndPointCli.EndPointCli): - - def __init__(self,endPoint): - - # initialize parent class - EndPointCli.EndPointCli.__init__(self,endPoint,"endPoint Layerdebug") - -def main(): - - # create an endpoint - endPoint = EndPoint.EndPoint( - ListenerUdp.ListenerUdp(UDP_PORT), # listener - ParserPayload.ParserPayload(), # parser - [ # publishers - #PublisherScreen.PublisherScreen(), - PublisherCoapCSV.PublisherCoapCSV() - ], - ) - endPoint.start() - - # create an openCLI - cli = EpLayerdebugCli(endPoint) - cli.start() - -if __name__=='__main__': - - # setup loggin - logHandler = logging.handlers.RotatingFileHandler('EpLayerdebugCli.log', - maxBytes=2000000, - backupCount=5, - mode='w') - logHandler.setFormatter(logging.Formatter("%(asctime)s [%(name)s:%(levelname)s] %(message)s")) - for loggerName in ['EndPoint', - 'ListeningEngine', - 'ListenerUdp', - 'ProcessingEngine', - 'ParserOneNum', - 'PublishingEngine', - 'PublisherScreen', - ]: - temp = logging.getLogger(loggerName) - temp.setLevel(logging.DEBUG) - temp.addHandler(logHandler) - - # start the application - main() +import os +import sys +if __name__=='__main__': + cur_path = sys.path[0] + sys.path.insert(0, os.path.join(cur_path, '..', '..', '..', 'openCli')) # openCli/ + sys.path.insert(0, os.path.join(cur_path, '..', '..')) # openEndPoint/ + +import logging +import logging.handlers + +from engine import EndPointCli +from engine import EndPoint +from listener import ListenerUdp +#from epparser import ParserOneNum +from epparser import ParserCoap +from epparser import ParserPayload +from publisher import PublisherScreen,PublisherCoapCSV + +UDP_PORT = 5683 + +class EpLayerdebugCli(EndPointCli.EndPointCli): + + def __init__(self,endPoint): + + # initialize parent class + EndPointCli.EndPointCli.__init__(self,endPoint,"endPoint Layerdebug") + +def main(): + + # create an endpoint + endPoint = EndPoint.EndPoint( + ListenerUdp.ListenerUdp(UDP_PORT), # listener + ParserPayload.ParserPayload(), # parser + [ # publishers + #PublisherScreen.PublisherScreen(), + PublisherCoapCSV.PublisherCoapCSV() + ], + ) + endPoint.start() + + # create an openCLI + cli = EpLayerdebugCli(endPoint) + cli.start() + +if __name__=='__main__': + + # setup loggin + logHandler = logging.handlers.RotatingFileHandler('EpLayerdebugCli.log', + maxBytes=2000000, + backupCount=5, + mode='w') + logHandler.setFormatter(logging.Formatter("%(asctime)s [%(name)s:%(levelname)s] %(message)s")) + for loggerName in ['EndPoint', + 'ListeningEngine', + 'ListenerUdp', + 'ProcessingEngine', + 'ParserOneNum', + 'PublishingEngine', + 'PublisherScreen', + ]: + temp = logging.getLogger(loggerName) + temp.setLevel(logging.DEBUG) + temp.addHandler(logHandler) + + # start the application + main() diff --git a/software/openEndPoint/bin/EpLayerdebugWeb/EpLayerdebugWeb.py b/software/openEndPoint/bin/EpLayerdebugWeb/EpLayerdebugWeb.py index f903560ef..770b6d159 100644 --- a/software/openEndPoint/bin/EpLayerdebugWeb/EpLayerdebugWeb.py +++ b/software/openEndPoint/bin/EpLayerdebugWeb/EpLayerdebugWeb.py @@ -1,65 +1,65 @@ -import os -import sys -if __name__=='__main__': - cur_path = sys.path[0] - sys.path.insert(0, os.path.join(cur_path, '..', '..', '..', 'openCli')) # openCli/ - sys.path.insert(0, os.path.join(cur_path, '..', '..')) # openEndPoint/ - -import logging -import logging.handlers - -from engine import EndPointCli -from engine import EndPoint -from listener import ListenerUdp -from epparser import ParserOneNum -from publisher import PublisherScreen -from publisher import PublisherWeb - -UDP_PORT = 5683 - -class EpLayerdebugWeb(EndPointCli.EndPointCli): - - def __init__(self,endPoint): - - # initialize parent class - EndPointCli.EndPointCli.__init__(self,endPoint,"endPoint Layerdebug") - -def main(): - - # create an endpoint - endPoint = EndPoint.EndPoint( - ListenerUdp.ListenerUdp(UDP_PORT), # listener - ParserOneNum.ParserOneNum(), # parser - [ # publishers - #PublisherScreen.PublisherScreen(), - PublisherWeb.PublisherWeb(), - ], - ) - endPoint.start() - - # create an openCLI - cli = EpLayerdebugWeb(endPoint) - cli.start() - -if __name__=='__main__': - - # setup loggin - logHandler = logging.handlers.RotatingFileHandler('EpLayerdebugWeb.log', - maxBytes=2000000, - backupCount=5, - mode='w') - logHandler.setFormatter(logging.Formatter("%(asctime)s [%(name)s:%(levelname)s] %(message)s")) - for loggerName in ['EndPoint', - 'ListeningEngine', - 'ListenerUdp', - 'ProcessingEngine', - 'ParserOneNum', - 'PublishingEngine', - 'PublisherScreen', - ]: - temp = logging.getLogger(loggerName) - temp.setLevel(logging.DEBUG) - temp.addHandler(logHandler) - - # start the application +import os +import sys +if __name__=='__main__': + cur_path = sys.path[0] + sys.path.insert(0, os.path.join(cur_path, '..', '..', '..', 'openCli')) # openCli/ + sys.path.insert(0, os.path.join(cur_path, '..', '..')) # openEndPoint/ + +import logging +import logging.handlers + +from engine import EndPointCli +from engine import EndPoint +from listener import ListenerUdp +from epparser import ParserOneNum +from publisher import PublisherScreen +from publisher import PublisherWeb + +UDP_PORT = 5683 + +class EpLayerdebugWeb(EndPointCli.EndPointCli): + + def __init__(self,endPoint): + + # initialize parent class + EndPointCli.EndPointCli.__init__(self,endPoint,"endPoint Layerdebug") + +def main(): + + # create an endpoint + endPoint = EndPoint.EndPoint( + ListenerUdp.ListenerUdp(UDP_PORT), # listener + ParserOneNum.ParserOneNum(), # parser + [ # publishers + #PublisherScreen.PublisherScreen(), + PublisherWeb.PublisherWeb(), + ], + ) + endPoint.start() + + # create an openCLI + cli = EpLayerdebugWeb(endPoint) + cli.start() + +if __name__=='__main__': + + # setup loggin + logHandler = logging.handlers.RotatingFileHandler('EpLayerdebugWeb.log', + maxBytes=2000000, + backupCount=5, + mode='w') + logHandler.setFormatter(logging.Formatter("%(asctime)s [%(name)s:%(levelname)s] %(message)s")) + for loggerName in ['EndPoint', + 'ListeningEngine', + 'ListenerUdp', + 'ProcessingEngine', + 'ParserOneNum', + 'PublishingEngine', + 'PublisherScreen', + ]: + temp = logging.getLogger(loggerName) + temp.setLevel(logging.DEBUG) + temp.addHandler(logHandler) + + # start the application main() \ No newline at end of file diff --git a/software/openEndPoint/bin/EpTestCli/EpTestCli.py b/software/openEndPoint/bin/EpTestCli/EpTestCli.py index 61785d23b..2a03dea3b 100644 --- a/software/openEndPoint/bin/EpTestCli/EpTestCli.py +++ b/software/openEndPoint/bin/EpTestCli/EpTestCli.py @@ -1,63 +1,63 @@ -import os -import sys -if __name__=='__main__': - cur_path = sys.path[0] - sys.path.insert(0, os.path.join(cur_path, '..', '..', '..', 'openCli')) # openCli/ - sys.path.insert(0, os.path.join(cur_path, '..', '..')) # openEndPoint/ - -import logging -import logging.handlers - -from engine import EndPointCli -from engine import EndPoint -from listener import ListenerTestPeriod -from epparser import ParserOneNum -from publisher import PublisherScreen - -PERIOD_MS = 1000 - -class EpTestCli(EndPointCli.EndPointCli): - - def __init__(self,endPoint): - - # initialize parent class - EndPointCli.EndPointCli.__init__(self,endPoint,"end point test") - -def main(): - - # create an endpoint - endPoint = EndPoint.EndPoint( - ListenerTestPeriod.ListenerTestPeriod(PERIOD_MS), # listener - ParserOneNum.ParserOneNum(), # parser - [ # publishers - PublisherScreen.PublisherScreen(), - ], - ) - endPoint.start() - - # create an openCLI - cli = EpTestCli(endPoint) - cli.start() - -if __name__=='__main__': - - # setup loggin - logHandler = logging.handlers.RotatingFileHandler('EpTestCli.log', - maxBytes=2000000, - backupCount=5, - mode='w') - logHandler.setFormatter(logging.Formatter("%(asctime)s [%(name)s:%(levelname)s] %(message)s")) - for loggerName in ['EndPoint', - 'ListeningEngine', - 'ListenerTestPeriod', - 'ProcessingEngine', - 'ParserOneNum', - 'PublishingEngine', - 'PublisherScreen', - ]: - temp = logging.getLogger(loggerName) - temp.setLevel(logging.DEBUG) - temp.addHandler(logHandler) - - # start the application +import os +import sys +if __name__=='__main__': + cur_path = sys.path[0] + sys.path.insert(0, os.path.join(cur_path, '..', '..', '..', 'openCli')) # openCli/ + sys.path.insert(0, os.path.join(cur_path, '..', '..')) # openEndPoint/ + +import logging +import logging.handlers + +from engine import EndPointCli +from engine import EndPoint +from listener import ListenerTestPeriod +from epparser import ParserOneNum +from publisher import PublisherScreen + +PERIOD_MS = 1000 + +class EpTestCli(EndPointCli.EndPointCli): + + def __init__(self,endPoint): + + # initialize parent class + EndPointCli.EndPointCli.__init__(self,endPoint,"end point test") + +def main(): + + # create an endpoint + endPoint = EndPoint.EndPoint( + ListenerTestPeriod.ListenerTestPeriod(PERIOD_MS), # listener + ParserOneNum.ParserOneNum(), # parser + [ # publishers + PublisherScreen.PublisherScreen(), + ], + ) + endPoint.start() + + # create an openCLI + cli = EpTestCli(endPoint) + cli.start() + +if __name__=='__main__': + + # setup loggin + logHandler = logging.handlers.RotatingFileHandler('EpTestCli.log', + maxBytes=2000000, + backupCount=5, + mode='w') + logHandler.setFormatter(logging.Formatter("%(asctime)s [%(name)s:%(levelname)s] %(message)s")) + for loggerName in ['EndPoint', + 'ListeningEngine', + 'ListenerTestPeriod', + 'ProcessingEngine', + 'ParserOneNum', + 'PublishingEngine', + 'PublisherScreen', + ]: + temp = logging.getLogger(loggerName) + temp.setLevel(logging.DEBUG) + temp.addHandler(logHandler) + + # start the application main() \ No newline at end of file diff --git a/software/openEndPoint/bin/EpTestWeb/EpTestWeb.py b/software/openEndPoint/bin/EpTestWeb/EpTestWeb.py index 88232547a..c1ac8fb5b 100644 --- a/software/openEndPoint/bin/EpTestWeb/EpTestWeb.py +++ b/software/openEndPoint/bin/EpTestWeb/EpTestWeb.py @@ -1,65 +1,65 @@ -import os -import sys -if __name__=='__main__': - cur_path = sys.path[0] - sys.path.insert(0, os.path.join(cur_path, '..', '..', '..', 'openCli')) # openCli/ - sys.path.insert(0, os.path.join(cur_path, '..', '..')) # openEndPoint/ - -import logging -import logging.handlers - -from engine import EndPointCli -from engine import EndPoint -from listener import ListenerTestPeriod -from epparser import ParserOneNum -from publisher import PublisherScreen -from publisher import PublisherWeb - -PERIOD_MS = 1000 - -class EpTestWeb(EndPointCli.EndPointCli): - - def __init__(self,endPoint): - - # initialize parent class - EndPointCli.EndPointCli.__init__(self,endPoint,"end point test") - -def main(): - - # create an endpoint - endPoint = EndPoint.EndPoint( - ListenerTestPeriod.ListenerTestPeriod(PERIOD_MS), # listener - ParserOneNum.ParserOneNum(), # parser - [ # publishers - PublisherScreen.PublisherScreen(), - PublisherWeb.PublisherWeb(), - ], - ) - endPoint.start() - - # create an openCLI - cli = EpTestWeb(endPoint) - cli.start() - -if __name__=='__main__': - - # setup loggin - logHandler = logging.handlers.RotatingFileHandler('EpTestWeb.log', - maxBytes=2000000, - backupCount=5, - mode='w') - logHandler.setFormatter(logging.Formatter("%(asctime)s [%(name)s:%(levelname)s] %(message)s")) - for loggerName in ['EndPoint', - 'ListeningEngine', - 'ListenerTestPeriod', - 'ProcessingEngine', - 'ParserOneNum', - 'PublishingEngine', - 'PublisherScreen', - ]: - temp = logging.getLogger(loggerName) - temp.setLevel(logging.DEBUG) - temp.addHandler(logHandler) - - # start the application +import os +import sys +if __name__=='__main__': + cur_path = sys.path[0] + sys.path.insert(0, os.path.join(cur_path, '..', '..', '..', 'openCli')) # openCli/ + sys.path.insert(0, os.path.join(cur_path, '..', '..')) # openEndPoint/ + +import logging +import logging.handlers + +from engine import EndPointCli +from engine import EndPoint +from listener import ListenerTestPeriod +from epparser import ParserOneNum +from publisher import PublisherScreen +from publisher import PublisherWeb + +PERIOD_MS = 1000 + +class EpTestWeb(EndPointCli.EndPointCli): + + def __init__(self,endPoint): + + # initialize parent class + EndPointCli.EndPointCli.__init__(self,endPoint,"end point test") + +def main(): + + # create an endpoint + endPoint = EndPoint.EndPoint( + ListenerTestPeriod.ListenerTestPeriod(PERIOD_MS), # listener + ParserOneNum.ParserOneNum(), # parser + [ # publishers + PublisherScreen.PublisherScreen(), + PublisherWeb.PublisherWeb(), + ], + ) + endPoint.start() + + # create an openCLI + cli = EpTestWeb(endPoint) + cli.start() + +if __name__=='__main__': + + # setup loggin + logHandler = logging.handlers.RotatingFileHandler('EpTestWeb.log', + maxBytes=2000000, + backupCount=5, + mode='w') + logHandler.setFormatter(logging.Formatter("%(asctime)s [%(name)s:%(levelname)s] %(message)s")) + for loggerName in ['EndPoint', + 'ListeningEngine', + 'ListenerTestPeriod', + 'ProcessingEngine', + 'ParserOneNum', + 'PublishingEngine', + 'PublisherScreen', + ]: + temp = logging.getLogger(loggerName) + temp.setLevel(logging.DEBUG) + temp.addHandler(logHandler) + + # start the application main() \ No newline at end of file diff --git a/software/openEndPoint/bin/EpTestWeb/templates/googlegauge.html b/software/openEndPoint/bin/EpTestWeb/templates/googlegauge.html index 4d47bf5ed..d8b12c17f 100644 --- a/software/openEndPoint/bin/EpTestWeb/templates/googlegauge.html +++ b/software/openEndPoint/bin/EpTestWeb/templates/googlegauge.html @@ -1,58 +1,58 @@ -$def with (title=None) - - - - \ - $if title: : $title\ - - - - - - -
- +$def with (title=None) + + + + \ + $if title: : $title\ + + + + + + +
+ \ No newline at end of file diff --git a/software/openEndPoint/bin/EpUdpRawCli/EpUdpRawCli.py b/software/openEndPoint/bin/EpUdpRawCli/EpUdpRawCli.py index 4c89f9b0a..127bcaf75 100644 --- a/software/openEndPoint/bin/EpUdpRawCli/EpUdpRawCli.py +++ b/software/openEndPoint/bin/EpUdpRawCli/EpUdpRawCli.py @@ -1,86 +1,86 @@ -import os -import sys -if __name__=='__main__': - cur_path = sys.path[0] - sys.path.insert(0, os.path.join(cur_path, '..', '..', '..', 'openCli')) # openCli/ - sys.path.insert(0, os.path.join(cur_path, '..', '..')) # openEndPoint/ - -import logging -import logging.handlers - -from engine import EndPointCli -from engine import EndPoint -from listener import ListenerUdp -from epparser import ParserOneList -from publisher import PublisherScreen -from injector import InjectorCoap, InjectorCoapLed - -UDP_PORT = 5683 - -class EpUdpRawCli(EndPointCli.EndPointCli): - - def __init__(self,endPoint): - - # initialize parent class - EndPointCli.EndPointCli.__init__(self,endPoint,"endPoint UDP Raw") - - # add commands - self.registerCommand('inject', - 'in', - 'inject data to CoAP resource', - [], - self._handlerInject) - - #======================== public ========================================== - - #======================== private ========================================= - - #===== callbacks - - def _handlerInject(self,params): - destination_ip = "2001:470:810a:d42f:1415:9209:22c:99" - destination_port = 5683 - destination_resource = 'l' - payload = [0x01,0x02] - InjectorCoap.InjectorCoap.inject((destination_ip,destination_port), - destination_resource, - payload) - -def main(): - - # create an endpoint - endPoint = EndPoint.EndPoint( - ListenerUdp.ListenerUdp(UDP_PORT), # listener - ParserOneList.ParserOneList(), # parser - [ # publishers - PublisherScreen.PublisherScreen(), - ], - ) - endPoint.start() - - # create an openCLI - cli = EpUdpRawCli(endPoint) - cli.start() - -if __name__=='__main__': - - # setup loggin - logHandler = logging.handlers.RotatingFileHandler('EpUdpRawCli.log', - maxBytes=2000000, - backupCount=5, - mode='w') - logHandler.setFormatter(logging.Formatter("%(asctime)s [%(name)s:%(levelname)s] %(message)s")) - for loggerName in ['EndPoint', - 'ListeningEngine', - 'ListenerUdp', - 'ProcessingEngine', - 'ParserOneNum', - 'PublishingEngine', - 'PublisherScreen', - ]: - temp = logging.getLogger(loggerName) - temp.setLevel(logging.DEBUG) - temp.addHandler(logHandler) - - # start the application +import os +import sys +if __name__=='__main__': + cur_path = sys.path[0] + sys.path.insert(0, os.path.join(cur_path, '..', '..', '..', 'openCli')) # openCli/ + sys.path.insert(0, os.path.join(cur_path, '..', '..')) # openEndPoint/ + +import logging +import logging.handlers + +from engine import EndPointCli +from engine import EndPoint +from listener import ListenerUdp +from epparser import ParserOneList +from publisher import PublisherScreen +from injector import InjectorCoap, InjectorCoapLed + +UDP_PORT = 5683 + +class EpUdpRawCli(EndPointCli.EndPointCli): + + def __init__(self,endPoint): + + # initialize parent class + EndPointCli.EndPointCli.__init__(self,endPoint,"endPoint UDP Raw") + + # add commands + self.registerCommand('inject', + 'in', + 'inject data to CoAP resource', + [], + self._handlerInject) + + #======================== public ========================================== + + #======================== private ========================================= + + #===== callbacks + + def _handlerInject(self,params): + destination_ip = "2001:470:810a:d42f:1415:9209:22c:99" + destination_port = 5683 + destination_resource = 'l' + payload = [0x01,0x02] + InjectorCoap.InjectorCoap.inject((destination_ip,destination_port), + destination_resource, + payload) + +def main(): + + # create an endpoint + endPoint = EndPoint.EndPoint( + ListenerUdp.ListenerUdp(UDP_PORT), # listener + ParserOneList.ParserOneList(), # parser + [ # publishers + PublisherScreen.PublisherScreen(), + ], + ) + endPoint.start() + + # create an openCLI + cli = EpUdpRawCli(endPoint) + cli.start() + +if __name__=='__main__': + + # setup loggin + logHandler = logging.handlers.RotatingFileHandler('EpUdpRawCli.log', + maxBytes=2000000, + backupCount=5, + mode='w') + logHandler.setFormatter(logging.Formatter("%(asctime)s [%(name)s:%(levelname)s] %(message)s")) + for loggerName in ['EndPoint', + 'ListeningEngine', + 'ListenerUdp', + 'ProcessingEngine', + 'ParserOneNum', + 'PublishingEngine', + 'PublisherScreen', + ]: + temp = logging.getLogger(loggerName) + temp.setLevel(logging.DEBUG) + temp.addHandler(logHandler) + + # start the application main() \ No newline at end of file diff --git a/software/openEndPoint/engine/EndPoint.py b/software/openEndPoint/engine/EndPoint.py index 28f445bd2..9b8ff1350 100644 --- a/software/openEndPoint/engine/EndPoint.py +++ b/software/openEndPoint/engine/EndPoint.py @@ -1,63 +1,63 @@ -import logging -class NullHandler(logging.Handler): - def emit(self, record): - pass -log = logging.getLogger('EndPoint') -log.setLevel(logging.ERROR) -log.addHandler(NullHandler()) - -import ListeningEngine -import ProcessingEngine -import PublishingEngine - -class EndPoint(object): - - def __init__(self,listener,parser,publishers): - - # store params - self.listeningEngine = None - self.listener = listener - self.processingEngine = None - self.parser = parser - self.publisherEngines = [] - self.publishers = publishers - - # log - log.debug('creating instance') - - # publisherEngines - input_functions = [] - for publisher in self.publishers: - tempEngine = PublishingEngine.PublishingEngine(publisher) - self.publisherEngines.append(tempEngine) - input_functions.append(tempEngine.indicateData) - - # processingEngine - self.processingEngine = ProcessingEngine.ProcessingEngine(self.parser, - input_functions) - - # listeningEngine - self.listeningEngine = ListeningEngine.ListeningEngine(self.listener, - self.processingEngine.indicateData) - - def start(self): - - # log - log.debug('starting') - - for pub in self.publisherEngines: - pub.start() - self.processingEngine.start() - self.listeningEngine.start() - - def stop(self): - # close the listening thread. This will propagate to the processing - # and publishing threads. - self.listeningEngine.stop() - - def getStats(self): - return { - 'listeningEngine' : self.listeningEngine.getStats(), - 'processingEngine' : self.processingEngine.getStats(), - 'publisherEngines' : [pub.getStats() for pub in self.publisherEngines], +import logging +class NullHandler(logging.Handler): + def emit(self, record): + pass +log = logging.getLogger('EndPoint') +log.setLevel(logging.ERROR) +log.addHandler(NullHandler()) + +import ListeningEngine +import ProcessingEngine +import PublishingEngine + +class EndPoint(object): + + def __init__(self,listener,parser,publishers): + + # store params + self.listeningEngine = None + self.listener = listener + self.processingEngine = None + self.parser = parser + self.publisherEngines = [] + self.publishers = publishers + + # log + log.debug('creating instance') + + # publisherEngines + input_functions = [] + for publisher in self.publishers: + tempEngine = PublishingEngine.PublishingEngine(publisher) + self.publisherEngines.append(tempEngine) + input_functions.append(tempEngine.indicateData) + + # processingEngine + self.processingEngine = ProcessingEngine.ProcessingEngine(self.parser, + input_functions) + + # listeningEngine + self.listeningEngine = ListeningEngine.ListeningEngine(self.listener, + self.processingEngine.indicateData) + + def start(self): + + # log + log.debug('starting') + + for pub in self.publisherEngines: + pub.start() + self.processingEngine.start() + self.listeningEngine.start() + + def stop(self): + # close the listening thread. This will propagate to the processing + # and publishing threads. + self.listeningEngine.stop() + + def getStats(self): + return { + 'listeningEngine' : self.listeningEngine.getStats(), + 'processingEngine' : self.processingEngine.getStats(), + 'publisherEngines' : [pub.getStats() for pub in self.publisherEngines], } \ No newline at end of file diff --git a/software/openEndPoint/engine/EndPointCli.py b/software/openEndPoint/engine/EndPointCli.py index b6caf5bd2..a6df7eb7b 100644 --- a/software/openEndPoint/engine/EndPointCli.py +++ b/software/openEndPoint/engine/EndPointCli.py @@ -1,39 +1,39 @@ -import logging -class NullHandler(logging.Handler): - def emit(self, record): - pass -log = logging.getLogger('endPointTestCli') -log.setLevel(logging.ERROR) -log.addHandler(NullHandler()) - -import pprint - -import OpenCli - -class EndPointCli(OpenCli.OpenCli): - - def __init__(self,endPoint,appName): - - # store params - self.endPoint = endPoint - - # initialize parent class - OpenCli.OpenCli.__init__(self,appName,self.quit_cb) - - # add commands - self.registerCommand('stats', - 'st', - 'list stats', - [], - self._handlerStats) - - #======================== public ========================================== - - def quit_cb(self): - self.endPoint.stop() - - #======================== private ========================================= - - def _handlerStats(self,params): - pp = pprint.PrettyPrinter(indent=3) - pp.pprint(self.endPoint.getStats()) +import logging +class NullHandler(logging.Handler): + def emit(self, record): + pass +log = logging.getLogger('endPointTestCli') +log.setLevel(logging.ERROR) +log.addHandler(NullHandler()) + +import pprint + +import OpenCli + +class EndPointCli(OpenCli.OpenCli): + + def __init__(self,endPoint,appName): + + # store params + self.endPoint = endPoint + + # initialize parent class + OpenCli.OpenCli.__init__(self,appName,self.quit_cb) + + # add commands + self.registerCommand('stats', + 'st', + 'list stats', + [], + self._handlerStats) + + #======================== public ========================================== + + def quit_cb(self): + self.endPoint.stop() + + #======================== private ========================================= + + def _handlerStats(self,params): + pp = pprint.PrettyPrinter(indent=3) + pp.pprint(self.endPoint.getStats()) diff --git a/software/openEndPoint/engine/EngineException.py b/software/openEndPoint/engine/EngineException.py index 2713719e7..4105cb539 100644 --- a/software/openEndPoint/engine/EngineException.py +++ b/software/openEndPoint/engine/EngineException.py @@ -1,20 +1,20 @@ -class EngineException(Exception): - - def __init__(self, reason=''): - self.value = reason - - def __str__(self) : - return "{0}: {1}".format(self.__class__.__name__, - self.value) - -class TearDownException(EngineException): - pass - -class OutputUnavailableException(EngineException): - pass - -class ParsingException(EngineException): - pass - -class PublishingException(EngineException): - pass +class EngineException(Exception): + + def __init__(self, reason=''): + self.value = reason + + def __str__(self) : + return "{0}: {1}".format(self.__class__.__name__, + self.value) + +class TearDownException(EngineException): + pass + +class OutputUnavailableException(EngineException): + pass + +class ParsingException(EngineException): + pass + +class PublishingException(EngineException): + pass diff --git a/software/openEndPoint/engine/EngineStats.py b/software/openEndPoint/engine/EngineStats.py index eca08471d..e5967fc91 100644 --- a/software/openEndPoint/engine/EngineStats.py +++ b/software/openEndPoint/engine/EngineStats.py @@ -1,50 +1,50 @@ -import logging -class NullHandler(logging.Handler): - def emit(self, record): - pass -log = logging.getLogger('EngineStats') -log.setLevel(logging.ERROR) -log.addHandler(NullHandler()) - -import threading -import copy - -class EngineStats(object) : - - def __init__(self, statNames): - - # store params - self.statNames = statNames - - # local variables - self.statsLock = threading.Lock() - self.stats = {} - - # reset stats - self.reset() - - def __str__(self): - return '\n'.join(["- {0}: {1}".format(k,v) for (k,v) in self.stats.items()]) - - #======================== public ========================================== - - def reset(self): - self.statsLock.acquire() - self.stats = {} - for name in self.statNames: - self.stats[name] = 0 - self.statsLock.release() - - def increment(self,statName,step=1): - self.statsLock.acquire() - self.stats[statName] += step - self.statsLock.release() - - def getStats(self): - self.statsLock.acquire() - returnVal = copy.deepcopy(self.stats) - self.statsLock.release() - - return returnVal - +import logging +class NullHandler(logging.Handler): + def emit(self, record): + pass +log = logging.getLogger('EngineStats') +log.setLevel(logging.ERROR) +log.addHandler(NullHandler()) + +import threading +import copy + +class EngineStats(object) : + + def __init__(self, statNames): + + # store params + self.statNames = statNames + + # local variables + self.statsLock = threading.Lock() + self.stats = {} + + # reset stats + self.reset() + + def __str__(self): + return '\n'.join(["- {0}: {1}".format(k,v) for (k,v) in self.stats.items()]) + + #======================== public ========================================== + + def reset(self): + self.statsLock.acquire() + self.stats = {} + for name in self.statNames: + self.stats[name] = 0 + self.statsLock.release() + + def increment(self,statName,step=1): + self.statsLock.acquire() + self.stats[statName] += step + self.statsLock.release() + + def getStats(self): + self.statsLock.acquire() + returnVal = copy.deepcopy(self.stats) + self.statsLock.release() + + return returnVal + #======================== private ========================================= \ No newline at end of file diff --git a/software/openEndPoint/engine/ListeningEngine.py b/software/openEndPoint/engine/ListeningEngine.py index a14f1efc5..75fa6dc44 100644 --- a/software/openEndPoint/engine/ListeningEngine.py +++ b/software/openEndPoint/engine/ListeningEngine.py @@ -1,73 +1,73 @@ -import logging -class NullHandler(logging.Handler): - def emit(self, record): - pass -log = logging.getLogger('ListeningEngine') -log.setLevel(logging.ERROR) -log.addHandler(NullHandler()) - -import threading - -import EngineStats -from EngineException import TearDownException, \ - OutputUnavailableException - -class ListeningEngine(threading.Thread): - - def __init__(self,listener,output_cb): - - # store params - self.listener = listener - self.output_cb = output_cb - - # log - log.debug("creating instance") - - # initialize parent class - threading.Thread.__init__(self) - - # give this thread a name - self.name = 'ListeningEngine' - - # local variables - self.stats = EngineStats.EngineStats(['numIn', - 'numOutOk', - 'numOutFail']) - - #======================== public ========================================== - - def run(self): - - while True: - - # block until receiving some data - try: - (timestamp,source,data) = self.listener.getData() - except TearDownException: - # log - self.warning("TearDown") - - # stop this thread - break - - # log - log.debug("Got data {2} at {0} from {1}".format(timestamp,source,data)) - - # update stats - self.stats.increment('numIn') - - # pass on to output - try: - self.output_cb((timestamp,source,data)) - except OutputUnavailableException: - self.stats.increment('numOutFail') - else: - self.stats.increment('numOutOk') - - def stop(self): - self.listener.stop() - - def getStats(self): - return self.stats.getStats() - +import logging +class NullHandler(logging.Handler): + def emit(self, record): + pass +log = logging.getLogger('ListeningEngine') +log.setLevel(logging.ERROR) +log.addHandler(NullHandler()) + +import threading + +import EngineStats +from EngineException import TearDownException, \ + OutputUnavailableException + +class ListeningEngine(threading.Thread): + + def __init__(self,listener,output_cb): + + # store params + self.listener = listener + self.output_cb = output_cb + + # log + log.debug("creating instance") + + # initialize parent class + threading.Thread.__init__(self) + + # give this thread a name + self.name = 'ListeningEngine' + + # local variables + self.stats = EngineStats.EngineStats(['numIn', + 'numOutOk', + 'numOutFail']) + + #======================== public ========================================== + + def run(self): + + while True: + + # block until receiving some data + try: + (timestamp,source,data) = self.listener.getData() + except TearDownException: + # log + self.warning("TearDown") + + # stop this thread + break + + # log + log.debug("Got data {2} at {0} from {1}".format(timestamp,source,data)) + + # update stats + self.stats.increment('numIn') + + # pass on to output + try: + self.output_cb((timestamp,source,data)) + except OutputUnavailableException: + self.stats.increment('numOutFail') + else: + self.stats.increment('numOutOk') + + def stop(self): + self.listener.stop() + + def getStats(self): + return self.stats.getStats() + #======================== private ========================================= \ No newline at end of file diff --git a/software/openEndPoint/engine/ProcessingEngine.py b/software/openEndPoint/engine/ProcessingEngine.py index b9f5b9d86..20d792154 100644 --- a/software/openEndPoint/engine/ProcessingEngine.py +++ b/software/openEndPoint/engine/ProcessingEngine.py @@ -1,80 +1,80 @@ -import logging -class NullHandler(logging.Handler): - def emit(self, record): - pass -log = logging.getLogger('ProcessingEngine') -log.setLevel(logging.ERROR) -log.addHandler(NullHandler()) - -import threading -import Queue - -import EngineStats -from EngineException import OutputUnavailableException, \ - ParsingException - -class ProcessingEngine(threading.Thread): - - def __init__(self,parser,output_cbs): - - # store params - self.parser = parser - self.output_cbs = output_cbs - - # log - log.debug("creating instance") - - # initialize parent class - threading.Thread.__init__(self) - - # give this thread a name - self.name = 'ProcessingEngine' - - # local variables - self.goOn = True - self.inputQueue = Queue.Queue() - self.stats = EngineStats.EngineStats(['numIn', - 'numParseOk', - 'numParseFail', - 'numOutOk', - 'numOutFail']) - - def run(self): - - # log - log.debug('starting') - - while self.goOn: - - # block until reading data from the input queue - (timestamp,source,data) = self.inputQueue.get() - - # increment stats - self.stats.increment('numIn') - - # parse - try: - parsedData = self.parser.parse(data) - except ParsingException: - # increment stats - self.stats.increment('numParseFail') - else: - # increment stats - self.stats.increment('numParseOk') - - # call the callbacks - for cb in self.output_cbs: - cb((timestamp,source,parsedData)) - - #======================== public ========================================== - - def indicateData(self,data): - try: - self.inputQueue.put_nowait(data) - except Queue.Full: - raise OutputUnavailableException() - - def getStats(self): - return self.stats.getStats() - +import logging +class NullHandler(logging.Handler): + def emit(self, record): + pass +log = logging.getLogger('ProcessingEngine') +log.setLevel(logging.ERROR) +log.addHandler(NullHandler()) + +import threading +import Queue + +import EngineStats +from EngineException import OutputUnavailableException, \ + ParsingException + +class ProcessingEngine(threading.Thread): + + def __init__(self,parser,output_cbs): + + # store params + self.parser = parser + self.output_cbs = output_cbs + + # log + log.debug("creating instance") + + # initialize parent class + threading.Thread.__init__(self) + + # give this thread a name + self.name = 'ProcessingEngine' + + # local variables + self.goOn = True + self.inputQueue = Queue.Queue() + self.stats = EngineStats.EngineStats(['numIn', + 'numParseOk', + 'numParseFail', + 'numOutOk', + 'numOutFail']) + + def run(self): + + # log + log.debug('starting') + + while self.goOn: + + # block until reading data from the input queue + (timestamp,source,data) = self.inputQueue.get() + + # increment stats + self.stats.increment('numIn') + + # parse + try: + parsedData = self.parser.parse(data) + except ParsingException: + # increment stats + self.stats.increment('numParseFail') + else: + # increment stats + self.stats.increment('numParseOk') + + # call the callbacks + for cb in self.output_cbs: + cb((timestamp,source,parsedData)) + + #======================== public ========================================== + + def indicateData(self,data): + try: + self.inputQueue.put_nowait(data) + except Queue.Full: + raise OutputUnavailableException() + + def getStats(self): + return self.stats.getStats() + #======================== private ========================================= \ No newline at end of file diff --git a/software/openEndPoint/engine/PublishingEngine.py b/software/openEndPoint/engine/PublishingEngine.py index 77c7bd779..bd3a3d8a7 100644 --- a/software/openEndPoint/engine/PublishingEngine.py +++ b/software/openEndPoint/engine/PublishingEngine.py @@ -1,75 +1,75 @@ -import logging -class NullHandler(logging.Handler): - def emit(self, record): - pass -log = logging.getLogger('PublishingEngine') -log.setLevel(logging.ERROR) -log.addHandler(NullHandler()) - -import threading -import Queue - -import EngineStats -from EngineException import OutputUnavailableException, \ - PublishingException - -class PublishingEngine(threading.Thread): - - def __init__(self,publisher): - - # store params - self.publisher = publisher - - # log - log.debug("creating instance") - - # initialize parent class - threading.Thread.__init__(self) - - # give this thread a name - self.name = 'PublishingEngine' - - # local variables - self.goOn = True - self.inputQueue = Queue.Queue() - self.stats = EngineStats.EngineStats(['numIn', - 'numPublishedOk', - 'numPublishedFail']) - - def run(self): - - # log - log.debug('starting') - - self.publisher.run() - - while self.goOn: - - # block until reading data from the input queue - (timestamp,source,data) = self.inputQueue.get() - - # increment stats - self.stats.increment('numIn') - - # publish - try: - self.publisher.publish(timestamp,source,data) - except PublishingException: - # increment stats - self.stats.increment('numPublishedFail') - else: - # increment stats - self.stats.increment('numPublishedOk') - - #======================== public ========================================== - - def indicateData(self,data): - try: - self.inputQueue.put_nowait(data) - except Queue.Full: - raise OutputUnavailableException() - - def getStats(self): - return self.stats.getStats() - +import logging +class NullHandler(logging.Handler): + def emit(self, record): + pass +log = logging.getLogger('PublishingEngine') +log.setLevel(logging.ERROR) +log.addHandler(NullHandler()) + +import threading +import Queue + +import EngineStats +from EngineException import OutputUnavailableException, \ + PublishingException + +class PublishingEngine(threading.Thread): + + def __init__(self,publisher): + + # store params + self.publisher = publisher + + # log + log.debug("creating instance") + + # initialize parent class + threading.Thread.__init__(self) + + # give this thread a name + self.name = 'PublishingEngine' + + # local variables + self.goOn = True + self.inputQueue = Queue.Queue() + self.stats = EngineStats.EngineStats(['numIn', + 'numPublishedOk', + 'numPublishedFail']) + + def run(self): + + # log + log.debug('starting') + + self.publisher.run() + + while self.goOn: + + # block until reading data from the input queue + (timestamp,source,data) = self.inputQueue.get() + + # increment stats + self.stats.increment('numIn') + + # publish + try: + self.publisher.publish(timestamp,source,data) + except PublishingException: + # increment stats + self.stats.increment('numPublishedFail') + else: + # increment stats + self.stats.increment('numPublishedOk') + + #======================== public ========================================== + + def indicateData(self,data): + try: + self.inputQueue.put_nowait(data) + except Queue.Full: + raise OutputUnavailableException() + + def getStats(self): + return self.stats.getStats() + #======================== private ========================================= \ No newline at end of file diff --git a/software/openEndPoint/epparser/CoapCodes.py b/software/openEndPoint/epparser/CoapCodes.py index a6d0dc9e9..1d450b76f 100644 --- a/software/openEndPoint/epparser/CoapCodes.py +++ b/software/openEndPoint/epparser/CoapCodes.py @@ -1,50 +1,50 @@ -#defines all coap option code - -option_codes = { - #response codes - 65:"2.01 Created ", - 66:"2.02 Deleted ", - 67:"2.03 Valid ", - 68:"2.04 Changed ", - 69:"2.05 Content ", - 128:"4.00 Bad Request ", - 129:"4.01 Unauthorized ", - 130:"4.02 Bad Option ", - 131:"4.03 Forbidden ", - 132:"4.04 Not Found ", - 133:"4.05 Method Not Allowed ", - 140:"4.12 Precondition Failed ", - 141:"4.13 Request Entity Too Large ", - 143:"4.15 Unsupported Media Type ", - 160:"5.00 Internal Server Error ", - 161:"5.01 Not Implemented ", - 162:"5.02 Bad Gateway ", - 163:"5.03 Service Unavailable ", - 164:"5.04 Gateway Timeout ", - 165:"5.05 Proxying Not Supported ", - #option number registry - 1:"Content-Type ", - 2:"Max-Age ", - 3:"Proxy-Uri ", - 4:"ETag ", - 5:"Uri-Host ", - 6:"Location-Path ", - 7:"Uri-Port ", - 8:"Location-Query ", - 9:"Uri-Path ", - 11:"Token ", - 12:"Accept ", - 13:"If-Match ", - 15:"Uri-Query ", - 21:"If-None-Match ", - #media types - 0:"text/plain; charset=utf-8 ", - 40:"application/link-format ", - 41:"application/xml ", - 42:"application/octet-stream ", - 47:"application/exi ", - 50:"application/json " -} - - +#defines all coap option code + +option_codes = { + #response codes + 65:"2.01 Created ", + 66:"2.02 Deleted ", + 67:"2.03 Valid ", + 68:"2.04 Changed ", + 69:"2.05 Content ", + 128:"4.00 Bad Request ", + 129:"4.01 Unauthorized ", + 130:"4.02 Bad Option ", + 131:"4.03 Forbidden ", + 132:"4.04 Not Found ", + 133:"4.05 Method Not Allowed ", + 140:"4.12 Precondition Failed ", + 141:"4.13 Request Entity Too Large ", + 143:"4.15 Unsupported Media Type ", + 160:"5.00 Internal Server Error ", + 161:"5.01 Not Implemented ", + 162:"5.02 Bad Gateway ", + 163:"5.03 Service Unavailable ", + 164:"5.04 Gateway Timeout ", + 165:"5.05 Proxying Not Supported ", + #option number registry + 1:"Content-Type ", + 2:"Max-Age ", + 3:"Proxy-Uri ", + 4:"ETag ", + 5:"Uri-Host ", + 6:"Location-Path ", + 7:"Uri-Port ", + 8:"Location-Query ", + 9:"Uri-Path ", + 11:"Token ", + 12:"Accept ", + 13:"If-Match ", + 15:"Uri-Query ", + 21:"If-None-Match ", + #media types + 0:"text/plain; charset=utf-8 ", + 40:"application/link-format ", + 41:"application/xml ", + 42:"application/octet-stream ", + 47:"application/exi ", + 50:"application/json " +} + + \ No newline at end of file diff --git a/software/openEndPoint/epparser/IsJSON.py b/software/openEndPoint/epparser/IsJSON.py index 211be1d85..37a1d9697 100644 --- a/software/openEndPoint/epparser/IsJSON.py +++ b/software/openEndPoint/epparser/IsJSON.py @@ -1,24 +1,24 @@ -''' -Created on 11/07/2012 - -@author: xvilajosana -''' -import JSONWrapper - -class IsJSON(object): - ''' - classdocs - ''' - - - def __init__(s): - ''' - Constructor - ''' - - def toJSON(self): - json=JSONWrapper.JSONWrapper() - return json.json_repr(self) - - def __str__(self): +''' +Created on 11/07/2012 + +@author: xvilajosana +''' +import JSONWrapper + +class IsJSON(object): + ''' + classdocs + ''' + + + def __init__(s): + ''' + Constructor + ''' + + def toJSON(self): + json=JSONWrapper.JSONWrapper() + return json.json_repr(self) + + def __str__(self): return self.toJSON() \ No newline at end of file diff --git a/software/openEndPoint/epparser/old/coapCodes.py b/software/openEndPoint/epparser/old/coapCodes.py index a6d0dc9e9..1d450b76f 100644 --- a/software/openEndPoint/epparser/old/coapCodes.py +++ b/software/openEndPoint/epparser/old/coapCodes.py @@ -1,50 +1,50 @@ -#defines all coap option code - -option_codes = { - #response codes - 65:"2.01 Created ", - 66:"2.02 Deleted ", - 67:"2.03 Valid ", - 68:"2.04 Changed ", - 69:"2.05 Content ", - 128:"4.00 Bad Request ", - 129:"4.01 Unauthorized ", - 130:"4.02 Bad Option ", - 131:"4.03 Forbidden ", - 132:"4.04 Not Found ", - 133:"4.05 Method Not Allowed ", - 140:"4.12 Precondition Failed ", - 141:"4.13 Request Entity Too Large ", - 143:"4.15 Unsupported Media Type ", - 160:"5.00 Internal Server Error ", - 161:"5.01 Not Implemented ", - 162:"5.02 Bad Gateway ", - 163:"5.03 Service Unavailable ", - 164:"5.04 Gateway Timeout ", - 165:"5.05 Proxying Not Supported ", - #option number registry - 1:"Content-Type ", - 2:"Max-Age ", - 3:"Proxy-Uri ", - 4:"ETag ", - 5:"Uri-Host ", - 6:"Location-Path ", - 7:"Uri-Port ", - 8:"Location-Query ", - 9:"Uri-Path ", - 11:"Token ", - 12:"Accept ", - 13:"If-Match ", - 15:"Uri-Query ", - 21:"If-None-Match ", - #media types - 0:"text/plain; charset=utf-8 ", - 40:"application/link-format ", - 41:"application/xml ", - 42:"application/octet-stream ", - 47:"application/exi ", - 50:"application/json " -} - - +#defines all coap option code + +option_codes = { + #response codes + 65:"2.01 Created ", + 66:"2.02 Deleted ", + 67:"2.03 Valid ", + 68:"2.04 Changed ", + 69:"2.05 Content ", + 128:"4.00 Bad Request ", + 129:"4.01 Unauthorized ", + 130:"4.02 Bad Option ", + 131:"4.03 Forbidden ", + 132:"4.04 Not Found ", + 133:"4.05 Method Not Allowed ", + 140:"4.12 Precondition Failed ", + 141:"4.13 Request Entity Too Large ", + 143:"4.15 Unsupported Media Type ", + 160:"5.00 Internal Server Error ", + 161:"5.01 Not Implemented ", + 162:"5.02 Bad Gateway ", + 163:"5.03 Service Unavailable ", + 164:"5.04 Gateway Timeout ", + 165:"5.05 Proxying Not Supported ", + #option number registry + 1:"Content-Type ", + 2:"Max-Age ", + 3:"Proxy-Uri ", + 4:"ETag ", + 5:"Uri-Host ", + 6:"Location-Path ", + 7:"Uri-Port ", + 8:"Location-Query ", + 9:"Uri-Path ", + 11:"Token ", + 12:"Accept ", + 13:"If-Match ", + 15:"Uri-Query ", + 21:"If-None-Match ", + #media types + 0:"text/plain; charset=utf-8 ", + 40:"application/link-format ", + 41:"application/xml ", + 42:"application/octet-stream ", + 47:"application/exi ", + 50:"application/json " +} + + \ No newline at end of file diff --git a/software/openEndPoint/epparser/old/coapParserX.py b/software/openEndPoint/epparser/old/coapParserX.py index ae9e30f58..3c59f0515 100644 --- a/software/openEndPoint/epparser/old/coapParserX.py +++ b/software/openEndPoint/epparser/old/coapParserX.py @@ -1,149 +1,149 @@ -import binascii -import socket -import struct -import os -import datetime - -port = 5683 - -option_codes = { - #response codes - 65:"2.01 Created", - 66:"2.02 Deleted", - 67:"2.03 Valid", - 68:"2.04 Changed", - 69:"2.05 Content", - 128:"4.00 Bad Request ", - 129:"4.01 Unauthorized", - 130:"4.02 Bad Option", - 131:"4.03 Forbidden", - 132:"4.04 Not Found", - 133:"4.05 Method Not Allowed", - 140:"4.12 Precondition Failed", - 141:"4.13 Request Entity Too Large", - 143:"4.15 Unsupported Media Type", - 160:"5.00 Internal Server Error", - 161:"5.01 Not Implemented", - 162:"5.02 Bad Gateway", - 163:"5.03 Service Unavailable ", - 164:"5.04 Gateway Timeout", - 165:"5.05 Proxying Not Supported", - #option number registry - 1:"Content-Type", - 2:"Max-Age", - 3:"Proxy-Uri", - 4:"ETag", - 5:"Uri-Host", - 6:"Location-Path", - 7:"Uri-Port", - 8:"Location-Query", - 9:"Uri-Path", - 11:"Token", - 12:"Accept", - 13:"If-Match", - 15:"Uri-Query", - 21:"If-None-Match", - #media types - 0:"text/plain; charset=utf-8", - 40:"application/link-format", - 41:"application/xml", - 42:"application/octet-stream", - 47:"application/exi", - 50:"application/json" -} - - -def parseCoapData(data, address): - #try: - version = int((ord(data[0])& 0xc0) >> 6) - type = int((ord(data[0])& 0x30) >> 4) - options = int((ord(data[0])& 0xF)) - code = int(ord(data[1])) - #for now we only deal with code=3(PUT) code=2(POST) - mId = int(str(data[2:4]).encode("hex"),16) - optionList = [] - option_pointer = 4 - #print version,type,options,code - for i in range(0, options): - optionDelta = int((ord(data[option_pointer])&0b11110000)>>4) - optionNumber = optionDelta - if (i > 0): - optionNumber = optionDelta + optionList[i-1][0] - length = int(ord(data[option_pointer])&0b00001111) - print data[option_pointer+1:option_pointer+length+1] - option_payload = data[option_pointer+1:option_pointer+length+1] - option_desc = "" #string describing option - try: - #try to get a string to associate with the option code, if none exists use the number - #option_payload = int(ord(option_payload)) - #option_payload = option_codes[optionDelta] - option_desc = option_codes[optionNumber] - except: - pass - optionList.append([optionDelta, length, option_desc, option_payload]) - option_pointer = option_pointer + length + 1 - - #print "poipoi start" - #for b in data[option_pointer:option_pointer+5]: - #print str(ord(b)) - #xaviPayload = 256*ord(data[option_pointer])+ord(data[option_pointer+1]) - #print "xaviP="+str(xaviPayload) - #cmd = 'wget "http://openwsnstats.appspot.com/rest/stats?sid=1&nid=1&rssi='+str(xaviPayload)+'&numtx=10&numrx=20&numack=10&cost=1.0"' - #print cmd - #os.system(cmd) - #print "poipoi stop" - - payload="" - #try: - # for i in range(len(data[option_pointer:])-1): - # payload += hex(struct.unpack('b',data[option_pointer+i:option_pointer+i+1])[0]) #data[option_pointer:] - #except: - # for i in range(len(data[option_pointer:])-1): - # payload += hex(struct.unpack('b',data[option_pointer+i:option_pointer+i+1])[0]) - - payload = binascii.hexlify(data[option_pointer:]) - - print "addr", address - print "version ", version - print "type ", type - print "options ", options - print "code ", code - print "mId", mId - print "optionList (delta, length, str)", optionList - print "payload ", payload - - #write the data to file if we're intereted in it - if((code == 3 or code == 2) and address[0][0:2] != "00" ): - print "writing file" - if not os.path.exists("/var/www/data/" + address[0]): - os.makedirs("/var/www/data/" + address[0]) - sensor_name = "" - now = datetime.datetime.now() - for option in optionList: - if (option[2] == 'Location-Path'): - filepath = "/var/www/data/"+address[0]+"/" + option[3]+".txt" - f = open(filepath,"a") - if os.path.getsize(filepath)==0: - f.write('logtime,coap-payload-hex'+ "\n") - writeline = "" - writeline += str(now) + "," - print "payload xv ", payload - writeline += payload - f.write(writeline + "\n") - f.close() - #dump everythign else in a "raw" file for debugging - f_raw = open("/var/www/data/"+address[0]+"/raw.txt","a") - f_raw.write(str(now) + "," + binascii.hexlify(data) + "\n") - f_raw.close() - - #except: - # print "Error parsing packet. This demo server only supports a barebone coap post/put implementation." - -socket_handler = socket.socket(socket.AF_INET6, socket.SOCK_DGRAM) -socket_handler.bind(('',port)) -while True: - raw,conn = socket_handler.recvfrom(1024) - print raw - parseCoapData(raw, conn) - #print 'version='+str( (ord(raw[0])& 0xc0) >> 6) - print binascii.hexlify(raw) +import binascii +import socket +import struct +import os +import datetime + +port = 5683 + +option_codes = { + #response codes + 65:"2.01 Created", + 66:"2.02 Deleted", + 67:"2.03 Valid", + 68:"2.04 Changed", + 69:"2.05 Content", + 128:"4.00 Bad Request ", + 129:"4.01 Unauthorized", + 130:"4.02 Bad Option", + 131:"4.03 Forbidden", + 132:"4.04 Not Found", + 133:"4.05 Method Not Allowed", + 140:"4.12 Precondition Failed", + 141:"4.13 Request Entity Too Large", + 143:"4.15 Unsupported Media Type", + 160:"5.00 Internal Server Error", + 161:"5.01 Not Implemented", + 162:"5.02 Bad Gateway", + 163:"5.03 Service Unavailable ", + 164:"5.04 Gateway Timeout", + 165:"5.05 Proxying Not Supported", + #option number registry + 1:"Content-Type", + 2:"Max-Age", + 3:"Proxy-Uri", + 4:"ETag", + 5:"Uri-Host", + 6:"Location-Path", + 7:"Uri-Port", + 8:"Location-Query", + 9:"Uri-Path", + 11:"Token", + 12:"Accept", + 13:"If-Match", + 15:"Uri-Query", + 21:"If-None-Match", + #media types + 0:"text/plain; charset=utf-8", + 40:"application/link-format", + 41:"application/xml", + 42:"application/octet-stream", + 47:"application/exi", + 50:"application/json" +} + + +def parseCoapData(data, address): + #try: + version = int((ord(data[0])& 0xc0) >> 6) + type = int((ord(data[0])& 0x30) >> 4) + options = int((ord(data[0])& 0xF)) + code = int(ord(data[1])) + #for now we only deal with code=3(PUT) code=2(POST) + mId = int(str(data[2:4]).encode("hex"),16) + optionList = [] + option_pointer = 4 + #print version,type,options,code + for i in range(0, options): + optionDelta = int((ord(data[option_pointer])&0b11110000)>>4) + optionNumber = optionDelta + if (i > 0): + optionNumber = optionDelta + optionList[i-1][0] + length = int(ord(data[option_pointer])&0b00001111) + print data[option_pointer+1:option_pointer+length+1] + option_payload = data[option_pointer+1:option_pointer+length+1] + option_desc = "" #string describing option + try: + #try to get a string to associate with the option code, if none exists use the number + #option_payload = int(ord(option_payload)) + #option_payload = option_codes[optionDelta] + option_desc = option_codes[optionNumber] + except: + pass + optionList.append([optionDelta, length, option_desc, option_payload]) + option_pointer = option_pointer + length + 1 + + #print "poipoi start" + #for b in data[option_pointer:option_pointer+5]: + #print str(ord(b)) + #xaviPayload = 256*ord(data[option_pointer])+ord(data[option_pointer+1]) + #print "xaviP="+str(xaviPayload) + #cmd = 'wget "http://openwsnstats.appspot.com/rest/stats?sid=1&nid=1&rssi='+str(xaviPayload)+'&numtx=10&numrx=20&numack=10&cost=1.0"' + #print cmd + #os.system(cmd) + #print "poipoi stop" + + payload="" + #try: + # for i in range(len(data[option_pointer:])-1): + # payload += hex(struct.unpack('b',data[option_pointer+i:option_pointer+i+1])[0]) #data[option_pointer:] + #except: + # for i in range(len(data[option_pointer:])-1): + # payload += hex(struct.unpack('b',data[option_pointer+i:option_pointer+i+1])[0]) + + payload = binascii.hexlify(data[option_pointer:]) + + print "addr", address + print "version ", version + print "type ", type + print "options ", options + print "code ", code + print "mId", mId + print "optionList (delta, length, str)", optionList + print "payload ", payload + + #write the data to file if we're intereted in it + if((code == 3 or code == 2) and address[0][0:2] != "00" ): + print "writing file" + if not os.path.exists("/var/www/data/" + address[0]): + os.makedirs("/var/www/data/" + address[0]) + sensor_name = "" + now = datetime.datetime.now() + for option in optionList: + if (option[2] == 'Location-Path'): + filepath = "/var/www/data/"+address[0]+"/" + option[3]+".txt" + f = open(filepath,"a") + if os.path.getsize(filepath)==0: + f.write('logtime,coap-payload-hex'+ "\n") + writeline = "" + writeline += str(now) + "," + print "payload xv ", payload + writeline += payload + f.write(writeline + "\n") + f.close() + #dump everythign else in a "raw" file for debugging + f_raw = open("/var/www/data/"+address[0]+"/raw.txt","a") + f_raw.write(str(now) + "," + binascii.hexlify(data) + "\n") + f_raw.close() + + #except: + # print "Error parsing packet. This demo server only supports a barebone coap post/put implementation." + +socket_handler = socket.socket(socket.AF_INET6, socket.SOCK_DGRAM) +socket_handler.bind(('',port)) +while True: + raw,conn = socket_handler.recvfrom(1024) + print raw + parseCoapData(raw, conn) + #print 'version='+str( (ord(raw[0])& 0xc0) >> 6) + print binascii.hexlify(raw) diff --git a/software/openEndPoint/epparser/specificparsers/UDPStormParser.py b/software/openEndPoint/epparser/specificparsers/UDPStormParser.py index 2b36fa11a..ccff1aacb 100644 --- a/software/openEndPoint/epparser/specificparsers/UDPStormParser.py +++ b/software/openEndPoint/epparser/specificparsers/UDPStormParser.py @@ -1,40 +1,40 @@ -''' -Created on 17/07/2012 - -@author: xvilajosana -''' -import logging -class NullHandler(logging.Handler): - def emit(self, record): - pass -log = logging.getLogger('UDPStormParser') -log.setLevel(logging.ERROR) -log.addHandler(NullHandler()) - -import SpecificParser -from .. import CoapHeader -from .. import Payload - - -from ..ParserException import IncorrectParserException - -# Parses the ures test data -class UDPStormParser(SpecificParser.SpecificParser): - - apps=['strm'] #application name, can be a list. - headerStructure = { - 'structure': '>8) & 0xff), - ((myId>>0) & 0xff)] - - # log the activity - self.log.debug('returning '+str(myEui64)) - - # respond - self.motehandler.sendCommand(self.motehandler.commandIds['OPENSIM_CMD_eui64_get'], - myEui64) - - #======================== private ========================================= \ No newline at end of file diff --git a/software/opensim/BspEmulator/BspRadio.py b/software/opensim/BspEmulator/BspRadio.py deleted file mode 100644 index 4511d2861..000000000 --- a/software/opensim/BspEmulator/BspRadio.py +++ /dev/null @@ -1,458 +0,0 @@ -#!/usr/bin/python - -import struct -import BspModule - -class RadioState: - STOPPED = 'STOPPED', # Completely stopped. - RFOFF = 'RFOFF', # Listening for commands by RF chain is off. - SETTING_FREQUENCY = 'SETTING_FREQUENCY', # Configuring the frequency. - FREQUENCY_SET = 'FREQUENCY_SET', # Done configuring the frequency. - LOADING_PACKET = 'LOADING_PACKET', # Loading packet to send over SPI. - PACKET_LOADED = 'PACKET_LOADED', # Packet is loaded in the TX buffer. - ENABLING_TX = 'ENABLING_TX', # The RF Tx chaing is being enabled (includes locked the PLL). - TX_ENABLED = 'TX_ENABLED', # Radio completely ready to transmit. - TRANSMITTING = 'TRANSMITTING', # Busy transmitting bytes. - ENABLING_RX = 'ENABLING_RX', # The RF Rx chaing is being enabled (includes locked the PLL). - LISTENING = 'LISTENING', # RF chain is on, listening, but no packet received yet. - RECEIVING = 'RECEIVING', # Busy receiving bytes. - TXRX_DONE = 'TXRX_DONE', # Frame has been sent/received completely. - TURNING_OFF = 'TURNING_OFF', # Turning the RF chain off. - -class BspRadio(BspModule.BspModule): - ''' - \brief Emulates the 'radio' BSP module - ''' - - INTR_STARTOFFRAME_MOTE = 'radio.startofframe_fromMote' - INTR_ENDOFFRAME_MOTE = 'radio.endofframe_fromMote' - INTR_STARTOFFRAME_PROPAGATION = 'radio.startofframe_fromPropagation' - INTR_ENDOFFRAME_PROPAGATION = 'radio.endofframe_fromPropagation' - - def __init__(self,engine,motehandler): - - # store params - self.engine = engine - self.motehandler = motehandler - - # local variables - self.timeline = self.engine.timeline - self.propagation = self.engine.propagation - self.radiotimer = self.motehandler.bspRadiotimer - - # local variables - self.frequency = None # frequency the radio is tuned to - self.isRfOn = False # radio is off - self.txBuf = [] - self.rxBuf = [] - self.delayTx = 0.000214 - - # initialize the parent - BspModule.BspModule.__init__(self,'BspRadio') - - # set initial state - self._changeState(RadioState.STOPPED) - - #======================== public ========================================== - - #=== commands - - def cmd_init(self,params): - '''emulates - void radio_init()''' - - # make sure length of params is expected - assert(len(params)==0) - - # log the activity - self.log.debug('cmd_init') - - # change state - self._changeState(RadioState.STOPPED) - - # remember that module has been intialized - self.isInitialized = True - - # change state - self._changeState(RadioState.RFOFF) - - # respond - self.motehandler.sendCommand(self.motehandler.commandIds['OPENSIM_CMD_radio_init']) - - def cmd_reset(self,params): - '''emulates - void radio_reset()''' - - # make sure length of params is expected - assert(len(params)==0) - - # log the activity - self.log.debug('cmd_reset') - - # change state - self._changeState(RadioState.STOPPED) - - # respond - self.motehandler.sendCommand(self.motehandler.commandIds['OPENSIM_CMD_radio_reset']) - - def cmd_startTimer(self,params): - '''emulates - void radio_startTimer(PORT_TIMER_WIDTH period)''' - - # log the activity - self.log.debug('cmd_startTimer') - - # defer to radiotimer - params = self.motehandler.bspRadiotimer.cmd_start(params,True) - - # respond - self.motehandler.sendCommand(self.motehandler.commandIds['OPENSIM_CMD_radio_startTimer'], - params) - - def cmd_getTimerValue(self,params): - '''emulates - PORT_TIMER_WIDTH radio_getTimerValue()''' - - # log the activity - self.log.debug('cmd_getTimerValue') - - # defer to radiotimer - params = self.motehandler.bspRadiotimer.cmd_getValue(params,True) - - # respond - self.motehandler.sendCommand(self.motehandler.commandIds['OPENSIM_CMD_radio_getTimerValue'], - params) - - def cmd_setTimerPeriod(self,params): - '''emulates - void radio_setTimerPeriod(PORT_TIMER_WIDTH period)''' - - # log the activity - self.log.debug('cmd_setTimerPeriod') - - # defer to radiotimer - params = self.motehandler.bspRadiotimer.cmd_setPeriod(params,True) - - # respond - self.motehandler.sendCommand(self.motehandler.commandIds['OPENSIM_CMD_radio_setTimerPeriod'], - params) - - def cmd_getTimerPeriod(self,params): - '''emulates - PORT_TIMER_WIDTH radio_getTimerPeriod()''' - - # log the activity - self.log.debug('cmd_getTimerPeriod') - - # defer to radiotimer - params = self.motehandler.bspRadiotimer.cmd_getPeriod(params,True) - - # respond - self.motehandler.sendCommand(self.motehandler.commandIds['OPENSIM_CMD_radio_getTimerPeriod'], - params) - - def cmd_setFrequency(self,params): - '''emulates - void radio_setFrequency(uint8_t frequency)''' - - # unpack the parameters - (self.frequency,) = struct.unpack('B', params) - - # log the activity - self.log.debug('cmd_setFrequency frequency='+str(self.frequency)) - - # change state - self._changeState(RadioState.SETTING_FREQUENCY) - - # change state - self._changeState(RadioState.FREQUENCY_SET) - - # respond - self.motehandler.sendCommand(self.motehandler.commandIds['OPENSIM_CMD_radio_setFrequency']) - - def cmd_rfOn(self,params): - '''emulates - void radio_rfOn()''' - - # make sure length of params is expected - assert(len(params)==0) - - # log the activity - self.log.debug('cmd_rfOn') - - # update local variable - self.isRfOn = True - - # respond - self.motehandler.sendCommand(self.motehandler.commandIds['OPENSIM_CMD_radio_rfOn']) - - def cmd_rfOff(self,params): - '''emulates - void radio_rfOff()''' - - # make sure length of params is expected - assert(len(params)==0) - - # log the activity - self.log.debug('cmd_rfOff') - - # change state - self._changeState(RadioState.TURNING_OFF) - - # update local variable - self.isRfOn = False - - # change state - self._changeState(RadioState.RFOFF) - - # respond - self.motehandler.sendCommand(self.motehandler.commandIds['OPENSIM_CMD_radio_rfOff']) - - def cmd_loadPacket(self,params): - '''emulates - void radio_loadPacket(uint8_t* packet, uint8_t len)''' - - # make sure length of params is expected - assert(len(params)==127+1) - - # log the activity - self.log.debug('cmd_loadPacket len={0}'.format(len(params))) - - # change state - self._changeState(RadioState.LOADING_PACKET) - - # update local variable - length = ord(params[0]) - print length - - self.txBuf = [] - self.txBuf.append(length) - for i in range(1,length+1): - self.txBuf.append(ord(params[i])) - output = '' - for c in self.txBuf: - output += ' %.2x'%c - print output - - # log - self.log.debug('txBuf={0}'.format(self.txBuf)) - - # change state - self._changeState(RadioState.PACKET_LOADED) - - # respond - self.motehandler.sendCommand(self.motehandler.commandIds['OPENSIM_CMD_radio_loadPacket']) - - def cmd_txEnable(self,params): - '''emulates - void radio_txEnable()''' - - # make sure length of params is expected - assert(len(params)==0) - - # log the activity - self.log.debug('cmd_txEnable') - - # change state - self._changeState(RadioState.ENABLING_TX) - - # change state - self._changeState(RadioState.TX_ENABLED) - - # respond - self.motehandler.sendCommand(self.motehandler.commandIds['OPENSIM_CMD_radio_txEnable']) - - def cmd_txNow(self,params): - '''emulates - void radio_txNow()''' - - # make sure length of params is expected - assert(len(params)==0) - - # log the activity - self.log.debug('cmd_txNow') - - # change state - self._changeState(RadioState.TRANSMITTING) - - # get current time - currenttime = self.timeline.getCurrentTime() - - # calculate when the "start of frame" event will take place - startOfFrameTime = currenttime+self.delayTx - - # schedule "start of frame" event - self.timeline.scheduleEvent(startOfFrameTime, - self.motehandler.getId(), - self.intr_startOfFrame_fromMote, - self.INTR_STARTOFFRAME_MOTE) - - # respond - self.motehandler.sendCommand(self.motehandler.commandIds['OPENSIM_CMD_radio_txNow']) - - def cmd_rxEnable(self,params): - '''emulates - void radio_rxEnable()''' - - # make sure length of params is expected - assert(len(params)==0) - - # log the activity - self.log.debug('cmd_rxEnable') - - # change state - self._changeState(RadioState.ENABLING_RX) - - # change state - self._changeState(RadioState.LISTENING) - - # respond - self.motehandler.sendCommand(self.motehandler.commandIds['OPENSIM_CMD_radio_rxEnable']) - - def cmd_rxNow(self,params): - '''emulates - void radio_rxNow()''' - - # make sure length of params is expected - assert(len(params)==0) - - # log the activity - self.log.debug('cmd_rxNow') - - # change state - self._changeState(RadioState.LISTENING) - - # respond - self.motehandler.sendCommand(self.motehandler.commandIds['OPENSIM_CMD_radio_rxNow']) - - def cmd_getReceivedFrame(self,params): - '''emulates - void radio_getReceivedFrame(uint8_t* pBufRead, - uint8_t* pLenRead, - uint8_t maxBufLen, - int8_t* pRssi, - uint8_t* pLqi, - uint8_t* pCrc)''' - - # make sure length of params is expected - assert(len(params)==0) - - # log the activity - self.log.debug('cmd_getReceivedFrame') - - #==== prepare response - # uint8_t rxBuffer[128]; - params = self.rxBuf[1:] - while len(params)<128: - params.append(0) - # uint8_t len; - params.append(len(self.rxBuf)-1) - # int8_t rssi; - for i in struct.pack('>0)%0xff,(counterVal>>8)%0xff]) - - def intr_startOfFrame_fromPropagation(self): - - # signal start of frame to mote - counterVal = self.radiotimer.getCounterVal() - self.motehandler.sendCommand(self.motehandler.commandIds['OPENSIM_CMD_radio_isr_startFrame'], - [(counterVal>>0)%0xff,(counterVal>>8)%0xff]) - - def intr_endOfFrame_fromMote(self): - # indicate transmission end to propagation model - self.propagation.txEnd(self.motehandler.getId()) - - # signal end of frame to mote - counterVal = self.radiotimer.getCounterVal() - self.motehandler.sendCommand(self.motehandler.commandIds['OPENSIM_CMD_radio_isr_endFrame'], - [(counterVal>>0)%0xff,(counterVal>>8)%0xff]) - - def intr_endOfFrame_fromPropagation(self): - - # signal end of frame to mote - counterVal = self.radiotimer.getCounterVal() - self.motehandler.sendCommand(self.motehandler.commandIds['OPENSIM_CMD_radio_isr_endFrame'], - [(counterVal>>0)%0xff,(counterVal>>8)%0xff]) - - #======================== indication from propagation ===================== - - def indicateTxStart(self,moteId,packet,channel): - - self.log.debug('indicateTxStart from moteId={0} channel={1} len={2}'.format( - moteId,channel,len(packet))) - - if (self.isInitialized==True and - self.state==RadioState.LISTENING and - self.frequency==channel): - self._changeState(RadioState.RECEIVING) - self.rxBuf = packet - self.rssi = -50 - self.lqi = 100 - self.crcPasses = True - - # log - self.log.debug('rxBuf={0}'.format(self.rxBuf)) - - # schedule start of frame - self.timeline.scheduleEvent(self.timeline.getCurrentTime(), - self.motehandler.getId(), - self.intr_startOfFrame_fromPropagation, - self.INTR_STARTOFFRAME_PROPAGATION) - - def indicateTxEnd(self,moteId): - - self.log.debug('indicateTxEnd from moteId={0}'.format(moteId)) - - if (self.isInitialized==True and - self.state==RadioState.RECEIVING): - self._changeState(RadioState.TXRX_DONE) - - # schedule end of frame - self.timeline.scheduleEvent(self.timeline.getCurrentTime(), - self.motehandler.getId(), - self.intr_endOfFrame_fromPropagation, - self.INTR_ENDOFFRAME_PROPAGATION) - - #======================== private ========================================= - - def _packetLengthToDuration(self,numBytes): - return float(numBytes*8)/250000.0 - - def _changeState(self,newState): - self.state = newState - self.log.debug('state={0}'.format(self.state)) \ No newline at end of file diff --git a/software/opensim/BspEmulator/BspUart.py b/software/opensim/BspEmulator/BspUart.py deleted file mode 100644 index 61e846229..000000000 --- a/software/opensim/BspEmulator/BspUart.py +++ /dev/null @@ -1,139 +0,0 @@ -#!/usr/bin/python - -import struct -import BspModule -import serial - -class BspUart(BspModule.BspModule): - ''' - \brief Emulates the 'uart' BSP module - ''' - - def __init__(self,engine,motehandler): - - # store params - self.engine = engine - self.motehandler = motehandler - - # local variables - #self.serialHandler = serial.Serial('\\\\.\\CNCA0',baudrate=115200) - self.interruptsEnabled = False - self.txInterruptFlag = False - self.rxInterruptFlag = False - - # initialize the parent - BspModule.BspModule.__init__(self,'BspUart') - - #======================== public ========================================== - - #=== commands - - def cmd_init(self,params): - '''emulates - void uart_init()''' - - # make sure length of params is expected - assert(len(params)==0) - - # log the activity - self.log.debug('cmd_init') - - # remember that module has been intialized - self.isInitialized = True - - # respond - self.motehandler.sendCommand(self.motehandler.commandIds['OPENSIM_CMD_uart_init']) - - def cmd_enableInterrupts(self,params): - '''emulates - void uart_enableInterrupts()''' - - # make sure length of params is expected - assert(len(params)==0) - - # log the activity - self.log.debug('cmd_enableInterrupts') - - # update variables - self.interruptsEnabled = True - - # respond - self.motehandler.sendCommand(self.motehandler.commandIds['OPENSIM_CMD_uart_enableInterrupts']) - - def cmd_disableInterrupts(self,params): - '''emulates - void uart_disableInterrupts()''' - - # make sure length of params is expected - assert(len(params)==0) - - # log the activity - self.log.debug('cmd_disableInterrupts') - - # update variables - self.interruptsEnabled = False - - # respond - self.motehandler.sendCommand(self.motehandler.commandIds['OPENSIM_CMD_uart_disableInterrupts']) - - def cmd_clearRxInterrupts(self,params): - '''emulates - void uart_clearRxInterrupts()''' - - # make sure length of params is expected - assert(len(params)==0) - - # log the activity - self.log.debug('cmd_clearRxInterrupts') - - # update variables - self.rxInterruptFlag = False - - # respond - self.motehandler.sendCommand(self.motehandler.commandIds['OPENSIM_CMD_uart_clearRxInterrupts']) - - def cmd_clearTxInterrupts(self,params): - '''emulates - void uart_clearTxInterrupts()''' - - # make sure length of params is expected - assert(len(params)==0) - - # log the activity - self.log.debug('cmd_clearTxInterrupts') - - # update variables - self.txInterruptFlag = False - - # respond - self.motehandler.sendCommand(self.motehandler.commandIds['OPENSIM_CMD_uart_clearTxInterrupts']) - - def cmd_writeByte(self,params): - '''emulates - void uart_writeByte(uint8_t byteToWrite)''' - - # unpack the parameters - (self.lastTxChar,) = struct.unpack('timeLastTick: - return 0 - else: - period = self._getPeriod() - return int(math.floor(float(timeLastTick-eventTime)/float(period))) - - #======================== private ========================================= - - def _getPeriod(self): - - period = float(1)/float(self.frequency) # nominal period - period += float(self.drift)*float(period/1000000) # apply drift - - return period - \ No newline at end of file diff --git a/software/opensim/SimEngine/DaemonThread.py b/software/opensim/SimEngine/DaemonThread.py deleted file mode 100644 index 94de981d4..000000000 --- a/software/opensim/SimEngine/DaemonThread.py +++ /dev/null @@ -1,77 +0,0 @@ -#!/usr/bin/python - -import threading -import socket -import logging - -from MoteHandler import MoteHandler - -TCPCONN_MAXBACKLOG = 1 # the max number of unserved TCP connections - -class NullLogHandler(logging.Handler): - def emit(self, record): - pass - -class DaemonThread(threading.Thread): - ''' - \brief Thread waiting for new connections from motes over TCP. - ''' - - TCPPORT = 14159 - - def __init__(self,engine): - - # store variables - self.engine = engine - - # local variables - - # logging - self.log = logging.getLogger('DaemonThread') - self.log.setLevel(logging.DEBUG) - self.log.addHandler(NullLogHandler()) - - # initialize parent class - threading.Thread.__init__(self) - - # set thread name - self.setName('DaemonThread') - - # thread daemon mode - self.setDaemon(True) - - def run(self): - - # log - self.log.info('starting on port='+str(self.TCPPORT)) - - # create socket to listen on - try: - self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) - self.socket.bind(('',self.TCPPORT)) - self.socket.listen(TCPCONN_MAXBACKLOG) - except Exception as err: - self.log.debug('could not start listening, err='+str(err)) - - self.log.debug('listening') - - while True: - - # the daemon stops here while waiting for a user to connect - conn,addr = self.socket.accept() - - # log connection attempt - self.log.info("Connection attempt from "+str(addr)) - - # get id - - # get location - - # hand over connection to moteHandler - moteHandler = MoteHandler(self.engine,conn,addr[0],addr[1]) - - # indicate to the engine the new mote's handler - self.engine.indicateNewMote(moteHandler) - - # start the new mote handler - moteHandler.start() diff --git a/software/opensim/SimEngine/LocationManager.py b/software/opensim/SimEngine/LocationManager.py deleted file mode 100644 index 0d4180b37..000000000 --- a/software/opensim/SimEngine/LocationManager.py +++ /dev/null @@ -1,44 +0,0 @@ -#!/usr/bin/python - -import random -import logging - -class NullLogHandler(logging.Handler): - def emit(self, record): - pass - -class LocationManager(object): - ''' - \brief The module which assigns locations to the motes. - ''' - - def __init__(self,engine): - - # store params - self.engine = engine - - # local variables - - # logging - self.log = logging.getLogger('LocationManager') - self.log.setLevel(logging.DEBUG) - self.log.addHandler(NullLogHandler()) - - - #======================== public ========================================== - - def getLocation(self): - - x = random.randint(0,100) - y = random.randint(0,100) - z = 0 - - # debug - self.log.debug('assigning location ('+str(x)+','+str(y)+','+str(z)+')') - - return (x,y,z) - - #======================== private ========================================= - - #======================== helpers ========================================= - \ No newline at end of file diff --git a/software/opensim/SimEngine/MoteHandler.py b/software/opensim/SimEngine/MoteHandler.py deleted file mode 100644 index 99152e84a..000000000 --- a/software/opensim/SimEngine/MoteHandler.py +++ /dev/null @@ -1,370 +0,0 @@ -#!/usr/bin/python - -import threading -import socket -import logging -import os -import time -import binascii - -from BspEmulator import BspBoard -from BspEmulator import BspBsp_timer -from BspEmulator import BspDebugpins -from BspEmulator import BspEui64 -from BspEmulator import BspLeds -from BspEmulator import BspRadio -from BspEmulator import BspRadiotimer -from BspEmulator import BspUart -from BspEmulator import HwSupply -from BspEmulator import HwCrystal - -TCPRXBUFSIZE = 4096 # size of the TCP reception buffer - -class NullLogHandler(logging.Handler): - def emit(self, record): - pass - -class MoteHandler(threading.Thread): - ''' - \brief Handle the connection of a mote. - ''' - - commandIds = { - #===== from client to server - # board - 'OPENSIM_CMD_board_init' : 0, - 'OPENSIM_CMD_board_sleep' : 1, - # bsp_timer - 'OPENSIM_CMD_bsp_timer_init' : 2, - 'OPENSIM_CMD_bsp_timer_reset' : 3, - 'OPENSIM_CMD_bsp_timer_scheduleIn' : 4, - 'OPENSIM_CMD_bsp_timer_cancel_schedule' : 5, - 'OPENSIM_CMD_bsp_timer_get_currentValue' : 6, - # debugpins - 'OPENSIM_CMD_debugpins_init' : 7, - 'OPENSIM_CMD_debugpins_frame_toggle' : 8, - 'OPENSIM_CMD_debugpins_frame_clr' : 9, - 'OPENSIM_CMD_debugpins_frame_set' : 10, - 'OPENSIM_CMD_debugpins_slot_toggle' : 11, - 'OPENSIM_CMD_debugpins_slot_clr' : 12, - 'OPENSIM_CMD_debugpins_slot_set' : 13, - 'OPENSIM_CMD_debugpins_fsm_toggle' : 14, - 'OPENSIM_CMD_debugpins_fsm_clr' : 15, - 'OPENSIM_CMD_debugpins_fsm_set' : 16, - 'OPENSIM_CMD_debugpins_task_toggle' : 17, - 'OPENSIM_CMD_debugpins_task_clr' : 18, - 'OPENSIM_CMD_debugpins_task_set' : 19, - 'OPENSIM_CMD_debugpins_isr_toggle' : 20, - 'OPENSIM_CMD_debugpins_isr_clr' : 21, - 'OPENSIM_CMD_debugpins_isr_set' : 22, - 'OPENSIM_CMD_debugpins_radio_toggle' : 23, - 'OPENSIM_CMD_debugpins_radio_clr' : 24, - 'OPENSIM_CMD_debugpins_radio_set' : 25, - # eui64 - 'OPENSIM_CMD_eui64_get' : 26, - # leds - 'OPENSIM_CMD_leds_init' : 27, - 'OPENSIM_CMD_leds_error_on' : 28, - 'OPENSIM_CMD_leds_error_off' : 29, - 'OPENSIM_CMD_leds_error_toggle' : 30, - 'OPENSIM_CMD_leds_error_isOn' : 31, - 'OPENSIM_CMD_leds_radio_on' : 32, - 'OPENSIM_CMD_leds_radio_off' : 33, - 'OPENSIM_CMD_leds_radio_toggle' : 34, - 'OPENSIM_CMD_leds_radio_isOn' : 35, - 'OPENSIM_CMD_leds_sync_on' : 36, - 'OPENSIM_CMD_leds_sync_off' : 37, - 'OPENSIM_CMD_leds_sync_toggle' : 38, - 'OPENSIM_CMD_leds_sync_isOn' : 39, - 'OPENSIM_CMD_leds_debug_on' : 40, - 'OPENSIM_CMD_leds_debug_off' : 41, - 'OPENSIM_CMD_leds_debug_toggle' : 42, - 'OPENSIM_CMD_leds_debug_isOn' : 43, - 'OPENSIM_CMD_leds_all_on' : 44, - 'OPENSIM_CMD_leds_all_off' : 45, - 'OPENSIM_CMD_leds_all_toggle' : 46, - 'OPENSIM_CMD_leds_circular_shift' : 47, - 'OPENSIM_CMD_leds_increment' : 48, - # radio - 'OPENSIM_CMD_radio_init' : 49, - 'OPENSIM_CMD_radio_reset' : 50, - 'OPENSIM_CMD_radio_startTimer' : 51, - 'OPENSIM_CMD_radio_getTimerValue' : 52, - 'OPENSIM_CMD_radio_setTimerPeriod' : 53, - 'OPENSIM_CMD_radio_getTimerPeriod' : 54, - 'OPENSIM_CMD_radio_setFrequency' : 55, - 'OPENSIM_CMD_radio_rfOn' : 56, - 'OPENSIM_CMD_radio_rfOff' : 57, - 'OPENSIM_CMD_radio_loadPacket' : 58, - 'OPENSIM_CMD_radio_txEnable' : 59, - 'OPENSIM_CMD_radio_txNow' : 60, - 'OPENSIM_CMD_radio_rxEnable' : 61, - 'OPENSIM_CMD_radio_rxNow' : 62, - 'OPENSIM_CMD_radio_getReceivedFrame' : 63, - # radiotimer - 'OPENSIM_CMD_radiotimer_init' : 64, - 'OPENSIM_CMD_radiotimer_start' : 65, - 'OPENSIM_CMD_radiotimer_getValue' : 66, - 'OPENSIM_CMD_radiotimer_setPeriod' : 67, - 'OPENSIM_CMD_radiotimer_getPeriod' : 68, - 'OPENSIM_CMD_radiotimer_schedule' : 69, - 'OPENSIM_CMD_radiotimer_cancel' : 70, - 'OPENSIM_CMD_radiotimer_getCapturedTime' : 71, - # uart - 'OPENSIM_CMD_uart_init' : 72, - 'OPENSIM_CMD_uart_enableInterrupts' : 73, - 'OPENSIM_CMD_uart_disableInterrupts' : 74, - 'OPENSIM_CMD_uart_clearRxInterrupts' : 75, - 'OPENSIM_CMD_uart_clearTxInterrupts' : 76, - 'OPENSIM_CMD_uart_writeByte' : 77, - 'OPENSIM_CMD_uart_readByte' : 78, - # supply - #===== from server to client - # board - # bsp_timer - 'OPENSIM_CMD_bsp_timer_isr' : 100, - # debugpins - # eui64 - # leds - # radio - 'OPENSIM_CMD_radio_isr_startFrame' : 101, - 'OPENSIM_CMD_radio_isr_endFrame' : 102, - # radiotimer - 'OPENSIM_CMD_radiotimer_isr_compare' : 103, - 'OPENSIM_CMD_radiotimer_isr_overflow' : 104, - # uart - 'OPENSIM_CMD_uart_isr_tx' : 105, - 'OPENSIM_CMD_uart_isr_rx' : 106, - # supply - 'OPENSIM_CMD_supply_on' : 107, - 'OPENSIM_CMD_supply_off' : 108, - } - - def __init__(self,engine,conn,addr,port): - - # store params - self.engine = engine - self.conn = conn - self.addr = addr - self.port = port - - # obtain an id and location for the new mote - self.id = self.engine.idmanager.getId() - self.location = self.engine.locationmanager.getLocation() - - #=== local variables - self.loghandler = self.engine.loghandler - # stats - self.numRxCommands = 0 - self.numTxCommands = 0 - # hw - self.hwSupply = HwSupply.HwSupply(self.engine,self) - self.hwCrystal = HwCrystal.HwCrystal(self.engine,self) - # bsp - self.bspBoard = BspBoard.BspBoard(self.engine,self) - self.bspBsp_timer = BspBsp_timer.BspBsp_timer(self.engine,self) - self.bspDebugpins = BspDebugpins.BspDebugpins(self.engine,self) - self.bspEui64 = BspEui64.BspEui64(self.engine,self) - self.bspLeds = BspLeds.BspLeds(self.engine,self) - self.bspRadiotimer = BspRadiotimer.BspRadiotimer(self.engine,self) - self.bspRadio = BspRadio.BspRadio(self.engine,self) - self.bspUart = BspUart.BspUart(self.engine,self) - # callbacks - self.commandCallbacks = { - # board - self.commandIds['OPENSIM_CMD_board_init'] : self.bspBoard.cmd_init, - self.commandIds['OPENSIM_CMD_board_sleep'] : self.bspBoard.cmd_sleep, - # bsp_timer - self.commandIds['OPENSIM_CMD_bsp_timer_init'] : self.bspBsp_timer.cmd_init, - self.commandIds['OPENSIM_CMD_bsp_timer_reset'] : self.bspBsp_timer.cmd_reset, - self.commandIds['OPENSIM_CMD_bsp_timer_scheduleIn'] : self.bspBsp_timer.cmd_scheduleIn, - self.commandIds['OPENSIM_CMD_bsp_timer_cancel_schedule'] : self.bspBsp_timer.cmd_cancel_schedule, - self.commandIds['OPENSIM_CMD_bsp_timer_get_currentValue']: self.bspBsp_timer.cmd_get_currentValue, - # debugpins - self.commandIds['OPENSIM_CMD_debugpins_init'] : self.bspDebugpins.cmd_init, - self.commandIds['OPENSIM_CMD_debugpins_frame_toggle'] : self.bspDebugpins.cmd_frame_toggle, - self.commandIds['OPENSIM_CMD_debugpins_frame_clr'] : self.bspDebugpins.cmd_frame_clr, - self.commandIds['OPENSIM_CMD_debugpins_frame_set'] : self.bspDebugpins.cmd_frame_set, - self.commandIds['OPENSIM_CMD_debugpins_slot_toggle'] : self.bspDebugpins.cmd_slot_toggle, - self.commandIds['OPENSIM_CMD_debugpins_slot_clr'] : self.bspDebugpins.cmd_slot_clr, - self.commandIds['OPENSIM_CMD_debugpins_slot_set'] : self.bspDebugpins.cmd_slot_set, - self.commandIds['OPENSIM_CMD_debugpins_fsm_toggle'] : self.bspDebugpins.cmd_fsm_toggle, - self.commandIds['OPENSIM_CMD_debugpins_fsm_clr'] : self.bspDebugpins.cmd_fsm_clr, - self.commandIds['OPENSIM_CMD_debugpins_fsm_set'] : self.bspDebugpins.cmd_fsm_set, - self.commandIds['OPENSIM_CMD_debugpins_task_toggle'] : self.bspDebugpins.cmd_task_toggle, - self.commandIds['OPENSIM_CMD_debugpins_task_clr'] : self.bspDebugpins.cmd_task_clr, - self.commandIds['OPENSIM_CMD_debugpins_task_set'] : self.bspDebugpins.cmd_task_set, - self.commandIds['OPENSIM_CMD_debugpins_isr_toggle'] : self.bspDebugpins.cmd_isr_toggle, - self.commandIds['OPENSIM_CMD_debugpins_isr_clr'] : self.bspDebugpins.cmd_isr_clr, - self.commandIds['OPENSIM_CMD_debugpins_isr_set'] : self.bspDebugpins.cmd_isr_set, - self.commandIds['OPENSIM_CMD_debugpins_radio_toggle'] : self.bspDebugpins.cmd_radio_toggle, - self.commandIds['OPENSIM_CMD_debugpins_radio_clr'] : self.bspDebugpins.cmd_radio_clr, - self.commandIds['OPENSIM_CMD_debugpins_radio_set'] : self.bspDebugpins.cmd_radio_set, - # eui64 - self.commandIds['OPENSIM_CMD_eui64_get'] : self.bspEui64.cmd_get, - # leds - self.commandIds['OPENSIM_CMD_leds_init'] : self.bspLeds.cmd_init, - self.commandIds['OPENSIM_CMD_leds_error_on'] : self.bspLeds.cmd_error_on, - self.commandIds['OPENSIM_CMD_leds_error_off'] : self.bspLeds.cmd_error_off, - self.commandIds['OPENSIM_CMD_leds_error_toggle'] : self.bspLeds.cmd_error_toggle, - self.commandIds['OPENSIM_CMD_leds_error_isOn'] : self.bspLeds.cmd_error_isOn, - self.commandIds['OPENSIM_CMD_leds_radio_on'] : self.bspLeds.cmd_radio_on, - self.commandIds['OPENSIM_CMD_leds_radio_off'] : self.bspLeds.cmd_radio_off, - self.commandIds['OPENSIM_CMD_leds_radio_toggle'] : self.bspLeds.cmd_radio_toggle, - self.commandIds['OPENSIM_CMD_leds_radio_isOn'] : self.bspLeds.cmd_radio_isOn, - self.commandIds['OPENSIM_CMD_leds_sync_on'] : self.bspLeds.cmd_sync_on, - self.commandIds['OPENSIM_CMD_leds_sync_off'] : self.bspLeds.cmd_sync_off, - self.commandIds['OPENSIM_CMD_leds_sync_toggle'] : self.bspLeds.cmd_sync_toggle, - self.commandIds['OPENSIM_CMD_leds_sync_isOn'] : self.bspLeds.cmd_sync_isOn, - self.commandIds['OPENSIM_CMD_leds_debug_on'] : self.bspLeds.cmd_debug_on, - self.commandIds['OPENSIM_CMD_leds_debug_off'] : self.bspLeds.cmd_debug_off, - self.commandIds['OPENSIM_CMD_leds_debug_toggle'] : self.bspLeds.cmd_debug_toggle, - self.commandIds['OPENSIM_CMD_leds_debug_isOn'] : self.bspLeds.cmd_debug_isOn, - self.commandIds['OPENSIM_CMD_leds_all_on'] : self.bspLeds.cmd_all_on, - self.commandIds['OPENSIM_CMD_leds_all_off'] : self.bspLeds.cmd_all_off, - self.commandIds['OPENSIM_CMD_leds_all_toggle'] : self.bspLeds.cmd_all_toggle, - self.commandIds['OPENSIM_CMD_leds_circular_shift'] : self.bspLeds.cmd_circular_shift, - self.commandIds['OPENSIM_CMD_leds_increment'] : self.bspLeds.cmd_increment, - # radio - self.commandIds['OPENSIM_CMD_radio_init'] : self.bspRadio.cmd_init, - self.commandIds['OPENSIM_CMD_radio_reset'] : self.bspRadio.cmd_reset, - self.commandIds['OPENSIM_CMD_radio_startTimer'] : self.bspRadio.cmd_startTimer, - self.commandIds['OPENSIM_CMD_radio_getTimerValue'] : self.bspRadio.cmd_getTimerValue, - self.commandIds['OPENSIM_CMD_radio_setTimerPeriod'] : self.bspRadio.cmd_setTimerPeriod, - self.commandIds['OPENSIM_CMD_radio_getTimerPeriod'] : self.bspRadio.cmd_getTimerPeriod, - self.commandIds['OPENSIM_CMD_radio_setFrequency'] : self.bspRadio.cmd_setFrequency, - self.commandIds['OPENSIM_CMD_radio_rfOn'] : self.bspRadio.cmd_rfOn, - self.commandIds['OPENSIM_CMD_radio_rfOff'] : self.bspRadio.cmd_rfOff, - self.commandIds['OPENSIM_CMD_radio_loadPacket'] : self.bspRadio.cmd_loadPacket, - self.commandIds['OPENSIM_CMD_radio_txEnable'] : self.bspRadio.cmd_txEnable, - self.commandIds['OPENSIM_CMD_radio_txNow'] : self.bspRadio.cmd_txNow, - self.commandIds['OPENSIM_CMD_radio_rxEnable'] : self.bspRadio.cmd_rxEnable, - self.commandIds['OPENSIM_CMD_radio_rxNow'] : self.bspRadio.cmd_rxNow, - self.commandIds['OPENSIM_CMD_radio_getReceivedFrame'] : self.bspRadio.cmd_getReceivedFrame, - # radiotimer - self.commandIds['OPENSIM_CMD_radiotimer_init'] : self.bspRadiotimer.cmd_init, - self.commandIds['OPENSIM_CMD_radiotimer_start'] : self.bspRadiotimer.cmd_start, - self.commandIds['OPENSIM_CMD_radiotimer_getValue'] : self.bspRadiotimer.cmd_getValue, - self.commandIds['OPENSIM_CMD_radiotimer_setPeriod'] : self.bspRadiotimer.cmd_setPeriod, - self.commandIds['OPENSIM_CMD_radiotimer_getPeriod'] : self.bspRadiotimer.cmd_getPeriod, - self.commandIds['OPENSIM_CMD_radiotimer_schedule'] : self.bspRadiotimer.cmd_schedule, - self.commandIds['OPENSIM_CMD_radiotimer_cancel'] : self.bspRadiotimer.cmd_cancel, - self.commandIds['OPENSIM_CMD_radiotimer_getCapturedTime']: self.bspRadiotimer.cmd_getCapturedTime, - # uart - self.commandIds['OPENSIM_CMD_uart_init'] : self.bspUart.cmd_init, - self.commandIds['OPENSIM_CMD_uart_enableInterrupts'] : self.bspUart.cmd_enableInterrupts, - self.commandIds['OPENSIM_CMD_uart_disableInterrupts'] : self.bspUart.cmd_disableInterrupts, - self.commandIds['OPENSIM_CMD_uart_clearRxInterrupts'] : self.bspUart.cmd_clearRxInterrupts, - self.commandIds['OPENSIM_CMD_uart_clearTxInterrupts'] : self.bspUart.cmd_clearTxInterrupts, - self.commandIds['OPENSIM_CMD_uart_writeByte'] : self.bspUart.cmd_writeByte, - self.commandIds['OPENSIM_CMD_uart_readByte'] : self.bspUart.cmd_readByte, - } - - # logging this module - self.log = logging.getLogger('MoteHandler_'+str(self.id)) - self.log.setLevel(logging.DEBUG) - self.log.addHandler(NullLogHandler()) - - # logging this mote's modules - for loggerName in [ - 'MoteHandler_'+str(self.id), - # hw - 'HwSupply_'+str(self.id), - 'HwCrystal_'+str(self.id), - # bsp - 'BspBoard_'+str(self.id), - 'BspBsp_timer_'+str(self.id), - 'BspDebugpins_'+str(self.id), - 'BspEui64_'+str(self.id), - 'BspLeds_'+str(self.id), - 'BspRadiotimer_'+str(self.id), - 'BspRadio_'+str(self.id), - 'BspUart_'+str(self.id), - ]: - temp = logging.getLogger(loggerName) - temp.setLevel(logging.DEBUG) - temp.addHandler(self.loghandler) - - # initialize parent class - threading.Thread.__init__(self) - - # set thread name - self.setName('MoteHandler_'+str(self.id)) - - # thread daemon mode - self.setDaemon(True) - - def run(self): - - # log - self.log.info('starting') - - while(1): - # wait for a command - try: - input = self.conn.recv(TCPRXBUFSIZE) - except socket.error as err: - self.log.critical('connection error (err='+str(err)+')') - break - - # make sure I received something - assert(len(input)>0) - - # handle the received packet - self._handleReceivedCommand(input) - - #======================== public ========================================== - - def getId(self): - return self.id - - def getLocation(self): - return self.location - - def sendCommand(self,commandId,params=[]): - - # log - self.log.debug('sending command='+self._cmdIdToName(commandId)) - - # update statistics - self.numTxCommands += 1 - - # send command over connection - dataToSend = '' - dataToSend += chr(commandId) - for c in params: - dataToSend += chr(c) - self.conn.sendall(dataToSend) - - #======================== private ========================================= - - def _handleReceivedCommand(self,input): - - # get the command id and params from the received command - cmdId = ord(input[0]) - params = input[1:] - - # log - self.log.debug('received command='+self._cmdIdToName(cmdId)) - - # update statistics - self.numRxCommands += 1 - - # make sure I know what callback to call - assert(cmdId in self.commandCallbacks) - - # call the callback - try: - returnVal = self.commandCallbacks[cmdId](params) - except Exception as err: - self.log.critical(str(err)) - self.engine.pause() - raise - - def _cmdIdToName(self,cmdId): - cmdName = 'unknow' - for k,v in self.commandIds.items(): - if cmdId==v: - cmdName = k - break - return cmdName \ No newline at end of file diff --git a/software/opensim/SimEngine/Propagation.py b/software/opensim/SimEngine/Propagation.py deleted file mode 100644 index 422ca26a3..000000000 --- a/software/opensim/SimEngine/Propagation.py +++ /dev/null @@ -1,58 +0,0 @@ -#!/usr/bin/python - -import logging - -class NullLogHandler(logging.Handler): - def emit(self, record): - pass - -class Propagation(object): - ''' - \brief The propagation model of the engine. - ''' - - def __init__(self,engine): - - # store params - self.engine = engine - - # local variables - - # logging - self.log = logging.getLogger('Propagation') - self.log.setLevel(logging.DEBUG) - self.log.addHandler(NullLogHandler()) - - #======================== public ========================================== - - def txStart(self,moteId,packet,channel): - - # log - self.log.info('txStart from {0} on channel {1}, {2} bytes'.format( - moteId, - channel, - len(packet))) - - # TODO: calculate rssi - - # indicate to each mote - for i in range(self.engine.getNumMotes()): - motehandler = self.engine.getMoteHandler(i) - if motehandler.getId()!=moteId: - motehandler.bspRadio.indicateTxStart(moteId,packet,channel) - - def txEnd(self,moteId): - - # log - self.log.info('txStop from {0}'.format(moteId)) - - # indicate to each mote - for i in range(self.engine.getNumMotes()): - motehandler = self.engine.getMoteHandler(i) - if motehandler.getId()!=moteId: - motehandler.bspRadio.indicateTxEnd(moteId) - - #======================== private ========================================= - - #======================== helpers ========================================= - \ No newline at end of file diff --git a/software/opensim/SimEngine/opensim_proto.py b/software/opensim/SimEngine/opensim_proto.py deleted file mode 100644 index dcbc21b94..000000000 --- a/software/opensim/SimEngine/opensim_proto.py +++ /dev/null @@ -1,101 +0,0 @@ -#!/usr/bin/python - -import threading -import socket -import logging -import os -import time - -from BspEmulator import BspBoard -from BspEmulator import BspBsp_timer -from BspEmulator import BspDebugpins -from BspEmulator import BspEui64 -from BspEmulator import BspLeds -from BspEmulator import BspRadio -from BspEmulator import BspRadiotimer -from BspEmulator import BspUart - -TCPRXBUFSIZE = 4096 # size of the TCP reception buffer - -class NullLogHandler(logging.Handler): - def emit(self, record): - pass - -class OpenSimProto(object): - ''' - \brief Handle the connection of a mote. - ''' - - def __init__(self,conn,addr,port): - - # store params - self.conn = conn - self.addr = addr - self.port = port - - # local variables - self.waitingForReplySem = threading.Lock() - self.waitingForReply = False - - # bsp components - self.bspBoard = BspBoard.BspBoard() - self.bspBsp_timer = BspBsp_timer.BspBsp_timer() - self.bspDebugpins = BspDebugpins.BspDebugpins() - self.bspEui64 = BspEui64.BspEui64() - self.bspLeds = BspLeds.BspLeds() - self.bspRadio = BspRadio.BspRadio() - self.bspRadiotimer = BspRadiotimer.BspRadiotimer() - self.bspUart = BspUart.BspUart() - - # logging - self.log = logging.getLogger('MoteHandler') - self.log.setLevel(logging.DEBUG) - self.log.addHandler(NullLogHandler()) - - # initialize parent class - threading.Thread.__init__(self) - - # set thread name - self.setName('MoteHandler') - - # thread daemon mode - self.setDaemon(True) - - def run(self): - - # log - self.log.info('starting') - - self.conn.send('poipoi') - - while(1): - try: - input = self.conn.recv(TCPRXBUFSIZE) - except socket.error as err: - self.log.critical('connection error (err='+str(err)+')') - break - - self.log.info('received input='+str(input)) - if self.waitingForReply: - self.log.debug('This is a reply.') - self.response = input - self.waitingForReplySem.release() - else: - self.log.debug('This is a response.') - self._handleReceivedCommand(input) - - #======================== public ========================================== - - def sendCommand(send,dataToSend): - self.conn.send(dataToSend) - self.waitingForReply = True - self.waitingForReplySem.acquire() - - #======================== private ========================================= - - def _handleReceivedCommand(self,input): - time.sleep(1) - - print ord(input[0]) - - self.conn.send(chr(0)) \ No newline at end of file diff --git a/software/opensim/bin/opensim_cli/opensim_cli.py b/software/opensim/bin/opensim_cli/opensim_cli.py deleted file mode 100644 index fcca6b734..000000000 --- a/software/opensim/bin/opensim_cli/opensim_cli.py +++ /dev/null @@ -1,40 +0,0 @@ -#!/usr/bin/python - -import os -import sys - -temp_path = sys.path[0] -if temp_path: - sys.path.insert(0, os.path.join(temp_path, '..', '..')) - -import logging -import logging.handlers -import binascii -from SimEngine import SimEngine -from SimCli import SimCli - -LOG_FORMAT = "%(asctime)s [%(name)s:%(levelname)s] %(message)s" - -#============================ logging ========================================= - -logFileName = 'logs/opensim.log' -loghandler = logging.handlers.RotatingFileHandler(logFileName, - maxBytes=2000000, - backupCount=5, - mode='w') -loghandler.setFormatter(logging.Formatter(LOG_FORMAT)) - -#============================ main ============================================ - -def main(): - - # instantiate a SimEngine object - simengine = SimEngine.SimEngine(loghandler) - simengine.start() - - # instantiate the CLI interface - cliHandler = SimCli.SimCli(simengine) - cliHandler.start() - -if __name__ == "__main__": - main() diff --git a/software/opensim/bin/opensim_gui/opensim_gui.py b/software/opensim/bin/opensim_gui/opensim_gui.py deleted file mode 100644 index 48014554d..000000000 --- a/software/opensim/bin/opensim_gui/opensim_gui.py +++ /dev/null @@ -1,42 +0,0 @@ -#!/usr/bin/python - -import os -import sys - -temp_path = sys.path[0] -if temp_path: - sys.path.insert(0, os.path.join(temp_path, '..', '..')) - -import logging -import logging.handlers -import binascii -from SimEngine import SimEngine - -from SimGui import SimGui -from SimGui import SimWindow - -LOG_FORMAT = "%(asctime)s [%(name)s:%(levelname)s] %(message)s" - -#============================ logging ========================================= - -logFileName = 'logs/opensim.log' -loghandler = logging.handlers.RotatingFileHandler(logFileName, - maxBytes=2000000, - backupCount=5, - mode='w') -loghandler.setFormatter(logging.Formatter(LOG_FORMAT)) - -#============================ main ============================================ - -def main(): - - # instantiate a SimEngine object - simengine = SimEngine.SimEngine(loghandler) - simengine.start() - - # instantiate the CLI interface - guiHandler = SimGui.SimGui(simengine) - guiHandler.start() - -if __name__ == "__main__": - main() diff --git a/software/opensim/opensim.session b/software/opensim/opensim.session deleted file mode 100644 index 814cce06b..000000000 --- a/software/opensim/opensim.session +++ /dev/null @@ -1,28 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/software/opensim/sim_version.py b/software/opensim/sim_version.py deleted file mode 100644 index bb4fecdfb..000000000 --- a/software/opensim/sim_version.py +++ /dev/null @@ -1 +0,0 @@ -VERSION = (1, 0, 0) \ No newline at end of file diff --git a/software/openvisualizer/EventBus/Event.py b/software/openvisualizer/EventBus/Event.py deleted file mode 100644 index b6674d9a0..000000000 --- a/software/openvisualizer/EventBus/Event.py +++ /dev/null @@ -1,43 +0,0 @@ -''' -Created on 24/08/2012 - -@author: xvilajosana -''' -class Event: - ''' - \brief Representation of an event, in the event bus. - - Events are used to queue them up when emitted synchronously. - ''' - def __init__(self, uri, args, minNumReceivers=None, maxNumReceivers=None): - ''' - \brief Initializer. - - \param uri The URI of the signal (a string). Can be a regular - expression. - \param args Any arguments to be passed to the listeners. - ''' - self._uri = uri - self._args = args - self._minNumReceivers = minNumReceivers - self._maxNumReceivers = maxNumReceivers - - def get_uri(self): - return self._uri - - def get_args(self): - return self._args - - def get_minNumReceivers(self): - return self._minNumReceivers - - def get_maxNumReceivers(self): - return self._maxNumReceivers - - def __str__(self): - returnVal = [] - returnVal += ['uri={0}'.format(self._uri)] - returnVal += ['args={0}'.format(self._args)] - returnVal += ['minNumReceivers={0}'.format(self._minNumReceivers)] - returnVal += ['maxNumReceivers={0}'.format(self._maxNumReceivers)] - return ' '.join(returnVal) \ No newline at end of file diff --git a/software/openvisualizer/EventBus/EventBus.py b/software/openvisualizer/EventBus/EventBus.py deleted file mode 100644 index 62b02ba79..000000000 --- a/software/openvisualizer/EventBus/EventBus.py +++ /dev/null @@ -1,365 +0,0 @@ -''' -Created on 24/08/2012 - -@author: xvilajosana -''' -import logging -class NullHandler(logging.Handler): - def emit(self, record): - pass -log = logging.getLogger('EventBus') -log.setLevel(logging.DEBUG) -log.addHandler(NullHandler()) - -import sys -import threading -import time -import copy -import json - -import Subscription -import Event - -class EventBus(threading.Thread): - ''' - \brief An event bus to which modules can publish/subscribe. - - It is implemented as a singleton, i.e. only one instance of the eventBus - lives in the system. This means that separate modules can instantiate this - class independently and publish/subscribe to the result of that - instantiation. - ''' - _instance = None - _init = False - - def __new__(cls, *args, **kwargs): - ''' - \brief Override creation of the object so it is create only once - (singleton pattern) - ''' - if not cls._instance: - cls._instance = super(EventBus, cls).__new__(cls, *args, **kwargs) - return cls._instance - - def __init__(self): - ''' - \brief Initializer. - - \note This function is called after __new__. - ''' - - if self._init: - return - - # log - log.debug("initialize instance") - - # intialize parent class - threading.Thread.__init__(self) - - # give this thread a name - self.name = 'eventBus' - - # local variables - self._dataLock = threading.Lock() - self._eventSem = threading.Semaphore(0) - self._pending_events = [] ##< list of pending events - self._subscriptions = {} ##< list of subscriptions - self._next_id = 1 ##< index of a new element in _subscriptions - self._init = True ##< this object was initialized - self._stats = {} - - # start asynchronous handling - self.start() - - def run(self): - # log - log.debug("thread running") - - try: - while True: - - # block until at least one event is in the pending events - self._eventSem.acquire() - - # pop the head event - try: - self._dataLock.acquire() - event = self._pending_events.pop(0) - finally: - self._dataLock.release() - - if isinstance(event,Event.Event): - # normal case - - # log - log.debug("popped event {0} ".format(event)) - - # publish - - self.publish_sync(event.get_uri(), - *event.get_args(), - minNumReceivers=event.get_minNumReceivers(), - maxNumReceivers=event.get_maxNumReceivers()) - - elif (instance(event,str)) and (event=='close'): - # teardown case - - # log - log.debug("...closed.") - - return - - else: - - # log - log.critical("unexpected event={0}".format(event)) - - raise SystemError() - except Exception as err: - log.critical(err) - raise - - #======================== public ========================================== - - def subscribe(self, func, uri=None): - ''' - \brief Adds a subscriber to the event bus. - - The given function pointer passed is called whenever an event is sent - that matches the given regular expression. If no regular expression - was given, the function is called for any emitted signal. - - \param func The function to call. - \param uri The URI trigger this fuction to be called. - - \returns The unique identifier of this registration, an int. The caller - can store and use that ID to unsubscribe. - ''' - - # log - log.info("adding subscriber: {0} -> {1}".format( - uri, - func, - ) - ) - - # param validation - assert callable(func) - if uri: - assert isinstance(uri,str) - - # create the Subscription instance - subs = Subscription.Subscription(func,uri) - - # get a unique ID for that subscriber - id = self._getNextId() - - # store subs - try: - self._dataLock.acquire() - self._subscriptions[id] = subs - finally: - self._dataLock.release() - - return id - - def unsubscribe(self, id): - ''' - \brief Removes a subscriber from the event bus. - - \param The id of the subscriber to remove, an int. - - \returns True if the subscriber was found (and removed). - \returns False if the subscriber was not found. - ''' - - # param validation - assert isinstance(id,int) - assert id > 0 - - try: - self._dataLock.acquire() - if id in self._subscriptions: - - # log - log.info("removed subscriber id {0}".format(id)) - - # delete - del self._subscriptions[id] - - return True - - else: - - # log - log.warning("could not find subscriber id {0} to remove".format(id)) - - return False - - raise SystemError() - finally: - self._dataLock.release() - - def publish(self, uri, *args, **kwargs): - ''' - \brief Publish an event. - - Publication is done asynchronously by the eventBus thread, i.e. - sometimes after this function is called. - - \param uri The URI of the published event. - \param args The arguments to pass to the callback function - ''' - # log - log.debug("publish uri={0} args={1} kwargs={2}".format(uri,args,kwargs)) - - # param validation - assert uri - assert isinstance(uri,str) - if 'minNumReceivers' in kwargs: - assert isinstance(kwargs['minNumReceivers'],int) - if 'maxNumReceivers' in kwargs: - assert isinstance(kwargs['maxNumReceivers'],int) - - try: - self._dataLock.acquire() - self._pending_events.append(Event.Event(uri, args)) - self._eventSem.release() - finally: - self._dataLock.release() - - def publish_sync(self, uri, *args, **kwargs): - ''' - \brief Publish an event synchronously. - - Publication is done before this function returns. - - \param uri The URI of the published event. - \param args The arguments to pass to the callback function - ''' - # log - log.debug("publish_sync uri={0} args={1} kwargs={2}".format(uri,args,kwargs)) - - # param validation - assert uri - assert isinstance(uri,str) - if ('minNumReceivers' in kwargs) and kwargs['minNumReceivers']: - assert isinstance(kwargs['minNumReceivers'],int) - if ('maxNumReceivers' in kwargs) and kwargs['maxNumReceivers']: - assert isinstance(kwargs['maxNumReceivers'],int) - - # update stats - try: - self._dataLock.acquire() - if uri not in self._stats: - self._stats[uri] = { - 'numIn': 0, - 'numOut': 0, - } - self._stats[uri]['numIn'] += 1 - finally: - self._dataLock.release() - - # local variables - self.numReceivers = 0 - - # publish to subscribers - try: - self._dataLock.acquire() - for (id,subs) in self._subscriptions.items(): - if subs.matches_uri(uri): - subs.get_function()(*args) - self.numReceivers += 1 - self._stats[uri]['numOut'] += self.numReceivers - finally: - self._dataLock.release() - - # ensure that number receivers is expected - if ('minNumReceivers' in kwargs) and kwargs['minNumReceivers']: - if self.numReceiverskwargs['maxNumReceivers']: - raise SystemError('expected a most {0} receivers for event {1}, got {2}'.format( - kwargs['maxNumReceivers'], - uri, - self.numReceivers, - ) - ) - - def getSubscriptions(self): - ''' - \brief Retrieve the current list of subscriptions. - - \returns The current list of subscriptions, as a dictionary of - dictionaries: - - returnVal = { - 1: { - 'uri': 'someURI' - 'function': cb_function - }, - etc. - } - - ''' - returnVal = {} - try: - self._dataLock.acquire() - for (id,subs) in self._subscriptions.items(): - returnVal[id] = { - 'uri': subs.get_event_uri(), - 'function': subs.get_function(), - } - finally: - self._dataLock.release() - return returnVal - - def getStats(self): - try: - self._dataLock.acquire() - tempStats = copy.deepcopy(self._stats) - finally: - self._dataLock.release() - - returnVal = [] - for (k,v) in tempStats.items(): - returnVal.append({ - 'uri': k, - 'numIn': v['numIn'], - 'numOut': v['numOut'], - }) - return json.dumps(returnVal,sort_keys=True,indent=4) - - def close(self): - ''' - \brief Destroy this eventBus. - - \note This also stops the thread. - ''' - - # log - log.debug("closing...") - - self._pending_events.append('close') - self._eventSem.release() - - #======================== private ========================================= - - def _getNextId(self): - assert self._next_id < sys.maxint - - try: - self._dataLock.acquire() - retunVal = self._next_id - self._next_id += 1 - finally: - self._dataLock.release() - - return retunVal diff --git a/software/openvisualizer/EventBus/Subscription.py b/software/openvisualizer/EventBus/Subscription.py deleted file mode 100644 index 94ad2eee6..000000000 --- a/software/openvisualizer/EventBus/Subscription.py +++ /dev/null @@ -1,50 +0,0 @@ -''' -Created on 24/08/2012 - -@author: xvilajosana -''' -import re - -class Subscription: - ''' - \brief Representation of an Subscription, in the event bus. - - This object contains both the URI and the function to call. - ''' - - def __init__(self, func, event_uri): - ''' - \param func The function to be called when the event is sent. - \param event_uri The URI of the signal (a string). Can be a regular - expression. - ''' - # validate params - assert func - assert callable(func) - if event_uri: - assert isinstance(event_uri,str) - - # store params - self._func = func - self._event_uri = event_uri - - # local variables - self._event_re = None - if event_uri: - self._event_re = re.compile(event_uri) - - #======================== public ========================================== - - def get_function(self): - return self._func - - def get_event_uri(self): - return self._event_uri - - def matches_uri(self, uri): - assert uri - assert isinstance(uri,str) - - if self._event_re is None: - return True - return self._event_re.match(uri) \ No newline at end of file diff --git a/software/openvisualizer/EventBus/unit_tests/test_sync.py b/software/openvisualizer/EventBus/unit_tests/test_sync.py deleted file mode 100644 index 23622464a..000000000 --- a/software/openvisualizer/EventBus/unit_tests/test_sync.py +++ /dev/null @@ -1,270 +0,0 @@ -#!/usr/bin/env python - -import os -import sys -sys.path.insert(0, os.path.join(sys.path[0], '..')) - -import time -import pprint -import logging -import logging.handlers - -import pytest - -import EventBus - -#============================ logging ========================================= - -LOGFILE_NAME = 'test_sync.log' - -import logging -class NullHandler(logging.Handler): - def emit(self, record): - pass -log = logging.getLogger('test_sync') -log.setLevel(logging.ERROR) -log.addHandler(NullHandler()) - -logHandler = logging.handlers.RotatingFileHandler(LOGFILE_NAME, - backupCount=5, - mode='w') -logHandler.setFormatter(logging.Formatter("%(asctime)s [%(name)s:%(levelname)s] %(message)s")) -for loggerName in ['test_sync', - 'EventBus',]: - temp = logging.getLogger(loggerName) - temp.setLevel(logging.DEBUG) - temp.addHandler(logHandler) - -#============================ helpers ========================================= - -class Subscriber(object): - def __init__(self,name): - self.name = name - self.resetNotifications() - - def notification_singleText(self,publishedText): - - # log - log.debug("{0} notification_singleText publishedText={1}".format(self.name, - publishedText)) - - assert isinstance(publishedText,str) - - self.notifications['text'].append(publishedText) - - def notification_doubleNum(self,num1,num2): - - # log - log.debug("{0} notification_doubleNum num1={1} num2={2}".format( - self.name, - num1, - num2)) - - assert isinstance(num1,int) - assert isinstance(num2,int) - - self.notifications['num'].append((num1,num2)) - - def resetNotifications(self): - self.notifications = { - 'text': [], - 'num': [], - } - -def prettyformat(dataToPrint): - pp = pprint.PrettyPrinter(indent=4) - return pp.pformat(dataToPrint) - -#============================ tests =========================================== - -global subscriber1 -global subscriber2 - -#----- setup - -def test_setup(): - global bus - global subscriber1 - global subscriber2 - - log.debug("\n\n----------test_setup") - - bus = EventBus.EventBus() - - assert bus - assert isinstance(bus,EventBus.EventBus) - assert bus.getSubscriptions()=={} - -#---- subscription - -def test_subscribe_both(): - global subscriber1 - global subscriber2 - - log.debug("\n\n----------test_subscribe_both") - - subscriber1 = Subscriber('subscriber1') - subscriber2 = Subscriber('subscriber2') - - EventBus.EventBus().subscribe(subscriber1.notification_singleText,'text') - EventBus.EventBus().subscribe(subscriber1.notification_doubleNum,'num') - EventBus.EventBus().subscribe(subscriber2.notification_singleText,'text') - EventBus.EventBus().subscribe(subscriber2.notification_doubleNum,'num') - - # log - log.debug(prettyformat(bus.getSubscriptions())) - - assert len(bus.getSubscriptions().keys())==4 - -#---- text publication - -def test_publishText_sync_both(): - global subscriber1 - global subscriber2 - - log.debug("\n\n----------test_publishText_sync_both") - - EventBus.EventBus().publish_sync('text','someText1') - - # log - log.debug(prettyformat(subscriber1.notifications)) - log.debug(prettyformat(subscriber2.notifications)) - - assert subscriber1.notifications=={ - 'text': ['someText1'], - 'num': [], - } - assert subscriber2.notifications=={ - 'text': ['someText1'], - 'num': [], - } - -def test_publishText_sync_both_again(): - global subscriber1 - global subscriber2 - - log.debug("\n\n----------test_publishText_sync_both_again") - - EventBus.EventBus().publish_sync('text','someText2') - - # log - log.debug(prettyformat(subscriber1.notifications)) - log.debug(prettyformat(subscriber2.notifications)) - - assert subscriber1.notifications=={ - 'text': ['someText1','someText2'], - 'num': [], - } - assert subscriber2.notifications=={ - 'text': ['someText1','someText2'], - 'num': [], - } - -def test_publishText_async_both(): - global subscriber1 - global subscriber2 - - log.debug("\n\n----------test_publishText_async_both") - - EventBus.EventBus().publish('text','someText3') - - time.sleep(1) # longest possible time for thread to publish - - # log - log.debug(prettyformat(subscriber1.notifications)) - log.debug(prettyformat(subscriber2.notifications)) - - assert subscriber1.notifications=={ - 'text': ['someText1','someText2','someText3'], - 'num': [], - } - assert subscriber2.notifications=={ - 'text': ['someText1','someText2','someText3'], - 'num': [], - } - -def test_publishText_async_both_again(): - global subscriber1 - global subscriber2 - - log.debug("\n\n----------test_publishText_async_both_again") - - EventBus.EventBus().publish('text','someText4') - - time.sleep(1) # longest possible time for thread to publish - - # log - log.debug(prettyformat(subscriber1.notifications)) - log.debug(prettyformat(subscriber2.notifications)) - - assert subscriber1.notifications=={ - 'text': ['someText1','someText2','someText3','someText4'], - 'num': [], - } - assert subscriber2.notifications=={ - 'text': ['someText1','someText2','someText3','someText4'], - 'num': [], - } - -def test_publishNum_sync_both(): - global subscriber1 - global subscriber2 - - log.debug("\n\n----------test_publishNum_sync_both") - - EventBus.EventBus().publish_sync('num',1,2) - - # log - log.debug(prettyformat(subscriber1.notifications)) - log.debug(prettyformat(subscriber2.notifications)) - - assert subscriber1.notifications=={ - 'text': ['someText1','someText2','someText3','someText4'], - 'num': [(1,2)], - } - assert subscriber2.notifications=={ - 'text': ['someText1','someText2','someText3','someText4'], - 'num': [(1,2)], - } - -#---- unsubscription - -def test_unsubscription(): - global subscriber1 - global subscriber2 - - log.debug("\n\n----------test_unsubscription") - - res = EventBus.EventBus().unsubscribe(3) - assert res - res = EventBus.EventBus().unsubscribe(4) - assert res - - # log - log.debug(prettyformat(EventBus.EventBus().getSubscriptions())) - - EventBus.EventBus().publish_sync('text','someText5') - EventBus.EventBus().publish_sync('num',3,4) - - # log - log.debug(prettyformat(subscriber1.notifications)) - log.debug(prettyformat(subscriber2.notifications)) - - assert subscriber1.notifications=={ - 'text': ['someText1','someText2','someText3','someText4','someText5'], - 'num': [(1,2),(3,4)], - } - assert subscriber2.notifications=={ - 'text': ['someText1','someText2','someText3','someText4'], - 'num': [(1,2)], - } - -#----- teardown - -def test_teardown(): - global subscriber1 - global subscriber2 - - log.debug("\n\n----------test_teardown") - - EventBus.EventBus().close() \ No newline at end of file diff --git a/software/openvisualizer/PyDispatcher-2.0.3/MANIFEST.in b/software/openvisualizer/PyDispatcher-2.0.3/MANIFEST.in deleted file mode 100644 index 558c5d2ae..000000000 --- a/software/openvisualizer/PyDispatcher-2.0.3/MANIFEST.in +++ /dev/null @@ -1,14 +0,0 @@ -include MANIFEST.in -include license.txt -include *.py -recursive-include docs *.html -recursive-include docs/images *.png -recursive-include docs/style *.css -recursive-include docs/pydoc *.html *.py -recursive-include examples *.py - -recursive-include tests *.py - -global-exclude *.bat -global-exclude ./CVS -global-exclude .cvsignore diff --git a/software/openvisualizer/PyDispatcher-2.0.3/PKG-INFO b/software/openvisualizer/PyDispatcher-2.0.3/PKG-INFO deleted file mode 100644 index b12cb4045..000000000 --- a/software/openvisualizer/PyDispatcher-2.0.3/PKG-INFO +++ /dev/null @@ -1,27 +0,0 @@ -Metadata-Version: 1.0 -Name: PyDispatcher -Version: 2.0.3 -Summary: Multi-producer-multi-consumer signal dispatching mechanism -Home-page: http://pydispatcher.sourceforge.net -Author: Mike C. Fletcher -Author-email: pydispatcher-devel@lists.sourceforge.net -License: BSD-style, see license.txt for details -Description: Dispatcher mechanism for creating event models - - PyDispatcher is an enhanced version of Patrick K. O'Brien's - original dispatcher.py module. It provides the Python - programmer with a robust mechanism for event routing within - various application contexts. - - Included in the package are the robustapply and saferef - modules, which provide the ability to selectively apply - arguments to callable objects and to reference instance - methods using weak-references. - -Keywords: dispatcher,dispatch,pydispatch,event,signal,sender,receiver,propagate,multi-consumer,multi-producer,saferef,robustapply,apply -Platform: Any -Classifier: License :: OSI Approved :: BSD License -Classifier: Programming Language :: Python -Classifier: Programming Language :: Python :: 3 -Classifier: Topic :: Software Development :: Libraries :: Python Modules -Classifier: Intended Audience :: Developers diff --git a/software/openvisualizer/PyDispatcher-2.0.3/PyDispatcher.egg-info/PKG-INFO b/software/openvisualizer/PyDispatcher-2.0.3/PyDispatcher.egg-info/PKG-INFO deleted file mode 100644 index b12cb4045..000000000 --- a/software/openvisualizer/PyDispatcher-2.0.3/PyDispatcher.egg-info/PKG-INFO +++ /dev/null @@ -1,27 +0,0 @@ -Metadata-Version: 1.0 -Name: PyDispatcher -Version: 2.0.3 -Summary: Multi-producer-multi-consumer signal dispatching mechanism -Home-page: http://pydispatcher.sourceforge.net -Author: Mike C. Fletcher -Author-email: pydispatcher-devel@lists.sourceforge.net -License: BSD-style, see license.txt for details -Description: Dispatcher mechanism for creating event models - - PyDispatcher is an enhanced version of Patrick K. O'Brien's - original dispatcher.py module. It provides the Python - programmer with a robust mechanism for event routing within - various application contexts. - - Included in the package are the robustapply and saferef - modules, which provide the ability to selectively apply - arguments to callable objects and to reference instance - methods using weak-references. - -Keywords: dispatcher,dispatch,pydispatch,event,signal,sender,receiver,propagate,multi-consumer,multi-producer,saferef,robustapply,apply -Platform: Any -Classifier: License :: OSI Approved :: BSD License -Classifier: Programming Language :: Python -Classifier: Programming Language :: Python :: 3 -Classifier: Topic :: Software Development :: Libraries :: Python Modules -Classifier: Intended Audience :: Developers diff --git a/software/openvisualizer/PyDispatcher-2.0.3/PyDispatcher.egg-info/SOURCES.txt b/software/openvisualizer/PyDispatcher-2.0.3/PyDispatcher.egg-info/SOURCES.txt deleted file mode 100644 index c1e0d8ec1..000000000 --- a/software/openvisualizer/PyDispatcher-2.0.3/PyDispatcher.egg-info/SOURCES.txt +++ /dev/null @@ -1,35 +0,0 @@ -MANIFEST.in -license.txt -setup.py -PyDispatcher.egg-info/PKG-INFO -PyDispatcher.egg-info/SOURCES.txt -PyDispatcher.egg-info/dependency_links.txt -PyDispatcher.egg-info/top_level.txt -docs/index.html -docs/images/greypinstripe.png -docs/pydoc/__init__.py -docs/pydoc/builddocs.py -docs/pydoc/pydispatch.__init__.html -docs/pydoc/pydispatch.dispatcher.html -docs/pydoc/pydispatch.errors.html -docs/pydoc/pydispatch.html -docs/pydoc/pydispatch.robust.html -docs/pydoc/pydispatch.robustapply.html -docs/pydoc/pydispatch.saferef.html -docs/pydoc/pydoc2.py -docs/pydoc/weakref.html -docs/style/sitestyle.css -examples/__init__.py -examples/extra_args.py -examples/hello_messages.py -examples/simple_sample.py -pydispatch/__init__.py -pydispatch/dispatcher.py -pydispatch/errors.py -pydispatch/robust.py -pydispatch/robustapply.py -pydispatch/saferef.py -tests/__init__.py -tests/test_dispatcher.py -tests/test_robustapply.py -tests/test_saferef.py \ No newline at end of file diff --git a/software/openvisualizer/PyDispatcher-2.0.3/PyDispatcher.egg-info/dependency_links.txt b/software/openvisualizer/PyDispatcher-2.0.3/PyDispatcher.egg-info/dependency_links.txt deleted file mode 100644 index 8b1378917..000000000 --- a/software/openvisualizer/PyDispatcher-2.0.3/PyDispatcher.egg-info/dependency_links.txt +++ /dev/null @@ -1 +0,0 @@ - diff --git a/software/openvisualizer/PyDispatcher-2.0.3/PyDispatcher.egg-info/top_level.txt b/software/openvisualizer/PyDispatcher-2.0.3/PyDispatcher.egg-info/top_level.txt deleted file mode 100644 index 62f5b70fc..000000000 --- a/software/openvisualizer/PyDispatcher-2.0.3/PyDispatcher.egg-info/top_level.txt +++ /dev/null @@ -1 +0,0 @@ -pydispatch diff --git a/software/openvisualizer/PyDispatcher-2.0.3/docs/images/greypinstripe.png b/software/openvisualizer/PyDispatcher-2.0.3/docs/images/greypinstripe.png deleted file mode 100644 index 006a3a3d6..000000000 Binary files a/software/openvisualizer/PyDispatcher-2.0.3/docs/images/greypinstripe.png and /dev/null differ diff --git a/software/openvisualizer/PyDispatcher-2.0.3/docs/index.html b/software/openvisualizer/PyDispatcher-2.0.3/docs/index.html deleted file mode 100644 index 4123d0b91..000000000 --- a/software/openvisualizer/PyDispatcher-2.0.3/docs/index.html +++ /dev/null @@ -1,263 +0,0 @@ - - - - - Python Dispatch Package - - - - - - - - -

PyDispatcher

- -

PyDispatcher provides the Python programmer -with a multiple-producer-multiple-consumer signal-registration and -routing infrastructure for use in multiple contexts.  The -mechanism -of PyDispatcher started life as a highly rated recipe -in the Python -Cookbook.  The project -aims -to include various enhancements to the recipe developed during use in -various applications.  It is primarily maintained by Mike Fletcher.  A derivative -of the project provides the Django web framework's "signal" system.
-

- -

To be more concrete about what PyDispatcher does for you:
-

- -
    - -
  • provides a centralized service for delivering messages to -registered objects (in the local process).  It allows you to -register any number of functions (callable objects) which can receive -signals from senders.
  • -
      -
    • registration can be for all senders, particular sending -objects, or "anonymous" messages (messages where the sender is None)
      -
    • -
    • registration can be for any signal, or particular signals
    • -
    • a single signal will be delivered to all appropriate registered -receivers, so that multiple registrations do not interfere with each -other
      -
    • -
    -
  • there is no requirement for the sender or receiver to be -dispatcher-aware.  Any Python object save the None object can act -as a sender, and any callable object can act as a receiver.  There -is no need to inherit from a particular class or provide a particular -interface on the object.
    -
  • -
  • the system uses weak references to receivers wherever possible
  • -
      -
    • object lifetimes are not affected by PyDispatcher registrations -(that is, when your object goes away, the registrations related to the -object also go away). 
      -
    • -
    • references to common transient objects (in particular instance -methods) are stored as compound weak references. 
      -
    • -
    • weak references can be disabled on a -registration-by-registration basis
    • -
    -
  • allows rich signal types, signals are simply hashable objects -used to store and retrieve sub-tables, they are otherwise opaque to the -dispatcher mechanism
  • -
  • allows sending more information when sending than any particular -receiver can handle, dispatcher automatically culls those arguments -which are not appropriate for the particular receiver.  This -allows registering very simple functions dealing with general messages, -while still allowing natural passing of arguments to higher level -functions.
    -
  • -
- -

The dispatcher mechanism is particularly useful when constructing -Model-View-Controller style applications where it is not desirable to -have the Model objects aware of the event model.

- -

Acquisition and Installation

- -

PyDispatcher is available as a standard Python distutils -installation package from the Python Package Index (PyPI).  To -install, run:
-

- -
pip install PyDispatcher
- -

PyDispatcher does not include any binary packages, so there should -be no issues in installation.  PyDispatcher is maintained on the -LaunchPad project in bzr.  To help develop, check out the project -like so:

- -
bzr branch lp:~mcfletch/pydispatcher/working
- -

You can either send a pull request via LaunchPad or email a -patch-set via:

- -
bzr send --mail-to=mcfletch@vrplumber.com
- -

PyDispatcher represents one of the more involved -usage patterns for Python weakref objects. We have discovered a few -problems in weakref operation of which users of the package should be -aware.
-

- -

Python 2.2.2 (and -earlier) weak reference implementations have a subtle bug -in their weakref destructor code which can cause memory access errors -(aka segfaults) on program shutdown.  If you are using Python 2.2, -it is strongly -recommended that you use Python 2.2.3 or -later -when using PyDispatcher.  Note that this will not address the -following issue.
-

- -

Python 2.3.2 (and earlier) has a different (even -more subtle) bug -in the weakref destructor code which, again, can cause segfaults.  -If you are using Python 2.3, it is strongly -recommended that you use Python 2.3.3 or -later -when using PyDispatcher.  This bug-fix will not be ported back to -the Python 2.2.x branch, so if you are using Python 2.2.3 you may -encounter this situation. -

- -

Documentation

- -

You can find usage samples in the examples directory of the -distribution.  The dispatcher module's reference documentation is -currently the major source of information regarding usage.
-

- -

PyDispatcher welcomes contributions, suggestions, and feedback from -users in the pydispatcher-dev mailing -list.

-

Usage

-

To set up a function to receive signals:

-
from pydispatch import dispatcher
SIGNAL = 'my-first-signal'

def handle_event( sender ):
"""Simple event handler"""
print 'Signal was sent by', sender
dispatcher.connect( handle_event, signal=SIGNAL, sender=dispatcher.Any )
-

The use of the Any object allows the handler to listen for messages -from any Sender or to listen to Any message being sent.  To send -messages:

-
first_sender = object()
second_sender = {}
def main( ):
dispatcher.send( signal=SIGNAL, sender=first_sender )
dispatcher.send( signal=SIGNAL, sender=second_sender )
-

Which causes the following to be printed:

-
Signal was sent by <object object at 0x196a090>
Signal was sent by {}
-

Handler Functions

-

Handler functions in PyDispatcher are relatively loose in their -definition.  A handler can simply declare the parameters it would -like to receive and receive only those parameters when the signal is -sent.  The sender can include extra parameters for those handlers -which require them without worrying about whether a more generic -handler can accept them:

-
def handle_specific_event( sender, moo ):
"""Handle a simple event, requiring a "moo" parameter"""
print 'Specialized event for %(sender)s moo=%(moo)r'%locals()
dispatcher.connect( handle_specific_event, signal=SIGNAL2, sender=dispatcher.Any )
-

This connection requires that all senders of the particular signal -send a "moo" parameter, but a handler that listens for all events and -does not provide a "moo" parameter would silently ignore the sender -having passed a "moo".

-

2 parameters are always available to handler functions if they would like to use them:

- - - - - - - - - - - - - - - -
Parameter
-
Value
-
sender
-
Object from/for which the event was sent, can be dispatcher.Anonymous for anonymous signals
-
signal
-
Signal object used when sending
-
-

Positional arguments and named arguments are passed through, but if -positional arguments are used, they will fill in the parameters of the -receiver in order and cause conflicts if named parameters are specified -which match their names.  Generally it is advisable to use named -arguments when defining sending messages.
-

- - -

Related Software

- -
    - -
  • Louie
  • -
      -
    • Reworked pydispatcher providing plugin infrastructure including -Twisted and PyQt specific support
    • -
    -
- -

Release Notes

- -
    - -
  • Version 2.0.3
  • -
      -
    • Support for Python 3.2 (via 2to3) added, Python 2.x is still -the primary development target
      -
    • -
    -
  • Version 2.0.2
  • -
      -
    • Further packaging fixes.
      -
    • -
    -
  • Version 2.0.1 (this version and all previous versions are -available from the old SourceForge -project)
    -
  • -
      -
    • Packaging fixes to allow for easy_install based installation
    • -
    -
  • Version 2.0.0
  • -
      -
    • Renames the top-level package to "pydispatch" to avoid -conflicts with common conflicting "dispatch" module.
    • -
    -
  • Version 1.0.3
  • -
      -
    • Add "robust" module with single function sendRobust, which -catches errors during callbacks and returns the error instances instead -of propagating the error
    • -
    • Patch bug in SafeRef deletion where traceback module has -already been deleted by interpreter shutdown
    • -
    • Patch bug in _removeReceiver where sendersBack has already been -deleted by interpreter shutdown
    • -
    • Make SafeRef pre-cache method name to allow for repr after -cleanup of the method
    • -
    -
  • Version 1.0.2
  • -
      -
    • Fixes another memory leak, again wrt the back-reference table
      -
    • -
    -
  • Version 1.0.1
  • -
      -
    • Fixes 2 memory leaks, one regarding the back-reference table -for receivers, the other being a failure to register all receivers -beyond the first for deletion
    • -
    -
  • Version 1.0.0
  • -
      -
    • Initial SourceForge release with restructured codebase
      -
    • -
    -
- - - - \ No newline at end of file diff --git a/software/openvisualizer/PyDispatcher-2.0.3/docs/pydoc/__init__.py b/software/openvisualizer/PyDispatcher-2.0.3/docs/pydoc/__init__.py deleted file mode 100644 index 02576fcfe..000000000 --- a/software/openvisualizer/PyDispatcher-2.0.3/docs/pydoc/__init__.py +++ /dev/null @@ -1,7 +0,0 @@ -"""pydoc documentation system with enhancements and automatic local builder - -This package is based on the standard pydoc package, -with a few minor enhancements, and a slightly modified -format. An automatic mechanism for generating extensive -documentation for the OpenGLContext project is provided. -""" \ No newline at end of file diff --git a/software/openvisualizer/PyDispatcher-2.0.3/docs/pydoc/builddocs.py b/software/openvisualizer/PyDispatcher-2.0.3/docs/pydoc/builddocs.py deleted file mode 100644 index d53bf89dd..000000000 --- a/software/openvisualizer/PyDispatcher-2.0.3/docs/pydoc/builddocs.py +++ /dev/null @@ -1,26 +0,0 @@ -#! /usr/bin/env python -"""Script to automatically generate OpenGLContext documentation""" -import pydoc2 - -if __name__ == "__main__": - excludes = [ - "math", - "string", - ] - stops = [ - "OpenGL.Demo.NeHe", - "OpenGL.Demo.GLE", - "OpenGL.Demo.da", - ] - - modules = [ - "pydispatch", - "weakref", - ] - pydoc2.PackageDocumentationGenerator( - baseModules = modules, - destinationDirectory = ".", - exclusions = excludes, - recursionStops = stops, - ).process () - diff --git a/software/openvisualizer/PyDispatcher-2.0.3/docs/pydoc/pydispatch.__init__.html b/software/openvisualizer/PyDispatcher-2.0.3/docs/pydoc/pydispatch.__init__.html deleted file mode 100644 index 1e4bc6ada..000000000 --- a/software/openvisualizer/PyDispatcher-2.0.3/docs/pydoc/pydispatch.__init__.html +++ /dev/null @@ -1,32 +0,0 @@ - - -Python: module pydispatch.__init__ - - - - -
 
- 
pydispatch.__init__ (version 2.0.3)
index
/home/mcfletch/pylive/pydispatch/pydispatch/__init__.py
-

Multi-consumer multi-producer dispatching mechanism

-

- - - - - -
 
-Data
       __author__ = "Patrick K. O'Brien"
-__file__ = '/home/mcfletch/pylive/pydispatch/pydispatch/__init__.pyc'
-__license__ = 'BSD-style, see license.txt for details'
-__name__ = 'pydispatch.__init__'
-__version__ = '2.0.3'

- - - - - -
 
-Author
       Patrick K. O'Brien
- \ No newline at end of file diff --git a/software/openvisualizer/PyDispatcher-2.0.3/docs/pydoc/pydispatch.dispatcher.html b/software/openvisualizer/PyDispatcher-2.0.3/docs/pydoc/pydispatch.dispatcher.html deleted file mode 100644 index ba0e1c9ab..000000000 --- a/software/openvisualizer/PyDispatcher-2.0.3/docs/pydoc/pydispatch.dispatcher.html +++ /dev/null @@ -1,307 +0,0 @@ - - -Python: module pydispatch.dispatcher - - - - -
 
- 
pydispatch.dispatcher (version 1.1)
index
/home/mcfletch/pylive/pydispatch/pydispatch/dispatcher.py
-

Multiple-producer-multiple-consumer signal-dispatching

-dispatcher is the core of the PyDispatcher system,
-providing the primary API and the core logic for the
-system.

-Module attributes of note:

-        Any -- Singleton used to signal either "Any Sender" or
-                "Any Signal".  See documentation of the _Any class.
-        Anonymous -- Singleton used to signal "Anonymous Sender"
-                See documentation of the _Anonymous class.

-Internal attributes:
-        WEAKREF_TYPES -- tuple of types/classes which represent
-                weak references to receivers, and thus must be de-
-                referenced on retrieval to retrieve the callable
-                object
-        connections -- { senderkey (id) : { signal : [receivers...]}}
-        senders -- { senderkey (id) : weakref(sender) }
-                used for cleaning up sender references on sender
-                deletion
-        sendersBack -- { receiverkey (id) : [senderkey (id)...] }
-                used for cleaning up receiver references on receiver
-                deletion, (considerably speeds up the cleanup process
-                vs. the original code.)

-

- - - - - -
 
-Modules
       
pydispatch.errors
-pydispatch.robustapply
-
pydispatch.saferef
-types
-
weakref
-

- - - - - -
 
-Classes
       
-
_Parameter -
-
-
_Anonymous -
_Any -
-
-
-

- - - - - - - -
 
-class _Anonymous(_Parameter)
   Singleton used to signal "Anonymous Sender"

-The Anonymous object is used to signal that the sender
-of a message is not specified (as distinct from being
-"any sender").  Registering callbacks for Anonymous
-will only receive messages sent without senders.  Sending
-with anonymous will only send messages to those receivers
-registered for Any or Anonymous.

-Note:
-        The default sender for connect is Any, while the
-        default sender for send is Anonymous.  This has
-        the effect that if you do not specify any senders
-        in either function then all messages are routed
-        as though there was a single sender (Anonymous)
-        being used everywhere.
 
 Methods inherited from _Parameter:
-
__repr__(self)
- -

- - - - - - - -
 
-class _Any(_Parameter)
   Singleton used to signal either "Any Sender" or "Any Signal"

-The Any object can be used with connect, disconnect,
-send, or sendExact to signal that the parameter given
-Any should react to all senders/signals, not just
-a particular sender/signal.
 
 Methods inherited from _Parameter:
-
__repr__(self)
- -

- - - - - - - -
 
-class _Parameter
   Used to represent default parameter values.
 
 Methods defined here:
-
__repr__(self)
- -

- - - - - -
 
-Functions
       
_cleanupConnections(senderkey, signal)
Delete any empty signals for senderkey. Delete senderkey if empty.
-
_killBackref(receiver, senderkey)
Do the actual removal of back reference from receiver to senderkey
-
_removeBackrefs(senderkey)
Remove all back-references to this senderkey
-
_removeOldBackRefs(senderkey, signal, receiver, receivers)
Kill old sendersBack references from receiver

-This guards against multiple registration of the same
-receiver for a given signal and sender leaking memory
-as old back reference records build up.

-Also removes old receiver instance from receivers
-
_removeReceiver(receiver)
Remove receiver from connections.
-
_removeSender(senderkey)
Remove senderkey from connections.
-
connect(receiver, signal=_Any, sender=_Any, weak=True)
Connect receiver to sender for signal

-receiver -- a callable Python object which is to receive
-        messages/signals/events.  Receivers must be hashable
-        objects.

-        if weak is True, then receiver must be weak-referencable
-        (more precisely saferef.safeRef() must be able to create
-        a reference to the receiver).

-        Receivers are fairly flexible in their specification,
-        as the machinery in the robustApply module takes care
-        of most of the details regarding figuring out appropriate
-        subsets of the sent arguments to apply to a given
-        receiver.

-        Note:
-                if receiver is itself a weak reference (a callable),
-                it will be de-referenced by the system's machinery,
-                so *generally* weak references are not suitable as
-                receivers, though some use might be found for the
-                facility whereby a higher-level library passes in
-                pre-weakrefed receiver references.

-signal -- the signal to which the receiver should respond

-        if Any, receiver will receive any signal from the
-        indicated sender (which might also be Any, but is not
-        necessarily Any).
-        
-        Otherwise must be a hashable Python object other than
-        None (DispatcherError raised on None).
-        
-sender -- the sender to which the receiver should respond

-        if Any, receiver will receive the indicated signals
-        from any sender.
-        
-        if Anonymous, receiver will only receive indicated
-        signals from send/sendExact which do not specify a
-        sender, or specify Anonymous explicitly as the sender.

-        Otherwise can be any python object.
-        
-weak -- whether to use weak references to the receiver
-        By default, the module will attempt to use weak
-        references to the receiver objects.  If this parameter
-        is false, then strong references will be used.

-returns None, may raise DispatcherTypeError
-
disconnect(receiver, signal=_Any, sender=_Any, weak=True)
Disconnect receiver from sender for signal

-receiver -- the registered receiver to disconnect
-signal -- the registered signal to disconnect
-sender -- the registered sender to disconnect
-weak -- the weakref state to disconnect

-disconnect reverses the process of connect,
-the semantics for the individual elements are
-logically equivalent to a tuple of
-(receiver, signal, sender, weak) used as a key
-to be deleted from the internal routing tables.
-(The actual process is slightly more complex
-but the semantics are basically the same).

-Note:
-        Using disconnect is not required to cleanup
-        routing when an object is deleted, the framework
-        will remove routes for deleted objects
-        automatically.  It's only necessary to disconnect
-        if you want to stop routing to a live object.
-        
-returns None, may raise DispatcherTypeError or
-        DispatcherKeyError
-
getAllReceivers(sender=_Any, signal=_Any)
Get list of all receivers from global tables

-This gets all receivers which should receive
-the given signal from sender, each receiver should
-be produced only once by the resulting generator
-
getReceivers(sender=_Any, signal=_Any)
Get list of receivers from global tables

-This utility function allows you to retrieve the
-raw list of receivers from the connections table
-for the given sender and signal pair.

-Note:
-        there is no guarantee that this is the actual list
-        stored in the connections table, so the value
-        should be treated as a simple iterable/truth value
-        rather than, for instance a list to which you
-        might append new records.

-Normally you would use liveReceiversgetReceivers( ...))
-to retrieve the actual receiver objects as an iterable
-object.
-
liveReceivers(receivers)
Filter sequence of receivers to get resolved, live receivers

-This is a generator which will iterate over
-the passed sequence, checking for weak references
-and resolving them, then returning all live
-receivers.
-
send(signal=_Any, sender=_Anonymous, *arguments, **named)
Send signal from sender to all connected receivers.

-signal -- (hashable) signal value, see connect for details

-sender -- the sender of the signal

-        if Any, only receivers registered for Any will receive
-        the message.

-        if Anonymous, only receivers registered to receive
-        messages from Anonymous or Any will receive the message

-        Otherwise can be any python object (normally one
-        registered with a connect if you actually want
-        something to occur).

-arguments -- positional arguments which will be passed to
-        *all* receivers. Note that this may raise TypeErrors
-        if the receivers do not allow the particular arguments.
-        Note also that arguments are applied before named
-        arguments, so they should be used with care.

-named -- named arguments which will be filtered according
-        to the parameters of the receivers to only provide those
-        acceptable to the receiver.

-Return a list of tuple pairs [(receiver, response), ... ]

-if any receiver raises an error, the error propagates back
-through send, terminating the dispatch loop, so it is quite
-possible to not have all receivers called if a raises an
-error.
-
sendExact(signal=_Any, sender=_Anonymous, *arguments, **named)
Send signal only to those receivers registered for exact message

-sendExact allows for avoiding Any/Anonymous registered
-handlers, sending only to those receivers explicitly
-registered for a particular signal on a particular
-sender.
-

- - - - - -
 
-Data
       Anonymous = _Anonymous
-Any = _Any
-WEAKREF_TYPES = (<type 'weakref'>, <class 'pydispatch.saferef.BoundMethodWeakref'>)
-__author__ = "Patrick K. O'Brien <pobrien@orbtech.com>"
-__cvsid__ = '$Id: dispatcher.py,v 1.1 2010/03/30 15:45:55 mcfletch Exp $'
-__file__ = '/home/mcfletch/pylive/pydispatch/pydispatch/dispatcher.pyc'
-__name__ = 'pydispatch.dispatcher'
-__package__ = 'pydispatch'
-__version__ = '1.1'
-connections = {}
-generators = _Feature((2, 2, 0, 'alpha', 1), (2, 3, 0, 'final', 0), 0)
-senders = {}
-sendersBack = {}

- - - - - -
 
-Author
       Patrick K. O'Brien <pobrien@orbtech.com>
- \ No newline at end of file diff --git a/software/openvisualizer/PyDispatcher-2.0.3/docs/pydoc/pydispatch.errors.html b/software/openvisualizer/PyDispatcher-2.0.3/docs/pydoc/pydispatch.errors.html deleted file mode 100644 index 63accfc44..000000000 --- a/software/openvisualizer/PyDispatcher-2.0.3/docs/pydoc/pydispatch.errors.html +++ /dev/null @@ -1,242 +0,0 @@ - - -Python: module pydispatch.errors - - - - -
 
- 
pydispatch.errors
index
/home/mcfletch/pylive/pydispatch/pydispatch/errors.py
-

Error types for dispatcher mechanism

-

- - - - - -
 
-Classes
       
-
Exception(BaseException) -
-
-
DispatcherError -
-
-
DispatcherKeyError(KeyError, DispatcherError) -
DispatcherTypeError(TypeError, DispatcherError) -
-
-
-
-
KeyError(LookupError) -
-
-
DispatcherKeyError(KeyError, DispatcherError) -
-
-
TypeError(StandardError) -
-
-
DispatcherTypeError(TypeError, DispatcherError) -
-
-
-

- - - - - - - -
 
-class DispatcherError(Exception)
   Base class for all Dispatcher errors
 
 
Method resolution order:
-
DispatcherError
-
Exception
-
BaseException
-
object
-
-
-Data descriptors defined here:
-
__weakref__
-
list of weak references to the object (if defined)
-
-
-Methods inherited from Exception:
-
__init__(...)
x.__init__(...) initializes x; see help(type(x)) for signature
- -
-Data and other attributes inherited from Exception:
-
__new__ = <built-in method __new__ of type object>
T.__new__(S, ...) -> a new object with type S, a subtype of T
- -
-Methods inherited from BaseException:
-
__delattr__(...)
x.__delattr__('name') <==> del x.name
- -
__getattribute__(...)
x.__getattribute__('name') <==> x.name
- -
__getitem__(...)
x.__getitem__(y) <==> x[y]
- -
__getslice__(...)
x.__getslice__(i, j) <==> x[i:j]

-Use of negative indices is not supported.
- -
__reduce__(...)
- -
__repr__(...)
x.__repr__() <==> repr(x)
- -
__setattr__(...)
x.__setattr__('name', value) <==> x.name = value
- -
__setstate__(...)
- -
__str__(...)
x.__str__() <==> str(x)
- -
__unicode__(...)
- -
-Data descriptors inherited from BaseException:
-
__dict__
-
-
args
-
-
message
-
-

- - - - - - - -
 
-class DispatcherKeyError(KeyError, DispatcherError)
   Error raised when unknown (sender,signal) set specified
 
 
Method resolution order:
-
DispatcherKeyError
-
KeyError
-
LookupError
-
StandardError
-
DispatcherError
-
Exception
-
BaseException
-
object
-
-
-Data descriptors defined here:
-
__weakref__
-
list of weak references to the object (if defined)
-
-
-Methods inherited from KeyError:
-
__init__(...)
x.__init__(...) initializes x; see help(type(x)) for signature
- -
__str__(...)
x.__str__() <==> str(x)
- -
-Data and other attributes inherited from KeyError:
-
__new__ = <built-in method __new__ of type object>
T.__new__(S, ...) -> a new object with type S, a subtype of T
- -
-Methods inherited from BaseException:
-
__delattr__(...)
x.__delattr__('name') <==> del x.name
- -
__getattribute__(...)
x.__getattribute__('name') <==> x.name
- -
__getitem__(...)
x.__getitem__(y) <==> x[y]
- -
__getslice__(...)
x.__getslice__(i, j) <==> x[i:j]

-Use of negative indices is not supported.
- -
__reduce__(...)
- -
__repr__(...)
x.__repr__() <==> repr(x)
- -
__setattr__(...)
x.__setattr__('name', value) <==> x.name = value
- -
__setstate__(...)
- -
__unicode__(...)
- -
-Data descriptors inherited from BaseException:
-
__dict__
-
-
args
-
-
message
-
-

- - - - - - - -
 
-class DispatcherTypeError(TypeError, DispatcherError)
   Error raised when inappropriate signal-type specified (None)
 
 
Method resolution order:
-
DispatcherTypeError
-
TypeError
-
StandardError
-
DispatcherError
-
Exception
-
BaseException
-
object
-
-
-Data descriptors defined here:
-
__weakref__
-
list of weak references to the object (if defined)
-
-
-Methods inherited from TypeError:
-
__init__(...)
x.__init__(...) initializes x; see help(type(x)) for signature
- -
-Data and other attributes inherited from TypeError:
-
__new__ = <built-in method __new__ of type object>
T.__new__(S, ...) -> a new object with type S, a subtype of T
- -
-Methods inherited from BaseException:
-
__delattr__(...)
x.__delattr__('name') <==> del x.name
- -
__getattribute__(...)
x.__getattribute__('name') <==> x.name
- -
__getitem__(...)
x.__getitem__(y) <==> x[y]
- -
__getslice__(...)
x.__getslice__(i, j) <==> x[i:j]

-Use of negative indices is not supported.
- -
__reduce__(...)
- -
__repr__(...)
x.__repr__() <==> repr(x)
- -
__setattr__(...)
x.__setattr__('name', value) <==> x.name = value
- -
__setstate__(...)
- -
__str__(...)
x.__str__() <==> str(x)
- -
__unicode__(...)
- -
-Data descriptors inherited from BaseException:
-
__dict__
-
-
args
-
-
message
-
-

- - - - - -
 
-Data
       __file__ = '/home/mcfletch/pylive/pydispatch/pydispatch/errors.pyc'
-__name__ = 'pydispatch.errors'
- \ No newline at end of file diff --git a/software/openvisualizer/PyDispatcher-2.0.3/docs/pydoc/pydispatch.html b/software/openvisualizer/PyDispatcher-2.0.3/docs/pydoc/pydispatch.html deleted file mode 100644 index 3800564f7..000000000 --- a/software/openvisualizer/PyDispatcher-2.0.3/docs/pydoc/pydispatch.html +++ /dev/null @@ -1,40 +0,0 @@ - - -Python: package pydispatch - - - - -
 
- 
pydispatch (version 2.0.3)
index
/home/mcfletch/pylive/pydispatch/pydispatch/__init__.py
-

Multi-consumer multi-producer dispatching mechanism

-

- - - - - -
 
-Package Contents
       __init__ -- Multi-consumer multi-producer dispatching mechanism
dispatcher -- Multiple-producer-multiple-consumer signal-dispatching
errors -- Error types for dispatcher mechanism
robust -- Module implementing error-catching version of send (sendRobust)
robustapply -- Robust apply mechanism
saferef -- Refactored "safe reference" from dispatcher.py

- - - - - -
 
-Data
       __author__ = "Patrick K. O'Brien"
-__file__ = '/home/mcfletch/pylive/pydispatch/pydispatch/__init__.pyc'
-__license__ = 'BSD-style, see license.txt for details'
-__name__ = 'pydispatch'
-__path__ = ['/home/mcfletch/pylive/pydispatch/pydispatch']
-__version__ = '2.0.3'

- - - - - -
 
-Author
       Patrick K. O'Brien
- \ No newline at end of file diff --git a/software/openvisualizer/PyDispatcher-2.0.3/docs/pydoc/pydispatch.robust.html b/software/openvisualizer/PyDispatcher-2.0.3/docs/pydoc/pydispatch.robust.html deleted file mode 100644 index 693af1c80..000000000 --- a/software/openvisualizer/PyDispatcher-2.0.3/docs/pydoc/pydispatch.robust.html +++ /dev/null @@ -1,62 +0,0 @@ - - -Python: module pydispatch.robust - - - - -
 
- 
pydispatch.robust
index
/home/mcfletch/pylive/pydispatch/pydispatch/robust.py
-

Module implementing error-catching version of send (sendRobust)

-

- - - - - -
 
-Functions
       
sendRobust(signal=_Any, sender=_Anonymous, *arguments, **named)
Send signal from sender to all connected receivers catching errors

-signal -- (hashable) signal value, see connect for details

-sender -- the sender of the signal

-        if Any, only receivers registered for Any will receive
-        the message.

-        if Anonymous, only receivers registered to receive
-        messages from Anonymous or Any will receive the message

-        Otherwise can be any python object (normally one
-        registered with a connect if you actually want
-        something to occur).

-arguments -- positional arguments which will be passed to
-        *all* receivers. Note that this may raise TypeErrors
-        if the receivers do not allow the particular arguments.
-        Note also that arguments are applied before named
-        arguments, so they should be used with care.

-named -- named arguments which will be filtered according
-        to the parameters of the receivers to only provide those
-        acceptable to the receiver.

-Return a list of tuple pairs [(receiver, response), ... ]

-if any receiver raises an error (specifically any subclass of Exception),
-the error instance is returned as the result for that receiver.
-

- - - - - -
 
-Data
       Anonymous = _Anonymous
-Any = _Any
-__file__ = '/home/mcfletch/pylive/pydispatch/pydispatch/robust.pyc'
-__name__ = 'pydispatch.robust'
-__package__ = 'pydispatch'
- \ No newline at end of file diff --git a/software/openvisualizer/PyDispatcher-2.0.3/docs/pydoc/pydispatch.robustapply.html b/software/openvisualizer/PyDispatcher-2.0.3/docs/pydoc/pydispatch.robustapply.html deleted file mode 100644 index c4f943810..000000000 --- a/software/openvisualizer/PyDispatcher-2.0.3/docs/pydoc/pydispatch.robustapply.html +++ /dev/null @@ -1,54 +0,0 @@ - - -Python: module pydispatch.robustapply - - - - -
 
- 
pydispatch.robustapply
index
/home/mcfletch/pylive/pydispatch/pydispatch/robustapply.py
-

Robust apply mechanism

-Provides a function "call", which can sort out
-what arguments a given callable object can take,
-and subset the given arguments to match only
-those which are acceptable.

-

- - - - - -
 
-Modules
       
sys
-

- - - - - -
 
-Functions
       
function(receiver)
Get function-like callable object for given receiver

-returns (function_or_method, codeObject, fromMethod)

-If fromMethod is true, then the callable already
-has its first argument bound
-
robustApply(receiver, *arguments, **named)
Call receiver with arguments and an appropriate subset of named
-

- - - - - -
 
-Data
       __file__ = '/home/mcfletch/pylive/pydispatch/pydispatch/robustapply.pyc'
-__name__ = 'pydispatch.robustapply'
-__package__ = 'pydispatch'
-func_code = 'func_code'
-im_code = 'im_code'
-im_func = 'im_func'
-im_self = 'im_self'
- \ No newline at end of file diff --git a/software/openvisualizer/PyDispatcher-2.0.3/docs/pydoc/pydispatch.saferef.html b/software/openvisualizer/PyDispatcher-2.0.3/docs/pydoc/pydispatch.saferef.html deleted file mode 100644 index 48c8c8d68..000000000 --- a/software/openvisualizer/PyDispatcher-2.0.3/docs/pydoc/pydispatch.saferef.html +++ /dev/null @@ -1,164 +0,0 @@ - - -Python: module pydispatch.saferef - - - - -
 
- 
pydispatch.saferef
index
/home/mcfletch/pylive/pydispatch/pydispatch/saferef.py
-

Refactored "safe reference" from dispatcher.py

-

- - - - - -
 
-Modules
       
sys
-
traceback
-
weakref
-

- - - - - -
 
-Classes
       
-
object -
-
-
BoundMethodWeakref -
-
-
-

- - - - - - - -
 
-class BoundMethodWeakref(object)
   'Safe' and reusable weak references to instance methods

-BoundMethodWeakref objects provide a mechanism for
-referencing a bound method without requiring that the
-method object itself (which is normally a transient
-object) is kept alive.  Instead, the BoundMethodWeakref
-object keeps weak references to both the object and the
-function which together define the instance method.

-Attributes:
-        key -- the identity key for the reference, calculated
-                by the class's calculateKey method applied to the
-                target instance method
-        deletionMethods -- sequence of callable objects taking
-                single argument, a reference to this object which
-                will be called when *either* the target object or
-                target function is garbage collected (i.e. when
-                this object becomes invalid).  These are specified
-                as the onDelete parameters of safeRef calls.
-        weakSelf -- weak reference to the target object
-        weakFunc -- weak reference to the target function

-Class Attributes:
-        _allInstances -- class attribute pointing to all live
-                BoundMethodWeakref objects indexed by the class's
-                calculateKey(target) method applied to the target
-                objects.  This weak value dictionary is used to
-                short-circuit creation so that multiple references
-                to the same (object, function) pair produce the
-                same BoundMethodWeakref instance.
 
 Methods defined here:
-
__call__(self)
Return a strong reference to the bound method

-If the target cannot be retrieved, then will
-return None, otherwise returns a bound instance
-method for our object and function.

-Note:
-        You may call this method any number of times,
-        as it does not invalidate the reference.
- -
__cmp__(self, other)
Compare with another reference
- -
__init__(self, target, onDelete=None)
Return a weak-reference-like instance for a bound method

-target -- the instance-method target for the weak
-        reference, must have <im_self> and <im_func> attributes
-        and be reconstructable via:
-                target.<im_func>.__get__( target.<im_self> )
-        which is true of built-in instance methods.
-onDelete -- optional callback which will be called
-        when this weak reference ceases to be valid
-        (i.e. either the object or the function is garbage
-        collected).  Should take a single argument,
-        which will be passed a pointer to this object.
- -
__nonzero__(self)
Whether we are still a valid reference
- -
__repr__ = __str__(self)
- -
__str__(self)
Give a friendly representation of the object
- -
-Class methods defined here:
-
calculateKey(cls, target) from type
Calculate the reference key for this reference

-Currently this is a two-tuple of the id()'s of the
-target object and the target function respectively.
- -
-Static methods defined here:
-
__new__(cls, target, onDelete=None, *arguments, **named)
Create new instance or return current instance

-Basically this method of construction allows us to
-short-circuit creation of references to already-
-referenced instance methods.  The key corresponding
-to the target is calculated, and if there is already
-an existing reference, that is returned, with its
-deletionMethods attribute updated.  Otherwise the
-new instance is created and registered in the table
-of already-referenced methods.
- -
-Data descriptors defined here:
-
__dict__
-
dictionary for instance variables (if defined)
-
-
__weakref__
-
list of weak references to the object (if defined)
-
-

- - - - - -
 
-Functions
       
safeRef(target, onDelete=None)
Return a *safe* weak reference to a callable target

-target -- the object to be weakly referenced, if it's a
-        bound method reference, will create a BoundMethodWeakref,
-        otherwise creates a simple weakref.
-onDelete -- if provided, will have a hard reference stored
-        to the callable to be called after the safe reference
-        goes out of scope with the reference object, (either a
-        weakref or a BoundMethodWeakref) as argument.
-

- - - - - -
 
-Data
       __file__ = '/home/mcfletch/pylive/pydispatch/pydispatch/saferef.pyc'
-__name__ = 'pydispatch.saferef'
-__package__ = 'pydispatch'
-im_func = 'im_func'
-im_self = 'im_self'
- \ No newline at end of file diff --git a/software/openvisualizer/PyDispatcher-2.0.3/docs/pydoc/pydoc2.py b/software/openvisualizer/PyDispatcher-2.0.3/docs/pydoc/pydoc2.py deleted file mode 100644 index 95660a2d7..000000000 --- a/software/openvisualizer/PyDispatcher-2.0.3/docs/pydoc/pydoc2.py +++ /dev/null @@ -1,381 +0,0 @@ -"""Pydoc sub-class for generating documentation for entire packages""" -import pydoc, inspect, os, string -import sys, imp, os, stat, re, types, inspect -from repr import Repr -from string import expandtabs, find, join, lower, split, strip, rfind, rstrip - - -class DefaultFormatter(pydoc.HTMLDoc): - def docmodule(self, object, name=None, mod=None, packageContext = None, *ignored): - """Produce HTML documentation for a module object.""" - name = object.__name__ # ignore the passed-in name - parts = split(name, '.') - links = [] - for i in range(len(parts)-1): - links.append( - '%s' % - (join(parts[:i+1], '.'), parts[i])) - linkedname = join(links + parts[-1:], '.') - head = '%s' % linkedname - try: - path = inspect.getabsfile(object) - url = path - if sys.platform == 'win32': - import nturl2path - url = nturl2path.pathname2url(path) - filelink = '%s' % (url, path) - except TypeError: - filelink = '(built-in)' - info = [] - if hasattr(object, '__version__'): - version = str(object.__version__) - if version[:11] == '$' + 'Revision: ' and version[-1:] == '$': - version = strip(version[11:-1]) - info.append('version %s' % self.escape(version)) - if hasattr(object, '__date__'): - info.append(self.escape(str(object.__date__))) - if info: - head = head + ' (%s)' % join(info, ', ') - result = self.heading( - head, '#ffffff', '#7799ee', 'index
' + filelink) - - modules = inspect.getmembers(object, inspect.ismodule) - - classes, cdict = [], {} - for key, value in inspect.getmembers(object, inspect.isclass): - if (inspect.getmodule(value) or object) is object: - classes.append((key, value)) - cdict[key] = cdict[value] = '#' + key - for key, value in classes: - for base in value.__bases__: - key, modname = base.__name__, base.__module__ - module = sys.modules.get(modname) - if modname != name and module and hasattr(module, key): - if getattr(module, key) is base: - if not cdict.has_key(key): - cdict[key] = cdict[base] = modname + '.html#' + key - funcs, fdict = [], {} - for key, value in inspect.getmembers(object, inspect.isroutine): - if inspect.isbuiltin(value) or inspect.getmodule(value) is object: - funcs.append((key, value)) - fdict[key] = '#-' + key - if inspect.isfunction(value): fdict[value] = fdict[key] - data = [] - for key, value in inspect.getmembers(object, pydoc.isdata): - if key not in ['__builtins__', '__doc__']: - data.append((key, value)) - - doc = self.markup(pydoc.getdoc(object), self.preformat, fdict, cdict) - doc = doc and '%s' % doc - result = result + '

%s

\n' % doc - - packageContext.clean ( classes, object ) - packageContext.clean ( funcs, object ) - packageContext.clean ( data, object ) - - if hasattr(object, '__path__'): - modpkgs = [] - modnames = [] - for file in os.listdir(object.__path__[0]): - path = os.path.join(object.__path__[0], file) - modname = inspect.getmodulename(file) - if modname and modname not in modnames: - modpkgs.append((modname, name, 0, 0)) - modnames.append(modname) - elif pydoc.ispackage(path): - modpkgs.append((file, name, 1, 0)) - modpkgs.sort() - contents = self.multicolumn(modpkgs, self.modpkglink) -## result = result + self.bigsection( -## 'Package Contents', '#ffffff', '#aa55cc', contents) - result = result + self.moduleSection( object, packageContext) - elif modules: - contents = self.multicolumn( - modules, lambda (key, value), s=self: s.modulelink(value)) - result = result + self.bigsection( - 'Modules', '#fffff', '#aa55cc', contents) - - - if classes: - classlist = map(lambda (key, value): value, classes) - contents = [ - self.formattree(inspect.getclasstree(classlist, 1), name)] - for key, value in classes: - contents.append(self.document(value, key, name, fdict, cdict)) - result = result + self.bigsection( - 'Classes', '#ffffff', '#ee77aa', join(contents)) - if funcs: - contents = [] - for key, value in funcs: - contents.append(self.document(value, key, name, fdict, cdict)) - result = result + self.bigsection( - 'Functions', '#ffffff', '#eeaa77', join(contents)) - if data: - contents = [] - for key, value in data: - contents.append(self.document(value, key)) - result = result + self.bigsection( - 'Data', '#ffffff', '#55aa55', join(contents, '
\n')) - if hasattr(object, '__author__'): - contents = self.markup(str(object.__author__), self.preformat) - result = result + self.bigsection( - 'Author', '#ffffff', '#7799ee', contents) - if hasattr(object, '__credits__'): - contents = self.markup(str(object.__credits__), self.preformat) - result = result + self.bigsection( - 'Credits', '#ffffff', '#7799ee', contents) - - return result - - def classlink(self, object, modname): - """Make a link for a class.""" - name, module = object.__name__, sys.modules.get(object.__module__) - if hasattr(module, name) and getattr(module, name) is object: - return '%s' % ( - module.__name__, name, name - ) - return pydoc.classname(object, modname) - - def moduleSection( self, object, packageContext ): - """Create a module-links section for the given object (module)""" - modules = inspect.getmembers(object, inspect.ismodule) - packageContext.clean ( modules, object ) - packageContext.recurseScan( modules ) - - if hasattr(object, '__path__'): - modpkgs = [] - modnames = [] - for file in os.listdir(object.__path__[0]): - path = os.path.join(object.__path__[0], file) - modname = inspect.getmodulename(file) - if modname and modname not in modnames: - modpkgs.append((modname, object.__name__, 0, 0)) - modnames.append(modname) - elif pydoc.ispackage(path): - modpkgs.append((file, object.__name__, 1, 0)) - modpkgs.sort() - # do more recursion here... - for (modname, name, ya,yo) in modpkgs: - packageContext.addInteresting( join( (object.__name__, modname), '.')) - items = [] - for (modname, name, ispackage,isshadowed) in modpkgs: - try: - # get the actual module object... -## if modname == "events": -## import pdb -## pdb.set_trace() - module = pydoc.safeimport( "%s.%s"%(name,modname) ) - description, documentation = pydoc.splitdoc( inspect.getdoc( module )) - if description: - items.append( - """%s -- %s"""% ( - self.modpkglink( (modname, name, ispackage, isshadowed) ), - description, - ) - ) - else: - items.append( - self.modpkglink( (modname, name, ispackage, isshadowed) ) - ) - except: - items.append( - self.modpkglink( (modname, name, ispackage, isshadowed) ) - ) - contents = string.join( items, '
') - result = self.bigsection( - 'Package Contents', '#ffffff', '#aa55cc', contents) - elif modules: - contents = self.multicolumn( - modules, lambda (key, value), s=self: s.modulelink(value)) - result = self.bigsection( - 'Modules', '#fffff', '#aa55cc', contents) - else: - result = "" - return result - - -class AlreadyDone(Exception): - pass - - - -class PackageDocumentationGenerator: - """A package document generator creates documentation - for an entire package using pydoc's machinery. - - baseModules -- modules which will be included - and whose included and children modules will be - considered fair game for documentation - destinationDirectory -- the directory into which - the HTML documentation will be written - recursion -- whether to add modules which are - referenced by and/or children of base modules - exclusions -- a list of modules whose contents will - not be shown in any other module, commonly - such modules as OpenGL.GL, wxPython.wx etc. - recursionStops -- a list of modules which will - explicitly stop recursion (i.e. they will never - be included), even if they are children of base - modules. - formatter -- allows for passing in a custom formatter - see DefaultFormatter for sample implementation. - """ - def __init__ ( - self, baseModules, destinationDirectory = ".", - recursion = 1, exclusions = (), - recursionStops = (), - formatter = None - ): - self.destinationDirectory = os.path.abspath( destinationDirectory) - self.exclusions = {} - self.warnings = [] - self.baseSpecifiers = {} - self.completed = {} - self.recursionStops = {} - self.recursion = recursion - for stop in recursionStops: - self.recursionStops[ stop ] = 1 - self.pending = [] - for exclusion in exclusions: - try: - self.exclusions[ exclusion ]= pydoc.locate ( exclusion) - except pydoc.ErrorDuringImport, value: - self.warn( """Unable to import the module %s which was specified as an exclusion module"""% (repr(exclusion))) - self.formatter = formatter or DefaultFormatter() - for base in baseModules: - self.addBase( base ) - def warn( self, message ): - """Warnings are used for recoverable, but not necessarily ignorable conditions""" - self.warnings.append (message) - def info (self, message): - """Information/status report""" - print message - def addBase(self, specifier): - """Set the base of the documentation set, only children of these modules will be documented""" - try: - self.baseSpecifiers [specifier] = pydoc.locate ( specifier) - self.pending.append (specifier) - except pydoc.ErrorDuringImport, value: - self.warn( """Unable to import the module %s which was specified as a base module"""% (repr(specifier))) - def addInteresting( self, specifier): - """Add a module to the list of interesting modules""" - if self.checkScope( specifier): -## print "addInteresting", specifier - self.pending.append (specifier) - else: - self.completed[ specifier] = 1 - def checkScope (self, specifier): - """Check that the specifier is "in scope" for the recursion""" - if not self.recursion: - return 0 - items = string.split (specifier, ".") - stopCheck = items [:] - while stopCheck: - name = string.join(items, ".") - if self.recursionStops.get( name): - return 0 - elif self.completed.get (name): - return 0 - del stopCheck[-1] - while items: - if self.baseSpecifiers.get( string.join(items, ".")): - return 1 - del items[-1] - # was not within any given scope - return 0 - - def process( self ): - """Having added all of the base and/or interesting modules, - proceed to generate the appropriate documentation for each - module in the appropriate directory, doing the recursion - as we go.""" - try: - while self.pending: - try: - if self.completed.has_key( self.pending[0] ): - raise AlreadyDone( self.pending[0] ) - self.info( """Start %s"""% (repr(self.pending[0]))) - object = pydoc.locate ( self.pending[0] ) - self.info( """ ... found %s"""% (repr(object.__name__))) - except AlreadyDone: - pass - except pydoc.ErrorDuringImport, value: - self.info( """ ... FAILED %s"""% (repr( value))) - self.warn( """Unable to import the module %s"""% (repr(self.pending[0]))) - except (SystemError, SystemExit), value: - self.info( """ ... FAILED %s"""% (repr( value))) - self.warn( """Unable to import the module %s"""% (repr(self.pending[0]))) - except Exception, value: - self.info( """ ... FAILED %s"""% (repr( value))) - self.warn( """Unable to import the module %s"""% (repr(self.pending[0]))) - else: - page = self.formatter.page( - pydoc.describe(object), - self.formatter.docmodule( - object, - object.__name__, - packageContext = self, - ) - ) - file = open ( - os.path.join( - self.destinationDirectory, - self.pending[0] + ".html", - ), - 'w', - ) - file.write(page) - file.close() - self.completed[ self.pending[0]] = object - del self.pending[0] - finally: - for item in self.warnings: - print item - - def clean (self, objectList, object): - """callback from the formatter object asking us to remove - those items in the key, value pairs where the object is - imported from one of the excluded modules""" - for key, value in objectList[:]: - for excludeObject in self.exclusions.values(): - if hasattr( excludeObject, key ) and excludeObject is not object: - if ( - getattr( excludeObject, key) is value or - (hasattr( excludeObject, '__name__') and - excludeObject.__name__ == "Numeric" - ) - ): - objectList[:] = [ (k,o) for k,o in objectList if k != key ] - def recurseScan(self, objectList): - """Process the list of modules trying to add each to the - list of interesting modules""" - for key, value in objectList: - self.addInteresting( value.__name__ ) - - - -if __name__ == "__main__": - excludes = [ - "OpenGL.GL", - "OpenGL.GLU", - "OpenGL.GLUT", - "OpenGL.GLE", - "OpenGL.GLX", - "wxPython.wx", - "Numeric", - "_tkinter", - "Tkinter", - ] - - modules = [ - "OpenGLContext.debug", -## "wxPython.glcanvas", -## "OpenGL.Tk", -## "OpenGL", - ] - PackageDocumentationGenerator( - baseModules = modules, - destinationDirectory = "z:\\temp", - exclusions = excludes, - ).process () - \ No newline at end of file diff --git a/software/openvisualizer/PyDispatcher-2.0.3/docs/pydoc/weakref.html b/software/openvisualizer/PyDispatcher-2.0.3/docs/pydoc/weakref.html deleted file mode 100644 index 50171ccdc..000000000 --- a/software/openvisualizer/PyDispatcher-2.0.3/docs/pydoc/weakref.html +++ /dev/null @@ -1,305 +0,0 @@ - - -Python: module weakref - - - - -
 
- 
weakref
index
/usr/lib/python2.7/weakref.py
-

Weak reference support for Python.

-This module is an implementation of PEP 205:

-http://www.python.org/dev/peps/pep-0205/

-

- - - - - -
 
-Modules
       
UserDict
-

- - - - - -
 
-Classes
       
-
UserDict -
-
-
WeakKeyDictionary -
WeakValueDictionary -
-
-
__builtin__.weakref(object) -
-
-
KeyedRef -
-
-
-

- - - - - - - -
 
-class KeyedRef(__builtin__.weakref)
   Specialized reference that includes a key corresponding to the value.

-This is used in the WeakValueDictionary to avoid having to create
-a function object for each key stored in the mapping.  A shared
-callback object can use the 'key' attribute of a KeyedRef instead
-of getting a reference to the key from an enclosing scope.
 
 
Method resolution order:
-
KeyedRef
-
__builtin__.weakref
-
object
-
-
-Methods defined here:
-
__init__(self, ob, callback, key)
- -
-Static methods defined here:
-
__new__(type, ob, callback, key)
- -
-Data descriptors defined here:
-
key
-
-
-Methods inherited from __builtin__.weakref:
-
__call__(...)
x.__call__(...) <==> x(...)
- -
__eq__(...)
x.__eq__(y) <==> x==y
- -
__ge__(...)
x.__ge__(y) <==> x>=y
- -
__gt__(...)
x.__gt__(y) <==> x>y
- -
__hash__(...)
x.__hash__() <==> hash(x)
- -
__le__(...)
x.__le__(y) <==> x<=y
- -
__lt__(...)
x.__lt__(y) <==> x<y
- -
__ne__(...)
x.__ne__(y) <==> x!=y
- -
__repr__(...)
x.__repr__() <==> repr(x)
- -

- - - - - - - -
 
-class WeakKeyDictionary(UserDict)
   Mapping class that references keys weakly.

-Entries in the dictionary will be discarded when there is no
-longer a strong reference to the key. This can be used to
-associate additional data with an object owned by other parts of
-an application without adding attributes to those objects. This
-can be especially useful with objects that override attribute
-accesses.
 
 Methods defined here:
-
__contains__(self, key)
- -
__copy__ = copy(self)
- -
__deepcopy__(self, memo)
- -
__delitem__(self, key)
- -
__getitem__(self, key)
- -
__init__(self, dict=None)
- -
__iter__(self)
- -
__repr__(self)
- -
__setitem__(self, key, value)
- -
copy(self)
- -
get(self, key, default=None)
- -
has_key(self, key)
- -
items(self)
- -
iteritems(self)
- -
iterkeyrefs(self)
Return an iterator that yields the weak references to the keys.

-The references are not guaranteed to be 'live' at the time
-they are used, so the result of calling the references needs
-to be checked before being used.  This can be used to avoid
-creating references that will cause the garbage collector to
-keep the keys around longer than needed.
- -
iterkeys(self)
- -
itervalues(self)
- -
keyrefs(self)
Return a list of weak references to the keys.

-The references are not guaranteed to be 'live' at the time
-they are used, so the result of calling the references needs
-to be checked before being used.  This can be used to avoid
-creating references that will cause the garbage collector to
-keep the keys around longer than needed.
- -
keys(self)
- -
pop(self, key, *args)
- -
popitem(self)
- -
setdefault(self, key, default=None)
- -
update(self, dict=None, **kwargs)
- -
-Methods inherited from UserDict:
-
__cmp__(self, dict)
- -
__len__(self)
- -
clear(self)
- -
values(self)
- -
-Class methods inherited from UserDict:
-
fromkeys(cls, iterable, value=None) from __builtin__.classobj
- -
-Data and other attributes inherited from UserDict:
-
__hash__ = None
- -

- - - - - - - -
 
-class WeakValueDictionary(UserDict)
   Mapping class that references values weakly.

-Entries in the dictionary will be discarded when no strong
-reference to the value exists anymore
 
 Methods defined here:
-
__contains__(self, key)
- -
__copy__ = copy(self)
- -
__deepcopy__(self, memo)
- -
__getitem__(self, key)
- -
__init__(self, *args, **kw)
- -
__iter__(self)
- -
__repr__(self)
- -
__setitem__(self, key, value)
- -
copy(self)
- -
get(self, key, default=None)
- -
has_key(self, key)
- -
items(self)
- -
iteritems(self)
- -
iterkeys(self)
- -
itervaluerefs(self)
Return an iterator that yields the weak references to the values.

-The references are not guaranteed to be 'live' at the time
-they are used, so the result of calling the references needs
-to be checked before being used.  This can be used to avoid
-creating references that will cause the garbage collector to
-keep the values around longer than needed.
- -
itervalues(self)
- -
pop(self, key, *args)
- -
popitem(self)
- -
setdefault(self, key, default=None)
- -
update(self, dict=None, **kwargs)
- -
valuerefs(self)
Return a list of weak references to the values.

-The references are not guaranteed to be 'live' at the time
-they are used, so the result of calling the references needs
-to be checked before being used.  This can be used to avoid
-creating references that will cause the garbage collector to
-keep the values around longer than needed.
- -
values(self)
- -
-Methods inherited from UserDict:
-
__cmp__(self, dict)
- -
__delitem__(self, key)
- -
__len__(self)
- -
clear(self)
- -
keys(self)
- -
-Class methods inherited from UserDict:
-
fromkeys(cls, iterable, value=None) from __builtin__.classobj
- -
-Data and other attributes inherited from UserDict:
-
__hash__ = None
- -

- - - - - -
 
-Functions
       
getweakrefcount(...)
getweakrefcount(object) -- return the number of weak references
-to 'object'.
-
getweakrefs(...)
getweakrefs(object) -- return a list of all weak reference objects
-that point to 'object'.
-
proxy(...)
proxy(object[, callback]) -- create a proxy object that weakly
-references 'object'.  'callback', if given, is called with a
-reference to the proxy when 'object' is about to be finalized.
-

- - - - - -
 
-Data
       ProxyTypes = (<type 'weakproxy'>, <type 'weakcallableproxy'>)
-__all__ = ['ref', 'proxy', 'getweakrefcount', 'getweakrefs', 'WeakKeyDictionary', 'ReferenceError', 'ReferenceType', 'ProxyType', 'CallableProxyType', 'ProxyTypes', 'WeakValueDictionary', 'WeakSet']
-__file__ = '/usr/lib/python2.7/weakref.pyc'
-__name__ = 'weakref'
- \ No newline at end of file diff --git a/software/openvisualizer/PyDispatcher-2.0.3/docs/style/sitestyle.css b/software/openvisualizer/PyDispatcher-2.0.3/docs/style/sitestyle.css deleted file mode 100644 index 051defdb5..000000000 --- a/software/openvisualizer/PyDispatcher-2.0.3/docs/style/sitestyle.css +++ /dev/null @@ -1,59 +0,0 @@ -h1,h2,h3 { - color: #111144; - background-image: url(../images/greypinstripe.png); - border-top-style: solid; - border-top-width: 1 -} -.footer { - color: #111144; - background-image: url(../images/greypinstripe.png); - text-align: center; - border-bottom-style: solid; - border-bottom-width: 1 -} -th { - color: #111144; - background-image: url(../images/greypinstripe.png); - text-align: center; -} -.introduction { - margin-left: 60; - margin-right: 60; - color: #555555; -} -.technical { - margin-left: 60; - margin-right: 60; - color: #557755; -} -p { - margin-left: 10; - margin-right: 10; -} -ul { - margin-left: 30; -} -pre { - background-color: #ffffcc; - margin-left: 60; -} -blockquote { - margin-left: 90; -} -body { - background-color: #FFFFFF; - color: #000000; - font-family: Arial, Helvetica; -} -a:link { - color: #3333e0; - text-decoration: none; -} -a:visited { - color: #1111aa; - text-decoration: none; -} -a:active { - color: #111133; - text-decoration: none; -} diff --git a/software/openvisualizer/PyDispatcher-2.0.3/examples/__init__.py b/software/openvisualizer/PyDispatcher-2.0.3/examples/__init__.py deleted file mode 100644 index 393933cb8..000000000 --- a/software/openvisualizer/PyDispatcher-2.0.3/examples/__init__.py +++ /dev/null @@ -1,3 +0,0 @@ -"""Example scripts for the dispatch project -""" - diff --git a/software/openvisualizer/PyDispatcher-2.0.3/examples/extra_args.py b/software/openvisualizer/PyDispatcher-2.0.3/examples/extra_args.py deleted file mode 100644 index 19ff6d427..000000000 --- a/software/openvisualizer/PyDispatcher-2.0.3/examples/extra_args.py +++ /dev/null @@ -1,23 +0,0 @@ -#! /usr/bin/env python -from pydispatch import dispatcher -SIGNAL = 'my-first-signal' -SIGNAL2 = 'my-second-signal' - -def handle_event( sender ): - """Simple event handler""" - print 'Signal was sent by', sender -dispatcher.connect( handle_event, signal=SIGNAL, sender=dispatcher.Any ) -def handle_specific_event( sender, moo ): - """Handle a simple event, requiring a "moo" parameter""" - print 'Specialized event for %(sender)s moo=%(moo)r'%locals() -dispatcher.connect( handle_specific_event, signal=SIGNAL2, sender=dispatcher.Any ) - -first_sender = object() -second_sender = {} -def main( ): - dispatcher.send( signal=SIGNAL, sender=first_sender ) - dispatcher.send( signal=SIGNAL, sender=second_sender ) - dispatcher.send( signal=SIGNAL2, sender=second_sender, moo='this' ) - -if __name__ == "__main__": - main() diff --git a/software/openvisualizer/PyDispatcher-2.0.3/examples/hello_messages.py b/software/openvisualizer/PyDispatcher-2.0.3/examples/hello_messages.py deleted file mode 100644 index 92f7540ea..000000000 --- a/software/openvisualizer/PyDispatcher-2.0.3/examples/hello_messages.py +++ /dev/null @@ -1,17 +0,0 @@ -#! /usr/bin/env python -from pydispatch import dispatcher -SIGNAL = 'my-first-signal' - -def handle_event( sender ): - """Simple event handler""" - print 'Signal was sent by', sender -dispatcher.connect( handle_event, signal=SIGNAL, sender=dispatcher.Any ) - -first_sender = object() -second_sender = {} -def main( ): - dispatcher.send( signal=SIGNAL, sender=first_sender ) - dispatcher.send( signal=SIGNAL, sender=second_sender ) - -if __name__ == "__main__": - main() diff --git a/software/openvisualizer/PyDispatcher-2.0.3/examples/simple_sample.py b/software/openvisualizer/PyDispatcher-2.0.3/examples/simple_sample.py deleted file mode 100644 index 7de3f40fb..000000000 --- a/software/openvisualizer/PyDispatcher-2.0.3/examples/simple_sample.py +++ /dev/null @@ -1,77 +0,0 @@ -"""Simple sample showing basic usage pattern""" -from pydispatch import dispatcher - -def doSomethingUseful( table, signal, sender ): - """Sample method to receive signals""" - print ' doSomethingUseful', repr(table), signal, sender -def doSomethingElse( signal, **named ): - """Sample method to receive signals - - This method demonstrates the use of the **named - parameter, which allows a method to receive all - remaining parameters from the send call. - """ - print ' doSomethingElse', named -def doDefault( ): - """Sample method to receive All signals - - Note that this function will be registered for all - signals from a given object. It does not have the - same interface as any of the other functions - registered for those signals. The system will - automatically determine the appropriate calling - signature for the function. - """ - print ' doDefault (no arguments)' - -class Node(object): - """Sample object to send signals, note lack of dispatcher-aware code""" - def __init__( self, name="an object" ): - self.name = name - def __repr__( self ): - return "%s( %r )"%( self.__class__.__name__, self.name ) - -DO_LOTS = 0 -DO_SOMETHING = ('THIS','IS','A','MORE','COMPLEX','SIGNAL') -DO_SOMETHING_ELSE = Node() - -ourObjects = [ - Node(), - Node(), - Node(), -] -if __name__ == "__main__": - # Establish some "routing" connections - dispatcher.connect ( - doSomethingUseful, - signal = DO_LOTS, - sender = ourObjects[0], - ) - dispatcher.connect ( - doSomethingElse, - signal = DO_SOMETHING, - sender = ourObjects[0], - ) - dispatcher.connect( - doDefault, - signal = dispatcher.Any, # this is actually the default, - sender = ourObjects[0], - ) - print "Sending DO_LOTS from first object" - dispatcher.send( - signal = DO_LOTS, - sender = ourObjects[0], - table = "Table Argument", - ) - print "Sending DO_SOMETHING from first object" - dispatcher.send( - signal = DO_SOMETHING, - sender = ourObjects[0], - table = "Table Argument", - ) - print "Sending DO_SOMETHING_ELSE from first object" - dispatcher.send( - signal = DO_SOMETHING_ELSE, - sender = ourObjects[0], - table = "Table Argument", - ) diff --git a/software/openvisualizer/PyDispatcher-2.0.3/license.txt b/software/openvisualizer/PyDispatcher-2.0.3/license.txt deleted file mode 100644 index 0960a6073..000000000 --- a/software/openvisualizer/PyDispatcher-2.0.3/license.txt +++ /dev/null @@ -1,34 +0,0 @@ -PyDispatcher License - - Copyright (c) 2001-2006, Patrick K. O'Brien and Contributors - All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions - are met: - - Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - - Redistributions in binary form must reproduce the above - copyright notice, this list of conditions and the following - disclaimer in the documentation and/or other materials - provided with the distribution. - - The name of Patrick K. O'Brien, or the name of any Contributor, - may not be used to endorse or promote products derived from this - software without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED - OF THE POSSIBILITY OF SUCH DAMAGE. - diff --git a/software/openvisualizer/PyDispatcher-2.0.3/pydispatch/__init__.py b/software/openvisualizer/PyDispatcher-2.0.3/pydispatch/__init__.py deleted file mode 100644 index b13f5f695..000000000 --- a/software/openvisualizer/PyDispatcher-2.0.3/pydispatch/__init__.py +++ /dev/null @@ -1,6 +0,0 @@ -"""Multi-consumer multi-producer dispatching mechanism -""" -__version__ = "2.0.3" -__author__ = "Patrick K. O'Brien" -__license__ = "BSD-style, see license.txt for details" - diff --git a/software/openvisualizer/PyDispatcher-2.0.3/pydispatch/dispatcher.py b/software/openvisualizer/PyDispatcher-2.0.3/pydispatch/dispatcher.py deleted file mode 100644 index e0e48473f..000000000 --- a/software/openvisualizer/PyDispatcher-2.0.3/pydispatch/dispatcher.py +++ /dev/null @@ -1,492 +0,0 @@ -"""Multiple-producer-multiple-consumer signal-dispatching - -dispatcher is the core of the PyDispatcher system, -providing the primary API and the core logic for the -system. - -Module attributes of note: - - Any -- Singleton used to signal either "Any Sender" or - "Any Signal". See documentation of the _Any class. - Anonymous -- Singleton used to signal "Anonymous Sender" - See documentation of the _Anonymous class. - -Internal attributes: - WEAKREF_TYPES -- tuple of types/classes which represent - weak references to receivers, and thus must be de- - referenced on retrieval to retrieve the callable - object - connections -- { senderkey (id) : { signal : [receivers...]}} - senders -- { senderkey (id) : weakref(sender) } - used for cleaning up sender references on sender - deletion - sendersBack -- { receiverkey (id) : [senderkey (id)...] } - used for cleaning up receiver references on receiver - deletion, (considerably speeds up the cleanup process - vs. the original code.) -""" -from __future__ import generators -import weakref -from pydispatch import saferef, robustapply, errors - -__author__ = "Patrick K. O'Brien " -__cvsid__ = "$Id: dispatcher.py,v 1.1 2010/03/30 15:45:55 mcfletch Exp $" -__version__ = "$Revision: 1.1 $"[11:-2] - -class _Parameter: - """Used to represent default parameter values.""" - def __repr__(self): - return self.__class__.__name__ - -class _Any(_Parameter): - """Singleton used to signal either "Any Sender" or "Any Signal" - - The Any object can be used with connect, disconnect, - send, or sendExact to signal that the parameter given - Any should react to all senders/signals, not just - a particular sender/signal. - """ -Any = _Any() - -class _Anonymous(_Parameter): - """Singleton used to signal "Anonymous Sender" - - The Anonymous object is used to signal that the sender - of a message is not specified (as distinct from being - "any sender"). Registering callbacks for Anonymous - will only receive messages sent without senders. Sending - with anonymous will only send messages to those receivers - registered for Any or Anonymous. - - Note: - The default sender for connect is Any, while the - default sender for send is Anonymous. This has - the effect that if you do not specify any senders - in either function then all messages are routed - as though there was a single sender (Anonymous) - being used everywhere. - """ -Anonymous = _Anonymous() - -WEAKREF_TYPES = (weakref.ReferenceType, saferef.BoundMethodWeakref) - -connections = {} -senders = {} -sendersBack = {} - - -def connect(receiver, signal=Any, sender=Any, weak=True): - """Connect receiver to sender for signal - - receiver -- a callable Python object which is to receive - messages/signals/events. Receivers must be hashable - objects. - - if weak is True, then receiver must be weak-referencable - (more precisely saferef.safeRef() must be able to create - a reference to the receiver). - - Receivers are fairly flexible in their specification, - as the machinery in the robustApply module takes care - of most of the details regarding figuring out appropriate - subsets of the sent arguments to apply to a given - receiver. - - Note: - if receiver is itself a weak reference (a callable), - it will be de-referenced by the system's machinery, - so *generally* weak references are not suitable as - receivers, though some use might be found for the - facility whereby a higher-level library passes in - pre-weakrefed receiver references. - - signal -- the signal to which the receiver should respond - - if Any, receiver will receive any signal from the - indicated sender (which might also be Any, but is not - necessarily Any). - - Otherwise must be a hashable Python object other than - None (DispatcherError raised on None). - - sender -- the sender to which the receiver should respond - - if Any, receiver will receive the indicated signals - from any sender. - - if Anonymous, receiver will only receive indicated - signals from send/sendExact which do not specify a - sender, or specify Anonymous explicitly as the sender. - - Otherwise can be any python object. - - weak -- whether to use weak references to the receiver - By default, the module will attempt to use weak - references to the receiver objects. If this parameter - is false, then strong references will be used. - - returns None, may raise DispatcherTypeError - """ - if signal is None: - raise errors.DispatcherTypeError( - 'Signal cannot be None (receiver=%r sender=%r)'%( receiver,sender) - ) - if weak: - receiver = saferef.safeRef(receiver, onDelete=_removeReceiver) - senderkey = id(sender) - if senderkey in connections: - signals = connections[senderkey] - else: - connections[senderkey] = signals = {} - # Keep track of senders for cleanup. - # Is Anonymous something we want to clean up? - if sender not in (None, Anonymous, Any): - def remove(object, senderkey=senderkey): - _removeSender(senderkey=senderkey) - # Skip objects that can not be weakly referenced, which means - # they won't be automatically cleaned up, but that's too bad. - try: - weakSender = weakref.ref(sender, remove) - senders[senderkey] = weakSender - except: - pass - - receiverID = id(receiver) - # get current set, remove any current references to - # this receiver in the set, including back-references - if signal in signals: - receivers = signals[signal] - _removeOldBackRefs(senderkey, signal, receiver, receivers) - else: - receivers = signals[signal] = [] - try: - current = sendersBack.get( receiverID ) - if current is None: - sendersBack[ receiverID ] = current = [] - if senderkey not in current: - current.append(senderkey) - except: - pass - - receivers.append(receiver) - - - -def disconnect(receiver, signal=Any, sender=Any, weak=True): - """Disconnect receiver from sender for signal - - receiver -- the registered receiver to disconnect - signal -- the registered signal to disconnect - sender -- the registered sender to disconnect - weak -- the weakref state to disconnect - - disconnect reverses the process of connect, - the semantics for the individual elements are - logically equivalent to a tuple of - (receiver, signal, sender, weak) used as a key - to be deleted from the internal routing tables. - (The actual process is slightly more complex - but the semantics are basically the same). - - Note: - Using disconnect is not required to cleanup - routing when an object is deleted, the framework - will remove routes for deleted objects - automatically. It's only necessary to disconnect - if you want to stop routing to a live object. - - returns None, may raise DispatcherTypeError or - DispatcherKeyError - """ - if signal is None: - raise errors.DispatcherTypeError( - 'Signal cannot be None (receiver=%r sender=%r)'%( receiver,sender) - ) - if weak: receiver = saferef.safeRef(receiver) - senderkey = id(sender) - try: - signals = connections[senderkey] - receivers = signals[signal] - except KeyError: - raise errors.DispatcherKeyError( - """No receivers found for signal %r from sender %r""" %( - signal, - sender - ) - ) - try: - # also removes from receivers - _removeOldBackRefs(senderkey, signal, receiver, receivers) - except ValueError: - raise errors.DispatcherKeyError( - """No connection to receiver %s for signal %s from sender %s""" %( - receiver, - signal, - sender - ) - ) - _cleanupConnections(senderkey, signal) - -def getReceivers( sender = Any, signal = Any ): - """Get list of receivers from global tables - - This utility function allows you to retrieve the - raw list of receivers from the connections table - for the given sender and signal pair. - - Note: - there is no guarantee that this is the actual list - stored in the connections table, so the value - should be treated as a simple iterable/truth value - rather than, for instance a list to which you - might append new records. - - Normally you would use liveReceivers( getReceivers( ...)) - to retrieve the actual receiver objects as an iterable - object. - """ - try: - return connections[id(sender)][signal] - except KeyError: - return [] - -def liveReceivers(receivers): - """Filter sequence of receivers to get resolved, live receivers - - This is a generator which will iterate over - the passed sequence, checking for weak references - and resolving them, then returning all live - receivers. - """ - for receiver in receivers: - if isinstance( receiver, WEAKREF_TYPES): - # Dereference the weak reference. - receiver = receiver() - if receiver is not None: - yield receiver - else: - yield receiver - - - -def getAllReceivers( sender = Any, signal = Any ): - """Get list of all receivers from global tables - - This gets all receivers which should receive - the given signal from sender, each receiver should - be produced only once by the resulting generator - """ - receivers = {} - for set in ( - # Get receivers that receive *this* signal from *this* sender. - getReceivers( sender, signal ), - # Add receivers that receive *any* signal from *this* sender. - getReceivers( sender, Any ), - # Add receivers that receive *this* signal from *any* sender. - getReceivers( Any, signal ), - # Add receivers that receive *any* signal from *any* sender. - getReceivers( Any, Any ), - ): - for receiver in set: - if receiver: # filter out dead instance-method weakrefs - try: - if receiver not in receivers: - receivers[receiver] = 1 - yield receiver - except TypeError: - # dead weakrefs raise TypeError on hash... - pass - -def send(signal=Any, sender=Anonymous, *arguments, **named): - """Send signal from sender to all connected receivers. - - signal -- (hashable) signal value, see connect for details - - sender -- the sender of the signal - - if Any, only receivers registered for Any will receive - the message. - - if Anonymous, only receivers registered to receive - messages from Anonymous or Any will receive the message - - Otherwise can be any python object (normally one - registered with a connect if you actually want - something to occur). - - arguments -- positional arguments which will be passed to - *all* receivers. Note that this may raise TypeErrors - if the receivers do not allow the particular arguments. - Note also that arguments are applied before named - arguments, so they should be used with care. - - named -- named arguments which will be filtered according - to the parameters of the receivers to only provide those - acceptable to the receiver. - - Return a list of tuple pairs [(receiver, response), ... ] - - if any receiver raises an error, the error propagates back - through send, terminating the dispatch loop, so it is quite - possible to not have all receivers called if a raises an - error. - """ - # Call each receiver with whatever arguments it can accept. - # Return a list of tuple pairs [(receiver, response), ... ]. - responses = [] - for receiver in liveReceivers(getAllReceivers(sender, signal)): - response = robustapply.robustApply( - receiver, - signal=signal, - sender=sender, - *arguments, - **named - ) - responses.append((receiver, response)) - return responses -def sendExact( signal=Any, sender=Anonymous, *arguments, **named ): - """Send signal only to those receivers registered for exact message - - sendExact allows for avoiding Any/Anonymous registered - handlers, sending only to those receivers explicitly - registered for a particular signal on a particular - sender. - """ - responses = [] - for receiver in liveReceivers(getReceivers(sender, signal)): - response = robustapply.robustApply( - receiver, - signal=signal, - sender=sender, - *arguments, - **named - ) - responses.append((receiver, response)) - return responses - - -def _removeReceiver(receiver): - """Remove receiver from connections.""" - if not sendersBack: - # During module cleanup the mapping will be replaced with None - return False - backKey = id(receiver) - try: - backSet = sendersBack.pop(backKey) - except KeyError: - return False - else: - for senderkey in backSet: - try: - signals = connections[senderkey].keys() - except KeyError: - pass - else: - for signal in signals: - try: - receivers = connections[senderkey][signal] - except KeyError: - pass - else: - try: - receivers.remove( receiver ) - except Exception: - pass - _cleanupConnections(senderkey, signal) - -def _cleanupConnections(senderkey, signal): - """Delete any empty signals for senderkey. Delete senderkey if empty.""" - try: - receivers = connections[senderkey][signal] - except: - pass - else: - if not receivers: - # No more connected receivers. Therefore, remove the signal. - try: - signals = connections[senderkey] - except KeyError: - pass - else: - del signals[signal] - if not signals: - # No more signal connections. Therefore, remove the sender. - _removeSender(senderkey) - -def _removeSender(senderkey): - """Remove senderkey from connections.""" - _removeBackrefs(senderkey) - try: - del connections[senderkey] - except KeyError: - pass - # Senderkey will only be in senders dictionary if sender - # could be weakly referenced. - try: - del senders[senderkey] - except: - pass - - -def _removeBackrefs( senderkey): - """Remove all back-references to this senderkey""" - try: - signals = connections[senderkey] - except KeyError: - signals = None - else: - items = signals.items() - def allReceivers( ): - for signal,set in items: - for item in set: - yield item - for receiver in allReceivers(): - _killBackref( receiver, senderkey ) - -def _removeOldBackRefs(senderkey, signal, receiver, receivers): - """Kill old sendersBack references from receiver - - This guards against multiple registration of the same - receiver for a given signal and sender leaking memory - as old back reference records build up. - - Also removes old receiver instance from receivers - """ - try: - index = receivers.index(receiver) - # need to scan back references here and remove senderkey - except ValueError: - return False - else: - oldReceiver = receivers[index] - del receivers[index] - found = 0 - signals = connections.get(signal) - if signals is not None: - for sig,recs in connections.get(signal,{}).iteritems(): - if sig != signal: - for rec in recs: - if rec is oldReceiver: - found = 1 - break - if not found: - _killBackref( oldReceiver, senderkey ) - return True - return False - - -def _killBackref( receiver, senderkey ): - """Do the actual removal of back reference from receiver to senderkey""" - receiverkey = id(receiver) - set = sendersBack.get( receiverkey, () ) - while senderkey in set: - try: - set.remove( senderkey ) - except: - break - if not set: - try: - del sendersBack[ receiverkey ] - except KeyError: - pass - return True diff --git a/software/openvisualizer/PyDispatcher-2.0.3/pydispatch/errors.py b/software/openvisualizer/PyDispatcher-2.0.3/pydispatch/errors.py deleted file mode 100644 index a2eb32ed7..000000000 --- a/software/openvisualizer/PyDispatcher-2.0.3/pydispatch/errors.py +++ /dev/null @@ -1,10 +0,0 @@ -"""Error types for dispatcher mechanism -""" - -class DispatcherError(Exception): - """Base class for all Dispatcher errors""" -class DispatcherKeyError(KeyError, DispatcherError): - """Error raised when unknown (sender,signal) set specified""" -class DispatcherTypeError(TypeError, DispatcherError): - """Error raised when inappropriate signal-type specified (None)""" - diff --git a/software/openvisualizer/PyDispatcher-2.0.3/pydispatch/robust.py b/software/openvisualizer/PyDispatcher-2.0.3/pydispatch/robust.py deleted file mode 100644 index 929f550c6..000000000 --- a/software/openvisualizer/PyDispatcher-2.0.3/pydispatch/robust.py +++ /dev/null @@ -1,57 +0,0 @@ -"""Module implementing error-catching version of send (sendRobust)""" -from pydispatch.dispatcher import Any, Anonymous, liveReceivers, getAllReceivers -from pydispatch.robustapply import robustApply - -def sendRobust( - signal=Any, - sender=Anonymous, - *arguments, **named -): - """Send signal from sender to all connected receivers catching errors - - signal -- (hashable) signal value, see connect for details - - sender -- the sender of the signal - - if Any, only receivers registered for Any will receive - the message. - - if Anonymous, only receivers registered to receive - messages from Anonymous or Any will receive the message - - Otherwise can be any python object (normally one - registered with a connect if you actually want - something to occur). - - arguments -- positional arguments which will be passed to - *all* receivers. Note that this may raise TypeErrors - if the receivers do not allow the particular arguments. - Note also that arguments are applied before named - arguments, so they should be used with care. - - named -- named arguments which will be filtered according - to the parameters of the receivers to only provide those - acceptable to the receiver. - - Return a list of tuple pairs [(receiver, response), ... ] - - if any receiver raises an error (specifically any subclass of Exception), - the error instance is returned as the result for that receiver. - """ - # Call each receiver with whatever arguments it can accept. - # Return a list of tuple pairs [(receiver, response), ... ]. - responses = [] - for receiver in liveReceivers(getAllReceivers(sender, signal)): - try: - response = robustApply( - receiver, - signal=signal, - sender=sender, - *arguments, - **named - ) - except Exception, err: - responses.append((receiver, err)) - else: - responses.append((receiver, response)) - return responses diff --git a/software/openvisualizer/PyDispatcher-2.0.3/pydispatch/robustapply.py b/software/openvisualizer/PyDispatcher-2.0.3/pydispatch/robustapply.py deleted file mode 100644 index 452760807..000000000 --- a/software/openvisualizer/PyDispatcher-2.0.3/pydispatch/robustapply.py +++ /dev/null @@ -1,57 +0,0 @@ -"""Robust apply mechanism - -Provides a function "call", which can sort out -what arguments a given callable object can take, -and subset the given arguments to match only -those which are acceptable. -""" -import sys -if sys.hexversion >= 0x3000000: - im_func = '__func__' - im_self = '__self__' - im_code = '__code__' - func_code = '__code__' -else: - im_func = 'im_func' - im_self = 'im_self' - im_code = 'im_code' - func_code = 'func_code' - -def function( receiver ): - """Get function-like callable object for given receiver - - returns (function_or_method, codeObject, fromMethod) - - If fromMethod is true, then the callable already - has its first argument bound - """ - if hasattr(receiver, '__call__'): - # Reassign receiver to the actual method that will be called. - if hasattr( receiver.__call__, im_func) or hasattr( receiver.__call__, im_code): - receiver = receiver.__call__ - if hasattr( receiver, im_func ): - # an instance-method... - return receiver, getattr(getattr(receiver, im_func), func_code), 1 - elif not hasattr( receiver, func_code): - raise ValueError('unknown reciever type %s %s'%(receiver, type(receiver))) - return receiver, getattr(receiver,func_code), 0 - -def robustApply(receiver, *arguments, **named): - """Call receiver with arguments and an appropriate subset of named - """ - receiver, codeObject, startIndex = function( receiver ) - acceptable = codeObject.co_varnames[startIndex+len(arguments):codeObject.co_argcount] - for name in codeObject.co_varnames[startIndex:startIndex+len(arguments)]: - if name in named: - raise TypeError( - """Argument %r specified both positionally and as a keyword for calling %r"""% ( - name, receiver, - ) - ) - if not (codeObject.co_flags & 8): - # fc does not have a **kwds type parameter, therefore - # remove unacceptable arguments. - for arg in named.keys(): - if arg not in acceptable: - del named[arg] - return receiver(*arguments, **named) diff --git a/software/openvisualizer/PyDispatcher-2.0.3/pydispatch/saferef.py b/software/openvisualizer/PyDispatcher-2.0.3/pydispatch/saferef.py deleted file mode 100644 index f1929a593..000000000 --- a/software/openvisualizer/PyDispatcher-2.0.3/pydispatch/saferef.py +++ /dev/null @@ -1,171 +0,0 @@ -"""Refactored "safe reference" from dispatcher.py""" -import weakref, traceback, sys - -if sys.hexversion >= 0x3000000: - im_func = '__func__' - im_self = '__self__' -else: - im_func = 'im_func' - im_self = 'im_self' -def safeRef(target, onDelete = None): - """Return a *safe* weak reference to a callable target - - target -- the object to be weakly referenced, if it's a - bound method reference, will create a BoundMethodWeakref, - otherwise creates a simple weakref. - onDelete -- if provided, will have a hard reference stored - to the callable to be called after the safe reference - goes out of scope with the reference object, (either a - weakref or a BoundMethodWeakref) as argument. - """ - if hasattr(target, im_self): - if getattr(target, im_self) is not None: - # Turn a bound method into a BoundMethodWeakref instance. - # Keep track of these instances for lookup by disconnect(). - assert hasattr(target, im_func), """safeRef target %r has %s, but no %s, don't know how to create reference"""%( target,im_self,im_func) - reference = BoundMethodWeakref( - target=target, - onDelete=onDelete - ) - return reference - if onDelete is not None: - return weakref.ref(target, onDelete) - else: - return weakref.ref( target ) - -class BoundMethodWeakref(object): - """'Safe' and reusable weak references to instance methods - - BoundMethodWeakref objects provide a mechanism for - referencing a bound method without requiring that the - method object itself (which is normally a transient - object) is kept alive. Instead, the BoundMethodWeakref - object keeps weak references to both the object and the - function which together define the instance method. - - Attributes: - key -- the identity key for the reference, calculated - by the class's calculateKey method applied to the - target instance method - deletionMethods -- sequence of callable objects taking - single argument, a reference to this object which - will be called when *either* the target object or - target function is garbage collected (i.e. when - this object becomes invalid). These are specified - as the onDelete parameters of safeRef calls. - weakSelf -- weak reference to the target object - weakFunc -- weak reference to the target function - - Class Attributes: - _allInstances -- class attribute pointing to all live - BoundMethodWeakref objects indexed by the class's - calculateKey(target) method applied to the target - objects. This weak value dictionary is used to - short-circuit creation so that multiple references - to the same (object, function) pair produce the - same BoundMethodWeakref instance. - - """ - _allInstances = weakref.WeakValueDictionary() - def __new__( cls, target, onDelete=None, *arguments,**named ): - """Create new instance or return current instance - - Basically this method of construction allows us to - short-circuit creation of references to already- - referenced instance methods. The key corresponding - to the target is calculated, and if there is already - an existing reference, that is returned, with its - deletionMethods attribute updated. Otherwise the - new instance is created and registered in the table - of already-referenced methods. - """ - key = cls.calculateKey(target) - current =cls._allInstances.get(key) - if current is not None: - current.deletionMethods.append( onDelete) - return current - else: - base = super( BoundMethodWeakref, cls).__new__( cls ) - cls._allInstances[key] = base - base.__init__( target, onDelete, *arguments,**named) - return base - def __init__(self, target, onDelete=None): - """Return a weak-reference-like instance for a bound method - - target -- the instance-method target for the weak - reference, must have and attributes - and be reconstructable via: - target..__get__( target. ) - which is true of built-in instance methods. - onDelete -- optional callback which will be called - when this weak reference ceases to be valid - (i.e. either the object or the function is garbage - collected). Should take a single argument, - which will be passed a pointer to this object. - """ - def remove(weak, self=self): - """Set self.isDead to true when method or instance is destroyed""" - methods = self.deletionMethods[:] - del self.deletionMethods[:] - try: - del self.__class__._allInstances[ self.key ] - except KeyError: - pass - for function in methods: - try: - if hasattr(function, '__call__' ): - function( self ) - except Exception, e: - try: - traceback.print_exc() - except AttributeError: - print '''Exception during saferef %s cleanup function %s: %s'''%( - self, function, e - ) - self.deletionMethods = [onDelete] - self.key = self.calculateKey( target ) - self.weakSelf = weakref.ref(getattr(target,im_self), remove) - self.weakFunc = weakref.ref(getattr(target,im_func), remove) - self.selfName = getattr(target,im_self).__class__.__name__ - self.funcName = str(getattr(target,im_func).__name__) - def calculateKey( cls, target ): - """Calculate the reference key for this reference - - Currently this is a two-tuple of the id()'s of the - target object and the target function respectively. - """ - return (id(getattr(target,im_self)),id(getattr(target,im_func))) - calculateKey = classmethod( calculateKey ) - def __str__(self): - """Give a friendly representation of the object""" - return """%s( %s.%s )"""%( - self.__class__.__name__, - self.selfName, - self.funcName, - ) - __repr__ = __str__ - def __nonzero__( self ): - """Whether we are still a valid reference""" - return self() is not None - def __cmp__( self, other ): - """Compare with another reference""" - if not isinstance (other,self.__class__): - return cmp( self.__class__, type(other) ) - return cmp( self.key, other.key) - def __call__(self): - """Return a strong reference to the bound method - - If the target cannot be retrieved, then will - return None, otherwise returns a bound instance - method for our object and function. - - Note: - You may call this method any number of times, - as it does not invalidate the reference. - """ - target = self.weakSelf() - if target is not None: - function = self.weakFunc() - if function is not None: - return function.__get__(target) - return None diff --git a/software/openvisualizer/PyDispatcher-2.0.3/setup.cfg b/software/openvisualizer/PyDispatcher-2.0.3/setup.cfg deleted file mode 100644 index 861a9f554..000000000 --- a/software/openvisualizer/PyDispatcher-2.0.3/setup.cfg +++ /dev/null @@ -1,5 +0,0 @@ -[egg_info] -tag_build = -tag_date = 0 -tag_svn_revision = 0 - diff --git a/software/openvisualizer/PyDispatcher-2.0.3/setup.py b/software/openvisualizer/PyDispatcher-2.0.3/setup.py deleted file mode 100644 index 0fbd003e4..000000000 --- a/software/openvisualizer/PyDispatcher-2.0.3/setup.py +++ /dev/null @@ -1,89 +0,0 @@ -#!/usr/bin/env python -"""Installs PyDispatcher using distutils (or setuptools/distribute) - -Run: - python setup.py install -to install the package from the source archive. -""" -import sys, os -try: - from setuptools import setup -except ImportError: - from distutils.core import setup - -extra_commands = {} -extra_arguments = {} - -if sys.hexversion >= 0x2030000: - # work around distutils complaints under Python 2.2.x - extra_arguments = { - 'classifiers': [ - """License :: OSI Approved :: BSD License""", - """Programming Language :: Python""", - """Programming Language :: Python :: 3""", - """Topic :: Software Development :: Libraries :: Python Modules""", - """Intended Audience :: Developers""", - ], - #'download_url': "http://sourceforge.net/projects/pydispatcher/files/pydispatcher/", - 'keywords': 'dispatcher,dispatch,pydispatch,event,signal,sender,receiver,propagate,multi-consumer,multi-producer,saferef,robustapply,apply', - 'long_description' : """Dispatcher mechanism for creating event models - -PyDispatcher is an enhanced version of Patrick K. O'Brien's -original dispatcher.py module. It provides the Python -programmer with a robust mechanism for event routing within -various application contexts. - -Included in the package are the robustapply and saferef -modules, which provide the ability to selectively apply -arguments to callable objects and to reference instance -methods using weak-references. -""", - 'platforms': ['Any'], - } -if sys.hexversion >= 0x3000000: - try: - from distutils.command.build_py import build_py_2to3 - extra_commands['build_py'] = build_py_2to3 - except ImportError: - pass - -version = [ - (line.split('=')[1]).strip().strip('"').strip("'") - for line in open(os.path.join('pydispatch','__init__.py')) - if line.startswith( '__version__' ) -][0] - -if __name__ == "__main__": - ### Now the actual set up call - setup ( - name = "PyDispatcher", - version = version, - description= "Multi-producer-multi-consumer signal dispatching mechanism", - author = "Patrick K. O'Brien", - maintainer = "Mike C. Fletcher", - author_email = "pydispatcher-devel@lists.sourceforge.net", - maintainer_email = "pydispatcher-devel@lists.sourceforge.net", - url = "http://pydispatcher.sourceforge.net", - license = "BSD-style, see license.txt for details", - - package_dir = { - 'pydispatch':'pydispatch', - }, - - packages = [ - 'pydispatch', - ], - - options = { - 'sdist':{'use_defaults':0, 'force_manifest':1,'formats': ['gztar','zip'],}, - 'bdist_rpm':{ - 'group':'Libraries/Python', - 'provides':'python-dispatcher', - 'requires':"python", - }, - }, - cmdclass = extra_commands, - use_2to3 = True, - # registration metadata - **extra_arguments - ) diff --git a/software/openvisualizer/PyDispatcher-2.0.3/tests/__init__.py b/software/openvisualizer/PyDispatcher-2.0.3/tests/__init__.py deleted file mode 100644 index b112ba530..000000000 --- a/software/openvisualizer/PyDispatcher-2.0.3/tests/__init__.py +++ /dev/null @@ -1,3 +0,0 @@ -"""Unit-tests for the dispatch project -""" - diff --git a/software/openvisualizer/PyDispatcher-2.0.3/tests/test_dispatcher.py b/software/openvisualizer/PyDispatcher-2.0.3/tests/test_dispatcher.py deleted file mode 100644 index c2d45349d..000000000 --- a/software/openvisualizer/PyDispatcher-2.0.3/tests/test_dispatcher.py +++ /dev/null @@ -1,130 +0,0 @@ -from pydispatch.dispatcher import * -from pydispatch import dispatcher, robust - -import unittest, pprint -def x(a): - return a - -class Dummy( object ): - pass -class Callable(object): - def __call__( self, a ): - return a - def a( self, a ): - return a - -class DispatcherTests(unittest.TestCase): - """Test suite for dispatcher (barely started)""" - - def _isclean( self ): - """Assert that everything has been cleaned up automatically""" - assert len(dispatcher.sendersBack) == 0, dispatcher.sendersBack - assert len(dispatcher.connections) == 0, dispatcher.connections - assert len(dispatcher.senders) == 0, dispatcher.senders - - def testExact (self): - a = Dummy() - signal = 'this' - connect( x, signal, a ) - expected = [(x,a)] - result = send('this',a, a=a) - assert result == expected,"""Send didn't return expected result:\n\texpected:%s\n\tgot:%s"""% (expected, result) - disconnect( x, signal, a ) - assert len(list(getAllReceivers(a,signal))) == 0 - self._isclean() - def testAnonymousSend(self): - a = Dummy() - signal = 'this' - connect( x, signal ) - expected = [(x,a)] - result = send(signal,None, a=a) - assert result == expected,"""Send didn't return expected result:\n\texpected:%s\n\tgot:%s"""% (expected, result) - disconnect( x, signal ) - assert len(list(getAllReceivers(None,signal))) == 0 - self._isclean() - def testAnyRegistration(self): - a = Dummy() - signal = 'this' - connect( x, signal, Any ) - expected = [(x,a)] - result = send('this',object(), a=a) - assert result == expected,"""Send didn't return expected result:\n\texpected:%s\n\tgot:%s"""% (expected, result) - disconnect( x, signal, Any ) - expected = [] - result = send('this',object(), a=a) - assert result == expected,"""Send didn't return expected result:\n\texpected:%s\n\tgot:%s"""% (expected, result) - assert len(list(getAllReceivers(Any,signal))) == 0 - - self._isclean() - - def testAnyRegistration2(self): - a = Dummy() - signal = 'this' - connect( x, Any, a ) - expected = [(x,a)] - result = send('this',a, a=a) - assert result == expected,"""Send didn't return expected result:\n\texpected:%s\n\tgot:%s"""% (expected, result) - disconnect( x, Any, a ) - assert len(list(getAllReceivers(a,Any))) == 0 - self._isclean() - def testGarbageCollected(self): - a = Callable() - b = Dummy() - signal = 'this' - connect( a.a, signal, b ) - expected = [] - del a - result = send('this',b, a=b) - assert result == expected,"""Send didn't return expected result:\n\texpected:%s\n\tgot:%s"""% (expected, result) - assert len(list(getAllReceivers(b,signal))) == 0, """Remaining handlers: %s"""%(getAllReceivers(b,signal),) - self._isclean() - def testGarbageCollectedObj(self): - class x: - def __call__( self, a ): - return a - a = Callable() - b = Dummy() - signal = 'this' - connect( a, signal, b ) - expected = [] - del a - result = send('this',b, a=b) - assert result == expected,"""Send didn't return expected result:\n\texpected:%s\n\tgot:%s"""% (expected, result) - assert len(list(getAllReceivers(b,signal))) == 0, """Remaining handlers: %s"""%(getAllReceivers(b,signal),) - self._isclean() - - - def testMultipleRegistration(self): - a = Callable() - b = Dummy() - signal = 'this' - connect( a, signal, b ) - connect( a, signal, b ) - connect( a, signal, b ) - connect( a, signal, b ) - connect( a, signal, b ) - connect( a, signal, b ) - result = send('this',b, a=b) - assert len( result ) == 1, result - assert len(list(getAllReceivers(b,signal))) == 1, """Remaining handlers: %s"""%(getAllReceivers(b,signal),) - del a - del b - del result - self._isclean() - def testRobust( self ): - """Test the sendRobust function""" - def fails( ): - raise ValueError( 'this' ) - a = object() - signal = 'this' - connect( fails, Any, a ) - result = robust.sendRobust('this',a, a=a) - err = result[0][1] - assert isinstance( err, ValueError ) - assert err.args == ('this',) - -def getSuite(): - return unittest.makeSuite(DispatcherTests,'test') - -if __name__ == "__main__": - unittest.main () diff --git a/software/openvisualizer/PyDispatcher-2.0.3/tests/test_robustapply.py b/software/openvisualizer/PyDispatcher-2.0.3/tests/test_robustapply.py deleted file mode 100644 index 914e3a681..000000000 --- a/software/openvisualizer/PyDispatcher-2.0.3/tests/test_robustapply.py +++ /dev/null @@ -1,27 +0,0 @@ -from pydispatch.robustapply import * - -import unittest -def noArgument(): - pass -def oneArgument (blah): - pass -def twoArgument(blah, other): - pass -class TestCases( unittest.TestCase ): - def test01( self ): - robustApply(noArgument ) - def test02( self ): - self.assertRaises( TypeError, robustApply, noArgument, "this" ) - def test03( self ): - self.assertRaises( TypeError, robustApply, oneArgument ) - def test04( self ): - """Raise error on duplication of a particular argument""" - self.assertRaises( TypeError, robustApply, oneArgument, "this", blah = "that" ) - -def getSuite(): - return unittest.makeSuite(TestCases,'test') - - -if __name__ == "__main__": - unittest.main() - diff --git a/software/openvisualizer/PyDispatcher-2.0.3/tests/test_saferef.py b/software/openvisualizer/PyDispatcher-2.0.3/tests/test_saferef.py deleted file mode 100644 index 8f7b21058..000000000 --- a/software/openvisualizer/PyDispatcher-2.0.3/tests/test_saferef.py +++ /dev/null @@ -1,76 +0,0 @@ -from pydispatch.saferef import * - -import unittest -class T1( object): - def x( self ): - pass -def t2(obj): - pass -class T2( object ): - def __call__( self, obj ): - pass -class Tester (unittest.TestCase): - def setUp (self): - ts = [] - ss = [] - for x in range( 5000 ): - t = T1() - ts.append( t) - s = safeRef(t.x, self._closure ) - ss.append( s) - ts.append( t2 ) - ss.append( safeRef(t2, self._closure) ) - for x in range( 30 ): - t = T2() - ts.append( t) - s = safeRef(t, self._closure ) - ss.append( s) - self.ts = ts - self.ss = ss - self.closureCount = 0 - def tearDown( self ): - del self.ts - del self.ss - def testIn(self): - """Test the "in" operator for safe references (cmp)""" - for t in self.ts[:50]: - assert safeRef(t.x) in self.ss - def testValid(self): - """Test that the references are valid (return instance methods)""" - for s in self.ss: - assert s() - def testShortCircuit (self): - """Test that creation short-circuits to reuse existing references""" - sd = {} - for s in self.ss: - sd[s] = 1 - for t in self.ts: - if hasattr( t, 'x'): - assert safeRef(t.x) in sd - else: - assert safeRef(t) in sd - def testRepresentation (self): - """Test that the reference object's representation works - - XXX Doesn't currently check the results, just that no error - is raised - """ - repr( self.ss[-1] ) - - def test(self): - self.closureCount = 0 - wholeI = len(self.ts) - for i in range( len(self.ts)-1, -1, -1): - del self.ts[i] - if wholeI-i != self.closureCount: - """Unexpected number of items closed, expected %s, got %s closed"""%( wholeI-i,self.closureCount) - - def _closure(self, ref): - """Dumb utility mechanism to increment deletion counter""" - self.closureCount +=1 - -def getSuite(): - return unittest.makeSuite(Tester,'test') - -if __name__ == "__main__": - unittest.main () diff --git a/software/openvisualizer/README.txt b/software/openvisualizer/README.txt new file mode 100644 index 000000000..1c4f99da4 --- /dev/null +++ b/software/openvisualizer/README.txt @@ -0,0 +1,58 @@ +.. Formatted as reStructuredText + +OpenVisualizer is part of UC Berkeley's OpenWSN project. It provides +monitoring, visualization, and debugging for an OpenWSN-based wireless sensor +network. See the project `home page`_ for more information. + +Installation +------------ +You may install OpenVisualizer with the standard pip command line, as shown +below. See the pip `installation instructions`_ if it is not installed +already. You must be logged in with Windows administrator or Linux superuser +privileges to install to system-level directories. + +:: + + > pip install openVisualizer + +Alternatively, you may download the OpenVisualizer archive, extract it, and +install with the standard Python setup.py command line, as shown below. This +command uses pip to retrieve other required Python libraries. + +:: + + > python setup.py install + +Dependencies +------------ +You also may need to separately install a driver for a USB-connected mote. +On Windows, a couple of other tools are required. See the OpenVisualizer +`installation page`_ for a list. + +Running, etc. +------------- +Once everything is installed, you may run the web interface, GUI, or command +line utiltity as described on the OpenVisualizer home page. + +To uninstall a pip-based installation, use the command line:: + + > pip uninstall openVisualizer + +Please contact us via the `mailing list`_ or an `issue report`_ if you +have any questions or suggestions. + +| Thanks! +| The OpenWSN Team + +.. _home page: + https://openwsn.atlassian.net/wiki/display/OW/OpenVisualizer + +.. _installation instructions: + http://www.pip-installer.org/en/latest/installing.html + +.. _installation page: + https://openwsn.atlassian.net/wiki/display/OW/Installation+and+Dependencies + +.. _mailing list: https://openwsn.atlassian.net/wiki/display/OW/Mailing+List + +.. _issue report: https://openwsn.atlassian.net diff --git a/software/openvisualizer/SConstruct b/software/openvisualizer/SConstruct new file mode 100644 index 000000000..bb49d28a0 --- /dev/null +++ b/software/openvisualizer/SConstruct @@ -0,0 +1,310 @@ +# Copyright (c) 2010-2013, Regents of the University of California. +# All rights reserved. +# +# Released under the BSD 3-Clause license as published at the link below. +# https://openwsn.atlassian.net/wiki/display/OW/License + +import os +import platform +import subprocess +import sys +import SCons +import sconsUtils + +#============================ banner ========================================== + +banner = [""] +banner += [" ___ _ _ _ ___ _ _ "] +banner += ["| . | ___ ___ ._ _ | | | |/ __>| \ |"] +banner += ["| | || . \/ ._>| ' || | | |\__ \| |"] +banner += ["`___'| _/\___.|_|_||__/_/ <___/|_\_|"] +banner += [" |_| openwsn.org"] +banner += [""] + +print '\n'.join(banner) + +#============================ SCons environment =============================== + +#===== help text + +Help(''' +Usage: + scons [options] + scons copy-simfw + scons + scons unittests + scons docs + +Targets: + rungui/runcli/runweb: + Run OpenVisualizer with GUI, command line, or web interface, + respectively. + The application is run in the build/runui/ directory. Since it accesses + your computer's network interfaces, it must be run as + superuser/administrator. + + Options + --sim Run in simulator mode with default count of motes. + --simCount=n Run in simulator mode with 'n' motes. + --simTopology= + Force a certain topology for simulation. + --nosimcopy Skips copying simulation firmware at startup from the + openwsn-fw directory. + --ovdebug Enable debug mode; more detailed logging + + Web UI only + --host=

Web server listens on IP address; + default 0.0.0.0 (all interfaces) + --port=n Web server listens on port number 'n'; + default 8080 + + copy-simfw: + Copy files for the simulator, generated from an OpenWSN firmware + build on this host. Assumes firmware top-level directory is + '../../../openwsn-fw'. + + Options + --simhost= + Platform and OS for firmware; supports creation of a + setup package with multiple variants. Defaults to the + platform-OS on which SCons is running. Valid entries: + amd64-linux, x86-linux, amd64-windows, x86-windows + + sdist: + Generate a standard Python source distribution archive (for + setup.py) in build{0}dist directory. Installs data files to the + openvisualizer package directory. + + upload: + Uploads sdist archive to PyPI. The user must be registered as an + Owner or Maintainer of OpenVisualizer. The user's PyPI credentials + must be stored in their home directory .pypirc file. + + sdist-native: + Linux only + Generate a standard Python source distribution archive (for + setup.py) in build{0}dist directory. Installs to native directories + for the OS on which this command is run. This command *must* be + run on a Linux host to generate a Linux target archive. Installs + data files to /usr/local/share. + + docs: + Generate source documentation in build{0}html directory + +'''.format(os.sep)) +# Help for trace option on next line. Removed from help because trace +# implementation is not working. +# --trace Run yappi-based memory trace + + +# Define base environment +env = Environment( + ENV = {'PATH' : os.environ['PATH']} +) +# Must define with absolute path since SCons construction may occur in a +# subdirectory via SConscript. +env['ROOT_BUILD_DIR'] = os.path.join(os.getcwd(), 'build') + +# External openwsn-fw repository directory. An environment variable makes it +# easy to change since it depends on the host running this script. +env['FW_DIR'] = os.path.join('..', '..', '..', 'openwsn-fw') + +def default(env,target,source): + print SCons.Script.help_text + +Default(env.Command('default', None, default)) + + +# Define environment and options common to all run... targets +runnerEnv = env.Clone() + +AddOption('--sim', + dest = 'simOpt', + default = False, + action = 'store_true') +runnerEnv['SIMOPT'] = GetOption('simOpt') + +AddOption('--simCount', + dest = 'simCount', + default = 0, + type = 'int') +runnerEnv['SIMCOUNT'] = GetOption('simCount') + +AddOption('--simTopology', + dest = 'simTopology', + default = '', + type = 'string') +runnerEnv['SIMTOPOLOGY'] = GetOption('simTopology') + +AddOption('--nosimcopy', + dest = 'simcopyOpt', + default = True, + action = 'store_true') +runnerEnv['SIMCOPYOPT'] = GetOption('simcopyOpt') + +AddOption('--trace', + dest = 'traceOpt', + default = False, + action = 'store_true') +runnerEnv['TRACEOPT'] = GetOption('traceOpt') + +AddOption('--ovdebug', + dest = 'debugOpt', + default = False, + action = 'store_true') +runnerEnv['DEBUGOPT'] = GetOption('debugOpt') + + +# These options are used only by the web runner. We define them here for +# simplicity, but they must be removed from non-web use in the runner +# SConscript. +AddOption('--host', + dest = 'hostOpt', + default = '0.0.0.0', + type = 'string') +runnerEnv['HOSTOPT'] = GetOption('hostOpt') + +AddOption('--port', + dest = 'portOpt', + default = 8080, + type = 'int') +runnerEnv['PORTOPT'] = GetOption('portOpt') + +#============================ SCons targets =================================== + +#===== copy-simfw + +simhosts = ['amd64-linux','x86-linux','amd64-windows','x86-windows'] +if os.name == 'nt': + defaultIndex = 2 if platform.architecture()[0]=='64bit' else 3 +else: + defaultIndex = 0 if platform.architecture()[0]=='64bit' else 1 + +AddOption('--simhost', + dest = 'simhostOpt', + default = simhosts[defaultIndex], + type = 'choice', + choices = simhosts) + +# Must copy SIMHOSTOPT to runner environment since it also reads sconsUtils.py. +env['SIMHOSTOPT'] = GetOption('simhostOpt') +runnerEnv['SIMHOSTOPT'] = env['SIMHOSTOPT'] + +Alias('copy-simfw', sconsUtils.copySimfw(env, 'simcopy')) + +#===== rungui, runcli, runweb + +# Must define run targets below the copy-simfw target so SIMHOSTOPT is available. +# Run targets may copy simulation firmware before starting. + +appdir = os.path.join('bin', 'openVisualizerApp') + +SConscript( + os.path.join(appdir, 'SConscript'), + exports = {"env": runnerEnv}, +) + +# Copy variables for data files out of runner environment, to be used in +# dist targets below. +env['CONF_FILES'] = runnerEnv['CONF_FILES'] +env['DATA_DIRS'] = runnerEnv['DATA_DIRS'] + +#===== sdist + +def makeTreeSdist(env, target): + ''' + Creates a target that requires creation of a source distribution. Uses + the target name as a phony target to force the build. Supports 'sdist' and + 'upload' targets. + + First, copies the data files from the openVisualizerApp directory as data + for the openvisualizer package. Then creates the source dist archive. + Cleans up the temporary package data file. + ''' + datadir = os.path.join('openvisualizer', 'data') + appdir = os.path.join('bin', 'openVisualizerApp') + distdir = os.path.join('build', 'dist') + topdir = os.path.join('..', '..') + cmdlist = [] + + cmdlist.append(Delete(distdir)) + cmdlist.append(Delete(datadir)) + cmdlist.append(Delete('openVisualizer.egg-info')) + + cmdlist.append(Mkdir(datadir)) + cmdlist.append(Copy(os.path.join(datadir, 'requirements.pip'), + os.path.join(topdir, 'requirements.pip'))) + for conf in env['CONF_FILES']: + cmdlist.append(Copy(os.path.join(datadir, conf), os.path.join(appdir, conf))) + for data in env['DATA_DIRS']: + cmdlist.append(Copy(os.path.join(datadir, data), os.path.join(appdir, data))) + + sdistLines = ['python setup.py sdist', + '--formats=gztar,zip', + '--dist-dir {0}'.format(distdir)] + if target == 'sdist': + cmdlist.append(' '.join(sdistLines)) + elif target == 'upload': + # Must first run sdist before upload + cmdlist.append(' '.join(sdistLines + ['upload'])) + else: + print 'Target "{0}" not supported'.format(target) + + cmdlist.append(Delete(datadir)) + cmdlist.append(Delete('openVisualizer.egg-info')) + + return env.Command(target, '', cmdlist) + +Alias('sdist', makeTreeSdist(env, 'sdist')) +Alias('upload', makeTreeSdist(env, 'upload')) + +#===== sdist-native + +def makeNativeSdist(env): + ''' + Creates the source dist archive for a OS-native install. Uses a + phony target to force build. + ''' + distdir = os.path.join('build', 'dist') + + return env.Command('native', '', + [ + Delete(distdir), + Delete('MANIFEST'), + Copy('setup.py', 'nativeSetup.py'), + 'python setup.py sdist --dist-dir {0}'.format(distdir), + Delete('setup.py'), + Delete('MANIFEST'), + ]) + +Alias('sdist-native', makeNativeSdist(env)) + +#===== unittest + +# scan for SConscript contains unit tests +dirs = [ + os.path.join('openvisualizer', 'moteProbe'), + os.path.join('openvisualizer', 'openLbr'), + os.path.join('openvisualizer', 'RPL'), +] +for d in dirs: + SConscript( + os.path.join(d, 'SConscript'), + exports = {"env": env}, + ) + +Alias( + 'unittests', + [ + 'unittests_moteProbe', + 'unittests_openLbr', + 'unittests_RPL', + ] +) + +#===== docs + +SConscript( + os.path.join('docs', 'SConscript'), + exports = {"env": env}, +) diff --git a/software/openvisualizer/bin/moteProbeCli/moteProbeCli.py b/software/openvisualizer/bin/moteProbeCli/moteProbeCli.py index d73748c04..b25b41305 100644 --- a/software/openvisualizer/bin/moteProbeCli/moteProbeCli.py +++ b/software/openvisualizer/bin/moteProbeCli/moteProbeCli.py @@ -1,86 +1,82 @@ -import os -import sys -if __name__=='__main__': - cur_path = sys.path[0] - sys.path.insert(0, os.path.join(cur_path, '..', '..')) # openvisualizer/ - sys.path.insert(0, os.path.join(cur_path, '..', '..', '..', 'openCli')) # openCli/ - sys.path.insert(0, os.path.join(cur_path, '..', '..','PyDispatcher-2.0.3'))# PyDispatcher-2.0.3/ - -from moteProbe import moteProbe -from OpenCli import OpenCli - -TCP_PORT_START = 8090 - -class moteProbeCli(OpenCli): - - def __init__(self,moteProbe_handlers): - - # store params - self.moteProbe_handlers = moteProbe_handlers - - # initialize parent class - OpenCli.__init__(self,"mote probe CLI",self.quit_cb) - - # add commands - self.registerCommand('status', - 's', - 'print status', - [], - self._handlerStatus) - - #======================== public ========================================== - - #======================== private ========================================= - - #===== callbacks - - def _handlerStatus(self,params): - output = [] - - for mp in self.moteProbe_handlers: - output += [' - serial port {0}@{1} presented on TCP port {2}'.format( - mp.getSerialPortName(), - mp.getSerialPortBaudrate(), - mp.getTcpPort())] - - print '\n'.join(output) - - #===== helpers - - def quit_cb(self): - for mb in self.moteProbe_handlers: - mb.quit() - -def main(): - - moteProbe_handlers = [] - - # create a moteProbe for each mote connected to this computer - serialPortNames = moteProbe.utils.findSerialPorts() - port_numbers = [TCP_PORT_START+i for i in range(len(serialPortNames))] - for (serialPortName,port_number) in zip(serialPortNames,port_numbers): - moteProbe_handlers.append(moteProbe.moteProbe(serialPortName,port_number)) - - # create an open CLI - cli = moteProbeCli(moteProbe_handlers) - cli.start() - -#============================ application logging ============================= -import logging -import logging.handlers -logHandler = logging.handlers.RotatingFileHandler('moteProbe.log', - maxBytes=2000000, - backupCount=5, - mode='w') -logHandler.setFormatter(logging.Formatter("%(asctime)s [%(name)s:%(levelname)s] %(message)s")) -for loggerName in ['moteProbe', - 'moteProbeSerialThread', - 'moteProbeSocketThread', - 'moteProbeUtils', - ]: - temp = logging.getLogger(loggerName) - temp.setLevel(logging.DEBUG) - temp.addHandler(logHandler) - -if __name__=="__main__": +import os +import sys +if __name__=='__main__': + cur_path = sys.path[0] + sys.path.insert(0, os.path.join(cur_path, '..', '..')) # openvisualizer/ + sys.path.insert(0, os.path.join(cur_path, '..', '..', '..', 'openCli')) # openCli/ + sys.path.insert(0, os.path.join(cur_path, '..', '..','PyDispatcher-2.0.3'))# PyDispatcher-2.0.3/ + +from moteProbe import moteProbe +from OpenCli import OpenCli + +TCP_PORT_START = 8090 + +class moteProbeCli(OpenCli): + + def __init__(self,moteProbe_handlers): + + # store params + self.moteProbe_handlers = moteProbe_handlers + + # initialize parent class + OpenCli.__init__(self,"mote probe CLI",self.quit_cb) + + # add commands + self.registerCommand('status', + 's', + 'print status', + [], + self._handlerStatus) + + #======================== public ========================================== + + #======================== private ========================================= + + #===== callbacks + + def _handlerStatus(self,params): + output = [] + + for mp in self.moteProbe_handlers: + output += [' - serial port {0}@{1} presented on TCP port {2}'.format( + mp.getSerialPortName(), + mp.getSerialPortBaudrate(), + mp.getTcpPort())] + + print '\n'.join(output) + + #===== helpers + + def quit_cb(self): + for mb in self.moteProbe_handlers: + mb.quit() + +def main(): + + moteProbe_handlers = [] + + # create a moteProbe for each mote connected to this computer + serialPortNames = moteProbe.utils.findSerialPorts() + port_numbers = [TCP_PORT_START+i for i in range(len(serialPortNames))] + for (serialPortName,port_number) in zip(serialPortNames,port_numbers): + moteProbe_handlers.append(moteProbe.moteProbe(serialPortName,port_number)) + + # create an open CLI + cli = moteProbeCli(moteProbe_handlers) + cli.start() + +#============================ application logging ============================= +import logging +import logging.handlers +logHandler = logging.handlers.RotatingFileHandler('moteProbe.log', + maxBytes=2000000, + backupCount=5, + mode='w') +logHandler.setFormatter(logging.Formatter("%(asctime)s [%(name)s:%(levelname)s] %(message)s")) +for loggerName in ['moteProbe']: + temp = logging.getLogger(loggerName) + temp.setLevel(logging.DEBUG) + temp.addHandler(logHandler) + +if __name__=="__main__": main() \ No newline at end of file diff --git a/software/openvisualizer/bin/moteResExperimentCli/moteResExperiementCli.py b/software/openvisualizer/bin/moteResExperimentCli/moteResExperiementCli.py index 6addc4c05..6f0265120 100644 --- a/software/openvisualizer/bin/moteResExperimentCli/moteResExperiementCli.py +++ b/software/openvisualizer/bin/moteResExperimentCli/moteResExperiementCli.py @@ -1,150 +1,150 @@ -import sys -import os -import struct -import binascii -if __name__=='__main__': - cur_path = sys.path[0] - sys.path.insert(0, os.path.join(cur_path, '..', '..')) # openvisualizer/ - sys.path.insert(0, os.path.join(cur_path, '..', '..', '..', 'openCli')) # openCli/ - -import logging -class NullHandler(logging.Handler): - def emit(self, record): - pass -log = logging.getLogger('MoteStateCli') -log.setLevel(logging.DEBUG) -log.addHandler(NullHandler()) - -from moteProbe import moteProbe -from moteConnector import moteConnector -from moteState import moteState -from OpenCli import OpenCli - -LOCAL_ADDRESS = '127.0.0.1' -TCP_PORT_START = 8090 - -class MoteStateCli(OpenCli): - - def __init__(self,moteProbe_handlers,moteConnector_handlers,moteState_handlers): - - # store params - self.moteProbe_handlers = moteProbe_handlers - self.moteConnector_handlers = moteConnector_handlers - self.moteState_handlers = moteState_handlers - - # initialize parent class - OpenCli.__init__(self,"Reservation Experiment CLI",self._quit_cb) - - # add commands - self.registerCommand('list', - 'l', - 'list available states', - [], - self._handlerList) - self.registerCommand('state', - 's', - 'prints some state', - ['state parameter'], - self._handlerState) - self.registerCommand('reserve', - 'r', - 'reserve cells; e.g. "r e6 eb 2 10032"', - ['mote_addr','neighbor_addr','num_of_links','start_at_asn'], - self._handlerRes) - - #======================== public ========================================== - - #======================== private ========================================= - - #===== callbacks - - def _handlerList(self,params): - for ms in self.moteState_handlers: - output = [] - output += ['available states:'] - output += [' - {0}'.format(s) for s in ms.getStateElemNames()] - print '\n'.join(output) - - def _handlerState(self,params): - for ms in self.moteState_handlers: - try: - print ms.getStateElem(params[0]) - except ValueError as err: - print err - - def _handlerRes(self,params): - for ms in self.moteState_handlers: - try: - myid = str(ms.getStateElem("IdManager").data[0]['my16bID']) - myid=myid[3:5] - if myid==params[0]:#match the ID and then send command to mote - print(params) - input = struct.pack(' - - OpenWSN tables - - - - - -
- - + + + OpenWSN tables + + + + + +
+ + \ No newline at end of file diff --git a/software/openvisualizer/bin/openVisualizerApp/SConscript b/software/openvisualizer/bin/openVisualizerApp/SConscript new file mode 100644 index 000000000..a0af5dda6 --- /dev/null +++ b/software/openvisualizer/bin/openVisualizerApp/SConscript @@ -0,0 +1,161 @@ +# Copyright (c) 2010-2013, Regents of the University of California. +# All rights reserved. +# +# Released under the BSD 3-Clause license as published at the link below. +# https://openwsn.atlassian.net/wiki/display/OW/License +''' +SCons script to run the application within the source repository. +Provides rungui, runcli, and runweb targets. +''' + +import os +import subprocess +import sconsUtils + +Import('env') + +def uiRunner(target, source, env): + ''' + Builder to run OpenVisualizerApp as subprocess in current directory. + Note: Although this SCons task is constructed in the bin/openVisualizerApp + directory, it is executed from the root openvisualizer directory (../..). + + Target is never created; always runs Python app. Does not check if + app is running already. Assumes current process already runs with the + required superuser/administrator privileges. + ''' + # Include root directory + pypath = '.' + try: + envpath = os.environ['PYTHONPATH'] + if envpath: + pypath = pypath + os.pathsep + envpath + except KeyError: + pass + + subEnv = os.environ.copy() + subEnv['PYTHONPATH'] = pypath + + argList = [ + 'python', str(source[0]), + '-a', env['BUILD_DIR'], + ] + if env['SIMCOUNT']: + # Must append to list in a single item, without embedded quotes. + argList.append('--simCount={0}'.format(env['SIMCOUNT'])) + elif env['SIMOPT']: + argList.append('--sim') + + if env['SIMTOPOLOGY']: + argList.append('--simTopology={0}'.format(env['SIMTOPOLOGY'])) + + if env['TRACEOPT']: + argList.append('--trace') + if env['DEBUGOPT']: + argList.append('--debug') + + if env['HOSTOPT']: + argList.append('-H {0}'.format(env['HOSTOPT'])) + if env['PORTOPT']: + argList.append('-p {0}'.format(env['PORTOPT'])) + + result = 0 + try: + p = subprocess.Popen(argList, env=subEnv) + + if env['WAIT_ON_UI']: + # Must wait for CLI program that uses raw_input(); otherwise + # SCons exits and standard input is sent to shell. + result = p.wait() + else: + # Display PID to make it easier to kill if necessary. + print 'Child PID is {0}'.format(p.pid) + except: + result = 1 + + return result + +def setupUiRunner(env, uiFile, dataDirs): + ''' + Sets up dependencies for data files required to run an OpenVisualizer + UI. The data files are copied to the environment's BUILD_DIR. + + * Copies simulation firmware to the sim_files data directory if running + a simulation. + * Creates commands to copy conf files unless they exist already. The + user may have edited them. + * Creates commands to copy the provided static data directories + unconditionally. + + :param uiFile: Filename to run in openVisualizerApp directory + :param dataDirs: Dirs containing static data + :rtype: The targets reference for the Builder. + ''' + + # Create Builder to run GUI + env.Append(BUILDERS = {'RunUi' : Builder(action = uiRunner)}) + + targets = env.RunUi(uiFile) + + if (env['SIMOPT'] or env['SIMCOUNT']) and env['SIMCOPYOPT']: + # Appending uiFile to pseudo-target to make it unique. + simfwTarget = 'simui-{0}'.format(uiFile) + Depends(targets, simfwTarget) + sconsUtils.copySimfw(env, simfwTarget) + + for node in (env['CONF_FILES'] + env['DATA_FILES']): + bldNode = os.path.join(env['BUILD_DIR'], node) + + Depends(targets, bldNode) + Command( + bldNode, + node, + [ + Mkdir(env['BUILD_DIR']), + Copy('$TARGET', '$SOURCE') + ] + ) + + for node in env['DATA_DIRS']: + bldNode = os.path.join(env['BUILD_DIR'], node) + + Depends(targets, bldNode) + Command( + bldNode, + node, + [ + Delete('$TARGET'), + Mkdir(env['BUILD_DIR']), + Copy('$TARGET', '$SOURCE') + ] + ) + AlwaysBuild(bldNode) + + return targets + +# Prepare the environment to create builders for data files and directoires, +# as well as a builder to run the app itself. +env['BUILD_DIR'] = os.path.join(env['ROOT_BUILD_DIR'], 'runui') +env['WAIT_ON_UI'] = False +# Must create the entries for use here and by parent SConstruct to identify +# these kinds of files for other use. +env['CONF_FILES'] = ['openvisualizer.conf', 'logging.conf', 'trace.conf'] +env['DATA_DIRS'] = ['web_files', 'sim_files'] +env['DATA_FILES'] = [] + +# Customize environment for each target. Must remove 'host' and 'port' +# options for GUI and CLI because they are not defined in those scripts. +guiEnv = env.Clone() +guiEnv['HOSTOPT'] = None +guiEnv['PORTOPT'] = None +Alias('rungui', setupUiRunner(guiEnv, 'openVisualizerGui.py', [])) + +cliEnv = env.Clone() +cliEnv['WAIT_ON_UI'] = True +cliEnv['HOSTOPT'] = None +cliEnv['PORTOPT'] = None +Alias('runcli', setupUiRunner(cliEnv, 'openVisualizerCli.py', [])) + +webEnv = env.Clone() +webdirs = ['web_files'] +Alias('runweb', setupUiRunner(webEnv, 'openVisualizerWeb.py', webdirs)) diff --git a/software/openvisualizer/bin/openVisualizerApp/logging.conf b/software/openvisualizer/bin/openVisualizerApp/logging.conf new file mode 100644 index 000000000..d8e7ce439 --- /dev/null +++ b/software/openvisualizer/bin/openVisualizerApp/logging.conf @@ -0,0 +1,190 @@ +# Note Expects 'logDir' passed in with location for file output. + +#============================ formatters ====================================== + +[formatters] +keys=std,console + +[formatter_std] +format=%(asctime)s [%(name)s:%(levelname)s] %(message)s +datefmt= + +[formatter_console] +format=%(asctime)s %(levelname)s %(message)s +datefmt=%H:%M:%S + +#============================ handlers ======================================== + +[handlers] +keys=std,console + +[handler_std] +class=handlers.RotatingFileHandler +# args: filename, open mode, max file size, backup file count +args=('%(logDir)s/openVisualizer.log', 'a', 2000000, 5) +formatter=std + +[handler_console] +class=StreamHandler +args=() +formatter=console + +#============================ loggers ========================================= + +[loggers] +keys=root,eventBusMonitor,openTun,openTunWindows,openTunLinux,eventBusClient,lbrClient,moteConnector,moteProbe,moteProbeUtils,moteState,openLbr,OpenParser,Parser,OpenHdlc,ParserData,ParserInfoErrorCritical,ParserStatus,RPL,SourceRoute,udpLatency,openVisualizerApp,openVisualizerGui,openVisualizerCli,openVisualizerWeb,OVtracer + +[logger_root] +level=ERROR +handlers=std + +[logger_eventBusMonitor] +level=ERROR +handlers=std +propagate=0 +qualname=eventBusMonitor + +[logger_eventBusClient] +level=ERROR +handlers=std +propagate=0 +qualname=eventBusClient + +[logger_openTun] +level=ERROR +handlers=std +propagate=0 +qualname=openTun + +[logger_openTunWindows] +level=ERROR +handlers=std +propagate=0 +qualname=openTunWindows + +[logger_openTunLinux] +level=ERROR +handlers=std +propagate=0 +qualname=openTunLinux + +[logger_lbrClient] +level=ERROR +handlers=std +propagate=0 +qualname=lbrClient + +[logger_moteConnector] +level=ERROR +handlers=std +propagate=0 +qualname=moteConnector + +[logger_moteProbe] +level=ERROR +handlers=std +propagate=0 +qualname=moteProbe + +[logger_moteProbeUtils] +level=ERROR +handlers=std +propagate=0 +qualname=moteProbeUtils + +[logger_moteState] +level=ERROR +handlers=std +propagate=0 +qualname=moteState + +[logger_openLbr] +level=ERROR +handlers=std +propagate=0 +qualname=openLbr + +[logger_OpenParser] +level=ERROR +handlers=std +propagate=0 +qualname=OpenParser + +[logger_Parser] +level=ERROR +handlers=std +propagate=0 +qualname=Parser + +[logger_ParserData] +level=ERROR +handlers=std +propagate=0 +qualname=ParserData + +[logger_ParserInfoErrorCritical] +level=INFO +handlers=std,console +propagate=0 +qualname=ParserInfoErrorCritical + +[logger_ParserStatus] +level=ERROR +handlers=std +propagate=0 +qualname=ParserStatus + +[logger_RPL] +level=INFO +handlers=std +propagate=0 +qualname=RPL + +[logger_SourceRoute] +level=ERROR +handlers=std +propagate=0 +qualname=SourceRoute + +[logger_udpLatency] +level=ERROR +handlers=std +propagate=0 +qualname=udpLatency + +[logger_OpenHdlc] +level=ERROR +handlers=std +propagate=0 +qualname=OpenHdlc + +[logger_openVisualizerApp] +level=INFO +handlers=std +propagate=0 +qualname=openVisualizerApp + +[logger_openVisualizerGui] +level=INFO +handlers=std +propagate=0 +qualname=openVisualizerGui + +[logger_openVisualizerCli] +level=INFO +handlers=std +propagate=0 +qualname=openVisualizerCli + +[logger_openVisualizerWeb] +level=INFO +handlers=std +propagate=0 +qualname=openVisualizerWeb + +[logger_OVtracer] +level=DEBUG +handlers=std +propagate=0 +qualname=OVtracer + diff --git a/software/openvisualizer/bin/openVisualizerApp/openVisualizerApp.py b/software/openvisualizer/bin/openVisualizerApp/openVisualizerApp.py new file mode 100644 index 000000000..4d629187a --- /dev/null +++ b/software/openvisualizer/bin/openVisualizerApp/openVisualizerApp.py @@ -0,0 +1,332 @@ +# Copyright (c) 2010-2013, Regents of the University of California. +# All rights reserved. +# +# Released under the BSD 3-Clause license as published at the link below. +# https://openwsn.atlassian.net/wiki/display/OW/License + +''' +Contains application model for OpenVisualizer. Expects to be called by +top-level UI module. See main() for startup use. +''' +import sys +import os +import logging +log = logging.getLogger('openVisualizerApp') + +from openvisualizer.eventBus import eventBusMonitor +from openvisualizer.moteProbe import moteProbe +from openvisualizer.moteConnector import moteConnector +from openvisualizer.moteState import moteState +from openvisualizer.RPL import RPL +from openvisualizer.openLbr import openLbr +from openvisualizer.openTun import openTun +from openvisualizer.RPL import UDPLatency +from openvisualizer.RPL import topology +from openvisualizer import appdirs + +import openvisualizer.openvisualizer_utils as u + +class OpenVisualizerApp(object): + ''' + Provides an application model for OpenVisualizer. Provides common, + top-level functionality for several UI clients. + ''' + + def __init__(self,confdir,datadir,logdir,simulatorMode,numMotes,trace,debug,simTopology): + + # store params + self.confdir = confdir + self.datadir = datadir + self.logdir = logdir + self.simulatorMode = simulatorMode + self.numMotes = numMotes + self.trace = trace + self.debug = debug + + # local variables + self.eventBusMonitor = eventBusMonitor.eventBusMonitor() + self.openLbr = openLbr.OpenLbr() + self.rpl = RPL.RPL() + self.topology = topology.topology() + self.udpLatency = UDPLatency.UDPLatency() + self.openTun = openTun.create() # call last since indicates prefix + if self.simulatorMode: + from openvisualizer.SimEngine import SimEngine, MoteHandler + + self.simengine = SimEngine.SimEngine(simTopology) + self.simengine.start() + + # create a moteProbe for each mote + if not self.simulatorMode: + # in "hardware" mode, motes are connected to the serial port + + self.moteProbes = [ + moteProbe.moteProbe(serialport=sp) for sp in moteProbe.findSerialPorts() + ] + else: + # in "simulator" mode, motes are emulated + sys.path.append(os.path.join(self.datadir, 'sim_files')) + import oos_openwsn + + MoteHandler.readNotifIds(os.path.join(self.datadir, 'sim_files', 'openwsnmodule_obj.h')) + self.moteProbes = [] + for _ in range(self.numMotes): + moteHandler = MoteHandler.MoteHandler(oos_openwsn.OpenMote()) + self.simengine.indicateNewMote(moteHandler) + self.moteProbes += [moteProbe.moteProbe(emulatedMote=moteHandler)] + + # create a moteConnector for each moteProbe + self.moteConnectors = [ + moteConnector.moteConnector(mp.getSerialPortName()) for mp in self.moteProbes + ] + + # create a moteState for each moteConnector + self.moteStates = [ + moteState.moteState(mc) for mc in self.moteConnectors + ] + + # boot all emulated motes, if applicable + if self.simulatorMode: + self.simengine.pause() + now = self.simengine.timeline.getCurrentTime() + for rank in range(self.simengine.getNumMotes()): + moteHandler = self.simengine.getMoteHandler(rank) + self.simengine.timeline.scheduleEvent( + now, + moteHandler.getId(), + moteHandler.hwSupply.switchOn, + moteHandler.hwSupply.INTR_SWITCHON + ) + self.simengine.resume() + + # start tracing threads + if self.trace: + import openvisualizer.OVtracer + logging.config.fileConfig( + os.path.join(self.confdir,'trace.conf'), + {'logDir': _forceSlashSep(self.logdir, self.debug)}) + OVtracer.OVtracer() + + #======================== public ========================================== + + def close(self): + '''Closes all thread-based components''' + + log.info('Closing OpenVisualizer') + self.openTun.close() + self.rpl.close() + for probe in self.moteProbes: + probe.close() + + def getMoteState(self, moteid): + ''' + Returns the moteState object for the provided connected mote. + + :param moteid: 16-bit ID of mote + :rtype: moteState or None if not found + ''' + for ms in self.moteStates: + idManager = ms.getStateElem(ms.ST_IDMANAGER) + if idManager and idManager.get16bAddr(): + addr = ''.join(['%02x'%b for b in idManager.get16bAddr()]) + if addr == moteid: + return ms + else: + return None + + +#============================ main ============================================ +import logging.config +from argparse import ArgumentParser + +DEFAULT_MOTE_COUNT = 3 + +def main(parser=None): + ''' + Entry point for application startup by UI. Parses common arguments. + + :param parser: Optional ArgumentParser passed in from enclosing UI module + to allow that module to pre-parse specific arguments + :rtype: openVisualizerApp object + ''' + if (parser == None): + parser = ArgumentParser() + + _addParserArgs(parser) + argspace = parser.parse_args() + + confdir, datadir, logdir = _initExternalDirs(argspace.appdir, argspace.debug) + + # Must use a '/'-separated path for log dir, even on Windows. + logging.config.fileConfig( + os.path.join(confdir,'logging.conf'), + {'logDir': _forceSlashSep(logdir, argspace.debug)} + ) + + if argspace.numMotes > 0: + # --simCount implies --sim + argspace.simulatorMode = True + elif argspace.simulatorMode == True: + # default count when --simCount not provided + argspace.numMotes = DEFAULT_MOTE_COUNT + + log.info('Initializing OpenVisualizerApp with options:\n\t{0}'.format( + '\n '.join(['appdir = {0}'.format(argspace.appdir), + 'sim = {0}'.format(argspace.simulatorMode), + 'simCount = {0}'.format(argspace.numMotes), + 'trace = {0}'.format(argspace.trace), + 'debug = {0}'.format(argspace.debug)], + ))) + log.info('Using external dirs:\n\t{0}'.format( + '\n '.join(['conf = {0}'.format(confdir), + 'data = {0}'.format(datadir), + 'log = {0}'.format(logdir)], + ))) + log.info('sys.path:\n\t{0}'.format('\n\t'.join(str(p) for p in sys.path))) + + return OpenVisualizerApp( + confdir = confdir, + datadir = datadir, + logdir = logdir, + simulatorMode = argspace.simulatorMode, + numMotes = argspace.numMotes, + trace = argspace.trace, + debug = argspace.debug, + simTopology = argspace.simTopology, + ) + +def _addParserArgs(parser): + parser.add_argument('-a', '--appDir', + dest = 'appdir', + default = '.', + action = 'store', + help = 'working directory' + ) + parser.add_argument('-s', '--sim', + dest = 'simulatorMode', + default = False, + action = 'store_true', + help = 'simulation mode, with default of {0} motes'.format(DEFAULT_MOTE_COUNT) + ) + parser.add_argument('-n', '--simCount', + dest = 'numMotes', + type = int, + default = 0, + help = 'simulation mode, with provided mote count' + ) + parser.add_argument('-t', '--trace', + dest = 'trace', + default = False, + action = 'store_true', + help = 'enables memory debugging' + ) + parser.add_argument('-st', '--simTopology', + dest = 'simTopology', + default = '', + action = 'store', + help = 'force a certain toplogy (simulation mode only)' + ) + parser.add_argument('-d', '--debug', + dest = 'debug', + default = False, + action = 'store_true', + help = 'enables application debugging' + ) + +def _forceSlashSep(ospath, debug): + ''' + Converts a Windows-based path to use '/' as the path element separator. + + :param ospath: A relative or absolute path for the OS on which this process + is running + :param debug: If true, print extra logging info + ''' + if os.sep == '/': + return ospath + + head = ospath + pathlist = [] + while True: + head, tail = os.path.split(head) + if tail == '': + pathlist.insert(0, head.rstrip('\\')) + break + else: + pathlist.insert(0, tail) + + pathstr = '/'.join(pathlist) + if debug: + print pathstr + return pathstr + +def _initExternalDirs(appdir, debug): + ''' + Find and define confdir for config files and datadir for static data. Also + return logdir for logs. There are several possiblities, searched in the order + described below. + + 1. Provided from command line, appdir parameter + 2. In the directory containing openVisualizerApp.py + 3. In native OS site-wide config and data directories + 4. In the openvisualizer package directory + + The directories differ only when using a native OS site-wide setup. + + :param debug: If true, print extra logging info + :returns: 3-Tuple with config dir, data dir, and log dir + :raises: RuntimeError if files/directories not found as expected + ''' + if not appdir == '.': + if not _verifyConfpath(appdir): + raise RuntimeError('Config file not in expected directory: {0}'.format(appdir)) + if debug: + print 'App data found via appdir' + return (appdir, appdir, appdir) + + filedir = os.path.dirname(__file__) + if _verifyConfpath(filedir): + if debug: + print 'App data found via openVisualizerApp.py' + return (filedir, filedir, filedir) + + confdir = appdirs.site_config_dir('openvisualizer', 'OpenWSN') + # Must use system log dir on Linux since running as superuser. + linuxLogdir = '/var/log/openvisualizer' + if _verifyConfpath(confdir): + if not sys.platform.startswith('linux'): + raise RuntimeError('Native OS external directories supported only on Linux') + + datadir = appdirs.site_data_dir('openvisualizer', 'OpenWSN') + logdir = linuxLogdir + if os.path.exists(datadir): + if not os.path.exists(logdir): + os.mkdir(logdir) + if debug: + print 'App data found via native OS' + return (confdir, datadir, logdir) + else: + raise RuntimeError('Cannot find expected data directory: {0}'.format(datadir)) + + datadir = os.path.join(os.path.dirname(u.__file__), 'data') + if _verifyConfpath(datadir): + if sys.platform == 'win32': + logdir = appdirs.user_log_dir('openvisualizer', 'OpenWSN', opinion=False) + else: + logdir = linuxLogdir + if not os.path.exists(logdir): + # Must make intermediate directories on Windows + os.makedirs(logdir) + if debug: + print 'App data found via openvisualizer package' + + return (datadir, datadir, logdir) + else: + raise RuntimeError('Cannot find expected data directory: {0}'.format(datadir)) + +def _verifyConfpath(confdir): + ''' + Returns True if OpenVisualizer conf files exist in the provided + directory. + ''' + confpath = os.path.join(confdir, 'openvisualizer.conf') + return os.path.isfile(confpath) diff --git a/software/openvisualizer/bin/openVisualizerApp/openVisualizerCli.py b/software/openvisualizer/bin/openVisualizerApp/openVisualizerCli.py new file mode 100755 index 000000000..4a7a40caf --- /dev/null +++ b/software/openvisualizer/bin/openVisualizerApp/openVisualizerCli.py @@ -0,0 +1,132 @@ +#!/usr/bin/python +# Copyright (c) 2010-2013, Regents of the University of California. +# All rights reserved. +# +# Released under the BSD 3-Clause license as published at the link below. +# https://openwsn.atlassian.net/wiki/display/OW/License + +import sys +import os + +if __name__=="__main__": + # Update pythonpath if running in in-tree development mode + basedir = os.path.dirname(__file__) + confFile = os.path.join(basedir, "openvisualizer.conf") + if os.path.exists(confFile): + import pathHelper + pathHelper.updatePath() + +import logging +log = logging.getLogger('openVisualizerCli') + +try: + from openvisualizer.moteState import moteState +except ImportError: + # Debug failed lookup on first library import + print 'ImportError: cannot find openvisualizer.moteState module' + print 'sys.path:\n\t{0}'.format('\n\t'.join(str(p) for p in sys.path)) + +from cmd import Cmd +import openVisualizerApp +import openvisualizer.openvisualizer_utils as u + + +class OpenVisualizerCli(Cmd): + + def __init__(self,app): + log.info('Creating OpenVisualizerCli') + + # store params + self.app = app + + Cmd.__init__(self) + self.doc_header = 'Commands (type "help all" or "help "):' + self.prompt = '> ' + self.intro = '\nOpenVisualizer (type "help" for commands)' + + #======================== public ========================================== + + #======================== private ========================================= + + #===== callbacks + + def do_state(self, arg): + """ + Prints provided state, or lists states. + Usage: state [state-name] + """ + if not arg: + for ms in self.app.moteStates: + output = [] + output += ['Available states:'] + output += [' - {0}'.format(s) for s in ms.getStateElemNames()] + self.stdout.write('\n'.join(output)) + self.stdout.write('\n') + else: + for ms in self.app.moteStates: + try: + self.stdout.write(str(ms.getStateElem(arg))) + self.stdout.write('\n') + except ValueError as err: + self.stdout.write(err) + + def do_list(self, arg): + """List available states. (Obsolete; use 'state' without parameters.)""" + self.do_state('') + + def do_root(self, arg): + """ + Sets dagroot to the provided mote, or lists motes + Usage: root [serial-port] + """ + if not arg: + self.stdout.write('Available ports:') + if self.app.moteStates: + for ms in self.app.moteStates: + self.stdout.write(' {0}'.format(ms.moteConnector.serialport)) + else: + self.stdout.write(' ') + self.stdout.write('\n') + else: + for ms in self.app.moteStates: + try: + if (ms.moteConnector.serialport==arg): + ms.triggerAction(moteState.moteState.TRIGGER_DAGROOT) + except ValueError as err: + self.stdout.write(err) + + def help_all(self): + """Lists first line of help for all documented commands""" + names = self.get_names() + names.sort() + maxlen = 65 + self.stdout.write( + 'type "help " for topic details\n'.format(80-maxlen-3)) + for name in names: + if name[:3] == 'do_': + try: + doc = getattr(self, name).__doc__ + if doc: + # Handle multi-line doc comments and format for length. + doclines = doc.splitlines() + doc = doclines[0] + if len(doc) == 0 and len(doclines) > 0: + doc = doclines[1].strip() + if len(doc) > maxlen: + doc = doc[:maxlen] + '...' + self.stdout.write('{0} - {1}\n'.format( + name[3:80-maxlen], doc)) + except AttributeError: + pass + + def do_quit(self, arg): + self.app.close() + return True + + +#============================ main ============================================ + +if __name__=="__main__": + app = openVisualizerApp.main() + cli = OpenVisualizerCli(app) + cli.cmdloop() diff --git a/software/openvisualizer/bin/openVisualizerApp/openVisualizerGui.py b/software/openvisualizer/bin/openVisualizerApp/openVisualizerGui.py new file mode 100755 index 000000000..409ffdaa3 --- /dev/null +++ b/software/openvisualizer/bin/openVisualizerApp/openVisualizerGui.py @@ -0,0 +1,193 @@ +#!/usr/bin/python +# Copyright (c) 2010-2013, Regents of the University of California. +# All rights reserved. +# +# Released under the BSD 3-Clause license as published at the link below. +# https://openwsn.atlassian.net/wiki/display/OW/License + +import sys +import os + +if __name__=="__main__": + # Update pythonpath if running in in-tree development mode + basedir = os.path.dirname(__file__) + confFile = os.path.join(basedir, "openvisualizer.conf") + if os.path.exists(confFile): + import pathHelper + pathHelper.updatePath() + +import logging +log = logging.getLogger('openVisualizerGui') + +try: + from openvisualizer.moteState import moteState +except ImportError: + # Debug failed lookup on first library import + print 'ImportError: cannot find openvisualizer.moteState module' + print 'sys.path:\n\t{0}'.format('\n\t'.join(str(p) for p in sys.path)) + +import openVisualizerApp +from openvisualizer.openUI import OpenWindow +from openvisualizer.openUI import OpenFrameState +from openvisualizer.openUI import OpenFrameButton +from openvisualizer.openUI import OpenFrameEventBus +import openvisualizer.openvisualizer_utils as u + +import Tkinter + +class MenuUpdateFrame(Tkinter.Frame): + """Updates the motes menu items with mote 16-bit IDs""" + + def setMoteStateHandler(self,ms): + self.ms = ms + + def setMenuList(self,menuList): + self.menuList = menuList + + def updateMenuLabel(self,indexToUpdate): + rawLabel = self.ms.getStateElem(moteState.moteState.ST_IDMANAGER).get16bAddr() + if rawLabel: + menuLabel = ''.join(['%02x'%b for b in rawLabel]) + self.menuList.entryconfig( + indexToUpdate, + label=menuLabel, + ) + +class OpenVisualizerGui(object): + + GUI_UPDATE_PERIOD = 500 + MENUENTRY_STATE = 'motes' + MENUENTRY_LBR = 'lbr' + MENUENTRY_EVENTBUS = 'eventBus' + + def __init__(self,app): + """Sets menu names initially to serial port ID""" + log.info('Creating OpenVisualizerGui') + + # store params + self.app = app + + # local variables + self.window = OpenWindow.OpenWindow("OpenVisualizer", self) + + #===== mote states frame + menuNames = [] + self.menuFrames = [] + for ms in self.app.moteStates: + thisFrame = MenuUpdateFrame(self.window) + thisFrame.setMoteStateHandler(ms) + frameOrganization = [ + [ + moteState.moteState.ST_ISSYNC, + moteState.moteState.ST_ASN, + moteState.moteState.ST_MYDAGRANK, + moteState.moteState.ST_KAPERIOD, + moteState.moteState.ST_OUPUTBUFFER, + moteState.moteState.ST_BACKOFF, + ], + [ + moteState.moteState.TRIGGER_DAGROOT, + moteState.moteState.ST_IDMANAGER, + ], + [ + moteState.moteState.ST_MACSTATS, + ], + [ + moteState.moteState.ST_SCHEDULE, + moteState.moteState.ST_QUEUE, + ], + [ + moteState.moteState.ST_NEIGHBORS, + ], + ] + for row in range(len(frameOrganization)): + tempRowFrame = Tkinter.Frame(thisFrame) + tempRowFrame.grid(row=row) + for column in range(len(frameOrganization[row])): + stateOrTrigger = frameOrganization[row][column] + if stateOrTrigger in moteState.moteState.ST_ALL: + tempFrameState = OpenFrameState.OpenFrameState( + guiParent = tempRowFrame, + frameName = stateOrTrigger, + row = 0, + column = column, + ) + tempFrameState.startAutoUpdate( + updatePeriod = self.GUI_UPDATE_PERIOD, + updateFunc = ms.getStateElem, + updateParams = (stateOrTrigger,), + ) + tempFrameState.show() + elif stateOrTrigger in moteState.moteState.TRIGGER_ALL: + tempFrameButton = OpenFrameButton.OpenFrameButton( + callfunction = ms.triggerAction, + callparams = (stateOrTrigger,), + guiParent = tempRowFrame, + frameName = stateOrTrigger, + buttonText = 'toggle', + row = 0, + column = column, + ) + tempFrameButton.show() + else: + raise SystemError('unexpected stateOrTrigger={0}'.format(stateOrTrigger)) + + menuNames += ['{0}'.format(ms.moteConnector.serialport)] + self.menuFrames += [thisFrame] + + # Add to menu; returns Tkinter.Menu + menuList = self.window.addMenuList( + listname = self.MENUENTRY_STATE, + names = menuNames, + frames = self.menuFrames, + ) + + for menuFrame in self.menuFrames: + menuFrame.setMenuList(menuList) + + menuList.config( + # Executes when menu displayed. + postcommand=self._updateMenuFrameNames + ) + + #===== openLbr Frame + # TODO + + #===== eventBusMonitor Frame + + thisFrame = Tkinter.Frame(self.window) + + tempFrameEventBus = OpenFrameEventBus.OpenFrameEventBus( + thisFrame, + self.app.eventBusMonitor, + row=1 + ) + tempFrameEventBus.show() + + # add to menu + self.window.addMenuItem( + name = self.MENUENTRY_EVENTBUS, + frame = thisFrame, + ) + + #======================== public ========================================== + + def start(self): + self.window.startGui() + + def close(self): + self.app.close() + + #======================== private ========================================= + + def _updateMenuFrameNames(self): + for i in range(len(self.menuFrames)): + self.menuFrames[i].updateMenuLabel(i) + + +#============================ main ============================================ + +if __name__=="__main__": + app = openVisualizerApp.main() + gui = OpenVisualizerGui(app) + gui.start() \ No newline at end of file diff --git a/software/openvisualizer/bin/openVisualizerApp/openVisualizerWeb.py b/software/openvisualizer/bin/openVisualizerApp/openVisualizerWeb.py new file mode 100644 index 000000000..cbcd2df58 --- /dev/null +++ b/software/openvisualizer/bin/openVisualizerApp/openVisualizerWeb.py @@ -0,0 +1,405 @@ +#!/usr/bin/python +# Copyright (c) 2013, Ken Bannister. +# All rights reserved. +# +# Released under the BSD 2-Clause license as published at the link below. +# http://opensource.org/licenses/BSD-2-Clause +import sys +import os + +if __name__=="__main__": + # Update pythonpath if running in in-tree development mode + basedir = os.path.dirname(__file__) + confFile = os.path.join(basedir, "openvisualizer.conf") + if os.path.exists(confFile): + import pathHelper + pathHelper.updatePath() + +import logging +log = logging.getLogger('openVisualizerWeb') + +try: + from openvisualizer.moteState import moteState +except ImportError: + # Debug failed lookup on first library import + print 'ImportError: cannot find openvisualizer.moteState module' + print 'sys.path:\n\t{0}'.format('\n\t'.join(str(p) for p in sys.path)) + +import json +import bottle +import random +import re +import threading +import signal +import functools +from bottle import view + +import openVisualizerApp +import openvisualizer.openvisualizer_utils as u +from openvisualizer.eventBus import eventBusClient +from openvisualizer.SimEngine import SimEngine +from openvisualizer.BspEmulator import VcdLogger +from openvisualizer import ovVersion + + +from pydispatch import dispatcher + +# add default parameters to all bottle templates +view = functools.partial(view, ovVersion='.'.join(list([str(v) for v in ovVersion.VERSION]))) + +class OpenVisualizerWeb(eventBusClient.eventBusClient): + ''' + Provides web UI for OpenVisualizer. Runs as a webapp in a Bottle web + server. + ''' + + def __init__(self,app,websrv): + ''' + :param app: OpenVisualizerApp + :param websrv: Web server + ''' + log.info('Creating OpenVisualizerWeb') + + # store params + self.app = app + self.engine = SimEngine.SimEngine() + self.websrv = websrv + + self._defineRoutes() + + # To find page templates + bottle.TEMPLATE_PATH.append('{0}/web_files/templates/'.format(self.app.datadir)) + + # initialize parent class + eventBusClient.eventBusClient.__init__( + self, + name = 'OpenVisualizerWeb', + registrations = [], + ) + + #======================== public ========================================== + + #======================== private ========================================= + + def _defineRoutes(self): + ''' + Matches web URL to impelementing method. Cannot use @route annotations + on the methods due to the class-based implementation. + ''' + self.websrv.route(path='/', callback=self._showMoteview) + self.websrv.route(path='/moteview', callback=self._showMoteview) + self.websrv.route(path='/moteview/:moteid', callback=self._showMoteview) + self.websrv.route(path='/motedata/:moteid', callback=self._getMoteData) + self.websrv.route(path='/toggle_root/:moteid', callback=self._toggleRoot) + self.websrv.route(path='/eventBus', callback=self._showEventBus) + self.websrv.route(path='/routing', callback=self._showRouting) + self.websrv.route(path='/routing/dag', callback=self._showDAG) + self.websrv.route(path='/eventdata', callback=self._getEventData) + self.websrv.route(path='/wiresharkDebug/:enabled', callback=self._setWiresharkDebug) + self.websrv.route(path='/gologicDebug/:enabled', callback=self._setGologicDebug) + self.websrv.route(path='/topology', callback=self._topologyPage) + self.websrv.route(path='/topology/data', callback=self._topologyData) + self.websrv.route(path='/topology/motes', method='POST', callback=self._topologyMotesUpdate) + self.websrv.route(path='/topology/connections', method='PUT', callback=self._topologyConnectionsCreate) + self.websrv.route(path='/topology/connections', method='POST', callback=self._topologyConnectionsUpdate) + self.websrv.route(path='/topology/connections', method='DELETE',callback=self._topologyConnectionsDelete) + self.websrv.route(path='/topology/route', method='GET', callback=self._topologyRouteRetrieve) + self.websrv.route(path='/static/', callback=self._serverStatic) + + @view('moteview.tmpl') + def _showMoteview(self, moteid=None): + ''' + Collects the list of motes, and the requested mote to view. + + :param moteid: 16-bit ID of mote (optional) + ''' + log.debug("moteview moteid parameter is {0}".format(moteid)); + + motelist = [] + for ms in self.app.moteStates: + addr = ms.getStateElem(moteState.moteState.ST_IDMANAGER).get16bAddr() + if addr: + motelist.append( ''.join(['%02x'%b for b in addr]) ) + else: + motelist.append(ms.moteConnector.serialport) + + tmplData = { + 'motelist' : motelist, + 'requested_mote' : moteid if moteid else 'none', + } + return tmplData + + def _serverStatic(self, filepath): + return bottle.static_file(filepath, + root='{0}/web_files/static/'.format(self.app.datadir)) + + def _toggleRoot(self, moteid): + ''' + Triggers toggle of DAGroot and bridge states, via moteState. No + real response. Page is updated when next retrieve mote data. + + :param moteid: 16-bit ID of mote + ''' + log.info('Toggle root status for moteid {0}'.format(moteid)) + ms = self.app.getMoteState(moteid) + if ms: + log.debug('Found mote {0} in moteStates'.format(moteid)) + ms.triggerAction(ms.TRIGGER_DAGROOT) + return '{"result" : "success"}' + else: + log.debug('Mote {0} not found in moteStates'.format(moteid)) + return '{"result" : "fail"}' + + def _getMoteData(self, moteid): + ''' + Collects data for the provided mote. + + :param moteid: 16-bit ID of mote + ''' + log.debug('Get JSON data for moteid {0}'.format(moteid)) + ms = self.app.getMoteState(moteid) + if ms: + log.debug('Found mote {0} in moteStates'.format(moteid)) + states = { + ms.ST_IDMANAGER : ms.getStateElem(ms.ST_IDMANAGER).toJson('data'), + ms.ST_ASN : ms.getStateElem(ms.ST_ASN).toJson('data'), + ms.ST_ISSYNC : ms.getStateElem(ms.ST_ISSYNC).toJson('data'), + ms.ST_MYDAGRANK : ms.getStateElem(ms.ST_MYDAGRANK).toJson('data'), + ms.ST_KAPERIOD : ms.getStateElem(ms.ST_KAPERIOD).toJson('data'), + ms.ST_OUPUTBUFFER : ms.getStateElem(ms.ST_OUPUTBUFFER).toJson('data'), + ms.ST_BACKOFF : ms.getStateElem(ms.ST_BACKOFF).toJson('data'), + ms.ST_MACSTATS : ms.getStateElem(ms.ST_MACSTATS).toJson('data'), + ms.ST_SCHEDULE : ms.getStateElem(ms.ST_SCHEDULE).toJson('data'), + ms.ST_QUEUE : ms.getStateElem(ms.ST_QUEUE).toJson('data'), + ms.ST_NEIGHBORS : ms.getStateElem(ms.ST_NEIGHBORS).toJson('data'), + } + else: + log.debug('Mote {0} not found in moteStates'.format(moteid)) + states = {} + return states + + def _setWiresharkDebug(self, enabled): + ''' + Selects whether eventBus must export debug packets. + + :param enabled: 'true' if enabled; any other value considered false + ''' + log.info('Enable wireshark debug : {0}'.format(enabled)) + self.app.eventBusMonitor.setWiresharkDebug(enabled == 'true') + return '{"result" : "success"}' + + def _setGologicDebug(self, enabled): + log.info('Enable GoLogic debug : {0}'.format(enabled)) + VcdLogger.VcdLogger().setEnabled(enabled == 'true') + return '{"result" : "success"}' + + @view('eventBus.tmpl') + def _showEventBus(self): + ''' + Simple page; data for the page template is identical to the data + for periodic updates of event list. + ''' + return self._getEventData() + + def _showDAG(self): + states,edges = self.app.topology.getDAG() + return { 'states': states, 'edges': edges } + + @view('routing.tmpl') + def _showRouting(self): + return {} + + @view('topology.tmpl') + def _topologyPage(self): + ''' + Retrieve the HTML/JS page. + ''' + + return {} + + def _topologyData(self): + ''' + Retrieve the topology data, in JSON format. + ''' + + # motes + motes = [] + rank = 0 + while True: + try: + mh = self.engine.getMoteHandler(rank) + id = mh.getId() + (lat,lon) = mh.getLocation() + motes += [ + { + 'id': id, + 'lat': lat, + 'lon': lon, + } + ] + rank+=1 + except IndexError: + break + + # connections + connections = self.engine.propagation.retrieveConnections() + + data = { + 'motes' : motes, + 'connections' : connections, + } + + return data + + def _topologyMotesUpdate(self): + + motesTemp = {} + for (k,v) in bottle.request.forms.items(): + m = re.match("motes\[(\w+)\]\[(\w+)\]", k) + assert m + index = int(m.group(1)) + param = m.group(2) + try: + v = int(v) + except ValueError: + try: + v = float(v) + except ValueError: + pass + if index not in motesTemp: + motesTemp[index] = {} + motesTemp[index][param] = v + + for (_,v) in motesTemp.items(): + mh = self.engine.getMoteHandlerById(v['id']) + mh.setLocation(v['lat'],v['lon']) + + def _topologyConnectionsCreate(self): + + data = bottle.request.forms + assert sorted(data.keys())==sorted(['fromMote', 'toMote']) + + fromMote = int(data['fromMote']) + toMote = int(data['toMote']) + + self.engine.propagation.createConnection(fromMote,toMote) + + def _topologyConnectionsUpdate(self): + data = bottle.request.forms + assert sorted(data.keys())==sorted(['fromMote', 'toMote', 'pdr']) + + fromMote = int(data['fromMote']) + toMote = int(data['toMote']) + pdr = float(data['pdr']) + + self.engine.propagation.updateConnection(fromMote,toMote,pdr) + + def _topologyConnectionsDelete(self): + + data = bottle.request.forms + assert sorted(data.keys())==sorted(['fromMote', 'toMote']) + + fromMote = int(data['fromMote']) + toMote = int(data['toMote']) + + self.engine.propagation.deleteConnection(fromMote,toMote) + + def _topologyRouteRetrieve(self): + + data = bottle.request.query + + assert data.keys()==['destination'] + + detination_eui = [0x14,0x15,0x92,0xcc,0x00,0x00,0x00,int(data['destination'])] + + route = self._dispatchAndGetResult( + signal = 'getSourceRoute', + data = detination_eui, + ) + + route = [r[-1] for r in route] + + data = { + 'route' : route, + } + + return data + + def _getEventData(self): + response = { + 'isDebugPkts' : 'true' if self.app.eventBusMonitor.wiresharkDebugEnabled else 'false', + 'stats' : self.app.eventBusMonitor.getStats(), + } + return response + +#============================ main ============================================ +from argparse import ArgumentParser + +def _addParserArgs(parser): + '''Adds arguments specific to web UI.''' + + parser.add_argument('-H', '--host', + dest = 'host', + default = '0.0.0.0', + action = 'store', + help = 'host address' + ) + + parser.add_argument('-p', '--port', + dest = 'port', + default = 8080, + action = 'store', + help = 'port number' + ) + +webapp = None +if __name__=="__main__": + parser = ArgumentParser() + _addParserArgs(parser) + argspace = parser.parse_known_args()[0] + + # log + log.info( + 'Initializing OpenVisualizerWeb with options: \n\t{0}'.format( + '\n '.join( + [ + 'host = {0}'.format(argspace.host), + 'port = {0}'.format(argspace.port) + ] + ) + ) + ) + + #===== start the app + app = openVisualizerApp.main(parser) + + #===== add a web interface + websrv = bottle.Bottle() + webapp = OpenVisualizerWeb(app, websrv) + + # start web interface in a separate thread + webthread = threading.Thread( + target = websrv.run, + kwargs = { + 'host' : argspace.host, + 'port' : argspace.port, + 'quiet' : not app.debug, + 'debug' : app.debug, + } + ) + webthread.start() + + #===== add a cli (minimal) interface + + banner = [] + banner += ['OpenVisualizer'] + banner += ['web interface started at {0}:{1}'.format(argspace.host,argspace.port)] + banner += ['enter \'q\' to exit'] + banner = '\n'.join(banner) + print banner + + while True: + input = raw_input('> ') + if input=='q': + print 'bye bye.' + os.kill(os.getpid(), signal.SIGTERM) \ No newline at end of file diff --git a/software/openvisualizer/bin/openVisualizerApp/openvisualizer.conf b/software/openvisualizer/bin/openVisualizerApp/openvisualizer.conf new file mode 100644 index 000000000..ec387be07 --- /dev/null +++ b/software/openvisualizer/bin/openVisualizerApp/openvisualizer.conf @@ -0,0 +1,5 @@ +# Presently, this file is used only as a placeholder. +# Configuration settings are not used. + +[web] +port = 8080 \ No newline at end of file diff --git a/software/openvisualizer/bin/openVisualizerApp/pathHelper.py b/software/openvisualizer/bin/openVisualizerApp/pathHelper.py new file mode 100644 index 000000000..7b1fcf924 --- /dev/null +++ b/software/openvisualizer/bin/openVisualizerApp/pathHelper.py @@ -0,0 +1,42 @@ +# Copyright (c) 2010-2013, Regents of the University of California. +# All rights reserved. +# +# Released under the BSD 3-Clause license as published at the link below. +# https://openwsn.atlassian.net/wiki/display/OW/License + +''' +Helper module to fix the Python path. + +There are different ways to run the OpenVisualizer: +- from SCons (e.g. "scons rungui"), in which case the project is run from the + openvisualizer/ root directory +- by double-clicking on the OpenVisualizerGui.py or OpenVisualizerCli.py files, + in which case, the program is run from the + openvisualizer\bin\openVisualizerApp directory. + +The function below ensure that, if the program is run by double-clicking, the +Python PATH is set up correctly. +''' + +import sys +import os + +def updatePath(): + ''' + This function determines whether the program is run from SCons or from the + source file. In the former case, the path is already set up correctly. In + the latter case, this function adjusts the path. + ''' + + # I'm assuming I'll have to update the path + updatePath = True + + # do NOT update if running from SCons + # TODO: this method is relatively fragile + uiFile = sys.argv[0] + if uiFile.startswith('bin'): + updatePath = False + + # update the path, if needed, to include the root openvisualizer directory + if updatePath: + sys.path.insert(0,os.path.join('..','..')) # root diff --git a/software/openvisualizer/bin/openVisualizerApp/sim_files/.gitignore b/software/openvisualizer/bin/openVisualizerApp/sim_files/.gitignore new file mode 100644 index 000000000..dc0803c2b --- /dev/null +++ b/software/openvisualizer/bin/openVisualizerApp/sim_files/.gitignore @@ -0,0 +1,4 @@ +# All sim firmware files are considered external. +*.so +*.pyd +*.h diff --git a/software/openvisualizer/bin/openVisualizerApp/trace.conf b/software/openvisualizer/bin/openVisualizerApp/trace.conf new file mode 100644 index 000000000..0a0c643d2 --- /dev/null +++ b/software/openvisualizer/bin/openVisualizerApp/trace.conf @@ -0,0 +1,46 @@ +# Note Expects 'logDir' passed in with location for file output. + +#============================ formatters ====================================== + +[formatters] +keys=std,console + +[formatter_std] +format=%(asctime)s [%(name)s:%(levelname)s] %(message)s +datefmt= + +[formatter_console] +format=%(asctime)s %(levelname)s %(message)s +datefmt=%H:%M:%S + +#============================ handlers ======================================== + +[handlers] +keys=std,console + +[handler_std] +class=handlers.RotatingFileHandler +# args: filename, open mode, max file size, backup file count +args=('%(logDir)s/tracer.log', 'a', 20000000, 5) +formatter=std + +[handler_console] +class=StreamHandler +args=() +formatter=console + +#============================ loggers ========================================= + +[loggers] +keys=root,OVtracer + +[logger_root] +level=ERROR +handlers=std + +[logger_OVtracer] +level=INFO +handlers=std +propagate=0 +qualname=OVtracer + diff --git a/software/openvisualizer/bin/openVisualizerApp/web_files/static/css/bootstrap.css b/software/openvisualizer/bin/openVisualizerApp/web_files/static/css/bootstrap.css new file mode 100755 index 000000000..14cc1f48e --- /dev/null +++ b/software/openvisualizer/bin/openVisualizerApp/web_files/static/css/bootstrap.css @@ -0,0 +1,5831 @@ +/*! + * Bootstrap v3.1.0 (http://getbootstrap.com) + * Copyright 2011-2014 Twitter, Inc. + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) + */ + +/*! normalize.css v3.0.0 | MIT License | git.io/normalize */ +html { + font-family: sans-serif; + -webkit-text-size-adjust: 100%; + -ms-text-size-adjust: 100%; +} +body { + margin: 0; +} +article, +aside, +details, +figcaption, +figure, +footer, +header, +hgroup, +main, +nav, +section, +summary { + display: block; +} +audio, +canvas, +progress, +video { + display: inline-block; + vertical-align: baseline; +} +audio:not([controls]) { + display: none; + height: 0; +} +[hidden], +template { + display: none; +} +a { + background: transparent; +} +a:active, +a:hover { + outline: 0; +} +abbr[title] { + border-bottom: 1px dotted; +} +b, +strong { + font-weight: bold; +} +dfn { + font-style: italic; +} +h1 { + margin: .67em 0; + font-size: 2em; +} +mark { + color: #000; + background: #ff0; +} +small { + font-size: 80%; +} +sub, +sup { + position: relative; + font-size: 75%; + line-height: 0; + vertical-align: baseline; +} +sup { + top: -.5em; +} +sub { + bottom: -.25em; +} +img { + border: 0; +} +svg:not(:root) { + overflow: hidden; +} +figure { + margin: 1em 40px; +} +hr { + height: 0; + -moz-box-sizing: content-box; + box-sizing: content-box; +} +pre { + overflow: auto; +} +code, +kbd, +pre, +samp { + font-family: monospace, monospace; + font-size: 1em; +} +button, +input, +optgroup, +select, +textarea { + margin: 0; + font: inherit; + color: inherit; +} +button { + overflow: visible; +} +button, +select { + text-transform: none; +} +button, +html input[type="button"], +input[type="reset"], +input[type="submit"] { + -webkit-appearance: button; + cursor: pointer; +} +button[disabled], +html input[disabled] { + cursor: default; +} +button::-moz-focus-inner, +input::-moz-focus-inner { + padding: 0; + border: 0; +} +input { + line-height: normal; +} +input[type="checkbox"], +input[type="radio"] { + box-sizing: border-box; + padding: 0; +} +input[type="number"]::-webkit-inner-spin-button, +input[type="number"]::-webkit-outer-spin-button { + height: auto; +} +input[type="search"] { + -webkit-box-sizing: content-box; + -moz-box-sizing: content-box; + box-sizing: content-box; + -webkit-appearance: textfield; +} +input[type="search"]::-webkit-search-cancel-button, +input[type="search"]::-webkit-search-decoration { + -webkit-appearance: none; +} +fieldset { + padding: .35em .625em .75em; + margin: 0 2px; + border: 1px solid #c0c0c0; +} +legend { + padding: 0; + border: 0; +} +textarea { + overflow: auto; +} +optgroup { + font-weight: bold; +} +table { + border-spacing: 0; + border-collapse: collapse; +} +td, +th { + padding: 0; +} +@media print { + * { + color: #000 !important; + text-shadow: none !important; + background: transparent !important; + box-shadow: none !important; + } + a, + a:visited { + text-decoration: underline; + } + a[href]:after { + content: " (" attr(href) ")"; + } + abbr[title]:after { + content: " (" attr(title) ")"; + } + a[href^="javascript:"]:after, + a[href^="#"]:after { + content: ""; + } + pre, + blockquote { + border: 1px solid #999; + + page-break-inside: avoid; + } + thead { + display: table-header-group; + } + tr, + img { + page-break-inside: avoid; + } + img { + max-width: 100% !important; + } + p, + h2, + h3 { + orphans: 3; + widows: 3; + } + h2, + h3 { + page-break-after: avoid; + } + select { + background: #fff !important; + } + .navbar { + display: none; + } + .table td, + .table th { + background-color: #fff !important; + } + .btn > .caret, + .dropup > .btn > .caret { + border-top-color: #000 !important; + } + .label { + border: 1px solid #000; + } + .table { + border-collapse: collapse !important; + } + .table-bordered th, + .table-bordered td { + border: 1px solid #ddd !important; + } +} +* { + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; +} +*:before, +*:after { + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; +} +html { + font-size: 62.5%; + + -webkit-tap-highlight-color: rgba(0, 0, 0, 0); +} +body { + font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; + font-size: 14px; + line-height: 1.428571429; + color: #333; + background-color: #fff; +} +input, +button, +select, +textarea { + font-family: inherit; + font-size: inherit; + line-height: inherit; +} +a { + color: #428bca; + text-decoration: none; +} +a:hover, +a:focus { + color: #2a6496; + text-decoration: underline; +} +a:focus { + outline: thin dotted; + outline: 5px auto -webkit-focus-ring-color; + outline-offset: -2px; +} +figure { + margin: 0; +} +img { + vertical-align: middle; +} +.img-responsive { + display: block; + max-width: 100%; + height: auto; +} +.img-rounded { + border-radius: 6px; +} +.img-thumbnail { + display: inline-block; + max-width: 100%; + height: auto; + padding: 4px; + line-height: 1.428571429; + background-color: #fff; + border: 1px solid #ddd; + border-radius: 4px; + -webkit-transition: all .2s ease-in-out; + transition: all .2s ease-in-out; +} +.img-circle { + border-radius: 50%; +} +hr { + margin-top: 20px; + margin-bottom: 20px; + border: 0; + border-top: 1px solid #eee; +} +.sr-only { + position: absolute; + width: 1px; + height: 1px; + padding: 0; + margin: -1px; + overflow: hidden; + clip: rect(0, 0, 0, 0); + border: 0; +} +h1, +h2, +h3, +h4, +h5, +h6, +.h1, +.h2, +.h3, +.h4, +.h5, +.h6 { + font-family: inherit; + font-weight: 500; + line-height: 1.1; + color: inherit; +} +h1 small, +h2 small, +h3 small, +h4 small, +h5 small, +h6 small, +.h1 small, +.h2 small, +.h3 small, +.h4 small, +.h5 small, +.h6 small, +h1 .small, +h2 .small, +h3 .small, +h4 .small, +h5 .small, +h6 .small, +.h1 .small, +.h2 .small, +.h3 .small, +.h4 .small, +.h5 .small, +.h6 .small { + font-weight: normal; + line-height: 1; + color: #999; +} +h1, +.h1, +h2, +.h2, +h3, +.h3 { + margin-top: 20px; + margin-bottom: 10px; +} +h1 small, +.h1 small, +h2 small, +.h2 small, +h3 small, +.h3 small, +h1 .small, +.h1 .small, +h2 .small, +.h2 .small, +h3 .small, +.h3 .small { + font-size: 65%; +} +h4, +.h4, +h5, +.h5, +h6, +.h6 { + margin-top: 10px; + margin-bottom: 10px; +} +h4 small, +.h4 small, +h5 small, +.h5 small, +h6 small, +.h6 small, +h4 .small, +.h4 .small, +h5 .small, +.h5 .small, +h6 .small, +.h6 .small { + font-size: 75%; +} +h1, +.h1 { + font-size: 36px; +} +h2, +.h2 { + font-size: 30px; +} +h3, +.h3 { + font-size: 24px; +} +h4, +.h4 { + font-size: 18px; +} +h5, +.h5 { + font-size: 14px; +} +h6, +.h6 { + font-size: 12px; +} +p { + margin: 0 0 10px; +} +.lead { + margin-bottom: 20px; + font-size: 16px; + font-weight: 200; + line-height: 1.4; +} +@media (min-width: 768px) { + .lead { + font-size: 21px; + } +} +small, +.small { + font-size: 85%; +} +cite { + font-style: normal; +} +.text-left { + text-align: left; +} +.text-right { + text-align: right; +} +.text-center { + text-align: center; +} +.text-justify { + text-align: justify; +} +.text-muted { + color: #999; +} +.text-primary { + color: #428bca; +} +a.text-primary:hover { + color: #3071a9; +} +.text-success { + color: #3c763d; +} +a.text-success:hover { + color: #2b542c; +} +.text-info { + color: #31708f; +} +a.text-info:hover { + color: #245269; +} +.text-warning { + color: #8a6d3b; +} +a.text-warning:hover { + color: #66512c; +} +.text-danger { + color: #a94442; +} +a.text-danger:hover { + color: #843534; +} +.bg-primary { + color: #fff; + background-color: #428bca; +} +a.bg-primary:hover { + background-color: #3071a9; +} +.bg-success { + background-color: #dff0d8; +} +a.bg-success:hover { + background-color: #c1e2b3; +} +.bg-info { + background-color: #d9edf7; +} +a.bg-info:hover { + background-color: #afd9ee; +} +.bg-warning { + background-color: #fcf8e3; +} +a.bg-warning:hover { + background-color: #f7ecb5; +} +.bg-danger { + background-color: #f2dede; +} +a.bg-danger:hover { + background-color: #e4b9b9; +} +.page-header { + padding-bottom: 9px; + margin: 40px 0 20px; + border-bottom: 1px solid #eee; +} +ul, +ol { + margin-top: 0; + margin-bottom: 10px; +} +ul ul, +ol ul, +ul ol, +ol ol { + margin-bottom: 0; +} +.list-unstyled { + padding-left: 0; + list-style: none; +} +.list-inline { + padding-left: 0; + list-style: none; +} +.list-inline > li { + display: inline-block; + padding-right: 5px; + padding-left: 5px; +} +.list-inline > li:first-child { + padding-left: 0; +} +dl { + margin-top: 0; + margin-bottom: 20px; +} +dt, +dd { + line-height: 1.428571429; +} +dt { + font-weight: bold; +} +dd { + margin-left: 0; +} +@media (min-width: 768px) { + .dl-horizontal dt { + float: left; + width: 160px; + overflow: hidden; + clear: left; + text-align: right; + text-overflow: ellipsis; + white-space: nowrap; + } + .dl-horizontal dd { + margin-left: 180px; + } +} +abbr[title], +abbr[data-original-title] { + cursor: help; + border-bottom: 1px dotted #999; +} +.initialism { + font-size: 90%; + text-transform: uppercase; +} +blockquote { + padding: 10px 20px; + margin: 0 0 20px; + font-size: 17.5px; + border-left: 5px solid #eee; +} +blockquote p:last-child, +blockquote ul:last-child, +blockquote ol:last-child { + margin-bottom: 0; +} +blockquote footer, +blockquote small, +blockquote .small { + display: block; + font-size: 80%; + line-height: 1.428571429; + color: #999; +} +blockquote footer:before, +blockquote small:before, +blockquote .small:before { + content: '\2014 \00A0'; +} +.blockquote-reverse, +blockquote.pull-right { + padding-right: 15px; + padding-left: 0; + text-align: right; + border-right: 5px solid #eee; + border-left: 0; +} +.blockquote-reverse footer:before, +blockquote.pull-right footer:before, +.blockquote-reverse small:before, +blockquote.pull-right small:before, +.blockquote-reverse .small:before, +blockquote.pull-right .small:before { + content: ''; +} +.blockquote-reverse footer:after, +blockquote.pull-right footer:after, +.blockquote-reverse small:after, +blockquote.pull-right small:after, +.blockquote-reverse .small:after, +blockquote.pull-right .small:after { + content: '\00A0 \2014'; +} +blockquote:before, +blockquote:after { + content: ""; +} +address { + margin-bottom: 20px; + font-style: normal; + line-height: 1.428571429; +} +code, +kbd, +pre, +samp { + font-family: Menlo, Monaco, Consolas, "Courier New", monospace; +} +code { + padding: 2px 4px; + font-size: 90%; + color: #c7254e; + white-space: nowrap; + background-color: #f9f2f4; + border-radius: 4px; +} +kbd { + padding: 2px 4px; + font-size: 90%; + color: #fff; + background-color: #333; + border-radius: 3px; + box-shadow: inset 0 -1px 0 rgba(0, 0, 0, .25); +} +pre { + display: block; + padding: 9.5px; + margin: 0 0 10px; + font-size: 13px; + line-height: 1.428571429; + color: #333; + word-break: break-all; + word-wrap: break-word; + background-color: #f5f5f5; + border: 1px solid #ccc; + border-radius: 4px; +} +pre code { + padding: 0; + font-size: inherit; + color: inherit; + white-space: pre-wrap; + background-color: transparent; + border-radius: 0; +} +.pre-scrollable { + max-height: 340px; + overflow-y: scroll; +} +.container { + padding-right: 15px; + padding-left: 15px; + margin-right: auto; + margin-left: auto; +} +@media (min-width: 768px) { + .container { + width: 750px; + } +} +@media (min-width: 992px) { + .container { + width: 970px; + } +} +@media (min-width: 1200px) { + .container { + width: 1170px; + } +} +.container-fluid { + padding-right: 15px; + padding-left: 15px; + margin-right: auto; + margin-left: auto; +} +.row { + margin-right: -15px; + margin-left: -15px; +} +.col-xs-1, .col-sm-1, .col-md-1, .col-lg-1, .col-xs-2, .col-sm-2, .col-md-2, .col-lg-2, .col-xs-3, .col-sm-3, .col-md-3, .col-lg-3, .col-xs-4, .col-sm-4, .col-md-4, .col-lg-4, .col-xs-5, .col-sm-5, .col-md-5, .col-lg-5, .col-xs-6, .col-sm-6, .col-md-6, .col-lg-6, .col-xs-7, .col-sm-7, .col-md-7, .col-lg-7, .col-xs-8, .col-sm-8, .col-md-8, .col-lg-8, .col-xs-9, .col-sm-9, .col-md-9, .col-lg-9, .col-xs-10, .col-sm-10, .col-md-10, .col-lg-10, .col-xs-11, .col-sm-11, .col-md-11, .col-lg-11, .col-xs-12, .col-sm-12, .col-md-12, .col-lg-12 { + position: relative; + min-height: 1px; + padding-right: 15px; + padding-left: 15px; +} +.col-xs-1, .col-xs-2, .col-xs-3, .col-xs-4, .col-xs-5, .col-xs-6, .col-xs-7, .col-xs-8, .col-xs-9, .col-xs-10, .col-xs-11, .col-xs-12 { + float: left; +} +.col-xs-12 { + width: 100%; +} +.col-xs-11 { + width: 91.66666666666666%; +} +.col-xs-10 { + width: 83.33333333333334%; +} +.col-xs-9 { + width: 75%; +} +.col-xs-8 { + width: 66.66666666666666%; +} +.col-xs-7 { + width: 58.333333333333336%; +} +.col-xs-6 { + width: 50%; +} +.col-xs-5 { + width: 41.66666666666667%; +} +.col-xs-4 { + width: 33.33333333333333%; +} +.col-xs-3 { + width: 25%; +} +.col-xs-2 { + width: 16.666666666666664%; +} +.col-xs-1 { + width: 8.333333333333332%; +} +.col-xs-pull-12 { + right: 100%; +} +.col-xs-pull-11 { + right: 91.66666666666666%; +} +.col-xs-pull-10 { + right: 83.33333333333334%; +} +.col-xs-pull-9 { + right: 75%; +} +.col-xs-pull-8 { + right: 66.66666666666666%; +} +.col-xs-pull-7 { + right: 58.333333333333336%; +} +.col-xs-pull-6 { + right: 50%; +} +.col-xs-pull-5 { + right: 41.66666666666667%; +} +.col-xs-pull-4 { + right: 33.33333333333333%; +} +.col-xs-pull-3 { + right: 25%; +} +.col-xs-pull-2 { + right: 16.666666666666664%; +} +.col-xs-pull-1 { + right: 8.333333333333332%; +} +.col-xs-pull-0 { + right: 0; +} +.col-xs-push-12 { + left: 100%; +} +.col-xs-push-11 { + left: 91.66666666666666%; +} +.col-xs-push-10 { + left: 83.33333333333334%; +} +.col-xs-push-9 { + left: 75%; +} +.col-xs-push-8 { + left: 66.66666666666666%; +} +.col-xs-push-7 { + left: 58.333333333333336%; +} +.col-xs-push-6 { + left: 50%; +} +.col-xs-push-5 { + left: 41.66666666666667%; +} +.col-xs-push-4 { + left: 33.33333333333333%; +} +.col-xs-push-3 { + left: 25%; +} +.col-xs-push-2 { + left: 16.666666666666664%; +} +.col-xs-push-1 { + left: 8.333333333333332%; +} +.col-xs-push-0 { + left: 0; +} +.col-xs-offset-12 { + margin-left: 100%; +} +.col-xs-offset-11 { + margin-left: 91.66666666666666%; +} +.col-xs-offset-10 { + margin-left: 83.33333333333334%; +} +.col-xs-offset-9 { + margin-left: 75%; +} +.col-xs-offset-8 { + margin-left: 66.66666666666666%; +} +.col-xs-offset-7 { + margin-left: 58.333333333333336%; +} +.col-xs-offset-6 { + margin-left: 50%; +} +.col-xs-offset-5 { + margin-left: 41.66666666666667%; +} +.col-xs-offset-4 { + margin-left: 33.33333333333333%; +} +.col-xs-offset-3 { + margin-left: 25%; +} +.col-xs-offset-2 { + margin-left: 16.666666666666664%; +} +.col-xs-offset-1 { + margin-left: 8.333333333333332%; +} +.col-xs-offset-0 { + margin-left: 0; +} +@media (min-width: 768px) { + .col-sm-1, .col-sm-2, .col-sm-3, .col-sm-4, .col-sm-5, .col-sm-6, .col-sm-7, .col-sm-8, .col-sm-9, .col-sm-10, .col-sm-11, .col-sm-12 { + float: left; + } + .col-sm-12 { + width: 100%; + } + .col-sm-11 { + width: 91.66666666666666%; + } + .col-sm-10 { + width: 83.33333333333334%; + } + .col-sm-9 { + width: 75%; + } + .col-sm-8 { + width: 66.66666666666666%; + } + .col-sm-7 { + width: 58.333333333333336%; + } + .col-sm-6 { + width: 50%; + } + .col-sm-5 { + width: 41.66666666666667%; + } + .col-sm-4 { + width: 33.33333333333333%; + } + .col-sm-3 { + width: 25%; + } + .col-sm-2 { + width: 16.666666666666664%; + } + .col-sm-1 { + width: 8.333333333333332%; + } + .col-sm-pull-12 { + right: 100%; + } + .col-sm-pull-11 { + right: 91.66666666666666%; + } + .col-sm-pull-10 { + right: 83.33333333333334%; + } + .col-sm-pull-9 { + right: 75%; + } + .col-sm-pull-8 { + right: 66.66666666666666%; + } + .col-sm-pull-7 { + right: 58.333333333333336%; + } + .col-sm-pull-6 { + right: 50%; + } + .col-sm-pull-5 { + right: 41.66666666666667%; + } + .col-sm-pull-4 { + right: 33.33333333333333%; + } + .col-sm-pull-3 { + right: 25%; + } + .col-sm-pull-2 { + right: 16.666666666666664%; + } + .col-sm-pull-1 { + right: 8.333333333333332%; + } + .col-sm-pull-0 { + right: 0; + } + .col-sm-push-12 { + left: 100%; + } + .col-sm-push-11 { + left: 91.66666666666666%; + } + .col-sm-push-10 { + left: 83.33333333333334%; + } + .col-sm-push-9 { + left: 75%; + } + .col-sm-push-8 { + left: 66.66666666666666%; + } + .col-sm-push-7 { + left: 58.333333333333336%; + } + .col-sm-push-6 { + left: 50%; + } + .col-sm-push-5 { + left: 41.66666666666667%; + } + .col-sm-push-4 { + left: 33.33333333333333%; + } + .col-sm-push-3 { + left: 25%; + } + .col-sm-push-2 { + left: 16.666666666666664%; + } + .col-sm-push-1 { + left: 8.333333333333332%; + } + .col-sm-push-0 { + left: 0; + } + .col-sm-offset-12 { + margin-left: 100%; + } + .col-sm-offset-11 { + margin-left: 91.66666666666666%; + } + .col-sm-offset-10 { + margin-left: 83.33333333333334%; + } + .col-sm-offset-9 { + margin-left: 75%; + } + .col-sm-offset-8 { + margin-left: 66.66666666666666%; + } + .col-sm-offset-7 { + margin-left: 58.333333333333336%; + } + .col-sm-offset-6 { + margin-left: 50%; + } + .col-sm-offset-5 { + margin-left: 41.66666666666667%; + } + .col-sm-offset-4 { + margin-left: 33.33333333333333%; + } + .col-sm-offset-3 { + margin-left: 25%; + } + .col-sm-offset-2 { + margin-left: 16.666666666666664%; + } + .col-sm-offset-1 { + margin-left: 8.333333333333332%; + } + .col-sm-offset-0 { + margin-left: 0; + } +} +@media (min-width: 992px) { + .col-md-1, .col-md-2, .col-md-3, .col-md-4, .col-md-5, .col-md-6, .col-md-7, .col-md-8, .col-md-9, .col-md-10, .col-md-11, .col-md-12 { + float: left; + } + .col-md-12 { + width: 100%; + } + .col-md-11 { + width: 91.66666666666666%; + } + .col-md-10 { + width: 83.33333333333334%; + } + .col-md-9 { + width: 75%; + } + .col-md-8 { + width: 66.66666666666666%; + } + .col-md-7 { + width: 58.333333333333336%; + } + .col-md-6 { + width: 50%; + } + .col-md-5 { + width: 41.66666666666667%; + } + .col-md-4 { + width: 33.33333333333333%; + } + .col-md-3 { + width: 25%; + } + .col-md-2 { + width: 16.666666666666664%; + } + .col-md-1 { + width: 8.333333333333332%; + } + .col-md-pull-12 { + right: 100%; + } + .col-md-pull-11 { + right: 91.66666666666666%; + } + .col-md-pull-10 { + right: 83.33333333333334%; + } + .col-md-pull-9 { + right: 75%; + } + .col-md-pull-8 { + right: 66.66666666666666%; + } + .col-md-pull-7 { + right: 58.333333333333336%; + } + .col-md-pull-6 { + right: 50%; + } + .col-md-pull-5 { + right: 41.66666666666667%; + } + .col-md-pull-4 { + right: 33.33333333333333%; + } + .col-md-pull-3 { + right: 25%; + } + .col-md-pull-2 { + right: 16.666666666666664%; + } + .col-md-pull-1 { + right: 8.333333333333332%; + } + .col-md-pull-0 { + right: 0; + } + .col-md-push-12 { + left: 100%; + } + .col-md-push-11 { + left: 91.66666666666666%; + } + .col-md-push-10 { + left: 83.33333333333334%; + } + .col-md-push-9 { + left: 75%; + } + .col-md-push-8 { + left: 66.66666666666666%; + } + .col-md-push-7 { + left: 58.333333333333336%; + } + .col-md-push-6 { + left: 50%; + } + .col-md-push-5 { + left: 41.66666666666667%; + } + .col-md-push-4 { + left: 33.33333333333333%; + } + .col-md-push-3 { + left: 25%; + } + .col-md-push-2 { + left: 16.666666666666664%; + } + .col-md-push-1 { + left: 8.333333333333332%; + } + .col-md-push-0 { + left: 0; + } + .col-md-offset-12 { + margin-left: 100%; + } + .col-md-offset-11 { + margin-left: 91.66666666666666%; + } + .col-md-offset-10 { + margin-left: 83.33333333333334%; + } + .col-md-offset-9 { + margin-left: 75%; + } + .col-md-offset-8 { + margin-left: 66.66666666666666%; + } + .col-md-offset-7 { + margin-left: 58.333333333333336%; + } + .col-md-offset-6 { + margin-left: 50%; + } + .col-md-offset-5 { + margin-left: 41.66666666666667%; + } + .col-md-offset-4 { + margin-left: 33.33333333333333%; + } + .col-md-offset-3 { + margin-left: 25%; + } + .col-md-offset-2 { + margin-left: 16.666666666666664%; + } + .col-md-offset-1 { + margin-left: 8.333333333333332%; + } + .col-md-offset-0 { + margin-left: 0; + } +} +@media (min-width: 1200px) { + .col-lg-1, .col-lg-2, .col-lg-3, .col-lg-4, .col-lg-5, .col-lg-6, .col-lg-7, .col-lg-8, .col-lg-9, .col-lg-10, .col-lg-11, .col-lg-12 { + float: left; + } + .col-lg-12 { + width: 100%; + } + .col-lg-11 { + width: 91.66666666666666%; + } + .col-lg-10 { + width: 83.33333333333334%; + } + .col-lg-9 { + width: 75%; + } + .col-lg-8 { + width: 66.66666666666666%; + } + .col-lg-7 { + width: 58.333333333333336%; + } + .col-lg-6 { + width: 50%; + } + .col-lg-5 { + width: 41.66666666666667%; + } + .col-lg-4 { + width: 33.33333333333333%; + } + .col-lg-3 { + width: 25%; + } + .col-lg-2 { + width: 16.666666666666664%; + } + .col-lg-1 { + width: 8.333333333333332%; + } + .col-lg-pull-12 { + right: 100%; + } + .col-lg-pull-11 { + right: 91.66666666666666%; + } + .col-lg-pull-10 { + right: 83.33333333333334%; + } + .col-lg-pull-9 { + right: 75%; + } + .col-lg-pull-8 { + right: 66.66666666666666%; + } + .col-lg-pull-7 { + right: 58.333333333333336%; + } + .col-lg-pull-6 { + right: 50%; + } + .col-lg-pull-5 { + right: 41.66666666666667%; + } + .col-lg-pull-4 { + right: 33.33333333333333%; + } + .col-lg-pull-3 { + right: 25%; + } + .col-lg-pull-2 { + right: 16.666666666666664%; + } + .col-lg-pull-1 { + right: 8.333333333333332%; + } + .col-lg-pull-0 { + right: 0; + } + .col-lg-push-12 { + left: 100%; + } + .col-lg-push-11 { + left: 91.66666666666666%; + } + .col-lg-push-10 { + left: 83.33333333333334%; + } + .col-lg-push-9 { + left: 75%; + } + .col-lg-push-8 { + left: 66.66666666666666%; + } + .col-lg-push-7 { + left: 58.333333333333336%; + } + .col-lg-push-6 { + left: 50%; + } + .col-lg-push-5 { + left: 41.66666666666667%; + } + .col-lg-push-4 { + left: 33.33333333333333%; + } + .col-lg-push-3 { + left: 25%; + } + .col-lg-push-2 { + left: 16.666666666666664%; + } + .col-lg-push-1 { + left: 8.333333333333332%; + } + .col-lg-push-0 { + left: 0; + } + .col-lg-offset-12 { + margin-left: 100%; + } + .col-lg-offset-11 { + margin-left: 91.66666666666666%; + } + .col-lg-offset-10 { + margin-left: 83.33333333333334%; + } + .col-lg-offset-9 { + margin-left: 75%; + } + .col-lg-offset-8 { + margin-left: 66.66666666666666%; + } + .col-lg-offset-7 { + margin-left: 58.333333333333336%; + } + .col-lg-offset-6 { + margin-left: 50%; + } + .col-lg-offset-5 { + margin-left: 41.66666666666667%; + } + .col-lg-offset-4 { + margin-left: 33.33333333333333%; + } + .col-lg-offset-3 { + margin-left: 25%; + } + .col-lg-offset-2 { + margin-left: 16.666666666666664%; + } + .col-lg-offset-1 { + margin-left: 8.333333333333332%; + } + .col-lg-offset-0 { + margin-left: 0; + } +} +table { + max-width: 100%; + background-color: transparent; +} +th { + text-align: left; +} +.table { + width: 100%; + margin-bottom: 20px; +} +.table > thead > tr > th, +.table > tbody > tr > th, +.table > tfoot > tr > th, +.table > thead > tr > td, +.table > tbody > tr > td, +.table > tfoot > tr > td { + padding: 8px; + line-height: 1.428571429; + vertical-align: top; + border-top: 1px solid #ddd; +} +.table > thead > tr > th { + vertical-align: bottom; + border-bottom: 2px solid #ddd; +} +.table > caption + thead > tr:first-child > th, +.table > colgroup + thead > tr:first-child > th, +.table > thead:first-child > tr:first-child > th, +.table > caption + thead > tr:first-child > td, +.table > colgroup + thead > tr:first-child > td, +.table > thead:first-child > tr:first-child > td { + border-top: 0; +} +.table > tbody + tbody { + border-top: 2px solid #ddd; +} +.table .table { + background-color: #fff; +} +.table-condensed > thead > tr > th, +.table-condensed > tbody > tr > th, +.table-condensed > tfoot > tr > th, +.table-condensed > thead > tr > td, +.table-condensed > tbody > tr > td, +.table-condensed > tfoot > tr > td { + padding: 5px; +} +.table-bordered { + border: 1px solid #ddd; +} +.table-bordered > thead > tr > th, +.table-bordered > tbody > tr > th, +.table-bordered > tfoot > tr > th, +.table-bordered > thead > tr > td, +.table-bordered > tbody > tr > td, +.table-bordered > tfoot > tr > td { + border: 1px solid #ddd; +} +.table-bordered > thead > tr > th, +.table-bordered > thead > tr > td { + border-bottom-width: 2px; +} +.table-striped > tbody > tr:nth-child(odd) > td, +.table-striped > tbody > tr:nth-child(odd) > th { + background-color: #f9f9f9; +} +.table-hover > tbody > tr:hover > td, +.table-hover > tbody > tr:hover > th { + background-color: #f5f5f5; +} +table col[class*="col-"] { + position: static; + display: table-column; + float: none; +} +table td[class*="col-"], +table th[class*="col-"] { + position: static; + display: table-cell; + float: none; +} +.table > thead > tr > td.active, +.table > tbody > tr > td.active, +.table > tfoot > tr > td.active, +.table > thead > tr > th.active, +.table > tbody > tr > th.active, +.table > tfoot > tr > th.active, +.table > thead > tr.active > td, +.table > tbody > tr.active > td, +.table > tfoot > tr.active > td, +.table > thead > tr.active > th, +.table > tbody > tr.active > th, +.table > tfoot > tr.active > th { + background-color: #f5f5f5; +} +.table-hover > tbody > tr > td.active:hover, +.table-hover > tbody > tr > th.active:hover, +.table-hover > tbody > tr.active:hover > td, +.table-hover > tbody > tr.active:hover > th { + background-color: #e8e8e8; +} +.table > thead > tr > td.success, +.table > tbody > tr > td.success, +.table > tfoot > tr > td.success, +.table > thead > tr > th.success, +.table > tbody > tr > th.success, +.table > tfoot > tr > th.success, +.table > thead > tr.success > td, +.table > tbody > tr.success > td, +.table > tfoot > tr.success > td, +.table > thead > tr.success > th, +.table > tbody > tr.success > th, +.table > tfoot > tr.success > th { + background-color: #dff0d8; +} +.table-hover > tbody > tr > td.success:hover, +.table-hover > tbody > tr > th.success:hover, +.table-hover > tbody > tr.success:hover > td, +.table-hover > tbody > tr.success:hover > th { + background-color: #d0e9c6; +} +.table > thead > tr > td.info, +.table > tbody > tr > td.info, +.table > tfoot > tr > td.info, +.table > thead > tr > th.info, +.table > tbody > tr > th.info, +.table > tfoot > tr > th.info, +.table > thead > tr.info > td, +.table > tbody > tr.info > td, +.table > tfoot > tr.info > td, +.table > thead > tr.info > th, +.table > tbody > tr.info > th, +.table > tfoot > tr.info > th { + background-color: #d9edf7; +} +.table-hover > tbody > tr > td.info:hover, +.table-hover > tbody > tr > th.info:hover, +.table-hover > tbody > tr.info:hover > td, +.table-hover > tbody > tr.info:hover > th { + background-color: #c4e3f3; +} +.table > thead > tr > td.warning, +.table > tbody > tr > td.warning, +.table > tfoot > tr > td.warning, +.table > thead > tr > th.warning, +.table > tbody > tr > th.warning, +.table > tfoot > tr > th.warning, +.table > thead > tr.warning > td, +.table > tbody > tr.warning > td, +.table > tfoot > tr.warning > td, +.table > thead > tr.warning > th, +.table > tbody > tr.warning > th, +.table > tfoot > tr.warning > th { + background-color: #fcf8e3; +} +.table-hover > tbody > tr > td.warning:hover, +.table-hover > tbody > tr > th.warning:hover, +.table-hover > tbody > tr.warning:hover > td, +.table-hover > tbody > tr.warning:hover > th { + background-color: #faf2cc; +} +.table > thead > tr > td.danger, +.table > tbody > tr > td.danger, +.table > tfoot > tr > td.danger, +.table > thead > tr > th.danger, +.table > tbody > tr > th.danger, +.table > tfoot > tr > th.danger, +.table > thead > tr.danger > td, +.table > tbody > tr.danger > td, +.table > tfoot > tr.danger > td, +.table > thead > tr.danger > th, +.table > tbody > tr.danger > th, +.table > tfoot > tr.danger > th { + background-color: #f2dede; +} +.table-hover > tbody > tr > td.danger:hover, +.table-hover > tbody > tr > th.danger:hover, +.table-hover > tbody > tr.danger:hover > td, +.table-hover > tbody > tr.danger:hover > th { + background-color: #ebcccc; +} +@media (max-width: 767px) { + .table-responsive { + width: 100%; + margin-bottom: 15px; + overflow-x: scroll; + overflow-y: hidden; + -webkit-overflow-scrolling: touch; + -ms-overflow-style: -ms-autohiding-scrollbar; + border: 1px solid #ddd; + } + .table-responsive > .table { + margin-bottom: 0; + } + .table-responsive > .table > thead > tr > th, + .table-responsive > .table > tbody > tr > th, + .table-responsive > .table > tfoot > tr > th, + .table-responsive > .table > thead > tr > td, + .table-responsive > .table > tbody > tr > td, + .table-responsive > .table > tfoot > tr > td { + white-space: nowrap; + } + .table-responsive > .table-bordered { + border: 0; + } + .table-responsive > .table-bordered > thead > tr > th:first-child, + .table-responsive > .table-bordered > tbody > tr > th:first-child, + .table-responsive > .table-bordered > tfoot > tr > th:first-child, + .table-responsive > .table-bordered > thead > tr > td:first-child, + .table-responsive > .table-bordered > tbody > tr > td:first-child, + .table-responsive > .table-bordered > tfoot > tr > td:first-child { + border-left: 0; + } + .table-responsive > .table-bordered > thead > tr > th:last-child, + .table-responsive > .table-bordered > tbody > tr > th:last-child, + .table-responsive > .table-bordered > tfoot > tr > th:last-child, + .table-responsive > .table-bordered > thead > tr > td:last-child, + .table-responsive > .table-bordered > tbody > tr > td:last-child, + .table-responsive > .table-bordered > tfoot > tr > td:last-child { + border-right: 0; + } + .table-responsive > .table-bordered > tbody > tr:last-child > th, + .table-responsive > .table-bordered > tfoot > tr:last-child > th, + .table-responsive > .table-bordered > tbody > tr:last-child > td, + .table-responsive > .table-bordered > tfoot > tr:last-child > td { + border-bottom: 0; + } +} +fieldset { + min-width: 0; + padding: 0; + margin: 0; + border: 0; +} +legend { + display: block; + width: 100%; + padding: 0; + margin-bottom: 20px; + font-size: 21px; + line-height: inherit; + color: #333; + border: 0; + border-bottom: 1px solid #e5e5e5; +} +label { + display: inline-block; + margin-bottom: 5px; + font-weight: bold; +} +input[type="search"] { + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; +} +input[type="radio"], +input[type="checkbox"] { + margin: 4px 0 0; + margin-top: 1px \9; + /* IE8-9 */ + line-height: normal; +} +input[type="file"] { + display: block; +} +input[type="range"] { + display: block; + width: 100%; +} +select[multiple], +select[size] { + height: auto; +} +input[type="file"]:focus, +input[type="radio"]:focus, +input[type="checkbox"]:focus { + outline: thin dotted; + outline: 5px auto -webkit-focus-ring-color; + outline-offset: -2px; +} +output { + display: block; + padding-top: 7px; + font-size: 14px; + line-height: 1.428571429; + color: #555; +} +.form-control { + display: block; + width: 100%; + height: 34px; + padding: 6px 12px; + font-size: 14px; + line-height: 1.428571429; + color: #555; + background-color: #fff; + background-image: none; + border: 1px solid #ccc; + border-radius: 4px; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075); + -webkit-transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s; + transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s; +} +.form-control:focus { + border-color: #66afe9; + outline: 0; + -webkit-box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102, 175, 233, .6); + box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102, 175, 233, .6); +} +.form-control:-moz-placeholder { + color: #999; +} +.form-control::-moz-placeholder { + color: #999; + opacity: 1; +} +.form-control:-ms-input-placeholder { + color: #999; +} +.form-control::-webkit-input-placeholder { + color: #999; +} +.form-control[disabled], +.form-control[readonly], +fieldset[disabled] .form-control { + cursor: not-allowed; + background-color: #eee; + opacity: 1; +} +textarea.form-control { + height: auto; +} +input[type="date"] { + line-height: 34px; +} +.form-group { + margin-bottom: 15px; +} +.radio, +.checkbox { + display: block; + min-height: 20px; + padding-left: 20px; + margin-top: 10px; + margin-bottom: 10px; +} +.radio label, +.checkbox label { + display: inline; + font-weight: normal; + cursor: pointer; +} +.radio input[type="radio"], +.radio-inline input[type="radio"], +.checkbox input[type="checkbox"], +.checkbox-inline input[type="checkbox"] { + float: left; + margin-left: -20px; +} +.radio + .radio, +.checkbox + .checkbox { + margin-top: -5px; +} +.radio-inline, +.checkbox-inline { + display: inline-block; + padding-left: 20px; + margin-bottom: 0; + font-weight: normal; + vertical-align: middle; + cursor: pointer; +} +.radio-inline + .radio-inline, +.checkbox-inline + .checkbox-inline { + margin-top: 0; + margin-left: 10px; +} +input[type="radio"][disabled], +input[type="checkbox"][disabled], +.radio[disabled], +.radio-inline[disabled], +.checkbox[disabled], +.checkbox-inline[disabled], +fieldset[disabled] input[type="radio"], +fieldset[disabled] input[type="checkbox"], +fieldset[disabled] .radio, +fieldset[disabled] .radio-inline, +fieldset[disabled] .checkbox, +fieldset[disabled] .checkbox-inline { + cursor: not-allowed; +} +.input-sm { + height: 30px; + padding: 5px 10px; + font-size: 12px; + line-height: 1.5; + border-radius: 3px; +} +select.input-sm { + height: 30px; + line-height: 30px; +} +textarea.input-sm, +select[multiple].input-sm { + height: auto; +} +.input-lg { + height: 46px; + padding: 10px 16px; + font-size: 18px; + line-height: 1.33; + border-radius: 6px; +} +select.input-lg { + height: 46px; + line-height: 46px; +} +textarea.input-lg, +select[multiple].input-lg { + height: auto; +} +.has-feedback { + position: relative; +} +.has-feedback .form-control { + padding-right: 42.5px; +} +.has-feedback .form-control-feedback { + position: absolute; + top: 25px; + right: 0; + display: block; + width: 34px; + height: 34px; + line-height: 34px; + text-align: center; +} +.has-success .help-block, +.has-success .control-label, +.has-success .radio, +.has-success .checkbox, +.has-success .radio-inline, +.has-success .checkbox-inline { + color: #3c763d; +} +.has-success .form-control { + border-color: #3c763d; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075); +} +.has-success .form-control:focus { + border-color: #2b542c; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 6px #67b168; + box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 6px #67b168; +} +.has-success .input-group-addon { + color: #3c763d; + background-color: #dff0d8; + border-color: #3c763d; +} +.has-success .form-control-feedback { + color: #3c763d; +} +.has-warning .help-block, +.has-warning .control-label, +.has-warning .radio, +.has-warning .checkbox, +.has-warning .radio-inline, +.has-warning .checkbox-inline { + color: #8a6d3b; +} +.has-warning .form-control { + border-color: #8a6d3b; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075); +} +.has-warning .form-control:focus { + border-color: #66512c; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 6px #c0a16b; + box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 6px #c0a16b; +} +.has-warning .input-group-addon { + color: #8a6d3b; + background-color: #fcf8e3; + border-color: #8a6d3b; +} +.has-warning .form-control-feedback { + color: #8a6d3b; +} +.has-error .help-block, +.has-error .control-label, +.has-error .radio, +.has-error .checkbox, +.has-error .radio-inline, +.has-error .checkbox-inline { + color: #a94442; +} +.has-error .form-control { + border-color: #a94442; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075); +} +.has-error .form-control:focus { + border-color: #843534; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 6px #ce8483; + box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 6px #ce8483; +} +.has-error .input-group-addon { + color: #a94442; + background-color: #f2dede; + border-color: #a94442; +} +.has-error .form-control-feedback { + color: #a94442; +} +.form-control-static { + margin-bottom: 0; +} +.help-block { + display: block; + margin-top: 5px; + margin-bottom: 10px; + color: #737373; +} +@media (min-width: 768px) { + .form-inline .form-group { + display: inline-block; + margin-bottom: 0; + vertical-align: middle; + } + .form-inline .form-control { + display: inline-block; + width: auto; + vertical-align: middle; + } + .form-inline .control-label { + margin-bottom: 0; + vertical-align: middle; + } + .form-inline .radio, + .form-inline .checkbox { + display: inline-block; + padding-left: 0; + margin-top: 0; + margin-bottom: 0; + vertical-align: middle; + } + .form-inline .radio input[type="radio"], + .form-inline .checkbox input[type="checkbox"] { + float: none; + margin-left: 0; + } + .form-inline .has-feedback .form-control-feedback { + top: 0; + } +} +.form-horizontal .control-label, +.form-horizontal .radio, +.form-horizontal .checkbox, +.form-horizontal .radio-inline, +.form-horizontal .checkbox-inline { + padding-top: 7px; + margin-top: 0; + margin-bottom: 0; +} +.form-horizontal .radio, +.form-horizontal .checkbox { + min-height: 27px; +} +.form-horizontal .form-group { + margin-right: -15px; + margin-left: -15px; +} +.form-horizontal .form-control-static { + padding-top: 7px; +} +@media (min-width: 768px) { + .form-horizontal .control-label { + text-align: right; + } +} +.form-horizontal .has-feedback .form-control-feedback { + top: 0; + right: 15px; +} +.btn { + display: inline-block; + padding: 6px 12px; + margin-bottom: 0; + font-size: 14px; + font-weight: normal; + line-height: 1.428571429; + text-align: center; + white-space: nowrap; + vertical-align: middle; + cursor: pointer; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + -o-user-select: none; + user-select: none; + background-image: none; + border: 1px solid transparent; + border-radius: 4px; +} +.btn:focus { + outline: thin dotted; + outline: 5px auto -webkit-focus-ring-color; + outline-offset: -2px; +} +.btn:hover, +.btn:focus { + color: #333; + text-decoration: none; +} +.btn:active, +.btn.active { + background-image: none; + outline: 0; + -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, .125); + box-shadow: inset 0 3px 5px rgba(0, 0, 0, .125); +} +.btn.disabled, +.btn[disabled], +fieldset[disabled] .btn { + pointer-events: none; + cursor: not-allowed; + filter: alpha(opacity=65); + -webkit-box-shadow: none; + box-shadow: none; + opacity: .65; +} +.btn-default { + color: #333; + background-color: #fff; + border-color: #ccc; +} +.btn-default:hover, +.btn-default:focus, +.btn-default:active, +.btn-default.active, +.open .dropdown-toggle.btn-default { + color: #333; + background-color: #ebebeb; + border-color: #adadad; +} +.btn-default:active, +.btn-default.active, +.open .dropdown-toggle.btn-default { + background-image: none; +} +.btn-default.disabled, +.btn-default[disabled], +fieldset[disabled] .btn-default, +.btn-default.disabled:hover, +.btn-default[disabled]:hover, +fieldset[disabled] .btn-default:hover, +.btn-default.disabled:focus, +.btn-default[disabled]:focus, +fieldset[disabled] .btn-default:focus, +.btn-default.disabled:active, +.btn-default[disabled]:active, +fieldset[disabled] .btn-default:active, +.btn-default.disabled.active, +.btn-default[disabled].active, +fieldset[disabled] .btn-default.active { + background-color: #fff; + border-color: #ccc; +} +.btn-default .badge { + color: #fff; + background-color: #333; +} +.btn-primary { + color: #fff; + background-color: #428bca; + border-color: #357ebd; +} +.btn-primary:hover, +.btn-primary:focus, +.btn-primary:active, +.btn-primary.active, +.open .dropdown-toggle.btn-primary { + color: #fff; + background-color: #3276b1; + border-color: #285e8e; +} +.btn-primary:active, +.btn-primary.active, +.open .dropdown-toggle.btn-primary { + background-image: none; +} +.btn-primary.disabled, +.btn-primary[disabled], +fieldset[disabled] .btn-primary, +.btn-primary.disabled:hover, +.btn-primary[disabled]:hover, +fieldset[disabled] .btn-primary:hover, +.btn-primary.disabled:focus, +.btn-primary[disabled]:focus, +fieldset[disabled] .btn-primary:focus, +.btn-primary.disabled:active, +.btn-primary[disabled]:active, +fieldset[disabled] .btn-primary:active, +.btn-primary.disabled.active, +.btn-primary[disabled].active, +fieldset[disabled] .btn-primary.active { + background-color: #428bca; + border-color: #357ebd; +} +.btn-primary .badge { + color: #428bca; + background-color: #fff; +} +.btn-success { + color: #fff; + background-color: #5cb85c; + border-color: #4cae4c; +} +.btn-success:hover, +.btn-success:focus, +.btn-success:active, +.btn-success.active, +.open .dropdown-toggle.btn-success { + color: #fff; + background-color: #47a447; + border-color: #398439; +} +.btn-success:active, +.btn-success.active, +.open .dropdown-toggle.btn-success { + background-image: none; +} +.btn-success.disabled, +.btn-success[disabled], +fieldset[disabled] .btn-success, +.btn-success.disabled:hover, +.btn-success[disabled]:hover, +fieldset[disabled] .btn-success:hover, +.btn-success.disabled:focus, +.btn-success[disabled]:focus, +fieldset[disabled] .btn-success:focus, +.btn-success.disabled:active, +.btn-success[disabled]:active, +fieldset[disabled] .btn-success:active, +.btn-success.disabled.active, +.btn-success[disabled].active, +fieldset[disabled] .btn-success.active { + background-color: #5cb85c; + border-color: #4cae4c; +} +.btn-success .badge { + color: #5cb85c; + background-color: #fff; +} +.btn-info { + color: #fff; + background-color: #5bc0de; + border-color: #46b8da; +} +.btn-info:hover, +.btn-info:focus, +.btn-info:active, +.btn-info.active, +.open .dropdown-toggle.btn-info { + color: #fff; + background-color: #39b3d7; + border-color: #269abc; +} +.btn-info:active, +.btn-info.active, +.open .dropdown-toggle.btn-info { + background-image: none; +} +.btn-info.disabled, +.btn-info[disabled], +fieldset[disabled] .btn-info, +.btn-info.disabled:hover, +.btn-info[disabled]:hover, +fieldset[disabled] .btn-info:hover, +.btn-info.disabled:focus, +.btn-info[disabled]:focus, +fieldset[disabled] .btn-info:focus, +.btn-info.disabled:active, +.btn-info[disabled]:active, +fieldset[disabled] .btn-info:active, +.btn-info.disabled.active, +.btn-info[disabled].active, +fieldset[disabled] .btn-info.active { + background-color: #5bc0de; + border-color: #46b8da; +} +.btn-info .badge { + color: #5bc0de; + background-color: #fff; +} +.btn-warning { + color: #fff; + background-color: #f0ad4e; + border-color: #eea236; +} +.btn-warning:hover, +.btn-warning:focus, +.btn-warning:active, +.btn-warning.active, +.open .dropdown-toggle.btn-warning { + color: #fff; + background-color: #ed9c28; + border-color: #d58512; +} +.btn-warning:active, +.btn-warning.active, +.open .dropdown-toggle.btn-warning { + background-image: none; +} +.btn-warning.disabled, +.btn-warning[disabled], +fieldset[disabled] .btn-warning, +.btn-warning.disabled:hover, +.btn-warning[disabled]:hover, +fieldset[disabled] .btn-warning:hover, +.btn-warning.disabled:focus, +.btn-warning[disabled]:focus, +fieldset[disabled] .btn-warning:focus, +.btn-warning.disabled:active, +.btn-warning[disabled]:active, +fieldset[disabled] .btn-warning:active, +.btn-warning.disabled.active, +.btn-warning[disabled].active, +fieldset[disabled] .btn-warning.active { + background-color: #f0ad4e; + border-color: #eea236; +} +.btn-warning .badge { + color: #f0ad4e; + background-color: #fff; +} +.btn-danger { + color: #fff; + background-color: #d9534f; + border-color: #d43f3a; +} +.btn-danger:hover, +.btn-danger:focus, +.btn-danger:active, +.btn-danger.active, +.open .dropdown-toggle.btn-danger { + color: #fff; + background-color: #d2322d; + border-color: #ac2925; +} +.btn-danger:active, +.btn-danger.active, +.open .dropdown-toggle.btn-danger { + background-image: none; +} +.btn-danger.disabled, +.btn-danger[disabled], +fieldset[disabled] .btn-danger, +.btn-danger.disabled:hover, +.btn-danger[disabled]:hover, +fieldset[disabled] .btn-danger:hover, +.btn-danger.disabled:focus, +.btn-danger[disabled]:focus, +fieldset[disabled] .btn-danger:focus, +.btn-danger.disabled:active, +.btn-danger[disabled]:active, +fieldset[disabled] .btn-danger:active, +.btn-danger.disabled.active, +.btn-danger[disabled].active, +fieldset[disabled] .btn-danger.active { + background-color: #d9534f; + border-color: #d43f3a; +} +.btn-danger .badge { + color: #d9534f; + background-color: #fff; +} +.btn-link { + font-weight: normal; + color: #428bca; + cursor: pointer; + border-radius: 0; +} +.btn-link, +.btn-link:active, +.btn-link[disabled], +fieldset[disabled] .btn-link { + background-color: transparent; + -webkit-box-shadow: none; + box-shadow: none; +} +.btn-link, +.btn-link:hover, +.btn-link:focus, +.btn-link:active { + border-color: transparent; +} +.btn-link:hover, +.btn-link:focus { + color: #2a6496; + text-decoration: underline; + background-color: transparent; +} +.btn-link[disabled]:hover, +fieldset[disabled] .btn-link:hover, +.btn-link[disabled]:focus, +fieldset[disabled] .btn-link:focus { + color: #999; + text-decoration: none; +} +.btn-lg { + padding: 10px 16px; + font-size: 18px; + line-height: 1.33; + border-radius: 6px; +} +.btn-sm { + padding: 5px 10px; + font-size: 12px; + line-height: 1.5; + border-radius: 3px; +} +.btn-xs { + padding: 1px 5px; + font-size: 12px; + line-height: 1.5; + border-radius: 3px; +} +.btn-block { + display: block; + width: 100%; + padding-right: 0; + padding-left: 0; +} +.btn-block + .btn-block { + margin-top: 5px; +} +input[type="submit"].btn-block, +input[type="reset"].btn-block, +input[type="button"].btn-block { + width: 100%; +} +.fade { + opacity: 0; + -webkit-transition: opacity .15s linear; + transition: opacity .15s linear; +} +.fade.in { + opacity: 1; +} +.collapse { + display: none; +} +.collapse.in { + display: block; +} +.collapsing { + position: relative; + height: 0; + overflow: hidden; + -webkit-transition: height .35s ease; + transition: height .35s ease; +} +@font-face { + font-family: 'Glyphicons Halflings'; + + src: url('../fonts/glyphicons-halflings-regular.eot'); + src: url('../fonts/glyphicons-halflings-regular.eot?#iefix') format('embedded-opentype'), url('../fonts/glyphicons-halflings-regular.woff') format('woff'), url('../fonts/glyphicons-halflings-regular.ttf') format('truetype'), url('../fonts/glyphicons-halflings-regular.svg#glyphicons_halflingsregular') format('svg'); +} +.glyphicon { + position: relative; + top: 1px; + display: inline-block; + font-family: 'Glyphicons Halflings'; + font-style: normal; + font-weight: normal; + line-height: 1; + + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} +.glyphicon-asterisk:before { + content: "\2a"; +} +.glyphicon-plus:before { + content: "\2b"; +} +.glyphicon-euro:before { + content: "\20ac"; +} +.glyphicon-minus:before { + content: "\2212"; +} +.glyphicon-cloud:before { + content: "\2601"; +} +.glyphicon-envelope:before { + content: "\2709"; +} +.glyphicon-pencil:before { + content: "\270f"; +} +.glyphicon-glass:before { + content: "\e001"; +} +.glyphicon-music:before { + content: "\e002"; +} +.glyphicon-search:before { + content: "\e003"; +} +.glyphicon-heart:before { + content: "\e005"; +} +.glyphicon-star:before { + content: "\e006"; +} +.glyphicon-star-empty:before { + content: "\e007"; +} +.glyphicon-user:before { + content: "\e008"; +} +.glyphicon-film:before { + content: "\e009"; +} +.glyphicon-th-large:before { + content: "\e010"; +} +.glyphicon-th:before { + content: "\e011"; +} +.glyphicon-th-list:before { + content: "\e012"; +} +.glyphicon-ok:before { + content: "\e013"; +} +.glyphicon-remove:before { + content: "\e014"; +} +.glyphicon-zoom-in:before { + content: "\e015"; +} +.glyphicon-zoom-out:before { + content: "\e016"; +} +.glyphicon-off:before { + content: "\e017"; +} +.glyphicon-signal:before { + content: "\e018"; +} +.glyphicon-cog:before { + content: "\e019"; +} +.glyphicon-trash:before { + content: "\e020"; +} +.glyphicon-home:before { + content: "\e021"; +} +.glyphicon-file:before { + content: "\e022"; +} +.glyphicon-time:before { + content: "\e023"; +} +.glyphicon-road:before { + content: "\e024"; +} +.glyphicon-download-alt:before { + content: "\e025"; +} +.glyphicon-download:before { + content: "\e026"; +} +.glyphicon-upload:before { + content: "\e027"; +} +.glyphicon-inbox:before { + content: "\e028"; +} +.glyphicon-play-circle:before { + content: "\e029"; +} +.glyphicon-repeat:before { + content: "\e030"; +} +.glyphicon-refresh:before { + content: "\e031"; +} +.glyphicon-list-alt:before { + content: "\e032"; +} +.glyphicon-lock:before { + content: "\e033"; +} +.glyphicon-flag:before { + content: "\e034"; +} +.glyphicon-headphones:before { + content: "\e035"; +} +.glyphicon-volume-off:before { + content: "\e036"; +} +.glyphicon-volume-down:before { + content: "\e037"; +} +.glyphicon-volume-up:before { + content: "\e038"; +} +.glyphicon-qrcode:before { + content: "\e039"; +} +.glyphicon-barcode:before { + content: "\e040"; +} +.glyphicon-tag:before { + content: "\e041"; +} +.glyphicon-tags:before { + content: "\e042"; +} +.glyphicon-book:before { + content: "\e043"; +} +.glyphicon-bookmark:before { + content: "\e044"; +} +.glyphicon-print:before { + content: "\e045"; +} +.glyphicon-camera:before { + content: "\e046"; +} +.glyphicon-font:before { + content: "\e047"; +} +.glyphicon-bold:before { + content: "\e048"; +} +.glyphicon-italic:before { + content: "\e049"; +} +.glyphicon-text-height:before { + content: "\e050"; +} +.glyphicon-text-width:before { + content: "\e051"; +} +.glyphicon-align-left:before { + content: "\e052"; +} +.glyphicon-align-center:before { + content: "\e053"; +} +.glyphicon-align-right:before { + content: "\e054"; +} +.glyphicon-align-justify:before { + content: "\e055"; +} +.glyphicon-list:before { + content: "\e056"; +} +.glyphicon-indent-left:before { + content: "\e057"; +} +.glyphicon-indent-right:before { + content: "\e058"; +} +.glyphicon-facetime-video:before { + content: "\e059"; +} +.glyphicon-picture:before { + content: "\e060"; +} +.glyphicon-map-marker:before { + content: "\e062"; +} +.glyphicon-adjust:before { + content: "\e063"; +} +.glyphicon-tint:before { + content: "\e064"; +} +.glyphicon-edit:before { + content: "\e065"; +} +.glyphicon-share:before { + content: "\e066"; +} +.glyphicon-check:before { + content: "\e067"; +} +.glyphicon-move:before { + content: "\e068"; +} +.glyphicon-step-backward:before { + content: "\e069"; +} +.glyphicon-fast-backward:before { + content: "\e070"; +} +.glyphicon-backward:before { + content: "\e071"; +} +.glyphicon-play:before { + content: "\e072"; +} +.glyphicon-pause:before { + content: "\e073"; +} +.glyphicon-stop:before { + content: "\e074"; +} +.glyphicon-forward:before { + content: "\e075"; +} +.glyphicon-fast-forward:before { + content: "\e076"; +} +.glyphicon-step-forward:before { + content: "\e077"; +} +.glyphicon-eject:before { + content: "\e078"; +} +.glyphicon-chevron-left:before { + content: "\e079"; +} +.glyphicon-chevron-right:before { + content: "\e080"; +} +.glyphicon-plus-sign:before { + content: "\e081"; +} +.glyphicon-minus-sign:before { + content: "\e082"; +} +.glyphicon-remove-sign:before { + content: "\e083"; +} +.glyphicon-ok-sign:before { + content: "\e084"; +} +.glyphicon-question-sign:before { + content: "\e085"; +} +.glyphicon-info-sign:before { + content: "\e086"; +} +.glyphicon-screenshot:before { + content: "\e087"; +} +.glyphicon-remove-circle:before { + content: "\e088"; +} +.glyphicon-ok-circle:before { + content: "\e089"; +} +.glyphicon-ban-circle:before { + content: "\e090"; +} +.glyphicon-arrow-left:before { + content: "\e091"; +} +.glyphicon-arrow-right:before { + content: "\e092"; +} +.glyphicon-arrow-up:before { + content: "\e093"; +} +.glyphicon-arrow-down:before { + content: "\e094"; +} +.glyphicon-share-alt:before { + content: "\e095"; +} +.glyphicon-resize-full:before { + content: "\e096"; +} +.glyphicon-resize-small:before { + content: "\e097"; +} +.glyphicon-exclamation-sign:before { + content: "\e101"; +} +.glyphicon-gift:before { + content: "\e102"; +} +.glyphicon-leaf:before { + content: "\e103"; +} +.glyphicon-fire:before { + content: "\e104"; +} +.glyphicon-eye-open:before { + content: "\e105"; +} +.glyphicon-eye-close:before { + content: "\e106"; +} +.glyphicon-warning-sign:before { + content: "\e107"; +} +.glyphicon-plane:before { + content: "\e108"; +} +.glyphicon-calendar:before { + content: "\e109"; +} +.glyphicon-random:before { + content: "\e110"; +} +.glyphicon-comment:before { + content: "\e111"; +} +.glyphicon-magnet:before { + content: "\e112"; +} +.glyphicon-chevron-up:before { + content: "\e113"; +} +.glyphicon-chevron-down:before { + content: "\e114"; +} +.glyphicon-retweet:before { + content: "\e115"; +} +.glyphicon-shopping-cart:before { + content: "\e116"; +} +.glyphicon-folder-close:before { + content: "\e117"; +} +.glyphicon-folder-open:before { + content: "\e118"; +} +.glyphicon-resize-vertical:before { + content: "\e119"; +} +.glyphicon-resize-horizontal:before { + content: "\e120"; +} +.glyphicon-hdd:before { + content: "\e121"; +} +.glyphicon-bullhorn:before { + content: "\e122"; +} +.glyphicon-bell:before { + content: "\e123"; +} +.glyphicon-certificate:before { + content: "\e124"; +} +.glyphicon-thumbs-up:before { + content: "\e125"; +} +.glyphicon-thumbs-down:before { + content: "\e126"; +} +.glyphicon-hand-right:before { + content: "\e127"; +} +.glyphicon-hand-left:before { + content: "\e128"; +} +.glyphicon-hand-up:before { + content: "\e129"; +} +.glyphicon-hand-down:before { + content: "\e130"; +} +.glyphicon-circle-arrow-right:before { + content: "\e131"; +} +.glyphicon-circle-arrow-left:before { + content: "\e132"; +} +.glyphicon-circle-arrow-up:before { + content: "\e133"; +} +.glyphicon-circle-arrow-down:before { + content: "\e134"; +} +.glyphicon-globe:before { + content: "\e135"; +} +.glyphicon-wrench:before { + content: "\e136"; +} +.glyphicon-tasks:before { + content: "\e137"; +} +.glyphicon-filter:before { + content: "\e138"; +} +.glyphicon-briefcase:before { + content: "\e139"; +} +.glyphicon-fullscreen:before { + content: "\e140"; +} +.glyphicon-dashboard:before { + content: "\e141"; +} +.glyphicon-paperclip:before { + content: "\e142"; +} +.glyphicon-heart-empty:before { + content: "\e143"; +} +.glyphicon-link:before { + content: "\e144"; +} +.glyphicon-phone:before { + content: "\e145"; +} +.glyphicon-pushpin:before { + content: "\e146"; +} +.glyphicon-usd:before { + content: "\e148"; +} +.glyphicon-gbp:before { + content: "\e149"; +} +.glyphicon-sort:before { + content: "\e150"; +} +.glyphicon-sort-by-alphabet:before { + content: "\e151"; +} +.glyphicon-sort-by-alphabet-alt:before { + content: "\e152"; +} +.glyphicon-sort-by-order:before { + content: "\e153"; +} +.glyphicon-sort-by-order-alt:before { + content: "\e154"; +} +.glyphicon-sort-by-attributes:before { + content: "\e155"; +} +.glyphicon-sort-by-attributes-alt:before { + content: "\e156"; +} +.glyphicon-unchecked:before { + content: "\e157"; +} +.glyphicon-expand:before { + content: "\e158"; +} +.glyphicon-collapse-down:before { + content: "\e159"; +} +.glyphicon-collapse-up:before { + content: "\e160"; +} +.glyphicon-log-in:before { + content: "\e161"; +} +.glyphicon-flash:before { + content: "\e162"; +} +.glyphicon-log-out:before { + content: "\e163"; +} +.glyphicon-new-window:before { + content: "\e164"; +} +.glyphicon-record:before { + content: "\e165"; +} +.glyphicon-save:before { + content: "\e166"; +} +.glyphicon-open:before { + content: "\e167"; +} +.glyphicon-saved:before { + content: "\e168"; +} +.glyphicon-import:before { + content: "\e169"; +} +.glyphicon-export:before { + content: "\e170"; +} +.glyphicon-send:before { + content: "\e171"; +} +.glyphicon-floppy-disk:before { + content: "\e172"; +} +.glyphicon-floppy-saved:before { + content: "\e173"; +} +.glyphicon-floppy-remove:before { + content: "\e174"; +} +.glyphicon-floppy-save:before { + content: "\e175"; +} +.glyphicon-floppy-open:before { + content: "\e176"; +} +.glyphicon-credit-card:before { + content: "\e177"; +} +.glyphicon-transfer:before { + content: "\e178"; +} +.glyphicon-cutlery:before { + content: "\e179"; +} +.glyphicon-header:before { + content: "\e180"; +} +.glyphicon-compressed:before { + content: "\e181"; +} +.glyphicon-earphone:before { + content: "\e182"; +} +.glyphicon-phone-alt:before { + content: "\e183"; +} +.glyphicon-tower:before { + content: "\e184"; +} +.glyphicon-stats:before { + content: "\e185"; +} +.glyphicon-sd-video:before { + content: "\e186"; +} +.glyphicon-hd-video:before { + content: "\e187"; +} +.glyphicon-subtitles:before { + content: "\e188"; +} +.glyphicon-sound-stereo:before { + content: "\e189"; +} +.glyphicon-sound-dolby:before { + content: "\e190"; +} +.glyphicon-sound-5-1:before { + content: "\e191"; +} +.glyphicon-sound-6-1:before { + content: "\e192"; +} +.glyphicon-sound-7-1:before { + content: "\e193"; +} +.glyphicon-copyright-mark:before { + content: "\e194"; +} +.glyphicon-registration-mark:before { + content: "\e195"; +} +.glyphicon-cloud-download:before { + content: "\e197"; +} +.glyphicon-cloud-upload:before { + content: "\e198"; +} +.glyphicon-tree-conifer:before { + content: "\e199"; +} +.glyphicon-tree-deciduous:before { + content: "\e200"; +} +.caret { + display: inline-block; + width: 0; + height: 0; + margin-left: 2px; + vertical-align: middle; + border-top: 4px solid; + border-right: 4px solid transparent; + border-left: 4px solid transparent; +} +.dropdown { + position: relative; +} +.dropdown-toggle:focus { + outline: 0; +} +.dropdown-menu { + position: absolute; + top: 100%; + left: 0; + z-index: 1000; + display: none; + float: left; + min-width: 160px; + padding: 5px 0; + margin: 2px 0 0; + font-size: 14px; + list-style: none; + background-color: #fff; + background-clip: padding-box; + border: 1px solid #ccc; + border: 1px solid rgba(0, 0, 0, .15); + border-radius: 4px; + -webkit-box-shadow: 0 6px 12px rgba(0, 0, 0, .175); + box-shadow: 0 6px 12px rgba(0, 0, 0, .175); +} +.dropdown-menu.pull-right { + right: 0; + left: auto; +} +.dropdown-menu .divider { + height: 1px; + margin: 9px 0; + overflow: hidden; + background-color: #e5e5e5; +} +.dropdown-menu > li > a { + display: block; + padding: 3px 20px; + clear: both; + font-weight: normal; + line-height: 1.428571429; + color: #333; + white-space: nowrap; +} +.dropdown-menu > li > a:hover, +.dropdown-menu > li > a:focus { + color: #262626; + text-decoration: none; + background-color: #f5f5f5; +} +.dropdown-menu > .active > a, +.dropdown-menu > .active > a:hover, +.dropdown-menu > .active > a:focus { + color: #fff; + text-decoration: none; + background-color: #428bca; + outline: 0; +} +.dropdown-menu > .disabled > a, +.dropdown-menu > .disabled > a:hover, +.dropdown-menu > .disabled > a:focus { + color: #999; +} +.dropdown-menu > .disabled > a:hover, +.dropdown-menu > .disabled > a:focus { + text-decoration: none; + cursor: not-allowed; + background-color: transparent; + background-image: none; + filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); +} +.open > .dropdown-menu { + display: block; +} +.open > a { + outline: 0; +} +.dropdown-menu-right { + right: 0; + left: auto; +} +.dropdown-menu-left { + right: auto; + left: 0; +} +.dropdown-header { + display: block; + padding: 3px 20px; + font-size: 12px; + line-height: 1.428571429; + color: #999; +} +.dropdown-backdrop { + position: fixed; + top: 0; + right: 0; + bottom: 0; + left: 0; + z-index: 990; +} +.pull-right > .dropdown-menu { + right: 0; + left: auto; +} +.dropup .caret, +.navbar-fixed-bottom .dropdown .caret { + content: ""; + border-top: 0; + border-bottom: 4px solid; +} +.dropup .dropdown-menu, +.navbar-fixed-bottom .dropdown .dropdown-menu { + top: auto; + bottom: 100%; + margin-bottom: 1px; +} +@media (min-width: 768px) { + .navbar-right .dropdown-menu { + right: 0; + left: auto; + } + .navbar-right .dropdown-menu-left { + right: auto; + left: 0; + } +} +.btn-group, +.btn-group-vertical { + position: relative; + display: inline-block; + vertical-align: middle; +} +.btn-group > .btn, +.btn-group-vertical > .btn { + position: relative; + float: left; +} +.btn-group > .btn:hover, +.btn-group-vertical > .btn:hover, +.btn-group > .btn:focus, +.btn-group-vertical > .btn:focus, +.btn-group > .btn:active, +.btn-group-vertical > .btn:active, +.btn-group > .btn.active, +.btn-group-vertical > .btn.active { + z-index: 2; +} +.btn-group > .btn:focus, +.btn-group-vertical > .btn:focus { + outline: none; +} +.btn-group .btn + .btn, +.btn-group .btn + .btn-group, +.btn-group .btn-group + .btn, +.btn-group .btn-group + .btn-group { + margin-left: -1px; +} +.btn-toolbar { + margin-left: -5px; +} +.btn-toolbar .btn-group, +.btn-toolbar .input-group { + float: left; +} +.btn-toolbar > .btn, +.btn-toolbar > .btn-group, +.btn-toolbar > .input-group { + margin-left: 5px; +} +.btn-group > .btn:not(:first-child):not(:last-child):not(.dropdown-toggle) { + border-radius: 0; +} +.btn-group > .btn:first-child { + margin-left: 0; +} +.btn-group > .btn:first-child:not(:last-child):not(.dropdown-toggle) { + border-top-right-radius: 0; + border-bottom-right-radius: 0; +} +.btn-group > .btn:last-child:not(:first-child), +.btn-group > .dropdown-toggle:not(:first-child) { + border-top-left-radius: 0; + border-bottom-left-radius: 0; +} +.btn-group > .btn-group { + float: left; +} +.btn-group > .btn-group:not(:first-child):not(:last-child) > .btn { + border-radius: 0; +} +.btn-group > .btn-group:first-child > .btn:last-child, +.btn-group > .btn-group:first-child > .dropdown-toggle { + border-top-right-radius: 0; + border-bottom-right-radius: 0; +} +.btn-group > .btn-group:last-child > .btn:first-child { + border-top-left-radius: 0; + border-bottom-left-radius: 0; +} +.btn-group .dropdown-toggle:active, +.btn-group.open .dropdown-toggle { + outline: 0; +} +.btn-group-xs > .btn { + padding: 1px 5px; + font-size: 12px; + line-height: 1.5; + border-radius: 3px; +} +.btn-group-sm > .btn { + padding: 5px 10px; + font-size: 12px; + line-height: 1.5; + border-radius: 3px; +} +.btn-group-lg > .btn { + padding: 10px 16px; + font-size: 18px; + line-height: 1.33; + border-radius: 6px; +} +.btn-group > .btn + .dropdown-toggle { + padding-right: 8px; + padding-left: 8px; +} +.btn-group > .btn-lg + .dropdown-toggle { + padding-right: 12px; + padding-left: 12px; +} +.btn-group.open .dropdown-toggle { + -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, .125); + box-shadow: inset 0 3px 5px rgba(0, 0, 0, .125); +} +.btn-group.open .dropdown-toggle.btn-link { + -webkit-box-shadow: none; + box-shadow: none; +} +.btn .caret { + margin-left: 0; +} +.btn-lg .caret { + border-width: 5px 5px 0; + border-bottom-width: 0; +} +.dropup .btn-lg .caret { + border-width: 0 5px 5px; +} +.btn-group-vertical > .btn, +.btn-group-vertical > .btn-group, +.btn-group-vertical > .btn-group > .btn { + display: block; + float: none; + width: 100%; + max-width: 100%; +} +.btn-group-vertical > .btn-group > .btn { + float: none; +} +.btn-group-vertical > .btn + .btn, +.btn-group-vertical > .btn + .btn-group, +.btn-group-vertical > .btn-group + .btn, +.btn-group-vertical > .btn-group + .btn-group { + margin-top: -1px; + margin-left: 0; +} +.btn-group-vertical > .btn:not(:first-child):not(:last-child) { + border-radius: 0; +} +.btn-group-vertical > .btn:first-child:not(:last-child) { + border-top-right-radius: 4px; + border-bottom-right-radius: 0; + border-bottom-left-radius: 0; +} +.btn-group-vertical > .btn:last-child:not(:first-child) { + border-top-left-radius: 0; + border-top-right-radius: 0; + border-bottom-left-radius: 4px; +} +.btn-group-vertical > .btn-group:not(:first-child):not(:last-child) > .btn { + border-radius: 0; +} +.btn-group-vertical > .btn-group:first-child:not(:last-child) > .btn:last-child, +.btn-group-vertical > .btn-group:first-child:not(:last-child) > .dropdown-toggle { + border-bottom-right-radius: 0; + border-bottom-left-radius: 0; +} +.btn-group-vertical > .btn-group:last-child:not(:first-child) > .btn:first-child { + border-top-left-radius: 0; + border-top-right-radius: 0; +} +.btn-group-justified { + display: table; + width: 100%; + table-layout: fixed; + border-collapse: separate; +} +.btn-group-justified > .btn, +.btn-group-justified > .btn-group { + display: table-cell; + float: none; + width: 1%; +} +.btn-group-justified > .btn-group .btn { + width: 100%; +} +[data-toggle="buttons"] > .btn > input[type="radio"], +[data-toggle="buttons"] > .btn > input[type="checkbox"] { + display: none; +} +.input-group { + position: relative; + display: table; + border-collapse: separate; +} +.input-group[class*="col-"] { + float: none; + padding-right: 0; + padding-left: 0; +} +.input-group .form-control { + float: left; + width: 100%; + margin-bottom: 0; +} +.input-group-lg > .form-control, +.input-group-lg > .input-group-addon, +.input-group-lg > .input-group-btn > .btn { + height: 46px; + padding: 10px 16px; + font-size: 18px; + line-height: 1.33; + border-radius: 6px; +} +select.input-group-lg > .form-control, +select.input-group-lg > .input-group-addon, +select.input-group-lg > .input-group-btn > .btn { + height: 46px; + line-height: 46px; +} +textarea.input-group-lg > .form-control, +textarea.input-group-lg > .input-group-addon, +textarea.input-group-lg > .input-group-btn > .btn, +select[multiple].input-group-lg > .form-control, +select[multiple].input-group-lg > .input-group-addon, +select[multiple].input-group-lg > .input-group-btn > .btn { + height: auto; +} +.input-group-sm > .form-control, +.input-group-sm > .input-group-addon, +.input-group-sm > .input-group-btn > .btn { + height: 30px; + padding: 5px 10px; + font-size: 12px; + line-height: 1.5; + border-radius: 3px; +} +select.input-group-sm > .form-control, +select.input-group-sm > .input-group-addon, +select.input-group-sm > .input-group-btn > .btn { + height: 30px; + line-height: 30px; +} +textarea.input-group-sm > .form-control, +textarea.input-group-sm > .input-group-addon, +textarea.input-group-sm > .input-group-btn > .btn, +select[multiple].input-group-sm > .form-control, +select[multiple].input-group-sm > .input-group-addon, +select[multiple].input-group-sm > .input-group-btn > .btn { + height: auto; +} +.input-group-addon, +.input-group-btn, +.input-group .form-control { + display: table-cell; +} +.input-group-addon:not(:first-child):not(:last-child), +.input-group-btn:not(:first-child):not(:last-child), +.input-group .form-control:not(:first-child):not(:last-child) { + border-radius: 0; +} +.input-group-addon, +.input-group-btn { + width: 1%; + white-space: nowrap; + vertical-align: middle; +} +.input-group-addon { + padding: 6px 12px; + font-size: 14px; + font-weight: normal; + line-height: 1; + color: #555; + text-align: center; + background-color: #eee; + border: 1px solid #ccc; + border-radius: 4px; +} +.input-group-addon.input-sm { + padding: 5px 10px; + font-size: 12px; + border-radius: 3px; +} +.input-group-addon.input-lg { + padding: 10px 16px; + font-size: 18px; + border-radius: 6px; +} +.input-group-addon input[type="radio"], +.input-group-addon input[type="checkbox"] { + margin-top: 0; +} +.input-group .form-control:first-child, +.input-group-addon:first-child, +.input-group-btn:first-child > .btn, +.input-group-btn:first-child > .btn-group > .btn, +.input-group-btn:first-child > .dropdown-toggle, +.input-group-btn:last-child > .btn:not(:last-child):not(.dropdown-toggle), +.input-group-btn:last-child > .btn-group:not(:last-child) > .btn { + border-top-right-radius: 0; + border-bottom-right-radius: 0; +} +.input-group-addon:first-child { + border-right: 0; +} +.input-group .form-control:last-child, +.input-group-addon:last-child, +.input-group-btn:last-child > .btn, +.input-group-btn:last-child > .btn-group > .btn, +.input-group-btn:last-child > .dropdown-toggle, +.input-group-btn:first-child > .btn:not(:first-child), +.input-group-btn:first-child > .btn-group:not(:first-child) > .btn { + border-top-left-radius: 0; + border-bottom-left-radius: 0; +} +.input-group-addon:last-child { + border-left: 0; +} +.input-group-btn { + position: relative; + font-size: 0; + white-space: nowrap; +} +.input-group-btn > .btn { + position: relative; +} +.input-group-btn > .btn + .btn { + margin-left: -1px; +} +.input-group-btn > .btn:hover, +.input-group-btn > .btn:focus, +.input-group-btn > .btn:active { + z-index: 2; +} +.input-group-btn:first-child > .btn, +.input-group-btn:first-child > .btn-group { + margin-right: -1px; +} +.input-group-btn:last-child > .btn, +.input-group-btn:last-child > .btn-group { + margin-left: -1px; +} +.nav { + padding-left: 0; + margin-bottom: 0; + list-style: none; +} +.nav > li { + position: relative; + display: block; +} +.nav > li > a { + position: relative; + display: block; + padding: 10px 15px; +} +.nav > li > a:hover, +.nav > li > a:focus { + text-decoration: none; + background-color: #eee; +} +.nav > li.disabled > a { + color: #999; +} +.nav > li.disabled > a:hover, +.nav > li.disabled > a:focus { + color: #999; + text-decoration: none; + cursor: not-allowed; + background-color: transparent; +} +.nav .open > a, +.nav .open > a:hover, +.nav .open > a:focus { + background-color: #eee; + border-color: #428bca; +} +.nav .nav-divider { + height: 1px; + margin: 9px 0; + overflow: hidden; + background-color: #e5e5e5; +} +.nav > li > a > img { + max-width: none; +} +.nav-tabs { + border-bottom: 1px solid #ddd; +} +.nav-tabs > li { + float: left; + margin-bottom: -1px; +} +.nav-tabs > li > a { + margin-right: 2px; + line-height: 1.428571429; + border: 1px solid transparent; + border-radius: 4px 4px 0 0; +} +.nav-tabs > li > a:hover { + border-color: #eee #eee #ddd; +} +.nav-tabs > li.active > a, +.nav-tabs > li.active > a:hover, +.nav-tabs > li.active > a:focus { + color: #555; + cursor: default; + background-color: #fff; + border: 1px solid #ddd; + border-bottom-color: transparent; +} +.nav-tabs.nav-justified { + width: 100%; + border-bottom: 0; +} +.nav-tabs.nav-justified > li { + float: none; +} +.nav-tabs.nav-justified > li > a { + margin-bottom: 5px; + text-align: center; +} +.nav-tabs.nav-justified > .dropdown .dropdown-menu { + top: auto; + left: auto; +} +@media (min-width: 768px) { + .nav-tabs.nav-justified > li { + display: table-cell; + width: 1%; + } + .nav-tabs.nav-justified > li > a { + margin-bottom: 0; + } +} +.nav-tabs.nav-justified > li > a { + margin-right: 0; + border-radius: 4px; +} +.nav-tabs.nav-justified > .active > a, +.nav-tabs.nav-justified > .active > a:hover, +.nav-tabs.nav-justified > .active > a:focus { + border: 1px solid #ddd; +} +@media (min-width: 768px) { + .nav-tabs.nav-justified > li > a { + border-bottom: 1px solid #ddd; + border-radius: 4px 4px 0 0; + } + .nav-tabs.nav-justified > .active > a, + .nav-tabs.nav-justified > .active > a:hover, + .nav-tabs.nav-justified > .active > a:focus { + border-bottom-color: #fff; + } +} +.nav-pills > li { + float: left; +} +.nav-pills > li > a { + border-radius: 4px; +} +.nav-pills > li + li { + margin-left: 2px; +} +.nav-pills > li.active > a, +.nav-pills > li.active > a:hover, +.nav-pills > li.active > a:focus { + color: #fff; + background-color: #428bca; +} +.nav-stacked > li { + float: none; +} +.nav-stacked > li + li { + margin-top: 2px; + margin-left: 0; +} +.nav-justified { + width: 100%; +} +.nav-justified > li { + float: none; +} +.nav-justified > li > a { + margin-bottom: 5px; + text-align: center; +} +.nav-justified > .dropdown .dropdown-menu { + top: auto; + left: auto; +} +@media (min-width: 768px) { + .nav-justified > li { + display: table-cell; + width: 1%; + } + .nav-justified > li > a { + margin-bottom: 0; + } +} +.nav-tabs-justified { + border-bottom: 0; +} +.nav-tabs-justified > li > a { + margin-right: 0; + border-radius: 4px; +} +.nav-tabs-justified > .active > a, +.nav-tabs-justified > .active > a:hover, +.nav-tabs-justified > .active > a:focus { + border: 1px solid #ddd; +} +@media (min-width: 768px) { + .nav-tabs-justified > li > a { + border-bottom: 1px solid #ddd; + border-radius: 4px 4px 0 0; + } + .nav-tabs-justified > .active > a, + .nav-tabs-justified > .active > a:hover, + .nav-tabs-justified > .active > a:focus { + border-bottom-color: #fff; + } +} +.tab-content > .tab-pane { + display: none; +} +.tab-content > .active { + display: block; +} +.nav-tabs .dropdown-menu { + margin-top: -1px; + border-top-left-radius: 0; + border-top-right-radius: 0; +} +.navbar { + position: relative; + min-height: 50px; + margin-bottom: 20px; + border: 1px solid transparent; +} +@media (min-width: 768px) { + .navbar { + border-radius: 4px; + } +} +@media (min-width: 768px) { + .navbar-header { + float: left; + } +} +.navbar-collapse { + max-height: 340px; + padding-right: 15px; + padding-left: 15px; + overflow-x: visible; + -webkit-overflow-scrolling: touch; + border-top: 1px solid transparent; + box-shadow: inset 0 1px 0 rgba(255, 255, 255, .1); +} +.navbar-collapse.in { + overflow-y: auto; +} +@media (min-width: 768px) { + .navbar-collapse { + width: auto; + border-top: 0; + box-shadow: none; + } + .navbar-collapse.collapse { + display: block !important; + height: auto !important; + padding-bottom: 0; + overflow: visible !important; + } + .navbar-collapse.in { + overflow-y: visible; + } + .navbar-fixed-top .navbar-collapse, + .navbar-static-top .navbar-collapse, + .navbar-fixed-bottom .navbar-collapse { + padding-right: 0; + padding-left: 0; + } +} +.container > .navbar-header, +.container-fluid > .navbar-header, +.container > .navbar-collapse, +.container-fluid > .navbar-collapse { + margin-right: -15px; + margin-left: -15px; +} +@media (min-width: 768px) { + .container > .navbar-header, + .container-fluid > .navbar-header, + .container > .navbar-collapse, + .container-fluid > .navbar-collapse { + margin-right: 0; + margin-left: 0; + } +} +.navbar-static-top { + z-index: 1000; + border-width: 0 0 1px; +} +@media (min-width: 768px) { + .navbar-static-top { + border-radius: 0; + } +} +.navbar-fixed-top, +.navbar-fixed-bottom { + position: fixed; + right: 0; + left: 0; + z-index: 1030; +} +@media (min-width: 768px) { + .navbar-fixed-top, + .navbar-fixed-bottom { + border-radius: 0; + } +} +.navbar-fixed-top { + top: 0; + border-width: 0 0 1px; +} +.navbar-fixed-bottom { + bottom: 0; + margin-bottom: 0; + border-width: 1px 0 0; +} +.navbar-brand { + float: left; + height: 20px; + padding: 15px 15px; + font-size: 18px; + line-height: 20px; +} +.navbar-brand:hover, +.navbar-brand:focus { + text-decoration: none; +} +@media (min-width: 768px) { + .navbar > .container .navbar-brand, + .navbar > .container-fluid .navbar-brand { + margin-left: -15px; + } +} +.navbar-toggle { + position: relative; + float: right; + padding: 9px 10px; + margin-top: 8px; + margin-right: 15px; + margin-bottom: 8px; + background-color: transparent; + background-image: none; + border: 1px solid transparent; + border-radius: 4px; +} +.navbar-toggle:focus { + outline: none; +} +.navbar-toggle .icon-bar { + display: block; + width: 22px; + height: 2px; + border-radius: 1px; +} +.navbar-toggle .icon-bar + .icon-bar { + margin-top: 4px; +} +@media (min-width: 768px) { + .navbar-toggle { + display: none; + } +} +.navbar-nav { + margin: 7.5px -15px; +} +.navbar-nav > li > a { + padding-top: 10px; + padding-bottom: 10px; + line-height: 20px; +} +@media (max-width: 767px) { + .navbar-nav .open .dropdown-menu { + position: static; + float: none; + width: auto; + margin-top: 0; + background-color: transparent; + border: 0; + box-shadow: none; + } + .navbar-nav .open .dropdown-menu > li > a, + .navbar-nav .open .dropdown-menu .dropdown-header { + padding: 5px 15px 5px 25px; + } + .navbar-nav .open .dropdown-menu > li > a { + line-height: 20px; + } + .navbar-nav .open .dropdown-menu > li > a:hover, + .navbar-nav .open .dropdown-menu > li > a:focus { + background-image: none; + } +} +@media (min-width: 768px) { + .navbar-nav { + float: left; + margin: 0; + } + .navbar-nav > li { + float: left; + } + .navbar-nav > li > a { + padding-top: 15px; + padding-bottom: 15px; + } + .navbar-nav.navbar-right:last-child { + margin-right: -15px; + } +} +@media (min-width: 768px) { + .navbar-left { + float: left !important; + } + .navbar-right { + float: right !important; + } +} +.navbar-form { + padding: 10px 15px; + margin-top: 8px; + margin-right: -15px; + margin-bottom: 8px; + margin-left: -15px; + border-top: 1px solid transparent; + border-bottom: 1px solid transparent; + -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, .1), 0 1px 0 rgba(255, 255, 255, .1); + box-shadow: inset 0 1px 0 rgba(255, 255, 255, .1), 0 1px 0 rgba(255, 255, 255, .1); +} +@media (min-width: 768px) { + .navbar-form .form-group { + display: inline-block; + margin-bottom: 0; + vertical-align: middle; + } + .navbar-form .form-control { + display: inline-block; + width: auto; + vertical-align: middle; + } + .navbar-form .control-label { + margin-bottom: 0; + vertical-align: middle; + } + .navbar-form .radio, + .navbar-form .checkbox { + display: inline-block; + padding-left: 0; + margin-top: 0; + margin-bottom: 0; + vertical-align: middle; + } + .navbar-form .radio input[type="radio"], + .navbar-form .checkbox input[type="checkbox"] { + float: none; + margin-left: 0; + } + .navbar-form .has-feedback .form-control-feedback { + top: 0; + } +} +@media (max-width: 767px) { + .navbar-form .form-group { + margin-bottom: 5px; + } +} +@media (min-width: 768px) { + .navbar-form { + width: auto; + padding-top: 0; + padding-bottom: 0; + margin-right: 0; + margin-left: 0; + border: 0; + -webkit-box-shadow: none; + box-shadow: none; + } + .navbar-form.navbar-right:last-child { + margin-right: -15px; + } +} +.navbar-nav > li > .dropdown-menu { + margin-top: 0; + border-top-left-radius: 0; + border-top-right-radius: 0; +} +.navbar-fixed-bottom .navbar-nav > li > .dropdown-menu { + border-bottom-right-radius: 0; + border-bottom-left-radius: 0; +} +.navbar-btn { + margin-top: 8px; + margin-bottom: 8px; +} +.navbar-btn.btn-sm { + margin-top: 10px; + margin-bottom: 10px; +} +.navbar-btn.btn-xs { + margin-top: 14px; + margin-bottom: 14px; +} +.navbar-text { + margin-top: 15px; + margin-bottom: 15px; +} +@media (min-width: 768px) { + .navbar-text { + float: left; + margin-right: 15px; + margin-left: 15px; + } + .navbar-text.navbar-right:last-child { + margin-right: 0; + } +} +.navbar-default { + background-color: #f8f8f8; + border-color: #e7e7e7; +} +.navbar-default .navbar-brand { + color: #777; +} +.navbar-default .navbar-brand:hover, +.navbar-default .navbar-brand:focus { + color: #5e5e5e; + background-color: transparent; +} +.navbar-default .navbar-text { + color: #777; +} +.navbar-default .navbar-nav > li > a { + color: #777; +} +.navbar-default .navbar-nav > li > a:hover, +.navbar-default .navbar-nav > li > a:focus { + color: #333; + background-color: transparent; +} +.navbar-default .navbar-nav > .active > a, +.navbar-default .navbar-nav > .active > a:hover, +.navbar-default .navbar-nav > .active > a:focus { + color: #555; + background-color: #e7e7e7; +} +.navbar-default .navbar-nav > .disabled > a, +.navbar-default .navbar-nav > .disabled > a:hover, +.navbar-default .navbar-nav > .disabled > a:focus { + color: #ccc; + background-color: transparent; +} +.navbar-default .navbar-toggle { + border-color: #ddd; +} +.navbar-default .navbar-toggle:hover, +.navbar-default .navbar-toggle:focus { + background-color: #ddd; +} +.navbar-default .navbar-toggle .icon-bar { + background-color: #888; +} +.navbar-default .navbar-collapse, +.navbar-default .navbar-form { + border-color: #e7e7e7; +} +.navbar-default .navbar-nav > .open > a, +.navbar-default .navbar-nav > .open > a:hover, +.navbar-default .navbar-nav > .open > a:focus { + color: #555; + background-color: #e7e7e7; +} +@media (max-width: 767px) { + .navbar-default .navbar-nav .open .dropdown-menu > li > a { + color: #777; + } + .navbar-default .navbar-nav .open .dropdown-menu > li > a:hover, + .navbar-default .navbar-nav .open .dropdown-menu > li > a:focus { + color: #333; + background-color: transparent; + } + .navbar-default .navbar-nav .open .dropdown-menu > .active > a, + .navbar-default .navbar-nav .open .dropdown-menu > .active > a:hover, + .navbar-default .navbar-nav .open .dropdown-menu > .active > a:focus { + color: #555; + background-color: #e7e7e7; + } + .navbar-default .navbar-nav .open .dropdown-menu > .disabled > a, + .navbar-default .navbar-nav .open .dropdown-menu > .disabled > a:hover, + .navbar-default .navbar-nav .open .dropdown-menu > .disabled > a:focus { + color: #ccc; + background-color: transparent; + } +} +.navbar-default .navbar-link { + color: #777; +} +.navbar-default .navbar-link:hover { + color: #333; +} +.navbar-inverse { + background-color: #222; + border-color: #080808; +} +.navbar-inverse .navbar-brand { + color: #999; +} +.navbar-inverse .navbar-brand:hover, +.navbar-inverse .navbar-brand:focus { + color: #fff; + background-color: transparent; +} +.navbar-inverse .navbar-text { + color: #999; +} +.navbar-inverse .navbar-nav > li > a { + color: #999; +} +.navbar-inverse .navbar-nav > li > a:hover, +.navbar-inverse .navbar-nav > li > a:focus { + color: #fff; + background-color: transparent; +} +.navbar-inverse .navbar-nav > .active > a, +.navbar-inverse .navbar-nav > .active > a:hover, +.navbar-inverse .navbar-nav > .active > a:focus { + color: #fff; + background-color: #080808; +} +.navbar-inverse .navbar-nav > .disabled > a, +.navbar-inverse .navbar-nav > .disabled > a:hover, +.navbar-inverse .navbar-nav > .disabled > a:focus { + color: #444; + background-color: transparent; +} +.navbar-inverse .navbar-toggle { + border-color: #333; +} +.navbar-inverse .navbar-toggle:hover, +.navbar-inverse .navbar-toggle:focus { + background-color: #333; +} +.navbar-inverse .navbar-toggle .icon-bar { + background-color: #fff; +} +.navbar-inverse .navbar-collapse, +.navbar-inverse .navbar-form { + border-color: #101010; +} +.navbar-inverse .navbar-nav > .open > a, +.navbar-inverse .navbar-nav > .open > a:hover, +.navbar-inverse .navbar-nav > .open > a:focus { + color: #fff; + background-color: #080808; +} +@media (max-width: 767px) { + .navbar-inverse .navbar-nav .open .dropdown-menu > .dropdown-header { + border-color: #080808; + } + .navbar-inverse .navbar-nav .open .dropdown-menu .divider { + background-color: #080808; + } + .navbar-inverse .navbar-nav .open .dropdown-menu > li > a { + color: #999; + } + .navbar-inverse .navbar-nav .open .dropdown-menu > li > a:hover, + .navbar-inverse .navbar-nav .open .dropdown-menu > li > a:focus { + color: #fff; + background-color: transparent; + } + .navbar-inverse .navbar-nav .open .dropdown-menu > .active > a, + .navbar-inverse .navbar-nav .open .dropdown-menu > .active > a:hover, + .navbar-inverse .navbar-nav .open .dropdown-menu > .active > a:focus { + color: #fff; + background-color: #080808; + } + .navbar-inverse .navbar-nav .open .dropdown-menu > .disabled > a, + .navbar-inverse .navbar-nav .open .dropdown-menu > .disabled > a:hover, + .navbar-inverse .navbar-nav .open .dropdown-menu > .disabled > a:focus { + color: #444; + background-color: transparent; + } +} +.navbar-inverse .navbar-link { + color: #999; +} +.navbar-inverse .navbar-link:hover { + color: #fff; +} +.breadcrumb { + padding: 8px 15px; + margin-bottom: 20px; + list-style: none; + background-color: #f5f5f5; + border-radius: 4px; +} +.breadcrumb > li { + display: inline-block; +} +.breadcrumb > li + li:before { + padding: 0 5px; + color: #ccc; + content: "/\00a0"; +} +.breadcrumb > .active { + color: #999; +} +.pagination { + display: inline-block; + padding-left: 0; + margin: 20px 0; + border-radius: 4px; +} +.pagination > li { + display: inline; +} +.pagination > li > a, +.pagination > li > span { + position: relative; + float: left; + padding: 6px 12px; + margin-left: -1px; + line-height: 1.428571429; + color: #428bca; + text-decoration: none; + background-color: #fff; + border: 1px solid #ddd; +} +.pagination > li:first-child > a, +.pagination > li:first-child > span { + margin-left: 0; + border-top-left-radius: 4px; + border-bottom-left-radius: 4px; +} +.pagination > li:last-child > a, +.pagination > li:last-child > span { + border-top-right-radius: 4px; + border-bottom-right-radius: 4px; +} +.pagination > li > a:hover, +.pagination > li > span:hover, +.pagination > li > a:focus, +.pagination > li > span:focus { + color: #2a6496; + background-color: #eee; + border-color: #ddd; +} +.pagination > .active > a, +.pagination > .active > span, +.pagination > .active > a:hover, +.pagination > .active > span:hover, +.pagination > .active > a:focus, +.pagination > .active > span:focus { + z-index: 2; + color: #fff; + cursor: default; + background-color: #428bca; + border-color: #428bca; +} +.pagination > .disabled > span, +.pagination > .disabled > span:hover, +.pagination > .disabled > span:focus, +.pagination > .disabled > a, +.pagination > .disabled > a:hover, +.pagination > .disabled > a:focus { + color: #999; + cursor: not-allowed; + background-color: #fff; + border-color: #ddd; +} +.pagination-lg > li > a, +.pagination-lg > li > span { + padding: 10px 16px; + font-size: 18px; +} +.pagination-lg > li:first-child > a, +.pagination-lg > li:first-child > span { + border-top-left-radius: 6px; + border-bottom-left-radius: 6px; +} +.pagination-lg > li:last-child > a, +.pagination-lg > li:last-child > span { + border-top-right-radius: 6px; + border-bottom-right-radius: 6px; +} +.pagination-sm > li > a, +.pagination-sm > li > span { + padding: 5px 10px; + font-size: 12px; +} +.pagination-sm > li:first-child > a, +.pagination-sm > li:first-child > span { + border-top-left-radius: 3px; + border-bottom-left-radius: 3px; +} +.pagination-sm > li:last-child > a, +.pagination-sm > li:last-child > span { + border-top-right-radius: 3px; + border-bottom-right-radius: 3px; +} +.pager { + padding-left: 0; + margin: 20px 0; + text-align: center; + list-style: none; +} +.pager li { + display: inline; +} +.pager li > a, +.pager li > span { + display: inline-block; + padding: 5px 14px; + background-color: #fff; + border: 1px solid #ddd; + border-radius: 15px; +} +.pager li > a:hover, +.pager li > a:focus { + text-decoration: none; + background-color: #eee; +} +.pager .next > a, +.pager .next > span { + float: right; +} +.pager .previous > a, +.pager .previous > span { + float: left; +} +.pager .disabled > a, +.pager .disabled > a:hover, +.pager .disabled > a:focus, +.pager .disabled > span { + color: #999; + cursor: not-allowed; + background-color: #fff; +} +.label { + display: inline; + padding: .2em .6em .3em; + font-size: 75%; + font-weight: bold; + line-height: 1; + color: #fff; + text-align: center; + white-space: nowrap; + vertical-align: baseline; + border-radius: .25em; +} +.label[href]:hover, +.label[href]:focus { + color: #fff; + text-decoration: none; + cursor: pointer; +} +.label:empty { + display: none; +} +.btn .label { + position: relative; + top: -1px; +} +.label-default { + background-color: #999; +} +.label-default[href]:hover, +.label-default[href]:focus { + background-color: #808080; +} +.label-primary { + background-color: #428bca; +} +.label-primary[href]:hover, +.label-primary[href]:focus { + background-color: #3071a9; +} +.label-success { + background-color: #5cb85c; +} +.label-success[href]:hover, +.label-success[href]:focus { + background-color: #449d44; +} +.label-info { + background-color: #5bc0de; +} +.label-info[href]:hover, +.label-info[href]:focus { + background-color: #31b0d5; +} +.label-warning { + background-color: #f0ad4e; +} +.label-warning[href]:hover, +.label-warning[href]:focus { + background-color: #ec971f; +} +.label-danger { + background-color: #d9534f; +} +.label-danger[href]:hover, +.label-danger[href]:focus { + background-color: #c9302c; +} +.badge { + display: inline-block; + min-width: 10px; + padding: 3px 7px; + font-size: 12px; + font-weight: bold; + line-height: 1; + color: #fff; + text-align: center; + white-space: nowrap; + vertical-align: baseline; + background-color: #999; + border-radius: 10px; +} +.badge:empty { + display: none; +} +.btn .badge { + position: relative; + top: -1px; +} +.btn-xs .badge { + top: 0; + padding: 1px 5px; +} +a.badge:hover, +a.badge:focus { + color: #fff; + text-decoration: none; + cursor: pointer; +} +a.list-group-item.active > .badge, +.nav-pills > .active > a > .badge { + color: #428bca; + background-color: #fff; +} +.nav-pills > li > a > .badge { + margin-left: 3px; +} +.jumbotron { + padding: 30px; + margin-bottom: 30px; + color: inherit; + background-color: #eee; +} +.jumbotron h1, +.jumbotron .h1 { + color: inherit; +} +.jumbotron p { + margin-bottom: 15px; + font-size: 21px; + font-weight: 200; +} +.container .jumbotron { + border-radius: 6px; +} +.jumbotron .container { + max-width: 100%; +} +@media screen and (min-width: 768px) { + .jumbotron { + padding-top: 48px; + padding-bottom: 48px; + } + .container .jumbotron { + padding-right: 60px; + padding-left: 60px; + } + .jumbotron h1, + .jumbotron .h1 { + font-size: 63px; + } +} +.thumbnail { + display: block; + padding: 4px; + margin-bottom: 20px; + line-height: 1.428571429; + background-color: #fff; + border: 1px solid #ddd; + border-radius: 4px; + -webkit-transition: all .2s ease-in-out; + transition: all .2s ease-in-out; +} +.thumbnail > img, +.thumbnail a > img { + display: block; + max-width: 100%; + height: auto; + margin-right: auto; + margin-left: auto; +} +a.thumbnail:hover, +a.thumbnail:focus, +a.thumbnail.active { + border-color: #428bca; +} +.thumbnail .caption { + padding: 9px; + color: #333; +} +.alert { + padding: 15px; + margin-bottom: 20px; + border: 1px solid transparent; + border-radius: 4px; +} +.alert h4 { + margin-top: 0; + color: inherit; +} +.alert .alert-link { + font-weight: bold; +} +.alert > p, +.alert > ul { + margin-bottom: 0; +} +.alert > p + p { + margin-top: 5px; +} +.alert-dismissable { + padding-right: 35px; +} +.alert-dismissable .close { + position: relative; + top: -2px; + right: -21px; + color: inherit; +} +.alert-success { + color: #3c763d; + background-color: #dff0d8; + border-color: #d6e9c6; +} +.alert-success hr { + border-top-color: #c9e2b3; +} +.alert-success .alert-link { + color: #2b542c; +} +.alert-info { + color: #31708f; + background-color: #d9edf7; + border-color: #bce8f1; +} +.alert-info hr { + border-top-color: #a6e1ec; +} +.alert-info .alert-link { + color: #245269; +} +.alert-warning { + color: #8a6d3b; + background-color: #fcf8e3; + border-color: #faebcc; +} +.alert-warning hr { + border-top-color: #f7e1b5; +} +.alert-warning .alert-link { + color: #66512c; +} +.alert-danger { + color: #a94442; + background-color: #f2dede; + border-color: #ebccd1; +} +.alert-danger hr { + border-top-color: #e4b9c0; +} +.alert-danger .alert-link { + color: #843534; +} +@-webkit-keyframes progress-bar-stripes { + from { + background-position: 40px 0; + } + to { + background-position: 0 0; + } +} +@keyframes progress-bar-stripes { + from { + background-position: 40px 0; + } + to { + background-position: 0 0; + } +} +.progress { + height: 20px; + margin-bottom: 20px; + overflow: hidden; + background-color: #f5f5f5; + border-radius: 4px; + -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, .1); + box-shadow: inset 0 1px 2px rgba(0, 0, 0, .1); +} +.progress-bar { + float: left; + width: 0; + height: 100%; + font-size: 12px; + line-height: 20px; + color: #fff; + text-align: center; + background-color: #428bca; + -webkit-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, .15); + box-shadow: inset 0 -1px 0 rgba(0, 0, 0, .15); + -webkit-transition: width .6s ease; + transition: width .6s ease; +} +.progress-striped .progress-bar { + 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: 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-size: 40px 40px; +} +.progress.active .progress-bar { + -webkit-animation: progress-bar-stripes 2s linear infinite; + animation: progress-bar-stripes 2s linear infinite; +} +.progress-bar-success { + background-color: #5cb85c; +} +.progress-striped .progress-bar-success { + background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); + background-image: linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); +} +.progress-bar-info { + background-color: #5bc0de; +} +.progress-striped .progress-bar-info { + background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); + background-image: linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); +} +.progress-bar-warning { + background-color: #f0ad4e; +} +.progress-striped .progress-bar-warning { + background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); + background-image: linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); +} +.progress-bar-danger { + background-color: #d9534f; +} +.progress-striped .progress-bar-danger { + background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); + background-image: linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); +} +.media, +.media-body { + overflow: hidden; + zoom: 1; +} +.media, +.media .media { + margin-top: 15px; +} +.media:first-child { + margin-top: 0; +} +.media-object { + display: block; +} +.media-heading { + margin: 0 0 5px; +} +.media > .pull-left { + margin-right: 10px; +} +.media > .pull-right { + margin-left: 10px; +} +.media-list { + padding-left: 0; + list-style: none; +} +.list-group { + padding-left: 0; + margin-bottom: 20px; +} +.list-group-item { + position: relative; + display: block; + padding: 10px 15px; + margin-bottom: -1px; + background-color: #fff; + border: 1px solid #ddd; +} +.list-group-item:first-child { + border-top-left-radius: 4px; + border-top-right-radius: 4px; +} +.list-group-item:last-child { + margin-bottom: 0; + border-bottom-right-radius: 4px; + border-bottom-left-radius: 4px; +} +.list-group-item > .badge { + float: right; +} +.list-group-item > .badge + .badge { + margin-right: 5px; +} +a.list-group-item { + color: #555; +} +a.list-group-item .list-group-item-heading { + color: #333; +} +a.list-group-item:hover, +a.list-group-item:focus { + text-decoration: none; + background-color: #f5f5f5; +} +a.list-group-item.active, +a.list-group-item.active:hover, +a.list-group-item.active:focus { + z-index: 2; + color: #fff; + background-color: #428bca; + border-color: #428bca; +} +a.list-group-item.active .list-group-item-heading, +a.list-group-item.active:hover .list-group-item-heading, +a.list-group-item.active:focus .list-group-item-heading { + color: inherit; +} +a.list-group-item.active .list-group-item-text, +a.list-group-item.active:hover .list-group-item-text, +a.list-group-item.active:focus .list-group-item-text { + color: #e1edf7; +} +.list-group-item-success { + color: #3c763d; + background-color: #dff0d8; +} +a.list-group-item-success { + color: #3c763d; +} +a.list-group-item-success .list-group-item-heading { + color: inherit; +} +a.list-group-item-success:hover, +a.list-group-item-success:focus { + color: #3c763d; + background-color: #d0e9c6; +} +a.list-group-item-success.active, +a.list-group-item-success.active:hover, +a.list-group-item-success.active:focus { + color: #fff; + background-color: #3c763d; + border-color: #3c763d; +} +.list-group-item-info { + color: #31708f; + background-color: #d9edf7; +} +a.list-group-item-info { + color: #31708f; +} +a.list-group-item-info .list-group-item-heading { + color: inherit; +} +a.list-group-item-info:hover, +a.list-group-item-info:focus { + color: #31708f; + background-color: #c4e3f3; +} +a.list-group-item-info.active, +a.list-group-item-info.active:hover, +a.list-group-item-info.active:focus { + color: #fff; + background-color: #31708f; + border-color: #31708f; +} +.list-group-item-warning { + color: #8a6d3b; + background-color: #fcf8e3; +} +a.list-group-item-warning { + color: #8a6d3b; +} +a.list-group-item-warning .list-group-item-heading { + color: inherit; +} +a.list-group-item-warning:hover, +a.list-group-item-warning:focus { + color: #8a6d3b; + background-color: #faf2cc; +} +a.list-group-item-warning.active, +a.list-group-item-warning.active:hover, +a.list-group-item-warning.active:focus { + color: #fff; + background-color: #8a6d3b; + border-color: #8a6d3b; +} +.list-group-item-danger { + color: #a94442; + background-color: #f2dede; +} +a.list-group-item-danger { + color: #a94442; +} +a.list-group-item-danger .list-group-item-heading { + color: inherit; +} +a.list-group-item-danger:hover, +a.list-group-item-danger:focus { + color: #a94442; + background-color: #ebcccc; +} +a.list-group-item-danger.active, +a.list-group-item-danger.active:hover, +a.list-group-item-danger.active:focus { + color: #fff; + background-color: #a94442; + border-color: #a94442; +} +.list-group-item-heading { + margin-top: 0; + margin-bottom: 5px; +} +.list-group-item-text { + margin-bottom: 0; + line-height: 1.3; +} +.panel { + margin-bottom: 20px; + background-color: #fff; + border: 1px solid transparent; + border-radius: 4px; + -webkit-box-shadow: 0 1px 1px rgba(0, 0, 0, .05); + box-shadow: 0 1px 1px rgba(0, 0, 0, .05); +} +.panel-body { + padding: 15px; +} +.panel > .list-group { + margin-bottom: 0; +} +.panel > .list-group .list-group-item { + border-width: 1px 0; + border-radius: 0; +} +.panel > .list-group .list-group-item:first-child { + border-top: 0; +} +.panel > .list-group .list-group-item:last-child { + border-bottom: 0; +} +.panel > .list-group:first-child .list-group-item:first-child { + border-top-left-radius: 3px; + border-top-right-radius: 3px; +} +.panel > .list-group:last-child .list-group-item:last-child { + border-bottom-right-radius: 3px; + border-bottom-left-radius: 3px; +} +.panel-heading + .list-group .list-group-item:first-child { + border-top-width: 0; +} +.panel > .table, +.panel > .table-responsive > .table { + margin-bottom: 0; +} +.panel > .table:first-child > thead:first-child > tr:first-child td:first-child, +.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child td:first-child, +.panel > .table:first-child > tbody:first-child > tr:first-child td:first-child, +.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child td:first-child, +.panel > .table:first-child > thead:first-child > tr:first-child th:first-child, +.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child th:first-child, +.panel > .table:first-child > tbody:first-child > tr:first-child th:first-child, +.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child th:first-child { + border-top-left-radius: 3px; +} +.panel > .table:first-child > thead:first-child > tr:first-child td:last-child, +.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child td:last-child, +.panel > .table:first-child > tbody:first-child > tr:first-child td:last-child, +.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child td:last-child, +.panel > .table:first-child > thead:first-child > tr:first-child th:last-child, +.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child th:last-child, +.panel > .table:first-child > tbody:first-child > tr:first-child th:last-child, +.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child th:last-child { + border-top-right-radius: 3px; +} +.panel > .table:last-child > tbody:last-child > tr:last-child td:first-child, +.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child td:first-child, +.panel > .table:last-child > tfoot:last-child > tr:last-child td:first-child, +.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child td:first-child, +.panel > .table:last-child > tbody:last-child > tr:last-child th:first-child, +.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child th:first-child, +.panel > .table:last-child > tfoot:last-child > tr:last-child th:first-child, +.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child th:first-child { + border-bottom-left-radius: 3px; +} +.panel > .table:last-child > tbody:last-child > tr:last-child td:last-child, +.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child td:last-child, +.panel > .table:last-child > tfoot:last-child > tr:last-child td:last-child, +.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child td:last-child, +.panel > .table:last-child > tbody:last-child > tr:last-child th:last-child, +.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child th:last-child, +.panel > .table:last-child > tfoot:last-child > tr:last-child th:last-child, +.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child th:last-child { + border-bottom-right-radius: 3px; +} +.panel > .panel-body + .table, +.panel > .panel-body + .table-responsive { + border-top: 1px solid #ddd; +} +.panel > .table > tbody:first-child > tr:first-child th, +.panel > .table > tbody:first-child > tr:first-child td { + border-top: 0; +} +.panel > .table-bordered, +.panel > .table-responsive > .table-bordered { + border: 0; +} +.panel > .table-bordered > thead > tr > th:first-child, +.panel > .table-responsive > .table-bordered > thead > tr > th:first-child, +.panel > .table-bordered > tbody > tr > th:first-child, +.panel > .table-responsive > .table-bordered > tbody > tr > th:first-child, +.panel > .table-bordered > tfoot > tr > th:first-child, +.panel > .table-responsive > .table-bordered > tfoot > tr > th:first-child, +.panel > .table-bordered > thead > tr > td:first-child, +.panel > .table-responsive > .table-bordered > thead > tr > td:first-child, +.panel > .table-bordered > tbody > tr > td:first-child, +.panel > .table-responsive > .table-bordered > tbody > tr > td:first-child, +.panel > .table-bordered > tfoot > tr > td:first-child, +.panel > .table-responsive > .table-bordered > tfoot > tr > td:first-child { + border-left: 0; +} +.panel > .table-bordered > thead > tr > th:last-child, +.panel > .table-responsive > .table-bordered > thead > tr > th:last-child, +.panel > .table-bordered > tbody > tr > th:last-child, +.panel > .table-responsive > .table-bordered > tbody > tr > th:last-child, +.panel > .table-bordered > tfoot > tr > th:last-child, +.panel > .table-responsive > .table-bordered > tfoot > tr > th:last-child, +.panel > .table-bordered > thead > tr > td:last-child, +.panel > .table-responsive > .table-bordered > thead > tr > td:last-child, +.panel > .table-bordered > tbody > tr > td:last-child, +.panel > .table-responsive > .table-bordered > tbody > tr > td:last-child, +.panel > .table-bordered > tfoot > tr > td:last-child, +.panel > .table-responsive > .table-bordered > tfoot > tr > td:last-child { + border-right: 0; +} +.panel > .table-bordered > thead > tr:first-child > th, +.panel > .table-responsive > .table-bordered > thead > tr:first-child > th, +.panel > .table-bordered > tbody > tr:first-child > th, +.panel > .table-responsive > .table-bordered > tbody > tr:first-child > th, +.panel > .table-bordered > tfoot > tr:first-child > th, +.panel > .table-responsive > .table-bordered > tfoot > tr:first-child > th, +.panel > .table-bordered > thead > tr:first-child > td, +.panel > .table-responsive > .table-bordered > thead > tr:first-child > td, +.panel > .table-bordered > tbody > tr:first-child > td, +.panel > .table-responsive > .table-bordered > tbody > tr:first-child > td, +.panel > .table-bordered > tfoot > tr:first-child > td, +.panel > .table-responsive > .table-bordered > tfoot > tr:first-child > td { + border-top: 0; +} +.panel > .table-bordered > thead > tr:last-child > th, +.panel > .table-responsive > .table-bordered > thead > tr:last-child > th, +.panel > .table-bordered > tbody > tr:last-child > th, +.panel > .table-responsive > .table-bordered > tbody > tr:last-child > th, +.panel > .table-bordered > tfoot > tr:last-child > th, +.panel > .table-responsive > .table-bordered > tfoot > tr:last-child > th, +.panel > .table-bordered > thead > tr:last-child > td, +.panel > .table-responsive > .table-bordered > thead > tr:last-child > td, +.panel > .table-bordered > tbody > tr:last-child > td, +.panel > .table-responsive > .table-bordered > tbody > tr:last-child > td, +.panel > .table-bordered > tfoot > tr:last-child > td, +.panel > .table-responsive > .table-bordered > tfoot > tr:last-child > td { + border-bottom: 0; +} +.panel > .table-responsive { + margin-bottom: 0; + border: 0; +} +.panel-heading { + padding: 10px 15px; + border-bottom: 1px solid transparent; + border-top-left-radius: 3px; + border-top-right-radius: 3px; +} +.panel-heading > .dropdown .dropdown-toggle { + color: inherit; +} +.panel-title { + margin-top: 0; + margin-bottom: 0; + font-size: 16px; + color: inherit; +} +.panel-title > a { + color: inherit; +} +.panel-footer { + padding: 10px 15px; + background-color: #f5f5f5; + border-top: 1px solid #ddd; + border-bottom-right-radius: 3px; + border-bottom-left-radius: 3px; +} +.panel-group { + margin-bottom: 20px; +} +.panel-group .panel { + margin-bottom: 0; + overflow: hidden; + border-radius: 4px; +} +.panel-group .panel + .panel { + margin-top: 5px; +} +.panel-group .panel-heading { + border-bottom: 0; +} +.panel-group .panel-heading + .panel-collapse .panel-body { + border-top: 1px solid #ddd; +} +.panel-group .panel-footer { + border-top: 0; +} +.panel-group .panel-footer + .panel-collapse .panel-body { + border-bottom: 1px solid #ddd; +} +.panel-default { + border-color: #ddd; +} +.panel-default > .panel-heading { + color: #333; + background-color: #f5f5f5; + border-color: #ddd; +} +.panel-default > .panel-heading + .panel-collapse .panel-body { + border-top-color: #ddd; +} +.panel-default > .panel-footer + .panel-collapse .panel-body { + border-bottom-color: #ddd; +} +.panel-primary { + border-color: #428bca; +} +.panel-primary > .panel-heading { + color: #fff; + background-color: #428bca; + border-color: #428bca; +} +.panel-primary > .panel-heading + .panel-collapse .panel-body { + border-top-color: #428bca; +} +.panel-primary > .panel-footer + .panel-collapse .panel-body { + border-bottom-color: #428bca; +} +.panel-success { + border-color: #d6e9c6; +} +.panel-success > .panel-heading { + color: #3c763d; + background-color: #dff0d8; + border-color: #d6e9c6; +} +.panel-success > .panel-heading + .panel-collapse .panel-body { + border-top-color: #d6e9c6; +} +.panel-success > .panel-footer + .panel-collapse .panel-body { + border-bottom-color: #d6e9c6; +} +.panel-info { + border-color: #bce8f1; +} +.panel-info > .panel-heading { + color: #31708f; + background-color: #d9edf7; + border-color: #bce8f1; +} +.panel-info > .panel-heading + .panel-collapse .panel-body { + border-top-color: #bce8f1; +} +.panel-info > .panel-footer + .panel-collapse .panel-body { + border-bottom-color: #bce8f1; +} +.panel-warning { + border-color: #faebcc; +} +.panel-warning > .panel-heading { + color: #8a6d3b; + background-color: #fcf8e3; + border-color: #faebcc; +} +.panel-warning > .panel-heading + .panel-collapse .panel-body { + border-top-color: #faebcc; +} +.panel-warning > .panel-footer + .panel-collapse .panel-body { + border-bottom-color: #faebcc; +} +.panel-danger { + border-color: #ebccd1; +} +.panel-danger > .panel-heading { + color: #a94442; + background-color: #f2dede; + border-color: #ebccd1; +} +.panel-danger > .panel-heading + .panel-collapse .panel-body { + border-top-color: #ebccd1; +} +.panel-danger > .panel-footer + .panel-collapse .panel-body { + border-bottom-color: #ebccd1; +} +.well { + min-height: 20px; + padding: 19px; + margin-bottom: 20px; + background-color: #f5f5f5; + border: 1px solid #e3e3e3; + border-radius: 4px; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .05); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, .05); +} +.well blockquote { + border-color: #ddd; + border-color: rgba(0, 0, 0, .15); +} +.well-lg { + padding: 24px; + border-radius: 6px; +} +.well-sm { + padding: 9px; + border-radius: 3px; +} +.close { + float: right; + font-size: 21px; + font-weight: bold; + line-height: 1; + color: #000; + text-shadow: 0 1px 0 #fff; + filter: alpha(opacity=20); + opacity: .2; +} +.close:hover, +.close:focus { + color: #000; + text-decoration: none; + cursor: pointer; + filter: alpha(opacity=50); + opacity: .5; +} +button.close { + -webkit-appearance: none; + padding: 0; + cursor: pointer; + background: transparent; + border: 0; +} +.modal-open { + overflow: hidden; +} +.modal { + position: fixed; + top: 0; + right: 0; + bottom: 0; + left: 0; + z-index: 1050; + display: none; + overflow: auto; + overflow-y: scroll; + -webkit-overflow-scrolling: touch; + outline: 0; +} +.modal.fade .modal-dialog { + -webkit-transition: -webkit-transform .3s ease-out; + -moz-transition: -moz-transform .3s ease-out; + -o-transition: -o-transform .3s ease-out; + transition: transform .3s ease-out; + -webkit-transform: translate(0, -25%); + -ms-transform: translate(0, -25%); + transform: translate(0, -25%); +} +.modal.in .modal-dialog { + -webkit-transform: translate(0, 0); + -ms-transform: translate(0, 0); + transform: translate(0, 0); +} +.modal-dialog { + position: relative; + width: auto; + margin: 10px; +} +.modal-content { + position: relative; + background-color: #fff; + background-clip: padding-box; + border: 1px solid #999; + border: 1px solid rgba(0, 0, 0, .2); + border-radius: 6px; + outline: none; + -webkit-box-shadow: 0 3px 9px rgba(0, 0, 0, .5); + box-shadow: 0 3px 9px rgba(0, 0, 0, .5); +} +.modal-backdrop { + position: fixed; + top: 0; + right: 0; + bottom: 0; + left: 0; + z-index: 1040; + background-color: #000; +} +.modal-backdrop.fade { + filter: alpha(opacity=0); + opacity: 0; +} +.modal-backdrop.in { + filter: alpha(opacity=50); + opacity: .5; +} +.modal-header { + min-height: 16.428571429px; + padding: 15px; + border-bottom: 1px solid #e5e5e5; +} +.modal-header .close { + margin-top: -2px; +} +.modal-title { + margin: 0; + line-height: 1.428571429; +} +.modal-body { + position: relative; + padding: 20px; +} +.modal-footer { + padding: 19px 20px 20px; + margin-top: 15px; + text-align: right; + border-top: 1px solid #e5e5e5; +} +.modal-footer .btn + .btn { + margin-bottom: 0; + margin-left: 5px; +} +.modal-footer .btn-group .btn + .btn { + margin-left: -1px; +} +.modal-footer .btn-block + .btn-block { + margin-left: 0; +} +@media (min-width: 768px) { + .modal-dialog { + width: 600px; + margin: 30px auto; + } + .modal-content { + -webkit-box-shadow: 0 5px 15px rgba(0, 0, 0, .5); + box-shadow: 0 5px 15px rgba(0, 0, 0, .5); + } + .modal-sm { + width: 300px; + } + .modal-lg { + width: 900px; + } +} +.tooltip { + position: absolute; + z-index: 1030; + display: block; + font-size: 12px; + line-height: 1.4; + visibility: visible; + filter: alpha(opacity=0); + opacity: 0; +} +.tooltip.in { + filter: alpha(opacity=90); + opacity: .9; +} +.tooltip.top { + padding: 5px 0; + margin-top: -3px; +} +.tooltip.right { + padding: 0 5px; + margin-left: 3px; +} +.tooltip.bottom { + padding: 5px 0; + margin-top: 3px; +} +.tooltip.left { + padding: 0 5px; + margin-left: -3px; +} +.tooltip-inner { + max-width: 200px; + padding: 3px 8px; + color: #fff; + text-align: center; + text-decoration: none; + background-color: #000; + border-radius: 4px; +} +.tooltip-arrow { + position: absolute; + width: 0; + height: 0; + border-color: transparent; + border-style: solid; +} +.tooltip.top .tooltip-arrow { + bottom: 0; + left: 50%; + margin-left: -5px; + border-width: 5px 5px 0; + border-top-color: #000; +} +.tooltip.top-left .tooltip-arrow { + bottom: 0; + left: 5px; + border-width: 5px 5px 0; + border-top-color: #000; +} +.tooltip.top-right .tooltip-arrow { + right: 5px; + bottom: 0; + border-width: 5px 5px 0; + border-top-color: #000; +} +.tooltip.right .tooltip-arrow { + top: 50%; + left: 0; + margin-top: -5px; + border-width: 5px 5px 5px 0; + border-right-color: #000; +} +.tooltip.left .tooltip-arrow { + top: 50%; + right: 0; + margin-top: -5px; + border-width: 5px 0 5px 5px; + border-left-color: #000; +} +.tooltip.bottom .tooltip-arrow { + top: 0; + left: 50%; + margin-left: -5px; + border-width: 0 5px 5px; + border-bottom-color: #000; +} +.tooltip.bottom-left .tooltip-arrow { + top: 0; + left: 5px; + border-width: 0 5px 5px; + border-bottom-color: #000; +} +.tooltip.bottom-right .tooltip-arrow { + top: 0; + right: 5px; + border-width: 0 5px 5px; + border-bottom-color: #000; +} +.popover { + position: absolute; + top: 0; + left: 0; + z-index: 1010; + display: none; + max-width: 276px; + padding: 1px; + text-align: left; + white-space: normal; + background-color: #fff; + background-clip: padding-box; + border: 1px solid #ccc; + border: 1px solid rgba(0, 0, 0, .2); + border-radius: 6px; + -webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, .2); + box-shadow: 0 5px 10px rgba(0, 0, 0, .2); +} +.popover.top { + margin-top: -10px; +} +.popover.right { + margin-left: 10px; +} +.popover.bottom { + margin-top: 10px; +} +.popover.left { + margin-left: -10px; +} +.popover-title { + padding: 8px 14px; + margin: 0; + font-size: 14px; + font-weight: normal; + line-height: 18px; + background-color: #f7f7f7; + border-bottom: 1px solid #ebebeb; + border-radius: 5px 5px 0 0; +} +.popover-content { + padding: 9px 14px; +} +.popover .arrow, +.popover .arrow:after { + position: absolute; + display: block; + width: 0; + height: 0; + border-color: transparent; + border-style: solid; +} +.popover .arrow { + border-width: 11px; +} +.popover .arrow:after { + content: ""; + border-width: 10px; +} +.popover.top .arrow { + bottom: -11px; + left: 50%; + margin-left: -11px; + border-top-color: #999; + border-top-color: rgba(0, 0, 0, .25); + border-bottom-width: 0; +} +.popover.top .arrow:after { + bottom: 1px; + margin-left: -10px; + content: " "; + border-top-color: #fff; + border-bottom-width: 0; +} +.popover.right .arrow { + top: 50%; + left: -11px; + margin-top: -11px; + border-right-color: #999; + border-right-color: rgba(0, 0, 0, .25); + border-left-width: 0; +} +.popover.right .arrow:after { + bottom: -10px; + left: 1px; + content: " "; + border-right-color: #fff; + border-left-width: 0; +} +.popover.bottom .arrow { + top: -11px; + left: 50%; + margin-left: -11px; + border-top-width: 0; + border-bottom-color: #999; + border-bottom-color: rgba(0, 0, 0, .25); +} +.popover.bottom .arrow:after { + top: 1px; + margin-left: -10px; + content: " "; + border-top-width: 0; + border-bottom-color: #fff; +} +.popover.left .arrow { + top: 50%; + right: -11px; + margin-top: -11px; + border-right-width: 0; + border-left-color: #999; + border-left-color: rgba(0, 0, 0, .25); +} +.popover.left .arrow:after { + right: 1px; + bottom: -10px; + content: " "; + border-right-width: 0; + border-left-color: #fff; +} +.carousel { + position: relative; +} +.carousel-inner { + position: relative; + width: 100%; + overflow: hidden; +} +.carousel-inner > .item { + position: relative; + display: none; + -webkit-transition: .6s ease-in-out left; + transition: .6s ease-in-out left; +} +.carousel-inner > .item > img, +.carousel-inner > .item > a > img { + display: block; + max-width: 100%; + height: auto; + line-height: 1; +} +.carousel-inner > .active, +.carousel-inner > .next, +.carousel-inner > .prev { + display: block; +} +.carousel-inner > .active { + left: 0; +} +.carousel-inner > .next, +.carousel-inner > .prev { + position: absolute; + top: 0; + width: 100%; +} +.carousel-inner > .next { + left: 100%; +} +.carousel-inner > .prev { + left: -100%; +} +.carousel-inner > .next.left, +.carousel-inner > .prev.right { + left: 0; +} +.carousel-inner > .active.left { + left: -100%; +} +.carousel-inner > .active.right { + left: 100%; +} +.carousel-control { + position: absolute; + top: 0; + bottom: 0; + left: 0; + width: 15%; + font-size: 20px; + color: #fff; + text-align: center; + text-shadow: 0 1px 2px rgba(0, 0, 0, .6); + filter: alpha(opacity=50); + opacity: .5; +} +.carousel-control.left { + background-image: -webkit-linear-gradient(left, color-stop(rgba(0, 0, 0, .5) 0%), color-stop(rgba(0, 0, 0, .0001) 100%)); + background-image: linear-gradient(to right, rgba(0, 0, 0, .5) 0%, rgba(0, 0, 0, .0001) 100%); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#80000000', endColorstr='#00000000', GradientType=1); + background-repeat: repeat-x; +} +.carousel-control.right { + right: 0; + left: auto; + background-image: -webkit-linear-gradient(left, color-stop(rgba(0, 0, 0, .0001) 0%), color-stop(rgba(0, 0, 0, .5) 100%)); + background-image: linear-gradient(to right, rgba(0, 0, 0, .0001) 0%, rgba(0, 0, 0, .5) 100%); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#00000000', endColorstr='#80000000', GradientType=1); + background-repeat: repeat-x; +} +.carousel-control:hover, +.carousel-control:focus { + color: #fff; + text-decoration: none; + filter: alpha(opacity=90); + outline: none; + opacity: .9; +} +.carousel-control .icon-prev, +.carousel-control .icon-next, +.carousel-control .glyphicon-chevron-left, +.carousel-control .glyphicon-chevron-right { + position: absolute; + top: 50%; + z-index: 5; + display: inline-block; +} +.carousel-control .icon-prev, +.carousel-control .glyphicon-chevron-left { + left: 50%; +} +.carousel-control .icon-next, +.carousel-control .glyphicon-chevron-right { + right: 50%; +} +.carousel-control .icon-prev, +.carousel-control .icon-next { + width: 20px; + height: 20px; + margin-top: -10px; + margin-left: -10px; + font-family: serif; +} +.carousel-control .icon-prev:before { + content: '\2039'; +} +.carousel-control .icon-next:before { + content: '\203a'; +} +.carousel-indicators { + position: absolute; + bottom: 10px; + left: 50%; + z-index: 15; + width: 60%; + padding-left: 0; + margin-left: -30%; + text-align: center; + list-style: none; +} +.carousel-indicators li { + display: inline-block; + width: 10px; + height: 10px; + margin: 1px; + text-indent: -999px; + cursor: pointer; + background-color: #000 \9; + background-color: rgba(0, 0, 0, 0); + border: 1px solid #fff; + border-radius: 10px; +} +.carousel-indicators .active { + width: 12px; + height: 12px; + margin: 0; + background-color: #fff; +} +.carousel-caption { + position: absolute; + right: 15%; + bottom: 20px; + left: 15%; + z-index: 10; + padding-top: 20px; + padding-bottom: 20px; + color: #fff; + text-align: center; + text-shadow: 0 1px 2px rgba(0, 0, 0, .6); +} +.carousel-caption .btn { + text-shadow: none; +} +@media screen and (min-width: 768px) { + .carousel-control .glyphicons-chevron-left, + .carousel-control .glyphicons-chevron-right, + .carousel-control .icon-prev, + .carousel-control .icon-next { + width: 30px; + height: 30px; + margin-top: -15px; + margin-left: -15px; + font-size: 30px; + } + .carousel-caption { + right: 20%; + left: 20%; + padding-bottom: 30px; + } + .carousel-indicators { + bottom: 20px; + } +} +.clearfix:before, +.clearfix:after, +.container:before, +.container:after, +.container-fluid:before, +.container-fluid:after, +.row:before, +.row:after, +.form-horizontal .form-group:before, +.form-horizontal .form-group:after, +.btn-toolbar:before, +.btn-toolbar:after, +.btn-group-vertical > .btn-group:before, +.btn-group-vertical > .btn-group:after, +.nav:before, +.nav:after, +.navbar:before, +.navbar:after, +.navbar-header:before, +.navbar-header:after, +.navbar-collapse:before, +.navbar-collapse:after, +.pager:before, +.pager:after, +.panel-body:before, +.panel-body:after, +.modal-footer:before, +.modal-footer:after { + display: table; + content: " "; +} +.clearfix:after, +.container:after, +.container-fluid:after, +.row:after, +.form-horizontal .form-group:after, +.btn-toolbar:after, +.btn-group-vertical > .btn-group:after, +.nav:after, +.navbar:after, +.navbar-header:after, +.navbar-collapse:after, +.pager:after, +.panel-body:after, +.modal-footer:after { + clear: both; +} +.center-block { + display: block; + margin-right: auto; + margin-left: auto; +} +.pull-right { + float: right !important; +} +.pull-left { + float: left !important; +} +.hide { + display: none !important; +} +.show { + display: block !important; +} +.invisible { + visibility: hidden; +} +.text-hide { + font: 0/0 a; + color: transparent; + text-shadow: none; + background-color: transparent; + border: 0; +} +.hidden { + display: none !important; + visibility: hidden !important; +} +.affix { + position: fixed; +} +@-ms-viewport { + width: device-width; +} +.visible-xs, +tr.visible-xs, +th.visible-xs, +td.visible-xs { + display: none !important; +} +@media (max-width: 767px) { + .visible-xs { + display: block !important; + } + table.visible-xs { + display: table; + } + tr.visible-xs { + display: table-row !important; + } + th.visible-xs, + td.visible-xs { + display: table-cell !important; + } +} +.visible-sm, +tr.visible-sm, +th.visible-sm, +td.visible-sm { + display: none !important; +} +@media (min-width: 768px) and (max-width: 991px) { + .visible-sm { + display: block !important; + } + table.visible-sm { + display: table; + } + tr.visible-sm { + display: table-row !important; + } + th.visible-sm, + td.visible-sm { + display: table-cell !important; + } +} +.visible-md, +tr.visible-md, +th.visible-md, +td.visible-md { + display: none !important; +} +@media (min-width: 992px) and (max-width: 1199px) { + .visible-md { + display: block !important; + } + table.visible-md { + display: table; + } + tr.visible-md { + display: table-row !important; + } + th.visible-md, + td.visible-md { + display: table-cell !important; + } +} +.visible-lg, +tr.visible-lg, +th.visible-lg, +td.visible-lg { + display: none !important; +} +@media (min-width: 1200px) { + .visible-lg { + display: block !important; + } + table.visible-lg { + display: table; + } + tr.visible-lg { + display: table-row !important; + } + th.visible-lg, + td.visible-lg { + display: table-cell !important; + } +} +@media (max-width: 767px) { + .hidden-xs, + tr.hidden-xs, + th.hidden-xs, + td.hidden-xs { + display: none !important; + } +} +@media (min-width: 768px) and (max-width: 991px) { + .hidden-sm, + tr.hidden-sm, + th.hidden-sm, + td.hidden-sm { + display: none !important; + } +} +@media (min-width: 992px) and (max-width: 1199px) { + .hidden-md, + tr.hidden-md, + th.hidden-md, + td.hidden-md { + display: none !important; + } +} +@media (min-width: 1200px) { + .hidden-lg, + tr.hidden-lg, + th.hidden-lg, + td.hidden-lg { + display: none !important; + } +} +.visible-print, +tr.visible-print, +th.visible-print, +td.visible-print { + display: none !important; +} +@media print { + .visible-print { + display: block !important; + } + table.visible-print { + display: table; + } + tr.visible-print { + display: table-row !important; + } + th.visible-print, + td.visible-print { + display: table-cell !important; + } +} +@media print { + .hidden-print, + tr.hidden-print, + th.hidden-print, + td.hidden-print { + display: none !important; + } +} +/*# sourceMappingURL=bootstrap.css.map */ diff --git a/software/openvisualizer/bin/openVisualizerApp/web_files/static/css/bootstrap.min.css b/software/openvisualizer/bin/openVisualizerApp/web_files/static/css/bootstrap.min.css new file mode 100755 index 000000000..381834ec8 --- /dev/null +++ b/software/openvisualizer/bin/openVisualizerApp/web_files/static/css/bootstrap.min.css @@ -0,0 +1,7 @@ +/*! + * Bootstrap v3.1.0 (http://getbootstrap.com) + * Copyright 2011-2014 Twitter, Inc. + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) + */ + +/*! normalize.css v3.0.0 | MIT License | git.io/normalize */html{font-family:sans-serif;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}body{margin:0}article,aside,details,figcaption,figure,footer,header,hgroup,main,nav,section,summary{display:block}audio,canvas,progress,video{display:inline-block;vertical-align:baseline}audio:not([controls]){display:none;height:0}[hidden],template{display:none}a{background:0 0}a:active,a:hover{outline:0}abbr[title]{border-bottom:1px dotted}b,strong{font-weight:700}dfn{font-style:italic}h1{font-size:2em;margin:.67em 0}mark{background:#ff0;color:#000}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sup{top:-.5em}sub{bottom:-.25em}img{border:0}svg:not(:root){overflow:hidden}figure{margin:1em 40px}hr{-moz-box-sizing:content-box;box-sizing:content-box;height:0}pre{overflow:auto}code,kbd,pre,samp{font-family:monospace,monospace;font-size:1em}button,input,optgroup,select,textarea{color:inherit;font:inherit;margin:0}button{overflow:visible}button,select{text-transform:none}button,html input[type=button],input[type=reset],input[type=submit]{-webkit-appearance:button;cursor:pointer}button[disabled],html input[disabled]{cursor:default}button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}input{line-height:normal}input[type=checkbox],input[type=radio]{box-sizing:border-box;padding:0}input[type=number]::-webkit-inner-spin-button,input[type=number]::-webkit-outer-spin-button{height:auto}input[type=search]{-webkit-appearance:textfield;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;box-sizing:content-box}input[type=search]::-webkit-search-cancel-button,input[type=search]::-webkit-search-decoration{-webkit-appearance:none}fieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em}legend{border:0;padding:0}textarea{overflow:auto}optgroup{font-weight:700}table{border-collapse:collapse;border-spacing:0}td,th{padding:0}@media print{*{text-shadow:none!important;color:#000!important;background:transparent!important;box-shadow:none!important}a,a:visited{text-decoration:underline}a[href]:after{content:" (" attr(href) ")"}abbr[title]:after{content:" (" attr(title) ")"}a[href^="javascript:"]:after,a[href^="#"]:after{content:""}pre,blockquote{border:1px solid #999;page-break-inside:avoid}thead{display:table-header-group}tr,img{page-break-inside:avoid}img{max-width:100%!important}p,h2,h3{orphans:3;widows:3}h2,h3{page-break-after:avoid}select{background:#fff!important}.navbar{display:none}.table td,.table th{background-color:#fff!important}.btn>.caret,.dropup>.btn>.caret{border-top-color:#000!important}.label{border:1px solid #000}.table{border-collapse:collapse!important}.table-bordered th,.table-bordered td{border:1px solid #ddd!important}}*{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}:before,:after{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}html{font-size:62.5%;-webkit-tap-highlight-color:rgba(0,0,0,0)}body{font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:14px;line-height:1.428571429;color:#333;background-color:#fff}input,button,select,textarea{font-family:inherit;font-size:inherit;line-height:inherit}a{color:#428bca;text-decoration:none}a:hover,a:focus{color:#2a6496;text-decoration:underline}a:focus{outline:thin dotted;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}figure{margin:0}img{vertical-align:middle}.img-responsive{display:block;max-width:100%;height:auto}.img-rounded{border-radius:6px}.img-thumbnail{padding:4px;line-height:1.428571429;background-color:#fff;border:1px solid #ddd;border-radius:4px;-webkit-transition:all .2s ease-in-out;transition:all .2s ease-in-out;display:inline-block;max-width:100%;height:auto}.img-circle{border-radius:50%}hr{margin-top:20px;margin-bottom:20px;border:0;border-top:1px solid #eee}.sr-only{position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;clip:rect(0,0,0,0);border:0}h1,h2,h3,h4,h5,h6,.h1,.h2,.h3,.h4,.h5,.h6{font-family:inherit;font-weight:500;line-height:1.1;color:inherit}h1 small,h2 small,h3 small,h4 small,h5 small,h6 small,.h1 small,.h2 small,.h3 small,.h4 small,.h5 small,.h6 small,h1 .small,h2 .small,h3 .small,h4 .small,h5 .small,h6 .small,.h1 .small,.h2 .small,.h3 .small,.h4 .small,.h5 .small,.h6 .small{font-weight:400;line-height:1;color:#999}h1,.h1,h2,.h2,h3,.h3{margin-top:20px;margin-bottom:10px}h1 small,.h1 small,h2 small,.h2 small,h3 small,.h3 small,h1 .small,.h1 .small,h2 .small,.h2 .small,h3 .small,.h3 .small{font-size:65%}h4,.h4,h5,.h5,h6,.h6{margin-top:10px;margin-bottom:10px}h4 small,.h4 small,h5 small,.h5 small,h6 small,.h6 small,h4 .small,.h4 .small,h5 .small,.h5 .small,h6 .small,.h6 .small{font-size:75%}h1,.h1{font-size:36px}h2,.h2{font-size:30px}h3,.h3{font-size:24px}h4,.h4{font-size:18px}h5,.h5{font-size:14px}h6,.h6{font-size:12px}p{margin:0 0 10px}.lead{margin-bottom:20px;font-size:16px;font-weight:200;line-height:1.4}@media (min-width:768px){.lead{font-size:21px}}small,.small{font-size:85%}cite{font-style:normal}.text-left{text-align:left}.text-right{text-align:right}.text-center{text-align:center}.text-justify{text-align:justify}.text-muted{color:#999}.text-primary{color:#428bca}a.text-primary:hover{color:#3071a9}.text-success{color:#3c763d}a.text-success:hover{color:#2b542c}.text-info{color:#31708f}a.text-info:hover{color:#245269}.text-warning{color:#8a6d3b}a.text-warning:hover{color:#66512c}.text-danger{color:#a94442}a.text-danger:hover{color:#843534}.bg-primary{color:#fff;background-color:#428bca}a.bg-primary:hover{background-color:#3071a9}.bg-success{background-color:#dff0d8}a.bg-success:hover{background-color:#c1e2b3}.bg-info{background-color:#d9edf7}a.bg-info:hover{background-color:#afd9ee}.bg-warning{background-color:#fcf8e3}a.bg-warning:hover{background-color:#f7ecb5}.bg-danger{background-color:#f2dede}a.bg-danger:hover{background-color:#e4b9b9}.page-header{padding-bottom:9px;margin:40px 0 20px;border-bottom:1px solid #eee}ul,ol{margin-top:0;margin-bottom:10px}ul ul,ol ul,ul ol,ol ol{margin-bottom:0}.list-unstyled{padding-left:0;list-style:none}.list-inline{padding-left:0;list-style:none}.list-inline>li{display:inline-block;padding-left:5px;padding-right:5px}.list-inline>li:first-child{padding-left:0}dl{margin-top:0;margin-bottom:20px}dt,dd{line-height:1.428571429}dt{font-weight:700}dd{margin-left:0}@media (min-width:768px){.dl-horizontal dt{float:left;width:160px;clear:left;text-align:right;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.dl-horizontal dd{margin-left:180px}}abbr[title],abbr[data-original-title]{cursor:help;border-bottom:1px dotted #999}.initialism{font-size:90%;text-transform:uppercase}blockquote{padding:10px 20px;margin:0 0 20px;font-size:17.5px;border-left:5px solid #eee}blockquote p:last-child,blockquote ul:last-child,blockquote ol:last-child{margin-bottom:0}blockquote footer,blockquote small,blockquote .small{display:block;font-size:80%;line-height:1.428571429;color:#999}blockquote footer:before,blockquote small:before,blockquote .small:before{content:'\2014 \00A0'}.blockquote-reverse,blockquote.pull-right{padding-right:15px;padding-left:0;border-right:5px solid #eee;border-left:0;text-align:right}.blockquote-reverse footer:before,blockquote.pull-right footer:before,.blockquote-reverse small:before,blockquote.pull-right small:before,.blockquote-reverse .small:before,blockquote.pull-right .small:before{content:''}.blockquote-reverse footer:after,blockquote.pull-right footer:after,.blockquote-reverse small:after,blockquote.pull-right small:after,.blockquote-reverse .small:after,blockquote.pull-right .small:after{content:'\00A0 \2014'}blockquote:before,blockquote:after{content:""}address{margin-bottom:20px;font-style:normal;line-height:1.428571429}code,kbd,pre,samp{font-family:Menlo,Monaco,Consolas,"Courier New",monospace}code{padding:2px 4px;font-size:90%;color:#c7254e;background-color:#f9f2f4;white-space:nowrap;border-radius:4px}kbd{padding:2px 4px;font-size:90%;color:#fff;background-color:#333;border-radius:3px;box-shadow:inset 0 -1px 0 rgba(0,0,0,.25)}pre{display:block;padding:9.5px;margin:0 0 10px;font-size:13px;line-height:1.428571429;word-break:break-all;word-wrap:break-word;color:#333;background-color:#f5f5f5;border:1px solid #ccc;border-radius:4px}pre code{padding:0;font-size:inherit;color:inherit;white-space:pre-wrap;background-color:transparent;border-radius:0}.pre-scrollable{max-height:340px;overflow-y:scroll}.container{margin-right:auto;margin-left:auto;padding-left:15px;padding-right:15px}@media (min-width:768px){.container{width:750px}}@media (min-width:992px){.container{width:970px}}@media (min-width:1200px){.container{width:1170px}}.container-fluid{margin-right:auto;margin-left:auto;padding-left:15px;padding-right:15px}.row{margin-left:-15px;margin-right:-15px}.col-xs-1,.col-sm-1,.col-md-1,.col-lg-1,.col-xs-2,.col-sm-2,.col-md-2,.col-lg-2,.col-xs-3,.col-sm-3,.col-md-3,.col-lg-3,.col-xs-4,.col-sm-4,.col-md-4,.col-lg-4,.col-xs-5,.col-sm-5,.col-md-5,.col-lg-5,.col-xs-6,.col-sm-6,.col-md-6,.col-lg-6,.col-xs-7,.col-sm-7,.col-md-7,.col-lg-7,.col-xs-8,.col-sm-8,.col-md-8,.col-lg-8,.col-xs-9,.col-sm-9,.col-md-9,.col-lg-9,.col-xs-10,.col-sm-10,.col-md-10,.col-lg-10,.col-xs-11,.col-sm-11,.col-md-11,.col-lg-11,.col-xs-12,.col-sm-12,.col-md-12,.col-lg-12{position:relative;min-height:1px;padding-left:15px;padding-right:15px}.col-xs-1,.col-xs-2,.col-xs-3,.col-xs-4,.col-xs-5,.col-xs-6,.col-xs-7,.col-xs-8,.col-xs-9,.col-xs-10,.col-xs-11,.col-xs-12{float:left}.col-xs-12{width:100%}.col-xs-11{width:91.66666666666666%}.col-xs-10{width:83.33333333333334%}.col-xs-9{width:75%}.col-xs-8{width:66.66666666666666%}.col-xs-7{width:58.333333333333336%}.col-xs-6{width:50%}.col-xs-5{width:41.66666666666667%}.col-xs-4{width:33.33333333333333%}.col-xs-3{width:25%}.col-xs-2{width:16.666666666666664%}.col-xs-1{width:8.333333333333332%}.col-xs-pull-12{right:100%}.col-xs-pull-11{right:91.66666666666666%}.col-xs-pull-10{right:83.33333333333334%}.col-xs-pull-9{right:75%}.col-xs-pull-8{right:66.66666666666666%}.col-xs-pull-7{right:58.333333333333336%}.col-xs-pull-6{right:50%}.col-xs-pull-5{right:41.66666666666667%}.col-xs-pull-4{right:33.33333333333333%}.col-xs-pull-3{right:25%}.col-xs-pull-2{right:16.666666666666664%}.col-xs-pull-1{right:8.333333333333332%}.col-xs-pull-0{right:0}.col-xs-push-12{left:100%}.col-xs-push-11{left:91.66666666666666%}.col-xs-push-10{left:83.33333333333334%}.col-xs-push-9{left:75%}.col-xs-push-8{left:66.66666666666666%}.col-xs-push-7{left:58.333333333333336%}.col-xs-push-6{left:50%}.col-xs-push-5{left:41.66666666666667%}.col-xs-push-4{left:33.33333333333333%}.col-xs-push-3{left:25%}.col-xs-push-2{left:16.666666666666664%}.col-xs-push-1{left:8.333333333333332%}.col-xs-push-0{left:0}.col-xs-offset-12{margin-left:100%}.col-xs-offset-11{margin-left:91.66666666666666%}.col-xs-offset-10{margin-left:83.33333333333334%}.col-xs-offset-9{margin-left:75%}.col-xs-offset-8{margin-left:66.66666666666666%}.col-xs-offset-7{margin-left:58.333333333333336%}.col-xs-offset-6{margin-left:50%}.col-xs-offset-5{margin-left:41.66666666666667%}.col-xs-offset-4{margin-left:33.33333333333333%}.col-xs-offset-3{margin-left:25%}.col-xs-offset-2{margin-left:16.666666666666664%}.col-xs-offset-1{margin-left:8.333333333333332%}.col-xs-offset-0{margin-left:0}@media (min-width:768px){.col-sm-1,.col-sm-2,.col-sm-3,.col-sm-4,.col-sm-5,.col-sm-6,.col-sm-7,.col-sm-8,.col-sm-9,.col-sm-10,.col-sm-11,.col-sm-12{float:left}.col-sm-12{width:100%}.col-sm-11{width:91.66666666666666%}.col-sm-10{width:83.33333333333334%}.col-sm-9{width:75%}.col-sm-8{width:66.66666666666666%}.col-sm-7{width:58.333333333333336%}.col-sm-6{width:50%}.col-sm-5{width:41.66666666666667%}.col-sm-4{width:33.33333333333333%}.col-sm-3{width:25%}.col-sm-2{width:16.666666666666664%}.col-sm-1{width:8.333333333333332%}.col-sm-pull-12{right:100%}.col-sm-pull-11{right:91.66666666666666%}.col-sm-pull-10{right:83.33333333333334%}.col-sm-pull-9{right:75%}.col-sm-pull-8{right:66.66666666666666%}.col-sm-pull-7{right:58.333333333333336%}.col-sm-pull-6{right:50%}.col-sm-pull-5{right:41.66666666666667%}.col-sm-pull-4{right:33.33333333333333%}.col-sm-pull-3{right:25%}.col-sm-pull-2{right:16.666666666666664%}.col-sm-pull-1{right:8.333333333333332%}.col-sm-pull-0{right:0}.col-sm-push-12{left:100%}.col-sm-push-11{left:91.66666666666666%}.col-sm-push-10{left:83.33333333333334%}.col-sm-push-9{left:75%}.col-sm-push-8{left:66.66666666666666%}.col-sm-push-7{left:58.333333333333336%}.col-sm-push-6{left:50%}.col-sm-push-5{left:41.66666666666667%}.col-sm-push-4{left:33.33333333333333%}.col-sm-push-3{left:25%}.col-sm-push-2{left:16.666666666666664%}.col-sm-push-1{left:8.333333333333332%}.col-sm-push-0{left:0}.col-sm-offset-12{margin-left:100%}.col-sm-offset-11{margin-left:91.66666666666666%}.col-sm-offset-10{margin-left:83.33333333333334%}.col-sm-offset-9{margin-left:75%}.col-sm-offset-8{margin-left:66.66666666666666%}.col-sm-offset-7{margin-left:58.333333333333336%}.col-sm-offset-6{margin-left:50%}.col-sm-offset-5{margin-left:41.66666666666667%}.col-sm-offset-4{margin-left:33.33333333333333%}.col-sm-offset-3{margin-left:25%}.col-sm-offset-2{margin-left:16.666666666666664%}.col-sm-offset-1{margin-left:8.333333333333332%}.col-sm-offset-0{margin-left:0}}@media (min-width:992px){.col-md-1,.col-md-2,.col-md-3,.col-md-4,.col-md-5,.col-md-6,.col-md-7,.col-md-8,.col-md-9,.col-md-10,.col-md-11,.col-md-12{float:left}.col-md-12{width:100%}.col-md-11{width:91.66666666666666%}.col-md-10{width:83.33333333333334%}.col-md-9{width:75%}.col-md-8{width:66.66666666666666%}.col-md-7{width:58.333333333333336%}.col-md-6{width:50%}.col-md-5{width:41.66666666666667%}.col-md-4{width:33.33333333333333%}.col-md-3{width:25%}.col-md-2{width:16.666666666666664%}.col-md-1{width:8.333333333333332%}.col-md-pull-12{right:100%}.col-md-pull-11{right:91.66666666666666%}.col-md-pull-10{right:83.33333333333334%}.col-md-pull-9{right:75%}.col-md-pull-8{right:66.66666666666666%}.col-md-pull-7{right:58.333333333333336%}.col-md-pull-6{right:50%}.col-md-pull-5{right:41.66666666666667%}.col-md-pull-4{right:33.33333333333333%}.col-md-pull-3{right:25%}.col-md-pull-2{right:16.666666666666664%}.col-md-pull-1{right:8.333333333333332%}.col-md-pull-0{right:0}.col-md-push-12{left:100%}.col-md-push-11{left:91.66666666666666%}.col-md-push-10{left:83.33333333333334%}.col-md-push-9{left:75%}.col-md-push-8{left:66.66666666666666%}.col-md-push-7{left:58.333333333333336%}.col-md-push-6{left:50%}.col-md-push-5{left:41.66666666666667%}.col-md-push-4{left:33.33333333333333%}.col-md-push-3{left:25%}.col-md-push-2{left:16.666666666666664%}.col-md-push-1{left:8.333333333333332%}.col-md-push-0{left:0}.col-md-offset-12{margin-left:100%}.col-md-offset-11{margin-left:91.66666666666666%}.col-md-offset-10{margin-left:83.33333333333334%}.col-md-offset-9{margin-left:75%}.col-md-offset-8{margin-left:66.66666666666666%}.col-md-offset-7{margin-left:58.333333333333336%}.col-md-offset-6{margin-left:50%}.col-md-offset-5{margin-left:41.66666666666667%}.col-md-offset-4{margin-left:33.33333333333333%}.col-md-offset-3{margin-left:25%}.col-md-offset-2{margin-left:16.666666666666664%}.col-md-offset-1{margin-left:8.333333333333332%}.col-md-offset-0{margin-left:0}}@media (min-width:1200px){.col-lg-1,.col-lg-2,.col-lg-3,.col-lg-4,.col-lg-5,.col-lg-6,.col-lg-7,.col-lg-8,.col-lg-9,.col-lg-10,.col-lg-11,.col-lg-12{float:left}.col-lg-12{width:100%}.col-lg-11{width:91.66666666666666%}.col-lg-10{width:83.33333333333334%}.col-lg-9{width:75%}.col-lg-8{width:66.66666666666666%}.col-lg-7{width:58.333333333333336%}.col-lg-6{width:50%}.col-lg-5{width:41.66666666666667%}.col-lg-4{width:33.33333333333333%}.col-lg-3{width:25%}.col-lg-2{width:16.666666666666664%}.col-lg-1{width:8.333333333333332%}.col-lg-pull-12{right:100%}.col-lg-pull-11{right:91.66666666666666%}.col-lg-pull-10{right:83.33333333333334%}.col-lg-pull-9{right:75%}.col-lg-pull-8{right:66.66666666666666%}.col-lg-pull-7{right:58.333333333333336%}.col-lg-pull-6{right:50%}.col-lg-pull-5{right:41.66666666666667%}.col-lg-pull-4{right:33.33333333333333%}.col-lg-pull-3{right:25%}.col-lg-pull-2{right:16.666666666666664%}.col-lg-pull-1{right:8.333333333333332%}.col-lg-pull-0{right:0}.col-lg-push-12{left:100%}.col-lg-push-11{left:91.66666666666666%}.col-lg-push-10{left:83.33333333333334%}.col-lg-push-9{left:75%}.col-lg-push-8{left:66.66666666666666%}.col-lg-push-7{left:58.333333333333336%}.col-lg-push-6{left:50%}.col-lg-push-5{left:41.66666666666667%}.col-lg-push-4{left:33.33333333333333%}.col-lg-push-3{left:25%}.col-lg-push-2{left:16.666666666666664%}.col-lg-push-1{left:8.333333333333332%}.col-lg-push-0{left:0}.col-lg-offset-12{margin-left:100%}.col-lg-offset-11{margin-left:91.66666666666666%}.col-lg-offset-10{margin-left:83.33333333333334%}.col-lg-offset-9{margin-left:75%}.col-lg-offset-8{margin-left:66.66666666666666%}.col-lg-offset-7{margin-left:58.333333333333336%}.col-lg-offset-6{margin-left:50%}.col-lg-offset-5{margin-left:41.66666666666667%}.col-lg-offset-4{margin-left:33.33333333333333%}.col-lg-offset-3{margin-left:25%}.col-lg-offset-2{margin-left:16.666666666666664%}.col-lg-offset-1{margin-left:8.333333333333332%}.col-lg-offset-0{margin-left:0}}table{max-width:100%;background-color:transparent}th{text-align:left}.table{width:100%;margin-bottom:20px}.table>thead>tr>th,.table>tbody>tr>th,.table>tfoot>tr>th,.table>thead>tr>td,.table>tbody>tr>td,.table>tfoot>tr>td{padding:8px;line-height:1.428571429;vertical-align:top;border-top:1px solid #ddd}.table>thead>tr>th{vertical-align:bottom;border-bottom:2px solid #ddd}.table>caption+thead>tr:first-child>th,.table>colgroup+thead>tr:first-child>th,.table>thead:first-child>tr:first-child>th,.table>caption+thead>tr:first-child>td,.table>colgroup+thead>tr:first-child>td,.table>thead:first-child>tr:first-child>td{border-top:0}.table>tbody+tbody{border-top:2px solid #ddd}.table .table{background-color:#fff}.table-condensed>thead>tr>th,.table-condensed>tbody>tr>th,.table-condensed>tfoot>tr>th,.table-condensed>thead>tr>td,.table-condensed>tbody>tr>td,.table-condensed>tfoot>tr>td{padding:5px}.table-bordered{border:1px solid #ddd}.table-bordered>thead>tr>th,.table-bordered>tbody>tr>th,.table-bordered>tfoot>tr>th,.table-bordered>thead>tr>td,.table-bordered>tbody>tr>td,.table-bordered>tfoot>tr>td{border:1px solid #ddd}.table-bordered>thead>tr>th,.table-bordered>thead>tr>td{border-bottom-width:2px}.table-striped>tbody>tr:nth-child(odd)>td,.table-striped>tbody>tr:nth-child(odd)>th{background-color:#f9f9f9}.table-hover>tbody>tr:hover>td,.table-hover>tbody>tr:hover>th{background-color:#f5f5f5}table col[class*=col-]{position:static;float:none;display:table-column}table td[class*=col-],table th[class*=col-]{position:static;float:none;display:table-cell}.table>thead>tr>td.active,.table>tbody>tr>td.active,.table>tfoot>tr>td.active,.table>thead>tr>th.active,.table>tbody>tr>th.active,.table>tfoot>tr>th.active,.table>thead>tr.active>td,.table>tbody>tr.active>td,.table>tfoot>tr.active>td,.table>thead>tr.active>th,.table>tbody>tr.active>th,.table>tfoot>tr.active>th{background-color:#f5f5f5}.table-hover>tbody>tr>td.active:hover,.table-hover>tbody>tr>th.active:hover,.table-hover>tbody>tr.active:hover>td,.table-hover>tbody>tr.active:hover>th{background-color:#e8e8e8}.table>thead>tr>td.success,.table>tbody>tr>td.success,.table>tfoot>tr>td.success,.table>thead>tr>th.success,.table>tbody>tr>th.success,.table>tfoot>tr>th.success,.table>thead>tr.success>td,.table>tbody>tr.success>td,.table>tfoot>tr.success>td,.table>thead>tr.success>th,.table>tbody>tr.success>th,.table>tfoot>tr.success>th{background-color:#dff0d8}.table-hover>tbody>tr>td.success:hover,.table-hover>tbody>tr>th.success:hover,.table-hover>tbody>tr.success:hover>td,.table-hover>tbody>tr.success:hover>th{background-color:#d0e9c6}.table>thead>tr>td.info,.table>tbody>tr>td.info,.table>tfoot>tr>td.info,.table>thead>tr>th.info,.table>tbody>tr>th.info,.table>tfoot>tr>th.info,.table>thead>tr.info>td,.table>tbody>tr.info>td,.table>tfoot>tr.info>td,.table>thead>tr.info>th,.table>tbody>tr.info>th,.table>tfoot>tr.info>th{background-color:#d9edf7}.table-hover>tbody>tr>td.info:hover,.table-hover>tbody>tr>th.info:hover,.table-hover>tbody>tr.info:hover>td,.table-hover>tbody>tr.info:hover>th{background-color:#c4e3f3}.table>thead>tr>td.warning,.table>tbody>tr>td.warning,.table>tfoot>tr>td.warning,.table>thead>tr>th.warning,.table>tbody>tr>th.warning,.table>tfoot>tr>th.warning,.table>thead>tr.warning>td,.table>tbody>tr.warning>td,.table>tfoot>tr.warning>td,.table>thead>tr.warning>th,.table>tbody>tr.warning>th,.table>tfoot>tr.warning>th{background-color:#fcf8e3}.table-hover>tbody>tr>td.warning:hover,.table-hover>tbody>tr>th.warning:hover,.table-hover>tbody>tr.warning:hover>td,.table-hover>tbody>tr.warning:hover>th{background-color:#faf2cc}.table>thead>tr>td.danger,.table>tbody>tr>td.danger,.table>tfoot>tr>td.danger,.table>thead>tr>th.danger,.table>tbody>tr>th.danger,.table>tfoot>tr>th.danger,.table>thead>tr.danger>td,.table>tbody>tr.danger>td,.table>tfoot>tr.danger>td,.table>thead>tr.danger>th,.table>tbody>tr.danger>th,.table>tfoot>tr.danger>th{background-color:#f2dede}.table-hover>tbody>tr>td.danger:hover,.table-hover>tbody>tr>th.danger:hover,.table-hover>tbody>tr.danger:hover>td,.table-hover>tbody>tr.danger:hover>th{background-color:#ebcccc}@media (max-width:767px){.table-responsive{width:100%;margin-bottom:15px;overflow-y:hidden;overflow-x:scroll;-ms-overflow-style:-ms-autohiding-scrollbar;border:1px solid #ddd;-webkit-overflow-scrolling:touch}.table-responsive>.table{margin-bottom:0}.table-responsive>.table>thead>tr>th,.table-responsive>.table>tbody>tr>th,.table-responsive>.table>tfoot>tr>th,.table-responsive>.table>thead>tr>td,.table-responsive>.table>tbody>tr>td,.table-responsive>.table>tfoot>tr>td{white-space:nowrap}.table-responsive>.table-bordered{border:0}.table-responsive>.table-bordered>thead>tr>th:first-child,.table-responsive>.table-bordered>tbody>tr>th:first-child,.table-responsive>.table-bordered>tfoot>tr>th:first-child,.table-responsive>.table-bordered>thead>tr>td:first-child,.table-responsive>.table-bordered>tbody>tr>td:first-child,.table-responsive>.table-bordered>tfoot>tr>td:first-child{border-left:0}.table-responsive>.table-bordered>thead>tr>th:last-child,.table-responsive>.table-bordered>tbody>tr>th:last-child,.table-responsive>.table-bordered>tfoot>tr>th:last-child,.table-responsive>.table-bordered>thead>tr>td:last-child,.table-responsive>.table-bordered>tbody>tr>td:last-child,.table-responsive>.table-bordered>tfoot>tr>td:last-child{border-right:0}.table-responsive>.table-bordered>tbody>tr:last-child>th,.table-responsive>.table-bordered>tfoot>tr:last-child>th,.table-responsive>.table-bordered>tbody>tr:last-child>td,.table-responsive>.table-bordered>tfoot>tr:last-child>td{border-bottom:0}}fieldset{padding:0;margin:0;border:0;min-width:0}legend{display:block;width:100%;padding:0;margin-bottom:20px;font-size:21px;line-height:inherit;color:#333;border:0;border-bottom:1px solid #e5e5e5}label{display:inline-block;margin-bottom:5px;font-weight:700}input[type=search]{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}input[type=radio],input[type=checkbox]{margin:4px 0 0;margin-top:1px \9;line-height:normal}input[type=file]{display:block}input[type=range]{display:block;width:100%}select[multiple],select[size]{height:auto}input[type=file]:focus,input[type=radio]:focus,input[type=checkbox]:focus{outline:thin dotted;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}output{display:block;padding-top:7px;font-size:14px;line-height:1.428571429;color:#555}.form-control{display:block;width:100%;height:34px;padding:6px 12px;font-size:14px;line-height:1.428571429;color:#555;background-color:#fff;background-image:none;border:1px solid #ccc;border-radius:4px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075);-webkit-transition:border-color ease-in-out .15s,box-shadow ease-in-out .15s;transition:border-color ease-in-out .15s,box-shadow ease-in-out .15s}.form-control:focus{border-color:#66afe9;outline:0;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(102,175,233,.6);box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(102,175,233,.6)}.form-control:-moz-placeholder{color:#999}.form-control::-moz-placeholder{color:#999;opacity:1}.form-control:-ms-input-placeholder{color:#999}.form-control::-webkit-input-placeholder{color:#999}.form-control[disabled],.form-control[readonly],fieldset[disabled] .form-control{cursor:not-allowed;background-color:#eee;opacity:1}textarea.form-control{height:auto}input[type=date]{line-height:34px}.form-group{margin-bottom:15px}.radio,.checkbox{display:block;min-height:20px;margin-top:10px;margin-bottom:10px;padding-left:20px}.radio label,.checkbox label{display:inline;font-weight:400;cursor:pointer}.radio input[type=radio],.radio-inline input[type=radio],.checkbox input[type=checkbox],.checkbox-inline input[type=checkbox]{float:left;margin-left:-20px}.radio+.radio,.checkbox+.checkbox{margin-top:-5px}.radio-inline,.checkbox-inline{display:inline-block;padding-left:20px;margin-bottom:0;vertical-align:middle;font-weight:400;cursor:pointer}.radio-inline+.radio-inline,.checkbox-inline+.checkbox-inline{margin-top:0;margin-left:10px}input[type=radio][disabled],input[type=checkbox][disabled],.radio[disabled],.radio-inline[disabled],.checkbox[disabled],.checkbox-inline[disabled],fieldset[disabled] input[type=radio],fieldset[disabled] input[type=checkbox],fieldset[disabled] .radio,fieldset[disabled] .radio-inline,fieldset[disabled] .checkbox,fieldset[disabled] .checkbox-inline{cursor:not-allowed}.input-sm{height:30px;padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}select.input-sm{height:30px;line-height:30px}textarea.input-sm,select[multiple].input-sm{height:auto}.input-lg{height:46px;padding:10px 16px;font-size:18px;line-height:1.33;border-radius:6px}select.input-lg{height:46px;line-height:46px}textarea.input-lg,select[multiple].input-lg{height:auto}.has-feedback{position:relative}.has-feedback .form-control{padding-right:42.5px}.has-feedback .form-control-feedback{position:absolute;top:25px;right:0;display:block;width:34px;height:34px;line-height:34px;text-align:center}.has-success .help-block,.has-success .control-label,.has-success .radio,.has-success .checkbox,.has-success .radio-inline,.has-success .checkbox-inline{color:#3c763d}.has-success .form-control{border-color:#3c763d;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075)}.has-success .form-control:focus{border-color:#2b542c;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #67b168;box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #67b168}.has-success .input-group-addon{color:#3c763d;border-color:#3c763d;background-color:#dff0d8}.has-success .form-control-feedback{color:#3c763d}.has-warning .help-block,.has-warning .control-label,.has-warning .radio,.has-warning .checkbox,.has-warning .radio-inline,.has-warning .checkbox-inline{color:#8a6d3b}.has-warning .form-control{border-color:#8a6d3b;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075)}.has-warning .form-control:focus{border-color:#66512c;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #c0a16b;box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #c0a16b}.has-warning .input-group-addon{color:#8a6d3b;border-color:#8a6d3b;background-color:#fcf8e3}.has-warning .form-control-feedback{color:#8a6d3b}.has-error .help-block,.has-error .control-label,.has-error .radio,.has-error .checkbox,.has-error .radio-inline,.has-error .checkbox-inline{color:#a94442}.has-error .form-control{border-color:#a94442;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075)}.has-error .form-control:focus{border-color:#843534;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #ce8483;box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #ce8483}.has-error .input-group-addon{color:#a94442;border-color:#a94442;background-color:#f2dede}.has-error .form-control-feedback{color:#a94442}.form-control-static{margin-bottom:0}.help-block{display:block;margin-top:5px;margin-bottom:10px;color:#737373}@media (min-width:768px){.form-inline .form-group{display:inline-block;margin-bottom:0;vertical-align:middle}.form-inline .form-control{display:inline-block;width:auto;vertical-align:middle}.form-inline .control-label{margin-bottom:0;vertical-align:middle}.form-inline .radio,.form-inline .checkbox{display:inline-block;margin-top:0;margin-bottom:0;padding-left:0;vertical-align:middle}.form-inline .radio input[type=radio],.form-inline .checkbox input[type=checkbox]{float:none;margin-left:0}.form-inline .has-feedback .form-control-feedback{top:0}}.form-horizontal .control-label,.form-horizontal .radio,.form-horizontal .checkbox,.form-horizontal .radio-inline,.form-horizontal .checkbox-inline{margin-top:0;margin-bottom:0;padding-top:7px}.form-horizontal .radio,.form-horizontal .checkbox{min-height:27px}.form-horizontal .form-group{margin-left:-15px;margin-right:-15px}.form-horizontal .form-control-static{padding-top:7px}@media (min-width:768px){.form-horizontal .control-label{text-align:right}}.form-horizontal .has-feedback .form-control-feedback{top:0;right:15px}.btn{display:inline-block;margin-bottom:0;font-weight:400;text-align:center;vertical-align:middle;cursor:pointer;background-image:none;border:1px solid transparent;white-space:nowrap;padding:6px 12px;font-size:14px;line-height:1.428571429;border-radius:4px;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;-o-user-select:none;user-select:none}.btn:focus{outline:thin dotted;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}.btn:hover,.btn:focus{color:#333;text-decoration:none}.btn:active,.btn.active{outline:0;background-image:none;-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,.125);box-shadow:inset 0 3px 5px rgba(0,0,0,.125)}.btn.disabled,.btn[disabled],fieldset[disabled] .btn{cursor:not-allowed;pointer-events:none;opacity:.65;filter:alpha(opacity=65);-webkit-box-shadow:none;box-shadow:none}.btn-default{color:#333;background-color:#fff;border-color:#ccc}.btn-default:hover,.btn-default:focus,.btn-default:active,.btn-default.active,.open .dropdown-toggle.btn-default{color:#333;background-color:#ebebeb;border-color:#adadad}.btn-default:active,.btn-default.active,.open .dropdown-toggle.btn-default{background-image:none}.btn-default.disabled,.btn-default[disabled],fieldset[disabled] .btn-default,.btn-default.disabled:hover,.btn-default[disabled]:hover,fieldset[disabled] .btn-default:hover,.btn-default.disabled:focus,.btn-default[disabled]:focus,fieldset[disabled] .btn-default:focus,.btn-default.disabled:active,.btn-default[disabled]:active,fieldset[disabled] .btn-default:active,.btn-default.disabled.active,.btn-default[disabled].active,fieldset[disabled] .btn-default.active{background-color:#fff;border-color:#ccc}.btn-default .badge{color:#fff;background-color:#333}.btn-primary{color:#fff;background-color:#428bca;border-color:#357ebd}.btn-primary:hover,.btn-primary:focus,.btn-primary:active,.btn-primary.active,.open .dropdown-toggle.btn-primary{color:#fff;background-color:#3276b1;border-color:#285e8e}.btn-primary:active,.btn-primary.active,.open .dropdown-toggle.btn-primary{background-image:none}.btn-primary.disabled,.btn-primary[disabled],fieldset[disabled] .btn-primary,.btn-primary.disabled:hover,.btn-primary[disabled]:hover,fieldset[disabled] .btn-primary:hover,.btn-primary.disabled:focus,.btn-primary[disabled]:focus,fieldset[disabled] .btn-primary:focus,.btn-primary.disabled:active,.btn-primary[disabled]:active,fieldset[disabled] .btn-primary:active,.btn-primary.disabled.active,.btn-primary[disabled].active,fieldset[disabled] .btn-primary.active{background-color:#428bca;border-color:#357ebd}.btn-primary .badge{color:#428bca;background-color:#fff}.btn-success{color:#fff;background-color:#5cb85c;border-color:#4cae4c}.btn-success:hover,.btn-success:focus,.btn-success:active,.btn-success.active,.open .dropdown-toggle.btn-success{color:#fff;background-color:#47a447;border-color:#398439}.btn-success:active,.btn-success.active,.open .dropdown-toggle.btn-success{background-image:none}.btn-success.disabled,.btn-success[disabled],fieldset[disabled] .btn-success,.btn-success.disabled:hover,.btn-success[disabled]:hover,fieldset[disabled] .btn-success:hover,.btn-success.disabled:focus,.btn-success[disabled]:focus,fieldset[disabled] .btn-success:focus,.btn-success.disabled:active,.btn-success[disabled]:active,fieldset[disabled] .btn-success:active,.btn-success.disabled.active,.btn-success[disabled].active,fieldset[disabled] .btn-success.active{background-color:#5cb85c;border-color:#4cae4c}.btn-success .badge{color:#5cb85c;background-color:#fff}.btn-info{color:#fff;background-color:#5bc0de;border-color:#46b8da}.btn-info:hover,.btn-info:focus,.btn-info:active,.btn-info.active,.open .dropdown-toggle.btn-info{color:#fff;background-color:#39b3d7;border-color:#269abc}.btn-info:active,.btn-info.active,.open .dropdown-toggle.btn-info{background-image:none}.btn-info.disabled,.btn-info[disabled],fieldset[disabled] .btn-info,.btn-info.disabled:hover,.btn-info[disabled]:hover,fieldset[disabled] .btn-info:hover,.btn-info.disabled:focus,.btn-info[disabled]:focus,fieldset[disabled] .btn-info:focus,.btn-info.disabled:active,.btn-info[disabled]:active,fieldset[disabled] .btn-info:active,.btn-info.disabled.active,.btn-info[disabled].active,fieldset[disabled] .btn-info.active{background-color:#5bc0de;border-color:#46b8da}.btn-info .badge{color:#5bc0de;background-color:#fff}.btn-warning{color:#fff;background-color:#f0ad4e;border-color:#eea236}.btn-warning:hover,.btn-warning:focus,.btn-warning:active,.btn-warning.active,.open .dropdown-toggle.btn-warning{color:#fff;background-color:#ed9c28;border-color:#d58512}.btn-warning:active,.btn-warning.active,.open .dropdown-toggle.btn-warning{background-image:none}.btn-warning.disabled,.btn-warning[disabled],fieldset[disabled] .btn-warning,.btn-warning.disabled:hover,.btn-warning[disabled]:hover,fieldset[disabled] .btn-warning:hover,.btn-warning.disabled:focus,.btn-warning[disabled]:focus,fieldset[disabled] .btn-warning:focus,.btn-warning.disabled:active,.btn-warning[disabled]:active,fieldset[disabled] .btn-warning:active,.btn-warning.disabled.active,.btn-warning[disabled].active,fieldset[disabled] .btn-warning.active{background-color:#f0ad4e;border-color:#eea236}.btn-warning .badge{color:#f0ad4e;background-color:#fff}.btn-danger{color:#fff;background-color:#d9534f;border-color:#d43f3a}.btn-danger:hover,.btn-danger:focus,.btn-danger:active,.btn-danger.active,.open .dropdown-toggle.btn-danger{color:#fff;background-color:#d2322d;border-color:#ac2925}.btn-danger:active,.btn-danger.active,.open .dropdown-toggle.btn-danger{background-image:none}.btn-danger.disabled,.btn-danger[disabled],fieldset[disabled] .btn-danger,.btn-danger.disabled:hover,.btn-danger[disabled]:hover,fieldset[disabled] .btn-danger:hover,.btn-danger.disabled:focus,.btn-danger[disabled]:focus,fieldset[disabled] .btn-danger:focus,.btn-danger.disabled:active,.btn-danger[disabled]:active,fieldset[disabled] .btn-danger:active,.btn-danger.disabled.active,.btn-danger[disabled].active,fieldset[disabled] .btn-danger.active{background-color:#d9534f;border-color:#d43f3a}.btn-danger .badge{color:#d9534f;background-color:#fff}.btn-link{color:#428bca;font-weight:400;cursor:pointer;border-radius:0}.btn-link,.btn-link:active,.btn-link[disabled],fieldset[disabled] .btn-link{background-color:transparent;-webkit-box-shadow:none;box-shadow:none}.btn-link,.btn-link:hover,.btn-link:focus,.btn-link:active{border-color:transparent}.btn-link:hover,.btn-link:focus{color:#2a6496;text-decoration:underline;background-color:transparent}.btn-link[disabled]:hover,fieldset[disabled] .btn-link:hover,.btn-link[disabled]:focus,fieldset[disabled] .btn-link:focus{color:#999;text-decoration:none}.btn-lg{padding:10px 16px;font-size:18px;line-height:1.33;border-radius:6px}.btn-sm{padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}.btn-xs{padding:1px 5px;font-size:12px;line-height:1.5;border-radius:3px}.btn-block{display:block;width:100%;padding-left:0;padding-right:0}.btn-block+.btn-block{margin-top:5px}input[type=submit].btn-block,input[type=reset].btn-block,input[type=button].btn-block{width:100%}.fade{opacity:0;-webkit-transition:opacity .15s linear;transition:opacity .15s linear}.fade.in{opacity:1}.collapse{display:none}.collapse.in{display:block}.collapsing{position:relative;height:0;overflow:hidden;-webkit-transition:height .35s ease;transition:height .35s ease}@font-face{font-family:'Glyphicons Halflings';src:url(../fonts/glyphicons-halflings-regular.eot);src:url(../fonts/glyphicons-halflings-regular.eot?#iefix) format('embedded-opentype'),url(../fonts/glyphicons-halflings-regular.woff) format('woff'),url(../fonts/glyphicons-halflings-regular.ttf) format('truetype'),url(../fonts/glyphicons-halflings-regular.svg#glyphicons_halflingsregular) format('svg')}.glyphicon{position:relative;top:1px;display:inline-block;font-family:'Glyphicons Halflings';font-style:normal;font-weight:400;line-height:1;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.glyphicon-asterisk:before{content:"\2a"}.glyphicon-plus:before{content:"\2b"}.glyphicon-euro:before{content:"\20ac"}.glyphicon-minus:before{content:"\2212"}.glyphicon-cloud:before{content:"\2601"}.glyphicon-envelope:before{content:"\2709"}.glyphicon-pencil:before{content:"\270f"}.glyphicon-glass:before{content:"\e001"}.glyphicon-music:before{content:"\e002"}.glyphicon-search:before{content:"\e003"}.glyphicon-heart:before{content:"\e005"}.glyphicon-star:before{content:"\e006"}.glyphicon-star-empty:before{content:"\e007"}.glyphicon-user:before{content:"\e008"}.glyphicon-film:before{content:"\e009"}.glyphicon-th-large:before{content:"\e010"}.glyphicon-th:before{content:"\e011"}.glyphicon-th-list:before{content:"\e012"}.glyphicon-ok:before{content:"\e013"}.glyphicon-remove:before{content:"\e014"}.glyphicon-zoom-in:before{content:"\e015"}.glyphicon-zoom-out:before{content:"\e016"}.glyphicon-off:before{content:"\e017"}.glyphicon-signal:before{content:"\e018"}.glyphicon-cog:before{content:"\e019"}.glyphicon-trash:before{content:"\e020"}.glyphicon-home:before{content:"\e021"}.glyphicon-file:before{content:"\e022"}.glyphicon-time:before{content:"\e023"}.glyphicon-road:before{content:"\e024"}.glyphicon-download-alt:before{content:"\e025"}.glyphicon-download:before{content:"\e026"}.glyphicon-upload:before{content:"\e027"}.glyphicon-inbox:before{content:"\e028"}.glyphicon-play-circle:before{content:"\e029"}.glyphicon-repeat:before{content:"\e030"}.glyphicon-refresh:before{content:"\e031"}.glyphicon-list-alt:before{content:"\e032"}.glyphicon-lock:before{content:"\e033"}.glyphicon-flag:before{content:"\e034"}.glyphicon-headphones:before{content:"\e035"}.glyphicon-volume-off:before{content:"\e036"}.glyphicon-volume-down:before{content:"\e037"}.glyphicon-volume-up:before{content:"\e038"}.glyphicon-qrcode:before{content:"\e039"}.glyphicon-barcode:before{content:"\e040"}.glyphicon-tag:before{content:"\e041"}.glyphicon-tags:before{content:"\e042"}.glyphicon-book:before{content:"\e043"}.glyphicon-bookmark:before{content:"\e044"}.glyphicon-print:before{content:"\e045"}.glyphicon-camera:before{content:"\e046"}.glyphicon-font:before{content:"\e047"}.glyphicon-bold:before{content:"\e048"}.glyphicon-italic:before{content:"\e049"}.glyphicon-text-height:before{content:"\e050"}.glyphicon-text-width:before{content:"\e051"}.glyphicon-align-left:before{content:"\e052"}.glyphicon-align-center:before{content:"\e053"}.glyphicon-align-right:before{content:"\e054"}.glyphicon-align-justify:before{content:"\e055"}.glyphicon-list:before{content:"\e056"}.glyphicon-indent-left:before{content:"\e057"}.glyphicon-indent-right:before{content:"\e058"}.glyphicon-facetime-video:before{content:"\e059"}.glyphicon-picture:before{content:"\e060"}.glyphicon-map-marker:before{content:"\e062"}.glyphicon-adjust:before{content:"\e063"}.glyphicon-tint:before{content:"\e064"}.glyphicon-edit:before{content:"\e065"}.glyphicon-share:before{content:"\e066"}.glyphicon-check:before{content:"\e067"}.glyphicon-move:before{content:"\e068"}.glyphicon-step-backward:before{content:"\e069"}.glyphicon-fast-backward:before{content:"\e070"}.glyphicon-backward:before{content:"\e071"}.glyphicon-play:before{content:"\e072"}.glyphicon-pause:before{content:"\e073"}.glyphicon-stop:before{content:"\e074"}.glyphicon-forward:before{content:"\e075"}.glyphicon-fast-forward:before{content:"\e076"}.glyphicon-step-forward:before{content:"\e077"}.glyphicon-eject:before{content:"\e078"}.glyphicon-chevron-left:before{content:"\e079"}.glyphicon-chevron-right:before{content:"\e080"}.glyphicon-plus-sign:before{content:"\e081"}.glyphicon-minus-sign:before{content:"\e082"}.glyphicon-remove-sign:before{content:"\e083"}.glyphicon-ok-sign:before{content:"\e084"}.glyphicon-question-sign:before{content:"\e085"}.glyphicon-info-sign:before{content:"\e086"}.glyphicon-screenshot:before{content:"\e087"}.glyphicon-remove-circle:before{content:"\e088"}.glyphicon-ok-circle:before{content:"\e089"}.glyphicon-ban-circle:before{content:"\e090"}.glyphicon-arrow-left:before{content:"\e091"}.glyphicon-arrow-right:before{content:"\e092"}.glyphicon-arrow-up:before{content:"\e093"}.glyphicon-arrow-down:before{content:"\e094"}.glyphicon-share-alt:before{content:"\e095"}.glyphicon-resize-full:before{content:"\e096"}.glyphicon-resize-small:before{content:"\e097"}.glyphicon-exclamation-sign:before{content:"\e101"}.glyphicon-gift:before{content:"\e102"}.glyphicon-leaf:before{content:"\e103"}.glyphicon-fire:before{content:"\e104"}.glyphicon-eye-open:before{content:"\e105"}.glyphicon-eye-close:before{content:"\e106"}.glyphicon-warning-sign:before{content:"\e107"}.glyphicon-plane:before{content:"\e108"}.glyphicon-calendar:before{content:"\e109"}.glyphicon-random:before{content:"\e110"}.glyphicon-comment:before{content:"\e111"}.glyphicon-magnet:before{content:"\e112"}.glyphicon-chevron-up:before{content:"\e113"}.glyphicon-chevron-down:before{content:"\e114"}.glyphicon-retweet:before{content:"\e115"}.glyphicon-shopping-cart:before{content:"\e116"}.glyphicon-folder-close:before{content:"\e117"}.glyphicon-folder-open:before{content:"\e118"}.glyphicon-resize-vertical:before{content:"\e119"}.glyphicon-resize-horizontal:before{content:"\e120"}.glyphicon-hdd:before{content:"\e121"}.glyphicon-bullhorn:before{content:"\e122"}.glyphicon-bell:before{content:"\e123"}.glyphicon-certificate:before{content:"\e124"}.glyphicon-thumbs-up:before{content:"\e125"}.glyphicon-thumbs-down:before{content:"\e126"}.glyphicon-hand-right:before{content:"\e127"}.glyphicon-hand-left:before{content:"\e128"}.glyphicon-hand-up:before{content:"\e129"}.glyphicon-hand-down:before{content:"\e130"}.glyphicon-circle-arrow-right:before{content:"\e131"}.glyphicon-circle-arrow-left:before{content:"\e132"}.glyphicon-circle-arrow-up:before{content:"\e133"}.glyphicon-circle-arrow-down:before{content:"\e134"}.glyphicon-globe:before{content:"\e135"}.glyphicon-wrench:before{content:"\e136"}.glyphicon-tasks:before{content:"\e137"}.glyphicon-filter:before{content:"\e138"}.glyphicon-briefcase:before{content:"\e139"}.glyphicon-fullscreen:before{content:"\e140"}.glyphicon-dashboard:before{content:"\e141"}.glyphicon-paperclip:before{content:"\e142"}.glyphicon-heart-empty:before{content:"\e143"}.glyphicon-link:before{content:"\e144"}.glyphicon-phone:before{content:"\e145"}.glyphicon-pushpin:before{content:"\e146"}.glyphicon-usd:before{content:"\e148"}.glyphicon-gbp:before{content:"\e149"}.glyphicon-sort:before{content:"\e150"}.glyphicon-sort-by-alphabet:before{content:"\e151"}.glyphicon-sort-by-alphabet-alt:before{content:"\e152"}.glyphicon-sort-by-order:before{content:"\e153"}.glyphicon-sort-by-order-alt:before{content:"\e154"}.glyphicon-sort-by-attributes:before{content:"\e155"}.glyphicon-sort-by-attributes-alt:before{content:"\e156"}.glyphicon-unchecked:before{content:"\e157"}.glyphicon-expand:before{content:"\e158"}.glyphicon-collapse-down:before{content:"\e159"}.glyphicon-collapse-up:before{content:"\e160"}.glyphicon-log-in:before{content:"\e161"}.glyphicon-flash:before{content:"\e162"}.glyphicon-log-out:before{content:"\e163"}.glyphicon-new-window:before{content:"\e164"}.glyphicon-record:before{content:"\e165"}.glyphicon-save:before{content:"\e166"}.glyphicon-open:before{content:"\e167"}.glyphicon-saved:before{content:"\e168"}.glyphicon-import:before{content:"\e169"}.glyphicon-export:before{content:"\e170"}.glyphicon-send:before{content:"\e171"}.glyphicon-floppy-disk:before{content:"\e172"}.glyphicon-floppy-saved:before{content:"\e173"}.glyphicon-floppy-remove:before{content:"\e174"}.glyphicon-floppy-save:before{content:"\e175"}.glyphicon-floppy-open:before{content:"\e176"}.glyphicon-credit-card:before{content:"\e177"}.glyphicon-transfer:before{content:"\e178"}.glyphicon-cutlery:before{content:"\e179"}.glyphicon-header:before{content:"\e180"}.glyphicon-compressed:before{content:"\e181"}.glyphicon-earphone:before{content:"\e182"}.glyphicon-phone-alt:before{content:"\e183"}.glyphicon-tower:before{content:"\e184"}.glyphicon-stats:before{content:"\e185"}.glyphicon-sd-video:before{content:"\e186"}.glyphicon-hd-video:before{content:"\e187"}.glyphicon-subtitles:before{content:"\e188"}.glyphicon-sound-stereo:before{content:"\e189"}.glyphicon-sound-dolby:before{content:"\e190"}.glyphicon-sound-5-1:before{content:"\e191"}.glyphicon-sound-6-1:before{content:"\e192"}.glyphicon-sound-7-1:before{content:"\e193"}.glyphicon-copyright-mark:before{content:"\e194"}.glyphicon-registration-mark:before{content:"\e195"}.glyphicon-cloud-download:before{content:"\e197"}.glyphicon-cloud-upload:before{content:"\e198"}.glyphicon-tree-conifer:before{content:"\e199"}.glyphicon-tree-deciduous:before{content:"\e200"}.caret{display:inline-block;width:0;height:0;margin-left:2px;vertical-align:middle;border-top:4px solid;border-right:4px solid transparent;border-left:4px solid transparent}.dropdown{position:relative}.dropdown-toggle:focus{outline:0}.dropdown-menu{position:absolute;top:100%;left:0;z-index:1000;display:none;float:left;min-width:160px;padding:5px 0;margin:2px 0 0;list-style:none;font-size:14px;background-color:#fff;border:1px solid #ccc;border:1px solid rgba(0,0,0,.15);border-radius:4px;-webkit-box-shadow:0 6px 12px rgba(0,0,0,.175);box-shadow:0 6px 12px rgba(0,0,0,.175);background-clip:padding-box}.dropdown-menu.pull-right{right:0;left:auto}.dropdown-menu .divider{height:1px;margin:9px 0;overflow:hidden;background-color:#e5e5e5}.dropdown-menu>li>a{display:block;padding:3px 20px;clear:both;font-weight:400;line-height:1.428571429;color:#333;white-space:nowrap}.dropdown-menu>li>a:hover,.dropdown-menu>li>a:focus{text-decoration:none;color:#262626;background-color:#f5f5f5}.dropdown-menu>.active>a,.dropdown-menu>.active>a:hover,.dropdown-menu>.active>a:focus{color:#fff;text-decoration:none;outline:0;background-color:#428bca}.dropdown-menu>.disabled>a,.dropdown-menu>.disabled>a:hover,.dropdown-menu>.disabled>a:focus{color:#999}.dropdown-menu>.disabled>a:hover,.dropdown-menu>.disabled>a:focus{text-decoration:none;background-color:transparent;background-image:none;filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);cursor:not-allowed}.open>.dropdown-menu{display:block}.open>a{outline:0}.dropdown-menu-right{left:auto;right:0}.dropdown-menu-left{left:0;right:auto}.dropdown-header{display:block;padding:3px 20px;font-size:12px;line-height:1.428571429;color:#999}.dropdown-backdrop{position:fixed;left:0;right:0;bottom:0;top:0;z-index:990}.pull-right>.dropdown-menu{right:0;left:auto}.dropup .caret,.navbar-fixed-bottom .dropdown .caret{border-top:0;border-bottom:4px solid;content:""}.dropup .dropdown-menu,.navbar-fixed-bottom .dropdown .dropdown-menu{top:auto;bottom:100%;margin-bottom:1px}@media (min-width:768px){.navbar-right .dropdown-menu{left:auto;right:0}.navbar-right .dropdown-menu-left{left:0;right:auto}}.btn-group,.btn-group-vertical{position:relative;display:inline-block;vertical-align:middle}.btn-group>.btn,.btn-group-vertical>.btn{position:relative;float:left}.btn-group>.btn:hover,.btn-group-vertical>.btn:hover,.btn-group>.btn:focus,.btn-group-vertical>.btn:focus,.btn-group>.btn:active,.btn-group-vertical>.btn:active,.btn-group>.btn.active,.btn-group-vertical>.btn.active{z-index:2}.btn-group>.btn:focus,.btn-group-vertical>.btn:focus{outline:0}.btn-group .btn+.btn,.btn-group .btn+.btn-group,.btn-group .btn-group+.btn,.btn-group .btn-group+.btn-group{margin-left:-1px}.btn-toolbar{margin-left:-5px}.btn-toolbar .btn-group,.btn-toolbar .input-group{float:left}.btn-toolbar>.btn,.btn-toolbar>.btn-group,.btn-toolbar>.input-group{margin-left:5px}.btn-group>.btn:not(:first-child):not(:last-child):not(.dropdown-toggle){border-radius:0}.btn-group>.btn:first-child{margin-left:0}.btn-group>.btn:first-child:not(:last-child):not(.dropdown-toggle){border-bottom-right-radius:0;border-top-right-radius:0}.btn-group>.btn:last-child:not(:first-child),.btn-group>.dropdown-toggle:not(:first-child){border-bottom-left-radius:0;border-top-left-radius:0}.btn-group>.btn-group{float:left}.btn-group>.btn-group:not(:first-child):not(:last-child)>.btn{border-radius:0}.btn-group>.btn-group:first-child>.btn:last-child,.btn-group>.btn-group:first-child>.dropdown-toggle{border-bottom-right-radius:0;border-top-right-radius:0}.btn-group>.btn-group:last-child>.btn:first-child{border-bottom-left-radius:0;border-top-left-radius:0}.btn-group .dropdown-toggle:active,.btn-group.open .dropdown-toggle{outline:0}.btn-group-xs>.btn{padding:1px 5px;font-size:12px;line-height:1.5;border-radius:3px}.btn-group-sm>.btn{padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}.btn-group-lg>.btn{padding:10px 16px;font-size:18px;line-height:1.33;border-radius:6px}.btn-group>.btn+.dropdown-toggle{padding-left:8px;padding-right:8px}.btn-group>.btn-lg+.dropdown-toggle{padding-left:12px;padding-right:12px}.btn-group.open .dropdown-toggle{-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,.125);box-shadow:inset 0 3px 5px rgba(0,0,0,.125)}.btn-group.open .dropdown-toggle.btn-link{-webkit-box-shadow:none;box-shadow:none}.btn .caret{margin-left:0}.btn-lg .caret{border-width:5px 5px 0;border-bottom-width:0}.dropup .btn-lg .caret{border-width:0 5px 5px}.btn-group-vertical>.btn,.btn-group-vertical>.btn-group,.btn-group-vertical>.btn-group>.btn{display:block;float:none;width:100%;max-width:100%}.btn-group-vertical>.btn-group>.btn{float:none}.btn-group-vertical>.btn+.btn,.btn-group-vertical>.btn+.btn-group,.btn-group-vertical>.btn-group+.btn,.btn-group-vertical>.btn-group+.btn-group{margin-top:-1px;margin-left:0}.btn-group-vertical>.btn:not(:first-child):not(:last-child){border-radius:0}.btn-group-vertical>.btn:first-child:not(:last-child){border-top-right-radius:4px;border-bottom-right-radius:0;border-bottom-left-radius:0}.btn-group-vertical>.btn:last-child:not(:first-child){border-bottom-left-radius:4px;border-top-right-radius:0;border-top-left-radius:0}.btn-group-vertical>.btn-group:not(:first-child):not(:last-child)>.btn{border-radius:0}.btn-group-vertical>.btn-group:first-child:not(:last-child)>.btn:last-child,.btn-group-vertical>.btn-group:first-child:not(:last-child)>.dropdown-toggle{border-bottom-right-radius:0;border-bottom-left-radius:0}.btn-group-vertical>.btn-group:last-child:not(:first-child)>.btn:first-child{border-top-right-radius:0;border-top-left-radius:0}.btn-group-justified{display:table;width:100%;table-layout:fixed;border-collapse:separate}.btn-group-justified>.btn,.btn-group-justified>.btn-group{float:none;display:table-cell;width:1%}.btn-group-justified>.btn-group .btn{width:100%}[data-toggle=buttons]>.btn>input[type=radio],[data-toggle=buttons]>.btn>input[type=checkbox]{display:none}.input-group{position:relative;display:table;border-collapse:separate}.input-group[class*=col-]{float:none;padding-left:0;padding-right:0}.input-group .form-control{float:left;width:100%;margin-bottom:0}.input-group-lg>.form-control,.input-group-lg>.input-group-addon,.input-group-lg>.input-group-btn>.btn{height:46px;padding:10px 16px;font-size:18px;line-height:1.33;border-radius:6px}select.input-group-lg>.form-control,select.input-group-lg>.input-group-addon,select.input-group-lg>.input-group-btn>.btn{height:46px;line-height:46px}textarea.input-group-lg>.form-control,textarea.input-group-lg>.input-group-addon,textarea.input-group-lg>.input-group-btn>.btn,select[multiple].input-group-lg>.form-control,select[multiple].input-group-lg>.input-group-addon,select[multiple].input-group-lg>.input-group-btn>.btn{height:auto}.input-group-sm>.form-control,.input-group-sm>.input-group-addon,.input-group-sm>.input-group-btn>.btn{height:30px;padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}select.input-group-sm>.form-control,select.input-group-sm>.input-group-addon,select.input-group-sm>.input-group-btn>.btn{height:30px;line-height:30px}textarea.input-group-sm>.form-control,textarea.input-group-sm>.input-group-addon,textarea.input-group-sm>.input-group-btn>.btn,select[multiple].input-group-sm>.form-control,select[multiple].input-group-sm>.input-group-addon,select[multiple].input-group-sm>.input-group-btn>.btn{height:auto}.input-group-addon,.input-group-btn,.input-group .form-control{display:table-cell}.input-group-addon:not(:first-child):not(:last-child),.input-group-btn:not(:first-child):not(:last-child),.input-group .form-control:not(:first-child):not(:last-child){border-radius:0}.input-group-addon,.input-group-btn{width:1%;white-space:nowrap;vertical-align:middle}.input-group-addon{padding:6px 12px;font-size:14px;font-weight:400;line-height:1;color:#555;text-align:center;background-color:#eee;border:1px solid #ccc;border-radius:4px}.input-group-addon.input-sm{padding:5px 10px;font-size:12px;border-radius:3px}.input-group-addon.input-lg{padding:10px 16px;font-size:18px;border-radius:6px}.input-group-addon input[type=radio],.input-group-addon input[type=checkbox]{margin-top:0}.input-group .form-control:first-child,.input-group-addon:first-child,.input-group-btn:first-child>.btn,.input-group-btn:first-child>.btn-group>.btn,.input-group-btn:first-child>.dropdown-toggle,.input-group-btn:last-child>.btn:not(:last-child):not(.dropdown-toggle),.input-group-btn:last-child>.btn-group:not(:last-child)>.btn{border-bottom-right-radius:0;border-top-right-radius:0}.input-group-addon:first-child{border-right:0}.input-group .form-control:last-child,.input-group-addon:last-child,.input-group-btn:last-child>.btn,.input-group-btn:last-child>.btn-group>.btn,.input-group-btn:last-child>.dropdown-toggle,.input-group-btn:first-child>.btn:not(:first-child),.input-group-btn:first-child>.btn-group:not(:first-child)>.btn{border-bottom-left-radius:0;border-top-left-radius:0}.input-group-addon:last-child{border-left:0}.input-group-btn{position:relative;font-size:0;white-space:nowrap}.input-group-btn>.btn{position:relative}.input-group-btn>.btn+.btn{margin-left:-1px}.input-group-btn>.btn:hover,.input-group-btn>.btn:focus,.input-group-btn>.btn:active{z-index:2}.input-group-btn:first-child>.btn,.input-group-btn:first-child>.btn-group{margin-right:-1px}.input-group-btn:last-child>.btn,.input-group-btn:last-child>.btn-group{margin-left:-1px}.nav{margin-bottom:0;padding-left:0;list-style:none}.nav>li{position:relative;display:block}.nav>li>a{position:relative;display:block;padding:10px 15px}.nav>li>a:hover,.nav>li>a:focus{text-decoration:none;background-color:#eee}.nav>li.disabled>a{color:#999}.nav>li.disabled>a:hover,.nav>li.disabled>a:focus{color:#999;text-decoration:none;background-color:transparent;cursor:not-allowed}.nav .open>a,.nav .open>a:hover,.nav .open>a:focus{background-color:#eee;border-color:#428bca}.nav .nav-divider{height:1px;margin:9px 0;overflow:hidden;background-color:#e5e5e5}.nav>li>a>img{max-width:none}.nav-tabs{border-bottom:1px solid #ddd}.nav-tabs>li{float:left;margin-bottom:-1px}.nav-tabs>li>a{margin-right:2px;line-height:1.428571429;border:1px solid transparent;border-radius:4px 4px 0 0}.nav-tabs>li>a:hover{border-color:#eee #eee #ddd}.nav-tabs>li.active>a,.nav-tabs>li.active>a:hover,.nav-tabs>li.active>a:focus{color:#555;background-color:#fff;border:1px solid #ddd;border-bottom-color:transparent;cursor:default}.nav-tabs.nav-justified{width:100%;border-bottom:0}.nav-tabs.nav-justified>li{float:none}.nav-tabs.nav-justified>li>a{text-align:center;margin-bottom:5px}.nav-tabs.nav-justified>.dropdown .dropdown-menu{top:auto;left:auto}@media (min-width:768px){.nav-tabs.nav-justified>li{display:table-cell;width:1%}.nav-tabs.nav-justified>li>a{margin-bottom:0}}.nav-tabs.nav-justified>li>a{margin-right:0;border-radius:4px}.nav-tabs.nav-justified>.active>a,.nav-tabs.nav-justified>.active>a:hover,.nav-tabs.nav-justified>.active>a:focus{border:1px solid #ddd}@media (min-width:768px){.nav-tabs.nav-justified>li>a{border-bottom:1px solid #ddd;border-radius:4px 4px 0 0}.nav-tabs.nav-justified>.active>a,.nav-tabs.nav-justified>.active>a:hover,.nav-tabs.nav-justified>.active>a:focus{border-bottom-color:#fff}}.nav-pills>li{float:left}.nav-pills>li>a{border-radius:4px}.nav-pills>li+li{margin-left:2px}.nav-pills>li.active>a,.nav-pills>li.active>a:hover,.nav-pills>li.active>a:focus{color:#fff;background-color:#428bca}.nav-stacked>li{float:none}.nav-stacked>li+li{margin-top:2px;margin-left:0}.nav-justified{width:100%}.nav-justified>li{float:none}.nav-justified>li>a{text-align:center;margin-bottom:5px}.nav-justified>.dropdown .dropdown-menu{top:auto;left:auto}@media (min-width:768px){.nav-justified>li{display:table-cell;width:1%}.nav-justified>li>a{margin-bottom:0}}.nav-tabs-justified{border-bottom:0}.nav-tabs-justified>li>a{margin-right:0;border-radius:4px}.nav-tabs-justified>.active>a,.nav-tabs-justified>.active>a:hover,.nav-tabs-justified>.active>a:focus{border:1px solid #ddd}@media (min-width:768px){.nav-tabs-justified>li>a{border-bottom:1px solid #ddd;border-radius:4px 4px 0 0}.nav-tabs-justified>.active>a,.nav-tabs-justified>.active>a:hover,.nav-tabs-justified>.active>a:focus{border-bottom-color:#fff}}.tab-content>.tab-pane{display:none}.tab-content>.active{display:block}.nav-tabs .dropdown-menu{margin-top:-1px;border-top-right-radius:0;border-top-left-radius:0}.navbar{position:relative;min-height:50px;margin-bottom:20px;border:1px solid transparent}@media (min-width:768px){.navbar{border-radius:4px}}@media (min-width:768px){.navbar-header{float:left}}.navbar-collapse{max-height:340px;overflow-x:visible;padding-right:15px;padding-left:15px;border-top:1px solid transparent;box-shadow:inset 0 1px 0 rgba(255,255,255,.1);-webkit-overflow-scrolling:touch}.navbar-collapse.in{overflow-y:auto}@media (min-width:768px){.navbar-collapse{width:auto;border-top:0;box-shadow:none}.navbar-collapse.collapse{display:block!important;height:auto!important;padding-bottom:0;overflow:visible!important}.navbar-collapse.in{overflow-y:visible}.navbar-fixed-top .navbar-collapse,.navbar-static-top .navbar-collapse,.navbar-fixed-bottom .navbar-collapse{padding-left:0;padding-right:0}}.container>.navbar-header,.container-fluid>.navbar-header,.container>.navbar-collapse,.container-fluid>.navbar-collapse{margin-right:-15px;margin-left:-15px}@media (min-width:768px){.container>.navbar-header,.container-fluid>.navbar-header,.container>.navbar-collapse,.container-fluid>.navbar-collapse{margin-right:0;margin-left:0}}.navbar-static-top{z-index:1000;border-width:0 0 1px}@media (min-width:768px){.navbar-static-top{border-radius:0}}.navbar-fixed-top,.navbar-fixed-bottom{position:fixed;right:0;left:0;z-index:1030}@media (min-width:768px){.navbar-fixed-top,.navbar-fixed-bottom{border-radius:0}}.navbar-fixed-top{top:0;border-width:0 0 1px}.navbar-fixed-bottom{bottom:0;margin-bottom:0;border-width:1px 0 0}.navbar-brand{float:left;padding:15px;font-size:18px;line-height:20px;height:20px}.navbar-brand:hover,.navbar-brand:focus{text-decoration:none}@media (min-width:768px){.navbar>.container .navbar-brand,.navbar>.container-fluid .navbar-brand{margin-left:-15px}}.navbar-toggle{position:relative;float:right;margin-right:15px;padding:9px 10px;margin-top:8px;margin-bottom:8px;background-color:transparent;background-image:none;border:1px solid transparent;border-radius:4px}.navbar-toggle:focus{outline:0}.navbar-toggle .icon-bar{display:block;width:22px;height:2px;border-radius:1px}.navbar-toggle .icon-bar+.icon-bar{margin-top:4px}@media (min-width:768px){.navbar-toggle{display:none}}.navbar-nav{margin:7.5px -15px}.navbar-nav>li>a{padding-top:10px;padding-bottom:10px;line-height:20px}@media (max-width:767px){.navbar-nav .open .dropdown-menu{position:static;float:none;width:auto;margin-top:0;background-color:transparent;border:0;box-shadow:none}.navbar-nav .open .dropdown-menu>li>a,.navbar-nav .open .dropdown-menu .dropdown-header{padding:5px 15px 5px 25px}.navbar-nav .open .dropdown-menu>li>a{line-height:20px}.navbar-nav .open .dropdown-menu>li>a:hover,.navbar-nav .open .dropdown-menu>li>a:focus{background-image:none}}@media (min-width:768px){.navbar-nav{float:left;margin:0}.navbar-nav>li{float:left}.navbar-nav>li>a{padding-top:15px;padding-bottom:15px}.navbar-nav.navbar-right:last-child{margin-right:-15px}}@media (min-width:768px){.navbar-left{float:left!important}.navbar-right{float:right!important}}.navbar-form{margin-left:-15px;margin-right:-15px;padding:10px 15px;border-top:1px solid transparent;border-bottom:1px solid transparent;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.1),0 1px 0 rgba(255,255,255,.1);box-shadow:inset 0 1px 0 rgba(255,255,255,.1),0 1px 0 rgba(255,255,255,.1);margin-top:8px;margin-bottom:8px}@media (min-width:768px){.navbar-form .form-group{display:inline-block;margin-bottom:0;vertical-align:middle}.navbar-form .form-control{display:inline-block;width:auto;vertical-align:middle}.navbar-form .control-label{margin-bottom:0;vertical-align:middle}.navbar-form .radio,.navbar-form .checkbox{display:inline-block;margin-top:0;margin-bottom:0;padding-left:0;vertical-align:middle}.navbar-form .radio input[type=radio],.navbar-form .checkbox input[type=checkbox]{float:none;margin-left:0}.navbar-form .has-feedback .form-control-feedback{top:0}}@media (max-width:767px){.navbar-form .form-group{margin-bottom:5px}}@media (min-width:768px){.navbar-form{width:auto;border:0;margin-left:0;margin-right:0;padding-top:0;padding-bottom:0;-webkit-box-shadow:none;box-shadow:none}.navbar-form.navbar-right:last-child{margin-right:-15px}}.navbar-nav>li>.dropdown-menu{margin-top:0;border-top-right-radius:0;border-top-left-radius:0}.navbar-fixed-bottom .navbar-nav>li>.dropdown-menu{border-bottom-right-radius:0;border-bottom-left-radius:0}.navbar-btn{margin-top:8px;margin-bottom:8px}.navbar-btn.btn-sm{margin-top:10px;margin-bottom:10px}.navbar-btn.btn-xs{margin-top:14px;margin-bottom:14px}.navbar-text{margin-top:15px;margin-bottom:15px}@media (min-width:768px){.navbar-text{float:left;margin-left:15px;margin-right:15px}.navbar-text.navbar-right:last-child{margin-right:0}}.navbar-default{background-color:#f8f8f8;border-color:#e7e7e7}.navbar-default .navbar-brand{color:#777}.navbar-default .navbar-brand:hover,.navbar-default .navbar-brand:focus{color:#5e5e5e;background-color:transparent}.navbar-default .navbar-text{color:#777}.navbar-default .navbar-nav>li>a{color:#777}.navbar-default .navbar-nav>li>a:hover,.navbar-default .navbar-nav>li>a:focus{color:#333;background-color:transparent}.navbar-default .navbar-nav>.active>a,.navbar-default .navbar-nav>.active>a:hover,.navbar-default .navbar-nav>.active>a:focus{color:#555;background-color:#e7e7e7}.navbar-default .navbar-nav>.disabled>a,.navbar-default .navbar-nav>.disabled>a:hover,.navbar-default .navbar-nav>.disabled>a:focus{color:#ccc;background-color:transparent}.navbar-default .navbar-toggle{border-color:#ddd}.navbar-default .navbar-toggle:hover,.navbar-default .navbar-toggle:focus{background-color:#ddd}.navbar-default .navbar-toggle .icon-bar{background-color:#888}.navbar-default .navbar-collapse,.navbar-default .navbar-form{border-color:#e7e7e7}.navbar-default .navbar-nav>.open>a,.navbar-default .navbar-nav>.open>a:hover,.navbar-default .navbar-nav>.open>a:focus{background-color:#e7e7e7;color:#555}@media (max-width:767px){.navbar-default .navbar-nav .open .dropdown-menu>li>a{color:#777}.navbar-default .navbar-nav .open .dropdown-menu>li>a:hover,.navbar-default .navbar-nav .open .dropdown-menu>li>a:focus{color:#333;background-color:transparent}.navbar-default .navbar-nav .open .dropdown-menu>.active>a,.navbar-default .navbar-nav .open .dropdown-menu>.active>a:hover,.navbar-default .navbar-nav .open .dropdown-menu>.active>a:focus{color:#555;background-color:#e7e7e7}.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a,.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a:hover,.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a:focus{color:#ccc;background-color:transparent}}.navbar-default .navbar-link{color:#777}.navbar-default .navbar-link:hover{color:#333}.navbar-inverse{background-color:#222;border-color:#080808}.navbar-inverse .navbar-brand{color:#999}.navbar-inverse .navbar-brand:hover,.navbar-inverse .navbar-brand:focus{color:#fff;background-color:transparent}.navbar-inverse .navbar-text{color:#999}.navbar-inverse .navbar-nav>li>a{color:#999}.navbar-inverse .navbar-nav>li>a:hover,.navbar-inverse .navbar-nav>li>a:focus{color:#fff;background-color:transparent}.navbar-inverse .navbar-nav>.active>a,.navbar-inverse .navbar-nav>.active>a:hover,.navbar-inverse .navbar-nav>.active>a:focus{color:#fff;background-color:#080808}.navbar-inverse .navbar-nav>.disabled>a,.navbar-inverse .navbar-nav>.disabled>a:hover,.navbar-inverse .navbar-nav>.disabled>a:focus{color:#444;background-color:transparent}.navbar-inverse .navbar-toggle{border-color:#333}.navbar-inverse .navbar-toggle:hover,.navbar-inverse .navbar-toggle:focus{background-color:#333}.navbar-inverse .navbar-toggle .icon-bar{background-color:#fff}.navbar-inverse .navbar-collapse,.navbar-inverse .navbar-form{border-color:#101010}.navbar-inverse .navbar-nav>.open>a,.navbar-inverse .navbar-nav>.open>a:hover,.navbar-inverse .navbar-nav>.open>a:focus{background-color:#080808;color:#fff}@media (max-width:767px){.navbar-inverse .navbar-nav .open .dropdown-menu>.dropdown-header{border-color:#080808}.navbar-inverse .navbar-nav .open .dropdown-menu .divider{background-color:#080808}.navbar-inverse .navbar-nav .open .dropdown-menu>li>a{color:#999}.navbar-inverse .navbar-nav .open .dropdown-menu>li>a:hover,.navbar-inverse .navbar-nav .open .dropdown-menu>li>a:focus{color:#fff;background-color:transparent}.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a,.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a:hover,.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a:focus{color:#fff;background-color:#080808}.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a,.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a:hover,.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a:focus{color:#444;background-color:transparent}}.navbar-inverse .navbar-link{color:#999}.navbar-inverse .navbar-link:hover{color:#fff}.breadcrumb{padding:8px 15px;margin-bottom:20px;list-style:none;background-color:#f5f5f5;border-radius:4px}.breadcrumb>li{display:inline-block}.breadcrumb>li+li:before{content:"/\00a0";padding:0 5px;color:#ccc}.breadcrumb>.active{color:#999}.pagination{display:inline-block;padding-left:0;margin:20px 0;border-radius:4px}.pagination>li{display:inline}.pagination>li>a,.pagination>li>span{position:relative;float:left;padding:6px 12px;line-height:1.428571429;text-decoration:none;color:#428bca;background-color:#fff;border:1px solid #ddd;margin-left:-1px}.pagination>li:first-child>a,.pagination>li:first-child>span{margin-left:0;border-bottom-left-radius:4px;border-top-left-radius:4px}.pagination>li:last-child>a,.pagination>li:last-child>span{border-bottom-right-radius:4px;border-top-right-radius:4px}.pagination>li>a:hover,.pagination>li>span:hover,.pagination>li>a:focus,.pagination>li>span:focus{color:#2a6496;background-color:#eee;border-color:#ddd}.pagination>.active>a,.pagination>.active>span,.pagination>.active>a:hover,.pagination>.active>span:hover,.pagination>.active>a:focus,.pagination>.active>span:focus{z-index:2;color:#fff;background-color:#428bca;border-color:#428bca;cursor:default}.pagination>.disabled>span,.pagination>.disabled>span:hover,.pagination>.disabled>span:focus,.pagination>.disabled>a,.pagination>.disabled>a:hover,.pagination>.disabled>a:focus{color:#999;background-color:#fff;border-color:#ddd;cursor:not-allowed}.pagination-lg>li>a,.pagination-lg>li>span{padding:10px 16px;font-size:18px}.pagination-lg>li:first-child>a,.pagination-lg>li:first-child>span{border-bottom-left-radius:6px;border-top-left-radius:6px}.pagination-lg>li:last-child>a,.pagination-lg>li:last-child>span{border-bottom-right-radius:6px;border-top-right-radius:6px}.pagination-sm>li>a,.pagination-sm>li>span{padding:5px 10px;font-size:12px}.pagination-sm>li:first-child>a,.pagination-sm>li:first-child>span{border-bottom-left-radius:3px;border-top-left-radius:3px}.pagination-sm>li:last-child>a,.pagination-sm>li:last-child>span{border-bottom-right-radius:3px;border-top-right-radius:3px}.pager{padding-left:0;margin:20px 0;list-style:none;text-align:center}.pager li{display:inline}.pager li>a,.pager li>span{display:inline-block;padding:5px 14px;background-color:#fff;border:1px solid #ddd;border-radius:15px}.pager li>a:hover,.pager li>a:focus{text-decoration:none;background-color:#eee}.pager .next>a,.pager .next>span{float:right}.pager .previous>a,.pager .previous>span{float:left}.pager .disabled>a,.pager .disabled>a:hover,.pager .disabled>a:focus,.pager .disabled>span{color:#999;background-color:#fff;cursor:not-allowed}.label{display:inline;padding:.2em .6em .3em;font-size:75%;font-weight:700;line-height:1;color:#fff;text-align:center;white-space:nowrap;vertical-align:baseline;border-radius:.25em}.label[href]:hover,.label[href]:focus{color:#fff;text-decoration:none;cursor:pointer}.label:empty{display:none}.btn .label{position:relative;top:-1px}.label-default{background-color:#999}.label-default[href]:hover,.label-default[href]:focus{background-color:gray}.label-primary{background-color:#428bca}.label-primary[href]:hover,.label-primary[href]:focus{background-color:#3071a9}.label-success{background-color:#5cb85c}.label-success[href]:hover,.label-success[href]:focus{background-color:#449d44}.label-info{background-color:#5bc0de}.label-info[href]:hover,.label-info[href]:focus{background-color:#31b0d5}.label-warning{background-color:#f0ad4e}.label-warning[href]:hover,.label-warning[href]:focus{background-color:#ec971f}.label-danger{background-color:#d9534f}.label-danger[href]:hover,.label-danger[href]:focus{background-color:#c9302c}.badge{display:inline-block;min-width:10px;padding:3px 7px;font-size:12px;font-weight:700;color:#fff;line-height:1;vertical-align:baseline;white-space:nowrap;text-align:center;background-color:#999;border-radius:10px}.badge:empty{display:none}.btn .badge{position:relative;top:-1px}.btn-xs .badge{top:0;padding:1px 5px}a.badge:hover,a.badge:focus{color:#fff;text-decoration:none;cursor:pointer}a.list-group-item.active>.badge,.nav-pills>.active>a>.badge{color:#428bca;background-color:#fff}.nav-pills>li>a>.badge{margin-left:3px}.jumbotron{padding:30px;margin-bottom:30px;color:inherit;background-color:#eee}.jumbotron h1,.jumbotron .h1{color:inherit}.jumbotron p{margin-bottom:15px;font-size:21px;font-weight:200}.container .jumbotron{border-radius:6px}.jumbotron .container{max-width:100%}@media screen and (min-width:768px){.jumbotron{padding-top:48px;padding-bottom:48px}.container .jumbotron{padding-left:60px;padding-right:60px}.jumbotron h1,.jumbotron .h1{font-size:63px}}.thumbnail{display:block;padding:4px;margin-bottom:20px;line-height:1.428571429;background-color:#fff;border:1px solid #ddd;border-radius:4px;-webkit-transition:all .2s ease-in-out;transition:all .2s ease-in-out}.thumbnail>img,.thumbnail a>img{display:block;max-width:100%;height:auto;margin-left:auto;margin-right:auto}a.thumbnail:hover,a.thumbnail:focus,a.thumbnail.active{border-color:#428bca}.thumbnail .caption{padding:9px;color:#333}.alert{padding:15px;margin-bottom:20px;border:1px solid transparent;border-radius:4px}.alert h4{margin-top:0;color:inherit}.alert .alert-link{font-weight:700}.alert>p,.alert>ul{margin-bottom:0}.alert>p+p{margin-top:5px}.alert-dismissable{padding-right:35px}.alert-dismissable .close{position:relative;top:-2px;right:-21px;color:inherit}.alert-success{background-color:#dff0d8;border-color:#d6e9c6;color:#3c763d}.alert-success hr{border-top-color:#c9e2b3}.alert-success .alert-link{color:#2b542c}.alert-info{background-color:#d9edf7;border-color:#bce8f1;color:#31708f}.alert-info hr{border-top-color:#a6e1ec}.alert-info .alert-link{color:#245269}.alert-warning{background-color:#fcf8e3;border-color:#faebcc;color:#8a6d3b}.alert-warning hr{border-top-color:#f7e1b5}.alert-warning .alert-link{color:#66512c}.alert-danger{background-color:#f2dede;border-color:#ebccd1;color:#a94442}.alert-danger hr{border-top-color:#e4b9c0}.alert-danger .alert-link{color:#843534}@-webkit-keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}@keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}.progress{overflow:hidden;height:20px;margin-bottom:20px;background-color:#f5f5f5;border-radius:4px;-webkit-box-shadow:inset 0 1px 2px rgba(0,0,0,.1);box-shadow:inset 0 1px 2px rgba(0,0,0,.1)}.progress-bar{float:left;width:0;height:100%;font-size:12px;line-height:20px;color:#fff;text-align:center;background-color:#428bca;-webkit-box-shadow:inset 0 -1px 0 rgba(0,0,0,.15);box-shadow:inset 0 -1px 0 rgba(0,0,0,.15);-webkit-transition:width .6s ease;transition:width .6s ease}.progress-striped .progress-bar{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: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-size:40px 40px}.progress.active .progress-bar{-webkit-animation:progress-bar-stripes 2s linear infinite;animation:progress-bar-stripes 2s linear infinite}.progress-bar-success{background-color:#5cb85c}.progress-striped .progress-bar-success{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.progress-bar-info{background-color:#5bc0de}.progress-striped .progress-bar-info{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.progress-bar-warning{background-color:#f0ad4e}.progress-striped .progress-bar-warning{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.progress-bar-danger{background-color:#d9534f}.progress-striped .progress-bar-danger{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.media,.media-body{overflow:hidden;zoom:1}.media,.media .media{margin-top:15px}.media:first-child{margin-top:0}.media-object{display:block}.media-heading{margin:0 0 5px}.media>.pull-left{margin-right:10px}.media>.pull-right{margin-left:10px}.media-list{padding-left:0;list-style:none}.list-group{margin-bottom:20px;padding-left:0}.list-group-item{position:relative;display:block;padding:10px 15px;margin-bottom:-1px;background-color:#fff;border:1px solid #ddd}.list-group-item:first-child{border-top-right-radius:4px;border-top-left-radius:4px}.list-group-item:last-child{margin-bottom:0;border-bottom-right-radius:4px;border-bottom-left-radius:4px}.list-group-item>.badge{float:right}.list-group-item>.badge+.badge{margin-right:5px}a.list-group-item{color:#555}a.list-group-item .list-group-item-heading{color:#333}a.list-group-item:hover,a.list-group-item:focus{text-decoration:none;background-color:#f5f5f5}a.list-group-item.active,a.list-group-item.active:hover,a.list-group-item.active:focus{z-index:2;color:#fff;background-color:#428bca;border-color:#428bca}a.list-group-item.active .list-group-item-heading,a.list-group-item.active:hover .list-group-item-heading,a.list-group-item.active:focus .list-group-item-heading{color:inherit}a.list-group-item.active .list-group-item-text,a.list-group-item.active:hover .list-group-item-text,a.list-group-item.active:focus .list-group-item-text{color:#e1edf7}.list-group-item-success{color:#3c763d;background-color:#dff0d8}a.list-group-item-success{color:#3c763d}a.list-group-item-success .list-group-item-heading{color:inherit}a.list-group-item-success:hover,a.list-group-item-success:focus{color:#3c763d;background-color:#d0e9c6}a.list-group-item-success.active,a.list-group-item-success.active:hover,a.list-group-item-success.active:focus{color:#fff;background-color:#3c763d;border-color:#3c763d}.list-group-item-info{color:#31708f;background-color:#d9edf7}a.list-group-item-info{color:#31708f}a.list-group-item-info .list-group-item-heading{color:inherit}a.list-group-item-info:hover,a.list-group-item-info:focus{color:#31708f;background-color:#c4e3f3}a.list-group-item-info.active,a.list-group-item-info.active:hover,a.list-group-item-info.active:focus{color:#fff;background-color:#31708f;border-color:#31708f}.list-group-item-warning{color:#8a6d3b;background-color:#fcf8e3}a.list-group-item-warning{color:#8a6d3b}a.list-group-item-warning .list-group-item-heading{color:inherit}a.list-group-item-warning:hover,a.list-group-item-warning:focus{color:#8a6d3b;background-color:#faf2cc}a.list-group-item-warning.active,a.list-group-item-warning.active:hover,a.list-group-item-warning.active:focus{color:#fff;background-color:#8a6d3b;border-color:#8a6d3b}.list-group-item-danger{color:#a94442;background-color:#f2dede}a.list-group-item-danger{color:#a94442}a.list-group-item-danger .list-group-item-heading{color:inherit}a.list-group-item-danger:hover,a.list-group-item-danger:focus{color:#a94442;background-color:#ebcccc}a.list-group-item-danger.active,a.list-group-item-danger.active:hover,a.list-group-item-danger.active:focus{color:#fff;background-color:#a94442;border-color:#a94442}.list-group-item-heading{margin-top:0;margin-bottom:5px}.list-group-item-text{margin-bottom:0;line-height:1.3}.panel{margin-bottom:20px;background-color:#fff;border:1px solid transparent;border-radius:4px;-webkit-box-shadow:0 1px 1px rgba(0,0,0,.05);box-shadow:0 1px 1px rgba(0,0,0,.05)}.panel-body{padding:15px}.panel>.list-group{margin-bottom:0}.panel>.list-group .list-group-item{border-width:1px 0;border-radius:0}.panel>.list-group .list-group-item:first-child{border-top:0}.panel>.list-group .list-group-item:last-child{border-bottom:0}.panel>.list-group:first-child .list-group-item:first-child{border-top-right-radius:3px;border-top-left-radius:3px}.panel>.list-group:last-child .list-group-item:last-child{border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel-heading+.list-group .list-group-item:first-child{border-top-width:0}.panel>.table,.panel>.table-responsive>.table{margin-bottom:0}.panel>.table:first-child>thead:first-child>tr:first-child td:first-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child td:first-child,.panel>.table:first-child>tbody:first-child>tr:first-child td:first-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child td:first-child,.panel>.table:first-child>thead:first-child>tr:first-child th:first-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child th:first-child,.panel>.table:first-child>tbody:first-child>tr:first-child th:first-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child th:first-child{border-top-left-radius:3px}.panel>.table:first-child>thead:first-child>tr:first-child td:last-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child td:last-child,.panel>.table:first-child>tbody:first-child>tr:first-child td:last-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child td:last-child,.panel>.table:first-child>thead:first-child>tr:first-child th:last-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child th:last-child,.panel>.table:first-child>tbody:first-child>tr:first-child th:last-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child th:last-child{border-top-right-radius:3px}.panel>.table:last-child>tbody:last-child>tr:last-child td:first-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child td:first-child,.panel>.table:last-child>tfoot:last-child>tr:last-child td:first-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child td:first-child,.panel>.table:last-child>tbody:last-child>tr:last-child th:first-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child th:first-child,.panel>.table:last-child>tfoot:last-child>tr:last-child th:first-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child th:first-child{border-bottom-left-radius:3px}.panel>.table:last-child>tbody:last-child>tr:last-child td:last-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child td:last-child,.panel>.table:last-child>tfoot:last-child>tr:last-child td:last-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child td:last-child,.panel>.table:last-child>tbody:last-child>tr:last-child th:last-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child th:last-child,.panel>.table:last-child>tfoot:last-child>tr:last-child th:last-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child th:last-child{border-bottom-right-radius:3px}.panel>.panel-body+.table,.panel>.panel-body+.table-responsive{border-top:1px solid #ddd}.panel>.table>tbody:first-child>tr:first-child th,.panel>.table>tbody:first-child>tr:first-child td{border-top:0}.panel>.table-bordered,.panel>.table-responsive>.table-bordered{border:0}.panel>.table-bordered>thead>tr>th:first-child,.panel>.table-responsive>.table-bordered>thead>tr>th:first-child,.panel>.table-bordered>tbody>tr>th:first-child,.panel>.table-responsive>.table-bordered>tbody>tr>th:first-child,.panel>.table-bordered>tfoot>tr>th:first-child,.panel>.table-responsive>.table-bordered>tfoot>tr>th:first-child,.panel>.table-bordered>thead>tr>td:first-child,.panel>.table-responsive>.table-bordered>thead>tr>td:first-child,.panel>.table-bordered>tbody>tr>td:first-child,.panel>.table-responsive>.table-bordered>tbody>tr>td:first-child,.panel>.table-bordered>tfoot>tr>td:first-child,.panel>.table-responsive>.table-bordered>tfoot>tr>td:first-child{border-left:0}.panel>.table-bordered>thead>tr>th:last-child,.panel>.table-responsive>.table-bordered>thead>tr>th:last-child,.panel>.table-bordered>tbody>tr>th:last-child,.panel>.table-responsive>.table-bordered>tbody>tr>th:last-child,.panel>.table-bordered>tfoot>tr>th:last-child,.panel>.table-responsive>.table-bordered>tfoot>tr>th:last-child,.panel>.table-bordered>thead>tr>td:last-child,.panel>.table-responsive>.table-bordered>thead>tr>td:last-child,.panel>.table-bordered>tbody>tr>td:last-child,.panel>.table-responsive>.table-bordered>tbody>tr>td:last-child,.panel>.table-bordered>tfoot>tr>td:last-child,.panel>.table-responsive>.table-bordered>tfoot>tr>td:last-child{border-right:0}.panel>.table-bordered>thead>tr:first-child>th,.panel>.table-responsive>.table-bordered>thead>tr:first-child>th,.panel>.table-bordered>tbody>tr:first-child>th,.panel>.table-responsive>.table-bordered>tbody>tr:first-child>th,.panel>.table-bordered>tfoot>tr:first-child>th,.panel>.table-responsive>.table-bordered>tfoot>tr:first-child>th,.panel>.table-bordered>thead>tr:first-child>td,.panel>.table-responsive>.table-bordered>thead>tr:first-child>td,.panel>.table-bordered>tbody>tr:first-child>td,.panel>.table-responsive>.table-bordered>tbody>tr:first-child>td,.panel>.table-bordered>tfoot>tr:first-child>td,.panel>.table-responsive>.table-bordered>tfoot>tr:first-child>td{border-top:0}.panel>.table-bordered>thead>tr:last-child>th,.panel>.table-responsive>.table-bordered>thead>tr:last-child>th,.panel>.table-bordered>tbody>tr:last-child>th,.panel>.table-responsive>.table-bordered>tbody>tr:last-child>th,.panel>.table-bordered>tfoot>tr:last-child>th,.panel>.table-responsive>.table-bordered>tfoot>tr:last-child>th,.panel>.table-bordered>thead>tr:last-child>td,.panel>.table-responsive>.table-bordered>thead>tr:last-child>td,.panel>.table-bordered>tbody>tr:last-child>td,.panel>.table-responsive>.table-bordered>tbody>tr:last-child>td,.panel>.table-bordered>tfoot>tr:last-child>td,.panel>.table-responsive>.table-bordered>tfoot>tr:last-child>td{border-bottom:0}.panel>.table-responsive{border:0;margin-bottom:0}.panel-heading{padding:10px 15px;border-bottom:1px solid transparent;border-top-right-radius:3px;border-top-left-radius:3px}.panel-heading>.dropdown .dropdown-toggle{color:inherit}.panel-title{margin-top:0;margin-bottom:0;font-size:16px;color:inherit}.panel-title>a{color:inherit}.panel-footer{padding:10px 15px;background-color:#f5f5f5;border-top:1px solid #ddd;border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel-group{margin-bottom:20px}.panel-group .panel{margin-bottom:0;border-radius:4px;overflow:hidden}.panel-group .panel+.panel{margin-top:5px}.panel-group .panel-heading{border-bottom:0}.panel-group .panel-heading+.panel-collapse .panel-body{border-top:1px solid #ddd}.panel-group .panel-footer{border-top:0}.panel-group .panel-footer+.panel-collapse .panel-body{border-bottom:1px solid #ddd}.panel-default{border-color:#ddd}.panel-default>.panel-heading{color:#333;background-color:#f5f5f5;border-color:#ddd}.panel-default>.panel-heading+.panel-collapse .panel-body{border-top-color:#ddd}.panel-default>.panel-footer+.panel-collapse .panel-body{border-bottom-color:#ddd}.panel-primary{border-color:#428bca}.panel-primary>.panel-heading{color:#fff;background-color:#428bca;border-color:#428bca}.panel-primary>.panel-heading+.panel-collapse .panel-body{border-top-color:#428bca}.panel-primary>.panel-footer+.panel-collapse .panel-body{border-bottom-color:#428bca}.panel-success{border-color:#d6e9c6}.panel-success>.panel-heading{color:#3c763d;background-color:#dff0d8;border-color:#d6e9c6}.panel-success>.panel-heading+.panel-collapse .panel-body{border-top-color:#d6e9c6}.panel-success>.panel-footer+.panel-collapse .panel-body{border-bottom-color:#d6e9c6}.panel-info{border-color:#bce8f1}.panel-info>.panel-heading{color:#31708f;background-color:#d9edf7;border-color:#bce8f1}.panel-info>.panel-heading+.panel-collapse .panel-body{border-top-color:#bce8f1}.panel-info>.panel-footer+.panel-collapse .panel-body{border-bottom-color:#bce8f1}.panel-warning{border-color:#faebcc}.panel-warning>.panel-heading{color:#8a6d3b;background-color:#fcf8e3;border-color:#faebcc}.panel-warning>.panel-heading+.panel-collapse .panel-body{border-top-color:#faebcc}.panel-warning>.panel-footer+.panel-collapse .panel-body{border-bottom-color:#faebcc}.panel-danger{border-color:#ebccd1}.panel-danger>.panel-heading{color:#a94442;background-color:#f2dede;border-color:#ebccd1}.panel-danger>.panel-heading+.panel-collapse .panel-body{border-top-color:#ebccd1}.panel-danger>.panel-footer+.panel-collapse .panel-body{border-bottom-color:#ebccd1}.well{min-height:20px;padding:19px;margin-bottom:20px;background-color:#f5f5f5;border:1px solid #e3e3e3;border-radius:4px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.05);box-shadow:inset 0 1px 1px rgba(0,0,0,.05)}.well blockquote{border-color:#ddd;border-color:rgba(0,0,0,.15)}.well-lg{padding:24px;border-radius:6px}.well-sm{padding:9px;border-radius:3px}.close{float:right;font-size:21px;font-weight:700;line-height:1;color:#000;text-shadow:0 1px 0 #fff;opacity:.2;filter:alpha(opacity=20)}.close:hover,.close:focus{color:#000;text-decoration:none;cursor:pointer;opacity:.5;filter:alpha(opacity=50)}button.close{padding:0;cursor:pointer;background:0 0;border:0;-webkit-appearance:none}.modal-open{overflow:hidden}.modal{display:none;overflow:auto;overflow-y:scroll;position:fixed;top:0;right:0;bottom:0;left:0;z-index:1050;-webkit-overflow-scrolling:touch;outline:0}.modal.fade .modal-dialog{-webkit-transform:translate(0,-25%);-ms-transform:translate(0,-25%);transform:translate(0,-25%);-webkit-transition:-webkit-transform .3s ease-out;-moz-transition:-moz-transform .3s ease-out;-o-transition:-o-transform .3s ease-out;transition:transform .3s ease-out}.modal.in .modal-dialog{-webkit-transform:translate(0,0);-ms-transform:translate(0,0);transform:translate(0,0)}.modal-dialog{position:relative;width:auto;margin:10px}.modal-content{position:relative;background-color:#fff;border:1px solid #999;border:1px solid rgba(0,0,0,.2);border-radius:6px;-webkit-box-shadow:0 3px 9px rgba(0,0,0,.5);box-shadow:0 3px 9px rgba(0,0,0,.5);background-clip:padding-box;outline:0}.modal-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;z-index:1040;background-color:#000}.modal-backdrop.fade{opacity:0;filter:alpha(opacity=0)}.modal-backdrop.in{opacity:.5;filter:alpha(opacity=50)}.modal-header{padding:15px;border-bottom:1px solid #e5e5e5;min-height:16.428571429px}.modal-header .close{margin-top:-2px}.modal-title{margin:0;line-height:1.428571429}.modal-body{position:relative;padding:20px}.modal-footer{margin-top:15px;padding:19px 20px 20px;text-align:right;border-top:1px solid #e5e5e5}.modal-footer .btn+.btn{margin-left:5px;margin-bottom:0}.modal-footer .btn-group .btn+.btn{margin-left:-1px}.modal-footer .btn-block+.btn-block{margin-left:0}@media (min-width:768px){.modal-dialog{width:600px;margin:30px auto}.modal-content{-webkit-box-shadow:0 5px 15px rgba(0,0,0,.5);box-shadow:0 5px 15px rgba(0,0,0,.5)}.modal-sm{width:300px}.modal-lg{width:900px}}.tooltip{position:absolute;z-index:1030;display:block;visibility:visible;font-size:12px;line-height:1.4;opacity:0;filter:alpha(opacity=0)}.tooltip.in{opacity:.9;filter:alpha(opacity=90)}.tooltip.top{margin-top:-3px;padding:5px 0}.tooltip.right{margin-left:3px;padding:0 5px}.tooltip.bottom{margin-top:3px;padding:5px 0}.tooltip.left{margin-left:-3px;padding:0 5px}.tooltip-inner{max-width:200px;padding:3px 8px;color:#fff;text-align:center;text-decoration:none;background-color:#000;border-radius:4px}.tooltip-arrow{position:absolute;width:0;height:0;border-color:transparent;border-style:solid}.tooltip.top .tooltip-arrow{bottom:0;left:50%;margin-left:-5px;border-width:5px 5px 0;border-top-color:#000}.tooltip.top-left .tooltip-arrow{bottom:0;left:5px;border-width:5px 5px 0;border-top-color:#000}.tooltip.top-right .tooltip-arrow{bottom:0;right:5px;border-width:5px 5px 0;border-top-color:#000}.tooltip.right .tooltip-arrow{top:50%;left:0;margin-top:-5px;border-width:5px 5px 5px 0;border-right-color:#000}.tooltip.left .tooltip-arrow{top:50%;right:0;margin-top:-5px;border-width:5px 0 5px 5px;border-left-color:#000}.tooltip.bottom .tooltip-arrow{top:0;left:50%;margin-left:-5px;border-width:0 5px 5px;border-bottom-color:#000}.tooltip.bottom-left .tooltip-arrow{top:0;left:5px;border-width:0 5px 5px;border-bottom-color:#000}.tooltip.bottom-right .tooltip-arrow{top:0;right:5px;border-width:0 5px 5px;border-bottom-color:#000}.popover{position:absolute;top:0;left:0;z-index:1010;display:none;max-width:276px;padding:1px;text-align:left;background-color:#fff;background-clip:padding-box;border:1px solid #ccc;border:1px solid rgba(0,0,0,.2);border-radius:6px;-webkit-box-shadow:0 5px 10px rgba(0,0,0,.2);box-shadow:0 5px 10px rgba(0,0,0,.2);white-space:normal}.popover.top{margin-top:-10px}.popover.right{margin-left:10px}.popover.bottom{margin-top:10px}.popover.left{margin-left:-10px}.popover-title{margin:0;padding:8px 14px;font-size:14px;font-weight:400;line-height:18px;background-color:#f7f7f7;border-bottom:1px solid #ebebeb;border-radius:5px 5px 0 0}.popover-content{padding:9px 14px}.popover .arrow,.popover .arrow:after{position:absolute;display:block;width:0;height:0;border-color:transparent;border-style:solid}.popover .arrow{border-width:11px}.popover .arrow:after{border-width:10px;content:""}.popover.top .arrow{left:50%;margin-left:-11px;border-bottom-width:0;border-top-color:#999;border-top-color:rgba(0,0,0,.25);bottom:-11px}.popover.top .arrow:after{content:" ";bottom:1px;margin-left:-10px;border-bottom-width:0;border-top-color:#fff}.popover.right .arrow{top:50%;left:-11px;margin-top:-11px;border-left-width:0;border-right-color:#999;border-right-color:rgba(0,0,0,.25)}.popover.right .arrow:after{content:" ";left:1px;bottom:-10px;border-left-width:0;border-right-color:#fff}.popover.bottom .arrow{left:50%;margin-left:-11px;border-top-width:0;border-bottom-color:#999;border-bottom-color:rgba(0,0,0,.25);top:-11px}.popover.bottom .arrow:after{content:" ";top:1px;margin-left:-10px;border-top-width:0;border-bottom-color:#fff}.popover.left .arrow{top:50%;right:-11px;margin-top:-11px;border-right-width:0;border-left-color:#999;border-left-color:rgba(0,0,0,.25)}.popover.left .arrow:after{content:" ";right:1px;border-right-width:0;border-left-color:#fff;bottom:-10px}.carousel{position:relative}.carousel-inner{position:relative;overflow:hidden;width:100%}.carousel-inner>.item{display:none;position:relative;-webkit-transition:.6s ease-in-out left;transition:.6s ease-in-out left}.carousel-inner>.item>img,.carousel-inner>.item>a>img{display:block;max-width:100%;height:auto;line-height:1}.carousel-inner>.active,.carousel-inner>.next,.carousel-inner>.prev{display:block}.carousel-inner>.active{left:0}.carousel-inner>.next,.carousel-inner>.prev{position:absolute;top:0;width:100%}.carousel-inner>.next{left:100%}.carousel-inner>.prev{left:-100%}.carousel-inner>.next.left,.carousel-inner>.prev.right{left:0}.carousel-inner>.active.left{left:-100%}.carousel-inner>.active.right{left:100%}.carousel-control{position:absolute;top:0;left:0;bottom:0;width:15%;opacity:.5;filter:alpha(opacity=50);font-size:20px;color:#fff;text-align:center;text-shadow:0 1px 2px rgba(0,0,0,.6)}.carousel-control.left{background-image:-webkit-linear-gradient(left,color-stop(rgba(0,0,0,.5) 0),color-stop(rgba(0,0,0,.0001) 100%));background-image:linear-gradient(to right,rgba(0,0,0,.5) 0,rgba(0,0,0,.0001) 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#80000000', endColorstr='#00000000', GradientType=1)}.carousel-control.right{left:auto;right:0;background-image:-webkit-linear-gradient(left,color-stop(rgba(0,0,0,.0001) 0),color-stop(rgba(0,0,0,.5) 100%));background-image:linear-gradient(to right,rgba(0,0,0,.0001) 0,rgba(0,0,0,.5) 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#00000000', endColorstr='#80000000', GradientType=1)}.carousel-control:hover,.carousel-control:focus{outline:0;color:#fff;text-decoration:none;opacity:.9;filter:alpha(opacity=90)}.carousel-control .icon-prev,.carousel-control .icon-next,.carousel-control .glyphicon-chevron-left,.carousel-control .glyphicon-chevron-right{position:absolute;top:50%;z-index:5;display:inline-block}.carousel-control .icon-prev,.carousel-control .glyphicon-chevron-left{left:50%}.carousel-control .icon-next,.carousel-control .glyphicon-chevron-right{right:50%}.carousel-control .icon-prev,.carousel-control .icon-next{width:20px;height:20px;margin-top:-10px;margin-left:-10px;font-family:serif}.carousel-control .icon-prev:before{content:'\2039'}.carousel-control .icon-next:before{content:'\203a'}.carousel-indicators{position:absolute;bottom:10px;left:50%;z-index:15;width:60%;margin-left:-30%;padding-left:0;list-style:none;text-align:center}.carousel-indicators li{display:inline-block;width:10px;height:10px;margin:1px;text-indent:-999px;border:1px solid #fff;border-radius:10px;cursor:pointer;background-color:#000 \9;background-color:rgba(0,0,0,0)}.carousel-indicators .active{margin:0;width:12px;height:12px;background-color:#fff}.carousel-caption{position:absolute;left:15%;right:15%;bottom:20px;z-index:10;padding-top:20px;padding-bottom:20px;color:#fff;text-align:center;text-shadow:0 1px 2px rgba(0,0,0,.6)}.carousel-caption .btn{text-shadow:none}@media screen and (min-width:768px){.carousel-control .glyphicons-chevron-left,.carousel-control .glyphicons-chevron-right,.carousel-control .icon-prev,.carousel-control .icon-next{width:30px;height:30px;margin-top:-15px;margin-left:-15px;font-size:30px}.carousel-caption{left:20%;right:20%;padding-bottom:30px}.carousel-indicators{bottom:20px}}.clearfix:before,.clearfix:after,.container:before,.container:after,.container-fluid:before,.container-fluid:after,.row:before,.row:after,.form-horizontal .form-group:before,.form-horizontal .form-group:after,.btn-toolbar:before,.btn-toolbar:after,.btn-group-vertical>.btn-group:before,.btn-group-vertical>.btn-group:after,.nav:before,.nav:after,.navbar:before,.navbar:after,.navbar-header:before,.navbar-header:after,.navbar-collapse:before,.navbar-collapse:after,.pager:before,.pager:after,.panel-body:before,.panel-body:after,.modal-footer:before,.modal-footer:after{content:" ";display:table}.clearfix:after,.container:after,.container-fluid:after,.row:after,.form-horizontal .form-group:after,.btn-toolbar:after,.btn-group-vertical>.btn-group:after,.nav:after,.navbar:after,.navbar-header:after,.navbar-collapse:after,.pager:after,.panel-body:after,.modal-footer:after{clear:both}.center-block{display:block;margin-left:auto;margin-right:auto}.pull-right{float:right!important}.pull-left{float:left!important}.hide{display:none!important}.show{display:block!important}.invisible{visibility:hidden}.text-hide{font:0/0 a;color:transparent;text-shadow:none;background-color:transparent;border:0}.hidden{display:none!important;visibility:hidden!important}.affix{position:fixed}@-ms-viewport{width:device-width}.visible-xs,tr.visible-xs,th.visible-xs,td.visible-xs{display:none!important}@media (max-width:767px){.visible-xs{display:block!important}table.visible-xs{display:table}tr.visible-xs{display:table-row!important}th.visible-xs,td.visible-xs{display:table-cell!important}}.visible-sm,tr.visible-sm,th.visible-sm,td.visible-sm{display:none!important}@media (min-width:768px) and (max-width:991px){.visible-sm{display:block!important}table.visible-sm{display:table}tr.visible-sm{display:table-row!important}th.visible-sm,td.visible-sm{display:table-cell!important}}.visible-md,tr.visible-md,th.visible-md,td.visible-md{display:none!important}@media (min-width:992px) and (max-width:1199px){.visible-md{display:block!important}table.visible-md{display:table}tr.visible-md{display:table-row!important}th.visible-md,td.visible-md{display:table-cell!important}}.visible-lg,tr.visible-lg,th.visible-lg,td.visible-lg{display:none!important}@media (min-width:1200px){.visible-lg{display:block!important}table.visible-lg{display:table}tr.visible-lg{display:table-row!important}th.visible-lg,td.visible-lg{display:table-cell!important}}@media (max-width:767px){.hidden-xs,tr.hidden-xs,th.hidden-xs,td.hidden-xs{display:none!important}}@media (min-width:768px) and (max-width:991px){.hidden-sm,tr.hidden-sm,th.hidden-sm,td.hidden-sm{display:none!important}}@media (min-width:992px) and (max-width:1199px){.hidden-md,tr.hidden-md,th.hidden-md,td.hidden-md{display:none!important}}@media (min-width:1200px){.hidden-lg,tr.hidden-lg,th.hidden-lg,td.hidden-lg{display:none!important}}.visible-print,tr.visible-print,th.visible-print,td.visible-print{display:none!important}@media print{.visible-print{display:block!important}table.visible-print{display:table}tr.visible-print{display:table-row!important}th.visible-print,td.visible-print{display:table-cell!important}}@media print{.hidden-print,tr.hidden-print,th.hidden-print,td.hidden-print{display:none!important}} \ No newline at end of file diff --git a/software/openvisualizer/bin/openVisualizerApp/web_files/static/css/d3.css b/software/openvisualizer/bin/openVisualizerApp/web_files/static/css/d3.css new file mode 100644 index 000000000..6c8a3ba1d --- /dev/null +++ b/software/openvisualizer/bin/openVisualizerApp/web_files/static/css/d3.css @@ -0,0 +1,29 @@ +svg { + background-color: #c0c0c0; + border: 0px solid black; + overflow: hidden; +} + +.node rect { + stroke-width: 2px; + stroke: #fff; + fill: #fff; +} + +#node-CLOSED rect { + fill: #fff; +} + +#node-ESTAB rect { + fill: #fff; +} + +.edgeLabel rect { + fill: #fff; +} + +.edgePath path { + stroke: #fff; + stroke-width: 2px; + fill: none; +} \ No newline at end of file diff --git a/software/openvisualizer/bin/openVisualizerApp/web_files/static/css/openvisualizer.css b/software/openvisualizer/bin/openVisualizerApp/web_files/static/css/openvisualizer.css new file mode 100755 index 000000000..9ef3141fd --- /dev/null +++ b/software/openvisualizer/bin/openVisualizerApp/web_files/static/css/openvisualizer.css @@ -0,0 +1,223 @@ +/* Global Styles */ + +body { + padding-top: 121px; + background-color: #f8f8f8; +} + +@media(min-width:768px) { + body { + padding-top: 11px; + } +} + +/* Wrappers */ + +#wrapper { + width: 100%; +} + +#page-wrapper { + padding: 0 15px; + min-height: 568px; + background-color: #fff; +} + +@media(min-width:768px) { + #page-wrapper { + position: inherit; + margin: 0 0 0 185px; + padding: 0 30px; + min-height: 1300px; + } +} + +/* Navigation */ + +.navbar-top-links li { + display: inline-block; +} + +.navbar-top-links li:last-child { + margin-right: 15px; +} + +.navbar-top-links li a { + padding: 15px; + min-height: 50px; +} + +.navbar-top-links .dropdown-menu li { + display: block; +} + +.navbar-top-links .dropdown-menu li:last-child { + margin-right: 0; +} + +.navbar-top-links .dropdown-menu li a { + padding: 3px 20px; + min-height: 0; +} + +.navbar-top-links .dropdown-menu li a div { + white-space: normal; +} + +.navbar-top-links .dropdown-messages, +.navbar-top-links .dropdown-tasks, +.navbar-top-links .dropdown-alerts { + width: 310px; + min-width: 0; +} + +.navbar-top-links .dropdown-messages { + margin-left: 5px; +} + +.navbar-top-links .dropdown-tasks { + margin-left: -59px; +} + +.navbar-top-links .dropdown-alerts { + margin-left: -123px; +} + +.navbar-top-links .dropdown-user { + right: 0; + left: auto; +} + +/* Sidebar Menu Styles */ + +.navbar-static-side ul li { + border-bottom: 1px solid #e7e7e7; +} + +.sidebar-search { + padding: 15px; +} + +.arrow { + float: right; +} + +.fa.arrow:before { + content: "\f104"; +} + +.active > a > .fa.arrow:before { + content: "\f107"; +} + +.nav-second-level li, +.nav-third-level li { + border-bottom: none !important; +} + +.nav-second-level li a { + padding-left: 37px; +} + +.nav-third-level li a { + padding-left: 52px; +} + +@media(min-width:768px) { + .navbar-static-side { + z-index: 1; + position: absolute; + width: 185px; + } + + .navbar-top-links .dropdown-messages, + .navbar-top-links .dropdown-tasks, + .navbar-top-links .dropdown-alerts { + margin-left: auto; + } +} + +@media(max-height:600px) and (max-width:767px) { + .sidebar-collapse { + max-height: 300px; + overflow-y: scroll; + } +} + +@media(max-height:400px) and (max-width:767px) { + .sidebar-collapse { + max-height: 200px; + overflow-y: scroll; + } +} + +/* Buttons */ + +.btn-outline { + color: inherit; + background-color: transparent; + transition: all .5s; +} + +.btn-primary.btn-outline { + color: #428bca; +} + +.btn-success.btn-outline { + color: #5cb85c; +} + +.btn-info.btn-outline { + color: #5bc0de; +} + +.btn-warning.btn-outline { + color: #f0ad4e; +} + +.btn-danger.btn-outline { + color: #d9534f; +} + +.btn-primary.btn-outline:hover, +.btn-success.btn-outline:hover, +.btn-info.btn-outline:hover, +.btn-warning.btn-outline:hover, +.btn-danger.btn-outline:hover { + color: #fff; +} + +/* Logo */ + +#logo { + border-bottom: 3px solid #e7e7e7; +} + +.logo-img { + padding: 12px 42px; +} + +/* Override */ + +a { + color: #3070a7; +} + +a :hover { + color: #033f79; +} + +.active { + background-color: white; +} + +.navbar { + min-height: 11px !important; +} + +.ovVersion { + color: #c0c0c0; + position: absolute; + left: 50%; + transform: translate(-50%, 0%); +} \ No newline at end of file diff --git a/software/openvisualizer/bin/openVisualizerApp/web_files/static/font-awesome/css/font-awesome.css b/software/openvisualizer/bin/openVisualizerApp/web_files/static/font-awesome/css/font-awesome.css new file mode 100755 index 000000000..048cff973 --- /dev/null +++ b/software/openvisualizer/bin/openVisualizerApp/web_files/static/font-awesome/css/font-awesome.css @@ -0,0 +1,1338 @@ +/*! + * Font Awesome 4.0.3 by @davegandy - http://fontawesome.io - @fontawesome + * License - http://fontawesome.io/license (Font: SIL OFL 1.1, CSS: MIT License) + */ +/* FONT PATH + * -------------------------- */ +@font-face { + font-family: 'FontAwesome'; + src: url('../fonts/fontawesome-webfont.eot?v=4.0.3'); + src: url('../fonts/fontawesome-webfont.eot?#iefix&v=4.0.3') format('embedded-opentype'), url('../fonts/fontawesome-webfont.woff?v=4.0.3') format('woff'), url('../fonts/fontawesome-webfont.ttf?v=4.0.3') format('truetype'), url('../fonts/fontawesome-webfont.svg?v=4.0.3#fontawesomeregular') format('svg'); + font-weight: normal; + font-style: normal; +} +.fa { + display: inline-block; + font-family: FontAwesome; + font-style: normal; + font-weight: normal; + line-height: 1; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} +/* makes the font 33% larger relative to the icon container */ +.fa-lg { + font-size: 1.3333333333333333em; + line-height: 0.75em; + vertical-align: -15%; +} +.fa-2x { + font-size: 2em; +} +.fa-3x { + font-size: 3em; +} +.fa-4x { + font-size: 4em; +} +.fa-5x { + font-size: 5em; +} +.fa-fw { + width: 1.2857142857142858em; + text-align: center; +} +.fa-ul { + padding-left: 0; + margin-left: 2.142857142857143em; + list-style-type: none; +} +.fa-ul > li { + position: relative; +} +.fa-li { + position: absolute; + left: -2.142857142857143em; + width: 2.142857142857143em; + top: 0.14285714285714285em; + text-align: center; +} +.fa-li.fa-lg { + left: -1.8571428571428572em; +} +.fa-border { + padding: .2em .25em .15em; + border: solid 0.08em #eeeeee; + border-radius: .1em; +} +.pull-right { + float: right; +} +.pull-left { + float: left; +} +.fa.pull-left { + margin-right: .3em; +} +.fa.pull-right { + margin-left: .3em; +} +.fa-spin { + -webkit-animation: spin 2s infinite linear; + -moz-animation: spin 2s infinite linear; + -o-animation: spin 2s infinite linear; + animation: spin 2s infinite linear; +} +@-moz-keyframes spin { + 0% { + -moz-transform: rotate(0deg); + } + 100% { + -moz-transform: rotate(359deg); + } +} +@-webkit-keyframes spin { + 0% { + -webkit-transform: rotate(0deg); + } + 100% { + -webkit-transform: rotate(359deg); + } +} +@-o-keyframes spin { + 0% { + -o-transform: rotate(0deg); + } + 100% { + -o-transform: rotate(359deg); + } +} +@-ms-keyframes spin { + 0% { + -ms-transform: rotate(0deg); + } + 100% { + -ms-transform: rotate(359deg); + } +} +@keyframes spin { + 0% { + transform: rotate(0deg); + } + 100% { + transform: rotate(359deg); + } +} +.fa-rotate-90 { + filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=1); + -webkit-transform: rotate(90deg); + -moz-transform: rotate(90deg); + -ms-transform: rotate(90deg); + -o-transform: rotate(90deg); + transform: rotate(90deg); +} +.fa-rotate-180 { + filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=2); + -webkit-transform: rotate(180deg); + -moz-transform: rotate(180deg); + -ms-transform: rotate(180deg); + -o-transform: rotate(180deg); + transform: rotate(180deg); +} +.fa-rotate-270 { + filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=3); + -webkit-transform: rotate(270deg); + -moz-transform: rotate(270deg); + -ms-transform: rotate(270deg); + -o-transform: rotate(270deg); + transform: rotate(270deg); +} +.fa-flip-horizontal { + filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=0, mirror=1); + -webkit-transform: scale(-1, 1); + -moz-transform: scale(-1, 1); + -ms-transform: scale(-1, 1); + -o-transform: scale(-1, 1); + transform: scale(-1, 1); +} +.fa-flip-vertical { + filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=2, mirror=1); + -webkit-transform: scale(1, -1); + -moz-transform: scale(1, -1); + -ms-transform: scale(1, -1); + -o-transform: scale(1, -1); + transform: scale(1, -1); +} +.fa-stack { + position: relative; + display: inline-block; + width: 2em; + height: 2em; + line-height: 2em; + vertical-align: middle; +} +.fa-stack-1x, +.fa-stack-2x { + position: absolute; + left: 0; + width: 100%; + text-align: center; +} +.fa-stack-1x { + line-height: inherit; +} +.fa-stack-2x { + font-size: 2em; +} +.fa-inverse { + color: #ffffff; +} +/* Font Awesome uses the Unicode Private Use Area (PUA) to ensure screen + readers do not read off random characters that represent icons */ +.fa-glass:before { + content: "\f000"; +} +.fa-music:before { + content: "\f001"; +} +.fa-search:before { + content: "\f002"; +} +.fa-envelope-o:before { + content: "\f003"; +} +.fa-heart:before { + content: "\f004"; +} +.fa-star:before { + content: "\f005"; +} +.fa-star-o:before { + content: "\f006"; +} +.fa-user:before { + content: "\f007"; +} +.fa-film:before { + content: "\f008"; +} +.fa-th-large:before { + content: "\f009"; +} +.fa-th:before { + content: "\f00a"; +} +.fa-th-list:before { + content: "\f00b"; +} +.fa-check:before { + content: "\f00c"; +} +.fa-times:before { + content: "\f00d"; +} +.fa-search-plus:before { + content: "\f00e"; +} +.fa-search-minus:before { + content: "\f010"; +} +.fa-power-off:before { + content: "\f011"; +} +.fa-signal:before { + content: "\f012"; +} +.fa-gear:before, +.fa-cog:before { + content: "\f013"; +} +.fa-trash-o:before { + content: "\f014"; +} +.fa-home:before { + content: "\f015"; +} +.fa-file-o:before { + content: "\f016"; +} +.fa-clock-o:before { + content: "\f017"; +} +.fa-road:before { + content: "\f018"; +} +.fa-download:before { + content: "\f019"; +} +.fa-arrow-circle-o-down:before { + content: "\f01a"; +} +.fa-arrow-circle-o-up:before { + content: "\f01b"; +} +.fa-inbox:before { + content: "\f01c"; +} +.fa-play-circle-o:before { + content: "\f01d"; +} +.fa-rotate-right:before, +.fa-repeat:before { + content: "\f01e"; +} +.fa-refresh:before { + content: "\f021"; +} +.fa-list-alt:before { + content: "\f022"; +} +.fa-lock:before { + content: "\f023"; +} +.fa-flag:before { + content: "\f024"; +} +.fa-headphones:before { + content: "\f025"; +} +.fa-volume-off:before { + content: "\f026"; +} +.fa-volume-down:before { + content: "\f027"; +} +.fa-volume-up:before { + content: "\f028"; +} +.fa-qrcode:before { + content: "\f029"; +} +.fa-barcode:before { + content: "\f02a"; +} +.fa-tag:before { + content: "\f02b"; +} +.fa-tags:before { + content: "\f02c"; +} +.fa-book:before { + content: "\f02d"; +} +.fa-bookmark:before { + content: "\f02e"; +} +.fa-print:before { + content: "\f02f"; +} +.fa-camera:before { + content: "\f030"; +} +.fa-font:before { + content: "\f031"; +} +.fa-bold:before { + content: "\f032"; +} +.fa-italic:before { + content: "\f033"; +} +.fa-text-height:before { + content: "\f034"; +} +.fa-text-width:before { + content: "\f035"; +} +.fa-align-left:before { + content: "\f036"; +} +.fa-align-center:before { + content: "\f037"; +} +.fa-align-right:before { + content: "\f038"; +} +.fa-align-justify:before { + content: "\f039"; +} +.fa-list:before { + content: "\f03a"; +} +.fa-dedent:before, +.fa-outdent:before { + content: "\f03b"; +} +.fa-indent:before { + content: "\f03c"; +} +.fa-video-camera:before { + content: "\f03d"; +} +.fa-picture-o:before { + content: "\f03e"; +} +.fa-pencil:before { + content: "\f040"; +} +.fa-map-marker:before { + content: "\f041"; +} +.fa-adjust:before { + content: "\f042"; +} +.fa-tint:before { + content: "\f043"; +} +.fa-edit:before, +.fa-pencil-square-o:before { + content: "\f044"; +} +.fa-share-square-o:before { + content: "\f045"; +} +.fa-check-square-o:before { + content: "\f046"; +} +.fa-arrows:before { + content: "\f047"; +} +.fa-step-backward:before { + content: "\f048"; +} +.fa-fast-backward:before { + content: "\f049"; +} +.fa-backward:before { + content: "\f04a"; +} +.fa-play:before { + content: "\f04b"; +} +.fa-pause:before { + content: "\f04c"; +} +.fa-stop:before { + content: "\f04d"; +} +.fa-forward:before { + content: "\f04e"; +} +.fa-fast-forward:before { + content: "\f050"; +} +.fa-step-forward:before { + content: "\f051"; +} +.fa-eject:before { + content: "\f052"; +} +.fa-chevron-left:before { + content: "\f053"; +} +.fa-chevron-right:before { + content: "\f054"; +} +.fa-plus-circle:before { + content: "\f055"; +} +.fa-minus-circle:before { + content: "\f056"; +} +.fa-times-circle:before { + content: "\f057"; +} +.fa-check-circle:before { + content: "\f058"; +} +.fa-question-circle:before { + content: "\f059"; +} +.fa-info-circle:before { + content: "\f05a"; +} +.fa-crosshairs:before { + content: "\f05b"; +} +.fa-times-circle-o:before { + content: "\f05c"; +} +.fa-check-circle-o:before { + content: "\f05d"; +} +.fa-ban:before { + content: "\f05e"; +} +.fa-arrow-left:before { + content: "\f060"; +} +.fa-arrow-right:before { + content: "\f061"; +} +.fa-arrow-up:before { + content: "\f062"; +} +.fa-arrow-down:before { + content: "\f063"; +} +.fa-mail-forward:before, +.fa-share:before { + content: "\f064"; +} +.fa-expand:before { + content: "\f065"; +} +.fa-compress:before { + content: "\f066"; +} +.fa-plus:before { + content: "\f067"; +} +.fa-minus:before { + content: "\f068"; +} +.fa-asterisk:before { + content: "\f069"; +} +.fa-exclamation-circle:before { + content: "\f06a"; +} +.fa-gift:before { + content: "\f06b"; +} +.fa-leaf:before { + content: "\f06c"; +} +.fa-fire:before { + content: "\f06d"; +} +.fa-eye:before { + content: "\f06e"; +} +.fa-eye-slash:before { + content: "\f070"; +} +.fa-warning:before, +.fa-exclamation-triangle:before { + content: "\f071"; +} +.fa-plane:before { + content: "\f072"; +} +.fa-calendar:before { + content: "\f073"; +} +.fa-random:before { + content: "\f074"; +} +.fa-comment:before { + content: "\f075"; +} +.fa-magnet:before { + content: "\f076"; +} +.fa-chevron-up:before { + content: "\f077"; +} +.fa-chevron-down:before { + content: "\f078"; +} +.fa-retweet:before { + content: "\f079"; +} +.fa-shopping-cart:before { + content: "\f07a"; +} +.fa-folder:before { + content: "\f07b"; +} +.fa-folder-open:before { + content: "\f07c"; +} +.fa-arrows-v:before { + content: "\f07d"; +} +.fa-arrows-h:before { + content: "\f07e"; +} +.fa-bar-chart-o:before { + content: "\f080"; +} +.fa-twitter-square:before { + content: "\f081"; +} +.fa-facebook-square:before { + content: "\f082"; +} +.fa-camera-retro:before { + content: "\f083"; +} +.fa-key:before { + content: "\f084"; +} +.fa-gears:before, +.fa-cogs:before { + content: "\f085"; +} +.fa-comments:before { + content: "\f086"; +} +.fa-thumbs-o-up:before { + content: "\f087"; +} +.fa-thumbs-o-down:before { + content: "\f088"; +} +.fa-star-half:before { + content: "\f089"; +} +.fa-heart-o:before { + content: "\f08a"; +} +.fa-sign-out:before { + content: "\f08b"; +} +.fa-linkedin-square:before { + content: "\f08c"; +} +.fa-thumb-tack:before { + content: "\f08d"; +} +.fa-external-link:before { + content: "\f08e"; +} +.fa-sign-in:before { + content: "\f090"; +} +.fa-trophy:before { + content: "\f091"; +} +.fa-github-square:before { + content: "\f092"; +} +.fa-upload:before { + content: "\f093"; +} +.fa-lemon-o:before { + content: "\f094"; +} +.fa-phone:before { + content: "\f095"; +} +.fa-square-o:before { + content: "\f096"; +} +.fa-bookmark-o:before { + content: "\f097"; +} +.fa-phone-square:before { + content: "\f098"; +} +.fa-twitter:before { + content: "\f099"; +} +.fa-facebook:before { + content: "\f09a"; +} +.fa-github:before { + content: "\f09b"; +} +.fa-unlock:before { + content: "\f09c"; +} +.fa-credit-card:before { + content: "\f09d"; +} +.fa-rss:before { + content: "\f09e"; +} +.fa-hdd-o:before { + content: "\f0a0"; +} +.fa-bullhorn:before { + content: "\f0a1"; +} +.fa-bell:before { + content: "\f0f3"; +} +.fa-certificate:before { + content: "\f0a3"; +} +.fa-hand-o-right:before { + content: "\f0a4"; +} +.fa-hand-o-left:before { + content: "\f0a5"; +} +.fa-hand-o-up:before { + content: "\f0a6"; +} +.fa-hand-o-down:before { + content: "\f0a7"; +} +.fa-arrow-circle-left:before { + content: "\f0a8"; +} +.fa-arrow-circle-right:before { + content: "\f0a9"; +} +.fa-arrow-circle-up:before { + content: "\f0aa"; +} +.fa-arrow-circle-down:before { + content: "\f0ab"; +} +.fa-globe:before { + content: "\f0ac"; +} +.fa-wrench:before { + content: "\f0ad"; +} +.fa-tasks:before { + content: "\f0ae"; +} +.fa-filter:before { + content: "\f0b0"; +} +.fa-briefcase:before { + content: "\f0b1"; +} +.fa-arrows-alt:before { + content: "\f0b2"; +} +.fa-group:before, +.fa-users:before { + content: "\f0c0"; +} +.fa-chain:before, +.fa-link:before { + content: "\f0c1"; +} +.fa-cloud:before { + content: "\f0c2"; +} +.fa-flask:before { + content: "\f0c3"; +} +.fa-cut:before, +.fa-scissors:before { + content: "\f0c4"; +} +.fa-copy:before, +.fa-files-o:before { + content: "\f0c5"; +} +.fa-paperclip:before { + content: "\f0c6"; +} +.fa-save:before, +.fa-floppy-o:before { + content: "\f0c7"; +} +.fa-square:before { + content: "\f0c8"; +} +.fa-bars:before { + content: "\f0c9"; +} +.fa-list-ul:before { + content: "\f0ca"; +} +.fa-list-ol:before { + content: "\f0cb"; +} +.fa-strikethrough:before { + content: "\f0cc"; +} +.fa-underline:before { + content: "\f0cd"; +} +.fa-table:before { + content: "\f0ce"; +} +.fa-magic:before { + content: "\f0d0"; +} +.fa-truck:before { + content: "\f0d1"; +} +.fa-pinterest:before { + content: "\f0d2"; +} +.fa-pinterest-square:before { + content: "\f0d3"; +} +.fa-google-plus-square:before { + content: "\f0d4"; +} +.fa-google-plus:before { + content: "\f0d5"; +} +.fa-money:before { + content: "\f0d6"; +} +.fa-caret-down:before { + content: "\f0d7"; +} +.fa-caret-up:before { + content: "\f0d8"; +} +.fa-caret-left:before { + content: "\f0d9"; +} +.fa-caret-right:before { + content: "\f0da"; +} +.fa-columns:before { + content: "\f0db"; +} +.fa-unsorted:before, +.fa-sort:before { + content: "\f0dc"; +} +.fa-sort-down:before, +.fa-sort-asc:before { + content: "\f0dd"; +} +.fa-sort-up:before, +.fa-sort-desc:before { + content: "\f0de"; +} +.fa-envelope:before { + content: "\f0e0"; +} +.fa-linkedin:before { + content: "\f0e1"; +} +.fa-rotate-left:before, +.fa-undo:before { + content: "\f0e2"; +} +.fa-legal:before, +.fa-gavel:before { + content: "\f0e3"; +} +.fa-dashboard:before, +.fa-tachometer:before { + content: "\f0e4"; +} +.fa-comment-o:before { + content: "\f0e5"; +} +.fa-comments-o:before { + content: "\f0e6"; +} +.fa-flash:before, +.fa-bolt:before { + content: "\f0e7"; +} +.fa-sitemap:before { + content: "\f0e8"; +} +.fa-umbrella:before { + content: "\f0e9"; +} +.fa-paste:before, +.fa-clipboard:before { + content: "\f0ea"; +} +.fa-lightbulb-o:before { + content: "\f0eb"; +} +.fa-exchange:before { + content: "\f0ec"; +} +.fa-cloud-download:before { + content: "\f0ed"; +} +.fa-cloud-upload:before { + content: "\f0ee"; +} +.fa-user-md:before { + content: "\f0f0"; +} +.fa-stethoscope:before { + content: "\f0f1"; +} +.fa-suitcase:before { + content: "\f0f2"; +} +.fa-bell-o:before { + content: "\f0a2"; +} +.fa-coffee:before { + content: "\f0f4"; +} +.fa-cutlery:before { + content: "\f0f5"; +} +.fa-file-text-o:before { + content: "\f0f6"; +} +.fa-building-o:before { + content: "\f0f7"; +} +.fa-hospital-o:before { + content: "\f0f8"; +} +.fa-ambulance:before { + content: "\f0f9"; +} +.fa-medkit:before { + content: "\f0fa"; +} +.fa-fighter-jet:before { + content: "\f0fb"; +} +.fa-beer:before { + content: "\f0fc"; +} +.fa-h-square:before { + content: "\f0fd"; +} +.fa-plus-square:before { + content: "\f0fe"; +} +.fa-angle-double-left:before { + content: "\f100"; +} +.fa-angle-double-right:before { + content: "\f101"; +} +.fa-angle-double-up:before { + content: "\f102"; +} +.fa-angle-double-down:before { + content: "\f103"; +} +.fa-angle-left:before { + content: "\f104"; +} +.fa-angle-right:before { + content: "\f105"; +} +.fa-angle-up:before { + content: "\f106"; +} +.fa-angle-down:before { + content: "\f107"; +} +.fa-desktop:before { + content: "\f108"; +} +.fa-laptop:before { + content: "\f109"; +} +.fa-tablet:before { + content: "\f10a"; +} +.fa-mobile-phone:before, +.fa-mobile:before { + content: "\f10b"; +} +.fa-circle-o:before { + content: "\f10c"; +} +.fa-quote-left:before { + content: "\f10d"; +} +.fa-quote-right:before { + content: "\f10e"; +} +.fa-spinner:before { + content: "\f110"; +} +.fa-circle:before { + content: "\f111"; +} +.fa-mail-reply:before, +.fa-reply:before { + content: "\f112"; +} +.fa-github-alt:before { + content: "\f113"; +} +.fa-folder-o:before { + content: "\f114"; +} +.fa-folder-open-o:before { + content: "\f115"; +} +.fa-smile-o:before { + content: "\f118"; +} +.fa-frown-o:before { + content: "\f119"; +} +.fa-meh-o:before { + content: "\f11a"; +} +.fa-gamepad:before { + content: "\f11b"; +} +.fa-keyboard-o:before { + content: "\f11c"; +} +.fa-flag-o:before { + content: "\f11d"; +} +.fa-flag-checkered:before { + content: "\f11e"; +} +.fa-terminal:before { + content: "\f120"; +} +.fa-code:before { + content: "\f121"; +} +.fa-reply-all:before { + content: "\f122"; +} +.fa-mail-reply-all:before { + content: "\f122"; +} +.fa-star-half-empty:before, +.fa-star-half-full:before, +.fa-star-half-o:before { + content: "\f123"; +} +.fa-location-arrow:before { + content: "\f124"; +} +.fa-crop:before { + content: "\f125"; +} +.fa-code-fork:before { + content: "\f126"; +} +.fa-unlink:before, +.fa-chain-broken:before { + content: "\f127"; +} +.fa-question:before { + content: "\f128"; +} +.fa-info:before { + content: "\f129"; +} +.fa-exclamation:before { + content: "\f12a"; +} +.fa-superscript:before { + content: "\f12b"; +} +.fa-subscript:before { + content: "\f12c"; +} +.fa-eraser:before { + content: "\f12d"; +} +.fa-puzzle-piece:before { + content: "\f12e"; +} +.fa-microphone:before { + content: "\f130"; +} +.fa-microphone-slash:before { + content: "\f131"; +} +.fa-shield:before { + content: "\f132"; +} +.fa-calendar-o:before { + content: "\f133"; +} +.fa-fire-extinguisher:before { + content: "\f134"; +} +.fa-rocket:before { + content: "\f135"; +} +.fa-maxcdn:before { + content: "\f136"; +} +.fa-chevron-circle-left:before { + content: "\f137"; +} +.fa-chevron-circle-right:before { + content: "\f138"; +} +.fa-chevron-circle-up:before { + content: "\f139"; +} +.fa-chevron-circle-down:before { + content: "\f13a"; +} +.fa-html5:before { + content: "\f13b"; +} +.fa-css3:before { + content: "\f13c"; +} +.fa-anchor:before { + content: "\f13d"; +} +.fa-unlock-alt:before { + content: "\f13e"; +} +.fa-bullseye:before { + content: "\f140"; +} +.fa-ellipsis-h:before { + content: "\f141"; +} +.fa-ellipsis-v:before { + content: "\f142"; +} +.fa-rss-square:before { + content: "\f143"; +} +.fa-play-circle:before { + content: "\f144"; +} +.fa-ticket:before { + content: "\f145"; +} +.fa-minus-square:before { + content: "\f146"; +} +.fa-minus-square-o:before { + content: "\f147"; +} +.fa-level-up:before { + content: "\f148"; +} +.fa-level-down:before { + content: "\f149"; +} +.fa-check-square:before { + content: "\f14a"; +} +.fa-pencil-square:before { + content: "\f14b"; +} +.fa-external-link-square:before { + content: "\f14c"; +} +.fa-share-square:before { + content: "\f14d"; +} +.fa-compass:before { + content: "\f14e"; +} +.fa-toggle-down:before, +.fa-caret-square-o-down:before { + content: "\f150"; +} +.fa-toggle-up:before, +.fa-caret-square-o-up:before { + content: "\f151"; +} +.fa-toggle-right:before, +.fa-caret-square-o-right:before { + content: "\f152"; +} +.fa-euro:before, +.fa-eur:before { + content: "\f153"; +} +.fa-gbp:before { + content: "\f154"; +} +.fa-dollar:before, +.fa-usd:before { + content: "\f155"; +} +.fa-rupee:before, +.fa-inr:before { + content: "\f156"; +} +.fa-cny:before, +.fa-rmb:before, +.fa-yen:before, +.fa-jpy:before { + content: "\f157"; +} +.fa-ruble:before, +.fa-rouble:before, +.fa-rub:before { + content: "\f158"; +} +.fa-won:before, +.fa-krw:before { + content: "\f159"; +} +.fa-bitcoin:before, +.fa-btc:before { + content: "\f15a"; +} +.fa-file:before { + content: "\f15b"; +} +.fa-file-text:before { + content: "\f15c"; +} +.fa-sort-alpha-asc:before { + content: "\f15d"; +} +.fa-sort-alpha-desc:before { + content: "\f15e"; +} +.fa-sort-amount-asc:before { + content: "\f160"; +} +.fa-sort-amount-desc:before { + content: "\f161"; +} +.fa-sort-numeric-asc:before { + content: "\f162"; +} +.fa-sort-numeric-desc:before { + content: "\f163"; +} +.fa-thumbs-up:before { + content: "\f164"; +} +.fa-thumbs-down:before { + content: "\f165"; +} +.fa-youtube-square:before { + content: "\f166"; +} +.fa-youtube:before { + content: "\f167"; +} +.fa-xing:before { + content: "\f168"; +} +.fa-xing-square:before { + content: "\f169"; +} +.fa-youtube-play:before { + content: "\f16a"; +} +.fa-dropbox:before { + content: "\f16b"; +} +.fa-stack-overflow:before { + content: "\f16c"; +} +.fa-instagram:before { + content: "\f16d"; +} +.fa-flickr:before { + content: "\f16e"; +} +.fa-adn:before { + content: "\f170"; +} +.fa-bitbucket:before { + content: "\f171"; +} +.fa-bitbucket-square:before { + content: "\f172"; +} +.fa-tumblr:before { + content: "\f173"; +} +.fa-tumblr-square:before { + content: "\f174"; +} +.fa-long-arrow-down:before { + content: "\f175"; +} +.fa-long-arrow-up:before { + content: "\f176"; +} +.fa-long-arrow-left:before { + content: "\f177"; +} +.fa-long-arrow-right:before { + content: "\f178"; +} +.fa-apple:before { + content: "\f179"; +} +.fa-windows:before { + content: "\f17a"; +} +.fa-android:before { + content: "\f17b"; +} +.fa-linux:before { + content: "\f17c"; +} +.fa-dribbble:before { + content: "\f17d"; +} +.fa-skype:before { + content: "\f17e"; +} +.fa-foursquare:before { + content: "\f180"; +} +.fa-trello:before { + content: "\f181"; +} +.fa-female:before { + content: "\f182"; +} +.fa-male:before { + content: "\f183"; +} +.fa-gittip:before { + content: "\f184"; +} +.fa-sun-o:before { + content: "\f185"; +} +.fa-moon-o:before { + content: "\f186"; +} +.fa-archive:before { + content: "\f187"; +} +.fa-bug:before { + content: "\f188"; +} +.fa-vk:before { + content: "\f189"; +} +.fa-weibo:before { + content: "\f18a"; +} +.fa-renren:before { + content: "\f18b"; +} +.fa-pagelines:before { + content: "\f18c"; +} +.fa-stack-exchange:before { + content: "\f18d"; +} +.fa-arrow-circle-o-right:before { + content: "\f18e"; +} +.fa-arrow-circle-o-left:before { + content: "\f190"; +} +.fa-toggle-left:before, +.fa-caret-square-o-left:before { + content: "\f191"; +} +.fa-dot-circle-o:before { + content: "\f192"; +} +.fa-wheelchair:before { + content: "\f193"; +} +.fa-vimeo-square:before { + content: "\f194"; +} +.fa-turkish-lira:before, +.fa-try:before { + content: "\f195"; +} +.fa-plus-square-o:before { + content: "\f196"; +} diff --git a/software/openvisualizer/bin/openVisualizerApp/web_files/static/font-awesome/css/font-awesome.min.css b/software/openvisualizer/bin/openVisualizerApp/web_files/static/font-awesome/css/font-awesome.min.css new file mode 100755 index 000000000..449d6ac55 --- /dev/null +++ b/software/openvisualizer/bin/openVisualizerApp/web_files/static/font-awesome/css/font-awesome.min.css @@ -0,0 +1,4 @@ +/*! + * Font Awesome 4.0.3 by @davegandy - http://fontawesome.io - @fontawesome + * License - http://fontawesome.io/license (Font: SIL OFL 1.1, CSS: MIT License) + */@font-face{font-family:'FontAwesome';src:url('../fonts/fontawesome-webfont.eot?v=4.0.3');src:url('../fonts/fontawesome-webfont.eot?#iefix&v=4.0.3') format('embedded-opentype'),url('../fonts/fontawesome-webfont.woff?v=4.0.3') format('woff'),url('../fonts/fontawesome-webfont.ttf?v=4.0.3') format('truetype'),url('../fonts/fontawesome-webfont.svg?v=4.0.3#fontawesomeregular') format('svg');font-weight:normal;font-style:normal}.fa{display:inline-block;font-family:FontAwesome;font-style:normal;font-weight:normal;line-height:1;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.fa-lg{font-size:1.3333333333333333em;line-height:.75em;vertical-align:-15%}.fa-2x{font-size:2em}.fa-3x{font-size:3em}.fa-4x{font-size:4em}.fa-5x{font-size:5em}.fa-fw{width:1.2857142857142858em;text-align:center}.fa-ul{padding-left:0;margin-left:2.142857142857143em;list-style-type:none}.fa-ul>li{position:relative}.fa-li{position:absolute;left:-2.142857142857143em;width:2.142857142857143em;top:.14285714285714285em;text-align:center}.fa-li.fa-lg{left:-1.8571428571428572em}.fa-border{padding:.2em .25em .15em;border:solid .08em #eee;border-radius:.1em}.pull-right{float:right}.pull-left{float:left}.fa.pull-left{margin-right:.3em}.fa.pull-right{margin-left:.3em}.fa-spin{-webkit-animation:spin 2s infinite linear;-moz-animation:spin 2s infinite linear;-o-animation:spin 2s infinite linear;animation:spin 2s infinite linear}@-moz-keyframes spin{0%{-moz-transform:rotate(0deg)}100%{-moz-transform:rotate(359deg)}}@-webkit-keyframes spin{0%{-webkit-transform:rotate(0deg)}100%{-webkit-transform:rotate(359deg)}}@-o-keyframes spin{0%{-o-transform:rotate(0deg)}100%{-o-transform:rotate(359deg)}}@-ms-keyframes spin{0%{-ms-transform:rotate(0deg)}100%{-ms-transform:rotate(359deg)}}@keyframes spin{0%{transform:rotate(0deg)}100%{transform:rotate(359deg)}}.fa-rotate-90{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=1);-webkit-transform:rotate(90deg);-moz-transform:rotate(90deg);-ms-transform:rotate(90deg);-o-transform:rotate(90deg);transform:rotate(90deg)}.fa-rotate-180{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=2);-webkit-transform:rotate(180deg);-moz-transform:rotate(180deg);-ms-transform:rotate(180deg);-o-transform:rotate(180deg);transform:rotate(180deg)}.fa-rotate-270{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=3);-webkit-transform:rotate(270deg);-moz-transform:rotate(270deg);-ms-transform:rotate(270deg);-o-transform:rotate(270deg);transform:rotate(270deg)}.fa-flip-horizontal{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=0,mirror=1);-webkit-transform:scale(-1,1);-moz-transform:scale(-1,1);-ms-transform:scale(-1,1);-o-transform:scale(-1,1);transform:scale(-1,1)}.fa-flip-vertical{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=2,mirror=1);-webkit-transform:scale(1,-1);-moz-transform:scale(1,-1);-ms-transform:scale(1,-1);-o-transform:scale(1,-1);transform:scale(1,-1)}.fa-stack{position:relative;display:inline-block;width:2em;height:2em;line-height:2em;vertical-align:middle}.fa-stack-1x,.fa-stack-2x{position:absolute;left:0;width:100%;text-align:center}.fa-stack-1x{line-height:inherit}.fa-stack-2x{font-size:2em}.fa-inverse{color:#fff}.fa-glass:before{content:"\f000"}.fa-music:before{content:"\f001"}.fa-search:before{content:"\f002"}.fa-envelope-o:before{content:"\f003"}.fa-heart:before{content:"\f004"}.fa-star:before{content:"\f005"}.fa-star-o:before{content:"\f006"}.fa-user:before{content:"\f007"}.fa-film:before{content:"\f008"}.fa-th-large:before{content:"\f009"}.fa-th:before{content:"\f00a"}.fa-th-list:before{content:"\f00b"}.fa-check:before{content:"\f00c"}.fa-times:before{content:"\f00d"}.fa-search-plus:before{content:"\f00e"}.fa-search-minus:before{content:"\f010"}.fa-power-off:before{content:"\f011"}.fa-signal:before{content:"\f012"}.fa-gear:before,.fa-cog:before{content:"\f013"}.fa-trash-o:before{content:"\f014"}.fa-home:before{content:"\f015"}.fa-file-o:before{content:"\f016"}.fa-clock-o:before{content:"\f017"}.fa-road:before{content:"\f018"}.fa-download:before{content:"\f019"}.fa-arrow-circle-o-down:before{content:"\f01a"}.fa-arrow-circle-o-up:before{content:"\f01b"}.fa-inbox:before{content:"\f01c"}.fa-play-circle-o:before{content:"\f01d"}.fa-rotate-right:before,.fa-repeat:before{content:"\f01e"}.fa-refresh:before{content:"\f021"}.fa-list-alt:before{content:"\f022"}.fa-lock:before{content:"\f023"}.fa-flag:before{content:"\f024"}.fa-headphones:before{content:"\f025"}.fa-volume-off:before{content:"\f026"}.fa-volume-down:before{content:"\f027"}.fa-volume-up:before{content:"\f028"}.fa-qrcode:before{content:"\f029"}.fa-barcode:before{content:"\f02a"}.fa-tag:before{content:"\f02b"}.fa-tags:before{content:"\f02c"}.fa-book:before{content:"\f02d"}.fa-bookmark:before{content:"\f02e"}.fa-print:before{content:"\f02f"}.fa-camera:before{content:"\f030"}.fa-font:before{content:"\f031"}.fa-bold:before{content:"\f032"}.fa-italic:before{content:"\f033"}.fa-text-height:before{content:"\f034"}.fa-text-width:before{content:"\f035"}.fa-align-left:before{content:"\f036"}.fa-align-center:before{content:"\f037"}.fa-align-right:before{content:"\f038"}.fa-align-justify:before{content:"\f039"}.fa-list:before{content:"\f03a"}.fa-dedent:before,.fa-outdent:before{content:"\f03b"}.fa-indent:before{content:"\f03c"}.fa-video-camera:before{content:"\f03d"}.fa-picture-o:before{content:"\f03e"}.fa-pencil:before{content:"\f040"}.fa-map-marker:before{content:"\f041"}.fa-adjust:before{content:"\f042"}.fa-tint:before{content:"\f043"}.fa-edit:before,.fa-pencil-square-o:before{content:"\f044"}.fa-share-square-o:before{content:"\f045"}.fa-check-square-o:before{content:"\f046"}.fa-arrows:before{content:"\f047"}.fa-step-backward:before{content:"\f048"}.fa-fast-backward:before{content:"\f049"}.fa-backward:before{content:"\f04a"}.fa-play:before{content:"\f04b"}.fa-pause:before{content:"\f04c"}.fa-stop:before{content:"\f04d"}.fa-forward:before{content:"\f04e"}.fa-fast-forward:before{content:"\f050"}.fa-step-forward:before{content:"\f051"}.fa-eject:before{content:"\f052"}.fa-chevron-left:before{content:"\f053"}.fa-chevron-right:before{content:"\f054"}.fa-plus-circle:before{content:"\f055"}.fa-minus-circle:before{content:"\f056"}.fa-times-circle:before{content:"\f057"}.fa-check-circle:before{content:"\f058"}.fa-question-circle:before{content:"\f059"}.fa-info-circle:before{content:"\f05a"}.fa-crosshairs:before{content:"\f05b"}.fa-times-circle-o:before{content:"\f05c"}.fa-check-circle-o:before{content:"\f05d"}.fa-ban:before{content:"\f05e"}.fa-arrow-left:before{content:"\f060"}.fa-arrow-right:before{content:"\f061"}.fa-arrow-up:before{content:"\f062"}.fa-arrow-down:before{content:"\f063"}.fa-mail-forward:before,.fa-share:before{content:"\f064"}.fa-expand:before{content:"\f065"}.fa-compress:before{content:"\f066"}.fa-plus:before{content:"\f067"}.fa-minus:before{content:"\f068"}.fa-asterisk:before{content:"\f069"}.fa-exclamation-circle:before{content:"\f06a"}.fa-gift:before{content:"\f06b"}.fa-leaf:before{content:"\f06c"}.fa-fire:before{content:"\f06d"}.fa-eye:before{content:"\f06e"}.fa-eye-slash:before{content:"\f070"}.fa-warning:before,.fa-exclamation-triangle:before{content:"\f071"}.fa-plane:before{content:"\f072"}.fa-calendar:before{content:"\f073"}.fa-random:before{content:"\f074"}.fa-comment:before{content:"\f075"}.fa-magnet:before{content:"\f076"}.fa-chevron-up:before{content:"\f077"}.fa-chevron-down:before{content:"\f078"}.fa-retweet:before{content:"\f079"}.fa-shopping-cart:before{content:"\f07a"}.fa-folder:before{content:"\f07b"}.fa-folder-open:before{content:"\f07c"}.fa-arrows-v:before{content:"\f07d"}.fa-arrows-h:before{content:"\f07e"}.fa-bar-chart-o:before{content:"\f080"}.fa-twitter-square:before{content:"\f081"}.fa-facebook-square:before{content:"\f082"}.fa-camera-retro:before{content:"\f083"}.fa-key:before{content:"\f084"}.fa-gears:before,.fa-cogs:before{content:"\f085"}.fa-comments:before{content:"\f086"}.fa-thumbs-o-up:before{content:"\f087"}.fa-thumbs-o-down:before{content:"\f088"}.fa-star-half:before{content:"\f089"}.fa-heart-o:before{content:"\f08a"}.fa-sign-out:before{content:"\f08b"}.fa-linkedin-square:before{content:"\f08c"}.fa-thumb-tack:before{content:"\f08d"}.fa-external-link:before{content:"\f08e"}.fa-sign-in:before{content:"\f090"}.fa-trophy:before{content:"\f091"}.fa-github-square:before{content:"\f092"}.fa-upload:before{content:"\f093"}.fa-lemon-o:before{content:"\f094"}.fa-phone:before{content:"\f095"}.fa-square-o:before{content:"\f096"}.fa-bookmark-o:before{content:"\f097"}.fa-phone-square:before{content:"\f098"}.fa-twitter:before{content:"\f099"}.fa-facebook:before{content:"\f09a"}.fa-github:before{content:"\f09b"}.fa-unlock:before{content:"\f09c"}.fa-credit-card:before{content:"\f09d"}.fa-rss:before{content:"\f09e"}.fa-hdd-o:before{content:"\f0a0"}.fa-bullhorn:before{content:"\f0a1"}.fa-bell:before{content:"\f0f3"}.fa-certificate:before{content:"\f0a3"}.fa-hand-o-right:before{content:"\f0a4"}.fa-hand-o-left:before{content:"\f0a5"}.fa-hand-o-up:before{content:"\f0a6"}.fa-hand-o-down:before{content:"\f0a7"}.fa-arrow-circle-left:before{content:"\f0a8"}.fa-arrow-circle-right:before{content:"\f0a9"}.fa-arrow-circle-up:before{content:"\f0aa"}.fa-arrow-circle-down:before{content:"\f0ab"}.fa-globe:before{content:"\f0ac"}.fa-wrench:before{content:"\f0ad"}.fa-tasks:before{content:"\f0ae"}.fa-filter:before{content:"\f0b0"}.fa-briefcase:before{content:"\f0b1"}.fa-arrows-alt:before{content:"\f0b2"}.fa-group:before,.fa-users:before{content:"\f0c0"}.fa-chain:before,.fa-link:before{content:"\f0c1"}.fa-cloud:before{content:"\f0c2"}.fa-flask:before{content:"\f0c3"}.fa-cut:before,.fa-scissors:before{content:"\f0c4"}.fa-copy:before,.fa-files-o:before{content:"\f0c5"}.fa-paperclip:before{content:"\f0c6"}.fa-save:before,.fa-floppy-o:before{content:"\f0c7"}.fa-square:before{content:"\f0c8"}.fa-bars:before{content:"\f0c9"}.fa-list-ul:before{content:"\f0ca"}.fa-list-ol:before{content:"\f0cb"}.fa-strikethrough:before{content:"\f0cc"}.fa-underline:before{content:"\f0cd"}.fa-table:before{content:"\f0ce"}.fa-magic:before{content:"\f0d0"}.fa-truck:before{content:"\f0d1"}.fa-pinterest:before{content:"\f0d2"}.fa-pinterest-square:before{content:"\f0d3"}.fa-google-plus-square:before{content:"\f0d4"}.fa-google-plus:before{content:"\f0d5"}.fa-money:before{content:"\f0d6"}.fa-caret-down:before{content:"\f0d7"}.fa-caret-up:before{content:"\f0d8"}.fa-caret-left:before{content:"\f0d9"}.fa-caret-right:before{content:"\f0da"}.fa-columns:before{content:"\f0db"}.fa-unsorted:before,.fa-sort:before{content:"\f0dc"}.fa-sort-down:before,.fa-sort-asc:before{content:"\f0dd"}.fa-sort-up:before,.fa-sort-desc:before{content:"\f0de"}.fa-envelope:before{content:"\f0e0"}.fa-linkedin:before{content:"\f0e1"}.fa-rotate-left:before,.fa-undo:before{content:"\f0e2"}.fa-legal:before,.fa-gavel:before{content:"\f0e3"}.fa-dashboard:before,.fa-tachometer:before{content:"\f0e4"}.fa-comment-o:before{content:"\f0e5"}.fa-comments-o:before{content:"\f0e6"}.fa-flash:before,.fa-bolt:before{content:"\f0e7"}.fa-sitemap:before{content:"\f0e8"}.fa-umbrella:before{content:"\f0e9"}.fa-paste:before,.fa-clipboard:before{content:"\f0ea"}.fa-lightbulb-o:before{content:"\f0eb"}.fa-exchange:before{content:"\f0ec"}.fa-cloud-download:before{content:"\f0ed"}.fa-cloud-upload:before{content:"\f0ee"}.fa-user-md:before{content:"\f0f0"}.fa-stethoscope:before{content:"\f0f1"}.fa-suitcase:before{content:"\f0f2"}.fa-bell-o:before{content:"\f0a2"}.fa-coffee:before{content:"\f0f4"}.fa-cutlery:before{content:"\f0f5"}.fa-file-text-o:before{content:"\f0f6"}.fa-building-o:before{content:"\f0f7"}.fa-hospital-o:before{content:"\f0f8"}.fa-ambulance:before{content:"\f0f9"}.fa-medkit:before{content:"\f0fa"}.fa-fighter-jet:before{content:"\f0fb"}.fa-beer:before{content:"\f0fc"}.fa-h-square:before{content:"\f0fd"}.fa-plus-square:before{content:"\f0fe"}.fa-angle-double-left:before{content:"\f100"}.fa-angle-double-right:before{content:"\f101"}.fa-angle-double-up:before{content:"\f102"}.fa-angle-double-down:before{content:"\f103"}.fa-angle-left:before{content:"\f104"}.fa-angle-right:before{content:"\f105"}.fa-angle-up:before{content:"\f106"}.fa-angle-down:before{content:"\f107"}.fa-desktop:before{content:"\f108"}.fa-laptop:before{content:"\f109"}.fa-tablet:before{content:"\f10a"}.fa-mobile-phone:before,.fa-mobile:before{content:"\f10b"}.fa-circle-o:before{content:"\f10c"}.fa-quote-left:before{content:"\f10d"}.fa-quote-right:before{content:"\f10e"}.fa-spinner:before{content:"\f110"}.fa-circle:before{content:"\f111"}.fa-mail-reply:before,.fa-reply:before{content:"\f112"}.fa-github-alt:before{content:"\f113"}.fa-folder-o:before{content:"\f114"}.fa-folder-open-o:before{content:"\f115"}.fa-smile-o:before{content:"\f118"}.fa-frown-o:before{content:"\f119"}.fa-meh-o:before{content:"\f11a"}.fa-gamepad:before{content:"\f11b"}.fa-keyboard-o:before{content:"\f11c"}.fa-flag-o:before{content:"\f11d"}.fa-flag-checkered:before{content:"\f11e"}.fa-terminal:before{content:"\f120"}.fa-code:before{content:"\f121"}.fa-reply-all:before{content:"\f122"}.fa-mail-reply-all:before{content:"\f122"}.fa-star-half-empty:before,.fa-star-half-full:before,.fa-star-half-o:before{content:"\f123"}.fa-location-arrow:before{content:"\f124"}.fa-crop:before{content:"\f125"}.fa-code-fork:before{content:"\f126"}.fa-unlink:before,.fa-chain-broken:before{content:"\f127"}.fa-question:before{content:"\f128"}.fa-info:before{content:"\f129"}.fa-exclamation:before{content:"\f12a"}.fa-superscript:before{content:"\f12b"}.fa-subscript:before{content:"\f12c"}.fa-eraser:before{content:"\f12d"}.fa-puzzle-piece:before{content:"\f12e"}.fa-microphone:before{content:"\f130"}.fa-microphone-slash:before{content:"\f131"}.fa-shield:before{content:"\f132"}.fa-calendar-o:before{content:"\f133"}.fa-fire-extinguisher:before{content:"\f134"}.fa-rocket:before{content:"\f135"}.fa-maxcdn:before{content:"\f136"}.fa-chevron-circle-left:before{content:"\f137"}.fa-chevron-circle-right:before{content:"\f138"}.fa-chevron-circle-up:before{content:"\f139"}.fa-chevron-circle-down:before{content:"\f13a"}.fa-html5:before{content:"\f13b"}.fa-css3:before{content:"\f13c"}.fa-anchor:before{content:"\f13d"}.fa-unlock-alt:before{content:"\f13e"}.fa-bullseye:before{content:"\f140"}.fa-ellipsis-h:before{content:"\f141"}.fa-ellipsis-v:before{content:"\f142"}.fa-rss-square:before{content:"\f143"}.fa-play-circle:before{content:"\f144"}.fa-ticket:before{content:"\f145"}.fa-minus-square:before{content:"\f146"}.fa-minus-square-o:before{content:"\f147"}.fa-level-up:before{content:"\f148"}.fa-level-down:before{content:"\f149"}.fa-check-square:before{content:"\f14a"}.fa-pencil-square:before{content:"\f14b"}.fa-external-link-square:before{content:"\f14c"}.fa-share-square:before{content:"\f14d"}.fa-compass:before{content:"\f14e"}.fa-toggle-down:before,.fa-caret-square-o-down:before{content:"\f150"}.fa-toggle-up:before,.fa-caret-square-o-up:before{content:"\f151"}.fa-toggle-right:before,.fa-caret-square-o-right:before{content:"\f152"}.fa-euro:before,.fa-eur:before{content:"\f153"}.fa-gbp:before{content:"\f154"}.fa-dollar:before,.fa-usd:before{content:"\f155"}.fa-rupee:before,.fa-inr:before{content:"\f156"}.fa-cny:before,.fa-rmb:before,.fa-yen:before,.fa-jpy:before{content:"\f157"}.fa-ruble:before,.fa-rouble:before,.fa-rub:before{content:"\f158"}.fa-won:before,.fa-krw:before{content:"\f159"}.fa-bitcoin:before,.fa-btc:before{content:"\f15a"}.fa-file:before{content:"\f15b"}.fa-file-text:before{content:"\f15c"}.fa-sort-alpha-asc:before{content:"\f15d"}.fa-sort-alpha-desc:before{content:"\f15e"}.fa-sort-amount-asc:before{content:"\f160"}.fa-sort-amount-desc:before{content:"\f161"}.fa-sort-numeric-asc:before{content:"\f162"}.fa-sort-numeric-desc:before{content:"\f163"}.fa-thumbs-up:before{content:"\f164"}.fa-thumbs-down:before{content:"\f165"}.fa-youtube-square:before{content:"\f166"}.fa-youtube:before{content:"\f167"}.fa-xing:before{content:"\f168"}.fa-xing-square:before{content:"\f169"}.fa-youtube-play:before{content:"\f16a"}.fa-dropbox:before{content:"\f16b"}.fa-stack-overflow:before{content:"\f16c"}.fa-instagram:before{content:"\f16d"}.fa-flickr:before{content:"\f16e"}.fa-adn:before{content:"\f170"}.fa-bitbucket:before{content:"\f171"}.fa-bitbucket-square:before{content:"\f172"}.fa-tumblr:before{content:"\f173"}.fa-tumblr-square:before{content:"\f174"}.fa-long-arrow-down:before{content:"\f175"}.fa-long-arrow-up:before{content:"\f176"}.fa-long-arrow-left:before{content:"\f177"}.fa-long-arrow-right:before{content:"\f178"}.fa-apple:before{content:"\f179"}.fa-windows:before{content:"\f17a"}.fa-android:before{content:"\f17b"}.fa-linux:before{content:"\f17c"}.fa-dribbble:before{content:"\f17d"}.fa-skype:before{content:"\f17e"}.fa-foursquare:before{content:"\f180"}.fa-trello:before{content:"\f181"}.fa-female:before{content:"\f182"}.fa-male:before{content:"\f183"}.fa-gittip:before{content:"\f184"}.fa-sun-o:before{content:"\f185"}.fa-moon-o:before{content:"\f186"}.fa-archive:before{content:"\f187"}.fa-bug:before{content:"\f188"}.fa-vk:before{content:"\f189"}.fa-weibo:before{content:"\f18a"}.fa-renren:before{content:"\f18b"}.fa-pagelines:before{content:"\f18c"}.fa-stack-exchange:before{content:"\f18d"}.fa-arrow-circle-o-right:before{content:"\f18e"}.fa-arrow-circle-o-left:before{content:"\f190"}.fa-toggle-left:before,.fa-caret-square-o-left:before{content:"\f191"}.fa-dot-circle-o:before{content:"\f192"}.fa-wheelchair:before{content:"\f193"}.fa-vimeo-square:before{content:"\f194"}.fa-turkish-lira:before,.fa-try:before{content:"\f195"}.fa-plus-square-o:before{content:"\f196"} \ No newline at end of file diff --git a/software/openvisualizer/bin/openVisualizerApp/web_files/static/font-awesome/fonts/FontAwesome.otf b/software/openvisualizer/bin/openVisualizerApp/web_files/static/font-awesome/fonts/FontAwesome.otf new file mode 100755 index 000000000..8b0f54e47 Binary files /dev/null and b/software/openvisualizer/bin/openVisualizerApp/web_files/static/font-awesome/fonts/FontAwesome.otf differ diff --git a/software/openvisualizer/bin/openVisualizerApp/web_files/static/font-awesome/fonts/fontawesome-webfont.eot b/software/openvisualizer/bin/openVisualizerApp/web_files/static/font-awesome/fonts/fontawesome-webfont.eot new file mode 100755 index 000000000..7c79c6a6b Binary files /dev/null and b/software/openvisualizer/bin/openVisualizerApp/web_files/static/font-awesome/fonts/fontawesome-webfont.eot differ diff --git a/software/openvisualizer/bin/openVisualizerApp/web_files/static/font-awesome/fonts/fontawesome-webfont.svg b/software/openvisualizer/bin/openVisualizerApp/web_files/static/font-awesome/fonts/fontawesome-webfont.svg new file mode 100755 index 000000000..45fdf3383 --- /dev/null +++ b/software/openvisualizer/bin/openVisualizerApp/web_files/static/font-awesome/fonts/fontawesome-webfont.svg @@ -0,0 +1,414 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/software/openvisualizer/bin/openVisualizerApp/web_files/static/font-awesome/fonts/fontawesome-webfont.ttf b/software/openvisualizer/bin/openVisualizerApp/web_files/static/font-awesome/fonts/fontawesome-webfont.ttf new file mode 100755 index 000000000..e89738de5 Binary files /dev/null and b/software/openvisualizer/bin/openVisualizerApp/web_files/static/font-awesome/fonts/fontawesome-webfont.ttf differ diff --git a/software/openvisualizer/bin/openVisualizerApp/web_files/static/font-awesome/fonts/fontawesome-webfont.woff b/software/openvisualizer/bin/openVisualizerApp/web_files/static/font-awesome/fonts/fontawesome-webfont.woff new file mode 100755 index 000000000..8c1748aab Binary files /dev/null and b/software/openvisualizer/bin/openVisualizerApp/web_files/static/font-awesome/fonts/fontawesome-webfont.woff differ diff --git a/software/openvisualizer/bin/openVisualizerApp/web_files/static/images/favicon.ico b/software/openvisualizer/bin/openVisualizerApp/web_files/static/images/favicon.ico new file mode 100644 index 000000000..3c466e4e6 Binary files /dev/null and b/software/openvisualizer/bin/openVisualizerApp/web_files/static/images/favicon.ico differ diff --git a/software/openvisualizer/bin/openVisualizerApp/web_files/static/images/openwsn_logo.png b/software/openvisualizer/bin/openVisualizerApp/web_files/static/images/openwsn_logo.png new file mode 100644 index 000000000..9c4ed6cdd Binary files /dev/null and b/software/openvisualizer/bin/openVisualizerApp/web_files/static/images/openwsn_logo.png differ diff --git a/software/openvisualizer/bin/openVisualizerApp/web_files/static/js/bootstrap.js b/software/openvisualizer/bin/openVisualizerApp/web_files/static/js/bootstrap.js new file mode 100755 index 000000000..39ec4710e --- /dev/null +++ b/software/openvisualizer/bin/openVisualizerApp/web_files/static/js/bootstrap.js @@ -0,0 +1,1951 @@ +/*! + * Bootstrap v3.1.0 (http://getbootstrap.com) + * Copyright 2011-2014 Twitter, Inc. + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) + */ + +if (typeof jQuery === 'undefined') { throw new Error('Bootstrap requires jQuery') } + +/* ======================================================================== + * Bootstrap: transition.js v3.1.0 + * http://getbootstrap.com/javascript/#transitions + * ======================================================================== + * Copyright 2011-2014 Twitter, Inc. + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) + * ======================================================================== */ + + ++function ($) { + 'use strict'; + + // CSS TRANSITION SUPPORT (Shoutout: http://www.modernizr.com/) + // ============================================================ + + function transitionEnd() { + var el = document.createElement('bootstrap') + + var transEndEventNames = { + 'WebkitTransition' : 'webkitTransitionEnd', + 'MozTransition' : 'transitionend', + 'OTransition' : 'oTransitionEnd otransitionend', + 'transition' : 'transitionend' + } + + for (var name in transEndEventNames) { + if (el.style[name] !== undefined) { + return { end: transEndEventNames[name] } + } + } + + return false // explicit for ie8 ( ._.) + } + + // http://blog.alexmaccaw.com/css-transitions + $.fn.emulateTransitionEnd = function (duration) { + var called = false, $el = this + $(this).one($.support.transition.end, function () { called = true }) + var callback = function () { if (!called) $($el).trigger($.support.transition.end) } + setTimeout(callback, duration) + return this + } + + $(function () { + $.support.transition = transitionEnd() + }) + +}(jQuery); + +/* ======================================================================== + * Bootstrap: alert.js v3.1.0 + * http://getbootstrap.com/javascript/#alerts + * ======================================================================== + * Copyright 2011-2014 Twitter, Inc. + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) + * ======================================================================== */ + + ++function ($) { + 'use strict'; + + // ALERT CLASS DEFINITION + // ====================== + + var dismiss = '[data-dismiss="alert"]' + var Alert = function (el) { + $(el).on('click', dismiss, this.close) + } + + Alert.prototype.close = function (e) { + var $this = $(this) + var selector = $this.attr('data-target') + + if (!selector) { + selector = $this.attr('href') + selector = selector && selector.replace(/.*(?=#[^\s]*$)/, '') // strip for ie7 + } + + var $parent = $(selector) + + if (e) e.preventDefault() + + if (!$parent.length) { + $parent = $this.hasClass('alert') ? $this : $this.parent() + } + + $parent.trigger(e = $.Event('close.bs.alert')) + + if (e.isDefaultPrevented()) return + + $parent.removeClass('in') + + function removeElement() { + $parent.trigger('closed.bs.alert').remove() + } + + $.support.transition && $parent.hasClass('fade') ? + $parent + .one($.support.transition.end, removeElement) + .emulateTransitionEnd(150) : + removeElement() + } + + + // ALERT PLUGIN DEFINITION + // ======================= + + var old = $.fn.alert + + $.fn.alert = function (option) { + return this.each(function () { + var $this = $(this) + var data = $this.data('bs.alert') + + if (!data) $this.data('bs.alert', (data = new Alert(this))) + if (typeof option == 'string') data[option].call($this) + }) + } + + $.fn.alert.Constructor = Alert + + + // ALERT NO CONFLICT + // ================= + + $.fn.alert.noConflict = function () { + $.fn.alert = old + return this + } + + + // ALERT DATA-API + // ============== + + $(document).on('click.bs.alert.data-api', dismiss, Alert.prototype.close) + +}(jQuery); + +/* ======================================================================== + * Bootstrap: button.js v3.1.0 + * http://getbootstrap.com/javascript/#buttons + * ======================================================================== + * Copyright 2011-2014 Twitter, Inc. + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) + * ======================================================================== */ + + ++function ($) { + 'use strict'; + + // BUTTON PUBLIC CLASS DEFINITION + // ============================== + + var Button = function (element, options) { + this.$element = $(element) + this.options = $.extend({}, Button.DEFAULTS, options) + this.isLoading = false + } + + Button.DEFAULTS = { + loadingText: 'loading...' + } + + Button.prototype.setState = function (state) { + var d = 'disabled' + var $el = this.$element + var val = $el.is('input') ? 'val' : 'html' + var data = $el.data() + + state = state + 'Text' + + if (!data.resetText) $el.data('resetText', $el[val]()) + + $el[val](data[state] || this.options[state]) + + // push to event loop to allow forms to submit + setTimeout($.proxy(function () { + if (state == 'loadingText') { + this.isLoading = true + $el.addClass(d).attr(d, d) + } else if (this.isLoading) { + this.isLoading = false + $el.removeClass(d).removeAttr(d) + } + }, this), 0) + } + + Button.prototype.toggle = function () { + var changed = true + var $parent = this.$element.closest('[data-toggle="buttons"]') + + if ($parent.length) { + var $input = this.$element.find('input') + if ($input.prop('type') == 'radio') { + if ($input.prop('checked') && this.$element.hasClass('active')) changed = false + else $parent.find('.active').removeClass('active') + } + if (changed) $input.prop('checked', !this.$element.hasClass('active')).trigger('change') + } + + if (changed) this.$element.toggleClass('active') + } + + + // BUTTON PLUGIN DEFINITION + // ======================== + + var old = $.fn.button + + $.fn.button = function (option) { + return this.each(function () { + var $this = $(this) + var data = $this.data('bs.button') + var options = typeof option == 'object' && option + + if (!data) $this.data('bs.button', (data = new Button(this, options))) + + if (option == 'toggle') data.toggle() + else if (option) data.setState(option) + }) + } + + $.fn.button.Constructor = Button + + + // BUTTON NO CONFLICT + // ================== + + $.fn.button.noConflict = function () { + $.fn.button = old + return this + } + + + // BUTTON DATA-API + // =============== + + $(document).on('click.bs.button.data-api', '[data-toggle^=button]', function (e) { + var $btn = $(e.target) + if (!$btn.hasClass('btn')) $btn = $btn.closest('.btn') + $btn.button('toggle') + e.preventDefault() + }) + +}(jQuery); + +/* ======================================================================== + * Bootstrap: carousel.js v3.1.0 + * http://getbootstrap.com/javascript/#carousel + * ======================================================================== + * Copyright 2011-2014 Twitter, Inc. + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) + * ======================================================================== */ + + ++function ($) { + 'use strict'; + + // CAROUSEL CLASS DEFINITION + // ========================= + + var Carousel = function (element, options) { + this.$element = $(element) + this.$indicators = this.$element.find('.carousel-indicators') + this.options = options + this.paused = + this.sliding = + this.interval = + this.$active = + this.$items = null + + this.options.pause == 'hover' && this.$element + .on('mouseenter', $.proxy(this.pause, this)) + .on('mouseleave', $.proxy(this.cycle, this)) + } + + Carousel.DEFAULTS = { + interval: 5000, + pause: 'hover', + wrap: true + } + + Carousel.prototype.cycle = function (e) { + e || (this.paused = false) + + this.interval && clearInterval(this.interval) + + this.options.interval + && !this.paused + && (this.interval = setInterval($.proxy(this.next, this), this.options.interval)) + + return this + } + + Carousel.prototype.getActiveIndex = function () { + this.$active = this.$element.find('.item.active') + this.$items = this.$active.parent().children() + + return this.$items.index(this.$active) + } + + Carousel.prototype.to = function (pos) { + var that = this + var activeIndex = this.getActiveIndex() + + if (pos > (this.$items.length - 1) || pos < 0) return + + if (this.sliding) return this.$element.one('slid.bs.carousel', function () { that.to(pos) }) + if (activeIndex == pos) return this.pause().cycle() + + return this.slide(pos > activeIndex ? 'next' : 'prev', $(this.$items[pos])) + } + + Carousel.prototype.pause = function (e) { + e || (this.paused = true) + + if (this.$element.find('.next, .prev').length && $.support.transition) { + this.$element.trigger($.support.transition.end) + this.cycle(true) + } + + this.interval = clearInterval(this.interval) + + return this + } + + Carousel.prototype.next = function () { + if (this.sliding) return + return this.slide('next') + } + + Carousel.prototype.prev = function () { + if (this.sliding) return + return this.slide('prev') + } + + Carousel.prototype.slide = function (type, next) { + var $active = this.$element.find('.item.active') + var $next = next || $active[type]() + var isCycling = this.interval + var direction = type == 'next' ? 'left' : 'right' + var fallback = type == 'next' ? 'first' : 'last' + var that = this + + if (!$next.length) { + if (!this.options.wrap) return + $next = this.$element.find('.item')[fallback]() + } + + if ($next.hasClass('active')) return this.sliding = false + + var e = $.Event('slide.bs.carousel', { relatedTarget: $next[0], direction: direction }) + this.$element.trigger(e) + if (e.isDefaultPrevented()) return + + this.sliding = true + + isCycling && this.pause() + + if (this.$indicators.length) { + this.$indicators.find('.active').removeClass('active') + this.$element.one('slid.bs.carousel', function () { + var $nextIndicator = $(that.$indicators.children()[that.getActiveIndex()]) + $nextIndicator && $nextIndicator.addClass('active') + }) + } + + if ($.support.transition && this.$element.hasClass('slide')) { + $next.addClass(type) + $next[0].offsetWidth // force reflow + $active.addClass(direction) + $next.addClass(direction) + $active + .one($.support.transition.end, function () { + $next.removeClass([type, direction].join(' ')).addClass('active') + $active.removeClass(['active', direction].join(' ')) + that.sliding = false + setTimeout(function () { that.$element.trigger('slid.bs.carousel') }, 0) + }) + .emulateTransitionEnd($active.css('transition-duration').slice(0, -1) * 1000) + } else { + $active.removeClass('active') + $next.addClass('active') + this.sliding = false + this.$element.trigger('slid.bs.carousel') + } + + isCycling && this.cycle() + + return this + } + + + // CAROUSEL PLUGIN DEFINITION + // ========================== + + var old = $.fn.carousel + + $.fn.carousel = function (option) { + return this.each(function () { + var $this = $(this) + var data = $this.data('bs.carousel') + var options = $.extend({}, Carousel.DEFAULTS, $this.data(), typeof option == 'object' && option) + var action = typeof option == 'string' ? option : options.slide + + if (!data) $this.data('bs.carousel', (data = new Carousel(this, options))) + if (typeof option == 'number') data.to(option) + else if (action) data[action]() + else if (options.interval) data.pause().cycle() + }) + } + + $.fn.carousel.Constructor = Carousel + + + // CAROUSEL NO CONFLICT + // ==================== + + $.fn.carousel.noConflict = function () { + $.fn.carousel = old + return this + } + + + // CAROUSEL DATA-API + // ================= + + $(document).on('click.bs.carousel.data-api', '[data-slide], [data-slide-to]', function (e) { + var $this = $(this), href + var $target = $($this.attr('data-target') || (href = $this.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '')) //strip for ie7 + var options = $.extend({}, $target.data(), $this.data()) + var slideIndex = $this.attr('data-slide-to') + if (slideIndex) options.interval = false + + $target.carousel(options) + + if (slideIndex = $this.attr('data-slide-to')) { + $target.data('bs.carousel').to(slideIndex) + } + + e.preventDefault() + }) + + $(window).on('load', function () { + $('[data-ride="carousel"]').each(function () { + var $carousel = $(this) + $carousel.carousel($carousel.data()) + }) + }) + +}(jQuery); + +/* ======================================================================== + * Bootstrap: collapse.js v3.1.0 + * http://getbootstrap.com/javascript/#collapse + * ======================================================================== + * Copyright 2011-2014 Twitter, Inc. + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) + * ======================================================================== */ + + ++function ($) { + 'use strict'; + + // COLLAPSE PUBLIC CLASS DEFINITION + // ================================ + + var Collapse = function (element, options) { + this.$element = $(element) + this.options = $.extend({}, Collapse.DEFAULTS, options) + this.transitioning = null + + if (this.options.parent) this.$parent = $(this.options.parent) + if (this.options.toggle) this.toggle() + } + + Collapse.DEFAULTS = { + toggle: true + } + + Collapse.prototype.dimension = function () { + var hasWidth = this.$element.hasClass('width') + return hasWidth ? 'width' : 'height' + } + + Collapse.prototype.show = function () { + if (this.transitioning || this.$element.hasClass('in')) return + + var startEvent = $.Event('show.bs.collapse') + this.$element.trigger(startEvent) + if (startEvent.isDefaultPrevented()) return + + var actives = this.$parent && this.$parent.find('> .panel > .in') + + if (actives && actives.length) { + var hasData = actives.data('bs.collapse') + if (hasData && hasData.transitioning) return + actives.collapse('hide') + hasData || actives.data('bs.collapse', null) + } + + var dimension = this.dimension() + + this.$element + .removeClass('collapse') + .addClass('collapsing') + [dimension](0) + + this.transitioning = 1 + + var complete = function () { + this.$element + .removeClass('collapsing') + .addClass('collapse in') + [dimension]('auto') + this.transitioning = 0 + this.$element.trigger('shown.bs.collapse') + } + + if (!$.support.transition) return complete.call(this) + + var scrollSize = $.camelCase(['scroll', dimension].join('-')) + + this.$element + .one($.support.transition.end, $.proxy(complete, this)) + .emulateTransitionEnd(350) + [dimension](this.$element[0][scrollSize]) + } + + Collapse.prototype.hide = function () { + if (this.transitioning || !this.$element.hasClass('in')) return + + var startEvent = $.Event('hide.bs.collapse') + this.$element.trigger(startEvent) + if (startEvent.isDefaultPrevented()) return + + var dimension = this.dimension() + + this.$element + [dimension](this.$element[dimension]()) + [0].offsetHeight + + this.$element + .addClass('collapsing') + .removeClass('collapse') + .removeClass('in') + + this.transitioning = 1 + + var complete = function () { + this.transitioning = 0 + this.$element + .trigger('hidden.bs.collapse') + .removeClass('collapsing') + .addClass('collapse') + } + + if (!$.support.transition) return complete.call(this) + + this.$element + [dimension](0) + .one($.support.transition.end, $.proxy(complete, this)) + .emulateTransitionEnd(350) + } + + Collapse.prototype.toggle = function () { + this[this.$element.hasClass('in') ? 'hide' : 'show']() + } + + + // COLLAPSE PLUGIN DEFINITION + // ========================== + + var old = $.fn.collapse + + $.fn.collapse = function (option) { + return this.each(function () { + var $this = $(this) + var data = $this.data('bs.collapse') + var options = $.extend({}, Collapse.DEFAULTS, $this.data(), typeof option == 'object' && option) + + if (!data && options.toggle && option == 'show') option = !option + if (!data) $this.data('bs.collapse', (data = new Collapse(this, options))) + if (typeof option == 'string') data[option]() + }) + } + + $.fn.collapse.Constructor = Collapse + + + // COLLAPSE NO CONFLICT + // ==================== + + $.fn.collapse.noConflict = function () { + $.fn.collapse = old + return this + } + + + // COLLAPSE DATA-API + // ================= + + $(document).on('click.bs.collapse.data-api', '[data-toggle=collapse]', function (e) { + var $this = $(this), href + var target = $this.attr('data-target') + || e.preventDefault() + || (href = $this.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '') //strip for ie7 + var $target = $(target) + var data = $target.data('bs.collapse') + var option = data ? 'toggle' : $this.data() + var parent = $this.attr('data-parent') + var $parent = parent && $(parent) + + if (!data || !data.transitioning) { + if ($parent) $parent.find('[data-toggle=collapse][data-parent="' + parent + '"]').not($this).addClass('collapsed') + $this[$target.hasClass('in') ? 'addClass' : 'removeClass']('collapsed') + } + + $target.collapse(option) + }) + +}(jQuery); + +/* ======================================================================== + * Bootstrap: dropdown.js v3.1.0 + * http://getbootstrap.com/javascript/#dropdowns + * ======================================================================== + * Copyright 2011-2014 Twitter, Inc. + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) + * ======================================================================== */ + + ++function ($) { + 'use strict'; + + // DROPDOWN CLASS DEFINITION + // ========================= + + var backdrop = '.dropdown-backdrop' + var toggle = '[data-toggle=dropdown]' + var Dropdown = function (element) { + $(element).on('click.bs.dropdown', this.toggle) + } + + Dropdown.prototype.toggle = function (e) { + var $this = $(this) + + if ($this.is('.disabled, :disabled')) return + + var $parent = getParent($this) + var isActive = $parent.hasClass('open') + + clearMenus() + + if (!isActive) { + if ('ontouchstart' in document.documentElement && !$parent.closest('.navbar-nav').length) { + // if mobile we use a backdrop because click events don't delegate + $('