polling charts

This commit is contained in:
Markos Calderon 2013-06-28 10:38:51 -05:00
parent c91ca88b59
commit c65313347d
5 changed files with 494 additions and 8 deletions

View File

@ -50,12 +50,15 @@ package org.bigbluebutton.modules.polling.managers
import org.bigbluebutton.modules.polling.views.PollingInstructionsWindow;
import org.bigbluebutton.modules.polling.views.PollingStatsWindow;
import org.bigbluebutton.modules.polling.views.PollingViewWindow;
import org.bigbluebutton.modules.polling.views.TakePollWindow;
import org.bigbluebutton.modules.polling.views.TakePollWindow;
public class PollingWindowManager {
private var pollingWindow:PollingViewWindow;
private var statsWindow:PollingStatsWindow;
private var displayResultWindow:DisplayResultWindow;
private var instructionsWindow:TakePollWindow;
//private var instructionsWindow:PollMainWindow;
//private var instructionsWindow:CreatePollWindow;
@ -187,13 +190,15 @@ package org.bigbluebutton.modules.polling.managers
// PollingStatsWindow.mxml Window Handlers
//#########################################################################
public function handleOpenPollingStatsWindow(e:PollingStatsWindowEvent):void{
statsWindow = new PollingStatsWindow();
statsWindow.trackingPoll = e.poll;
openWindow(statsWindow);
//statsWindow = new PollingStatsWindow();
//statsWindow.trackingPoll = e.poll;
displayResultWindow = new DisplayResultWindow();
openWindow(displayResultWindow);
statsFocusTimer.addEventListener(TimerEvent.TIMER, focusStatsWindow);
statsFocusTimer.start();
//statsFocusTimer.addEventListener(TimerEvent.TIMER, focusStatsWindow);
//statsFocusTimer.start();
}
private function focusStatsWindow(event:TimerEvent):void{

View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<mx:Panel xmlns:mx="http://www.adobe.com/2006/mxml" borderStyle="none" horizontalAlign="center"
headerHeight="0" borderThicknessBottom="0" borderThicknessLeft="0"
borderThicknessRight="0" borderThicknessTop="0">
</mx:Panel>

View File

@ -0,0 +1,25 @@
<?xml version="1.0" encoding="utf-8"?>
<mx:Panel xmlns:mx="http://www.adobe.com/2006/mxml" borderStyle="none" horizontalAlign="center"
headerHeight="0" borderThicknessBottom="0" borderThicknessLeft="0"
borderThicknessRight="0" borderThicknessTop="0">
<mx:PieChart id="pieChart"
dataProvider="{sampleData}"
showDataTips="true"
height="100%"
width="100%">
<mx:series>
<mx:PieSeries id="pieSeries"
field="Votes"
nameField="Answer"
filters="[]"
labelPosition="callout" />
</mx:series>
</mx:PieChart>
<mx:ControlBar width="100%">
<mx:Legend dataProvider="{pieChart}"
direction="horizontal"
labelPlacement="right"
horizontalGap="100"
width="100%" />
</mx:ControlBar>
</mx:Panel>

View File

@ -0,0 +1,419 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
BigBlueButton open source conferencing system - http://www.bigbluebutton.org
Copyright (c) 2010 BigBlueButton Inc. and by respective authors (see below).
BigBlueButton is free software; you can redistribute it and/or modify it under the
terms of the GNU Lesser General Public License as published by the Free Software
Foundation; either version 2.1 of the License, or (at your option) any later
version.
BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License along
with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
$Id: $
-->
<MDIWindow xmlns="flexlib.mdi.containers.*" xmlns:mx="http://www.adobe.com/2006/mxml"
height="150"
width="410"
xmlns:mate="http://mate.asfusion.com/"
implements="org.bigbluebutton.common.IBbbModuleWindow"
initialize="init();"
creationComplete="onCreationComplete()"
label="{ResourceUtil.getInstance().getString('bbb.polling.toolbar.toolTip')}"
title="{ResourceUtil.getInstance().getString('bbb.polling.toolbar.toolTip')}"
layout="absolute"
>
<mate:Listener type="{ShortcutEvent.FOCUS_WEBPOLL_ADDRESS}" method="focusWebPollBox" />
<mate:Listener type="{ShortcutEvent.FOCUS_POLL_DATA}" method="focusDataGrid" />
<mate:Listener type="{ShortcutEvent.SC_REFRESH_POLL}" method="remoteRefresh" />
<mate:Listener type="{ShortcutEvent.SC_STOP_POLL}" method="remoteStop" />
<mate:Listener type="{ShortcutEvent.SC_REPOST_POLL}" method="remoteRepost" />
<mate:Listener type="{ShortcutEvent.CLOSE_POLL_STATS}" method="remoteClose" />
<mx:Script>
<![CDATA[
import flash.events.TimerEvent;
import flash.utils.Timer;
import flexlib.mdi.events.MDIWindowEvent;
import mx.collections.ArrayCollection;
import mx.containers.*;
import mx.controls.*;
import mx.controls.Alert;
import mx.controls.Text;
import mx.controls.TextArea;
import mx.core.IUIComponent;
import mx.utils.ObjectUtil;
import mx.validators.Validator;
import org.bigbluebutton.common.LogUtil;
import org.bigbluebutton.common.Role;
import org.bigbluebutton.core.UsersUtil;
import org.bigbluebutton.core.managers.UserManager;
import org.bigbluebutton.main.model.users.BBBUser;
import org.bigbluebutton.main.model.users.Conference;
import org.bigbluebutton.main.views.MainCanvas;
import org.bigbluebutton.main.events.ShortcutEvent;
import org.bigbluebutton.modules.chat.events.SendPublicChatMessageEvent;
import org.bigbluebutton.modules.polling.events.GenerateWebKeyEvent;
import org.bigbluebutton.modules.polling.events.PollRefreshEvent;
import org.bigbluebutton.modules.polling.events.PollingStatsWindowEvent;
import org.bigbluebutton.modules.polling.events.PublishPollEvent;
import org.bigbluebutton.modules.polling.events.SavePollEvent;
import org.bigbluebutton.modules.polling.events.StartPollingEvent;
import org.bigbluebutton.modules.polling.events.StopPollEvent;
import org.bigbluebutton.modules.polling.events.VoteEvent;
import org.bigbluebutton.modules.polling.managers.PollingManager;
import org.bigbluebutton.modules.polling.model.AnswerObject;
import org.bigbluebutton.modules.polling.model.PollObject;
import org.bigbluebutton.modules.polling.model.PollStatLineObject;
import org.bigbluebutton.util.i18n.ResourceUtil;
import org.bigbluebutton.modules.polling.model.PollOptions;
import mx.charts.events.ChartItemEvent;
public static const LOGNAME:String = "[PollingStatsWindow] ";
[Bindable] public var question:String;
[Bindable] public var answers:Array;
[Bindable] public var trackingPoll:PollObject;
[Bindable] public var pollOptions:PollOptions;
[Bindable] private var baseIndex:int;
[Bindable] public var webPollUrl:String;
public var viewingClosedPoll:Boolean = false;
public var moduleAttributes:Object;
private var _userid:Number;
private var window:PollingStatsWindow;
private var conference:Conference;
[Bindable]public var reviewing:Boolean = false;
private var POLL_URL_COLOUR:String = "35071";
private var webClosed:Boolean;
private var notified:Boolean;
private var refreshTimer:Timer = new Timer(1000);
[Bindable] private var answerCollection:ArrayCollection = new ArrayCollection();
private var keyCombos:Object;
[Bindable]
public var sampleData:ArrayCollection = new ArrayCollection([
{Answer:"Chicken", Votes:4},
{Answer:"Hen", Votes:3},
{Answer:"egg", Votes:6}
]);
private function init():void{
pollOptions = new PollOptions();
baseIndex = pollOptions.baseTabIndex;
answerCollection = trackingPoll.generateStats();
conference = UserManager.getInstance().getConference();
webPollText.visible = (UsersUtil.amIPresenter() && (!reviewing && trackingPoll.publishToWeb));
btnClosePoll.visible = UsersUtil.amIPresenter();
webPollBox.visible = webPollText.visible;
if (webPollText.visible){
webClosed = false;
var generate: GenerateWebKeyEvent = new GenerateWebKeyEvent(GenerateWebKeyEvent.GENERATE);
generate.poll = trackingPoll;
dispatchEvent(generate);
}
notified = false;
statsView.addChild(new DisplayResultPieChartPanel());
}
private function autoRefresh(event:TimerEvent):void{
refreshPoll();
}
private function onCreationComplete():void{
hotkeyCapture();
titleBarOverlay.accessibilityName = ResourceUtil.getInstance().getString('bbb.polling.stats.accessTitle', [trackingPoll.title]);
titleBarOverlay.tabIndex = baseIndex;
minimizeBtn.tabIndex = baseIndex+1;
maximizeRestoreBtn.tabIndex = baseIndex+2;
closeBtn.tabIndex = baseIndex+3;
// If the statistics window is being opened to view a poll that has been published and closed, the interface will
// immediately appear with only the option to close the window.
if(viewingClosedPoll)
stopPoll();
if (UsersUtil.amIPresenter()){
messageForRecording("A poll is open for voting.");
messageForRecording(ResourceUtil.getInstance().getString('bbb.polling.createPoll.title') + " " + trackingPoll.title);
messageForRecording(ResourceUtil.getInstance().getString('bbb.polling.createPoll.question') + " " + trackingPoll.question);
messageForRecording(ResourceUtil.getInstance().getString('bbb.polling.createPoll.answers'));
for (var i:int = 0; i < trackingPoll.answers.length; i++){
messageForRecording("- " + trackingPoll.answers[i]);
}
}
if (webPollText.visible){
LogUtil.debug("webPollURL is : " + webPollUrl);
LogUtil.debug("webkey is : " + trackingPoll);
LogUtil.debug("webPollURLBox.Text is : " + webPollURLBox.text);
}
answers = trackingPoll.answers;
question = trackingPoll.question;
var lines:int = (question.length / 28) + 1;
for(var s:String in answers){
lines = lines + ((s.length / 28) + 1);
}
height = height + ((lines+1) * 45);
createResultsTable(answers.length, answers);
focusManager.setFocus(titleBarOverlay);
}
private function hotkeyCapture():void{
this.addEventListener(KeyboardEvent.KEY_DOWN, handleKeyDown);
//ResourceUtil.getInstance().addEventListener(Event.CHANGE, localeChanged); // Listen for locale changing
}
private function handleKeyDown(e:KeyboardEvent) :void {
var modifier:String = ExternalInterface.call("determineModifier");
loadKeyCombos(modifier);
var keyPress:String = (e.ctrlKey ? "control+" : "") +
(e.shiftKey ? "shift+" : "") +
(e.altKey ? "alt+" : "") + e.keyCode;
if (keyCombos[keyPress]) {
dispatchEvent(new ShortcutEvent(keyCombos[keyPress]));
}
}
private function loadKeyCombos(modifier:String):void {
keyCombos = new Object(); // always start with a fresh array
keyCombos[modifier+(ResourceUtil.getInstance().getString('bbb.shortcutkey.polling.focusData') as String)] = ShortcutEvent.FOCUS_POLL_DATA;
keyCombos[modifier+(ResourceUtil.getInstance().getString('bbb.shortcutkey.polling.refresh') as String)] = ShortcutEvent.SC_REFRESH_POLL;
keyCombos[modifier+(ResourceUtil.getInstance().getString('bbb.shortcutkey.polling.focusWebPoll') as String)] = ShortcutEvent.FOCUS_WEBPOLL_ADDRESS;
keyCombos[modifier+(ResourceUtil.getInstance().getString('bbb.shortcutkey.polling.stopPoll') as String)] = ShortcutEvent.SC_STOP_POLL;
keyCombos[modifier+(ResourceUtil.getInstance().getString('bbb.shortcutkey.polling.closeStatsWindow') as String)] = ShortcutEvent.CLOSE_POLL_STATS;
keyCombos[modifier+(ResourceUtil.getInstance().getString('bbb.shortcutkey.polling.repostPoll') as String)] = ShortcutEvent.SC_REPOST_POLL;
}
public function setUrlBoxText():void{
webPollURLBox.text = webPollUrl;
webPollURLBox.accessibilityName = ResourceUtil.getInstance().getString('bbb.polling.stats.webPollBoxAccessName', [webPollUrl]);
LogUtil.debug("webPollURLBox.Text is : " + webPollURLBox.text);
if (UsersUtil.amIPresenter())
messageForRecording(ResourceUtil.getInstance().getString('bbb.polling.stats.webPollURL') + " " + webPollUrl);
}
private function messageForRecording(message:String):void{
/*if (!viewingClosedPoll){
var chatMessage:SendPublicChatMessageEvent = new SendPublicChatMessageEvent(SendPublicChatMessageEvent.SEND_PUBLIC_CHAT_MESSAGE_EVENT);
chatMessage.message = message;
chatMessage.time = "";
chatMessage.color = POLL_URL_COLOUR.toString();
chatMessage.language = ResourceUtil.getInstance().getCurrentLanguageCode().split("_")[0];
dispatchEvent(chatMessage);
}*/
}
public function getPrefferedPosition():String{
return MainCanvas.POPUP;
}
private function refreshPoll():void{
var e:PollRefreshEvent = new PollRefreshEvent(PollRefreshEvent.GET);
e.poll.title = trackingPoll.title;
dispatchEvent(e);
} // end of function refreshResults
private function closeWindow():void{
dispatchEvent(new PollingStatsWindowEvent(PollingStatsWindowEvent.CLOSE));
}
public function refreshWindow(newVotes:Array, totalVotes:int, noVoteYet:int):void{
trackingPoll.votes = newVotes;
trackingPoll.totalVotes = totalVotes;
trackingPoll.didNotVote = noVoteYet;
createResultsTable(trackingPoll.answers.length, trackingPoll.answers);
invalidateDisplayList();
validateNow();
}
private function stopPoll():void{
refreshPoll();
refreshTimer.stop();
btnRefreshResults.visible = UsersUtil.amIPresenter();
btnRefreshResults.label = ResourceUtil.getInstance().getString('bbb.polling.stats.repost');
btnRefreshResults.removeEventListener(MouseEvent.CLICK, refreshWindow);
btnRefreshResults.addEventListener(MouseEvent.CLICK, publishPollAgain);
btnClosePoll.label = ResourceUtil.getInstance().getString('bbb.polling.stats.close');
btnClosePoll.removeEventListener(MouseEvent.CLICK, closeWindow);
btnClosePoll.addEventListener(MouseEvent.CLICK, closeButtonClick);
trackingPoll.status = false;
if (webPollText.visible && !webClosed){
webClosed = true;
messageForRecording(ResourceUtil.getInstance().getString('bbb.polling.webPollClosed'));
}
if (!notified){
var percentage:int;
var totalVotes:int = 0;
for (var n:int = 0; n < trackingPoll.votes.length; n++){
totalVotes+= int(trackingPoll.votes[n]);
}
messageForRecording(ResourceUtil.getInstance().getString('bbb.polling.pollClosed'));
for (var i:int = 0; i < trackingPoll.answers.length; i++){
if (totalVotes > 0){
percentage = Math.round(100*(trackingPoll.votes[i]/totalVotes));
}
else{
percentage = 0;
}
// Example of how this message will appear:
// "Answer one - 3 votes/73%"
messageForRecording(trackingPoll.answers[i] + " - " + trackingPoll.votes[i] + " " + ResourceUtil.getInstance().getString('bbb.polling.stats.votes') + "/" + percentage + "%");
}
notified = true;
}
stopViewersPolls();
}
private function publishPollAgain(e:Event):void{
var event:PublishPollEvent = new PublishPollEvent(PublishPollEvent.REPOST);
event.poll = trackingPoll;
dispatchEvent(event);
closeWindow();
}
private function closeButtonClick(e:Event):void{
closeWindow();
}
private function stopViewersPolls():void{
var stopPollEvent:StopPollEvent = new StopPollEvent(StopPollEvent.STOP_POLL);
stopPollEvent.poll = trackingPoll;
dispatchEvent(stopPollEvent);
}
private function createResultsTable(amount:uint, content:Array):void{
answerCollection = trackingPoll.generateStats();
answerCollection.addItem(didNotVote());
resultsGrid.dataProvider = answerCollection;
}
private function didNotVote():PollStatLineObject{
var pso:PollStatLineObject = new PollStatLineObject();
pso.answer = ResourceUtil.getInstance().getString('bbb.polling.stats.didNotVote');
pso.votes = trackingPoll.didNotVote.toString();
pso.percentage = "";
return pso;
}
private function focusWebPollBox(e:ShortcutEvent):void{
if (webPollURLBox.visible)
focusManager.setFocus(webPollURLBox);
}
private function focusDataGrid(e:ShortcutEvent):void{
focusManager.setFocus(resultsGrid);
}
// addAlert
private function remoteRefresh(e:ShortcutEvent):void{
if (btnRefreshResults.label == ResourceUtil.getInstance().getString('bbb.polling.stats.refresh')){
var message:String = ResourceUtil.getInstance().getString('bbb.polling.stats.alerts.refresh');
ExternalInterface.call("addAlert", message);
refreshPoll();
}
}
private function remoteStop(e:ShortcutEvent):void{
if (btnClosePoll.label == ResourceUtil.getInstance().getString('bbb.polling.stats.stopPoll')){
var message:String = ResourceUtil.getInstance().getString('bbb.polling.stats.alerts.stopPoll');
ExternalInterface.call("addAlert", message);
stopPoll();
}
}
private function remoteRepost(e:ShortcutEvent):void{
if (btnRefreshResults.label == ResourceUtil.getInstance().getString('bbb.polling.stats.repost')){
var message:String = ResourceUtil.getInstance().getString('bbb.polling.stats.alerts.repost');
ExternalInterface.call("addAlert", message);
publishPollAgain(e);
}
}
private function remoteClose(e:ShortcutEvent):void{
if (btnClosePoll.label == ResourceUtil.getInstance().getString('bbb.polling.stats.close')){
var message:String = ResourceUtil.getInstance().getString('bbb.polling.stats.alerts.close');
ExternalInterface.call("addAlert", message);
closeButtonClick(e);
}
}
]]>
</mx:Script>
<!-- Accessible statistics view -->
<mx:VBox width="100%"
height="90%"
horizontalAlign="center"
paddingLeft="10"
paddingRight="10"
focusEnabled="true"
id="statsView">
<mx:HBox width="90%"
paddingTop="10"
focusEnabled="true">
<mx:Text id="webPollText"
text="{ResourceUtil.getInstance().getString('bbb.polling.stats.webPollURL')}"
width="140"
/>
</mx:HBox>
<mx:HBox id="webPollBox"
width="90%">
<mx:TextArea id="webPollURLBox"
editable="false"
text=""
height="25"
width="95%"
tabIndex="{baseIndex+4}"
/>
</mx:HBox>
<mx:Text width="200"
paddingTop="15" paddingBottom="10"
fontWeight="bold" textAlign="center"
text="{question}"/>
</mx:VBox>
<mx:ControlBar width="100%" height="10%">
<mx:Spacer width="100%"/>
<mx:Button id="btnRefreshResults"
label="{ResourceUtil.getInstance().getString('bbb.polling.stats.refresh')}"
click="refreshPoll()"
width="100"
height="30"
visible = "true"
tabIndex="{baseIndex+6}"
/>
<mx:Button id="btnClosePoll"
label="{ResourceUtil.getInstance().getString('bbb.polling.stats.stopPoll')}"
click="stopPoll()"
width="100"
height="30"
visible = "true"
tabIndex="{baseIndex+7}"
/>
<mx:Spacer width="100%"/>
</mx:ControlBar>
</MDIWindow>

View File

@ -80,6 +80,7 @@
import org.bigbluebutton.modules.polling.model.PollStatLineObject;
import org.bigbluebutton.util.i18n.ResourceUtil;
import org.bigbluebutton.modules.polling.model.PollOptions;
import mx.charts.events.ChartItemEvent;
public static const LOGNAME:String = "[PollingStatsWindow] ";
[Bindable] public var question:String;
@ -102,7 +103,14 @@
private var refreshTimer:Timer = new Timer(1000);
[Bindable] private var answerCollection:ArrayCollection = new ArrayCollection();
private var keyCombos:Object;
[Bindable]
public var sampleData:ArrayCollection = new ArrayCollection([
{Answer:"Chicken", Votes:4},
{Answer:"Hen", Votes:3},
{Answer:"egg", Votes:6}
]);
private function init():void{
pollOptions = new PollOptions();
baseIndex = pollOptions.baseTabIndex;
@ -355,7 +363,7 @@
<!-- Accessible statistics view -->
<mx:VBox width="100%"
height="75%"
height="90%"
horizontalAlign="center"
paddingLeft="10"
paddingRight="10"
@ -406,6 +414,29 @@
/>
</mx:columns>
</mx:DataGrid>
<mx:Panel width="90%" height="90%">
<mx:PieChart id="pieChart"
dataProvider="{sampleData}"
showDataTips="true"
height="100%"
width="100%">
<mx:series>
<mx:PieSeries id="pieSeries"
field="Votes"
nameField="Answer"
filters="[]"
labelPosition="callout" />
</mx:series>
</mx:PieChart>
<mx:ControlBar width="100%">
<mx:Legend dataProvider="{pieChart}"
direction="horizontal"
labelPlacement="right"
horizontalGap="100"
width="100%" />
</mx:ControlBar>
</mx:Panel>
</mx:VBox>
<mx:ControlBar width="100%" height="10%">