<commit_before>var ReceiverAdsManager = null;

$( window ).bind( 'onReceiverKDPReady', function ( event ) {
    ReceiverLogger.log( "ReceiverAdsManager", "event-->onReceiverKDPReady", { 'adsEnabled?': kdp.evaluate( '{doubleClick.plugin}' ) } );
    if ( kdp.evaluate( '{doubleClick.plugin}' ) ) {
        ReceiverAdsManager = new AdsManager();
    }
} );

$( window ).bind( 'onReceiverReplay', function () {
    ReceiverLogger.log( "ReceiverAdsManager", "event-->onReceiverReplay" );
    if ( ReceiverAdsManager ) {
        ReceiverAdsManager.destroy();
    }
} );

$( window ).bind( 'onReceiverChangeMedia', function ( event, withAds ) {
    ReceiverLogger.log( "ReceiverAdsManager", "event-->onReceiverChangeMedia", { "withAds": withAds } );
    if ( ReceiverAdsManager ) {
        ReceiverAdsManager.destroy();
    }
    if ( withAds ) {
        ReceiverAdsManager = new AdsManager();
    }
} );

function AdsManager() {
    this.CLASS_NAME = 'ReceiverAdsManager';
    this._init();
}

AdsManager.prototype = {

    /**
     * Destroy the ads manager.
     */
    destroy: function () {
        ReceiverLogger.log( this.CLASS_NAME, "destroy" );
        /**
         * Return all the original implementations of media manager.
         * @type {*}
         */
        if ( !ReceiverQueueManager.isQueueActive() ) {
            mediaManager.customizedStatusCallback = mediaManager.customizedStatusCallbackOrig_ReceiverAdsManager;
        } else {
            ReceiverQueueManager.mediaStatusCallbackUnSubscribe();
        }
        mediaManager.onEnded = mediaManager.onEndedOrig;
        mediaManager.onPause = mediaManager.onPauseOrig;

        /**
         * Unbind kdp from all ads specific events.
         */
        kdp.kUnbind( "onCuePointsRevealed" );
        kdp.kUnbind( "durationChange" );
        kdp.kUnbind( "adErrorEvent" );
        kdp.kUnbind( "onAdPlay" );
        kdp.kUnbind( "preSequenceStart" );
        kdp.kUnbind( "preSequenceComplete" );
        kdp.kUnbind( "postSequenceStart" );
        kdp.kUnbind( "postSequenceComplete" );
        kdp.kUnbind( "onAllAdsCompleted" );

        ReceiverAdsManager = null;
    },

    /**
     * Returns whether the receiver playing an ad.
     * @returns {boolean}
     */
    isPlayingAd: function () {
        return this.adsInfo.isPlayingAd;
    },

    /**
     * Init the ads manager.
     * @private
     */
    _init: function () {
        ReceiverLogger.log( this.CLASS_NAME, "_init" );
        /**
         * The ad info object which sent on media status update to all senders.
         * @type {{adsBreakInfo: Array, isPlayingAd: boolean}}
         */
        this.adsInfo = { adsBreakInfo: [], isPlayingAd: false };
        /**
         * Indicator to know when all ads completed.
         * Will be called according to the adTagUrl.
         * For example:
         * If the adTagUrl contains only prerolls it will be called in the end of pre sequence.
         * If the adTagUrl contains only postrolls it will be called in the end of post sequence.
         * If the adTagUrl contains both prerolls & postrolls it will be called in the end of post sequence.
         * @type {boolean}
         */
        this.allAdsCompleted = false;
        /**
         * Indicator to know when post sequence starts to play (postrolls).
         * It's because we need to know when to call onEnded explicitly.
         * For example:
         * In the scenario of just prerolls, onAllAdsCompleted event will be called
         * before the content has start to play. In that case, we don't want to
         * call onEnded explicitly because it will then shutdown the receiver application.
         * To make a long story short, the only scenarios we will want to call onEnded explicitly
         * are when we playing postrolls.
         * @type {boolean}
         */
        this.postSequenceStart = false;
        /**
         * Indicates when the receiver has start to play for the first time when ads are enabled.
         * @type {boolean}
         */
        this.startPlayingWithAds = false;

        /**
         * Override all the necessary events of mediaManager to support IMA plugin on Chromecast.
         * @type {*}
         */
        if ( !ReceiverQueueManager.isQueueActive() ) {
            mediaManager.customizedStatusCallbackOrig_ReceiverAdsManager = mediaManager.customizedStatusCallback;
            mediaManager.customizedStatusCallback = this._customizedStatusCallback.bind( this );
        } else {
            ReceiverQueueManager.mediaStatusCallbackSubscribe( this._customizedStatusCallback.bind( this ) );
        }

        mediaManager.onEndedOrig = mediaManager.onEnded.bind( mediaManager );
        mediaManager.onEnded = this._onEnded.bind( this );

        mediaManager.onPauseOrig = mediaManager.onPause;
        mediaManager.onPause = this._onPause.bind( this );

        /**
         * Bind to the kdp ads specific events.
         */
        kdp.kBind( "onCuePointsRevealed", this._onCuePointsRevealed.bind( this ) );
        kdp.kBind( "durationChange", this._onDurationChange.bind( this ) );
        kdp.kBind( "adErrorEvent", this._onAdErrorEvent.bind( this ) );
        kdp.kBind( "onAdPlay", this._onAdPlay.bind( this ) );
        kdp.kBind( "preSequenceStart", this._onPreSequenceStart.bind( this ) );
        kdp.kBind( "preSequenceComplete", this._onPreSequenceComplete.bind( this ) );
        kdp.kBind( "postSequenceStart", this._onPostSequenceStart.bind( this ) );
        kdp.kBind( "postSequenceComplete", this._onPostSequenceComplete.bind( this ) );
        kdp.kBind( "onAllAdsCompleted", this._onAllAdsCompleted.bind( this ) );
    },

    /**
     * Override callback for media manager customizedStatusCallback.
     * @param mediaStatus
     * @returns mediaStatus
     * @private
     */
    _customizedStatusCallback: function ( mediaStatus ) {
        if ( !mediaStatus.customData ) {
            mediaStatus.customData = {};
        }
        var isIdle = mediaStatus.playerState === StateManager.State.IDLE;
        if ( this.startPlayingWithAds ) {
            if ( mediaStatus.customData.forceStatus ) {
                mediaStatus.playerState = mediaStatus.customData.forceStatus;
            } else if ( isIdle && !this.allAdsCompleted ) {
                mediaStatus.playerState = StateManager.State.PLAYING;
            }
        } else if ( mediaStatus.playerState === StateManager.State.PLAYING ) {
            this.startPlayingWithAds = true;
        }
        mediaStatus.customData.adsInfo = this.adsInfo;
        ReceiverLogger.log( this.CLASS_NAME, "_customizedStatusCallback_" + this.CLASS_NAME + " - Returning sender playerState of: "
            + mediaStatus.playerState, mediaStatus );

        return mediaStatus;
    },

    /**
     * Override callback for media manager onEnded.
     * @private
     */
    _onEnded: function () {
        ReceiverLogger.log( this.CLASS_NAME, "_onEnded", { 'allAdsCompleted': this.allAdsCompleted } );
        if ( this.allAdsCompleted ) {
            mediaManager.onEndedOrig();
        } else {
            mediaManager.broadcastStatus( false );
        }
    },

    /**
     * Override callback for media manager onPause.
     * @param event
     * @private
     */
    _onPause: function ( event ) {
        ReceiverLogger.log( this.CLASS_NAME, "_onPause", event );
        kdp.sendNotification( "doPause" );
        if ( this.adsInfo.isPlayingAd ) {
            // We have an issue that if sender pause in middle of an ad it sending the wrong status (PLAYING)
            // We need to understand the root cause
            mediaManager.broadcastStatus( false, event.data.requestId, {
                forceStatus: StateManager.State.PAUSED
            } );
        } else {
            mediaManager.broadcastStatus( false, event.data.requestId );
        }
    },

    /**
     * Handles the ads cue point which ima plugin revealed.
     * @param cuePoints
     * @private
     */
    _onCuePointsRevealed: function ( cuePoints ) {
        var adsBreakOrig = JSON.parse( cuePoints );
        ReceiverLogger.log( this.CLASS_NAME, "_onCuePointsRevealed", adsBreakOrig );
        for ( var i = 0; i < adsBreakOrig.length; i++ ) {
            var adBreak = adsBreakOrig[ i ];
            switch ( adBreak ) {
                case 0:
                    this.adsInfo.adsBreakInfo.push( adBreak );
                    break;
                case -1:
                    var mediaInfo = mediaManager.getMediaInformation();
                    if ( mediaInfo ) {
                        if ( mediaInfo.duration ) {
                            this.adsInfo.adsBreakInfo.push( mediaInfo.duration );
                        } else {
                            kdp.kBind( "receiverContentPlay", function ( contentDuration ) {
                                this.adsInfo.adsBreakInfo.push( Math.round( contentDuration ) );
                                mediaManager.broadcastStatus( false );
                                kdp.kUnbind( "receiverContentPlay" );
                            }.bind( this ) );
                        }
                    }
                    break;
                default:
                    break;
            }
        }
        mediaManager.broadcastStatus( false );
    },

    /**
     * Handles the change of duration on the video element.
     * @param event
     * @private
     */
    _onDurationChange: function ( event ) {
        var mediaInfo = mediaManager.getMediaInformation();
        if ( mediaInfo ) {
            ReceiverLogger.log( this.CLASS_NAME, "_onDurationChange", { 'newDuration': event.newValue } );
            mediaInfo.duration = event.newValue;
            mediaManager.setMediaInformation( mediaInfo );
            mediaManager.broadcastStatus( true );
        }
    },

    /**
     * Dispatch when error occurred when trying to play an ad.
     * @private
     */
    _onAdErrorEvent: function () {
        ReceiverLogger.error( this.CLASS_NAME, "_onAdErrorEvent" );
    },

    /**
     * Dispatch when ad starts to play.
     * @private
     */
    _onAdPlay: function () {
        ReceiverLogger.log( this.CLASS_NAME, "_onAdPlay, isPlayingAd=true" );
        this.adsInfo.isPlayingAd = true;
        mediaManager.broadcastStatus( false );
    },

    /**
     * Dispatch when pre sequence of ads starts.
     * @private
     */
    _onPreSequenceStart: function () {
        ReceiverStateManager.onShowMediaMetadata( false );
    },

    /**
     * Dispatch when pre sequence of ads completed.
     * @private
     */
    _onPreSequenceComplete: function () {
        ReceiverLogger.log( this.CLASS_NAME, "_onPreSequenceComplete, isPlayingAd=false" );
        this.adsInfo.isPlayingAd = false;
        mediaManager.broadcastStatus( false );
    },

    /**
     * Dispatch when post sequence of ads starts.
     * @private
     */
    _onPostSequenceStart: function () {
        this.postSequenceStart = true;
    },

    /**
     * Dispatch when post sequence of ads completed.
     * @private
     */
    _onPostSequenceComplete: function () {
        ReceiverLogger.log( this.CLASS_NAME, "_onPostSequenceComplete, isPlayingAd=false" );
        this.adsInfo.isPlayingAd = false;
        mediaManager.broadcastStatus( false );
    },

    /**
     * Dispatch when all ads completed to play.
     * @private
     */
    _onAllAdsCompleted: function () {
        this.allAdsCompleted = true;
        if ( this.postSequenceStart ) {
            this._onEnded();
        }
    }
};<commit_msg>FEC-6979 - Destroy ads manager on ad error (#3609)<commit_after>var ReceiverAdsManager = null;

$( window ).bind( 'onReceiverKDPReady', function ( event ) {
    ReceiverLogger.log( "ReceiverAdsManager", "event-->onReceiverKDPReady", { 'adsEnabled?': kdp.evaluate( '{doubleClick.plugin}' ) } );
    if ( kdp.evaluate( '{doubleClick.plugin}' ) ) {
        ReceiverAdsManager = new AdsManager();
    }
} );

$( window ).bind( 'onReceiverReplay', function () {
    ReceiverLogger.log( "ReceiverAdsManager", "event-->onReceiverReplay" );
    if ( ReceiverAdsManager ) {
        ReceiverAdsManager.destroy();
    }
} );

$( window ).bind( 'onReceiverChangeMedia', function ( event, withAds ) {
    ReceiverLogger.log( "ReceiverAdsManager", "event-->onReceiverChangeMedia", { "withAds": withAds } );
    if ( ReceiverAdsManager ) {
        ReceiverAdsManager.destroy();
    }
    if ( withAds ) {
        ReceiverAdsManager = new AdsManager();
    }
} );

function AdsManager() {
    this.CLASS_NAME = 'ReceiverAdsManager';
    this._init();
}

AdsManager.prototype = {

    /**
     * Destroy the ads manager.
     */
    destroy: function () {
        ReceiverLogger.log( this.CLASS_NAME, "destroy" );
        /**
         * Return all the original implementations of media manager.
         * @type {*}
         */
        if ( !ReceiverQueueManager.isQueueActive() ) {
            mediaManager.customizedStatusCallback = mediaManager.customizedStatusCallbackOrig_ReceiverAdsManager;
        } else {
            ReceiverQueueManager.mediaStatusCallbackUnSubscribe();
        }
        mediaManager.onEnded = mediaManager.onEndedOrig;
        mediaManager.onPause = mediaManager.onPauseOrig;

        /**
         * Unbind kdp from all ads specific events.
         */
        kdp.kUnbind( "onCuePointsRevealed" );
        kdp.kUnbind( "durationChange" );
        kdp.kUnbind( "adErrorEvent" );
        kdp.kUnbind( "onAdPlay" );
        kdp.kUnbind( "preSequenceStart" );
        kdp.kUnbind( "preSequenceComplete" );
        kdp.kUnbind( "postSequenceStart" );
        kdp.kUnbind( "postSequenceComplete" );
        kdp.kUnbind( "onAllAdsCompleted" );

        ReceiverAdsManager = null;
    },

    /**
     * Returns whether the receiver playing an ad.
     * @returns {boolean}
     */
    isPlayingAd: function () {
        return this.adsInfo.isPlayingAd;
    },

    /**
     * Init the ads manager.
     * @private
     */
    _init: function () {
        ReceiverLogger.log( this.CLASS_NAME, "_init" );
        /**
         * The ad info object which sent on media status update to all senders.
         * @type {{adsBreakInfo: Array, isPlayingAd: boolean}}
         */
        this.adsInfo = { adsBreakInfo: [], isPlayingAd: false };
        /**
         * Indicator to know when all ads completed.
         * Will be called according to the adTagUrl.
         * For example:
         * If the adTagUrl contains only prerolls it will be called in the end of pre sequence.
         * If the adTagUrl contains only postrolls it will be called in the end of post sequence.
         * If the adTagUrl contains both prerolls & postrolls it will be called in the end of post sequence.
         * @type {boolean}
         */
        this.allAdsCompleted = false;
        /**
         * Indicator to know when post sequence starts to play (postrolls).
         * It's because we need to know when to call onEnded explicitly.
         * For example:
         * In the scenario of just prerolls, onAllAdsCompleted event will be called
         * before the content has start to play. In that case, we don't want to
         * call onEnded explicitly because it will then shutdown the receiver application.
         * To make a long story short, the only scenarios we will want to call onEnded explicitly
         * are when we playing postrolls.
         * @type {boolean}
         */
        this.postSequenceStart = false;
        /**
         * Indicates when the receiver has start to play for the first time when ads are enabled.
         * @type {boolean}
         */
        this.startPlayingWithAds = false;

        /**
         * Override all the necessary events of mediaManager to support IMA plugin on Chromecast.
         * @type {*}
         */
        if ( !ReceiverQueueManager.isQueueActive() ) {
            mediaManager.customizedStatusCallbackOrig_ReceiverAdsManager = mediaManager.customizedStatusCallback;
            mediaManager.customizedStatusCallback = this._customizedStatusCallback.bind( this );
        } else {
            ReceiverQueueManager.mediaStatusCallbackSubscribe( this._customizedStatusCallback.bind( this ) );
        }

        mediaManager.onEndedOrig = mediaManager.onEnded.bind( mediaManager );
        mediaManager.onEnded = this._onEnded.bind( this );

        mediaManager.onPauseOrig = mediaManager.onPause;
        mediaManager.onPause = this._onPause.bind( this );

        /**
         * Bind to the kdp ads specific events.
         */
        kdp.kBind( "onCuePointsRevealed", this._onCuePointsRevealed.bind( this ) );
        kdp.kBind( "durationChange", this._onDurationChange.bind( this ) );
        kdp.kBind( "adErrorEvent", this._onAdErrorEvent.bind( this ) );
        kdp.kBind( "onAdPlay", this._onAdPlay.bind( this ) );
        kdp.kBind( "preSequenceStart", this._onPreSequenceStart.bind( this ) );
        kdp.kBind( "preSequenceComplete", this._onPreSequenceComplete.bind( this ) );
        kdp.kBind( "postSequenceStart", this._onPostSequenceStart.bind( this ) );
        kdp.kBind( "postSequenceComplete", this._onPostSequenceComplete.bind( this ) );
        kdp.kBind( "onAllAdsCompleted", this._onAllAdsCompleted.bind( this ) );
    },

    /**
     * Override callback for media manager customizedStatusCallback.
     * @param mediaStatus
     * @returns mediaStatus
     * @private
     */
    _customizedStatusCallback: function ( mediaStatus ) {
        if ( !mediaStatus.customData ) {
            mediaStatus.customData = {};
        }
        var isIdle = mediaStatus.playerState === StateManager.State.IDLE;
        if ( this.startPlayingWithAds ) {
            if ( mediaStatus.customData.forceStatus ) {
                mediaStatus.playerState = mediaStatus.customData.forceStatus;
            } else if ( isIdle && !this.allAdsCompleted ) {
                mediaStatus.playerState = StateManager.State.PLAYING;
            }
        } else if ( mediaStatus.playerState === StateManager.State.PLAYING ) {
            this.startPlayingWithAds = true;
        }
        mediaStatus.customData.adsInfo = this.adsInfo;
        ReceiverLogger.log( this.CLASS_NAME, "_customizedStatusCallback_" + this.CLASS_NAME + " - Returning sender playerState of: "
            + mediaStatus.playerState, mediaStatus );

        return mediaStatus;
    },

    /**
     * Override callback for media manager onEnded.
     * @private
     */
    _onEnded: function () {
        ReceiverLogger.log( this.CLASS_NAME, "_onEnded", { 'allAdsCompleted': this.allAdsCompleted } );
        if ( this.allAdsCompleted ) {
            mediaManager.onEndedOrig();
        } else {
            mediaManager.broadcastStatus( false );
        }
    },

    /**
     * Override callback for media manager onPause.
     * @param event
     * @private
     */
    _onPause: function ( event ) {
        ReceiverLogger.log( this.CLASS_NAME, "_onPause", event );
        kdp.sendNotification( "doPause" );
        if ( this.adsInfo.isPlayingAd ) {
            // We have an issue that if sender pause in middle of an ad it sending the wrong status (PLAYING)
            // We need to understand the root cause
            mediaManager.broadcastStatus( false, event.data.requestId, {
                forceStatus: StateManager.State.PAUSED
            } );
        } else {
            mediaManager.broadcastStatus( false, event.data.requestId );
        }
    },

    /**
     * Handles the ads cue point which ima plugin revealed.
     * @param cuePoints
     * @private
     */
    _onCuePointsRevealed: function ( cuePoints ) {
        var adsBreakOrig = JSON.parse( cuePoints );
        ReceiverLogger.log( this.CLASS_NAME, "_onCuePointsRevealed", adsBreakOrig );
        for ( var i = 0; i < adsBreakOrig.length; i++ ) {
            var adBreak = adsBreakOrig[ i ];
            switch ( adBreak ) {
                case 0:
                    this.adsInfo.adsBreakInfo.push( adBreak );
                    break;
                case -1:
                    var mediaInfo = mediaManager.getMediaInformation();
                    if ( mediaInfo ) {
                        if ( mediaInfo.duration ) {
                            this.adsInfo.adsBreakInfo.push( mediaInfo.duration );
                        } else {
                            kdp.kBind( "receiverContentPlay", function ( contentDuration ) {
                                this.adsInfo.adsBreakInfo.push( Math.round( contentDuration ) );
                                mediaManager.broadcastStatus( false );
                                kdp.kUnbind( "receiverContentPlay" );
                            }.bind( this ) );
                        }
                    }
                    break;
                default:
                    break;
            }
        }
        mediaManager.broadcastStatus( false );
    },

    /**
     * Handles the change of duration on the video element.
     * @param event
     * @private
     */
    _onDurationChange: function ( event ) {
        var mediaInfo = mediaManager.getMediaInformation();
        if ( mediaInfo ) {
            ReceiverLogger.log( this.CLASS_NAME, "_onDurationChange", { 'newDuration': event.newValue } );
            mediaInfo.duration = event.newValue;
            mediaManager.setMediaInformation( mediaInfo );
            mediaManager.broadcastStatus( true );
        }
    },

    /**
     * Dispatch when error occurred when trying to play an ad.
     * @private
     */
    _onAdErrorEvent: function () {
        ReceiverLogger.error( this.CLASS_NAME, "_onAdErrorEvent" );
        this.destroy();
    },

    /**
     * Dispatch when ad starts to play.
     * @private
     */
    _onAdPlay: function () {
        ReceiverLogger.log( this.CLASS_NAME, "_onAdPlay, isPlayingAd=true" );
        this.adsInfo.isPlayingAd = true;
        mediaManager.broadcastStatus( false );
    },

    /**
     * Dispatch when pre sequence of ads starts.
     * @private
     */
    _onPreSequenceStart: function () {
        ReceiverStateManager.onShowMediaMetadata( false );
    },

    /**
     * Dispatch when pre sequence of ads completed.
     * @private
     */
    _onPreSequenceComplete: function () {
        ReceiverLogger.log( this.CLASS_NAME, "_onPreSequenceComplete, isPlayingAd=false" );
        this.adsInfo.isPlayingAd = false;
        mediaManager.broadcastStatus( false );
    },

    /**
     * Dispatch when post sequence of ads starts.
     * @private
     */
    _onPostSequenceStart: function () {
        this.postSequenceStart = true;
    },

    /**
     * Dispatch when post sequence of ads completed.
     * @private
     */
    _onPostSequenceComplete: function () {
        ReceiverLogger.log( this.CLASS_NAME, "_onPostSequenceComplete, isPlayingAd=false" );
        this.adsInfo.isPlayingAd = false;
        mediaManager.broadcastStatus( false );
    },

    /**
     * Dispatch when all ads completed to play.
     * @private
     */
    _onAllAdsCompleted: function () {
        this.allAdsCompleted = true;
        if ( this.postSequenceStart ) {
            this._onEnded();
        }
    }
};<|endoftext|>


<commit_before>// game.js
// ========
"use strict";
module.exports = {
  map: function(size) {
   this.size = size || 70;
   function tile(properties) {
     //constructor
       if (properties.hasOwnProperty("x") && properties.hasOwnProperty("y")) {
           if(properties.x >= 0 && properties.y >= 0) {
             this.x = properties.x || 0;
             this.y = properties.y || 0;
           }
       }
     if (properties.hasOwnProperty("color")) {
         this.color = properties.color || "#ffffff";
     }
     if (properties.hasOwnProperty("kind")) {
       this.kind = null;
       switch (properties.Type) {
         case "floor":
         //floor
           this.kind = 0;
           break;
         default:
         //wall
         this.kind = 1;

       }
     }
     //Construct the list of items and players on the tile
     if (properties.hasOwnProperty("objects")) {
       this.objects =  new Array();
       if (Array.isArray(properties.objects)) {
           for (var i = 0; i < properties.objects.length; i++) {
             this.objects.push(properties.objects[i]);
           }
       }
     }
   }
   tile.prototype.getTile = function () {
      return {
            "objects":[],
            "color": this.color
      }
   };
   //create map
  this.mapArray = new Array();
   for (var i = 0; i < size; i++) {
     this.mapArray[i] =  new Array();
     for (var l = 0; l < size; l++) {
       var tileType = 0;
       var colorVal = "#ffffff";
       if ((i === 0) || (l === 0) || (i === this.size-1) || (l === this.size-1) ) {
         tileType = 1;
         colorVal = "#000000";
       }
      this.mapArray[i][l] = new tile({
         "x": i,
         "y": l,
         "color": colorVal,
         "objects": {},
         "kind": tileType
       });
     }
   }
 }
};
module.exports.map.prototype.getAbove = function (x,y) {
/*  if (y > this.mapArray.length) {
    return mapArray[x][0];
  }
  if (y < 0) {
    return mapArray[x][mapArray.length];
  }*/
  return this.mapArray[x][y+1];
};
module.exports.map.prototype.getBelow = function (x,y) {
return this.mapArray[x][y-1];
};
module.exports.map.prototype.getRight = function (x,y) {
return this.mapArray[x+1][y];
};
module.exports.map.prototype.getLeft = function (x,y) {
return this.mapArray[x-1][y];
};
module.exports.map.prototype.getTile = function (x,y) {
return this.mapArray[x][y];
};
module.exports.map.prototype.setTile = function (x,y,element) {
 this.mapArray[x][y] = element;
};
module.exports.map.prototype.setPlayer = function (x,y,player) {
    function getRandomColor() {
     var letters = '0123456789ABCDEF'.split('');
     var color = '#';
     for (var i = 0; i < 6; i++ ) {
         color += letters[Math.floor(Math.random() * 16)];
     }
     return color;
   }
 this.mapArray[x][y].objects[String(player)] = getRandomColor();
};
module.exports.map.prototype.movePlayer = function (x,y,direction,player) {
  console.log(x,y,direction,player);
  console.log(this.mapArray[x][y].objects);
  //first verify that player is on the tile
  if (this.mapArray[x][y].objects.hasOwnProperty(String(player))) {
    switch(expression) {
    case "up":
    if( this.mapArray[x][y-1].kind != 1) {
     this.mapArray[x][y-1].objects[String(player)] = this.mapArray[x][y].objects[String(player)];
     delete this.mapArray[x][y].objects[String(player)]; // remove reference to player on previous tile
   }
        break;
    case "down":
    if( this.mapArray[x][y+1].kind != 1) {
     this.mapArray[x][y+1].objects[String(player)] = this.mapArray[x][y].objects[String(player)];
     delete this.mapArray[x][y].objects[String(player)]; // remove reference to player on previous tile
   }
        break;
    default:

}
  }
};
module.exports.map.prototype.printMap = function() {
var mapVals = new Array();
  for (var i = 0; i < this.mapArray.length; i++) {
    mapVals[i] = [];
      for (var l = 0; l < this.mapArray[i].length; l++) {
        if ( Object.keys(this.mapArray[i][l].objects).length > 0 ) {
          for (var key in this.mapArray[i][l].objects) {
            mapVals[i][l] = this.mapArray[i][l].objects[key];
          }
        } else {
            mapVals[i][l] = this.mapArray[i][l].getTile();
        }
      }
  }
  return mapVals;
};
<commit_msg>test2<commit_after>// game.js
// ========
"use strict";
module.exports = {
  map: function(size) {
   this.size = size || 70;
   function tile(properties) {
     //constructor
       if (properties.hasOwnProperty("x") && properties.hasOwnProperty("y")) {
           if(properties.x >= 0 && properties.y >= 0) {
             this.x = properties.x || 0;
             this.y = properties.y || 0;
           }
       }
     if (properties.hasOwnProperty("color")) {
         this.color = properties.color || "#ffffff";
     }
     if (properties.hasOwnProperty("kind")) {
       this.kind = null;
       switch (properties.Type) {
         case "floor":
         //floor
           this.kind = 0;
           break;
         default:
         //wall
         this.kind = 1;

       }
     }
     //Construct the list of items and players on the tile
     if (properties.hasOwnProperty("objects")) {
       this.objects =  new Array();
       if (Array.isArray(properties.objects)) {
           for (var i = 0; i < properties.objects.length; i++) {
             this.objects.push(properties.objects[i]);
           }
       }
     }
   }
   tile.prototype.getTile = function () {
    var color = "#ffffff";
    var objectKey = "";
    for (var key in this.objects) {
        color  = this.objects[key];
        objectKey =  key;
    }
    if (color === "#ffffff") {
      color = this.color;
    }
      return {
            "objects":objectKey,
            "color": color
      }
   };
   //create map
  this.mapArray = new Array();
   for (var i = 0; i < size; i++) {
     this.mapArray[i] =  new Array();
     for (var l = 0; l < size; l++) {
       var tileType = 0;
       var colorVal = "#ffffff";
       if ((i === 0) || (l === 0) || (i === this.size-1) || (l === this.size-1) ) {
         tileType = 1;
         colorVal = "#000000";
       }
      this.mapArray[i][l] = new tile({
         "x": i,
         "y": l,
         "color": colorVal,
         "objects": {},
         "kind": tileType
       });
     }
   }
 }
};
module.exports.map.prototype.getAbove = function (x,y) {
/*  if (y > this.mapArray.length) {
    return mapArray[x][0];
  }
  if (y < 0) {
    return mapArray[x][mapArray.length];
  }*/
  return this.mapArray[x][y+1];
};
module.exports.map.prototype.getBelow = function (x,y) {
return this.mapArray[x][y-1];
};
module.exports.map.prototype.getRight = function (x,y) {
return this.mapArray[x+1][y];
};
module.exports.map.prototype.getLeft = function (x,y) {
return this.mapArray[x-1][y];
};
module.exports.map.prototype.getTile = function (x,y) {
return this.mapArray[x][y];
};
module.exports.map.prototype.setTile = function (x,y,element) {
 this.mapArray[x][y] = element;
};
module.exports.map.prototype.setPlayer = function (x,y,player) {
    function getRandomColor() {
     var letters = '0123456789ABCDEF'.split('');
     var color = '#';
     for (var i = 0; i < 6; i++ ) {
         color += letters[Math.floor(Math.random() * 16)];
     }
     return color;
   }
 this.mapArray[x][y].objects[String(player)] = getRandomColor();
};
module.exports.map.prototype.movePlayer = function (x,y,direction,player) {
  console.log(x,y,direction,player);
  console.log(this.mapArray[x][y].objects);
  //first verify that player is on the tile
  if (this.mapArray[x][y].objects.hasOwnProperty(String(player))) {
    switch(expression) {
    case "up":
    if( this.mapArray[x][y-1].kind != 1) {
     this.mapArray[x][y-1].objects[String(player)] = this.mapArray[x][y].objects[String(player)];
     delete this.mapArray[x][y].objects[String(player)]; // remove reference to player on previous tile
   }
        break;
    case "down":
    if( this.mapArray[x][y+1].kind != 1) {
     this.mapArray[x][y+1].objects[String(player)] = this.mapArray[x][y].objects[String(player)];
     delete this.mapArray[x][y].objects[String(player)]; // remove reference to player on previous tile
   }
        break;
    default:

}
  }
};
module.exports.map.prototype.printMap = function() {
var mapVals = new Array();
  for (var i = 0; i < this.mapArray.length; i++) {
    mapVals[i] = [];
      for (var l = 0; l < this.mapArray[i].length; l++) {

            mapVals[i][l] = this.mapArray[i][l].getTile();

      }
  }
  return mapVals;
};
<|endoftext|>


<commit_before>
var t = 0;
const exec = require('child_process').exec;
exec('node nodejs_app/app.js', function(error, stdout, stderr){
  if (error) {
    console.error('exec error: ${error}');
	t =1;
    return 1;
  }
 else{

  console.log('stdout: ${stdout}');
  console.log('stderr: ${stderr}');
  return 0;
 }
});

exec('node nodejs_app/app.js', function(error, stdout, stderr){
  if (error) {
    console.error('exec error: ${error} + $?'+error);
	t =1;
		 exec('echo "Succeeded" && killall node');
	  return 0;

  }
 else{

  console.log('stdout: ${stdout}');
  console.log('stderr: ${stderr}');

  return 1;
 }
});
<commit_msg>Update testsA.js<commit_after>
var t = 0;
const exec = require('child_process').exec;
exec('node nodejs_app/app.js', function(error, stdout, stderr){
  if (error) {
    console.error('exec error: ${error}');
	t =1;
    return 1;
  }
 else{

  console.log('stdout: ${stdout}');
  console.log('stderr: ${stderr}');
  return 0;
 }
});

exec('node nodejs_app/app.js', function(error, stdout, stderr){
  if (error) {
    console.error('exec error: ${error} + $!');
	t =1;
		 exec('echo "Succeeded" && killall node');
	  return 0;

  }
 else{

  console.log('stdout: ${stdout}');
  console.log('stderr: ${stderr}');

  return 1;
 }
});
<|endoftext|>


<commit_before>output.out = uglify_js.minify(input.in, {fromString: true});
<commit_msg>rename input. to $.<commit_after>output.out = uglify_js.minify($.in, {fromString: true});
<|endoftext|>


<commit_before>var RequestEmailLists = {
    name: 'RequestEmailLists',
    dom_target: undefined,
    label: undefined,

    render_init: function(section_label) {
        RequestEmailLists.label = section_label;
        RequestEmailLists.dom_target = '#popup_emaillist_' + safe_label(RequestEmailLists.label);
        WSData.fetch_instructed_section_emaillist_data(section_label,
                                                       RequestEmailLists.render_upon_data,
                                                       RequestEmailLists.render_error);
    },

    render_upon_data: function() {
        if (WSData._instructed_emaillist_data[RequestEmailLists.label] === undefined) {
            return;
        }
        RequestEmailLists.render();
    },

    render_error: function() {
        var error_code = WSData._instructed_emaillist_data_error_status[RequestEmailLists.label];
        if (error_code == 543) {
            raw = CardWithError.render("Request Email List");
            $(RequestEmailLists.dom_target).html(raw);
        }
    },

    render: function() {
        var data = WSData._instructed_emaillist_data[RequestEmailLists.label];
        if (data.total_course_wo_list > 1) {
            data.multi_sections_wo_list = true;
        }
        var term = data.year + ',' + data.quarter;
        var source   = $("#request_email_lists_tmpl").html();
        var template = Handlebars.compile(source);
        var raw = template(data);
        $(RequestEmailLists.dom_target).html(raw);
        LogUtils.cardLoaded(RequestEmailLists.name, RequestEmailLists.dom_target);

        RequestEmailLists.add_events($(RequestEmailLists.dom_target));
    },

    add_events: function(panel) {
        var label = safe_label(RequestEmailLists.label);

        $('#select_all', panel).click(function(ev) {
            WSData.log_interaction("select_all_on_request_emaillist_"+label);
            if(this.checked) {
                $(':checkbox').each(function() {
                    this.checked = true;
                });
            } else {
                $(':checkbox').each(function() {
                    this.checked = false;
                });
            }
        });

        $(panel).find("button:submit").on("click", function(ev) {
            ev.preventDefault();
            var target = $(ev.currentTarget).closest('form');
            // Don't POST if no boxes are checked
            if(!RequestEmailLists.form_has_checked(target)){
                return;
            }
            WSData.log_interaction("submit_request_emaillist_form_"+label);
            $.ajax({
                url: "/api/v1/emaillist/",
                dataType: "JSON",
                async: true,
                type: 'POST',
                accepts: {html: "text/html"},
                data: $(target).serialize(),
                success: function(results) {
                    if (results.none_selected) {
                        RequestEmailLists.render();
                        return false;
                    }
                    var source = $("#request_email_lists_tmpl").html();
                    var template = Handlebars.compile(source);
                    results.netid = window.user.netid;
                    var raw = template(results);
                    $(RequestEmailLists.dom_target).html(raw);
                },
                error: function(xhr, status, error) {
                    raw = CardWithError.render("Submit email list: " + error);
                    $(RequestEmailLists.dom_target).html(raw);
                    return false;
                }
            });
        });
    },

    form_has_checked: function(target){
        // test if single section modal
        var single_section = false;
        $(target).find(":hidden").each(function(idx, val){
            if($(val).attr("id") !== undefined && $(val).attr("id").indexOf("section_single") > -1){
                single_section =  true;
            }
        });
        if(single_section){
            return single_section
        }

        var checked = $(target).find(":checked");
        return checked.length > 0;
    }
};
<commit_msg>semicolon<commit_after>var RequestEmailLists = {
    name: 'RequestEmailLists',
    dom_target: undefined,
    label: undefined,

    render_init: function(section_label) {
        RequestEmailLists.label = section_label;
        RequestEmailLists.dom_target = '#popup_emaillist_' + safe_label(RequestEmailLists.label);
        WSData.fetch_instructed_section_emaillist_data(section_label,
                                                       RequestEmailLists.render_upon_data,
                                                       RequestEmailLists.render_error);
    },

    render_upon_data: function() {
        if (WSData._instructed_emaillist_data[RequestEmailLists.label] === undefined) {
            return;
        }
        RequestEmailLists.render();
    },

    render_error: function() {
        var error_code = WSData._instructed_emaillist_data_error_status[RequestEmailLists.label];
        if (error_code == 543) {
            raw = CardWithError.render("Request Email List");
            $(RequestEmailLists.dom_target).html(raw);
        }
    },

    render: function() {
        var data = WSData._instructed_emaillist_data[RequestEmailLists.label];
        if (data.total_course_wo_list > 1) {
            data.multi_sections_wo_list = true;
        }
        var term = data.year + ',' + data.quarter;
        var source   = $("#request_email_lists_tmpl").html();
        var template = Handlebars.compile(source);
        var raw = template(data);
        $(RequestEmailLists.dom_target).html(raw);
        LogUtils.cardLoaded(RequestEmailLists.name, RequestEmailLists.dom_target);

        RequestEmailLists.add_events($(RequestEmailLists.dom_target));
    },

    add_events: function(panel) {
        var label = safe_label(RequestEmailLists.label);

        $('#select_all', panel).click(function(ev) {
            WSData.log_interaction("select_all_on_request_emaillist_"+label);
            if(this.checked) {
                $(':checkbox').each(function() {
                    this.checked = true;
                });
            } else {
                $(':checkbox').each(function() {
                    this.checked = false;
                });
            }
        });

        $(panel).find("button:submit").on("click", function(ev) {
            ev.preventDefault();
            var target = $(ev.currentTarget).closest('form');
            // Don't POST if no boxes are checked
            if(!RequestEmailLists.form_has_checked(target)){
                return;
            }
            WSData.log_interaction("submit_request_emaillist_form_"+label);
            $.ajax({
                url: "/api/v1/emaillist/",
                dataType: "JSON",
                async: true,
                type: 'POST',
                accepts: {html: "text/html"},
                data: $(target).serialize(),
                success: function(results) {
                    if (results.none_selected) {
                        RequestEmailLists.render();
                        return false;
                    }
                    var source = $("#request_email_lists_tmpl").html();
                    var template = Handlebars.compile(source);
                    results.netid = window.user.netid;
                    var raw = template(results);
                    $(RequestEmailLists.dom_target).html(raw);
                },
                error: function(xhr, status, error) {
                    raw = CardWithError.render("Submit email list: " + error);
                    $(RequestEmailLists.dom_target).html(raw);
                    return false;
                }
            });
        });
    },

    form_has_checked: function(target){
        // test if single section modal
        var single_section = false;
        $(target).find(":hidden").each(function(idx, val){
            if($(val).attr("id") !== undefined && $(val).attr("id").indexOf("section_single") > -1){
                single_section =  true;
            }
        });
        if(single_section){
            return single_section;
        }

        var checked = $(target).find(":checked");
        return checked.length > 0;
    }
};
<|endoftext|>


<commit_before>module.exports = function (gulp) {
	gulp.task('compileAssets', [
		'clean:dev',
		'jst:dev',
		'less:dev',
		'copy:dev',
		'coffee:dev'
	]);
};
<commit_msg>modified to use with run-sequence<commit_after>module.exports = function (gulp, plugins) {
	gulp.task('compileAssets', function(cb) {
		plugins.sequence(
			'clean:dev',
			'jst:dev',
			'less:dev',
			'copy:dev',
			'coffee:dev',
			cb
		);
	});
};
<|endoftext|>


<commit_before>
/* js for source viewer tab */

// script+css nodes of DOM provided by content script are stored here
var data = {};

// maximum size of file to be beautified initially
// rest is beautified when scrolled to bottom
var MAX_SIZE = 20000;

// is whole file currently displayed?
var is_whole_file;

function init() {

    ask_page_data();

    // view sources
    $("ol").on("click", "a", function(){
        var a = $(this);
        if (a.attr("title"))
            return true; // html viewsource link

        var li = a.closest("li");
        $("ol>li").removeClass("sel");
        li.addClass("sel");

        is_whole_file = false;
        show_src(li);
        return false;
    });

    // show options
    $("#options").click(function(){
        chrome.tabs.create({url:"options.html"});
        return false;
    });

    // toggle beautify
    $("#beautify").click(function(){
        $(this).toggleClass("sel");
        is_whole_file = false;
        show_src();
        return false;
    });
    $(window).keydown(function(e) {
//        console.debug("d1", e.keyCode, e);
        if (e.keyCode == 66) {
            $("#beautify").trigger("click");
        }
        else if (e.keyCode == 78) {
            $("body").toggleClass("nolinenum");
            setTimeout(insert_line_numbers, 10);
        }
    });

    // inject custom css
    var css = get_config("css");
    if (css)
        $("body").append("");

    // set initial beautify mode
    if (get_config("beautify")) {
        $("#beautify").addClass("sel");
    }

    if (get_config("linenum"))
        $("body").removeClass("nolinenum");
    else
        $("body").addClass("nolinenum");

    // scroll handler to beautify whole file
    var w = $(window);
    w.scroll(function() {
        var top = w.scrollTop();
        if (top > 0 && $("body").height() <= (w.height() + top)) {
            // at bottom
            show_src(null, true);
        }
    });
    // anchor to beautify whole file
    $("#src").on("click", "#viewwhole", function() {
        show_src(null, true);
        return false;
    });
}

// init phase2, after tree populated
function init2() {

    // for calculating line height
    $("#src code").html(" ");

    setTimeout(function() {
        line_height = $("#src code span").height();

        // show html node initially
        $("#htmllist li >a").eq(0).trigger("click");
    }, 10);
}

function ask_page_data() {
    // call content script: ask js+css nodes
    if (window.chrome && chrome.tabs) {
        var tabid = location.hash.slice(1);
        tabid = parseInt(tabid);

        // ask to return onclick handlers too?
        var show_onclick = get_config("onclick");

        chrome.tabs.sendMessage(tabid, {"showonclick":show_onclick},
                                data_received);
    } else {
        // while developing
        data_received(debugdata);
    }
}

// shows the source in given

function show_src(li, show_whole_file) {
//    console.debug("show_src " + li + show_whole_file);

    if (!li) {
        // find active li
        li = $("li[class~=sel]");
        if (!li)
            return;
    }

    var index = li.index();

    $("body").removeClass("err");

    if (index < 0)
        return;

    // js or css array?
    var arr;
    var ol = li.parent();
    var lang = "";
    if (ol.get(0).id == "jslist") {
        arr = data.js;
        lang = "javascript";
    } else if (ol.get(0).id == "htmllist") {
        arr = data.html;
        lang = "xml";
    } else {
        arr = data.css;
        lang = "css";
    }

    $("#src>code").removeClass("language-javascript language-css language-xml").addClass("language-"+lang);

    var item = arr[index];

    if (item.src) {
        // external node
        if (item.data != undefined)
            build_item(item, lang, show_whole_file);
        else
            load_data(item);

        $("#fname").text(item.src);
    } else {
        // inline node
        build_item(item, lang, show_whole_file);

        $("#fname").text(item.count? data.url : item.onclick ? "ONCLICK" : "INLINE");
    }

    if (!$("body").hasClass("nolinenum"))
        setTimeout(insert_line_numbers, 10);
}

// shows the sources of a loaded node
function build_item(item, lang, show_whole_file) {
    if (is_whole_file)
        return;

    console.debug("build_item " + lang + " whole=" + is_whole_file);

    // large file, to show only first part?
    var s = item.data || item.inline;
    if (!show_whole_file && s.length > MAX_SIZE) {
        s = s.substr(0, MAX_SIZE);
        is_whole_file = false;
    } else {
        is_whole_file = true;
    }

    var pos = $(window).scrollTop();

    // called when source beautified
    var onFinish = function(txt) {
        $("#src>code").html(txt);

        if (!is_whole_file) {
            $("#src>code").append("\n\nView all");
        }

        // remember scroll pos
        if (!show_whole_file) {
            // chrome fix: scroll to top first
            window.scrollTo(0, 0);
        } else {
            window.scrollTo(0, pos);
        }
    };

    // prettify?
    if ($("#beautify").hasClass("sel")) {
        s = s.trim();

        if (lang.indexOf("css") >= 0)
            s = css_beautify(s);
        else if (lang.indexOf("xml") >= 0)
            s = html_beautify(s);
        else
            s = js_beautify(s);
    }

    // colorize?
    if (get_config("colorize")) {
        if (show_whole_file)
            $("body").addClass("wait2");

        setTimeout(function(){
            hljs.configure({classPrefix: ''});
            var result = hljs.highlight(lang, s, true);
            onFinish(hljs.fixMarkup(result.value));
            $("body").removeClass("wait2");
        }, 10);
    } else {
        onFinish(s);
    }
}

// updates length info of a loaded node
function update_li_text(item, header) {
    var s = "";
    if (item.src) {
        if (item.data != undefined)
            s = numberWithCommas(item.data.length)+" bytes";
    } else {
        s = numberWithCommas(item.inline.length)+" bytes";
    }

    if (item.imported)
        s += " @IMPORT";
    else if (item.dynamic)
        s += " INJECTED";

    if (item.count) {
        // single html item
        s += ", "+item.count+ " nodes ";
        s += "View original";
    }

    if (header) {
        s += "  "+header+"";
    }

    item.li.find("p").html(s);
}

// loads a source file
function load_data(item) {
//    console.debug("load "+item.src);

    $("body").addClass("wait");

    var xhr = new XMLHttpRequest();
    xhr.open('GET', item.src, true);

    xhr.onreadystatechange = function(event) {
        if (xhr.readyState == 4) {
            $("body").removeClass("wait");

            if (xhr.status === 200) {
                // cache file content
                item.data = xhr.responseText;

                var header = null;
                if (get_config("caching"))
                    header = pick_caching_header(xhr);

                show_src();
                update_li_text(item, header);
            } else {
                $("body").addClass("err");
                $("#src>code").text("HTTP Error " + xhr.status);
            }
        }
    };
    xhr.send(null);
}

// picks caching information of src file
function pick_caching_header(xhr) {
    var h = "Expires";
    var val = xhr.getResponseHeader(h);
    if (!val) {
        h = "Cache-Control";
        val = xhr.getResponseHeader(h);
    }
    if (!val) {
        h = "Age";
        val = xhr.getResponseHeader(h);
    }

    if (val)
        return h+": "+val;
}

// js+css data received from content script
function data_received(resp) {
    if (!resp) {
        // target page not yet loaded, ask again
        $("#src>code").text("Page loading...");
        setTimeout(ask_page_data, 500);
        return;
    } else if (resp.err) {
        // some error occurred
        $("body").addClass("err");
        $("#src>code").text(resp.err);
        return;
    }

    // remember data
    data = resp;

    // set badge for this source tab too
    update_badge(data);

    // set title
    var url = remove_url_prefix(resp.url);
    $("title").text("SRC "+url);

    var jscount = resp.js.length;
    var csscount = resp.css.length;
    var jsinline = 0;
    var cssinline = 0;
    var onclickcount = 0;

    var i, item;

    // html
    for (i = 0; i < resp.html.length; i++) {
        item = resp.html[i];
        add_item($("#htmllist"), item);
        update_li_text(item);
    }
    // js
    for (i = 0; i < jscount; i++) {
        item = resp.js[i];

        add_item($("#jslist"), item);
        if (!item.src)
            jsinline += 1;
        update_li_text(item);
    }
    // css
    for (i = 0; i < csscount; i++) {
        item = resp.css[i];
        add_item($("#csslist"), item);
        if (!item.src)
            cssinline += 1;
        update_li_text(item);
    }

    // update counts
    $("#jstotal").text(jscount-onclickcount);
    $("#jsext").text(jscount-onclickcount-jsinline);
    $("#jsin").text(jsinline);
    $("#csstotal").text(csscount);
    $("#cssext").text(csscount-cssinline);
    $("#cssin").text(cssinline);

    init2();
}

// builds and adds a source item to a

function add_item(ol, item) {
    var s;

    if (item.src)
        s = "
"+emphasize_name(item.src);
    else if (item.count)
        s = "
"+remove_url_prefix(data.url);
    else if (item.onclick)
        s = "
ONCLICK: ";
    else
        s = "
INLINE: ";
    s += "

";

    var li = $(s);
    if (!item.src) {
        li.addClass("inline");
        li.find("span").text(item.inline.substr(0,80));
    }
    if (item.dynamic)
        li.addClass("dynamic");
    if (item.src && config_is_hilighted(item.src))
        li.addClass("hi");

    item.li = li;

    ol.append(li);
}

// emphasizes the file name part of the url
function emphasize_name(url) {
    url = remove_url_prefix(url);

    var len = url.length;
    var i = url.lastIndexOf("/");
    var s;
    if (i == len-1)
        return url;
    else if (i < 0)
        return ""+url+"";
    else
        return url.substr(0,i+1) + "" + url.substr(i+1) + "";
    // zero-width space above, breaks line if needed
}

//http://stackoverflow.com/questions/2901102/how-to-print-number-with-commas-as-thousands-separators-in-javascript
function numberWithCommas(x) {
    return x.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
}

window.addEventListener('load', function() {
    init();
});

// fills #src ol to have N items of

function insert_line_numbers() {
    $("#src ol").empty();
    var nums = [];
    var count = calculate_line_count();

    for (var i = 0; i < count; i++) {
        nums.push("
");
    }
    $("#src ol").html(nums.join(""));
}

var line_height = 0;

function calculate_line_count() {
    // can't count linefeeds since pre-wrap can also wrap lines
//    var s = $("#src code").text();
//    return s.split("\n").length;

    // let's just calculate lines by box height
    var h = $("#src code").height();

    if (!line_height)
        return 1;

    return h/line_height - 1;
}

// removes "http://"
function remove_url_prefix(url) {
    if (url.startsWith("http://"))
        url = url.substr(7);
    else if (url.startsWith("https://"))
        url = url.substr(8);
    return url;
}

<commit_msg>Show access denied msg for system pages<commit_after>
/* js for source viewer tab */

// script+css nodes of DOM provided by content script are stored here
var data = {};

// maximum size of file to be beautified initially
// rest is beautified when scrolled to bottom
var MAX_SIZE = 20000;

// is whole file currently displayed?
var is_whole_file;

// id of target tab
var tabid;

function init() {

    tabid = parseInt(location.hash.slice(1));

    ask_page_data();

    // view sources
    $("ol").on("click", "a", function(){
        var a = $(this);
        if (a.attr("title"))
            return true; // html viewsource link

        var li = a.closest("li");
        $("ol>li").removeClass("sel");
        li.addClass("sel");

        is_whole_file = false;
        show_src(li);
        return false;
    });

    // show options
    $("#options").click(function(){
        chrome.tabs.create({url:"options.html"});
        return false;
    });

    // toggle beautify
    $("#beautify").click(function(){
        $(this).toggleClass("sel");
        is_whole_file = false;
        show_src();
        return false;
    });
    $(window).keydown(function(e) {
//        console.debug("d1", e.keyCode, e);
        if (e.keyCode == 66) {
            $("#beautify").trigger("click");
        }
        else if (e.keyCode == 78) {
            $("body").toggleClass("nolinenum");
            setTimeout(insert_line_numbers, 10);
        }
    });

    // inject custom css
    var css = get_config("css");
    if (css)
        $("body").append("");

    // set initial beautify mode
    if (get_config("beautify")) {
        $("#beautify").addClass("sel");
    }

    if (get_config("linenum"))
        $("body").removeClass("nolinenum");
    else
        $("body").addClass("nolinenum");

    // scroll handler to beautify whole file
    var w = $(window);
    w.scroll(function() {
        var top = w.scrollTop();
        if (top > 0 && $("body").height() <= (w.height() + top)) {
            // at bottom
            show_src(null, true);
        }
    });
    // anchor to beautify whole file
    $("#src").on("click", "#viewwhole", function() {
        show_src(null, true);
        return false;
    });
}

// init phase2, after tree populated
function init2() {

    // for calculating line height
    $("#src code").html(" ");

    setTimeout(function() {
        line_height = $("#src code span").height();

        // show html node initially
        $("#htmllist li >a").eq(0).trigger("click");
    }, 10);
}

function ask_page_data() {
    // call content script: ask js+css nodes
    if (window.chrome && chrome.tabs) {
        // ask to return onclick handlers too?
        var show_onclick = get_config("onclick");

        chrome.tabs.sendMessage(tabid, {"showonclick":show_onclick},
                                data_received);
    } else {
        // while developing
        data_received(debugdata);
    }
}

// shows the source in given

function show_src(li, show_whole_file) {
//    console.debug("show_src " + li + show_whole_file);

    if (!li) {
        // find active li
        li = $("li[class~=sel]");
        if (!li)
            return;
    }

    var index = li.index();

    $("body").removeClass("err");

    if (index < 0)
        return;

    // js or css array?
    var arr;
    var ol = li.parent();
    var lang = "";
    if (ol.get(0).id == "jslist") {
        arr = data.js;
        lang = "javascript";
    } else if (ol.get(0).id == "htmllist") {
        arr = data.html;
        lang = "xml";
    } else {
        arr = data.css;
        lang = "css";
    }

    $("#src>code").removeClass("language-javascript language-css language-xml").addClass("language-"+lang);

    var item = arr[index];

    if (item.src) {
        // external node
        if (item.data != undefined)
            build_item(item, lang, show_whole_file);
        else
            load_data(item);

        $("#fname").text(item.src);
    } else {
        // inline node
        build_item(item, lang, show_whole_file);

        $("#fname").text(item.count? data.url : item.onclick ? "ONCLICK" : "INLINE");
    }

    if (!$("body").hasClass("nolinenum"))
        setTimeout(insert_line_numbers, 10);
}

// shows the sources of a loaded node
function build_item(item, lang, show_whole_file) {
    if (is_whole_file)
        return;

    console.debug("build_item " + lang + " whole=" + is_whole_file);

    // large file, to show only first part?
    var s = item.data || item.inline;
    if (!show_whole_file && s.length > MAX_SIZE) {
        s = s.substr(0, MAX_SIZE);
        is_whole_file = false;
    } else {
        is_whole_file = true;
    }

    var pos = $(window).scrollTop();

    // called when source beautified
    var onFinish = function(txt) {
        $("#src>code").html(txt);

        if (!is_whole_file) {
            $("#src>code").append("\n\nView all");
        }

        // remember scroll pos
        if (!show_whole_file) {
            // chrome fix: scroll to top first
            window.scrollTo(0, 0);
        } else {
            window.scrollTo(0, pos);
        }
    };

    // prettify?
    if ($("#beautify").hasClass("sel")) {
        s = s.trim();

        if (lang.indexOf("css") >= 0)
            s = css_beautify(s);
        else if (lang.indexOf("xml") >= 0)
            s = html_beautify(s);
        else
            s = js_beautify(s);
    }

    // colorize?
    if (get_config("colorize")) {
        if (show_whole_file)
            $("body").addClass("wait2");

        setTimeout(function(){
            hljs.configure({classPrefix: ''});
            var result = hljs.highlight(lang, s, true);
            onFinish(hljs.fixMarkup(result.value));
            $("body").removeClass("wait2");
        }, 10);
    } else {
        onFinish(s);
    }
}

// updates length info of a loaded node
function update_li_text(item, header) {
    var s = "";
    if (item.src) {
        if (item.data != undefined)
            s = numberWithCommas(item.data.length)+" bytes";
    } else {
        s = numberWithCommas(item.inline.length)+" bytes";
    }

    if (item.imported)
        s += " @IMPORT";
    else if (item.dynamic)
        s += " INJECTED";

    if (item.count) {
        // single html item
        s += ", "+item.count+ " nodes ";
        s += "View original";
    }

    if (header) {
        s += "  "+header+"";
    }

    item.li.find("p").html(s);
}

// loads a source file
function load_data(item) {
//    console.debug("load "+item.src);

    $("body").addClass("wait");

    var xhr = new XMLHttpRequest();
    xhr.open('GET', item.src, true);

    xhr.onreadystatechange = function(event) {
        if (xhr.readyState == 4) {
            $("body").removeClass("wait");

            if (xhr.status === 200) {
                // cache file content
                item.data = xhr.responseText;

                var header = null;
                if (get_config("caching"))
                    header = pick_caching_header(xhr);

                show_src();
                update_li_text(item, header);
            } else {
                $("body").addClass("err");
                $("#src>code").text("HTTP Error " + xhr.status);
            }
        }
    };
    xhr.send(null);
}

// picks caching information of src file
function pick_caching_header(xhr) {
    var h = "Expires";
    var val = xhr.getResponseHeader(h);
    if (!val) {
        h = "Cache-Control";
        val = xhr.getResponseHeader(h);
    }
    if (!val) {
        h = "Age";
        val = xhr.getResponseHeader(h);
    }

    if (val)
        return h+": "+val;
}

// js+css data received from content script
function data_received(resp) {
    if (!resp) {
        var err = chrome.extension.lastError;

        // still loading page?
        chrome.tabs.get(tabid, function(tab) {
            if (tab.status == "complete" && err) {
                // can't show this page
                $("#src>code").text("Error: Access is denied to chrome:// and Chrome Store pages");
                return;
            }
            // target page not yet loaded, ask again
            $("#src>code").text("Page loading...");
            setTimeout(ask_page_data, 500);
        });
        return;

    } else if (resp.err) {
        // some error occurred
        $("body").addClass("err");
        $("#src>code").text(resp.err);
        return;
    }

    // remember data
    data = resp;

    // set badge for this source tab too
    update_badge(data);

    // set title
    var url = remove_url_prefix(resp.url);
    $("title").text("SRC "+url);

    var jscount = resp.js.length;
    var csscount = resp.css.length;
    var jsinline = 0;
    var cssinline = 0;
    var onclickcount = 0;

    var i, item;

    // html
    for (i = 0; i < resp.html.length; i++) {
        item = resp.html[i];
        add_item($("#htmllist"), item);
        update_li_text(item);
    }
    // js
    for (i = 0; i < jscount; i++) {
        item = resp.js[i];

        add_item($("#jslist"), item);
        if (!item.src)
            jsinline += 1;
        update_li_text(item);
    }
    // css
    for (i = 0; i < csscount; i++) {
        item = resp.css[i];
        add_item($("#csslist"), item);
        if (!item.src)
            cssinline += 1;
        update_li_text(item);
    }

    // update counts
    $("#jstotal").text(jscount-onclickcount);
    $("#jsext").text(jscount-onclickcount-jsinline);
    $("#jsin").text(jsinline);
    $("#csstotal").text(csscount);
    $("#cssext").text(csscount-cssinline);
    $("#cssin").text(cssinline);

    init2();
}

// builds and adds a source item to a

function add_item(ol, item) {
    var s;

    if (item.src)
        s = "
"+emphasize_name(item.src);
    else if (item.count)
        s = "
"+remove_url_prefix(data.url);
    else if (item.onclick)
        s = "
ONCLICK: ";
    else
        s = "
INLINE: ";
    s += "

";

    var li = $(s);
    if (!item.src) {
        li.addClass("inline");
        li.find("span").text(item.inline.substr(0,80));
    }
    if (item.dynamic)
        li.addClass("dynamic");
    if (item.src && config_is_hilighted(item.src))
        li.addClass("hi");

    item.li = li;

    ol.append(li);
}

// emphasizes the file name part of the url
function emphasize_name(url) {
    url = remove_url_prefix(url);

    var len = url.length;
    var i = url.lastIndexOf("/");
    var s;
    if (i == len-1)
        return url;
    else if (i < 0)
        return ""+url+"";
    else
        return url.substr(0,i+1) + "" + url.substr(i+1) + "";
    // zero-width space above, breaks line if needed
}

//http://stackoverflow.com/questions/2901102/how-to-print-number-with-commas-as-thousands-separators-in-javascript
function numberWithCommas(x) {
    return x.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
}

window.addEventListener('load', function() {
    init();
});

// fills #src ol to have N items of

function insert_line_numbers() {
    $("#src ol").empty();
    var nums = [];
    var count = calculate_line_count();

    for (var i = 0; i < count; i++) {
        nums.push("
");
    }
    $("#src ol").html(nums.join(""));
}

var line_height = 0;

function calculate_line_count() {
    // can't count linefeeds since pre-wrap can also wrap lines
//    var s = $("#src code").text();
//    return s.split("\n").length;

    // let's just calculate lines by box height
    var h = $("#src code").height();

    if (!line_height)
        return 1;

    return h/line_height - 1;
}

// removes "http://"
function remove_url_prefix(url) {
    if (url.startsWith("http://"))
        url = url.substr(7);
    else if (url.startsWith("https://"))
        url = url.substr(8);
    return url;
}

<|endoftext|>


<commit_before>require('../support/test_helper');

var assert = require('../support/assert');
var TestClient = require('../support/test_client');

describe('multilayer error cases', function() {

    it("layergroup with no cartocss_version", function(done) {
      var layergroup =  {
        version: '1.0.0',
        layers: [
           { options: {
               sql: 'select cartodb_id, ST_Translate(the_geom, 50, 0) as the_geom from test_table limit 2',
               cartocss: '#layer { marker-fill:red; marker-width:32; marker-allow-overlap:true; }'
             } }
        ]
      };

        var testClient = new TestClient(layergroup);
        testClient.createLayergroup(function(err) {
            assert.ok(err);
            assert.equal(err.message, 'Missing cartocss_version for layer 0 options');
            done();
        });
    });

    it("sql/cartocss combination errors", function(done) {
      var layergroup =  {
        version: '1.0.1',
        layers: [{ options: {
           sql: "select 1 as i, 'LINESTRING(0 0, 1 0)'::geometry as the_geom",
           cartocss_version: '2.0.2',
           cartocss: '#layer [missing=1] { line-width:16; }'
        }}]
      };
        var testClient = new TestClient(layergroup);
        testClient.createLayergroup(function(err) {
            assert.ok(err);
            assert.ok(err.message.match(/column "missing" does not exist/m));
            // cannot check for error starting with style0 until a new enough mapnik
            // is used: https://github.com/mapnik/mapnik/issues/1924
            //assert.ok(error.match(/^style0/), "Error doesn't start with style0: " + error);
            // TODO: check which layer introduced the problem ?
            done();
        });
    });

    it("sql/interactivity combination error", function(done) {
      var layergroup =  {
        version: '1.0.1',
        layers: [
          { options: {
           sql: "select 1 as i, st_setsrid('LINESTRING(0 0, 1 0)'::geometry, 4326) as the_geom",
           cartocss_version: '2.0.2',
           cartocss: '#layer { line-width:16; }',
           interactivity: 'i'
          }},
          { options: {
           sql: "select 1 as i, st_setsrid('LINESTRING(0 0, 1 0)'::geometry, 4326) as the_geom",
           cartocss_version: '2.0.2',
           cartocss: '#layer { line-width:16; }'
          }},
          { options: {
           sql: "select 1 as i, st_setsrid('LINESTRING(0 0, 1 0)'::geometry, 4326) as the_geom",
           cartocss_version: '2.0.2',
           cartocss: '#layer { line-width:16; }',
           interactivity: 'missing'
          }}
        ]
      };
        var testClient = new TestClient(layergroup);
        testClient.createLayergroup(function(err) {
            assert.ok(err);
            assert.ok(err.message.match(/column "missing" does not exist/m));
            // TODO: check which layer introduced the problem ?
            done();
        });
    });

    it("blank CartoCSS error", function(done) {
      var layergroup =  {
        version: '1.0.1',
        layers: [
          { options: {
           sql: "select 1 as i, 'LINESTRING(0 0, 1 0)'::geometry as the_geom",
           cartocss_version: '2.0.2',
           cartocss: '#style { line-width:16 }',
           interactivity: 'i'
          }},
          { options: {
           sql: "select 1 as i, 'LINESTRING(0 0, 1 0)'::geometry as the_geom",
           cartocss_version: '2.0.2',
           cartocss: '',
           interactivity: 'i'
          }}
        ]
      };
        var testClient = new TestClient(layergroup);
        testClient.createLayergroup(function(err) {
            assert.ok(err);
            assert.ok(err.message.match(/^style1: CartoCSS is empty/));
            done();
        });
    });

    it("Invalid mapnik-geometry-type CartoCSS error", function(done) {
      var layergroup =  {
        version: '1.0.1',
        layers: [
          { options: {
           sql: "select 1 as i, 'LINESTRING(0 0, 1 0)'::geometry as the_geom",
           cartocss_version: '2.0.2',
           cartocss: '#style [mapnik-geometry-type=bogus] { line-width:16 }'
          }},
          { options: {
           sql: "select 1 as i, 'LINESTRING(0 0, 1 0)'::geometry as the_geom",
           cartocss_version: '2.0.2',
           cartocss: '#style [mapnik-geometry-type=bogus] { line-width:16 }'
          }}
        ]
      };
        var testClient = new TestClient(layergroup);
        testClient.createLayergroup(function(err) {
            assert.ok(err);
            // carto-0.9.3 used to say "Failed to parse expression",
            // carto-0.9.5 says "not a valid keyword"
            assert.ok(err.message.match(/^style0:.*(Failed|not a valid)/));
            // TODO: check which layer introduced the problem ?
            done();
      });
    });

    it("post'ing style with non existent column (address) in filter returns 400 with error", function(done) {
        var layergroup =  {
            version: '1.0.1',
            layers: [
                { options: {
                    sql: 'select * from test_table limit 1',
                    cartocss: '#test_table::outline[address="one"], [address="two"] { marker-fill: red; }',
                    cartocss_version: '2.0.2',
                    interactivity: [ 'cartodb_id' ]
                } },
                { options: {
                    sql: 'select * from test_big_poly limit 1',
                    cartocss: '#test_big_poly { marker-fill:blue }',
                    cartocss_version: '2.0.2',
                    interactivity: [ 'cartodb_id' ]
                } }
            ]
        };

        var testClient = new TestClient(layergroup);
        testClient.createLayergroup(function(err) {
            assert.ok(err);
            assert.ok(err.message.match(/column "address" does not exist/m));
            done();
        });
    });

    it("post'ing style with non existent column for its own layer in filter returns 400 with error", function(done) {
        var layergroup =  {
            version: '1.0.1',
            layers: [
                { options: {
                    sql: 'select * from test_table limit 1',
                    cartocss: '#test_table::outline[nonexistent="one"], [nonexistent="two"] { marker-fill: red; }',
                    cartocss_version: '2.0.2',
                    interactivity: [ 'cartodb_id' ]
                } },
                { options: {
                    sql: 'select * from test_big_poly limit 1',
                    cartocss: '#test_big_poly { marker-fill:blue }',
                    cartocss_version: '2.0.2',
                    interactivity: [ 'cartodb_id' ]
                } }
            ]
        };

        var testClient = new TestClient(layergroup);
        testClient.createLayergroup(function(err) {
            assert.ok(err);
            assert.ok(err.message.match(/column "nonexistent" does not exist/m));
            assert.equal(err.layerIndex, 0);
            done();
        });
    });

    // See https://github.com/Vizzuality/Windshaft/issues/31
    it('bogus sql raises 400 status code', function(done) {
        var bogusSqlMapConfig = TestClient.singleLayerMapConfig('BOGUS FROM test_table');
        var testClient = new TestClient(bogusSqlMapConfig);
        testClient.createLayergroup(function(err) {
            assert.ok(err);
            assert.ok(/syntax error/.test(err.message), "Unexpected error: " + err.message);
            done();
        });
    });

    it("query with no geometry field returns 400 status",  function(done){
        var noGeometrySqlMapConfig = TestClient.singleLayerMapConfig('SELECT 1');
        var testClient = new TestClient(noGeometrySqlMapConfig);
        testClient.createLayergroup(function(err) {
            assert.ok(err);
            assert.ok(/column.*does not exist/.test(err.message), "Unexpected error: " + err.message);
            done();
        });
    });

    it("bogus style should raise 400 status",  function(done){
        var bogusStyleMapConfig = TestClient.defaultTableMapConfig('test_table', '#test_table{xxxxx;}');
        var testClient = new TestClient(bogusStyleMapConfig);
        testClient.createLayergroup(function(err) {
            assert.ok(err);

            assert.equal(err.message, 'style0:1:9 Invalid code: xxxxx;');

            done();
        });
    });

    it('should raise 400 error for out of bounds layer index',  function(done){
        var mapConfig = TestClient.singleLayerMapConfig('select * from test_table', null, null, 'name');
        var testClient = new TestClient(mapConfig);
        testClient.getTile(13, 4011, 3088, {layer: 1, format: 'grid.json'}, function(err) {
            assert.ok(err);
            assert.equal(err.message, "Layer '1' not found in layergroup");
            done();
        });
    });

});
<commit_msg>Remove empty lines<commit_after>require('../support/test_helper');

var assert = require('../support/assert');
var TestClient = require('../support/test_client');

describe('multilayer error cases', function() {

    it("layergroup with no cartocss_version", function(done) {
      var layergroup =  {
        version: '1.0.0',
        layers: [
           { options: {
               sql: 'select cartodb_id, ST_Translate(the_geom, 50, 0) as the_geom from test_table limit 2',
               cartocss: '#layer { marker-fill:red; marker-width:32; marker-allow-overlap:true; }'
             } }
        ]
      };

        var testClient = new TestClient(layergroup);
        testClient.createLayergroup(function(err) {
            assert.ok(err);
            assert.equal(err.message, 'Missing cartocss_version for layer 0 options');
            done();
        });
    });

    it("sql/cartocss combination errors", function(done) {
      var layergroup =  {
        version: '1.0.1',
        layers: [{ options: {
           sql: "select 1 as i, 'LINESTRING(0 0, 1 0)'::geometry as the_geom",
           cartocss_version: '2.0.2',
           cartocss: '#layer [missing=1] { line-width:16; }'
        }}]
      };
        var testClient = new TestClient(layergroup);
        testClient.createLayergroup(function(err) {
            assert.ok(err);
            assert.ok(err.message.match(/column "missing" does not exist/m));
            // cannot check for error starting with style0 until a new enough mapnik
            // is used: https://github.com/mapnik/mapnik/issues/1924
            //assert.ok(error.match(/^style0/), "Error doesn't start with style0: " + error);
            // TODO: check which layer introduced the problem ?
            done();
        });
    });

    it("sql/interactivity combination error", function(done) {
      var layergroup =  {
        version: '1.0.1',
        layers: [
          { options: {
           sql: "select 1 as i, st_setsrid('LINESTRING(0 0, 1 0)'::geometry, 4326) as the_geom",
           cartocss_version: '2.0.2',
           cartocss: '#layer { line-width:16; }',
           interactivity: 'i'
          }},
          { options: {
           sql: "select 1 as i, st_setsrid('LINESTRING(0 0, 1 0)'::geometry, 4326) as the_geom",
           cartocss_version: '2.0.2',
           cartocss: '#layer { line-width:16; }'
          }},
          { options: {
           sql: "select 1 as i, st_setsrid('LINESTRING(0 0, 1 0)'::geometry, 4326) as the_geom",
           cartocss_version: '2.0.2',
           cartocss: '#layer { line-width:16; }',
           interactivity: 'missing'
          }}
        ]
      };
        var testClient = new TestClient(layergroup);
        testClient.createLayergroup(function(err) {
            assert.ok(err);
            assert.ok(err.message.match(/column "missing" does not exist/m));
            // TODO: check which layer introduced the problem ?
            done();
        });
    });

    it("blank CartoCSS error", function(done) {
      var layergroup =  {
        version: '1.0.1',
        layers: [
          { options: {
           sql: "select 1 as i, 'LINESTRING(0 0, 1 0)'::geometry as the_geom",
           cartocss_version: '2.0.2',
           cartocss: '#style { line-width:16 }',
           interactivity: 'i'
          }},
          { options: {
           sql: "select 1 as i, 'LINESTRING(0 0, 1 0)'::geometry as the_geom",
           cartocss_version: '2.0.2',
           cartocss: '',
           interactivity: 'i'
          }}
        ]
      };
        var testClient = new TestClient(layergroup);
        testClient.createLayergroup(function(err) {
            assert.ok(err);
            assert.ok(err.message.match(/^style1: CartoCSS is empty/));
            done();
        });
    });

    it("Invalid mapnik-geometry-type CartoCSS error", function(done) {
      var layergroup =  {
        version: '1.0.1',
        layers: [
          { options: {
           sql: "select 1 as i, 'LINESTRING(0 0, 1 0)'::geometry as the_geom",
           cartocss_version: '2.0.2',
           cartocss: '#style [mapnik-geometry-type=bogus] { line-width:16 }'
          }},
          { options: {
           sql: "select 1 as i, 'LINESTRING(0 0, 1 0)'::geometry as the_geom",
           cartocss_version: '2.0.2',
           cartocss: '#style [mapnik-geometry-type=bogus] { line-width:16 }'
          }}
        ]
      };
        var testClient = new TestClient(layergroup);
        testClient.createLayergroup(function(err) {
            assert.ok(err);
            // carto-0.9.3 used to say "Failed to parse expression",
            // carto-0.9.5 says "not a valid keyword"
            assert.ok(err.message.match(/^style0:.*(Failed|not a valid)/));
            // TODO: check which layer introduced the problem ?
            done();
      });
    });

    it("post'ing style with non existent column (address) in filter returns 400 with error", function(done) {
        var layergroup =  {
            version: '1.0.1',
            layers: [
                { options: {
                    sql: 'select * from test_table limit 1',
                    cartocss: '#test_table::outline[address="one"], [address="two"] { marker-fill: red; }',
                    cartocss_version: '2.0.2',
                    interactivity: [ 'cartodb_id' ]
                } },
                { options: {
                    sql: 'select * from test_big_poly limit 1',
                    cartocss: '#test_big_poly { marker-fill:blue }',
                    cartocss_version: '2.0.2',
                    interactivity: [ 'cartodb_id' ]
                } }
            ]
        };

        var testClient = new TestClient(layergroup);
        testClient.createLayergroup(function(err) {
            assert.ok(err);
            assert.ok(err.message.match(/column "address" does not exist/m));
            done();
        });
    });

    it("post'ing style with non existent column for its own layer in filter returns 400 with error", function(done) {
        var layergroup =  {
            version: '1.0.1',
            layers: [
                { options: {
                    sql: 'select * from test_table limit 1',
                    cartocss: '#test_table::outline[nonexistent="one"], [nonexistent="two"] { marker-fill: red; }',
                    cartocss_version: '2.0.2',
                    interactivity: [ 'cartodb_id' ]
                } },
                { options: {
                    sql: 'select * from test_big_poly limit 1',
                    cartocss: '#test_big_poly { marker-fill:blue }',
                    cartocss_version: '2.0.2',
                    interactivity: [ 'cartodb_id' ]
                } }
            ]
        };

        var testClient = new TestClient(layergroup);
        testClient.createLayergroup(function(err) {
            assert.ok(err);
            assert.ok(err.message.match(/column "nonexistent" does not exist/m));
            assert.equal(err.layerIndex, 0);
            done();
        });
    });

    // See https://github.com/Vizzuality/Windshaft/issues/31
    it('bogus sql raises 400 status code', function(done) {
        var bogusSqlMapConfig = TestClient.singleLayerMapConfig('BOGUS FROM test_table');
        var testClient = new TestClient(bogusSqlMapConfig);
        testClient.createLayergroup(function(err) {
            assert.ok(err);
            assert.ok(/syntax error/.test(err.message), "Unexpected error: " + err.message);
            done();
        });
    });

    it("query with no geometry field returns 400 status",  function(done){
        var noGeometrySqlMapConfig = TestClient.singleLayerMapConfig('SELECT 1');
        var testClient = new TestClient(noGeometrySqlMapConfig);
        testClient.createLayergroup(function(err) {
            assert.ok(err);
            assert.ok(/column.*does not exist/.test(err.message), "Unexpected error: " + err.message);
            done();
        });
    });

    it("bogus style should raise 400 status",  function(done){
        var bogusStyleMapConfig = TestClient.defaultTableMapConfig('test_table', '#test_table{xxxxx;}');
        var testClient = new TestClient(bogusStyleMapConfig);
        testClient.createLayergroup(function(err) {
            assert.ok(err);
            assert.equal(err.message, 'style0:1:9 Invalid code: xxxxx;');
            done();
        });
    });

    it('should raise 400 error for out of bounds layer index',  function(done){
        var mapConfig = TestClient.singleLayerMapConfig('select * from test_table', null, null, 'name');
        var testClient = new TestClient(mapConfig);
        testClient.getTile(13, 4011, 3088, {layer: 1, format: 'grid.json'}, function(err) {
            assert.ok(err);
            assert.equal(err.message, "Layer '1' not found in layergroup");
            done();
        });
    });

});
<|endoftext|>


<commit_before>function Tile(index, cols, rows){
   this.index = index;
   this.num = 0;
   this.f = 0;
   this.g = 0;
   this.h = 0;
   this.previous = undefined;
   //[index - 1, index + 1, index - cols , index + cols] - without diagonals
   //[index - cols - 1, index + cols - 1, index - cols + 1, index + cols + 1] - diagonals
   //[index - 1, index + 1, index - cols, index + cols, index - cols - 1, index + cols - 1, index - cols + 1, index + cols + 1] - all
   this.neighbors = [index - 1, index + 1, index - cols, index + cols].filter(function(x){
     //start and end checker
     if(x >= 0 && x < cols * rows){
       //left edge checker
	   //diagonals: if(this.index % cols == 0 && (x == this.index - 1 || x == this.index - cols - 1 || x == this.index + cols - 1))
       if(this.index % cols == 0 && x == this.index - 1){
          return false;
       }
       //right edge checker
	   //diagonals: if((this.index + 1) % cols == 0 && (x == this.index + 1 || x == this.index - cols + 1 || x == this.index + cols + 1))
       if((this.index + 1) % cols == 0 && x == this.index + 1){
          return false;
       }
       return true;
     }
     return false;
   }, this);
};

function Tilemap(canvas, context) {
    this.tsize = 40; //tile size (40 x 40)
    this.cols = Math.ceil(canvas.width / this.tsize);
    this.rows = Math.ceil(canvas.height / this.tsize);

    this.tiles = [];
    for(var i = 0; i < this.cols * this.rows; i++){
        this.tiles.push(new Tile(i, this.cols, this.rows));
    };

    this.textures = [];
    for(var j = 1; j <= 7; j++){ //change when have spritesheet
        this.textures.push(document.getElementById(('grass-' + j)));
    }

    this.getTile = function(col, row) {
        return this.tiles[row * this.cols + col]
    };

    this.render = function(){
        for (var c = 0; c < this.cols; c++) {
            for (var r = 0; r < this.rows; r++) {
                var tile = this.getTile(c, r);
                if (tile.num == 0) {
                    context.drawImage(this.textures[0], c * this.tsize, r * this.tsize);
                }else if (tile.num == 1){
                    context.fillStyle = '#0d0d0d';
                    context.fillRect(c * this.tsize, r * this.tsize, this.tsize, this.tsize);
                }else if (tile.num == 2){
                    context.fillStyle = 'blue';
                    context.fillRect(c * this.tsize, r * this.tsize, this.tsize, this.tsize);
                }
            }
        }
    };//end of Tilemap render

    this.renderGrid = function(){
        for (var c = 0; c < this.cols; c++) {
            for (var r = 0; r < this.rows; r++) {
                context.strokeStyle = 'white';
                context.strokeRect(c * this.tsize, r * this.tsize, this.tsize, this.tsize);
            }
        }
    };// end of Tilemap render grid

    this.update = function(col, row, value){
        this.tiles[row * this.cols + col].num = value;
    }

    //why do we even need cols and rows here? rewrite with tiles array!
    this.randomize = function(){
        for (var c = 0; c < this.cols; c++) {
            for (var r = 0; r < this.rows; r++) {
                if(Math.random() < 0.2){
                    this.update(c, r, 1);
                }else{
                    this.update(c, r, 0);
                }
            }
        }
    };//end of randomize map

};//end of Tilemap

//PATHFINDER (work in progress)
//https://codepen.io/svmi3195/pen/gRrBBJ

//transforms index of 2d array to index of 1d array
function transIndex(arr, map){
  //arr[0] - x
  //arr[1] - y
  return arr[1] * map.cols + arr[0];
}

//transforms index of 1d array to index of 2d array
function transIndex2(index, map){
  return [index % map.cols, Math.floor(index / map.cols)]
}

function removeFromArray(array, element){
  for(var i = array.length - 1; i >= 0; i--){
    if(array[i] == element){
      array.splice(i, 1);
    }
  }
}

function heuristic(point1, point2){
  var a = point1[0] - point2[0];
  var b = point1[1] - point2[1];

  //euclidian distance
  var distance = Math.sqrt( a*a + b*b );
  //manhattan distance
  //var distance = Math.abs(a) + Math.abs(b);
  return distance;
}

function findPath(map, start, goal){
  var path = [];
  var openList = [];
  var closedList = [];
  if(!start){start = 0}
  if(!goal){goal = map.tiles.length -1}

  openList.push(start);

  var done = false;
  var iteration = 0;

  while(!done){
    iteration++;
    if(openList.length > 0){
      var winner = 0;
      for(var i = 0; i < openList.length; i++){
        if(map.tiles[openList[i]].f < map.tiles[openList[winner]].f){
          winner = i;
        }
      }
      var current = openList[winner];

      if(current == goal){
        done = true;
        console.log('Done!');
        path.push(start);
        var temp = current;
        path.push(temp);
        while(map.tiles[temp].previous){
          path.push(map.tiles[temp].previous);
          temp = map.tiles[temp].previous;
        }
      }

      removeFromArray(openList, current);
      closedList.push(current);

      var neighbors = map.tiles[current].neighbors;
      for(var nb = 0; nb < neighbors.length; nb++){
        var neighbor = neighbors[nb];

        if(!closedList.includes(neighbor) && map.tiles[neighbor].num != 1){
           var tempG = map.tiles[current].g + 1;

          var newPath = false;
          if(openList.includes(neighbor)){
            if(tempG < map.tiles[neighbor].g){
              map.tiles[neighbor].g = tempG;
              newPath = true;
            }
          }else{
            map.tiles[neighbor].g = tempG;
            newPath = true;
            openList.push(neighbor);
          }

          if(newPath){
            map.tiles[neighbor].h = heuristic(transIndex2(neighbor, map), transIndex2(goal, map));
            map.tiles[neighbor].f = map.tiles[neighbor].g + map.tiles[neighbor].h;
            map.tiles[neighbor].previous = current;
          }
        }
      }

  }else{
    //no solution
    done = true;
    return undefined;
  }

  //visualize path with blue rects:
  for(var p = 0; p < path.length; p++){
      map.tiles[path[p]].num = 2;
  }

  }

  return path;
}//end of findPath

<commit_msg>added diagonal neighbors<commit_after>function Tile(index, cols, rows){
   this.index = index;
   this.num = 0;
   this.f = 0;
   this.g = 0;
   this.h = 0;
   this.previous = undefined;
   //[index - 1, index + 1, index - cols , index + cols] - without diagonals
   //[index - cols - 1, index + cols - 1, index - cols + 1, index + cols + 1] - diagonals
   //[index - 1, index + 1, index - cols, index + cols, index - cols - 1, index + cols - 1, index - cols + 1, index + cols + 1] - all
   this.neighbors = [index - 1, index + 1, index - cols, index + cols].filter(function(x){
     //start and end checker
     if(x >= 0 && x < cols * rows){
       //left edge checker
	   //diagonals: if(this.index % cols == 0 && (x == this.index - 1 || x == this.index - cols - 1 || x == this.index + cols - 1))
       if(this.index % cols == 0 && x == this.index - 1){
          return false;
       }
       //right edge checker
	   //diagonals: if((this.index + 1) % cols == 0 && (x == this.index + 1 || x == this.index - cols + 1 || x == this.index + cols + 1))
       if((this.index + 1) % cols == 0 && x == this.index + 1){
          return false;
       }
       return true;
     }
     return false;
   }, this);
   //might need later for combat
   this.diagonalNeighbors = [index - cols - 1, index + cols - 1, index - cols + 1, index + cols + 1].filter(function(x){
     if(x >= 0 && x < cols * rows){
       //left edge checker
	   if(this.index % cols == 0 && (x == this.index - 1 || x == this.index - cols - 1 || x == this.index + cols - 1)){
          return false;
       }
       //right edge checker
     if((this.index + 1) % cols == 0 && (x == this.index + 1 || x == this.index - cols + 1 || x == this.index + cols + 1)){
          return false;
       }
       return true;
     }
     return false;
   }, this);
};

function Tilemap(canvas, context) {
    this.tsize = 40; //tile size (40 x 40)
    this.cols = Math.ceil(canvas.width / this.tsize);
    this.rows = Math.ceil(canvas.height / this.tsize);

    this.tiles = [];
    for(var i = 0; i < this.cols * this.rows; i++){
        this.tiles.push(new Tile(i, this.cols, this.rows));
    };

    this.textures = [];
    for(var j = 1; j <= 7; j++){ //change when have spritesheet
        this.textures.push(document.getElementById(('grass-' + j)));
    }

    this.getTile = function(col, row) {
        return this.tiles[row * this.cols + col]
    };

    this.render = function(){
        for (var c = 0; c < this.cols; c++) {
            for (var r = 0; r < this.rows; r++) {
                var tile = this.getTile(c, r);
                if (tile.num == 0) {
                    context.drawImage(this.textures[0], c * this.tsize, r * this.tsize);
                }else if (tile.num == 1){
                    context.fillStyle = '#0d0d0d';
                    context.fillRect(c * this.tsize, r * this.tsize, this.tsize, this.tsize);
                }else if (tile.num == 2){
                    context.fillStyle = 'blue';
                    context.fillRect(c * this.tsize, r * this.tsize, this.tsize, this.tsize);
                }
            }
        }
    };//end of Tilemap render

    this.renderGrid = function(){
        for (var c = 0; c < this.cols; c++) {
            for (var r = 0; r < this.rows; r++) {
                context.strokeStyle = 'white';
                context.strokeRect(c * this.tsize, r * this.tsize, this.tsize, this.tsize);
            }
        }
    };// end of Tilemap render grid

    this.update = function(col, row, value){
        this.tiles[row * this.cols + col].num = value;
    }

    //why do we even need cols and rows here? rewrite with tiles array!
    this.randomize = function(){
        for (var c = 0; c < this.cols; c++) {
            for (var r = 0; r < this.rows; r++) {
                if(Math.random() < 0.2){
                    this.update(c, r, 1);
                }else{
                    this.update(c, r, 0);
                }
            }
        }
    };//end of randomize map

};//end of Tilemap

//PATHFINDER (work in progress)
//https://codepen.io/svmi3195/pen/gRrBBJ

//transforms index of 2d array to index of 1d array
function transIndex(arr, map){
  //arr[0] - x
  //arr[1] - y
  return arr[1] * map.cols + arr[0];
}

//transforms index of 1d array to index of 2d array
function transIndex2(index, map){
  return [index % map.cols, Math.floor(index / map.cols)]
}

function removeFromArray(array, element){
  for(var i = array.length - 1; i >= 0; i--){
    if(array[i] == element){
      array.splice(i, 1);
    }
  }
}

function heuristic(point1, point2){
  var a = point1[0] - point2[0];
  var b = point1[1] - point2[1];

  //euclidian distance
  var distance = Math.sqrt( a*a + b*b );
  //manhattan distance
  //var distance = Math.abs(a) + Math.abs(b);
  return distance;
}

function findPath(map, start, goal){
  var path = [];
  var openList = [];
  var closedList = [];
  if(!start){start = 0}
  if(!goal){goal = map.tiles.length -1}

  openList.push(start);

  var done = false;
  var iteration = 0;

  while(!done){
    iteration++;
    if(openList.length > 0){
      var winner = 0;
      for(var i = 0; i < openList.length; i++){
        if(map.tiles[openList[i]].f < map.tiles[openList[winner]].f){
          winner = i;
        }
      }
      var current = openList[winner];

      if(current == goal){
        done = true;
        console.log('Done!');
        path.push(start);
        var temp = current;
        path.push(temp);
        while(map.tiles[temp].previous){
          path.push(map.tiles[temp].previous);
          temp = map.tiles[temp].previous;
        }
      }

      removeFromArray(openList, current);
      closedList.push(current);

      var neighbors = map.tiles[current].neighbors;
      for(var nb = 0; nb < neighbors.length; nb++){
        var neighbor = neighbors[nb];

        if(!closedList.includes(neighbor) && map.tiles[neighbor].num != 1){
           var tempG = map.tiles[current].g + 1;

          var newPath = false;
          if(openList.includes(neighbor)){
            if(tempG < map.tiles[neighbor].g){
              map.tiles[neighbor].g = tempG;
              newPath = true;
            }
          }else{
            map.tiles[neighbor].g = tempG;
            newPath = true;
            openList.push(neighbor);
          }

          if(newPath){
            map.tiles[neighbor].h = heuristic(transIndex2(neighbor, map), transIndex2(goal, map));
            map.tiles[neighbor].f = map.tiles[neighbor].g + map.tiles[neighbor].h;
            map.tiles[neighbor].previous = current;
          }
        }
      }

  }else{
    //no solution
    done = true;
    return undefined;
  }

  //visualize path with blue rects:
  for(var p = 0; p < path.length; p++){
      map.tiles[path[p]].num = 2;
  }

  }

  return path;
}//end of findPath

<|endoftext|>