client/annotviz/app/js/annotstimeline.js
changeset 124 b5697bcdbaff
parent 123 d8ef840eaf68
child 125 f9dd7bfed997
child 127 0386fb9efe27
equal deleted inserted replaced
123:d8ef840eaf68 124:b5697bcdbaff
    14 var defaultOptions = {
    14 var defaultOptions = {
    15     logger: undefined,
    15     logger: undefined,
    16     intervalWidth: 10,
    16     intervalWidth: 10,
    17     intervalHeight: 5,
    17     intervalHeight: 5,
    18     maxCellHeight: 200,
    18     maxCellHeight: 200,
    19     radius: 300
    19     radius: 300,
       
    20     serverUrl: 'http://127.0.0.1:8080',
       
    21     channel: 'ANNOT',
       
    22     maxPages: 1000,
       
    23     //eventCode:
    20 };
    24 };
    21 
    25 
    22 
    26 
    23 function AnnotsTimeLine(options){
    27 function AnnotsTimeLine(options){
    24     var _this = this;
    28     var _this = this;
    37     this.height = opts.height;
    41     this.height = opts.height;
    38     this.intervalHeight = opts.intervalHeight;
    42     this.intervalHeight = opts.intervalHeight;
    39     this.intervalWidth = opts.intervalWidth;
    43     this.intervalWidth = opts.intervalWidth;
    40     this.maxCellHeight = opts.maxCellHeight;
    44     this.maxCellHeight = opts.maxCellHeight;
    41     this.annotCategories = opts.annotCategories;
    45     this.annotCategories = opts.annotCategories;
    42     
    46 
       
    47     this.startTs = options.startTs || Date.now();
       
    48 
    43     this.circleX = opts.circleX || (this.width/2);
    49     this.circleX = opts.circleX || (this.width/2);
    44     this.circleY = opts.circleY || (this.height/2);
    50     this.circleY = opts.circleY || (this.height/2);
    45     this.radius = opts.radius;
    51     this.radius = opts.radius;
    46     this.perimeter = 2*Math.PI* this.radius;
    52     this.perimeter = 2*Math.PI* this.radius;
    47     this.intervalDuration = (this.intervalWidth * this.duration / this.perimeter);
    53     this.intervalDuration = (this.intervalWidth * this.duration / this.perimeter);
    48 
    54 
    49     var currentTime = Date.now() + 3600*1000;
    55     var channel = opts.channel;
       
    56     var eventCode = opts.eventCode;
       
    57     var serverUrl = opts.serverUrl;
       
    58     var maxPages = opts.maxPages;
       
    59 
    50     var totalIndex = Math.floor(this.perimeter/this.intervalWidth);
    60     var totalIndex = Math.floor(this.perimeter/this.intervalWidth);
    51 
    61 
    52     this.cells = []
    62     this.cells = [];
    53     for (var i=0; i<(this.perimeter/this.intervalWidth) ; i++){
    63     for (var i=0; i<(this.perimeter/this.intervalWidth) ; i++){
    54     	this.cells[i] = [];
    64     	this.cells[i] = [];
    55     	this.cells[i].i = i;
    65     	this.cells[i].i = i;
    56     	this.cells[i].totalAnnots = 0;
    66     	this.cells[i].totalAnnots = 0;
    57     	this.cells[i].categories = {};
    67     	this.cells[i].categories = {};
    61     var stageView = opts.stageView;
    71     var stageView = opts.stageView;
    62 
    72 
    63     //draw the base - circle and line to locate the scene
    73     //draw the base - circle and line to locate the scene
    64     var graphics = new PIXI.Graphics();
    74     var graphics = new PIXI.Graphics();
    65     graphics.lineStyle(2, 0x646464)
    75     graphics.lineStyle(2, 0x646464)
    66     	.drawCircle(this.circleX, this.circleY, this.radius - 3)
    76         .drawCircle(this.circleX, this.circleY, this.radius - 3)
    67     	.lineStyle(1, 0xD7D7D7)
    77         .lineStyle(1, 0xD7D7D7)
    68     	.drawCircle(this.circleX, this.circleY, this.radius*2/3)
    78         .drawCircle(this.circleX, this.circleY, this.radius*2/3)
    69     	.drawCircle(this.circleX, this.circleY, this.radius/3)
    79         .drawCircle(this.circleX, this.circleY, this.radius/3)
    70     	.lineStyle(1, 0x646464)
    80         .lineStyle(1, 0x646464)
    71     	.moveTo(this.circleX, this.circleY - (this.radius/3)/2)
    81         .moveTo(this.circleX, this.circleY - (this.radius/3)/2)
    72     	.lineTo(this.circleX, this.circleY - this.radius - this.maxCellHeight - 10)
    82         .lineTo(this.circleX, this.circleY - this.radius - this.maxCellHeight - 10)
    73     	.endFill()
    83         .endFill();
    74     this.container.addChild(graphics);
    84     this.container.addChild(graphics);
    75 
    85 
    76     //set time text
    86     //set time text
    77     //TODO : move this to annotsvizview
    87     //TODO : move this to annotsvizview
    78     var currentTimeText = new PIXI.Text("-- : -- : --", { font: '18pt Gothic Standard', fill: '#646464' });
    88     var currentTimeText = new PIXI.Text('-- : -- : --', { font: '18pt Gothic Standard', fill: '#646464' });
    79     currentTimeText.x = this.circleX - currentTimeText.width/2;
    89     currentTimeText.x = this.circleX - currentTimeText.width/2;
    80     currentTimeText.y = this.circleY - currentTimeText.height/2;
    90     currentTimeText.y = this.circleY - currentTimeText.height/2;
    81     this.container.addChild(currentTimeText);
    91     this.container.addChild(currentTimeText);
    82 
    92 
    83     stageView.registerComponent(this);
    93     stageView.registerComponent(this);
    84 
    94 
       
    95     var loadArchives = function() {
       
    96         //start timeBegin end startTime
       
    97         //query -> need channel + eventCode
       
    98         //iterate over data fill cells
       
    99         var startTs = _this.timeBegin;
       
   100         var endTs = _this.startTs;
       
   101 
       
   102         var url = serverUrl + '/p/api/v1/annotation';
       
   103         var filters = [
       
   104             { name: 'ts', op: '>', val: new Date(startTs).toISOString()}, //start
       
   105             { name: 'ts', op: '<=', val: new Date(endTs).toISOString()}, //end
       
   106             { name: 'channel', op: '==', val: channel}, //channel
       
   107             { name: 'event_code', op: '==', val: eventCode} //eventcode
       
   108         ];
       
   109 
       
   110         console.log(JSON.stringify({filters:filters}));
       
   111 
       
   112         url = url + '?q=' + JSON.stringify({filters:filters});
       
   113 
       
   114         var totalPage = 1;
       
   115         var currentPage = 1;
       
   116 
       
   117         var processResFunction = function(res) {
       
   118 
       
   119             if(res) {
       
   120                 var data = res.target.json;
       
   121                 /*jshint -W069 */
       
   122                 totalPage = Math.min(maxPages,parseInt(data['total_pages']));
       
   123                 console.log('DATA', data);
       
   124                 data.objects.forEach(function(annotation) {
       
   125                     _this.addAnnot(annotation);
       
   126                 });
       
   127             }
       
   128             if(currentPage <= totalPage) {
       
   129                 var jsonLoader = new PIXI.JsonLoader(url+'&page='+currentPage, true);
       
   130                 jsonLoader.on('loaded', processResFunction);
       
   131                 jsonLoader.load();
       
   132                 currentPage++;
       
   133             }
       
   134         };
       
   135         processResFunction();
       
   136 
       
   137     };
       
   138 
    85     //Add Annotation to the TimeLine
   139     //Add Annotation to the TimeLine
    86     this.addAnnot = function(data){
   140     this.addAnnot = function(data){
    87     	
   141 
    88     	var ts = Date.parse(data.ts);
   142     	var ts = Date.parse(data.ts);
    89     	var colorsDef;
   143     	var colorsDef;
    90     	_(this.annotCategories).eachRight(function(cdef) {
   144     	_(this.annotCategories).eachRight(function(cdef) {
    91             if(cdef.ts < ts) {
   145             if(cdef.ts < ts) {
    92                 colorsDef = cdef;
   146                 colorsDef = cdef;
    93                 return false;
   147                 return false;
    94             }
   148             }
    95         });
   149         });
    96     	
   150 
    97     	if (this.timeEnd > Date.parse(data.ts)){
   151     	if (this.timeEnd > ts){
    98 	    	var i = Math.floor(((Date.parse(data.ts) + 3600*1000) - this.timeBegin)/(1000*this.intervalDuration));
   152 	    	var i = Math.floor((ts - this.timeBegin)/(1000*this.intervalDuration));
    99 
   153 
   100 	    	if (typeof(this.cells[i].graphics) === 'undefined'){
   154 	    	if (typeof(this.cells[i].graphics) === 'undefined'){
   101 	    		this.initCell(this.cells[i], colorsDef);
   155 	    		this.initCell(this.cells[i], colorsDef);
   102 	    	}
   156 	    	}
   103 	    	
   157 
   104 	    	if (typeof(colorsDef.colors[data.content.category.code]) !== 'undefined'){
   158 	    	if (typeof(colorsDef.colors[data.content.category.code]) !== 'undefined'){
   105 	    		var annotCode = data.content.category.code;
   159 	    		var annotCode = data.content.category.code;
   106 	    	} else {
   160 	    	} else {
   107 	    		var annotCode = 'default';
   161 	    		var annotCode = 'default';
   108 	    	}
   162 	    	}
   109 	    	
   163 
   110 			this.cells[i].categories[annotCode].count += 1;
   164 			this.cells[i].categories[annotCode].count += 1;
   111 			this.cells[i].totalAnnots +=1;
   165 			this.cells[i].totalAnnots +=1;
   112 			this.redrawCell(this.cells[i], colorsDef);
   166 			this.redrawCell(this.cells[i], colorsDef);
   113     	}
   167     	}
   114     };
   168     };
   115 
   169 
   116     this.initTimeTexts = function() {
   170     this.initTimeTexts = function() {
   117 	    var tBeg = new PIXI.Text(Utils.formatTime(this.timeBegin), { font: '12pt Gothic Standard', fill: '#646464' });
   171         var tBeg = new PIXI.Text(Utils.formatTime(this.timeBegin), { font: '12pt Gothic Standard', fill: '#646464' });
   118 	    tBeg.x = this.circleX + 15;
   172         tBeg.x = this.circleX + 15;
   119 	    tBeg.y = this.circleY - this.radius - this.maxCellHeight - 10;
   173         tBeg.y = this.circleY - this.radius - this.maxCellHeight - 10;
   120 	    this.container.addChild(tBeg);
   174         this.container.addChild(tBeg);
   121 
   175 
   122 	    var tEnd = new PIXI.Text(Utils.formatTime(this.timeEnd), { font: '12pt Gothic Standard', fill: '#646464' });
   176         var tEnd = new PIXI.Text(Utils.formatTime(this.timeEnd), { font: '12pt Gothic Standard', fill: '#646464' });
   123 	    tEnd.x = this.circleX - 15 - tEnd.width;
   177         tEnd.x = this.circleX - 15 - tEnd.width;
   124 	    tEnd.y = this.circleY - this.radius - this.maxCellHeight - 10;
   178         tEnd.y = this.circleY - this.radius - this.maxCellHeight - 10;
   125 	    this.container.addChild(tEnd);
   179         this.container.addChild(tEnd);
   126 
   180 
   127 	    var t15 = new PIXI.Text(Utils.formatTime(((this.timeEnd - this.timeBegin)/4) + this.timeBegin), { font: '12pt Gothic Standard', fill: '#646464' });
   181         var t15 = new PIXI.Text(Utils.formatTime(((this.timeEnd - this.timeBegin)/4) + this.timeBegin), { font: '12pt Gothic Standard', fill: '#646464' });
   128 	    t15.x = this.circleX + this.radius + this.maxCellHeight + 10 ;
   182         t15.x = this.circleX + this.radius + this.maxCellHeight + 10 ;
   129 	    t15.y = this.circleY - t15.height;
   183         t15.y = this.circleY - t15.height;
   130 	    t15.rotation = Math.PI /2;
   184         t15.rotation = Math.PI /2;
   131 	    this.container.addChild(t15);
   185         this.container.addChild(t15);
   132 
   186 
   133 	    var t30 = new PIXI.Text(Utils.formatTime(((this.timeEnd - this.timeBegin)/2) + this.timeBegin), { font: '12pt Gothic Standard', fill: '#646464' });
   187         var t30 = new PIXI.Text(Utils.formatTime(((this.timeEnd - this.timeBegin)/2) + this.timeBegin), { font: '12pt Gothic Standard', fill: '#646464' });
   134 	    t30.x = this.circleX - t30.width/2;
   188         t30.x = this.circleX - t30.width/2;
   135 	    t30.y = this.circleY + this.radius + this.maxCellHeight - 2;
   189         t30.y = this.circleY + this.radius + this.maxCellHeight - 2;
   136 	    this.container.addChild(t30);
   190         this.container.addChild(t30);
   137 
   191 
   138 	    var t45 = new PIXI.Text(Utils.formatTime(((this.timeEnd - this.timeBegin)*3/4) + this.timeBegin), { font: '12pt Gothic Standard', fill: '#646464' });
   192         var t45 = new PIXI.Text(Utils.formatTime(((this.timeEnd - this.timeBegin)*3/4) + this.timeBegin), { font: '12pt Gothic Standard', fill: '#646464' });
   139 	    t45.x = this.circleX - this.radius - this.maxCellHeight - 10 ;
   193         t45.x = this.circleX - this.radius - this.maxCellHeight - 10 ;
   140 	    t45.y = this.circleY + t15.height;
   194         t45.y = this.circleY + t15.height;
   141 	    t45.rotation = -Math.PI/2;
   195         t45.rotation = -Math.PI/2;
   142 	    this.container.addChild(t45);
   196         this.container.addChild(t45);
   143     }
   197     };
   144 
   198 
   145     //Draw the cellule
   199     //Draw the cellule
   146     this.redrawCell = function(cell, colorsDef){
   200     this.redrawCell = function(cell, colorsDef){
   147     	
   201 
   148     	var y = 0;
   202     	var y = 0;
   149 
   203 
   150     	//Check if total height is higher than Max Cell Height
   204         //Check if total height is higher than Max Cell Height
   151     	if ((cell.totalAnnots*this.intervalHeight) > this.maxCellHeight){
   205         var heightStep;
   152     		var heightStep = this.maxCellHeight/cell.totalAnnots;
   206         if ((cell.totalAnnots*this.intervalHeight) > this.maxCellHeight){
   153     	} else {
   207             heightStep = this.maxCellHeight/cell.totalAnnots;
   154     		var heightStep = this.intervalHeight;
   208         } else {
   155     	}
   209             heightStep = this.intervalHeight;
       
   210         }
   156 
   211 
   157     	//Draw the rect depending on the height step calculated
   212     	//Draw the rect depending on the height step calculated
   158     	for (var i=0; i< colorsDef.order.length; i++){
   213     	for (var i=0; i< colorsDef.order.length; i++){
   159     		var currentCode = colorsDef.order[i];
   214     		var currentCode = colorsDef.order[i];
   160 			cell.graphics.beginFill(cell.categories[currentCode].color.replace("#", "0x"))
   215 			cell.graphics.beginFill(cell.categories[currentCode].color.replace("#", "0x"))
   161     			.drawRect(0, y, this.intervalWidth-1, -cell.categories[currentCode].count * heightStep)
   216     			.drawRect(0, y, this.intervalWidth-1, -cell.categories[currentCode].count * heightStep)
   162     			.endFill();
   217     			.endFill();
   163     		y -= cell.categories[currentCode].count*heightStep;
   218     		y -= cell.categories[currentCode].count*heightStep;
   164     	}
   219     	}
   165     }
   220     }
   166     
   221 
   167     this.initCell = function(cell, colorsDef){
   222     this.initCell = function(cell, colorsDef){
   168     	cell.graphics = new PIXI.Graphics();
   223     	cell.graphics = new PIXI.Graphics();
   169     	cell.graphics.position.x = this.circleX + this.radius * Math.sin(cell.i*(360/totalIndex)*(Math.PI/180));
   224     	cell.graphics.position.x = this.circleX + this.radius * Math.sin(cell.i*(360/totalIndex)*(Math.PI/180));
   170     	cell.graphics.position.y = this.circleY - this.radius * Math.cos(cell.i*(360/totalIndex)*(Math.PI/180));
   225     	cell.graphics.position.y = this.circleY - this.radius * Math.cos(cell.i*(360/totalIndex)*(Math.PI/180));
   171     	cell.graphics.rotation = (cell.i)*(360/totalIndex)*(Math.PI/180) + (360/(totalIndex*2))*(Math.PI/180);
   226     	cell.graphics.rotation = (cell.i)*(360/totalIndex)*(Math.PI/180) + (360/(totalIndex*2))*(Math.PI/180);
   172     	this.container.addChild(cell.graphics);
   227     	this.container.addChild(cell.graphics);
   173     	
   228 
   174     	for (var category in colorsDef.colors){
   229     	for (var category in colorsDef.colors){
   175     		cell.categories[category] = {
   230     		cell.categories[category] = {
   176 				"count": 0,
   231 				"count": 0,
   177 				"color": colorsDef.colors[category]
   232 				"color": colorsDef.colors[category]
   178     		};
   233     		};
   182 			"color": colorsDef.defaultColor
   237 			"color": colorsDef.defaultColor
   183     	}
   238     	}
   184     }
   239     }
   185 
   240 
   186     this.init = function() {
   241     this.init = function() {
   187     	ws.message(function(data) {
   242         ws.message(function(data) {
   188             _this.addAnnot(data);
   243             _this.addAnnot(data);
   189         });
   244         });
   190 
   245 
   191     	this.initTimeTexts();
   246         this.initTimeTexts();
   192     };
   247     };
   193 
   248 
       
   249     //TODO use moment.js
   194     this.updateTime = function(){
   250     this.updateTime = function(){
   195     	currentTime = Date.now() + 3600*1000;
   251         var currentTime = Date.now() + 3600*1000;
   196 
   252 
   197         var nbSec = currentTime / 1000;
   253         var nbSec = currentTime / 1000;
   198         var hours = Math.floor( nbSec / 3600 ) % 24;
   254         var hours = Math.floor( nbSec / 3600 ) % 24;
   199         var minutes = Math.floor( nbSec / 60 ) % 60;
   255         var minutes = Math.floor( nbSec / 60 ) % 60;
   200         var seconds = Math.floor(nbSec % 60);
   256         var seconds = Math.floor(nbSec % 60);
   204     };
   260     };
   205 
   261 
   206     var refreshTimeInterval;
   262     var refreshTimeInterval;
   207 
   263 
   208     this.start = function() {
   264     this.start = function() {
   209     	refreshTimeInterval = setInterval(function() {_this.updateTime();}, 1000);
   265         this.startTs = Date.now();
       
   266         refreshTimeInterval = setInterval(function() {_this.updateTime();}, 1000);
       
   267         loadArchives();
   210     };
   268     };
   211 
   269 
   212     this.refresh = function() {
   270     this.refresh = function() {
   213 
   271 
   214     };
   272     };
   215 
   273 
   216     this.stop = function(){
   274     this.stop = function(){
   217     	console.log(this.cells);
   275         console.log(this.cells);
   218     };
   276     };
   219 
   277 
   220     return this;
   278     return this;
   221 }
   279 }
   222 
   280 
   223 module.exports = {
   281 module.exports = {
   224 	AnnotsTimeLine: AnnotsTimeLine
   282     AnnotsTimeLine: AnnotsTimeLine
   225 };
   283 };