From 226e09169c090018c22247abb5f01e26b65d58bd Mon Sep 17 00:00:00 2001
From: Ryan Seys <rsmseys@gmail.com>
Date: Tue, 3 Jul 2012 15:15:29 +0000
Subject: [PATCH] Cursor events processible

---
 .../playback/slides/css/bbb.playback.css      | 10 +-
 .../slides/playback/slides/lib/writing.js     | 94 ++++++++++---------
 .../slides/scripts/publish/slides.rb          | 48 ++++++++++
 3 files changed, 108 insertions(+), 44 deletions(-)

diff --git a/record-and-playback/slides/playback/slides/css/bbb.playback.css b/record-and-playback/slides/playback/slides/css/bbb.playback.css
index f5ccb55705..84317c34f2 100755
--- a/record-and-playback/slides/playback/slides/css/bbb.playback.css
+++ b/record-and-playback/slides/playback/slides/css/bbb.playback.css
@@ -39,8 +39,16 @@ br{
 	margin-right: auto;
 }
 
-#cursor{
+.circle {
+	height: 15px;
+	width: 15px;
+	border-radius: 50%;
+}
+
+
+#cursor {
 	position: absolute;
+	background: red;
 }
 
 .chatcontainer{
diff --git a/record-and-playback/slides/playback/slides/lib/writing.js b/record-and-playback/slides/playback/slides/lib/writing.js
index 164cd8c890..ec12d0a250 100755
--- a/record-and-playback/slides/playback/slides/lib/writing.js
+++ b/record-and-playback/slides/playback/slides/lib/writing.js
@@ -1,8 +1,5 @@
 // - - - START OF GLOBAL VARIABLES - - - //
 "use strict";
-//coordinates to set
-var cursor_x_global;
-var cursor_y_global;
 
 function getUrlParameters() {
     var map = {};
@@ -13,24 +10,25 @@ function getUrlParameters() {
 var params = getUrlParameters();
 var MEETINGID = params.meetingId;
 var HOST = window.location.hostname;
-var shapes_svg = "http://" + HOST + "/slides/" + MEETINGID + '/shapes.svg';
-var events_xml = "http://" + HOST + "/slides/" + MEETINGID + '/panzooms.xml';
+var url = "http://" + HOST + "/slides/" + MEETINGID;
+var shapes_svg = url + '/shapes.svg';
+var events_xml = url + '/panzooms.xml';
+var cursor_xml = url + '/cursor.xml';
 //immediately load the content
-var SHAPES = "http://" + HOST + "/slides/" + MEETINGID + '/shapes.svg';
-document.getElementById("svgobject").setAttribute('data', SHAPES);
+document.getElementById("svgobject").setAttribute('data', shapes_svg);
 //current time
 var t;
 var len;
 
 //coordinates for x and y for each second
-var cursor_x = [0, 10, 20, 40, 50, 100];
-var cursor_y = [0, 10, 20, 30, 60, 60];
 var panAndZoomTimes = [];
 var viewBoxes = [];
+var coords = [];
 var times = [];
 var clearTimes = [];
 var main_shapes_times = [];
 var vboxValues = {};
+var cursorValues = {};
 var imageAtTime = {};
 var cursorStyle;
 
@@ -98,33 +96,29 @@ for (var k = 0;k < pzlen; k++) {
 	vboxValues[[panZoomArray[k].getAttribute("timestamp"), second_val]] = viewBoxes[k].childNodes[0].data;
 }
 
-// - - - END OF GLOBAL VARIABLES - - - //
 
-// - - - START OF JAVASCRIPT FUNCTIONS - - - //
+// PROCESS CURSOR.XML
+xmlhttp.open("GET", cursor_xml, false);
+xmlhttp.send();
+xmlDoc = xmlhttp.responseXML;
+//getting all the event tags
+var curelements = xmlDoc.getElementsByTagName("recording");
+var cursorArray = curelements[0].getElementsByTagName("event");
+coords = xmlDoc.getElementsByTagName("cursor");
 
-// Retrieves the next X point on the grid which the cursor is to go to.
-function getNextX(t) {
-    var x = times.indexOf(t);
-    if(x !== -1) {
-		//console.log("returning " + cursor_x[x]);
-        return cursor_x[x];
-    }
-	else {
-		return -1;
+var clen = cursorArray.length;
+//fill the times array with the times of the svg images.
+for (var m = 0; m < clen; m++) {
+	if(cursorArray[m+1] == undefined) {
+		second_val = "end";
 	}
+	else second_val = cursorArray[m+1].getAttribute("timestamp");
+	cursorValues[[cursorArray[m].getAttribute("timestamp"), second_val]] = coords[m].childNodes[0].data;
 }
 
-// Retrieves the next Y point on the grid which the cursor is to go to.
-function getNextY(t) {
-    var y = times.indexOf(t);
-    if(y !== -1) {
-		//console.log("returning " + cursor_y[y]);
-        return cursor_y[y];
-    }
-	else {
-		return -1;
-	}
-}
+// - - - END OF GLOBAL VARIABLES - - - //
+
+// - - - START OF JAVASCRIPT FUNCTIONS - - - //
 
 // Draw the cursor at a specific point
 function draw(x, y) {
@@ -134,16 +128,6 @@ function draw(x, y) {
     cursorStyle.top = (parseInt(document.getElementById("slide").offsetTop, 10) + parseInt(y, 10)) + "px";
 }
 
-var clearLength = clearTimes.length;
-
-function getPageId(time, image) {
-	for(var c = 0; c < clearLength; c++) {
-		if ((parseFloat(clearTimes[c][0]) <= time) && (parseFloat(clearTimes[c][1]) >= time) && (image === clearTimes[c][2])){
-			return clearTimes[c][3];
-		}
-	}
-}
-
 // Shows or hides the cursor object depending on true/false parameter passed.
 function showCursor(boolVal) {
 	cursorStyle = document.getElementById("cursor").style;
@@ -162,6 +146,10 @@ function setViewBox(val) {
 	svgfile.setAttribute('viewBox', val);
 }
 
+function setCursor(val) {
+	draw(val[0], val[1]);
+}
+
 function getImageAtTime(time) {
 	var curr_t = parseFloat(time);
 	var key;
@@ -191,6 +179,22 @@ function getViewboxAtTime(time) {
 	}
 }
 
+function getCursorAtTime(time) {
+	var curr_t = parseFloat(time);
+	var key;
+	for (key in cursorValues) {
+		if(cursorValues.hasOwnProperty(key)) {
+			var arry = key.split(",");
+			if(arry[1] == "end") {
+				return null;
+			}
+			else if ((parseFloat(arry[0]) <= curr_t) && (parseFloat(arry[1]) >= curr_t)) {
+				return cursorValues[key].split(' ');
+			}
+		}
+	}
+}
+
 // - - - END OF JAVASCRIPT FUNCTIONS - - - //
 
 window.onresize = function(event) {
@@ -214,8 +218,6 @@ p.code({
     end: 1,
     //1 goes here. only for the first second intialize everything
     onStart: function(options) {
-		cursor_x_global = 0;
-		cursor_y_global = 0;
 		svgobj.style.left = document.getElementById("slide").offsetLeft + "px";
 		svgobj.style.top = "8px";
 		p.mute();
@@ -325,6 +327,12 @@ p.code({
 			if(vboxVal !== undefined) {
 				setViewBox(vboxVal);
 			}
+			
+			var cursorVal = getCursorAtTime(t);
+			if(cursorVal != null) {
+				setCursor(cursorVal);
+			}
+			
 			var elapsed = new Date().getTime() - start;
 			if(parseInt(elapsed, 10) !== 0) {
 				//console.log("frame time: " + elapsed);
diff --git a/record-and-playback/slides/scripts/publish/slides.rb b/record-and-playback/slides/scripts/publish/slides.rb
index bbc88f8cec..380e784b30 100755
--- a/record-and-playback/slides/scripts/publish/slides.rb
+++ b/record-and-playback/slides/scripts/publish/slides.rb
@@ -81,6 +81,48 @@ def processPanAndZooms
 	BigBlueButton.logger.info("Finished creating panzooms.xml")
 end
 
+def processCursorEvents
+	BigBlueButton.logger.info("Processing cursor events")
+	$cursor_xml = Nokogiri::XML::Builder.new do |xml|
+		$xml = xml
+		$xml.recording('id' => 'cursor_events') do
+			x_prev = nil
+			y_prev = nil
+			timestamp_orig_prev = nil
+			timestamp_prev = nil
+			last_time = $cursor_events.last[:timestamp].to_f
+			$cursor_events.each do |cursorEvent|
+				timestamp_orig = cursorEvent[:timestamp].to_f
+				timestamp = ((timestamp_orig-$join_time)/1000).round(1)
+				
+				x = cursorEvent.xpath(".//xPercent")[0].text()
+				y = cursorEvent.xpath(".//yPercent")[0].text()
+				if(timestamp_prev == timestamp)
+				
+				else
+					if(x_prev && y_prev)
+						$xml.event(:timestamp => timestamp_prev, :orig => timestamp_orig_prev) do
+							$ss.each do |key,val|
+								$val = val
+								if key === timestamp_prev
+									$vbox_width = $val[0]
+									$vbox_height = $val[1]
+								end
+							end
+							$xml.cursor "#{($vbox_width.to_f*(x.to_f/100)).round(1)} #{($vbox_height.to_f*(y.to_f/100)).round(1)}"
+						end
+					end
+				end
+				timestamp_prev = timestamp
+				timestamp_orig_prev = timestamp_orig
+				x_prev = x
+				y_prev = y
+			end
+		end
+	end
+	BigBlueButton.logger.info("Finished processing cursor events")
+end
+
 def processClearEvents
 	# process all the cleared pages events.
 	$clear_page_events.each do |clearEvent|
@@ -441,6 +483,7 @@ $magic_mystery_number = 2
 $shapesold_svg_filename = 'shapes_old.svg'
 $shapes_svg_filename = 'shapes.svg'
 $panzooms_xml_filename = 'panzooms.xml'
+$cursor_xml_filename = 'cursor.xml'
 
 $originX = "NaN"
 $originY = "NaN"
@@ -549,6 +592,7 @@ if ($playback == "slides")
 		$chat_events = @doc.xpath("//event[@eventname='PublicChatEvent']")
 		$shape_events = @doc.xpath("//event[@eventname='AddShapeEvent']") # for the creation of shapes
 		$panzoom_events = @doc.xpath("//event[@eventname='ResizeAndMoveSlideEvent']") # for the action of panning and/or zooming
+		$cursor_events = @doc.xpath("//event[@eventname='CursorMoveEvent']")
 		$clear_page_events = @doc.xpath("//event[@eventname='ClearPageEvent']") # for clearing the svg image
 		$undo_events = @doc.xpath("//event[@eventname='UndoShapeEvent']") # for undoing shapes.
 		$join_time = @doc.xpath("//event[@eventname='ParticipantJoinEvent']")[0][:timestamp].to_f
@@ -557,6 +601,7 @@ if ($playback == "slides")
 		processChatMessages()
 		processShapesAndClears()
 		processPanAndZooms()
+		processCursorEvents()
 
 		# Write slides.xml to file
 		File.open("#{package_dir}/slides.xml", 'w') { |f| f.puts $slides_doc.to_xml }
@@ -566,6 +611,9 @@ if ($playback == "slides")
 
 		# Write panzooms.xml to file
 		File.open("#{package_dir}/#{$panzooms_xml_filename}", 'w') { |f| f.puts $panzooms_xml.to_xml }
+		
+		# Write panzooms.xml to file
+		File.open("#{package_dir}/#{$cursor_xml_filename}", 'w') { |f| f.puts $cursor_xml.to_xml }
 
         BigBlueButton.logger.info("Publishing slides")
 		# Now publish this recording files by copying them into the publish folder.
-- 
GitLab