├── js ├── MyFile.txt ├── slider.js ├── easypiechart-data.js ├── shift.js ├── save.js ├── vrtracker.js ├── markAttachment.js ├── abutment.js ├── html5shiv.min.js ├── chart-data.js ├── respond.min.js ├── exporting.js ├── visualizer.js ├── keyboard.js ├── utils.js ├── easypiechart.js ├── constraint.js ├── parser.js └── highcharts-3d.js ├── .gitignore ├── img └── visualizer.png ├── css ├── tether.sass ├── mixins │ ├── _pie-clearfix.sass │ └── _inline-block.sass ├── tether-theme-basic.sass ├── helpers │ ├── _tether.sass │ ├── _tether-theme-basic.sass │ └── _tether-theme-arrows.sass ├── tether-theme-arrows.sass ├── tether-theme-arrows-dark.sass ├── bootstrap-table.css ├── styles2.css ├── bootstrap-theme.min.css └── datepicker.css ├── fonts ├── glyphicons-halflings-regular.eot ├── glyphicons-halflings-regular.ttf └── glyphicons-halflings-regular.woff ├── index.html ├── tables ├── data2.json └── data1.json ├── README.md ├── visualizer.html ├── calibration.html └── dashboard.html /js/MyFile.txt: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | -------------------------------------------------------------------------------- /img/visualizer.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VR-Tracker/Master-Control/HEAD/img/visualizer.png -------------------------------------------------------------------------------- /css/tether.sass: -------------------------------------------------------------------------------- 1 | @import helpers/tether 2 | 3 | $themePrefix: "tether" 4 | 5 | +tether($themePrefix: $themePrefix) -------------------------------------------------------------------------------- /fonts/glyphicons-halflings-regular.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VR-Tracker/Master-Control/HEAD/fonts/glyphicons-halflings-regular.eot -------------------------------------------------------------------------------- /fonts/glyphicons-halflings-regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VR-Tracker/Master-Control/HEAD/fonts/glyphicons-halflings-regular.ttf -------------------------------------------------------------------------------- /fonts/glyphicons-halflings-regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VR-Tracker/Master-Control/HEAD/fonts/glyphicons-halflings-regular.woff -------------------------------------------------------------------------------- /css/mixins/_pie-clearfix.sass: -------------------------------------------------------------------------------- 1 | @mixin pie-clearfix 2 | *zoom: 1 3 | 4 | &:after 5 | content: "" 6 | display: table 7 | clear: both 8 | -------------------------------------------------------------------------------- /css/mixins/_inline-block.sass: -------------------------------------------------------------------------------- 1 | @mixin inline-block 2 | display: inline-block 3 | vertical-align: middle 4 | *vertical-align: auto 5 | *zoom: 1 6 | *display: inline 7 | -------------------------------------------------------------------------------- /js/slider.js: -------------------------------------------------------------------------------- 1 | function nextTab(elem) { 2 | $(elem).next().find('a[data-toggle="tab"]').click(); 3 | } 4 | function prevTab(elem) { 5 | $(elem).prev().find('a[data-toggle="tab"]').click(); 6 | } -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | VR Tracker - Master Control 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /css/tether-theme-basic.sass: -------------------------------------------------------------------------------- 1 | @import helpers/tether 2 | @import helpers/tether-theme-basic 3 | 4 | $themePrefix: "tether" 5 | $themeName: "basic" 6 | $backgroundColor: #fff 7 | $color: inherit 8 | 9 | +tether($themePrefix: $themePrefix) 10 | +tether-theme-basic($themePrefix: $themePrefix, $themeName: $themeName, $backgroundColor: $backgroundColor, $color: $color) -------------------------------------------------------------------------------- /css/helpers/_tether.sass: -------------------------------------------------------------------------------- 1 | =tether($themePrefix: "tether") 2 | .#{ $themePrefix }-element, .#{ $themePrefix }-element * 3 | 4 | &, &:after, &:before 5 | box-sizing: border-box 6 | 7 | .#{ $themePrefix }-element 8 | position: absolute 9 | display: none 10 | 11 | &.#{ $themePrefix }-open 12 | display: block 13 | -------------------------------------------------------------------------------- /css/tether-theme-arrows.sass: -------------------------------------------------------------------------------- 1 | @import helpers/tether 2 | @import helpers/tether-theme-arrows 3 | 4 | $themePrefix: "tether" 5 | $themeName: "arrows" 6 | $arrowSize: 16px 7 | $backgroundColor: #fff 8 | $color: inherit 9 | $useDropShadow: true 10 | 11 | +tether($themePrefix: $themePrefix) 12 | +tether-theme-arrows($themePrefix: $themePrefix, $themeName: $themeName, $arrowSize: $arrowSize, $backgroundColor: $backgroundColor, $color: $color, $useDropShadow: $useDropShadow) 13 | -------------------------------------------------------------------------------- /css/tether-theme-arrows-dark.sass: -------------------------------------------------------------------------------- 1 | @import helpers/tether 2 | @import helpers/tether-theme-arrows 3 | 4 | $themePrefix: "tether" 5 | $themeName: "arrows-dark" 6 | $arrowSize: 16px 7 | $backgroundColor: #000 8 | $color: #fff 9 | $useDropShadow: false 10 | 11 | +tether($themePrefix: $themePrefix) 12 | +tether-theme-arrows($themePrefix: $themePrefix, $themeName: $themeName, $arrowSize: $arrowSize, $backgroundColor: $backgroundColor, $color: $color, $useDropShadow: $useDropShadow) 13 | -------------------------------------------------------------------------------- /css/helpers/_tether-theme-basic.sass: -------------------------------------------------------------------------------- 1 | =tether-theme-basic($themePrefix: "tether", $themeName: "basic", $backgroundColor: #fff, $color: inherit) 2 | .#{ $themePrefix }-element.#{ $themePrefix }-theme-#{ $themeName } 3 | max-width: 100% 4 | max-height: 100% 5 | 6 | .#{ $themePrefix }-content 7 | border-radius: 5px 8 | box-shadow: 0 2px 8px rgba(0, 0, 0, .2) 9 | font-family: inherit 10 | background: $backgroundColor 11 | color: $color 12 | padding: 1em 13 | font-size: 1.1em 14 | line-height: 1.5em 15 | -------------------------------------------------------------------------------- /js/easypiechart-data.js: -------------------------------------------------------------------------------- 1 | $(function() { 2 | $('#easypiechart-teal').easyPieChart({ 3 | scaleColor: false, 4 | barColor: '#1ebfae' 5 | }); 6 | }); 7 | 8 | $(function() { 9 | $('#easypiechart-orange').easyPieChart({ 10 | scaleColor: false, 11 | barColor: '#ffb53e' 12 | }); 13 | }); 14 | 15 | $(function() { 16 | $('#easypiechart-red').easyPieChart({ 17 | scaleColor: false, 18 | barColor: '#f9243f' 19 | }); 20 | }); 21 | 22 | $(function() { 23 | $('#easypiechart-blue').easyPieChart({ 24 | scaleColor: false, 25 | barColor: '#30a5ff' 26 | }); 27 | }); 28 | -------------------------------------------------------------------------------- /tables/data2.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "id": 0, 4 | "name": "Item 0", 5 | "price": "$0" 6 | }, 7 | { 8 | "id": 1, 9 | "name": "Item 1", 10 | "price": "$1" 11 | }, 12 | { 13 | "id": 2, 14 | "name": "Item 2", 15 | "price": "$2" 16 | }, 17 | { 18 | "id": 3, 19 | "name": "Item 3", 20 | "price": "$3" 21 | }, 22 | { 23 | "id": 4, 24 | "name": "Item 4", 25 | "price": "$4" 26 | }, 27 | { 28 | "id": 5, 29 | "name": "Item 5", 30 | "price": "$5" 31 | }, 32 | { 33 | "id": 6, 34 | "name": "Item 6", 35 | "price": "$6" 36 | } 37 | ] -------------------------------------------------------------------------------- /js/shift.js: -------------------------------------------------------------------------------- 1 | /* globals TetherBase */ 2 | 3 | TetherBase.modules.push({ 4 | position({top, left}) { 5 | if (!this.options.shift) { 6 | return; 7 | } 8 | 9 | let shift = this.options.shift; 10 | if (typeof this.options.shift === 'function') { 11 | shift = this.options.shift.call(this, {top, left}); 12 | } 13 | 14 | let shiftTop, shiftLeft; 15 | if (typeof shift === 'string') { 16 | shift = shift.split(' '); 17 | shift[1] = shift[1] || shift[0]; 18 | 19 | ([shiftTop, shiftLeft] = shift); 20 | 21 | shiftTop = parseFloat(shiftTop, 10); 22 | shiftLeft = parseFloat(shiftLeft, 10); 23 | } else { 24 | ([shiftTop, shiftLeft] = [shift.top, shift.left]); 25 | } 26 | 27 | top += shiftTop; 28 | left += shiftLeft; 29 | 30 | return {top, left}; 31 | } 32 | }); 33 | -------------------------------------------------------------------------------- /js/save.js: -------------------------------------------------------------------------------- 1 | 2 | function WriteFile() 3 | { 4 | 5 | var fh = fopen("\\MyFile.txt", 3); // Open the file for writing 6 | 7 | if(fh!=-1) // If the file has been successfully opened 8 | { 9 | var str = "Some text goes here..."; 10 | fwrite(fh, str); // Write the string to a file 11 | fclose(fh); // Close the file 12 | } 13 | 14 | } 15 | function WriteFile1() 16 | { 17 | var fso = new ActiveXObject("Scripting.FileSystemObject"); 18 | var fh = fso.CreateTextFile("c:\\Test.txt", true); 19 | fh.WriteLine("Some text goes here..."); 20 | fh.Close(); 21 | } 22 | 23 | function openFile(){ 24 | var fh = fopen(getScriptPath(), 0); // Open the file for reading 25 | if(fh!=-1) // If the file has been successfully opened 26 | { 27 | length = flength(fh); // Get the length of the file 28 | str = fread(fh, length); // Read in the entire file 29 | fclose(fh); // Close the file 30 | 31 | // Display the contents of the file 32 | write(str); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /js/vrtracker.js: -------------------------------------------------------------------------------- 1 | VRTrackerWebsocket = function (websocketIP){ 2 | this.socket = WebSocket.call(this, 'ws://' + websocketIP + ':7777/user/'); 3 | //this.ip = 4 | //this.socket = new WebSocket('ws://' + websocketIP + ':7777/user/'); 5 | 6 | this.socket.onopen = function(event) { 7 | wsFailedAlert.style.display = "none"; 8 | wsSuccessAlert.style.display = "block"; 9 | console.log("Websocket connected"); 10 | assingAllTags(); 11 | }; 12 | // Handle any errors that occur. 13 | this.socket.onerror = function(error) { 14 | wsFailedAlert.style.display = "block"; 15 | wsSuccessAlert.style.display = "none"; 16 | console.log('WebSocket Error: ' + error); 17 | } 18 | // Handle messages sent by the server. 19 | this.socket.onmessage = function(event) { 20 | //getting the time of the message 21 | var message = event.data; 22 | parseMessage(message); 23 | } 24 | } 25 | 26 | VRTrackerWebsocket.prototype.sendMessage = function(websocket, message){ 27 | websocket.send(message); 28 | } 29 | 30 | VRTrackerWebsocket.prototype.getCamerasInformation = function(){ 31 | if(!calibrating) 32 | socket.send(askCamerasInformation); 33 | } 34 | -------------------------------------------------------------------------------- /js/markAttachment.js: -------------------------------------------------------------------------------- 1 | /* globals Tether */ 2 | 3 | Tether.modules.push({ 4 | initialize() { 5 | this.markers = {}; 6 | 7 | ['target', 'element'].forEach(type => { 8 | const el = document.createElement('div'); 9 | el.className = this.getClass(`${ type }-marker`); 10 | 11 | const dot = document.createElement('div'); 12 | dot.className = this.getClass('marker-dot'); 13 | el.appendChild(dot); 14 | 15 | this[type].appendChild(el); 16 | 17 | this.markers[type] = {dot, el}; 18 | }); 19 | }, 20 | 21 | position({manualOffset, manualTargetOffset}) { 22 | const offsets = { 23 | element: manualOffset, 24 | target: manualTargetOffset 25 | }; 26 | 27 | for (let type in offsets) { 28 | const offset = offsets[type]; 29 | for (let side in offset) { 30 | let val = offset[side]; 31 | const notString = typeof val !== 'string'; 32 | if (notString || 33 | val.indexOf('%') === -1 && 34 | val.indexOf('px') === -1) { 35 | val += 'px'; 36 | } 37 | 38 | if (this.markers[type].dot.style[side] !== val) { 39 | this.markers[type].dot.style[side] = val; 40 | } 41 | } 42 | } 43 | 44 | return true; 45 | } 46 | }); 47 | -------------------------------------------------------------------------------- /js/abutment.js: -------------------------------------------------------------------------------- 1 | /* globals TetherBase */ 2 | 3 | const {getBounds, updateClasses, defer} = TetherBase.Utils; 4 | 5 | TetherBase.modules.push({ 6 | position({top, left}) { 7 | const {height, width} = this.cache('element-bounds', () => { 8 | return getBounds(this.element); 9 | }); 10 | 11 | const targetPos = this.getTargetBounds(); 12 | 13 | const bottom = top + height; 14 | const right = left + width; 15 | 16 | const abutted = []; 17 | if (top <= targetPos.bottom && bottom >= targetPos.top) { 18 | ['left', 'right'].forEach(side => { 19 | const targetPosSide = targetPos[side]; 20 | if (targetPosSide === left || targetPosSide === right) { 21 | abutted.push(side); 22 | } 23 | }); 24 | } 25 | 26 | if (left <= targetPos.right && right >= targetPos.left) { 27 | ['top', 'bottom'].forEach(side => { 28 | const targetPosSide = targetPos[side]; 29 | if (targetPosSide === top || targetPosSide === bottom) { 30 | abutted.push(side); 31 | } 32 | }); 33 | } 34 | 35 | const allClasses = []; 36 | const addClasses = []; 37 | 38 | const sides = ['left', 'top', 'right', 'bottom']; 39 | allClasses.push(this.getClass('abutted')); 40 | sides.forEach(side => { 41 | allClasses.push(`${ this.getClass('abutted') }-${ side }`); 42 | }); 43 | 44 | if (abutted.length) { 45 | addClasses.push(this.getClass('abutted')); 46 | } 47 | 48 | abutted.forEach(side => { 49 | addClasses.push(`${ this.getClass('abutted') }-${ side }`); 50 | }); 51 | 52 | defer(() => { 53 | if (!(this.options.addTargetClasses === false)) { 54 | updateClasses(this.target, addClasses, allClasses); 55 | } 56 | updateClasses(this.element, addClasses, allClasses); 57 | }); 58 | 59 | return true; 60 | } 61 | }); 62 | -------------------------------------------------------------------------------- /tables/data1.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "id": 0, 4 | "type": "Item 0", 5 | "contain": "$0" 6 | }, 7 | { 8 | "id": 1, 9 | "type": "Item 1", 10 | "contain": "$1" 11 | }, 12 | { 13 | "id": 2, 14 | "type": "Item 2", 15 | "contain": "$2" 16 | }, 17 | { 18 | "id": 3, 19 | "type": "Item 3", 20 | "contain": "$3" 21 | }, 22 | { 23 | "id": 4, 24 | "type": "Item 4", 25 | "contain": "$4" 26 | }, 27 | { 28 | "id": 5, 29 | "type": "Item 5", 30 | "contain": "$5" 31 | }, 32 | { 33 | "id": 6, 34 | "type": "Item 6", 35 | "contain": "$6" 36 | }, 37 | { 38 | "id": 7, 39 | "type": "Item 7", 40 | "contain": "$7" 41 | }, 42 | { 43 | "id": 8, 44 | "type": "Item 8", 45 | "contain": "$8" 46 | }, 47 | { 48 | "id": 9, 49 | "type": "Item 9", 50 | "contain": "$9" 51 | }, 52 | { 53 | "id": 10, 54 | "type": "Item 10", 55 | "contain": "$10" 56 | }, 57 | { 58 | "id": 11, 59 | "type": "Item 11", 60 | "contain": "$11" 61 | }, 62 | { 63 | "id": 12, 64 | "type": "Item 12", 65 | "contain": "$12" 66 | }, 67 | { 68 | "id": 13, 69 | "type": "Item 13", 70 | "contain": "$13" 71 | }, 72 | { 73 | "id": 14, 74 | "type": "Item 14", 75 | "contain": "$14" 76 | }, 77 | { 78 | "id": 15, 79 | "type": "Item 15", 80 | "contain": "$15" 81 | }, 82 | { 83 | "id": 16, 84 | "type": "Item 16", 85 | "contain": "$16" 86 | }, 87 | { 88 | "id": 17, 89 | "type": "Item 17", 90 | "contain": "$17" 91 | }, 92 | { 93 | "id": 18, 94 | "type": "Item 18", 95 | "contain": "$18" 96 | }, 97 | { 98 | "id": 19, 99 | "type": "Item 19", 100 | "contain": "$19" 101 | }, 102 | { 103 | "id": 20, 104 | "type": "Item 20", 105 | "contain": "$20" 106 | } 107 | ] 108 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # MasterControl 2 | 3 | *Those tools will help you go through VR Tracker calibration* 4 | The Master Control helps you get the different information from the VR Tracker system. You have different pages to get informations on the whole system, do the calibration, ask for assistance, and report. 5 | 6 | ## Installation 7 | * Download or Clone this repo 8 | * **Make sure VR Tracker system is running and you are connected to VR Tracker Gateway wifi** (pwd: vrtracker) 9 | * Open index.html in your web browser 10 | 11 | ## Tools 12 | ### Dashboard 13 | The Dashboard is the tool to get all the informations on the system and the different connected devices. For more details, go and check the [wiki](https://github.com/VR-Tracker/Master-Control/wiki/Dashboard) to get a detail description of each element on the dashboard 14 | 15 | ### Calibration 16 | More informations on the calibration process can be found on [VR Tracker Get Started page](https://vrtracker.xyz/getstarted/). 17 | 18 | ### Visualizer 19 | The Visualizer page shows you the position of the Tags. It is to be improved for a faster refresh of the datas. 20 | *visualization.js* file can be a start to implement a **User** in Javascript. 21 | 22 | ![Visualizer](/img/visualizer.png) 23 | 24 | ### Release 25 | Find the different information on the [releases](https://github.com/VR-Tracker/Master-Control/releases), we will describe here what is new and what changed. (*We will update it very soon...) 26 | 27 | ### FAQ 28 | Check our [FAQ](https://vrtracker.xyz/faq/) for the common questions, if you have any issue, post it on the git or send us an email at : support@vrtracker.xyz 29 | 30 | ## Contributing 31 | 32 | Feel free to contribute or ask new features, we will prioritize the new features based on your needs :) 33 | 34 | ## Authors 35 | 36 | * **VR Tracker** - *Initial work* - [VR Tracker Dashboard](https://github.com/VR-Tracker/Master-Control) 37 | 38 | ## License 39 | 40 | This project is licensed under the GPL-3.0 - see the [LICENSE](https://github.com/VR-Tracker/Master-Control/blob/master/LICENSE) file for details 41 | 42 | ## Acknowledgments 43 | 44 | ## FAQ 45 | Check our [FAQ](https://vrtracker.xyz/faq/) for the common questions, if you have any issue, post it on the git or send us an email at : support@vrtracker.xyz 46 | 47 | ## License 48 | This project is licensed under the GPL-3.0 - see the [LICENSE](https://github.com/VR-Tracker/Plugins/blob/master/LICENSE) file for details 49 | 50 | ## Contributing 51 | Feel free to contribute or ask new features, we will prioritize the new features based on your needs :) 52 | -------------------------------------------------------------------------------- /js/html5shiv.min.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @preserve HTML5 Shiv 3.7.2 | @afarkas @jdalton @jon_neal @rem | MIT/GPL2 Licensed 3 | */ 4 | !function(a,b){function c(a,b){var c=a.createElement("p"),d=a.getElementsByTagName("head")[0]||a.documentElement;return c.innerHTML="x",d.insertBefore(c.lastChild,d.firstChild)}function d(){var a=t.elements;return"string"==typeof a?a.split(" "):a}function e(a,b){var c=t.elements;"string"!=typeof c&&(c=c.join(" ")),"string"!=typeof a&&(a=a.join(" ")),t.elements=c+" "+a,j(b)}function f(a){var b=s[a[q]];return b||(b={},r++,a[q]=r,s[r]=b),b}function g(a,c,d){if(c||(c=b),l)return c.createElement(a);d||(d=f(c));var e;return e=d.cache[a]?d.cache[a].cloneNode():p.test(a)?(d.cache[a]=d.createElem(a)).cloneNode():d.createElem(a),!e.canHaveChildren||o.test(a)||e.tagUrn?e:d.frag.appendChild(e)}function h(a,c){if(a||(a=b),l)return a.createDocumentFragment();c=c||f(a);for(var e=c.frag.cloneNode(),g=0,h=d(),i=h.length;i>g;g++)e.createElement(h[g]);return e}function i(a,b){b.cache||(b.cache={},b.createElem=a.createElement,b.createFrag=a.createDocumentFragment,b.frag=b.createFrag()),a.createElement=function(c){return t.shivMethods?g(c,a,b):b.createElem(c)},a.createDocumentFragment=Function("h,f","return function(){var n=f.cloneNode(),c=n.createElement;h.shivMethods&&("+d().join().replace(/[\w\-:]+/g,function(a){return b.createElem(a),b.frag.createElement(a),'c("'+a+'")'})+");return n}")(t,b.frag)}function j(a){a||(a=b);var d=f(a);return!t.shivCSS||k||d.hasCSS||(d.hasCSS=!!c(a,"article,aside,dialog,figcaption,figure,footer,header,hgroup,main,nav,section{display:block}mark{background:#FF0;color:#000}template{display:none}")),l||i(a,d),a}var k,l,m="3.7.2",n=a.html5||{},o=/^<|^(?:button|map|select|textarea|object|iframe|option|optgroup)$/i,p=/^(?:a|b|code|div|fieldset|h1|h2|h3|h4|h5|h6|i|label|li|ol|p|q|span|strong|style|table|tbody|td|th|tr|ul)$/i,q="_html5shiv",r=0,s={};!function(){try{var a=b.createElement("a");a.innerHTML="",k="hidden"in a,l=1==a.childNodes.length||function(){b.createElement("a");var a=b.createDocumentFragment();return"undefined"==typeof a.cloneNode||"undefined"==typeof a.createDocumentFragment||"undefined"==typeof a.createElement}()}catch(c){k=!0,l=!0}}();var t={elements:n.elements||"abbr article aside audio bdi canvas data datalist details dialog figcaption figure footer header hgroup main mark meter nav output picture progress section summary template time video",version:m,shivCSS:n.shivCSS!==!1,supportsUnknownElements:l,shivMethods:n.shivMethods!==!1,type:"default",shivDocument:j,createElement:g,createDocumentFragment:h,addElements:e};a.html5=t,j(b)}(this,document); -------------------------------------------------------------------------------- /js/chart-data.js: -------------------------------------------------------------------------------- 1 | var randomScalingFactor = function(){ return Math.round(Math.random()*1000)}; 2 | 3 | var lineChartData = { 4 | labels : ["January","February","March","April","May","June","July"], 5 | datasets : [ 6 | { 7 | label: "My First dataset", 8 | fillColor : "rgba(220,220,220,0.2)", 9 | strokeColor : "rgba(220,220,220,1)", 10 | pointColor : "rgba(220,220,220,1)", 11 | pointStrokeColor : "#fff", 12 | pointHighlightFill : "#fff", 13 | pointHighlightStroke : "rgba(220,220,220,1)", 14 | data : [randomScalingFactor(),randomScalingFactor(),randomScalingFactor(),randomScalingFactor(),randomScalingFactor(),randomScalingFactor(),randomScalingFactor()] 15 | }, 16 | { 17 | label: "My Second dataset", 18 | fillColor : "rgba(48, 164, 255, 0.2)", 19 | strokeColor : "rgba(48, 164, 255, 1)", 20 | pointColor : "rgba(48, 164, 255, 1)", 21 | pointStrokeColor : "#fff", 22 | pointHighlightFill : "#fff", 23 | pointHighlightStroke : "rgba(48, 164, 255, 1)", 24 | data : [randomScalingFactor(),randomScalingFactor(),randomScalingFactor(),randomScalingFactor(),randomScalingFactor(),randomScalingFactor(),randomScalingFactor()] 25 | } 26 | ] 27 | 28 | } 29 | 30 | var barChartData = { 31 | labels : ["January","February","March","April","May","June","July"], 32 | datasets : [ 33 | { 34 | fillColor : "rgba(220,220,220,0.5)", 35 | strokeColor : "rgba(220,220,220,0.8)", 36 | highlightFill: "rgba(220,220,220,0.75)", 37 | highlightStroke: "rgba(220,220,220,1)", 38 | data : [randomScalingFactor(),randomScalingFactor(),randomScalingFactor(),randomScalingFactor(),randomScalingFactor(),randomScalingFactor(),randomScalingFactor()] 39 | }, 40 | { 41 | fillColor : "rgba(48, 164, 255, 0.2)", 42 | strokeColor : "rgba(48, 164, 255, 0.8)", 43 | highlightFill : "rgba(48, 164, 255, 0.75)", 44 | highlightStroke : "rgba(48, 164, 255, 1)", 45 | data : [randomScalingFactor(),randomScalingFactor(),randomScalingFactor(),randomScalingFactor(),randomScalingFactor(),randomScalingFactor(),randomScalingFactor()] 46 | } 47 | ] 48 | 49 | } 50 | 51 | var pieData = [ 52 | { 53 | value: 300, 54 | color:"#30a5ff", 55 | highlight: "#62b9fb", 56 | label: "Blue" 57 | }, 58 | { 59 | value: 50, 60 | color: "#ffb53e", 61 | highlight: "#fac878", 62 | label: "Orange" 63 | }, 64 | { 65 | value: 100, 66 | color: "#1ebfae", 67 | highlight: "#3cdfce", 68 | label: "Teal" 69 | }, 70 | { 71 | value: 120, 72 | color: "#f9243f", 73 | highlight: "#f6495f", 74 | label: "Red" 75 | } 76 | 77 | ]; 78 | 79 | var doughnutData = [ 80 | { 81 | value: 300, 82 | color:"#30a5ff", 83 | highlight: "#62b9fb", 84 | label: "Blue" 85 | }, 86 | { 87 | value: 50, 88 | color: "#ffb53e", 89 | highlight: "#fac878", 90 | label: "Orange" 91 | }, 92 | { 93 | value: 100, 94 | color: "#1ebfae", 95 | highlight: "#3cdfce", 96 | label: "Teal" 97 | }, 98 | { 99 | value: 120, 100 | color: "#f9243f", 101 | highlight: "#f6495f", 102 | label: "Red" 103 | } 104 | 105 | ]; 106 | 107 | window.onload = function(){ 108 | var chart1 = document.getElementById("line-chart").getContext("2d"); 109 | window.myLine = new Chart(chart1).Line(lineChartData, { 110 | responsive: true 111 | }); 112 | var chart2 = document.getElementById("bar-chart").getContext("2d"); 113 | window.myBar = new Chart(chart2).Bar(barChartData, { 114 | responsive : true 115 | }); 116 | var chart3 = document.getElementById("doughnut-chart").getContext("2d"); 117 | window.myDoughnut = new Chart(chart3).Doughnut(doughnutData, {responsive : true 118 | }); 119 | var chart4 = document.getElementById("pie-chart").getContext("2d"); 120 | window.myPie = new Chart(chart4).Pie(pieData, {responsive : true 121 | }); 122 | 123 | }; -------------------------------------------------------------------------------- /js/respond.min.js: -------------------------------------------------------------------------------- 1 | /*! Respond.js v1.4.2: min/max-width media query polyfill 2 | * Copyright 2014 Scott Jehl 3 | * Licensed under MIT 4 | * http://j.mp/respondjs */ 5 | 6 | !function(a){"use strict";a.matchMedia=a.matchMedia||function(a){var b,c=a.documentElement,d=c.firstElementChild||c.firstChild,e=a.createElement("body"),f=a.createElement("div");return f.id="mq-test-1",f.style.cssText="position:absolute;top:-100em",e.style.background="none",e.appendChild(f),function(a){return f.innerHTML='­',c.insertBefore(e,d),b=42===f.offsetWidth,c.removeChild(e),{matches:b,media:a}}}(a.document)}(this),function(a){"use strict";function b(){v(!0)}var c={};a.respond=c,c.update=function(){};var d=[],e=function(){var b=!1;try{b=new a.XMLHttpRequest}catch(c){b=new a.ActiveXObject("Microsoft.XMLHTTP")}return function(){return b}}(),f=function(a,b){var c=e();c&&(c.open("GET",a,!0),c.onreadystatechange=function(){4!==c.readyState||200!==c.status&&304!==c.status||b(c.responseText)},4!==c.readyState&&c.send(null))},g=function(a){return a.replace(c.regex.minmaxwh,"").match(c.regex.other)};if(c.ajax=f,c.queue=d,c.unsupportedmq=g,c.regex={media:/@media[^\{]+\{([^\{\}]*\{[^\}\{]*\})+/gi,keyframes:/@(?:\-(?:o|moz|webkit)\-)?keyframes[^\{]+\{(?:[^\{\}]*\{[^\}\{]*\})+[^\}]*\}/gi,comments:/\/\*[^*]*\*+([^/][^*]*\*+)*\//gi,urls:/(url\()['"]?([^\/\)'"][^:\)'"]+)['"]?(\))/g,findStyles:/@media *([^\{]+)\{([\S\s]+?)$/,only:/(only\s+)?([a-zA-Z]+)\s?/,minw:/\(\s*min\-width\s*:\s*(\s*[0-9\.]+)(px|em)\s*\)/,maxw:/\(\s*max\-width\s*:\s*(\s*[0-9\.]+)(px|em)\s*\)/,minmaxwh:/\(\s*m(in|ax)\-(height|width)\s*:\s*(\s*[0-9\.]+)(px|em)\s*\)/gi,other:/\([^\)]*\)/g},c.mediaQueriesSupported=a.matchMedia&&null!==a.matchMedia("only all")&&a.matchMedia("only all").matches,!c.mediaQueriesSupported){var h,i,j,k=a.document,l=k.documentElement,m=[],n=[],o=[],p={},q=30,r=k.getElementsByTagName("head")[0]||l,s=k.getElementsByTagName("base")[0],t=r.getElementsByTagName("link"),u=function(){var a,b=k.createElement("div"),c=k.body,d=l.style.fontSize,e=c&&c.style.fontSize,f=!1;return b.style.cssText="position:absolute;font-size:1em;width:1em",c||(c=f=k.createElement("body"),c.style.background="none"),l.style.fontSize="100%",c.style.fontSize="100%",c.appendChild(b),f&&l.insertBefore(c,l.firstChild),a=b.offsetWidth,f?l.removeChild(c):c.removeChild(b),l.style.fontSize=d,e&&(c.style.fontSize=e),a=j=parsedouble(a)},v=function(b){var c="clientWidth",d=l[c],e="CSS1Compat"===k.compatMode&&d||k.body[c]||d,f={},g=t[t.length-1],p=(new Date).getTime();if(b&&h&&q>p-h)return a.clearTimeout(i),i=a.setTimeout(v,q),void 0;h=p;for(var s in m)if(m.hasOwnProperty(s)){var w=m[s],x=w.minw,y=w.maxw,z=null===x,A=null===y,B="em";x&&(x=parsedouble(x)*(x.indexOf(B)>-1?j||u():1)),y&&(y=parsedouble(y)*(y.indexOf(B)>-1?j||u():1)),w.hasquery&&(z&&A||!(z||e>=x)||!(A||y>=e))||(f[w.media]||(f[w.media]=[]),f[w.media].push(n[w.rules]))}for(var C in o)o.hasOwnProperty(C)&&o[C]&&o[C].parentNode===r&&r.removeChild(o[C]);o.length=0;for(var D in f)if(f.hasOwnProperty(D)){var E=k.createElement("style"),F=f[D].join("\n");E.type="text/css",E.media=D,r.insertBefore(E,g.nextSibling),E.styleSheet?E.styleSheet.cssText=F:E.appendChild(k.createTextNode(F)),o.push(E)}},w=function(a,b,d){var e=a.replace(c.regex.comments,"").replace(c.regex.keyframes,"").match(c.regex.media),f=e&&e.length||0;b=b.substring(0,b.lastIndexOf("/"));var h=function(a){return a.replace(c.regex.urls,"$1"+b+"$2$3")},i=!f&&d;b.length&&(b+="/"),i&&(f=1);for(var j=0;f>j;j++){var k,l,o,p;i?(k=d,n.push(h(a))):(k=e[j].match(c.regex.findStyles)&&RegExp.$1,n.push(RegExp.$2&&h(RegExp.$2))),o=k.split(","),p=o.length;for(var q=0;p>q;q++)l=o[q],g(l)||m.push({media:l.split("(")[0].match(c.regex.only)&&RegExp.$2||"all",rules:n.length-1,hasquery:l.indexOf("(")>-1,minw:l.match(c.regex.minw)&&parsedouble(RegExp.$1)+(RegExp.$2||""),maxw:l.match(c.regex.maxw)&&parsedouble(RegExp.$1)+(RegExp.$2||"")})}v()},x=function(){if(d.length){var b=d.shift();f(b.href,function(c){w(c,b.href,b.media),p[b.href]=!0,a.setTimeout(function(){x()},0)})}},y=function(){for(var b=0;b 2 | 3 | 4 | 5 | 6 | VR Tracker - Visualizer 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 21 | 22 | 23 | 24 | 25 | 39 | 40 | 49 | 50 |
51 | 52 |
53 | 57 |
58 | 59 |
60 | 61 |
62 |

