<commit_before>(function (mt) {


    mt.MixTubeApp.controller('mtPlaylistCtrl', function ($scope, $rootScope, $q, mtYoutubeClient, mtLogger) {

        /**  @type {mt.model.PlaylistEntry} */
        $scope.activePlaylistEntry = undefined;
        /**  @type {Array.<mt.model.PlaylistEntry>} */
        $scope.playlistEntries = mt.tools.TEST_VIDEOS.map(function (video) {
            var playlistEntry = new mt.model.PlaylistEntry();
            playlistEntry.id = mt.tools.uniqueId();
            playlistEntry.video = video;
            return playlistEntry;
        });

        /**
         * Finds the first next video in the playlist that still exist.
         *
         * Video can be removed from the remote provider so we have to check that before loading a video to prevent
         * playback interruption.
         *
         * @param {number} startPosition the position from where to start to look for the next valid video
         * @return {Promise} a promise with that provides the video instance when an existing video is found
         */
        var findNextValidPlaylistEntry = function (startPosition) {
            var deferred = $q.defer();

            var tryPosition = startPosition + 1;
            if (startPosition < $scope.playlistEntries.length) {
                var playlistEntry = $scope.playlistEntries[tryPosition];
                mtYoutubeClient.pingVideoById(playlistEntry.video.id).then(function (videoExists) {
                    if (videoExists) {
                        deferred.resolve(playlistEntry);
                    } else {
                        findNextValidPlaylistEntry(tryPosition).then(deferred.resolve);
                    }
                });
            }

            return deferred.promise;
        };

        var triggerPlaylistModified = function (modifiedPositions) {
            var activePosition = $scope.playlistEntries.indexOf($scope.activePlaylistEntry);
            $rootScope.$broadcast(mt.events.PlaylistModified, {
                activePosition: activePosition,
                modifiedPositions: modifiedPositions
            });
        };


        $scope.$on(mt.events.NextPlaylistEntryRequest, function () {
            mtLogger.debug('Next playlist entry request received');

            var activePosition = $scope.playlistEntries.indexOf($scope.activePlaylistEntry);
            findNextValidPlaylistEntry(activePosition).then(function (playlistEntry) {
                $rootScope.$broadcast(mt.events.LoadPlaylistEntryRequest, {playlistEntry: playlistEntry, autoplay: false});
            });
        });
<commit_msg>fixed a a bug that generated a stack trace when pinging the video for the last palylist entry<commit_after>(function (mt) {


    mt.MixTubeApp.controller('mtPlaylistCtrl', function ($scope, $rootScope, $q, mtYoutubeClient, mtLogger) {

        /**  @type {mt.model.PlaylistEntry} */
        $scope.activePlaylistEntry = undefined;
        /**  @type {Array.<mt.model.PlaylistEntry>} */
        $scope.playlistEntries = mt.tools.TEST_VIDEOS.map(function (video) {
            var playlistEntry = new mt.model.PlaylistEntry();
            playlistEntry.id = mt.tools.uniqueId();
            playlistEntry.video = video;
            return playlistEntry;
        });

        /**
         * Finds the first next video in the playlist that still exist.
         *
         * Video can be removed from the remote provider so we have to check that before loading a video to prevent
         * playback interruption.
         *
         * @param {number} startPosition the position from where to start to look for the next valid video
         * @return {Promise} a promise with that provides the video instance when an existing video is found
         */
        var findNextValidPlaylistEntry = function (startPosition) {
            var deferred = $q.defer();

            var tryPosition = startPosition + 1;
            if (tryPosition < $scope.playlistEntries.length) {
                var playlistEntry = $scope.playlistEntries[tryPosition];
                mtYoutubeClient.pingVideoById(playlistEntry.video.id).then(function (videoExists) {
                    if (videoExists) {
                        deferred.resolve(playlistEntry);
                    } else {
                        findNextValidPlaylistEntry(tryPosition).then(deferred.resolve);
                    }
                });
            } else {
                deferred.reject();
            }

            return deferred.promise;
        };

        var triggerPlaylistModified = function (modifiedPositions) {
            var activePosition = $scope.playlistEntries.indexOf($scope.activePlaylistEntry);
            $rootScope.$broadcast(mt.events.PlaylistModified, {
                activePosition: activePosition,
                modifiedPositions: modifiedPositions
            });
        };


        $scope.$on(mt.events.NextPlaylistEntryRequest, function () {
            mtLogger.debug('Next playlist entry request received');

            var activePosition = $scope.playlistEntries.indexOf($scope.activePlaylistEntry);
            findNextValidPlaylistEntry(activePosition).then(function (playlistEntry) {
                $rootScope.$broadcast(mt.events.LoadPlaylistEntryRequest, {playlistEntry: playlistEntry, autoplay: false});
            });
        });

{'fraction_non_alphanumeric': 0.09152035861038475, 'fraction_numerical': 0.00037355248412401944, 'mean_word_length': 2.118811881188119, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3729870', 'n_tokens_mistral': 1354, 'n_tokens_neox': 1296, 'n_words': 315}