angular.module("zoneXyViewer", ['mixpanelAPI', 'videoPlayer', 'eventTypeFilterGroup', 'errorStatusCheck', 'reportSettings']) .directive('zoneEventFilterControls', function () { return { restrict: 'E', replace: true, scope: { slId: '=', zone: '=', eventOutcomeSelection: '=', toggleEventOutcomeSelection: '&', shotOutcomeSelection: '=', toggleShotOutcomeSelection: '&', eventsSelection: '=', toggleEventsSelectionGroupName: '&' }, templateUrl: 'views/zoneEventFilterControls.html', controller: function ($scope) { $scope.$watch('season', function(newValue) { var newStartDate = ((newValue && newValue.startDate) ? newValue.startDate : undefined) var today = new Date(); var dd = today.getDate(); var mm = today.getMonth()+1; //January is 0! var yyyy = today.getFullYear(); if(dd<10) { dd='0'+dd } if(mm<10) { mm='0'+mm } today = yyyy+'-'+mm+'-'+dd; $scope.today=today; if ($scope.filterSet == undefined) { $scope.filterSet = {}; } $scope.filterSet['maxDate'] = today; $scope.filterSet['minDate'] = newStartDate; if ($scope.context == undefined) { $scope.context = {}; } $scope.context.dateFrom = newStartDate; $scope.context.dateTo = today; if (typeof $scope.team !== 'undetermined' && $scope.getCurrentId instanceof Function) { $scope.getEventsLocationData($scope.getCurrentId(), $scope.team, function () {}, $scope.filterSet) } }); $scope.blurMe = function ($event) { $event.target.blur(); } $scope.isEventOutcomeControlDisabled = function() { var returnFlag = false; if ($scope.eventsSelection.groupName == 'shot' || $scope.eventsSelection.groupName == 'goal' || $scope.eventsSelection.groupName == 'pass,shot,puckprotection' || $scope.eventsSelection.groupName == 'pass,carry' || $scope.eventsSelection.groupName == 'lpr' || $scope.eventsSelection.groupName == 'dumpinagainst' || $scope.eventsSelection.groupName == 'check' ) { returnFlag = true; } return returnFlag; } $scope.toggleEventOutcomeSelectionInternal = function(eventOutcome) { if ($scope.isEventOutcomeControlDisabled() == false) { $scope.toggleEventOutcomeSelection ({eventOutcome : eventOutcome}); } } $scope.isShotOutcomeActive = function(shotOutcome) { var returnFlag = false; if ($scope.eventsSelection.groupName == 'shot') { if (shotOutcome == 'all' && $scope.shotOutcomeSelection.length == 0) { returnFlag = true; } else if ($scope.shotOutcomeSelection.indexOf(shotOutcome) >= 0) { returnFlag = true; } } return returnFlag; } $scope.toggleShotOutcomeSelectionInternal = function(shotOutcome) { if ($scope.eventsSelection.groupName != 'shot') { $scope.eventsSelection.groupName = 'shot'; $scope.eventsSelection.set = ['eventname:shot+zone:oz']; } $scope.toggleShotOutcomeSelection ({shotOutcome : shotOutcome}); } $scope.$watch('eventsSelection.groupName', function(groupName) { $scope.toggleEventsSelectionGroupName({groupName : groupName}); }, true); } } }) .directive('zoneXyViewer', function() { return { restrict: 'E', replace: true, scope: { slId: '=', loadEvent: '=', apiEndpoint: '=', zone: '=', player: '=', team: '=', season: '=', allPlayers: '=', canViewClips: '=', permissions: '=' }, templateUrl: 'views/zoneXyViewer.html', controller: function ($rootScope, $scope, $timeout, $http, $filter, mixpanelAPI, errorStatusCheck, playlistCreator) { $scope.blurMe = function ($event) { $event.target.blur(); } $scope.flip = false; if ($scope.zone == 'dz') { $scope.flip = true; } $scope.filterSet={}; var today = new Date(); var dd = today.getDate(); var mm = today.getMonth()+1; //January is 0! var yyyy = today.getFullYear(); if(dd<10) { dd='0'+dd } if(mm<10) { mm='0'+mm } today = yyyy+'-'+mm+'-'+dd; $scope.today=today; $scope.filterSet['maxDate'] = today; $scope.filterSet['minDate'] = $scope.season.startDate; $scope.customMinDate = false; // Neutral Zone view includes carry plays which can be either OZ or DZ if ($scope.zone != 'nz') { $scope.filterSet['zone'] = $scope.zone; } $scope.displayDateSeasonFrom = $scope.filterSet['minDate']; $scope.displayDateSeasonTo = $scope.filterSet['maxDate']; $scope.getPrimaryPositionText = function (position) { var primaryPositionText = "Forward"; if (position == 'D') { primaryPositionText = "Defenceman"; } else if (position == 'G') { primaryPositionText = "Goaltender"; } return primaryPositionText; } $scope.decorateDetailsWithZoneContext = function (detailsObject) { detailsObject.reportType = $scope.reportType; detailsObject.fromDate = $scope.displayDateSeasonFrom; detailsObject.toDate = $scope.displayDateSeasonTo; detailsObject.manpowerSituation = $scope.context.manpowerSituation; detailsObject.periodType = $scope.context.periodType; detailsObject.eventOutcomeSelection = $scope.context.eventOutcomeSelection; if ($scope.context.eventsSelection.groupName == 'shot') { detailsObject.shotOutcomeSelection = $scope.context.shotOutcomeSelection; } return detailsObject; } $scope.$watch('displayDateSeasonFrom + displayDateSeasonTo', function () { if($scope.displayDateSeasonFrom <= $scope.displayDateSeasonTo){ $scope.filterSet['maxDate'] = $scope.displayDateSeasonTo; $scope.filterSet['minDate'] = $scope.displayDateSeasonFrom; $scope.getEventsLocationData($scope.getCurrentId(), $scope.team, function () {}, $scope.filterSet) if ($scope.player) { mixpanelAPI.send('setFilterDate', $scope.decorateDetailsWithContextInfo( $scope.decorateDetailsWithZoneContext($scope.eventProperties))); } } }); $scope.compareSets = function(set1, set2) { var returnComparison = true; if (set1.length != set2.length) { returnComparison =false; } else { for (var i=0;i 0) { filterValue += " || "; } filterValue += "(" + newValue[i] + ")"; } $scope.eventProperties = { "filter": filterValue }; if ($scope.viewerOkToLoad == true) { $scope.finalizeUpdateView(function(){}); mixpanelAPI.send('setEventFilter', $scope.decorateDetailsWithContextInfo( $scope.decorateDetailsWithZoneContext($scope.eventProperties))); } }, true); $scope.syncEventOutcomeSelectionToShotOutcomeSelection = function () { if ($scope.context.shotOutcomeSelection.length == 0) { $scope.context.eventOutcomeSelection = 'all'; } else if ($scope.context.shotOutcomeSelection.indexOf('onNet') < 0 ) { $scope.context.eventOutcomeSelection = 'failed'; } else if ($scope.context.shotOutcomeSelection.indexOf('missed') >= 0 || $scope.context.shotOutcomeSelection.indexOf('blocked') >= 0) { $scope.context.eventOutcomeSelection = 'all'; } else { $scope.context.eventOutcomeSelection = 'successful'; } } $scope.isGroupFilterableByOutcome = function (groupName) { var returnFlag = true; if (groupName == 'shot' || groupName == 'goal' || groupName == 'pass,shot,puckprotection' || groupName == 'pass,carry' || groupName == 'lpr' || groupName == 'dumpinagainst' || groupName == 'check') { returnFlag = false; } return returnFlag; } $scope.toggleEventsSelectionGroupName = function(groupName) { $scope.context.eventsSelection.groupName = groupName; if ($scope.isGroupFilterableByOutcome(groupName) == false) { $scope.context.eventOutcomeSelection = 'successful'; } if ($scope.context.eventsSelection.groupName == 'shot') { $scope.syncEventOutcomeSelectionToShotOutcomeSelection(); } $scope.getEventsLocationData($scope.getCurrentId(), $scope.team, function () {}, $scope.filterSet); } $scope.toggleEventOutcomeSelection = function(eventOutcomeSelection) { $scope.context.eventOutcomeSelection = eventOutcomeSelection; $scope.finalizeUpdateView(function(){}); mixpanelAPI.send('setEventFilter', $scope.decorateDetailsWithContextInfo( $scope.decorateDetailsWithZoneContext($scope.eventProperties))); } $scope.toggleShotOutcomeSelection=function(shotOutcome) { if ($scope.context.eventsSelection.groupName=='shot') { if (shotOutcome == 'all') { $scope.context.shotOutcomeSelection=[]; } else { var index = $scope.context.shotOutcomeSelection.indexOf(shotOutcome); if (index < 0) { $scope.context.shotOutcomeSelection.push(shotOutcome); } else { $scope.context.shotOutcomeSelection.splice(index, 1); } } $scope.syncEventOutcomeSelectionToShotOutcomeSelection(); $scope.finalizeUpdateView(function(){}); mixpanelAPI.send('setEventFilter', $scope.decorateDetailsWithContextInfo( $scope.decorateDetailsWithZoneContext($scope.eventProperties))); } } String.prototype.capitalize = function() { return this.charAt(0).toUpperCase() + this.slice(1); } $scope.getEventContextString = function() { var returnString = ""; var eventSelection=$scope.context.eventsSelection.set; var type=''; var eventName; if (eventSelection[0]!=undefined) { var outCome; for (var arg = 0; arg < eventSelection.length; ++ arg) { if (arg==eventSelection.length-1&& arg !=0){ type+=' and '; } else if (arg>0){ type+=','; } var attributes = eventSelection[arg].split('+'); var eventNameArray=eventSelection[arg].split('+')[0].split(':'); eventName=eventNameArray[1]; if ($scope.isGroupFilterableByOutcome(eventName.replace(/\|/g, ',')) && $scope.context.eventOutcomeSelection == 'successful' && arg==0){ type+='Successful '; } else if ($scope.isGroupFilterableByOutcome(eventName.replace(/\|/g, ',')) && $scope.context.eventOutcomeSelection == 'failed' && arg==0){ type+='Failed '; } if (eventSelection[arg].indexOf('successful') >= 0){ outCome='successful'; } else { outCome='failed'; } if (eventName=='shot'&&outCome=='successful'&&eventSelection[arg].indexOf('type') < 0){ type += ' Shot'; eventName=' Scoring Chance Generating Play'; } if (eventName=='puckprotection'&&outCome=='successful' > 0){ type += ' Deke'; eventName=' Scoring Chance Generating Play'; } if (eventName == 'lpr' && eventSelection[arg].indexOf('others') >=0) { type += ' Other'; } if (eventName=='controlledentryagainst'){ eventName=' Controlled Entry Against'; } if (eventName=='dumpinagainst'){ eventName=' Dump In Against'; } if (eventName == 'carry') { eventName=' Possession Driving Play'; type=type.replace('Successful', ''); if (eventSelection[arg].indexOf('dz')>=0 ) { type += ' Exit'; } if (eventSelection[arg].indexOf('nz')>=0 ) { type += ' Red-Line Carry'; } if (eventSelection[arg].indexOf('oz')>=0 ) { type += ' Entry'; } } for (var j = 0; j < attributes.length; ++ j){ var temp =attributes[j].split(':'); if (temp[0] == 'type' || temp[0] == 'previousname') { if (eventName == 'shot') { if (temp[1] == 'slot|slotblocked') { type += ' Slot'; } else if (temp[1] == 'deflected|deflectedblocked') { type += ' Deflected'; } else { type +=' Outside'; } } else if (temp[1]=='slot|eastwest|eastwestoffboards|rush|rushoffboards'){ type += 'Pass'; eventName='Scoring Chance Generating Play'; type=type.replace('Successful', ''); } else if (eventName == 'pass' && temp[1]=='eastwest|north|northoffboards|ozentryoffboards|ozentry'){ type += 'Pass'; eventName='Possession Driving Play'; type=type.replace('Successful', ''); } else if(temp[1]=='blueline'){ type+='Blue Line Hold' } else if (eventName == 'pass') { if (temp[1].indexOf('north')>=0 ) { type += ' North'; } if (temp[1].indexOf('south')>=0 ) { type += ' South'; } if (temp[1].indexOf('eastwest')>=0 ) { type += ' East-West'; } if (temp[1].indexOf('slot')>=0 ) { type += ' Slot'; } if (temp[1].indexOf('rush')>=0 ) { type += ' Off-the-Rush'; } if (temp[1].indexOf('stretch')>=0 ) { if (temp[1].indexOf('ozentrystretch')>=0 ) { type += ' OZ Entry Stretch'; } else { type += ' Stretch'; } } if (temp[1].indexOf('outlet')>=0 ) { type += ' Outlet'; } if (temp[1].indexOf('d2d')>=0 ) { type += ' D2D'; } } else if (eventName == 'lpr') { if (temp[1].indexOf('faceoff')>=0 ) { type += ' Face-Off'; } if (temp[1].indexOf('shot')>=0 || temp[1].indexOf('rebound')>=0) { type +=' Shot / Rebound'; } if (temp[1].indexOf('dumpin')>=0 || (temp[1].indexOf('opdump')>=0 && eventSelection[arg].indexOf('zone:dz')>=0)) { type +=' Dump-In'; } if (temp[1].indexOf('opdump')>=0 && eventSelection[arg].indexOf('zone:nz')>=0) { type +=' Opposition Dump-Out'; } if (temp[1].indexOf('dumpout')>=0) { type +=' Dump-Out'; } } else if (eventName == 'dumpout') { if (temp[1].indexOf('ice')>=0 ) { type += ' Open-Ice'; } if (temp[1].indexOf('boards')>=0 ) { type += ' Offboards'; } } else if (eventName == 'dumpin') { if (temp[1].indexOf('dump')>=0 ) { type += ' Regular'; } if (temp[1].indexOf('chip')>=0 ) { type += ' Chip-In'; } } else if (eventName == 'check') { if (temp[1].indexOf('body')>=0 ) { type += ' Body'; } if (temp[1].indexOf('stick')>=0 ) { type += ' Stick'; } } else if (eventName == 'puckprotection') { if (temp[1].indexOf('body')>=0 ) { type += ' Body'; } if (temp[1].indexOf('deke')>=0 ) { type += ' Open-Ice Deke'; } } else if (eventName == 'block') { if (temp[1].indexOf('pass')>=0 ) { type += ' Pass'; } if (temp[1].indexOf('shot')>=0 ) { type += ' Shot'; } } } } } if (type==''){ if (eventName=='pass|shot|puckprotection'){ eventName='Scoring Chance Generating Play'; } if (eventName=='pass|carry'){ eventName='Possession Driving Play'; } if (eventName=='shot' || eventName=='check') { type='All'; } if ($scope.isGroupFilterableByOutcome(eventName.replace(/\|/g, ','))) { type='All'; if ($scope.context.eventOutcomeSelection == 'successful' && arg==0){ type+='Successful '; } else if ($scope.context.eventOutcomeSelection == 'failed' && arg==0){ type+='Failed '; } } } if (j==attributes.length){ var eventDisplayName=eventName.capitalize(); if (eventName=='pass') { eventDisplayName += 'es'; type += ' ' + eventDisplayName; } else if (eventName=='reception'){ var eventDisplayName='Pass Receptions'; type += ' ' + eventDisplayName; } else if (eventName=='puckprotection'){ var eventDisplayName='Puck Protections'; type += ' ' + eventDisplayName; } else if (eventName=='lpr'){ eventDisplayName = 'LPRs'; type += ' ' + eventDisplayName; } else { if (eventName == 'shot') { for (var arg = 0; arg < $scope.context.shotOutcomeSelection.length; ++ arg) { if (arg==$scope.context.shotOutcomeSelection.length-1&& arg !=0){ type+=' and'; } else if (arg>0){ type+=','; } if ($scope.context.shotOutcomeSelection[arg]=='onNet'){ type +=' On Net' } if ($scope.context.shotOutcomeSelection[arg]=='missed'){ type +=' Missed' } if ($scope.context.shotOutcomeSelection[arg]=='blocked'){ type +=' Blocked' } } } eventDisplayName += 's'; type += ' ' + eventDisplayName; } } else { type+=','; } } returnString+=type; if ($scope.context.manpowerSituation == 'evenStrength') { returnString += ", at even strength"; } else if ($scope.context.manpowerSituation == 'powerPlay') { returnString += ", in power play"; } else if ($scope.context.manpowerSituation == 'shortHanded') { returnString += ", short handed"; } if ($scope.context.periodType != 'all') { if ($scope.context.periodType == 'regular') { returnString += ", regular time"; } else if ($scope.context.periodType == 'overTime') { returnString += ", overtime "; } } var today = new Date(); var dd = today.getDate(); var mm = today.getMonth()+1; //January is 0! var yyyy = today.getFullYear(); if(dd<10) { dd='0'+dd } if(mm<10) { mm='0'+mm } today = yyyy+'-'+mm+'-'+dd; $scope.today=today; var startDate = $scope.season ? $scope.season.startDate : $scope.filterSet['minDate']; if($scope.filterSet['maxDate']== $scope.today&&$scope.filterSet['minDate']!=startDate){ returnString += ', since ' + $scope.filterSet['minDate'] ; } else if($scope.filterSet['maxDate']!= $scope.today&&$scope.filterSet['minDate']==startDate){ returnString += ', up to ' + $scope.filterSet['maxDate'] ; } else if ($scope.filterSet['maxDate']!= $scope.today&&$scope.filterSet['minDate']!=startDate) { returnString += ', from ' + $scope.filterSet['minDate'] ; returnString += ' to ' + $scope.filterSet['maxDate'] ; } return returnString; } $scope.registerVideoPlayer = function (id, handlers) { if (id == $scope.slId + '-event-video-player') { $scope.eventPlaybackContext.playbackHandlers = handlers; } else if (id == $scope.slId + '-playlist-video-player') { $scope.playListPlaybackContext.playbackHandlers = handlers; } } $scope.deactivateVideo = function () { $scope.eventPlaybackContext.isVideoPlayerActive = false; $scope.eventPlaybackContext.playbackHandlers.deactivateVideo(); $scope.playListPlaybackContext.isVideoPlayerActive = false; $scope.playListPlaybackContext.playbackHandlers.deactivateVideo(); mixpanelAPI.send('closePlaybackDialog', $scope.decorateDetailsWithContextInfo({ "view": $scope.slId })); } $scope.eventPlaybackContext = { isVideoPlayerActive : false, event : null, playbackHandlers : null }; $scope.playListPlaybackContext = { isVideoPlayerActive : false, playbackHandlers : null }; $scope.playbackEvent = function (event) { } $scope.populateEventPlayerInfo = function (event) { if (typeof event.playerInfo === 'undefined') { var playerInfo = {}; if ($scope.mode == 'player') { var playerDetails = $scope.player; } else { var playerDetails = $scope.allPlayers[event.playerId]; } playerInfo.id = playerDetails.id; playerInfo.firstName = playerDetails.firstName; playerInfo.lastName = playerDetails.lastName; playerInfo.playerPosition = playerDetails.position; var team = playerDetails.team; playerInfo.team = {}; playerInfo.team.id = team.id; playerInfo.team.location = team.location; playerInfo.team.name = team.name; event.playerInfo = playerInfo; } }; // All ViewModel data related to the User Playlists $scope.playlistCreator = playlistCreator; // End User Playlist Data $scope.playbackPlayListInternal = function () { if ($scope.data.filtered.length > 0) { $scope.data.filtered.sort(function(a, b) { return (parseFloat(Date.parse(a.date)/1000) + parseFloat(a.gameTime)) - (parseFloat(Date.parse(b.date)/1000) + parseFloat(b.gameTime)); }); if ($scope.playListPlaybackContext.isVideoPlayerActive == false) { $scope.playListPlaybackContext.isVideoPlayerActive = true; } for (var i=0; i < $scope.data.filtered.length; i++) { $scope.populateEventPlayerInfo($scope.data.filtered[i]); } mixpanelAPI.send('playbackEventList', $scope.decorateDetailsWithContextInfo({ "view": $scope.slId, "numberOfEvents": $scope.data.filtered.length, "shotOutcomeSelection": $scope.context.shotOutcomeSelection, "eventOutcomeSelection": $scope.context.eventOutcomeSelection, "manpowerSituationFilter": $scope.context.manpowerSituation, "eventTypeEventFilter": $scope.context.eventsSelection.set })); $rootScope.$broadcast('eventSelection::Reset'); $scope.playListPlaybackContext.playbackHandlers.playbackEventList($scope.data.filtered); } } $scope.restartPlayList = function () { $scope.playListPlaybackContext.playbackHandlers.deactivateVideo(); $scope.playbackPlayListInternal(); mixpanelAPI.send('restartPlayList', $scope.decorateDetailsWithContextInfo({ "view": $scope.slId })); } $scope.onEventPlaybackStart = function (id, event) { mixpanelAPI.send('playbackStart', $scope.decorateDetailsWithContextInfo( mixpanelAPI.decorateDetailsWithGameInfo({ "view": $scope.slId, "event": event.id, "eventName": event.name, "shorthand": event.shorthand, "period": event.period, "toFrame": event.frame }, event.game))); } $scope.onTogglePlayPause = function () { mixpanelAPI.send('togglePlayPause', $scope.decorateDetailsWithContextInfo({ "view": $scope.slId })); } $scope.onSkipFwd = function () { mixpanelAPI.send('skipFwd', $scope.decorateDetailsWithContextInfo({ "view": $scope.slId })); } $scope.onSkipBack = function () { mixpanelAPI.send('skipBack', $scope.decorateDetailsWithContextInfo({ "view": $scope.slId })); } $scope.onSetSpeed = function (id, newSpeed) { $scope.playListPlaybackContext.playbackHandlers.setSpeed(newSpeed); $scope.eventPlaybackContext.playbackHandlers.setSpeed(newSpeed); mixpanelAPI.send('setSpeed', $scope.decorateDetailsWithContextInfo({ "view": $scope.slId, "speed": newSpeed })); } $scope.decorateDetailsWithContextInfo = function (details) { if ($scope.mode == 'team') { return mixpanelAPI.decorateDetailsWithTeamInfo(details, $scope.team); } if ($scope.mode == 'player') { return mixpanelAPI.decorateDetailsWithPlayerInfo(details, $scope.player); } } } // end of controller }; // end of directoive factory });