Visualizer

63 |
64 |
65 | 66 |
67 |
68 | 70 | 72 |
73 |
74 | 75 |
76 |
77 |
78 | No Internet Connection 79 |
80 | 81 |
82 |
83 |
84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | -------------------------------------------------------------------------------- /css/bootstrap-table.css: -------------------------------------------------------------------------------- 1 | .table { 2 | margin-bottom: 0 !important; 3 | border-bottom: 1px solid #dddddd; 4 | border-collapse: collapse !important; 5 | border-radius: 1px; 6 | } 7 | 8 | .fixed-table-container { 9 | position: relative; 10 | clear: both; 11 | border: 1px solid #dddddd; 12 | border-radius: 4px; 13 | -webkit-border-radius: 4px; 14 | -moz-border-radius: 4px; 15 | } 16 | 17 | .fixed-table-header { 18 | overflow: hidden; 19 | border-radius: 4px 4px 0 0; 20 | -webkit-border-radius: 4px 4px 0 0; 21 | -moz-border-radius: 4px 4px 0 0; 22 | } 23 | 24 | .fixed-table-body { 25 | overflow-x: auto; 26 | overflow-y: auto; 27 | height: 100%; 28 | } 29 | 30 | .fixed-table-container table { 31 | width: 100%; 32 | } 33 | 34 | .fixed-table-container thead th { 35 | height: 0; 36 | padding: 0; 37 | margin: 0; 38 | border-left: 1px solid #dddddd; 39 | } 40 | 41 | .fixed-table-container thead th:first-child { 42 | border-left: none; 43 | } 44 | 45 | .fixed-table-container thead th .th-inner { 46 | padding: 8px; 47 | line-height: 24px; 48 | vertical-align: top; 49 | overflow: hidden; 50 | text-overflow: ellipsis; 51 | white-space: nowrap; 52 | } 53 | 54 | .fixed-table-container thead th .sortable { 55 | cursor: pointer; 56 | } 57 | 58 | .fixed-table-container tbody td { 59 | border-left: 1px solid #dddddd; 60 | } 61 | 62 | .fixed-table-container tbody tr:first-child td { 63 | border-top: none; 64 | } 65 | 66 | .fixed-table-container tbody td:first-child { 67 | border-left: none; 68 | } 69 | 70 | /* the same color with .active */ 71 | .fixed-table-container tbody .selected td { 72 | background-color: #f5f5f5; 73 | } 74 | 75 | .fixed-table-container .bs-checkbox { 76 | text-align: center; 77 | } 78 | 79 | .fixed-table-container .bs-checkbox .th-inner { 80 | padding: 8px 0; 81 | } 82 | 83 | .fixed-table-container input[type="radio"], 84 | .fixed-table-container input[type="checkbox"] { 85 | margin: 0 auto !important; 86 | } 87 | 88 | .fixed-table-container .no-records-found { 89 | text-align: center; 90 | } 91 | 92 | 93 | .fixed-table-pagination .pagination, 94 | .fixed-table-pagination .pagination-detail { 95 | margin-top: 10px; 96 | margin-bottom: 10px; 97 | } 98 | 99 | .fixed-table-pagination .pagination a { 100 | padding: 6px 12px; 101 | line-height: 1.428571429; 102 | } 103 | 104 | .fixed-table-pagination .pagination-info { 105 | line-height: 34px; 106 | margin-right: 5px; 107 | } 108 | 109 | .fixed-table-pagination .btn-group { 110 | position: relative; 111 | display: inline-block; 112 | vertical-align: middle; 113 | } 114 | 115 | .fixed-table-pagination .dropup .dropdown-menu { 116 | margin-bottom: 0; 117 | } 118 | 119 | .fixed-table-pagination .page-list { 120 | display: inline-block; 121 | } 122 | 123 | .fixed-table-toolbar .columns { 124 | margin-left: 5px; 125 | } 126 | 127 | .fixed-table-toolbar .columns label { 128 | display: block; 129 | padding: 3px 20px; 130 | clear: both; 131 | font-weight: normal; 132 | line-height: 1.428571429; 133 | } 134 | 135 | .fixed-table-toolbar .bars, 136 | .fixed-table-toolbar .search, 137 | .fixed-table-toolbar .columns { 138 | position: relative; 139 | margin-top: 10px; 140 | margin-bottom: 10px; 141 | line-height: 34px; 142 | } 143 | 144 | .fixed-table-pagination li.disabled a { 145 | pointer-events: none; 146 | cursor: default; 147 | } 148 | 149 | .fixed-table-loading { 150 | display: none; 151 | position: absolute; 152 | top: 42px; 153 | right: 0; 154 | bottom: 0; 155 | left: 0; 156 | z-index: 99; 157 | background-color: #fff; 158 | text-align: center; 159 | } 160 | 161 | .fixed-table-body .card-view .title { 162 | font-weight: bold; 163 | display: inline-block; 164 | min-width: 30%; 165 | text-align: left !important; 166 | } 167 | 168 | /* support bootstrap 2 */ 169 | .fixed-table-body thead th .th-inner { 170 | box-sizing: border-box; 171 | } 172 | 173 | .table th, .table td { 174 | vertical-align: middle; 175 | box-sizing: border-box; 176 | } 177 | 178 | .fixed-table-toolbar .dropdown-menu { 179 | text-align: left; 180 | max-height: 300px; 181 | overflow: auto; 182 | } 183 | 184 | .fixed-table-toolbar .btn-group>.btn-group { 185 | display: inline-block; 186 | margin-left: -1px !important; 187 | } 188 | 189 | .fixed-table-toolbar .btn-group>.btn-group>.btn { 190 | border-radius: 0; 191 | } 192 | 193 | .fixed-table-toolbar .btn-group>.btn-group:first-child>.btn { 194 | border-top-left-radius: 4px; 195 | border-bottom-left-radius: 4px; 196 | } 197 | 198 | .fixed-table-toolbar .btn-group>.btn-group:last-child>.btn { 199 | border-top-right-radius: 4px; 200 | border-bottom-right-radius: 4px; 201 | } 202 | 203 | .table>thead>tr>th { 204 | vertical-align: bottom; 205 | border-bottom: 2px solid #ddd; 206 | } 207 | 208 | /* support bootstrap 3 */ 209 | .table thead>tr>th { 210 | padding: 0; 211 | margin: 0; 212 | } 213 | 214 | .pull-right .dropdown-menu { 215 | right: 0; 216 | left: auto; 217 | } 218 | 219 | /* calculate scrollbar width */ 220 | p.fixed-table-scroll-inner { 221 | width: 100%; 222 | height: 200px; 223 | } 224 | 225 | div.fixed-table-scroll-outer { 226 | top: 0; 227 | left: 0; 228 | visibility: hidden; 229 | width: 200px; 230 | height: 150px; 231 | overflow: hidden; 232 | } -------------------------------------------------------------------------------- /css/styles2.css: -------------------------------------------------------------------------------- 1 | .wizard { 2 | margin: 20px auto; 3 | background: #fff; 4 | } 5 | 6 | .wizard .nav-tabs { 7 | position: relative; 8 | margin: 40px auto; 9 | margin-bottom: 0; 10 | border-bottom-color: #e0e0e0; 11 | } 12 | 13 | .wizard > div.wizard-inner { 14 | position: relative; 15 | } 16 | 17 | 18 | .connecting-line { 19 | height: 2px; 20 | background: #e0e0e0; 21 | position: absolute; 22 | width: 80%; 23 | margin: 0 auto; 24 | left: 0; 25 | right: 0; 26 | top: 50%; 27 | z-index: 1; 28 | } 29 | 30 | .wizard .nav-tabs > li.active > a, .wizard .nav-tabs > li.active > a:hover, .wizard .nav-tabs > li.active > a:focus { 31 | color: #555555; 32 | cursor: default; 33 | border: 0; 34 | border-bottom-color: transparent; 35 | } 36 | 37 | span.round-tab { 38 | width: 70px; 39 | height: 70px; 40 | line-height: 70px; 41 | display: inline-block; 42 | border-radius: 100px; 43 | background: #fff; 44 | border: 2px solid #e0e0e0; 45 | z-index: 2; 46 | position: absolute; 47 | left: 0; 48 | text-align: center; 49 | font-size: 25px; 50 | } 51 | span.round-tab i{ 52 | color:#555555; 53 | } 54 | .wizard li.active span.round-tab { 55 | background: #fff; 56 | border: 2px solid #5bc0de; 57 | 58 | } 59 | .wizard li.active span.round-tab i{ 60 | color: #5bc0de; 61 | } 62 | 63 | span.round-tab:hover { 64 | color: #333; 65 | border: 2px solid #333; 66 | } 67 | 68 | .wizard .nav-tabs > li { 69 | width: 25%; 70 | } 71 | 72 | .wizard li:after { 73 | content: " "; 74 | position: absolute; 75 | left: 46%; 76 | opacity: 0; 77 | margin: 0 auto; 78 | bottom: 0px; 79 | border: 5px solid transparent; 80 | border-bottom-color: #5bc0de; 81 | transition: 0.1s ease-in-out; 82 | } 83 | 84 | .wizard li.active:after { 85 | content: " "; 86 | position: absolute; 87 | left: 46%; 88 | opacity: 1; 89 | margin: 0 auto; 90 | bottom: 0px; 91 | border: 10px solid transparent; 92 | border-bottom-color: #5bc0de; 93 | } 94 | 95 | .wizard .nav-tabs > li a { 96 | width: 70px; 97 | height: 70px; 98 | margin: 20px auto; 99 | border-radius: 100%; 100 | padding: 0; 101 | } 102 | 103 | .wizard .nav-tabs > li a:hover { 104 | background: transparent; 105 | } 106 | 107 | .wizard .tab-pane { 108 | position: relative; 109 | padding-top: 50px; 110 | } 111 | 112 | .wizard h3 { 113 | margin-top: 0; 114 | } 115 | 116 | @media( max-width : 585px ) { 117 | 118 | .wizard { 119 | width: 90%; 120 | height: auto !important; 121 | } 122 | 123 | span.round-tab { 124 | font-size: 16px; 125 | width: 50px; 126 | height: 50px; 127 | line-height: 50px; 128 | } 129 | 130 | .wizard .nav-tabs > li a { 131 | width: 50px; 132 | height: 50px; 133 | line-height: 50px; 134 | display: block; 135 | } 136 | 137 | .wizard li.active:after { 138 | content: " "; 139 | position: absolute; 140 | left: 35%; 141 | } 142 | } 143 | 144 | .button { 145 | width: 150px; 146 | padding: 10px; 147 | background-color: #FF8C00; 148 | box-shadow: -8px 8px 10px 3px rgba(0,0,0,0.2); 149 | font-weight:bold; text-decoration:none; 150 | } 151 | 152 | #cover{ 153 | position:fixed; 154 | top:0; 155 | left:0; 156 | background:rgba(0,0,0,0.6); 157 | z-index:1001; 158 | width:100%; 159 | height:100%; 160 | display:none; 161 | } 162 | /* 163 | #messageScreen { 164 | height:380px; 165 | width:340px; 166 | margin:0 auto; 167 | position:absolute;; 168 | z-index:10; 169 | display:none; 170 | border:5px solid #cccccc; 171 | border-radius:10px; 172 | } 173 | */ 174 | #calibration-failed { 175 | display:none; 176 | } 177 | 178 | #calibration-success, #calibrationMessage, #calibration-inprocess { 179 | display:none; 180 | } 181 | 182 | #messageScreen{ 183 | position: fixed; 184 | top: 30%; 185 | left:10%; 186 | z-index:1002; 187 | display:none; 188 | width: 80%; 189 | /*border:5px solid #cccccc; 190 | border-radius:10px;*/ 191 | } 192 | 193 | #messageScreen:target, #messageScreen:target + #cover{ 194 | display:block; opacity:2; 195 | } 196 | 197 | .cancel { 198 | display:block; 199 | position:absolute; 200 | top:3px; 201 | right:2px; 202 | /*background:rgb(245,245,245);*/ 203 | color:white; 204 | height:30px; 205 | width:35px; 206 | font-size:30px; 207 | text-decoration:none; 208 | text-align:center; 209 | font-weight:bold; 210 | } 211 | 212 | .quit-view { 213 | display:block; 214 | position:absolute; 215 | top:30px; 216 | right:2px; 217 | /*background:rgb(245,245,245);*/ 218 | color:white; 219 | height:30px; 220 | width:35px; 221 | font-size:30px; 222 | text-decoration:none; 223 | text-align:center; 224 | font-weight:bold; 225 | } 226 | 227 | #fullScreenMessage{ 228 | /*position: absolute; 229 | height: 50px;*/ 230 | /* 231 | 232 | top: 50%; 233 | left: 50%;*/ 234 | position: relative; 235 | width: 100%; 236 | font-size: 600%; 237 | text-align: center; 238 | color: black; 239 | /* 240 | margin-left: -50px; */ 241 | /* margin is -0.5 * dimension */ 242 | /* 243 | margin-top: -25px;*/ 244 | 245 | } 246 | #calibrationMessage{ 247 | position: relative; 248 | width: 100%; 249 | font-size: 300%; 250 | text-align: center; 251 | color: black; 252 | } 253 | 254 | #cross{ 255 | position:absolute; 256 | left: 50%; 257 | text-align: center; 258 | } 259 | 260 | #calibrate-btn{ 261 | width:30%; 262 | margin-left: 10px; 263 | background-color: #06c; 264 | color: white; 265 | } 266 | 267 | .update-info{ 268 | display : none; 269 | } 270 | -------------------------------------------------------------------------------- /css/helpers/_tether-theme-arrows.sass: -------------------------------------------------------------------------------- 1 | =tether-theme-arrows($themePrefix: "tether", $themeName: "arrows", $arrowSize: 16px, $arrowPointerEvents: null, $backgroundColor: #fff, $color: inherit, $useDropShadow: false) 2 | .#{ $themePrefix }-element.#{ $themePrefix }-theme-#{ $themeName } 3 | max-width: 100% 4 | max-height: 100% 5 | 6 | .#{ $themePrefix }-content 7 | border-radius: 5px 8 | position: relative 9 | font-family: inherit 10 | background: $backgroundColor 11 | color: $color 12 | padding: 1em 13 | font-size: 1.1em 14 | line-height: 1.5em 15 | 16 | @if $useDropShadow 17 | transform: translateZ(0) 18 | filter: drop-shadow(0 1px 4px rgba(0, 0, 0, .2)) 19 | 20 | &:before 21 | content: "" 22 | display: block 23 | position: absolute 24 | width: 0 25 | height: 0 26 | border-color: transparent 27 | border-width: $arrowSize 28 | border-style: solid 29 | pointer-events: $arrowPointerEvents 30 | 31 | // Centers and middles 32 | 33 | &.#{ $themePrefix }-element-attached-bottom.#{ $themePrefix }-element-attached-center .#{ $themePrefix }-content 34 | margin-bottom: $arrowSize 35 | 36 | &:before 37 | top: 100% 38 | left: 50% 39 | margin-left: - $arrowSize 40 | border-top-color: $backgroundColor 41 | 42 | &.#{ $themePrefix }-element-attached-top.#{ $themePrefix }-element-attached-center .#{ $themePrefix }-content 43 | margin-top: $arrowSize 44 | 45 | &:before 46 | bottom: 100% 47 | left: 50% 48 | margin-left: - $arrowSize 49 | border-bottom-color: $backgroundColor 50 | 51 | &.#{ $themePrefix }-element-attached-right.#{ $themePrefix }-element-attached-middle .#{ $themePrefix }-content 52 | margin-right: $arrowSize 53 | 54 | &:before 55 | left: 100% 56 | top: 50% 57 | margin-top: - $arrowSize 58 | border-left-color: $backgroundColor 59 | 60 | &.#{ $themePrefix }-element-attached-left.#{ $themePrefix }-element-attached-middle .#{ $themePrefix }-content 61 | margin-left: $arrowSize 62 | 63 | &:before 64 | right: 100% 65 | top: 50% 66 | margin-top: - $arrowSize 67 | border-right-color: $backgroundColor 68 | 69 | // Target middle/center, element corner 70 | 71 | &.#{ $themePrefix }-element-attached-left.#{ $themePrefix }-target-attached-center .#{ $themePrefix }-content 72 | left: - $arrowSize * 2 73 | 74 | &.#{ $themePrefix }-element-attached-right.#{ $themePrefix }-target-attached-center .#{ $themePrefix }-content 75 | left: $arrowSize * 2 76 | 77 | &.#{ $themePrefix }-element-attached-top.#{ $themePrefix }-element-attached-left.#{ $themePrefix }-target-attached-middle .#{ $themePrefix }-content 78 | margin-top: $arrowSize 79 | 80 | &:before 81 | bottom: 100% 82 | left: $arrowSize 83 | border-bottom-color: $backgroundColor 84 | 85 | &.#{ $themePrefix }-element-attached-top.#{ $themePrefix }-element-attached-right.#{ $themePrefix }-target-attached-middle .#{ $themePrefix }-content 86 | margin-top: $arrowSize 87 | 88 | &:before 89 | bottom: 100% 90 | right: $arrowSize 91 | border-bottom-color: $backgroundColor 92 | 93 | &.#{ $themePrefix }-element-attached-bottom.#{ $themePrefix }-element-attached-left.#{ $themePrefix }-target-attached-middle .#{ $themePrefix }-content 94 | margin-bottom: $arrowSize 95 | 96 | &:before 97 | top: 100% 98 | left: $arrowSize 99 | border-top-color: $backgroundColor 100 | 101 | &.#{ $themePrefix }-element-attached-bottom.#{ $themePrefix }-element-attached-right.#{ $themePrefix }-target-attached-middle .#{ $themePrefix }-content 102 | margin-bottom: $arrowSize 103 | 104 | &:before 105 | top: 100% 106 | right: $arrowSize 107 | border-top-color: $backgroundColor 108 | 109 | 110 | // Top and bottom corners 111 | 112 | &.#{ $themePrefix }-element-attached-top.#{ $themePrefix }-element-attached-left.#{ $themePrefix }-target-attached-bottom .#{ $themePrefix }-content 113 | margin-top: $arrowSize 114 | 115 | &:before 116 | bottom: 100% 117 | left: $arrowSize 118 | border-bottom-color: $backgroundColor 119 | 120 | &.#{ $themePrefix }-element-attached-top.#{ $themePrefix }-element-attached-right.#{ $themePrefix }-target-attached-bottom .#{ $themePrefix }-content 121 | margin-top: $arrowSize 122 | 123 | &:before 124 | bottom: 100% 125 | right: $arrowSize 126 | border-bottom-color: $backgroundColor 127 | 128 | &.#{ $themePrefix }-element-attached-bottom.#{ $themePrefix }-element-attached-left.#{ $themePrefix }-target-attached-top .#{ $themePrefix }-content 129 | margin-bottom: $arrowSize 130 | 131 | &:before 132 | top: 100% 133 | left: $arrowSize 134 | border-top-color: $backgroundColor 135 | 136 | &.#{ $themePrefix }-element-attached-bottom.#{ $themePrefix }-element-attached-right.#{ $themePrefix }-target-attached-top .#{ $themePrefix }-content 137 | margin-bottom: $arrowSize 138 | 139 | &:before 140 | top: 100% 141 | right: $arrowSize 142 | border-top-color: $backgroundColor 143 | 144 | // Side corners 145 | 146 | &.#{ $themePrefix }-element-attached-top.#{ $themePrefix }-element-attached-right.#{ $themePrefix }-target-attached-left .#{ $themePrefix }-content 147 | margin-right: $arrowSize 148 | 149 | &:before 150 | top: $arrowSize 151 | left: 100% 152 | border-left-color: $backgroundColor 153 | 154 | &.#{ $themePrefix }-element-attached-top.#{ $themePrefix }-element-attached-left.#{ $themePrefix }-target-attached-right .#{ $themePrefix }-content 155 | margin-left: $arrowSize 156 | 157 | &:before 158 | top: $arrowSize 159 | right: 100% 160 | border-right-color: $backgroundColor 161 | 162 | &.#{ $themePrefix }-element-attached-bottom.#{ $themePrefix }-element-attached-right.#{ $themePrefix }-target-attached-left .#{ $themePrefix }-content 163 | margin-right: $arrowSize 164 | 165 | &:before 166 | bottom: $arrowSize 167 | left: 100% 168 | border-left-color: $backgroundColor 169 | 170 | &.#{ $themePrefix }-element-attached-bottom.#{ $themePrefix }-element-attached-left.#{ $themePrefix }-target-attached-right .#{ $themePrefix }-content 171 | margin-left: $arrowSize 172 | 173 | &:before 174 | bottom: $arrowSize 175 | right: 100% 176 | border-right-color: $backgroundColor 177 | -------------------------------------------------------------------------------- /js/exporting.js: -------------------------------------------------------------------------------- 1 | /* 2 | Highcharts JS v5.0.6 (2016-12-07) 3 | Exporting module 4 | 5 | (c) 2010-2016 Torstein Honsi 6 | 7 | License: www.highcharts.com/license 8 | */ 9 | (function(h){"object"===typeof module&&module.exports?module.exports=h:h(Highcharts)})(function(h){(function(f){var h=f.defaultOptions,n=f.doc,A=f.Chart,u=f.addEvent,F=f.removeEvent,D=f.fireEvent,q=f.createElement,B=f.discardElement,v=f.css,p=f.merge,C=f.pick,k=f.each,r=f.extend,G=f.isTouchDevice,E=f.win,H=f.Renderer.prototype.symbols;r(h.lang,{printChart:"Print chart",downloadPNG:"Download PNG image",downloadJPEG:"Download JPEG image",downloadPDF:"Download PDF document",downloadSVG:"Download SVG vector image", 10 | contextButtonTitle:"Chart context menu"});h.navigation={buttonOptions:{theme:{},symbolSize:14,symbolX:12.5,symbolY:10.5,align:"right",buttonSpacing:3,height:22,verticalAlign:"top",width:24}};p(!0,h.navigation,{menuStyle:{border:"1px solid #999999",background:"#ffffff",padding:"5px 0"},menuItemStyle:{padding:"0.5em 1em",background:"none",color:"#333333",fontSize:G?"14px":"11px",transition:"background 250ms, color 250ms"},menuItemHoverStyle:{background:"#335cad",color:"#ffffff"},buttonOptions:{symbolFill:"#666666", 11 | symbolStroke:"#666666",symbolStrokeWidth:3,theme:{fill:"#ffffff",stroke:"none",padding:5}}});h.exporting={type:"image/png",url:"https://export.highcharts.com/",printMaxWidth:780,scale:2,buttons:{contextButton:{className:"highcharts-contextbutton",menuClassName:"highcharts-contextmenu",symbol:"menu",_titleKey:"contextButtonTitle",menuItems:[{textKey:"printChart",onclick:function(){this.print()}},{separator:!0},{textKey:"downloadPNG",onclick:function(){this.exportChart()}},{textKey:"downloadJPEG",onclick:function(){this.exportChart({type:"image/jpeg"})}}, 12 | {textKey:"downloadPDF",onclick:function(){this.exportChart({type:"application/pdf"})}},{textKey:"downloadSVG",onclick:function(){this.exportChart({type:"image/svg+xml"})}}]}}};f.post=function(a,c,e){var b;a=q("form",p({method:"post",action:a,enctype:"multipart/form-data"},e),{display:"none"},n.body);for(b in c)q("input",{type:"hidden",name:b,value:c[b]},null,a);a.submit();B(a)};r(A.prototype,{sanitizeSVG:function(a,c){if(c&&c.exporting&&c.exporting.allowHTML){var e=a.match(/<\/svg>(.*?$)/);e&&(e= 13 | '\x3cforeignObject x\x3d"0" y\x3d"0" width\x3d"'+c.chart.width+'" height\x3d"'+c.chart.height+'"\x3e\x3cbody xmlns\x3d"http://www.w3.org/1999/xhtml"\x3e'+e[1]+"\x3c/body\x3e\x3c/foreignObject\x3e",a=a.replace("\x3c/svg\x3e",e+"\x3c/svg\x3e"))}a=a.replace(/zIndex="[^"]+"/g,"").replace(/isShadow="[^"]+"/g,"").replace(/symbolName="[^"]+"/g,"").replace(/jQuery[0-9]+="[^"]+"/g,"").replace(/url\(("|")(\S+)("|")\)/g,"url($2)").replace(/url\([^#]+#/g,"url(#").replace(/.*?$/,"\x3c/svg\x3e").replace(/(fill|stroke)="rgba\(([ 0-9]+,[ 0-9]+,[ 0-9]+),([ 0-9\.]+)\)"/g,'$1\x3d"rgb($2)" $1-opacity\x3d"$3"').replace(/ /g,"\u00a0").replace(/­/g,"\u00ad");return a=a.replace(//g,"\x3c$1title\x3e").replace(/height=([^" ]+)/g,'height\x3d"$1"').replace(/width=([^" ]+)/g,'width\x3d"$1"').replace(/hc-svg-href="([^"]+)">/g,'xlink:href\x3d"$1"/\x3e').replace(/ id=([^" >]+)/g,' id\x3d"$1"').replace(/class=([^" >]+)/g, 15 | 'class\x3d"$1"').replace(/ transform /g," ").replace(/:(path|rect)/g,"$1").replace(/style="([^"]+)"/g,function(a){return a.toLowerCase()})},getChartHTML:function(){return this.container.innerHTML},getSVG:function(a){var c,e,b,w,m,g=p(this.options,a);n.createElementNS||(n.createElementNS=function(a,c){return n.createElement(c)});e=q("div",null,{position:"absolute",top:"-9999em",width:this.chartWidth+"px",height:this.chartHeight+"px"},n.body);b=this.renderTo.style.width;m=this.renderTo.style.height; 16 | b=g.exporting.sourceWidth||g.chart.width||/px$/.test(b)&&parseInt(b,10)||600;m=g.exporting.sourceHeight||g.chart.height||/px$/.test(m)&&parseInt(m,10)||400;r(g.chart,{animation:!1,renderTo:e,forExport:!0,renderer:"SVGRenderer",width:b,height:m});g.exporting.enabled=!1;delete g.data;g.series=[];k(this.series,function(a){w=p(a.userOptions,{animation:!1,enableMouseTracking:!1,showCheckbox:!1,visible:a.visible});w.isInternal||g.series.push(w)});k(this.axes,function(a){a.userOptions.internalKey=f.uniqueKey()}); 17 | c=new f.Chart(g,this.callback);a&&k(["xAxis","yAxis","series"],function(b){var d={};a[b]&&(d[b]=a[b],c.update(d))});k(this.axes,function(a){var b=f.find(c.axes,function(b){return b.options.internalKey===a.userOptions.internalKey}),d=a.getExtremes(),e=d.userMin,d=d.userMax;!b||void 0===e&&void 0===d||b.setExtremes(e,d,!0,!1)});b=c.getChartHTML();b=this.sanitizeSVG(b,g);g=null;c.destroy();B(e);return b},getSVGForExport:function(a,c){var e=this.options.exporting;return this.getSVG(p({chart:{borderRadius:0}}, 18 | e.chartOptions,c,{exporting:{sourceWidth:a&&a.sourceWidth||e.sourceWidth,sourceHeight:a&&a.sourceHeight||e.sourceHeight}}))},exportChart:function(a,c){c=this.getSVGForExport(a,c);a=p(this.options.exporting,a);f.post(a.url,{filename:a.filename||"chart",type:a.type,width:a.width||0,scale:a.scale,svg:c},a.formAttributes)},print:function(){var a=this,c=a.container,e=[],b=c.parentNode,f=n.body,m=f.childNodes,g=a.options.exporting.printMaxWidth,d,t;if(!a.isPrinting){a.isPrinting=!0;a.pointer.reset(null, 19 | 0);D(a,"beforePrint");if(t=g&&a.chartWidth>g)d=[a.options.chart.width,void 0,!1],a.setSize(g,void 0,!1);k(m,function(a,b){1===a.nodeType&&(e[b]=a.style.display,a.style.display="none")});f.appendChild(c);E.focus();E.print();setTimeout(function(){b.appendChild(c);k(m,function(a,b){1===a.nodeType&&(a.style.display=e[b])});a.isPrinting=!1;t&&a.setSize.apply(a,d);D(a,"afterPrint")},1E3)}},contextMenu:function(a,c,e,b,f,m,g){var d=this,t=d.options.navigation,w=d.chartWidth,h=d.chartHeight,p="cache-"+a, 20 | l=d[p],x=Math.max(f,m),y,z;l||(d[p]=l=q("div",{className:a},{position:"absolute",zIndex:1E3,padding:x+"px"},d.container),y=q("div",{className:"highcharts-menu"},null,l),v(y,r({MozBoxShadow:"3px 3px 10px #888",WebkitBoxShadow:"3px 3px 10px #888",boxShadow:"3px 3px 10px #888"},t.menuStyle)),z=function(){v(l,{display:"none"});g&&g.setState(0);d.openMenu=!1},u(l,"mouseleave",function(){l.hideTimer=setTimeout(z,500)}),u(l,"mouseenter",function(){clearTimeout(l.hideTimer)}),p=u(n,"mouseup",function(b){d.pointer.inClass(b.target, 21 | a)||z()}),u(d,"destroy",p),k(c,function(a){if(a){var b;a.separator?b=q("hr",null,null,y):(b=q("div",{className:"highcharts-menu-item",onclick:function(b){b&&b.stopPropagation();z();a.onclick&&a.onclick.apply(d,arguments)},innerHTML:a.text||d.options.lang[a.textKey]},null,y),b.onmouseover=function(){v(this,t.menuItemHoverStyle)},b.onmouseout=function(){v(this,t.menuItemStyle)},v(b,r({cursor:"pointer"},t.menuItemStyle)));d.exportDivElements.push(b)}}),d.exportDivElements.push(y,l),d.exportMenuWidth= 22 | l.offsetWidth,d.exportMenuHeight=l.offsetHeight);c={display:"block"};e+d.exportMenuWidth>w?c.right=w-e-f-x+"px":c.left=e-x+"px";b+m+d.exportMenuHeight>h&&"top"!==g.alignOptions.verticalAlign?c.bottom=h-b-x+"px":c.top=b+m-x+"px";v(l,c);d.openMenu=!0},addButton:function(a){var c=this,e=c.renderer,b=p(c.options.navigation.buttonOptions,a),f=b.onclick,m=b.menuItems,g,d,h=b.symbolSize||12;c.btnCount||(c.btnCount=0);c.exportDivElements||(c.exportDivElements=[],c.exportSVGElements=[]);if(!1!==b.enabled){var k= 23 | b.theme,n=k.states,q=n&&n.hover,n=n&&n.select,l;delete k.states;f?l=function(a){a.stopPropagation();f.call(c,a)}:m&&(l=function(){c.contextMenu(d.menuClassName,m,d.translateX,d.translateY,d.width,d.height,d);d.setState(2)});b.text&&b.symbol?k.paddingLeft=C(k.paddingLeft,25):b.text||r(k,{width:b.width,height:b.height,padding:0});d=e.button(b.text,0,0,l,k,q,n).addClass(a.className).attr({"stroke-linecap":"round",title:c.options.lang[b._titleKey],zIndex:3});d.menuClassName=a.menuClassName||"highcharts-menu-"+ 24 | c.btnCount++;b.symbol&&(g=e.symbol(b.symbol,b.symbolX-h/2,b.symbolY-h/2,h,h).addClass("highcharts-button-symbol").attr({zIndex:1}).add(d),g.attr({stroke:b.symbolStroke,fill:b.symbolFill,"stroke-width":b.symbolStrokeWidth||1}));d.add().align(r(b,{width:d.width,x:C(b.x,c.buttonOffset)}),!0,"spacingBox");c.buttonOffset+=(d.width+b.buttonSpacing)*("right"===b.align?-1:1);c.exportSVGElements.push(d,g)}},destroyExport:function(a){var c=a?a.target:this;a=c.exportSVGElements;var e=c.exportDivElements;a&& 25 | (k(a,function(a,e){a&&(a.onclick=a.ontouchstart=null,c.exportSVGElements[e]=a.destroy())}),a.length=0);e&&(k(e,function(a,e){clearTimeout(a.hideTimer);F(a,"mouseleave");c.exportDivElements[e]=a.onmouseout=a.onmouseover=a.ontouchstart=a.onclick=null;B(a)}),e.length=0)}});H.menu=function(a,c,e,b){return["M",a,c+2.5,"L",a+e,c+2.5,"M",a,c+b/2+.5,"L",a+e,c+b/2+.5,"M",a,c+b-1.5,"L",a+e,c+b-1.5]};A.prototype.renderExporting=function(){var a,c=this.options.exporting,e=c.buttons,b=this.isDirtyExporting||!this.exportSVGElements; 26 | this.buttonOffset=0;this.isDirtyExporting&&this.destroyExport();if(b&&!1!==c.enabled){for(a in e)this.addButton(e[a]);this.isDirtyExporting=!1}u(this,"destroy",this.destroyExport)};A.prototype.callbacks.push(function(a){a.renderExporting();u(a,"redraw",a.renderExporting);k(["exporting","navigation"],function(c){a[c]={update:function(e,b){a.isDirtyExporting=!0;p(!0,a.options[c],e);C(b,!0)&&a.redraw()}}})})})(h)}); 27 | -------------------------------------------------------------------------------- /js/visualizer.js: -------------------------------------------------------------------------------- 1 | var websocketIP = "192.168.42.1"; 2 | var askCamerasCameraPosition = "cmd=camerasposition" 3 | 4 | var wsFailedAlert = document.getElementById('ws_failed_alert'); 5 | var wsSuccessAlert = document.getElementById('ws_success_alert'); 6 | var calibrating = false; 7 | var socket; 8 | var calibrationBtn = document.getElementById('calibrationBtn'); 9 | var count = 0; 10 | var nombreCamera = 0; 11 | var countTable = [0]; 12 | var selectedTable = [false]; 13 | var cameraMac = []; 14 | 15 | var tagPositions = {}; 16 | var chart; 17 | var cameraNumberPosition = 0; 18 | var maxX = 3; 19 | var maxY = 3; 20 | var maxZ = 3; 21 | var tagTracked = new Map(); 22 | /* 23 | * On window load, open a websocket between the window and the server 24 | * Create a master on opening window 25 | */ 26 | 27 | window.onload=function(){ 28 | drawChart(); 29 | createWebsocket(); 30 | window.addEventListener('beforeunload', function(event) { 31 | //console.log('I am the 1st one.'); 32 | }); 33 | 34 | window.addEventListener('unload', function(event) { 35 | //console.log('I am the 3rd one.'); 36 | }); 37 | } 38 | 39 | 40 | 41 | function assingAllTags(){ 42 | var messageMac = "cmd=mac&uid=1"; 43 | sendMessage(socket, messageMac); 44 | var message = "cmd=assignalltag"; 45 | sendMessage(socket, message); 46 | sendMessage(socket,"cmd=camerasposition"); 47 | //setTimeout(function(){sendMessage(socket, message);}, 5000); 48 | } 49 | 50 | function clone(obj) { 51 | if (null == obj || "object" != typeof obj) return obj; 52 | var copy = obj.constructor(); 53 | for (var attr in obj) { 54 | if (obj.hasOwnProperty(attr)) copy[attr] = obj[attr]; 55 | } 56 | return copy; 57 | } 58 | 59 | var index = 0; 60 | 61 | function updateTagPosition(message){ 62 | for (var i = 0; i < message.length; i++ ) { 63 | if(!tagTracked.has(message[i].uid)){ 64 | tagTracked.set(message[i].uid, true) 65 | chart.addSeries({ 66 | name: 'Tag ' + message[i].uid, 67 | colorByPoint: true, 68 | data: [[parseFloat(message[i].x), parseFloat(message[i].z), parseFloat(message[i].y)]] 69 | }, false); 70 | chart.redraw(); 71 | } 72 | else { 73 | if(index % 10 == 0){ 74 | chart.series[i].update({ 75 | name: 'Tag ' + message[i].uid, 76 | colorByPoint: true, 77 | data: [[parseFloat(message[i].x), parseFloat(message[i].z), parseFloat(message[i].y)]] 78 | }, false); 79 | chart.redraw(); 80 | } 81 | } 82 | } 83 | 84 | index++; 85 | } 86 | 87 | function addCameraPosition(message){ 88 | for (var i = 0; i < cameraNumberPosition; i++ ) { 89 | if(i > chart.series.length){ 90 | chart.addSeries({ 91 | name: 'Camera ' + message[i].uid, 92 | colorByPoint: false, 93 | data: [[parseFloat(message[i].x), parseFloat(message[i].y), parseFloat(message[i].z)]] 94 | }, false); 95 | } 96 | else { 97 | chart.series[i].update({ 98 | name: 'Camera ' + message[i].uid, 99 | colorByPoint: false, 100 | data: [[parseFloat(message[i].x), parseFloat(message[i].y), parseFloat(message[i].z)]] 101 | }, false); 102 | } 103 | } 104 | chart.redraw(); 105 | } 106 | 107 | function drawChart(){ 108 | // Give the points a 3D feel by adding a radial gradient 109 | Highcharts.getOptions().colors = $.map(Highcharts.getOptions().colors, function (color) { 110 | return { 111 | radialGradient: { 112 | cx: 0.4, 113 | cy: 0.3, 114 | r: 0.5 115 | }, 116 | stops: [ 117 | [0, color], 118 | [1, Highcharts.Color(color).brighten(-0.2).get('rgb')] 119 | ] 120 | }; 121 | }); 122 | 123 | // Set up the chart 124 | chart = new Highcharts.Chart({ 125 | chart: { 126 | renderTo: 'graph', 127 | margin: 100, 128 | type: 'scatter', 129 | // zoomType: 'xy', 130 | options3d: { 131 | enabled: true, 132 | alpha: 10, 133 | beta: 30, 134 | depth: 250, 135 | viewDistance: 5, 136 | fitToPlot: false, 137 | frame: { 138 | bottom: { size: 1, color: 'rgba(0,0,0,0.02)' }, 139 | back: { size: 1, color: 'rgba(0,0,0,0.04)' }, 140 | side: { size: 1, color: 'rgba(0,0,0,0.06)' } 141 | } 142 | } 143 | }, 144 | title: { 145 | text: 'Tag Positions' 146 | }, 147 | subtitle: { 148 | text: 'Click and drag the plot area to rotate in space' 149 | }, 150 | tooltip: { 151 | enabled: false, 152 | crosshairs: true 153 | }, 154 | plotOptions: { 155 | scatter: { 156 | width: 5, 157 | height: 5, 158 | depth: 1 159 | }, 160 | series: { 161 | dataLabels: { 162 | enabled: true, 163 | inside: false, 164 | overflow: 'none', 165 | crop: true, 166 | shape: 'callout', 167 | backgroundColor:'rgba(0,0,0,0.8)', 168 | borderColor: 'rgba(0,0,0,0.9)', 169 | color: 'rgba(255,255,255,0.75)', 170 | borderWidth: .5, 171 | borderRadius: 5, 172 | y: -10, 173 | style: { 174 | fontFamily: 'Helvetica, sans-serif', 175 | fontSize: '10px', 176 | fontWeight: 'normal', 177 | textShadow: 'none' 178 | }, 179 | formatter: function() { 180 | return ''+this.series.name+'' 181 | +'
X: '+ this.x+''+'
Y: '+ this.point.options.z+''+'
Z: '+ this.y+''; 182 | } 183 | } 184 | } 185 | }, 186 | yAxis: { 187 | min: -5, 188 | max: 5, 189 | title: "y" 190 | }, 191 | xAxis: { 192 | min: -5, 193 | max: 5, 194 | gridLineWidth: 1, 195 | title: "x" 196 | }, 197 | zAxis: { 198 | min: -5, 199 | max: 5, 200 | showFirstLabel: false, 201 | title: "z" 202 | }, 203 | legend: { 204 | enabled: false 205 | }, 206 | series: [{ 207 | name: 'Camera', 208 | colorByPoint: true 209 | },{ 210 | name: 'Tag', 211 | colorByPoint: true 212 | }] 213 | }); 214 | 215 | 216 | // Add mouse events for rotation 217 | $(chart.container).on('mousedown.hc touchstart.hc', function (eStart) { 218 | eStart = chart.pointer.normalize(eStart); 219 | 220 | var posX = eStart.pageX, 221 | posY = eStart.pageY, 222 | alpha = chart.options.chart.options3d.alpha, 223 | beta = chart.options.chart.options3d.beta, 224 | newAlpha, 225 | newBeta, 226 | sensitivity = 5; // lower is more sensitive 227 | 228 | $(document).on({ 229 | 'mousemove.hc touchdrag.hc': function (e) { 230 | // Run beta 231 | newBeta = beta + (posX - e.pageX) / sensitivity; 232 | chart.options.chart.options3d.beta = newBeta; 233 | 234 | // Run alpha 235 | newAlpha = alpha + (e.pageY - posY) / sensitivity; 236 | chart.options.chart.options3d.alpha = newAlpha; 237 | 238 | chart.redraw(false); 239 | }, 240 | 'mouseup touchend': function () { 241 | $(document).off('.hc'); 242 | } 243 | }); 244 | }); 245 | 246 | } 247 | 248 | 249 | 250 | window.onclose=function(){ 251 | socket.close(); 252 | console.log("connection closed"); 253 | } 254 | 255 | function sendMessage(websocket, message){ 256 | websocket.send(message); 257 | } 258 | 259 | function getCamerasPosition(){ 260 | if(!calibrating) 261 | socket.send(askCamerasPosition); 262 | } 263 | 264 | function createWebsocket(){ 265 | socket = new WebSocket('ws://' + websocketIP + ':7777/user/'); 266 | 267 | socket.onopen = function(event) { 268 | wsFailedAlert.style.display = "none"; 269 | wsSuccessAlert.style.display = "block"; 270 | assingAllTags(); 271 | }; 272 | // Handle any errors that occur. 273 | socket.onerror = function(error) { 274 | wsFailedAlert.style.display = "block"; 275 | wsSuccessAlert.style.display = "none"; 276 | console.log('WebSocket Error: ' + error); 277 | } 278 | // Handle messages sent by the server. 279 | socket.onmessage = function(event) { 280 | //getting the time of the message 281 | var message = event.data; 282 | //console.log(message); 283 | parseMessage(message); 284 | } 285 | } 286 | -------------------------------------------------------------------------------- /js/keyboard.js: -------------------------------------------------------------------------------- 1 | KEY_SPACE = 32; 2 | REMAP_KEY_T = 5019; 3 | KEY_ESCAPE = 27; 4 | var CALIBRATING = true; 5 | var nextCalibrationIndex = 0; 6 | var calibrationCount = 0; 7 | var calibrationDetected = 0; 8 | var calibrationViewActivated = false; 9 | var pingMessage = "cmd=pingcalibrationtag"; 10 | var enablePingAgain = false; 11 | var tagConnected = true; 12 | document.onkeydown = applyKey; 13 | document.addEventListener('keypress', stopEscAction, false); 14 | 15 | function handleKeySpace(winObj){ 16 | 17 | hideCalibrationMessages(); 18 | if(tagConnected){ 19 | if(calibrationViewActivated){ 20 | // --- Display Message 21 | if(calibrationPoint.length > 0){ 22 | if(nextCalibrationIndex < calibrationPoint.length ){ 23 | var boutonNext = document.getElementById("next-point-btn"); 24 | if(nextCalibrationIndex > 0){ 25 | sendMessage(socket, pingMessage); 26 | document.getElementById("calibration-inprocess").style.display = "block"; 27 | if(calibrationCount == calibrationDetected){ 28 | calibrationCount++; 29 | } 30 | }else{ 31 | nextCalibrationIndex++; 32 | showNextCalibrationPoint(); 33 | boutonNext.style.display = "block"; 34 | 35 | } 36 | enablePingAgain = true; 37 | if(nextCalibrationIndex == calibrationPoint.length){ 38 | boutonNext.style.display = "None"; 39 | } 40 | }else{ 41 | if(nextCalibrationIndex == calibrationPoint.length){ 42 | if(calibrationDetected == calibrationCount){ 43 | //document.getElementById("calibration-inprocess").style.display = "block"; 44 | calibrationCount++; 45 | sendMessage(socket, pingMessage); 46 | } 47 | if(!enablePingAgain){ 48 | enablePingAgain = true; 49 | } 50 | document.getElementById("calibration-inprocess").style.display = "block"; 51 | }else{ 52 | console.log("Ping non possible"); 53 | } 54 | } 55 | }else{ 56 | masquerAffichageMessage(); 57 | } 58 | // 2° --- Map the keyCode in another keyCode not used 59 | //winObj.keyCode = intKeyCode ;//= REMAP_KEY_T; 60 | //winObj.returnValue = false; 61 | return false; 62 | 63 | }else{ 64 | calibrationViewActivated = true; 65 | if(nextCalibrationIndex != 0){ 66 | affichageMessage(); 67 | }else{ 68 | nextCalibrationIndex++; 69 | showNextCalibrationPoint(); 70 | } 71 | } 72 | }else{ 73 | var text = "Connect a Tag !"; 74 | document.getElementById("calibration-failed").innerHTML = "ERROR"; 75 | document.getElementById("calibration-failed").style.display = "block"; 76 | fullScreenMessage.innerHTML = text; 77 | affichageMessage(); 78 | calibrationMessage.display = "none"; 79 | } 80 | } 81 | 82 | function updateCalibration(ping){ 83 | hideCalibrationMessages(); 84 | if(tagConnected){ 85 | if(calibrationViewActivated){ 86 | // --- Display Message 87 | if(calibrationPoint.length > 0){ 88 | if(nextCalibrationIndex < calibrationPoint.length ){ 89 | var boutonNext = document.getElementById("next-point-btn"); 90 | if(nextCalibrationIndex > 0){ 91 | document.getElementById("calibration-inprocess").style.display = "block"; 92 | if(calibrationCount == calibrationDetected){ 93 | calibrationCount++; 94 | } 95 | }else{ 96 | nextCalibrationIndex++; 97 | showNextCalibrationPoint(); 98 | boutonNext.style.display = "block"; 99 | 100 | } 101 | enablePingAgain = true; 102 | if(nextCalibrationIndex == calibrationPoint.length){ 103 | boutonNext.style.display = "None"; 104 | } 105 | }else{ 106 | if(nextCalibrationIndex == calibrationPoint.length){ 107 | if(calibrationDetected == calibrationCount){ 108 | //document.getElementById("calibration-inprocess").style.display = "block"; 109 | calibrationCount++; 110 | } 111 | if(!enablePingAgain){ 112 | enablePingAgain = true; 113 | } 114 | document.getElementById("calibration-inprocess").style.display = "block"; 115 | }else{ 116 | console.log("Ping non possible"); 117 | } 118 | } 119 | }else{ 120 | masquerAffichageMessage(); 121 | } 122 | 123 | return false; 124 | 125 | }else{ 126 | calibrationViewActivated = true; 127 | if(nextCalibrationIndex != 0){ 128 | affichageMessage(); 129 | }else{ 130 | if(ping) 131 | calibrationCount++; 132 | nextCalibrationIndex++; 133 | showNextCalibrationPoint(); 134 | } 135 | } 136 | }else{ 137 | var text = "Connect a Tag !"; 138 | document.getElementById("calibration-failed").innerHTML = "ERROR"; 139 | document.getElementById("calibration-failed").style.display = "block"; 140 | fullScreenMessage.innerHTML = text; 141 | affichageMessage(); 142 | calibrationMessage.display = "none"; 143 | } 144 | } 145 | 146 | function applyKey (_event_){ 147 | //If calibration mode is on we enable the space press action 148 | if(CALIBRATING){ 149 | // --- Retrieve event object from current web explorer 150 | var winObj = checkEventObj(_event_); 151 | 152 | var intKeyCode = winObj.keyCode; 153 | // 1° --- Access with KEY SPACE 154 | if (intKeyCode == KEY_SPACE){ 155 | handleKeySpace(winObj); 156 | }else{ 157 | if(intKeyCode == KEY_ESCAPE){ 158 | if(calibrationViewActivated){ 159 | masquerAffichageMessage(); 160 | } 161 | } 162 | } 163 | }else{ 164 | console.log("Not Calibrating"); 165 | } 166 | } 167 | 168 | function checkEventObj ( _event_ ){ 169 | // --- IE explorer 170 | if ( window.event ) 171 | return window.event; 172 | // --- Netscape and other explorers 173 | else 174 | return _event_; 175 | } 176 | 177 | function masquerAffichageMessage(){ 178 | document.getElementById("calibrationMessage").style.display = "none"; 179 | document.getElementById("messageScreen").style.display = "none"; 180 | document.getElementById("cover").style.display = "none"; 181 | calibrationViewActivated = false 182 | } 183 | 184 | function hideCalibrationMessages(){ 185 | document.getElementById("calibration-failed").style.display = "none"; 186 | document.getElementById("calibration-success").style.display = "none"; 187 | document.getElementById("calibration-inprocess").style.display = "none"; 188 | 189 | } 190 | function affichageMessage(){ 191 | document.getElementById("calibrationMessage").style.display = "block"; 192 | document.getElementById("messageScreen").style.display = "block"; 193 | document.getElementById("cover").style.display = "block"; 194 | } 195 | 196 | function showNextCalibrationPoint(){ 197 | if(calibrationCount < calibrationPoint.length){ 198 | var calibrationPosition = calibrationPoint[calibrationCount]; 199 | var message = ""; 200 | if(calibrationPosition.length == 3){ 201 | calibrationMessage.display = "Bring Tag to Position :"; 202 | message += "X : " + calibrationPosition[0] + " - "; 203 | message += "Y : " + calibrationPosition[1] + " - "; 204 | message += "Z : " + calibrationPosition[2]; 205 | fullScreenMessage.innerHTML = message; 206 | affichageMessage(); 207 | } 208 | if(calibrationCount == calibrationPoint.length - 1) 209 | document.getElementById("next-point-btn").style.display = "none"; 210 | }else{ 211 | if(calibrationDetected == nextCalibrationIndex){ 212 | var calibrationPosition = calibrationPoint[calibrationCount - 1]; 213 | var message = ""; 214 | if(calibrationPosition.length == 3){ 215 | calibrationMessage.display = "Bring Tag to Position :"; 216 | message += "X : " + calibrationPosition[0] + " - "; 217 | message += "Y : " + calibrationPosition[1] + " - "; 218 | message += "Z : " + calibrationPosition[2]; 219 | fullScreenMessage.innerHTML = message; 220 | affichageMessage(); 221 | } 222 | }else{ 223 | affichageMessage(); 224 | var text = "Calibration Finished !"; 225 | calibrationMessage.display = "none"; 226 | fullScreenMessage.innerHTML = text; 227 | stopCalibration(); 228 | } 229 | } 230 | } 231 | 232 | function stopEscAction(evt) { 233 | var charCode = evt.charCode; 234 | if(charCode == KEY_ESCAPE){ 235 | if(calibrationViewActivated) 236 | evt.preventDefault(); 237 | } 238 | } 239 | -------------------------------------------------------------------------------- /js/utils.js: -------------------------------------------------------------------------------- 1 | let TetherBase; 2 | if (typeof TetherBase === 'undefined') { 3 | TetherBase = {modules: []}; 4 | } 5 | 6 | let zeroElement = null; 7 | 8 | // Same as native getBoundingClientRect, except it takes into account parent offsets 9 | // if the element lies within a nested document ( or