<commit_before>
(function () {
	'use strict'

	var worldWidth = 1200;
	var worldHeight = 1200;
	var currentX= worldWidth/2;
	var currentY= worldHeight/2;
	var velocity=5;
	var Keys = {
	        up: false,
	        down: false,
	        left: false,
	        right: false
	    },
	    ctx = background.getContext('2d'),
	    playerCTX = player.getContext('2d'),
	    boardCTX = board.getContext('2d'),
	    dx = 0,
	    dy = 0,
	    ptr,
	    playerPTR;

	// create tile
	ctx.fillStyle = '#2a6d27';
	ctx.fillRect(0, 0, 50, 50);
	ctx.fillStyle = 'rgba(255,255,255,0.5)';
	ctx.fillRect(0, 0, 1, 50);
	ctx.fillRect(0, 0, 50, 1);
	ctx.fillStyle = 'rgba(0,0,0,0.5)';
	ctx.fillRect(0, 39, 50, 1);
	ctx.fillRect(39, 0, 1, 50);
	ptr = ctx.createPattern(background, 'repeat');

	background.width =background.height = 400;
	drawBoard();
	drawTank("west");

	ctx.fillStyle = ptr;
	render();

	function drawTank(direction){

	    var tankWidth = 30,
	    tankHeight = 30,
	    cannonLength = 15,
	    cannonThickness = 11;

	    var rootX,rootY,rootHeight, rootWidth;
		var playerX = (background.width)/2-(tankWidth/2);
	    var playerY = (background.height)/2-(tankHeight/2);;

	    if (typeof direction == "undefined"||direction =='') {
	        direction ="west";
	    }

	    player.width = player.height = 400;

	    // add the player
	    // create tile

	    // find the center

	    playerCTX.fillStyle = 'red';
	    playerCTX.fillRect(playerX, playerY, tankWidth,tankHeight);

	    playerCTX.fillStyle = 'brown';
	    playerCTX.fillRect(playerX+5, playerY+5, tankWidth-10,tankHeight-10);

	    //draw the cannon
	    if(direction =='east'){
	        rootX=(playerX+tankWidth)-5;
	        rootY = playerY+tankHeight/2;
	        rootWidth=cannonLength;
	        rootHeight =cannonThickness/2;
	    }else if(direction =='west'){
	        rootX=(playerX-cannonLength)+5;
	        rootY = (playerY+tankHeight/2);
	        rootWidth=cannonLength;
	        rootHeight =cannonThickness/2;
	    }else if(direction =='north'){
	        rootX=playerX+tankWidth/2;
	        rootY = (playerY-cannonLength+5);
	        rootWidth=cannonThickness/2;
	        rootHeight =cannonLength;
	    }else if(direction =='south'){
	        rootX=playerX+(tankWidth/2);
	        rootY = (playerY+tankHeight)-5;
	        rootWidth=cannonThickness/2;
	        rootHeight =cannonLength;
	    }

	    playerCTX.fillRect(rootX, rootY, rootWidth,rootHeight);

	    playerPTR = playerCTX.createPattern(board, 'no-repeat');

	}

	function drawBoard(){
		var borderY,borderX;

	    board.width =board.height = 400;

	    if(currentY<board.height/2){
	        boardCTX.fillStyle = 'gray';
	        borderY= board.height/2 -currentY;
	        if(borderY<0){
	            borderY=0;
	        }
	        boardCTX.fillRect(0, 0, 400,borderY);
	    }
	    if(currentX<board.width/2){
	        boardCTX.fillStyle = 'gray';
	        borderX = board.width/2 -currentX;
	        if(borderX<0){
	            borderX=0;
	        }
	        boardCTX.fillRect(0, 0, borderX,400);
	    }
	    if(currentX>worldWidth-board.width/2){
	        boardCTX.fillStyle = 'gray';
	        borderX = currentX-worldWidth+board.width/2;
	        if(borderX>400){
	            borderX=400;
	        }
	        boardCTX.fillRect(400-borderX, 0,200+borderX ,400);
	    }
	    if(currentY>worldHeight-board.height/2){
	        boardCTX.fillStyle = 'gray';
	        borderY = currentY-worldHeight+board.height/2;
	        if(borderY>400){
	            borderY=400;
	        }
	        boardCTX.fillRect(0,400-borderY,400,200+borderY);
	    }
	}

	window.onkeydown = function(e) {
	    var kc = e.keyCode;
	    e.preventDefault();

	    if (kc === 37){
	        Keys.left = true;
	        drawTank("west");
	    } else if (kc === 38){
	        Keys.up = true;
	        drawTank("north");
	    } else if (kc === 39){
	        Keys.right = true;
	        drawTank("east");
	    } else if (kc === 40){
	        Keys.down = true;
	        drawTank("south");
	    }
	};

	window.onkeyup = function(e) {
	    var kc = e.keyCode;
	    e.preventDefault();

	    if (kc === 37) Keys.left = false;
	    else if (kc === 38) Keys.up = false;
	    else if (kc === 39) Keys.right = false;
	    else if (kc === 40) Keys.down = false;
	};

	var isDirty = false;

	function update(param) {
	    if (Keys.up) {

	        if(currentY>0){
	            isDirty = true;
	            dy+=velocity;
	            currentY-=velocity;
	        }
	    }
	    else if (Keys.down) {

	        if(currentY<worldHeight){
	            isDirty = true;
	            dy-=velocity;
	            currentY+=velocity;
	        }
	    }

	    if (Keys.left) {
	        if(currentX>0){
	            dx+=velocity;
	            isDirty = true;
	            currentX-=velocity;
	        }
	    }
	    else if (Keys.right) {
	        if(currentX<worldWidth){
	            dx-=velocity;
	            isDirty = true;
	            currentX+=velocity;
	        }
	    }

	    if (isDirty){
	 	   render();
		}
	    //requestAnimationFrame(update);
	}

	function render(param) {
	    drawBoard()
	    ctx.setTransform(1,0,0,1,dx,dy);
	    ctx.fillRect(-dx, -dy, 400,400);
	    isDirty= false;

	}
 	function timestamp() {
  		return window.performance && window.performance.now ? window.performance.now() : new Date().getTime();
	}

	var now, dt,
    last = timestamp(),
    step=1/60;

	function frame() {
  		now   = timestamp();

  		dt = Math.min(1, (now - last) / 1000);

  		while(dt > step) {
    		dt = dt - step;
    		update(step);
  		}
  		//render(dt);
  		last = now;
  		requestAnimationFrame(frame);
	}

	requestAnimationFrame(frame);

})();

<commit_msg>js clean up<commit_after>
(function () {
	'use strict'

	var gameConfig ={
		worldWidth: 1200,
		worldHeight: 1200,
		viewerMaxX:400,
		viewerMaxY:400
	},
	Keys = {
	        up: false,
	        down: false,
	        left: false,
	        right: false
	    },
	    viewerBackgroundCTX = background.getContext('2d'),
	    playerCTX = player.getContext('2d'),
	    boardCTX = board.getContext('2d'),
	    dx = 0,
	    dy = 0,
	    backgroundPTR,
	    playerPTR,
	    currentX,
	    currentY,
	    velocity;

	function initGame(){
		currentX =gameConfig.worldWidth/2,
		currentY =gameConfig.worldHeight/2,
		velocity =5;

		// draw playarea
		board.width = gameConfig.viewerMaxX;
	    board.height = gameConfig.viewerMaxY;

		// create tile
		viewerBackgroundCTX.fillStyle = '#2a6d27';
		viewerBackgroundCTX.fillRect(0, 0, 50, 50);
		viewerBackgroundCTX.fillStyle = 'rgba(255,255,255,0.5)';
		viewerBackgroundCTX.fillRect(0, 0, 1, 50);
		viewerBackgroundCTX.fillRect(0, 0, 50, 1);
		viewerBackgroundCTX.fillStyle = 'rgba(0,0,0,0.5)';
		viewerBackgroundCTX.fillRect(0, 39, 50, 1);
		viewerBackgroundCTX.fillRect(39, 0, 1, 50);

		backgroundPTR = viewerBackgroundCTX.createPattern(background, 'repeat');
		background.width =gameConfig.viewerMaxX;
		background.height = gameConfig.viewerMaxY;

		drawBoard();
		drawTank("west");

		viewerBackgroundCTX.fillStyle = backgroundPTR;
		render();
	}

	function drawTank(direction){

	    var tankWidth = 30,
	    tankHeight = 30,
	    cannonLength = 15,
	    cannonThickness = 11;

	    var rootX,rootY,rootHeight, rootWidth;
		var playerX = (gameConfig.viewerMaxX)/2-(tankWidth/2);
	    var playerY = (gameConfig.viewerMaxY)/2-(tankHeight/2);;

	    player.width = gameConfig.viewerMaxX;;
	    player.height = gameConfig.viewerMaxY;

	    if (typeof direction == "undefined"||direction =='') {
	        direction ="west";
	    }

	    playerCTX.fillStyle = 'red';
	    playerCTX.fillRect(playerX, playerY, tankWidth,tankHeight);

	    playerCTX.fillStyle = 'brown';
	    playerCTX.fillRect(playerX+5, playerY+5, tankWidth-10,tankHeight-10);

	    //draw the cannon
	    if(direction =='east'){
	        rootX=(playerX+tankWidth)-5;
	        rootY = playerY+tankHeight/2;
	        rootWidth=cannonLength;
	        rootHeight =cannonThickness/2;
	    }else if(direction =='west'){
	        rootX=(playerX-cannonLength)+5;
	        rootY = (playerY+tankHeight/2);
	        rootWidth=cannonLength;
	        rootHeight =cannonThickness/2;
	    }else if(direction =='north'){
	        rootX=playerX+tankWidth/2;
	        rootY = (playerY-cannonLength+5);
	        rootWidth=cannonThickness/2;
	        rootHeight =cannonLength;
	    }else if(direction =='south'){
	        rootX=playerX+(tankWidth/2);
	        rootY = (playerY+tankHeight)-5;
	        rootWidth=cannonThickness/2;
	        rootHeight =cannonLength;
	    }

	    playerCTX.fillRect(rootX, rootY, rootWidth,rootHeight);

	    playerPTR = playerCTX.createPattern(board, 'no-repeat');

	}

	function drawBoard(){
		var borderY,borderX;

	    board.width = gameConfig.viewerMaxX;
	    board.height = gameConfig.viewerMaxY;

	    if(currentY<gameConfig.viewerMaxY/2){
	        boardCTX.fillStyle = 'gray';
	        borderY= gameConfig.viewerMaxY/2 -currentY;
	        if(borderY<0){
	            borderY=0;
	        }
	        boardCTX.fillRect(0, 0, 400,borderY);
	    }
	    if(currentX<gameConfig.viewerMaxX/2){
	        boardCTX.fillStyle = 'gray';
	        borderX = gameConfig.viewerMaxX/2 -currentX;
	        if(borderX<0){
	            borderX=0;
	        }
	        boardCTX.fillRect(0, 0, borderX,400);
	    }
	    if(currentX>gameConfig.worldWidth-gameConfig.viewerMaxX/2){
	        boardCTX.fillStyle = 'gray';
	        borderX = currentX-gameConfig.worldWidth+gameConfig.viewerMaxX/2;
	        if(borderX>400){
	            borderX=400;
	        }
	        boardCTX.fillRect(400-borderX, 0,200+borderX ,400);
	    }
	    if(currentY>gameConfig.worldHeight-gameConfig.viewerMaxY/2){
	        boardCTX.fillStyle = 'gray';
	        borderY = currentY-gameConfig.worldHeight+gameConfig.viewerMaxY/2;
	        if(borderY>400){
	            borderY=400;
	        }
	        boardCTX.fillRect(0,400-borderY,400,200+borderY);
	    }
	}

	window.onkeydown = function(e) {
	    var kc = e.keyCode;
	    e.preventDefault();

	    if (kc === 37){
	        Keys.left = true;
	        drawTank("west");
	    } else if (kc === 38){
	        Keys.up = true;
	        drawTank("north");
	    } else if (kc === 39){
	        Keys.right = true;
	        drawTank("east");
	    } else if (kc === 40){
	        Keys.down = true;
	        drawTank("south");
	    }
	};

	window.onkeyup = function(e) {
	    var kc = e.keyCode;
	    e.preventDefault();

	    if (kc === 37) Keys.left = false;
	    else if (kc === 38) Keys.up = false;
	    else if (kc === 39) Keys.right = false;
	    else if (kc === 40) Keys.down = false;
	};

	function update(param) {
	    if (Keys.up) {

	        if(currentY>0){
	            dy+=velocity;
	            currentY-=velocity;
	        }
	    }
	    else if (Keys.down) {

	        if(currentY<gameConfig.worldHeight){
	            dy-=velocity;
	            currentY+=velocity;
	        }
	    }

	    if (Keys.left) {
	        if(currentX>0){
	            dx+=velocity;
	            currentX-=velocity;
	        }
	    }
	    else if (Keys.right) {
	        if(currentX<gameConfig.worldWidth){
	            dx-=velocity;
	            currentX+=velocity;
	        }
	    }

	}

	function render(param) {
	    drawBoard()
	    viewerBackgroundCTX.setTransform(1,0,0,1,dx,dy);
	    viewerBackgroundCTX.fillRect(-dx, -dy, 400,400);

	}
 	function timestamp() {
  		return window.performance && window.performance.now ? window.performance.now() : new Date().getTime();
	}

	var now, dt,
    last = timestamp(),
    step=1/60;

	function frame() {
  		now   = timestamp();

  		dt = Math.min(1, (now - last) / 1000);

  		while(dt > step) {
    		dt = dt - step;
    		update(step);
  		}
  		render();

  		last = now;
  		requestAnimationFrame(frame);
	}
	initGame();
	requestAnimationFrame(frame);

})();

<|endoftext|>


<commit_before>/**
 * Node.js implementation of a G-Homa Control Server
 * See : http://www.fhemwiki.de/wiki/G-Homa
 *
 * Tested with GAO G-Homa EMW302WF (IP20) and G-Homa EMW302WFO (IP44).
 */
var net = require('net');

// Prefix bytes for each data block
var PREFIX = new Buffer([0x5A,0xA5]);
// Postfix bytes for each data block
var POSTFIX = new Buffer([0x5B,0xB5]);

var INIT1A  = new Buffer([0x02,0x05,0x0D,0x07,0x05,0x07,0x12]);
var INIT1B  = new Buffer([0x02]);
var INIT2   = new Buffer([0x05,0x01])
var HEARTBEATREPLY  = new Buffer([0x06]);

var CMD_INIT1REPLY = new Buffer([0x03]);
var CMD_INIT2REPLY = new Buffer([0x07]);
var CMD_HEARTBEAT = new Buffer([0x04]);
var CMD_STATUS = new Buffer([0x90]);

var msg_padding ='             ';
var action_padding ='         ';

// Registry for nodes
var gHomaRegistry = [];
// Timeout to kick the nodes that have not send a heartbeat in some time
var timeout = 60000*5; // 5 Minutes

var server = net.createServer(function(socket) {
  log('','CONNECTED');

  // Should be default 'true' - but who knows
  socket.setNoDelay(true);

  // Used as receive buffer
  var buffer = new Buffer(0);

  // Initialize ghoma object
  var ghoma = {
    state : 'unknown',
    triggered : 'unknown',
    remoteAddress : socket.remoteAddress,
    remotePort : socket.remotePort,
    initalized : new Date(),
    lastheartbeat : new Date(),
    reregistered : 0,
    on : switchOn,
    off : switchOff,
    socket : socket
  }

  // Send init 1 msg
  var init1Msg = Buffer.concat([
    BuildMsg(INIT1A),
    BuildMsg(INIT1B),
  ]);
  send('INIT1',init1Msg);

  // Add a 'data' event handler to this instance of socket
  socket.on('data', function(data) {
      log('RECV', 'DATA', data);
      buffer = Buffer.concat([buffer, data]);
      var msg=nextMsg();
      while( msg ) {
        if( msg.command.equals( CMD_INIT1REPLY ) ) {
          ghoma.shortMac = msg.payload.slice(6,9);
          ghoma.id = ghoma.shortMac.toString('hex');
          // Remember the trigger code - used for on/off.
          ghoma.triggercode = msg.payload.slice(4,6);
          send('INIT2', BuildMsg(INIT2));
        } else if( msg.command.equals( CMD_INIT2REPLY ) ) {
          log('HANDLE', 'INIT2 RPLY');
          // Init2 reply comes 2 times - the first has the full mac address at the end of the paylod
          var fullMac = msg.payload.slice(msg.payload.length-6,msg.payload.length);

          if( ghoma.shortMac.equals(fullMac.slice(3))) {
            // Fullmac and shotmac matches -> first reply
            ghoma.fullMac = fullMac;
          } else {
            // Fullmac and shotmac does not match -> second reply -> remember it.
            var idx = indexOfById(ghoma.id);
            if( idx != -1 ) {
              // A reconnect of a existing. Replace existing.
              log('INFO','REREG' );
              if( exports.onClose ) {
                exports.onClose(gHomaRegistry[idx]);
              }
              ghoma.reregistered = gHomaRegistry[idx].reregistered + 1;
              gHomaRegistry[idx] = ghoma;
            } else {
              // a new never seen plug
              log('INFO','REG');
              gHomaRegistry.push(ghoma);
            }

            // notify listener about the new plug
            if( exports.onNew ) {
              exports.onNew(ghoma);
            }

          }
        } else if( msg.command.equals( CMD_STATUS ) ) {
          log('HANDLE', 'STATUS', msg.payload);

          var newstate = 'unknown';
          if( msg.payload[msg.payload.length-1] == 0xff ) {
            newstate = 'on'
          } else if( msg.payload[msg.payload.length-1] == 0x00 ) {
            newstate = 'off'
          }
          if( newstate!=ghoma.state ) {
            ghoma.prevstate = ghoma.state;
            ghoma.state = newstate;
            ghoma.statechanged = new Date();
            if( msg.payload[12] == 0x81 ) {
              ghoma.triggered = 'local';
            }else if( msg.payload[12] == 0x11 ) {
              ghoma.triggered = 'remote';
            } else {
              ghoma.triggered = 'unknown';
            }
            if( exports.onStatusChange ) {
              exports.onStatusChange(ghoma);
            }
          }
        } else if( msg.command.equals( CMD_HEARTBEAT ) ) {
          ghoma.lastheartbeat = new Date();
          if( exports.onHeartbeat ) {
            exports.onHeartbeat(ghoma);
          }
          send('HEARTBEAT RPLY', BuildMsg(HEARTBEATREPLY));
        } else {
          log('HANDLE','UNSUP CMD', msg.command );
        }
        msg=nextMsg();
      }
  });

  socket.on('close', function(data) {
    log('CLOSED', '');
    if( exports.onClose ) {
      exports.onClose(ghoma);
    }
    var idx = gHomaRegistry.indexOf(ghoma);
    if( idx!=-1 ) {
      gHomaRegistry.splice(idx,1);
    } else {
      log('WARN','CLOSENOREG');
    }
  });

  socket.on('error', function(err) {
    log('SCK ERR',err);
  });

  // Send msg via socket
  function send(msg, data) {
    log('SEND', msg, data);
    socket.write(data);
  }

  // Build and send on message
  function switchOn(){
    var onMsg = BuildMsg(
      Buffer.concat([
        //new Buffer([0x10,0x01,0x01,0x0a,0xe0,0x32,0x23]),
        new Buffer([0x10,0x01,0x01,0x0a,0xe0]),
        ghoma.triggercode,
        ghoma.shortMac,
        new Buffer([0xff,0xfe,0x00,0x00,0x10,0x11,0x00,0x00,0x01,0x00,0x00,0x00,0xff])
      ])
    );
    send('ON', onMsg);
  };

  // Build and send off message
  function switchOff(){
    var offMsg =BuildMsg(
      Buffer.concat([
        //new Buffer([0x10,0x01,0x01,0x0a,0xe0,0x32,0x23]),
        new Buffer([0x10,0x01,0x01,0x0a,0xe0]),
        ghoma.triggercode,
        ghoma.shortMac,
        new Buffer([0xff,0xfe,0x00,0x00,0x10,0x11,0x00,0x00,0x01,0x00,0x00,0x00,0x00])
      ])
    );
    send('OFF', offMsg);
  };

  // Extract next message from ghoma switch
  function nextMsg() {
    var msg = {};
    var prefixPos = buffer.indexOf(PREFIX);
    if( prefixPos!=-1 ) {
      if( prefixPos!=0 ) {
        throw Error("Prefix position not at 0.")
      }
      msg.length = buffer.readUIntBE(2,2);
      var postFixPos = buffer.indexOf(POSTFIX, 2);
      if( postFixPos!=-1 ) {
        msg.checksum = buffer.slice(postFixPos-1,postFixPos);
        msg.payload = buffer.slice(4, postFixPos-1);
        msg.command = msg.payload.slice(0,1);
        var sum = 0;
        for( i=0; i<msg.payload.length; i++) sum+=msg.payload[i];
        var checksum = new Buffer([0xFF - (sum & 255)]);

        if( msg.checksum[0]!=checksum[0]) {
          throw Error("Checksum error "+ msg.checksum[0] +" <> "+checksum[0]);
        }

        // Cut buffer
        buffer = buffer.slice(postFixPos+2);
        return msg;
      }
    }
  }

  function BuildMsg(payload) {
    // Calculate length from payload
    var length2Bytes= new Buffer([ payload.length >>> 8, payload.length & 255]);

    // Calculate checksum from payload
    var sum = 0;
    for( i=0; i<payload.length; i++) sum+=payload[i];
    var checksum = new Buffer([0xFF - (sum & 255)]);

    // Return concat result
    return Buffer.concat([
      PREFIX,
      length2Bytes,
      payload,
      checksum,
      POSTFIX
    ]);
  }

  function log(action, msg, data) {
    if( exports.log ) {
      if( data && msg ) {
        exports.log(pad(action_padding,action)+' ['+pad(msg_padding,msg)+'] '+ socket.remoteAddress + ' : ' + data.toString('hex'));
      } else {
        exports.log(pad(action_padding,action)+' ['+pad(msg_padding,msg)+'] '+ socket.remoteAddress);
      }
    }
  }

});

//
// Local helper functions
//

pad = function (pad, msg) { return (pad + msg).slice(-pad.length); }

log = function(action, msg) {
  if( exports.log ) {
    exports.log(pad(action_padding,'GHOMA')+' ['+pad(msg_padding,action)+'] '+msg);
  }
}

// Get plug by id
indexOfById = function(id) {
  var fid = -1;
  gHomaRegistry.forEach( function(ghoma,idx) {
    if( ghoma.id==id) {
      fid = idx;
    }
  });
  return fid;
}

// Return not the complete plug object
filterPlug = function(plug) {
  return {
    id : plug.id,
    state : plug.state,
    statechanged: plug.statechanged,
    tiggered: plug.triggered,
    prevstate : plug.prevstate,
    initalized : plug.initalized,
    remoteAddress : plug.remoteAddress,
    remotePort : plug.remotePort,
    on : plug.on,
    off : plug.off,
    reregistered : plug.reregistered,
    heartbeat: plug.lastheartbeat
  }
}

/**
 * Iterator method, to go to each registered plug.
 *
 * @param callback will receive the ghoma objects as first parameter.
 */
exports.forEach = function(callback) {
  gHomaRegistry.forEach(function(plug) {
    callback(filterPlug(plug));
  });
}

/**
 * Get a ghoma plug by ident
 *
 * @param id The ident. The ident is compared to the hex representation of the short mac.
 */
exports.get = function(id) {
  var idx = indexOfById(id);
  return (idx!=-1 ? filterPlug(gHomaRegistry[idx]) : null);
}

/**
 * Start listening server.
 *
 * @param port The listening port. Must match the port configured for the plugs.
 * @param address Optional binding address.
 */
exports.startServer=function(port, address) {
  log('START','Control server start at '+new Date());

  // Create server socket
  server.listen(port, address);

  // Start the check timeer
  checkTimer = setInterval( function() {
    var now = new Date();
    log('CHECK',now);
    gHomaRegistry.forEach( function(plug) {
      var diff = now.getTime() - plug.lastheartbeat.getTime();
      if( diff > timeout ) {
        log('TIMEOUT', 'No hearbeat from ['+plug.id+'] in '+diff+' ms. Last hearbeat was ['+plug.lastheartbeat+'].');
        plug.socket.destroy();  // This should trigger close
      }
    });
  }, timeout );

}

/**
 * Shutdown the server.
 */
exports.shutdown=function() {
  log('SHUTDOWN','Control server shutdown at '+new Date());
  // Destroy each socket
  gHomaRegistry.forEach(function(plug) {
    plug.socket.destroy();
  });
  // Close server socket
  server.close();
  // Remove check timer
  clearInterval(checkTimer);
}
<commit_msg>Switch state only for valid values<commit_after>/**
 * Node.js implementation of a G-Homa Control Server
 * See : http://www.fhemwiki.de/wiki/G-Homa
 *
 * Tested with GAO G-Homa EMW302WF (IP20) and G-Homa EMW302WFO (IP44).
 */
var net = require('net');

// Prefix bytes for each data block
var PREFIX = new Buffer([0x5A,0xA5]);
// Postfix bytes for each data block
var POSTFIX = new Buffer([0x5B,0xB5]);

var INIT1A  = new Buffer([0x02,0x05,0x0D,0x07,0x05,0x07,0x12]);
var INIT1B  = new Buffer([0x02]);
var INIT2   = new Buffer([0x05,0x01])
var HEARTBEATREPLY  = new Buffer([0x06]);

var CMD_INIT1REPLY = new Buffer([0x03]);
var CMD_INIT2REPLY = new Buffer([0x07]);
var CMD_HEARTBEAT = new Buffer([0x04]);
var CMD_STATUS = new Buffer([0x90]);

var msg_padding ='             ';
var action_padding ='         ';

// Registry for nodes
var gHomaRegistry = [];
// Timeout to kick the nodes that have not send a heartbeat in some time
var timeout = 60000*5; // 5 Minutes

var server = net.createServer(function(socket) {
  log('','CONNECTED');

  // Should be default 'true' - but who knows
  socket.setNoDelay(true);

  // Used as receive buffer
  var buffer = new Buffer(0);

  // Initialize ghoma object
  var ghoma = {
    state : 'unknown',
    triggered : 'unknown',
    remoteAddress : socket.remoteAddress,
    remotePort : socket.remotePort,
    initalized : new Date(),
    lastheartbeat : new Date(),
    reregistered : 0,
    on : switchOn,
    off : switchOff,
    socket : socket
  }

  // Send init 1 msg
  var init1Msg = Buffer.concat([
    BuildMsg(INIT1A),
    BuildMsg(INIT1B),
  ]);
  send('INIT1',init1Msg);

  // Add a 'data' event handler to this instance of socket
  socket.on('data', function(data) {
      log('RECV', 'DATA', data);
      buffer = Buffer.concat([buffer, data]);
      var msg=nextMsg();
      while( msg ) {
        if( msg.command.equals( CMD_INIT1REPLY ) ) {
          ghoma.shortMac = msg.payload.slice(6,9);
          ghoma.id = ghoma.shortMac.toString('hex');
          // Remember the trigger code - used for on/off.
          ghoma.triggercode = msg.payload.slice(4,6);
          send('INIT2', BuildMsg(INIT2));
        } else if( msg.command.equals( CMD_INIT2REPLY ) ) {
          log('HANDLE', 'INIT2 RPLY');
          // Init2 reply comes 2 times - the first has the full mac address at the end of the paylod
          var fullMac = msg.payload.slice(msg.payload.length-6,msg.payload.length);

          if( ghoma.shortMac.equals(fullMac.slice(3))) {
            // Fullmac and shotmac matches -> first reply
            ghoma.fullMac = fullMac;
          } else {
            // Fullmac and shotmac does not match -> second reply -> remember it.
            var idx = indexOfById(ghoma.id);
            if( idx != -1 ) {
              // A reconnect of a existing. Replace existing.
              log('INFO','REREG' );
              if( exports.onClose ) {
                exports.onClose(gHomaRegistry[idx]);
              }
              ghoma.reregistered = gHomaRegistry[idx].reregistered + 1;
              gHomaRegistry[idx] = ghoma;
            } else {
              // a new never seen plug
              log('INFO','REG');
              gHomaRegistry.push(ghoma);
            }

            // notify listener about the new plug
            if( exports.onNew ) {
              exports.onNew(ghoma);
            }

          }
        } else if( msg.command.equals( CMD_STATUS ) ) {
          log('HANDLE', 'STATUS', msg.payload);

          var newstate = 'unknown';
          if( msg.payload[msg.payload.length-1] == 0xff ) {
            newstate = 'on'
          } else if( msg.payload[msg.payload.length-1] == 0x00 ) {
            newstate = 'off'
          } else {
            log('HANDLE', 'STATUS', 'Status unknown: ' +  msg.payload[msg.payload.length-1]);
          }
          if( newstate!=ghoma.state && newstate != 'unknown') {
            ghoma.prevstate = ghoma.state;
            ghoma.state = newstate;
            ghoma.statechanged = new Date();
            if( msg.payload[12] == 0x81 ) {
              ghoma.triggered = 'local';
            }else if( msg.payload[12] == 0x11 ) {
              ghoma.triggered = 'remote';
            } else {
              ghoma.triggered = 'unknown';
            }
            if( exports.onStatusChange ) {
              exports.onStatusChange(ghoma);
            }
          }
        } else if( msg.command.equals( CMD_HEARTBEAT ) ) {
          ghoma.lastheartbeat = new Date();
          if( exports.onHeartbeat ) {
            exports.onHeartbeat(ghoma);
          }
          send('HEARTBEAT RPLY', BuildMsg(HEARTBEATREPLY));
        } else {
          log('HANDLE','UNSUP CMD', msg.command );
        }
        msg=nextMsg();
      }
  });

  socket.on('close', function(data) {
    log('CLOSED', '');
    if( exports.onClose ) {
      exports.onClose(ghoma);
    }
    var idx = gHomaRegistry.indexOf(ghoma);
    if( idx!=-1 ) {
      gHomaRegistry.splice(idx,1);
    } else {
      log('WARN','CLOSENOREG');
    }
  });

  socket.on('error', function(err) {
    log('SCK ERR',err);
  });

  // Send msg via socket
  function send(msg, data) {
    log('SEND', msg, data);
    socket.write(data);
  }

  // Build and send on message
  function switchOn(){
    var onMsg = BuildMsg(
      Buffer.concat([
        //new Buffer([0x10,0x01,0x01,0x0a,0xe0,0x32,0x23]),
        new Buffer([0x10,0x01,0x01,0x0a,0xe0]),
        ghoma.triggercode,
        ghoma.shortMac,
        new Buffer([0xff,0xfe,0x00,0x00,0x10,0x11,0x00,0x00,0x01,0x00,0x00,0x00,0xff])
      ])
    );
    send('ON', onMsg);
  };

  // Build and send off message
  function switchOff(){
    var offMsg =BuildMsg(
      Buffer.concat([
        //new Buffer([0x10,0x01,0x01,0x0a,0xe0,0x32,0x23]),
        new Buffer([0x10,0x01,0x01,0x0a,0xe0]),
        ghoma.triggercode,
        ghoma.shortMac,
        new Buffer([0xff,0xfe,0x00,0x00,0x10,0x11,0x00,0x00,0x01,0x00,0x00,0x00,0x00])
      ])
    );
    send('OFF', offMsg);
  };

  // Extract next message from ghoma switch
  function nextMsg() {
    var msg = {};
    var prefixPos = buffer.indexOf(PREFIX);
    if( prefixPos!=-1 ) {
      if( prefixPos!=0 ) {
        throw Error("Prefix position not at 0.")
      }
      msg.length = buffer.readUIntBE(2,2);
      var postFixPos = buffer.indexOf(POSTFIX, 2);
      if( postFixPos!=-1 ) {
        msg.checksum = buffer.slice(postFixPos-1,postFixPos);
        msg.payload = buffer.slice(4, postFixPos-1);
        msg.command = msg.payload.slice(0,1);
        var sum = 0;
        for( i=0; i<msg.payload.length; i++) sum+=msg.payload[i];
        var checksum = new Buffer([0xFF - (sum & 255)]);

        if( msg.checksum[0]!=checksum[0]) {
          throw Error("Checksum error "+ msg.checksum[0] +" <> "+checksum[0]);
        }

        // Cut buffer
        buffer = buffer.slice(postFixPos+2);
        return msg;
      }
    }
  }

  function BuildMsg(payload) {
    // Calculate length from payload
    var length2Bytes= new Buffer([ payload.length >>> 8, payload.length & 255]);

    // Calculate checksum from payload
    var sum = 0;
    for( i=0; i<payload.length; i++) sum+=payload[i];
    var checksum = new Buffer([0xFF - (sum & 255)]);

    // Return concat result
    return Buffer.concat([
      PREFIX,
      length2Bytes,
      payload,
      checksum,
      POSTFIX
    ]);
  }

  function log(action, msg, data) {
    if( exports.log ) {
      if( data && msg ) {
        exports.log(pad(action_padding,action)+' ['+pad(msg_padding,msg)+'] '+ socket.remoteAddress + ' : ' + data.toString('hex'));
      } else {
        exports.log(pad(action_padding,action)+' ['+pad(msg_padding,msg)+'] '+ socket.remoteAddress);
      }
    }
  }

});

//
// Local helper functions
//

pad = function (pad, msg) { return (pad + msg).slice(-pad.length); }

log = function(action, msg) {
  if( exports.log ) {
    exports.log(pad(action_padding,'GHOMA')+' ['+pad(msg_padding,action)+'] '+msg);
  }
}

// Get plug by id
indexOfById = function(id) {
  var fid = -1;
  gHomaRegistry.forEach( function(ghoma,idx) {
    if( ghoma.id==id) {
      fid = idx;
    }
  });
  return fid;
}

// Return not the complete plug object
filterPlug = function(plug) {
  return {
    id : plug.id,
    state : plug.state,
    statechanged: plug.statechanged,
    tiggered: plug.triggered,
    prevstate : plug.prevstate,
    initalized : plug.initalized,
    remoteAddress : plug.remoteAddress,
    remotePort : plug.remotePort,
    on : plug.on,
    off : plug.off,
    reregistered : plug.reregistered,
    heartbeat: plug.lastheartbeat
  }
}

/**
 * Iterator method, to go to each registered plug.
 *
 * @param callback will receive the ghoma objects as first parameter.
 */
exports.forEach = function(callback) {
  gHomaRegistry.forEach(function(plug) {
    callback(filterPlug(plug));
  });
}

/**
 * Get a ghoma plug by ident
 *
 * @param id The ident. The ident is compared to the hex representation of the short mac.
 */
exports.get = function(id) {
  var idx = indexOfById(id);
  return (idx!=-1 ? filterPlug(gHomaRegistry[idx]) : null);
}

/**
 * Start listening server.
 *
 * @param port The listening port. Must match the port configured for the plugs.
 * @param address Optional binding address.
 */
exports.startServer=function(port, address) {
  log('START','Control server start at '+new Date());

  // Create server socket
  server.listen(port, address);

  // Start the check timeer
  checkTimer = setInterval( function() {
    var now = new Date();
    log('CHECK',now);
    gHomaRegistry.forEach( function(plug) {
      var diff = now.getTime() - plug.lastheartbeat.getTime();
      if( diff > timeout ) {
        log('TIMEOUT', 'No hearbeat from ['+plug.id+'] in '+diff+' ms. Last hearbeat was ['+plug.lastheartbeat+'].');
        plug.socket.destroy();  // This should trigger close
      }
    });
  }, timeout );

}

/**
 * Shutdown the server.
 */
exports.shutdown=function() {
  log('SHUTDOWN','Control server shutdown at '+new Date());
  // Destroy each socket
  gHomaRegistry.forEach(function(plug) {
    plug.socket.destroy();
  });
  // Close server socket
  server.close();
  // Remove check timer
  clearInterval(checkTimer);
}
<|endoftext|>


<commit_before>// Consntants
var es_url = "http://fatcat-test.jc.rl.ac.uk:9200/badc/eufar/_search";

// Initialise map
var map = new google.maps.Map(document.getElementById('map'), {
    mapTypeId: google.maps.MapTypeId.TERRAIN,
    zoom: 7
});

// Array function
function is_in(array, item) {
    for (i = 0; i < array.length; i++) {
        if (i === array[i]) {
            return true;
        }
    }
    return false;
}

// Centre on London
var address = "Nordvest-Spitsbergen National Park"
var geocoder = new google.maps.Geocoder();
geocoder.geocode(
    {'address': address},
    function(results, status) {
        if(status == google.maps.GeocoderStatus.OK) {
            new google.maps.Marker({
                map: map,
                position: results[0].geometry.location
            });
        map.setCenter(results[0].geometry.location);
        }
    }
);

function create_es_request(bbox, offset) {
    temp_ne = bbox.getNorthEast();
    temp_sw = bbox.getSouthWest();

    // Build search extent using lng/lat and opposite corners
    nw = [temp_sw.lng().toString(),
          temp_ne.lat().toString()];
    se = [temp_ne.lng().toString(),
          temp_sw.lat().toString()];

    // Construct request for ElasticSearch
    request = {
        "_source": {
            "include": [
                "file.filename",
                "file.path",
                "spatial.geometries.bbox",
                "temporal"
            ]
        },
        "query": {
            "geo_shape": {
                "bbox": {
                    "shape": {
                        "type": "envelope",
                        "coordinates": [nw, se]
                    }
                }
            }
        },
        "size": 12
    };

    return request;
};

function construct_polygon(bbox) {
    // Construct bounding box polygon
    vertices = [];
    vertices.push(new google.maps.LatLng(bbox[0][1], bbox[0][0]));
    vertices.push(new google.maps.LatLng(bbox[1][1], bbox[1][0]));
    vertices.push(new google.maps.LatLng(bbox[3][1], bbox[3][0]));
    vertices.push(new google.maps.LatLng(bbox[2][1], bbox[2][0]));
    polygon = new google.maps.Polygon({
        paths: vertices,
        geodesic: false,
        strokeColor: "#FF0000",
        strokeWeight: 1,
        strokeOpacity: 1.0,
        fillColor: "#FF0000",
        fillOpacity: 0.1
    });

    return polygon
}

// Construct an info window from ElasticSearch hit
function construct_info_window(hit) {
    content = "

Filename: " +
              hit.file.filename + "
"

    if (hit.temporal) {
        content += "
Start Time: " +
                    hit.temporal.start_time + "
" +
                    "
End Time: " +
                    hit.temporal.end_time + "
"
    }

    content += "
Get data

"

    info = new google.maps.InfoWindow({
        content: content
    });

    return info;
}

// Function to search ES for data
var polygons = []
var info_windows = []
function search_es_bbox(bbox) {
    xhr = new XMLHttpRequest();
    xhr.open("POST", es_url, true);
    xhr.send(JSON.stringify(create_es_request(bbox)));

    // Handle the response
    xhr.onload = function (e) {
        if (xhr.readyState === 4) {
            response = JSON.parse(xhr.responseText);
            if (response.hits) {
                hits = response.hits.hits;
                for (i in hits) {
                    hit = hits[i]._source;
                    bbox = hit.spatial.geometries.bbox.coordinates;

                    // Construct and display polygon
                    polygon = construct_polygon(bbox);
                    polygons.push(polygon);
                    polygon.setMap(map);

                    // Add info window
                    iw = construct_info_window(hits[i]._source);
                    info_windows.push(iw);
                }

                for (i in info_windows) {
                    google.maps.event.addListener(
                        polygons[i], 'click',
                        (function(i, e) {
                            return function(e) {
                                for (j in info_windows) {
                                    info_windows[j].close()
                                }
                                info_windows[i].open(map, null);
                                info_windows[i].setPosition(e.latLng);
                            }
                        })(i)
                    );
                }
            }
        }
    }
}

function add_bounds_changed_listener(map) {
    // Add event listener to map
    google.maps.event.addListenerOnce(map, 'bounds_changed', function() {
        for (p in polygons) {
            polygons[p].setMap(null);
        }

        for (i in info_windows) {
            info_windows[i].close();
        }

        // Empty old arrays
        polygons = [];
        info_windows = []

        // Make ES request for geo data
        bounds = map.getBounds();
        search_es_bbox(bounds);

        // Rate-limit requests to ES to 1 every second
        window.setTimeout(function () {
            add_bounds_changed_listener(map)
        }, 1000);
    });
}
add_bounds_changed_listener(map);
<commit_msg>Add comments and tidy up Javascript for map interface<commit_after>// Constants
var es_url = "http://fatcat-test.jc.rl.ac.uk:9200/badc/eufar/_search";

// Initialise map
var map = new google.maps.Map(document.getElementById('map'), {
    mapTypeId: google.maps.MapTypeId.TERRAIN,
    zoom: 6
});

// Array function
function is_in(array, item) {
    for (i = 0; i < array.length; i++) {
        if (i === array[i]) {
            return true;
        }
    }
    return false;
}

// Centre the map on Hungary (because there's lots of data there)
var address = "Lake Balaton, Hungary"
var geocoder = new google.maps.Geocoder();
geocoder.geocode(
    {
        "address": address
    },
    function(results, status) {
            map.setCenter(results[0].geometry.location);
    }
);

// Creates an ES geo_shape filter query based on a bounding box
function create_es_request(bbox, offset) {
    temp_ne = bbox.getNorthEast();
    temp_sw = bbox.getSouthWest();

    // Build search extent using lng/lat and opposite corners
    nw = [temp_sw.lng().toString(),
          temp_ne.lat().toString()];
    se = [temp_ne.lng().toString(),
          temp_sw.lat().toString()];

    // Construct request for ElasticSearch
    request = {
        "_source": {
            "include": [
                "file.filename",
                "file.path",
                "spatial.geometries.bbox",
                "temporal"
            ]
        },
        "query": {
            "geo_shape": {
                "bbox": {
                    "shape": {
                        "type": "envelope",
                        "coordinates": [nw, se]
                    }
                }
            }
        },
        "size": 15
    };

    return request;
};

// Construct a google.maps.Polygon object from a bounding box
function construct_polygon(bbox) {
    // Construct bounding box polygon
    vertices = [];
    vertices.push(new google.maps.LatLng(bbox[0][1], bbox[0][0]));
    vertices.push(new google.maps.LatLng(bbox[1][1], bbox[1][0]));
    vertices.push(new google.maps.LatLng(bbox[3][1], bbox[3][0]));
    vertices.push(new google.maps.LatLng(bbox[2][1], bbox[2][0]));
    polygon = new google.maps.Polygon({
        paths: vertices,
        geodesic: false,
        strokeColor: "#FF0000",
        strokeWeight: 1,
        strokeOpacity: 1.0,
        fillColor: "#FF0000",
        fillOpacity: 0.1
    });

    return polygon
}

// Construct an info window from an ElasticSearch hit
// containing some useful metadata
function construct_info_window(hit) {
    content = "

Filename: " +
              hit.file.filename + "
"

    if (hit.temporal) {
        content += "
Start Time: " +
                    hit.temporal.start_time + "
" +
                    "
End Time: " +
                    hit.temporal.end_time + "
"
    }

    content += "
Get data

"

    info = new google.maps.InfoWindow({
        content: content
    });

    return info;
}

// Search ES for data (and display received data asynchronously)
var polygons = []
var info_windows = []
function search_es_bbox(bbox) {
    xhr = new XMLHttpRequest();
    xhr.open("POST", es_url, true);
    xhr.send(JSON.stringify(create_es_request(bbox)));

    // Handle the response
    xhr.onload = function (e) {
        if (xhr.readyState === 4) {
            response = JSON.parse(xhr.responseText);
            if (response.hits) {
                hits = response.hits.hits;
                for (i in hits) {
                    hit = hits[i]._source;
                    bbox = hit.spatial.geometries.bbox.coordinates;

                    // Construct and display polygon
                    polygon = construct_polygon(bbox);
                    polygon.setMap(map);
                    polygons.push(polygon);

                    // Add info window
                    iw = construct_info_window(hits[i]._source);
                    info_windows.push(iw);
                }

                // Add a listener to the constructed Polygon that closes all
                // InfoWindows, then opens a new one corresponding to the
                // polygon that was clicked
                for (i in info_windows) {
                    google.maps.event.addListener(
                        polygons[i], 'click',
                        (function(i, e) {
                            return function(e) {
                                for (j in info_windows) {
                                    info_windows[j].close()
                                }
                                info_windows[i].open(map, null);
                                info_windows[i].setPosition(e.latLng);
                            }
                        })(i)
                    );
                }
            }
        }
    }
}

// Add a listener to make an ES data request when the map bounds change
function add_bounds_changed_listener(map) {
    google.maps.event.addListenerOnce(map, 'bounds_changed',
        function() {
            // Clean up old polygons and info windows
            for (p in polygons) {
                polygons[p].setMap(null);
            }

            for (i in info_windows) {
                info_windows[i].close();
            }

            polygons = [];
            info_windows = []

            // Make ES request
            bounds = map.getBounds();
            search_es_bbox(bounds);

            // Rate-limit requests to ES to 1 per second
            window.setTimeout(function () {
                add_bounds_changed_listener(map)
            }, 1000);
        }
    );
}

// Start the main "bounds_changed" listener loop
add_bounds_changed_listener(map);
<|endoftext|>


<commit_before>var chart;

function init_graph(data, series, field, total_label, yAxisLabel) {
    if (!total_label) {
        total_label = "total";
    }

    var values = [];

    for (var i = 0; i < series.length; i++) {
        values.push([]);
    }

    for (var x = 0; x < data.length; x++) {
        let datum = data[x];
        var date = new Date(datum.date);

        var url = null;
        if (x > 0) {
            url = "https://github.com/rust-lang/rust/compare/" + data[x - 1].commit + "..." + data[x].commit;
        }

        for (var i = 0; i < series.length; i++) {
            let value = {
                commit: datum.commit,
                url: url,
                y: 0,
                x: date.valueOf() // number of milliseconds since 1970
            };
            if (series[i] in datum.data) {
                if (field in datum.data[series[i]]) {
                    value.y = datum.data[series[i]][field];
                }
            }
            value.name = date.toLocaleString();
            values[i].push(value);
        }
    }

    var datasets = [];
    for (var i = 0; i < series.length; i++) {
        var label = series[i];
        if (label == "total") {
            label = total_label;
        }
        datasets.push({
            name: label,
            animation: false,
            allowPointSelect: true,
            data: values[i],
            marker: {
                enabled: true
            },
        });
    }

    if (chart) {
        chart.destroy();
    }
    chart = new Highcharts.Chart({
        chart: {
            zoomType: "xy",
            renderTo: "chart-container",
            type: "line",
        },
        title: {
            text: "",
        },
        rangeSelector: {
            selected: 1,
        },
        series: datasets,
        tooltip: {
            shared: true,
            crosshairs: [true],
            formatter: function () {
                var date = new Date(this.x);
                var commit = this.points[0].point.commit.substr(0, 10);
                var s = "" + date.toLocaleString() + " - " + commit + "";
                for (let point of this.points) {
                    s += "
" + point.series.name + ": " + point.y;
                }
                return s;
            }
        },
        xAxis: {
            type: "datetime",
        },
        yAxis: {
            min: 0,
            title: {
                text: yAxisLabel,
            }
        },
        plotOptions: {
            line: {
                point: {
                    events: {
                        click: function (event) {
                            if (this.options.url) {
                                window.open(this.options.url, "_blank");
                            }
                            return false;
                        }
                    }
                }
            }
        }
    });
}
<commit_msg>Display only the current series in graph tooltips<commit_after>var chart;

function init_graph(data, series, field, total_label, yAxisLabel) {
    if (!total_label) {
        total_label = "total";
    }

    var values = [];

    for (var i = 0; i < series.length; i++) {
        values.push([]);
    }

    for (var x = 0; x < data.length; x++) {
        let datum = data[x];
        var date = new Date(datum.date);

        var url = null;
        if (x > 0) {
            url = "https://github.com/rust-lang/rust/compare/" + data[x - 1].commit + "..." + data[x].commit;
        }

        for (var i = 0; i < series.length; i++) {
            let value = {
                commit: datum.commit,
                url: url,
                y: 0,
                x: date.valueOf() // number of milliseconds since 1970
            };
            if (series[i] in datum.data) {
                if (field in datum.data[series[i]]) {
                    value.y = datum.data[series[i]][field];
                }
            }
            value.name = date.toLocaleString();
            values[i].push(value);
        }
    }

    var datasets = [];
    for (var i = 0; i < series.length; i++) {
        var label = series[i];
        if (label == "total") {
            label = total_label;
        }
        datasets.push({
            name: label,
            animation: false,
            allowPointSelect: true,
            data: values[i],
            marker: {
                enabled: true
            },
        });
    }

    if (chart) {
        chart.destroy();
    }
    chart = new Highcharts.Chart({
        chart: {
            zoomType: "xy",
            renderTo: "chart-container",
            type: "line",
        },
        title: {
            text: "",
        },
        rangeSelector: {
            selected: 1,
        },
        series: datasets,
        tooltip: {
            crosshairs: [true],
            formatter: function () {
                var date = new Date(this.x);
                var commit = this.point.commit.substr(0, 10);
                return "" + date.toLocaleString() + " - " + commit + "" +
                    "
" + this.series.name + ": " + this.y;
            }
        },
        xAxis: {
            type: "datetime",
        },
        yAxis: {
            min: 0,
            title: {
                text: yAxisLabel,
            }
        },
        plotOptions: {
            line: {
                point: {
                    events: {
                        click: function (event) {
                            if (this.options.url) {
                                window.open(this.options.url, "_blank");
                            }
                            return false;
                        }
                    }
                }
            }
        }
    });
}
<|endoftext|>


<commit_before>module.exports = function(grunt) {

  // Project configuration.
  grunt.initConfig({
    pkg: '<json:package.json>',
    lint: {
      files: ['grunt.js', 'mvc/**/*.js', 'test/*_test.js']
    },
    concat: {
      // Public JS
      'public': {
        src: [
          // sugar
          'public/sugar.js',
          // jQuery, then Bootstrap
          'public/js/jquery.js', 'public/js/bootstrap.js',
          // then Knockout
          'public/js/knockout.js',
          // then GMaps
          'public/js/gmaps.js',
          // then other js libs
          'public/js/*.js'
        ],
        dest: 'dist/js/all.js'
      },
      'mvc': {
        src: [
          'models/mapperList.js',
          'models/*.js'
        ],
        dest: 'dist/mvc/all.js'
      }
    },
    less: {
      'public': {
        src: 'public/css/index.less',
        dest: 'dist/css/all.css'
      }
    },
    watch: {
      'js': {
        files: ['public/js/**', 'mvc/**/*.js'],
        tasks: 'js'
      },
      'css': {
        files: 'public/css/**',
        tasks: 'css'
      }
    },
    jshint: {
      options: {
        curly: true,
        eqeqeq: true,
        immed: true,
        newcap: true,
        noarg: true,
        sub: true,
        undef: true,
        boss: true,
        eqnull: true,
        node: true,

        // ugh, should get a proper set up for envs
        browser: true,

        // Ignore strict
        strict: false
      },
      globals: {
        exports: true,
        describe: true,
        it: true,
        ko: true,
        $: true
      }
    }
  });

  // Load in grunt-contrib (contains LESS)
  grunt.loadNpmTasks('grunt-contrib');

  // Default task.
  // grunt.registerTask('default', 'lint concat less test');
  grunt.registerTask('default', 'single watch');

  grunt.registerTask('single', 'js css');

  grunt.registerTask('js', 'lint concat');
  grunt.registerTask('css', 'less');
};<commit_msg>Updated and ran grunt<commit_after>module.exports = function(grunt) {

  // Project configuration.
  grunt.initConfig({
    pkg: '<json:package.json>',
    lint: {
      files: ['grunt.js', 'mvc/**/*.js', 'test/*_test.js']
    },
    concat: {
      // Public JS
      'public': {
        src: [
          // sugar
          'public/sugar.js',
          // jQuery, then Bootstrap
          'public/js/jquery.js', 'public/js/bootstrap.js',
          // then Knockout
          'public/js/knockout.js',
          // then GMaps
          'public/js/gmaps.js',
          // then other js libs
          'public/js/*.js'
        ],
        dest: 'dist/js/all.js'
      },
      'mvc': {
        src: [
          'models/mapperList.js',
          'models/*.js'
        ],
        dest: 'dist/models/all.js'
      }
    },
    less: {
      'public': {
        src: 'public/css/index.less',
        dest: 'dist/css/all.css'
      }
    },
    watch: {
      'js': {
        files: ['public/js/**', 'mvc/**/*.js'],
        tasks: 'js'
      },
      'css': {
        files: 'public/css/**',
        tasks: 'css'
      }
    },
    jshint: {
      options: {
        curly: true,
        eqeqeq: true,
        immed: true,
        newcap: true,
        noarg: true,
        sub: true,
        undef: true,
        boss: true,
        eqnull: true,
        node: true,

        // ugh, should get a proper set up for envs
        browser: true,

        // Ignore strict
        strict: false
      },
      globals: {
        exports: true,
        describe: true,
        it: true,
        ko: true,
        $: true
      }
    }
  });

  // Load in grunt-contrib (contains LESS)
  grunt.loadNpmTasks('grunt-contrib');

  // Default task.
  // grunt.registerTask('default', 'lint concat less test');
  grunt.registerTask('default', 'single watch');

  grunt.registerTask('single', 'js css');

  grunt.registerTask('js', 'lint concat');
  grunt.registerTask('css', 'less');
};<|endoftext|>


<commit_before>module.exports = function(grunt) {

  // Project configuration.
  grunt.initConfig({
    pkg: '<json:package.json>',
    meta: {
      banner: '/*! <%= pkg.name %> - v<%= pkg.version %> - ' +
        '<%= grunt.template.today("yyyy-mm-dd") %> */'
    },
    coffee: {
      app: {
        src: ['src/**/*.coffee'],
        dest: 'lib/',
        options: {
            bare: true,
            preserve_dirs: true,
            base_path: "src"
        }
      }
    },

    watch: {
        files: ['src/**/*'],
        tasks: 'coffee concat:dist shell:generate_documentation concat:docs'
    },

    concat: {
      dist: {
        src: ['<banner>',
              '<file_strip_banner:lib/bridges/native/NativeBridge.js>',
              '<file_strip_banner:lib/NativeObject.js>',
              '<file_strip_banner:lib/models/Device.js>',
              '<file_strip_banner:lib/models/App.js>',
              '<file_strip_banner:lib/models/Button.js>',
              '<file_strip_banner:lib/models/Layer.js>',
              '<file_strip_banner:lib/models/Tab.js>',
              '<file_strip_banner:lib/models/NavigationBar.js>',
              '<file_strip_banner:lib/Steroids.js>'],
        dest: 'dist/steroids.js',
        separator: ';'
      },
      docs: {
        src: ['docs/Steroids.html',
              'docs/App.html',
              'docs/Device.html',
              'docs/Button.html',
              'docs/NavigationBar.html',
              'docs/Layer.html',
              'docs/Tab.html',
              'docs/NativeObject.html',
              'docs//NativeBridge.html'],
        dest: 'docs/<%= pkg.name %>-<%= pkg.version %>.html',
        separator: '
'
      }
    },

    shell: {
        generate_documentation: {
            command: 'npm run-script gdocs'
        }
    }
  });

  // Load tasks from "grunt-sample" grunt plugin installed via Npm.
  grunt.loadTasks('grunt-sample');
  grunt.loadNpmTasks('grunt-shell');
  grunt.loadNpmTasks('grunt-coffee');

  // Default task.
  grunt.registerTask('default', 'coffee');

};<commit_msg>Default task and watch switched<commit_after>module.exports = function(grunt) {

  // Project configuration.
  grunt.initConfig({
    pkg: '<json:package.json>',
    meta: {
      banner: '/*! <%= pkg.name %> - v<%= pkg.version %> - ' +
        '<%= grunt.template.today("yyyy-mm-dd") %> */'
    },
    coffee: {
      app: {
        src: ['src/**/*.coffee'],
        dest: 'lib/',
        options: {
            bare: true,
            preserve_dirs: true,
            base_path: "src"
        }
      }
    },

    watch: {
        files: ['src/**/*'],
        tasks: 'default'
    },

    concat: {
      dist: {
        src: ['<banner>',
              '<file_strip_banner:lib/bridges/native/NativeBridge.js>',
              '<file_strip_banner:lib/NativeObject.js>',
              '<file_strip_banner:lib/models/Device.js>',
              '<file_strip_banner:lib/models/App.js>',
              '<file_strip_banner:lib/models/Button.js>',
              '<file_strip_banner:lib/models/Layer.js>',
              '<file_strip_banner:lib/models/Tab.js>',
              '<file_strip_banner:lib/models/NavigationBar.js>',
              '<file_strip_banner:lib/Steroids.js>'],
        dest: 'dist/steroids.js',
        separator: ';'
      },
      docs: {
        src: ['docs/Steroids.html',
              'docs/App.html',
              'docs/Device.html',
              'docs/Button.html',
              'docs/NavigationBar.html',
              'docs/Layer.html',
              'docs/Tab.html',
              'docs/NativeObject.html',
              'docs//NativeBridge.html'],
        dest: 'docs/<%= pkg.name %>-<%= pkg.version %>.html',
        separator: '
'
      }
    },

    shell: {
        generate_documentation: {
            command: 'npm run-script gdocs'
        }
    }
  });

  // Load tasks from "grunt-sample" grunt plugin installed via Npm.
  grunt.loadTasks('grunt-sample');
  grunt.loadNpmTasks('grunt-shell');
  grunt.loadNpmTasks('grunt-coffee');

  // Default task.
  grunt.registerTask('default', 'coffee concat:dist shell:generate_documentation concat:docs');

};<|endoftext|>


<commit_before>module.exports = function(grunt) {

  // Project configuration.
  grunt.initConfig({
    pkg: '<json:package.json>',
    meta: {
      banner: '/*! <%= pkg.name %> - v<%= pkg.version %> - ' +
        '<%= grunt.template.today("yyyy-mm-dd") %>\n' +
        '<%= pkg.homepage ? "* " + pkg.homepage + "\n" : "" %>' +
        '* Copyright (c) <%= grunt.template.today("yyyy") %> <%= pkg.author.name %>;'
      },
    concat: {
      dist: {
        src: ['<banner:meta.banner>', 'js/reveal.js'],
        dest: 'js/reveal.concat.js'
      }
    },
    min: {
      dist: {
        src: ['<banner:meta.banner>', '<config:concat.dist.dest>'],
        dest: 'js/reveal.min.js'
      }
    },
    lint: {
      files: ['grunt.js', 'lib/**/*.js']
    },
    jshint: {
      options: {
        curly: true,
        eqeqeq: true,
        immed: true,
        latedef: true,
        newcap: true,
        noarg: true,
        sub: true,
        undef: true,
        boss: true,
        eqnull: true
      },
      globals: {
        exports: true,
        module: false
      }
    },
    uglify: {}
  });

  // Default task.
  grunt.registerTask('default', 'lint test concat min');

};<commit_msg>update gruntfile<commit_after>module.exports = function(grunt) {

  // Project configuration.
  grunt.initConfig({
    pkg: '<json:package.json>',
    meta: {
      banner: '/*! <%= pkg.name %> - v<%= pkg.version %> */'
      },
    concat: {
      dist: {
        src: ['<banner:meta.banner>', 'js/reveal.js'],
        dest: 'js/reveal.concat.js'
      }
    },
    min: {
      dist: {
        src: ['<banner:meta.banner>', '<config:concat.dist.dest>'],
        dest: 'js/reveal.min.js'
      }
    },
    lint: {
      files: ['grunt.js', 'js/reveal.js']
    },
    jshint: {
      options: {
        curly: true,
        eqeqeq: true,
        immed: true,
        latedef: true,
        newcap: true,
        noarg: true,
        sub: true,
        undef: true,
        boss: true,
        eqnull: true
      },
      globals: {
        exports: true,
        module: false
      }
    },
    uglify: {}
  });
  // Build task.
  grunt.registerTask('build', 'concat min');

  // Default task.
  grunt.registerTask('default', 'lint test concat min');

};<|endoftext|>


<commit_before>module.exports = function(grunt) {
    grunt.initConfig({
        handlebars_embed: {
            'public/application.js': [ 'client/lib/templates/*.handlebars' ]
        },

        concat: {
            dist: {
                src: [
                    'components/jquery/jquery.js',
                    'components/sugar/release/1.3.7/sugar-1.3.7.min.js',
                    'components/handlebars/handlebars-1.0.0-rc.1.js',
                    'components/bootstrap/docs/assets/js/bootstrap.js',
                    'vendor/ember.js/dist/ember.js',
                    'vendor/data/dist/ember-data.js',
                    'public/application.js',
                    'client/lib/app.js',
                    'client/lib/models/**.js',
                    'client/lib/router.js',
                    'client/lib/controllers/**.js',
                    'client/lib/views/**.js',
                ],
                dest: 'public/application.js'
            },
//             css: {
//                 src: [
//                     'components/bootstrap/docs/assets/css/bootstrap.css'
//                 ],
//                 dest: 'public/assets.css'
//             },
        },

        copy: {
            dist: {
                files: {
                    'public/': [ 'client/static/**' ]
                }
            },

            bootstrap: {
                files: {
                    'public/': [ 'components/bootstrap/docs/assets/css/bootstrap.css' ]
                }
            },

            images: {
                files: {
                    'public/img/': [ 'components/bootstrap/img/*' ]
                }
            }
        },

        watch: {
            scripts: {
                files: [ 'client/**', '<config:concat.dist.src>', 'resources/**js' ],
                tasks: 'handlebars_embed concat server'
            }
        }
    });

    grunt.registerTask('server', 'start server', function() {
        require('./app');
    });

//     grunt.loadNpmTasks('grunt-bowerful');
    grunt.loadNpmTasks('grunt-contrib-copy');
    grunt.loadNpmTasks('grunt-emberify');
    grunt.registerTask('default', 'handlebars_embed concat copy');
    grunt.registerTask('dev', 'handlebars_embed concat copy server watch');
};
<commit_msg>proper copy on watch<commit_after>module.exports = function(grunt) {
    grunt.initConfig({
        handlebars_embed: {
            'public/application.js': [ 'client/lib/templates/*.handlebars' ]
        },

        concat: {
            dist: {
                src: [
                    'components/jquery/jquery.js',
                    'components/sugar/release/1.3.7/sugar-1.3.7.min.js',
                    'components/handlebars/handlebars-1.0.0-rc.1.js',
                    'components/bootstrap/docs/assets/js/bootstrap.js',
                    'vendor/ember.js/dist/ember.js',
                    'vendor/data/dist/ember-data.js',
                    'public/application.js',
                    'client/lib/app.js',
                    'client/lib/models/**.js',
                    'client/lib/router.js',
                    'client/lib/controllers/**.js',
                    'client/lib/views/**.js',
                ],
                dest: 'public/application.js'
            },
//             css: {
//                 src: [
//                     'components/bootstrap/docs/assets/css/bootstrap.css'
//                 ],
//                 dest: 'public/assets.css'
//             },
        },

        copy: {
            dist: {
                files: {
                    'public/': [ 'client/static/**' ]
                }
            },

            bootstrap: {
                files: {
                    'public/': [ 'components/bootstrap/docs/assets/css/bootstrap.css' ]
                }
            },

            images: {
                files: {
                    'public/img/': [ 'components/bootstrap/img/*' ]
                }
            }
        },

        watch: {
            scripts: {
                files: [ 'client/**', '<config:concat.dist.src>', 'resources/**js' ],
                tasks: 'handlebars_embed concat copy server'
            }
        }
    });

    grunt.registerTask('server', 'start server', function() {
        require('./app');
    });

//     grunt.loadNpmTasks('grunt-bowerful');
    grunt.loadNpmTasks('grunt-contrib-copy');
    grunt.loadNpmTasks('grunt-emberify');
    grunt.registerTask('default', 'handlebars_embed concat copy');
    grunt.registerTask('dev', 'handlebars_embed concat copy server watch');
};
<|endoftext|>


<commit_before>module.exports = function(grunt) {

  grunt.loadTasks('./grunt/tasks');

  grunt.loadNpmTasks('grunt-image-embed');
  grunt.loadNpmTasks('grunt-contrib-mincss');

  grunt.registerTask('build:deploy', 'shell:compileDeploy concat:deploy min');
  grunt.registerTask('build:dev', 'shell:compileDev concat:css imageEmbed mincss css2js concat:dev');
//  grunt.registerTask('default', 'build:deploy build:dev');
  grunt.registerTask('default', 'amberc:all');

  grunt.initConfig({
    pkg: '<json:package.json>',

    meta: {
      banner: '/*!\n <%= pkg.title || pkg.name %> - v<%= pkg.version %> - <%= grunt.template.today("yyyy-mm-dd") %> \n License: <%= pkg.license.type %> \n*/\n'
    },

    pegjs: {
      amber_parser: {
        src: 'js/parser.pegjs',
        dest: 'js/parser.js',
        trackLineAndColumn: true,
        cache: false,
        export_var: 'smalltalk.parser'
      }
    },

    amberc: {
      _config: {
        amber_dir: process.cwd(),
        closure_jar: ''
      },
      all: {
        working_dir: 'st',
        target_dir : 'js',
        src: ['Kernel-Objects.st', 'Kernel-Classes.st', 'Kernel-Methods.st', 'Kernel-Collections.st',
              'Kernel-Exceptions.st', 'Kernel-Transcript.st', 'Kernel-Announcements.st',
              'Importer-Exporter.st', 'Compiler-Exceptions.st', 'Compiler-Core.st', 'Compiler-AST.st',
              'Compiler-IR.st', 'Compiler-Inlining.st', 'Compiler-Semantic.st',
              'Canvas.st', 'SUnit.st', 'IDE.st',
              'Kernel-Tests.st', 'Compiler-Tests.st',
              ],
        deploy: true
      },
      amber_kernel: {
        working_dir: 'st',
        target_dir : 'js',
        src: ['Kernel-Objects.st', 'Kernel-Classes.st', 'Kernel-Methods.st', 'Kernel-Collections.st',
              'Kernel-Exceptions.st', 'Kernel-Transcript.st', 'Kernel-Announcements.st'],
        deploy: true
      },
      amber_compiler: {
        working_dir: 'st',
        target_dir : 'js',
        src: ['Importer-Exporter.st', 'Compiler-Exceptions.st', 'Compiler-Core.st', 'Compiler-AST.st',
              'Compiler-IR.st', 'Compiler-Inlining.st', 'Compiler-Semantic.st'],
        output_name: 'Compiler',
        deploy: true
      },
      amber_canvas: {
        working_dir: 'st',
        target_dir : 'js',
        src: ['Canvas.st', 'SUnit.st'],
        deploy: true
      },
      amber_IDE: {
        working_dir: 'st',
        target_dir : 'js',
        src: ['IDE.st'],
        libraries: ['Canvas'],
        deploy: true
      },
      amber_tests: {
        working_dir: 'st',
        target_dir : 'js',
        src: ['Kernel-Tests.st', 'Compiler-Tests.st'],
        libraries: ['SUnit']
      },
      amber_dev: {
        working_dir: 'js',
        src: [
              'Compiler-Exceptions.js', 'Compiler-Core.js', 'Compiler-AST.js',
              'Compiler-IR.js', 'Compiler-Inlining.js', 'Compiler-Semantic.js',
              'Kernel-Tests.js', 'Compiler-Tests.js',
              'Canvas.js', 'IDE.js', 'SUnit.js'],
        output_name: 'amber_dev'
      },
      server: {
        working_dir: 'server',
        src: ['FileServer.st'],
        main_class: 'FileServer',
        output_name: 'server'
      },
      repl: {
        working_dir: 'repl',
        src: ['REPL.st'],
        main_class: 'Repl',
        output_name: 'amber'
      }
    },

    lint: {
      amber: ['js/*.js'],
      server: ['server/*.js'],
      repl: ['repl/*.js'],
      tests: ['test/*.js'],
      grunt: ['grunt.js', 'grunt/**/*.js']
    },

    concat: {
      deploy: {
        src: ['tmp/amber-compiled.deploy.js'],
        dest: 'dist/amber-<%= pkg.version %>.deploy.js'
      },

      css: {
        src: [
          'css/amber.css',
          'js/lib/CodeMirror/codemirror.css',
          'js/lib/CodeMirror/amber.css'
        ],
        dest: 'tmp/amber.css'
      },

      dev: {
        src: [
          'js/lib/jQuery/jquery-ui-1.8.16.custom.min.js',
          'js/lib/jQuery/jquery.textarea.js',
          'js/lib/CodeMirror/codemirror.js',
          'js/lib/CodeMirror/smalltalk.js',
          'tmp/amber-compiled.js',
          'tmp/css.js'
        ],
        dest: 'dist/amber-<%= pkg.version %>.js'
      }
    },

    imageEmbed: {
      dev: {
        src: ['tmp/amber.css'],
        dest: 'tmp/amber-images.css',
        options: {baseDir: 'public'}
      }
    },

    mincss: {
      dev: {
        src: ['tmp/amber-images.css'],
        dest: 'tmp/amber.min.css'
      }
    },

    css2js: {
      dev: {
        src: 'tmp/amber.min.css',
        dest: 'tmp/css.js'
      }
    },

    min: {
      deploy: {
        src: 'dist/amber-<%= pkg.version %>.deploy.js',
        dest: 'dist/amber-<%= pkg.version %>.deploy.min.js'
      }
    }
  });

  grunt.registerMultiTask('css2js', 'Embed CSS into JS', function() {
    var cssContent = grunt.task.directive(grunt.file.expandFiles(this.data.src)[0], grunt.file.read);
    var content =
      'var css="' + cssContent + '";' +
      'var cssTag = document.createElement("link");' +
      'document.head = document.head || document.getElementsByTagName("head")[0];' +
      'cssTag.href = "data:text/css,"+css;' +
      'cssTag.rel = "stylesheet";' +
      'document.head.appendChild(cssTag);';

    grunt.file.write(this.data.dest, content);

    grunt.log.writeln('File "' + this.data.dest + '" created.');
  });

  grunt.registerMultiTask('pegjs', 'Generate JavaScript parser from PEG.js description', function() {
    var PEG = require('pegjs');
    var pegOptions = {
      cache: this.data.cache || false,
      trackLineAndColumn: this.data.trackLineAndColumn || false
    };
    var export_var = this.data.export_var || 'module.exports';
    var parser = PEG.buildParser(grunt.file.read(this.data.src), pegOptions);
    var content = export_var + ' = ' + parser.toSource() + ';\n';
    grunt.file.write(this.data.dest, content);
  });
};
<commit_msg>grunt: reorder unittests to come last in amber_dev target<commit_after>module.exports = function(grunt) {

  grunt.loadTasks('./grunt/tasks');

  grunt.loadNpmTasks('grunt-image-embed');
  grunt.loadNpmTasks('grunt-contrib-mincss');

  grunt.registerTask('build:deploy', 'shell:compileDeploy concat:deploy min');
  grunt.registerTask('build:dev', 'shell:compileDev concat:css imageEmbed mincss css2js concat:dev');
//  grunt.registerTask('default', 'build:deploy build:dev');
  grunt.registerTask('default', 'amberc:all');

  grunt.initConfig({
    pkg: '<json:package.json>',

    meta: {
      banner: '/*!\n <%= pkg.title || pkg.name %> - v<%= pkg.version %> - <%= grunt.template.today("yyyy-mm-dd") %> \n License: <%= pkg.license.type %> \n*/\n'
    },

    pegjs: {
      amber_parser: {
        src: 'js/parser.pegjs',
        dest: 'js/parser.js',
        trackLineAndColumn: true,
        cache: false,
        export_var: 'smalltalk.parser'
      }
    },

    amberc: {
      _config: {
        amber_dir: process.cwd(),
        closure_jar: ''
      },
      all: {
        working_dir: 'st',
        target_dir : 'js',
        src: ['Kernel-Objects.st', 'Kernel-Classes.st', 'Kernel-Methods.st', 'Kernel-Collections.st',
              'Kernel-Exceptions.st', 'Kernel-Transcript.st', 'Kernel-Announcements.st',
              'Importer-Exporter.st', 'Compiler-Exceptions.st', 'Compiler-Core.st', 'Compiler-AST.st',
              'Compiler-IR.st', 'Compiler-Inlining.st', 'Compiler-Semantic.st',
              'Canvas.st', 'SUnit.st', 'IDE.st',
              'Kernel-Tests.st', 'Compiler-Tests.st',
              ],
        deploy: true
      },
      amber_kernel: {
        working_dir: 'st',
        target_dir : 'js',
        src: ['Kernel-Objects.st', 'Kernel-Classes.st', 'Kernel-Methods.st', 'Kernel-Collections.st',
              'Kernel-Exceptions.st', 'Kernel-Transcript.st', 'Kernel-Announcements.st'],
        deploy: true
      },
      amber_compiler: {
        working_dir: 'st',
        target_dir : 'js',
        src: ['Importer-Exporter.st', 'Compiler-Exceptions.st', 'Compiler-Core.st', 'Compiler-AST.st',
              'Compiler-IR.st', 'Compiler-Inlining.st', 'Compiler-Semantic.st'],
        output_name: 'Compiler',
        deploy: true
      },
      amber_canvas: {
        working_dir: 'st',
        target_dir : 'js',
        src: ['Canvas.st', 'SUnit.st'],
        deploy: true
      },
      amber_IDE: {
        working_dir: 'st',
        target_dir : 'js',
        src: ['IDE.st'],
        libraries: ['Canvas'],
        deploy: true
      },
      amber_tests: {
        working_dir: 'st',
        target_dir : 'js',
        src: ['Kernel-Tests.st', 'Compiler-Tests.st'],
        libraries: ['SUnit']
      },
      amber_dev: {
        working_dir: 'js',
        src: [
              'Compiler-Exceptions.js', 'Compiler-Core.js', 'Compiler-AST.js',
              'Compiler-IR.js', 'Compiler-Inlining.js', 'Compiler-Semantic.js',
              'Canvas.js', 'IDE.js', 'SUnit.js',
              'Kernel-Tests.js', 'Compiler-Tests.js', 'SUnit-Tests.js'],
        output_name: 'amber_dev'
      },
      server: {
        working_dir: 'server',
        src: ['FileServer.st'],
        main_class: 'FileServer',
        output_name: 'server'
      },
      repl: {
        working_dir: 'repl',
        src: ['REPL.st'],
        main_class: 'Repl',
        output_name: 'amber'
      }
    },

    lint: {
      amber: ['js/*.js'],
      server: ['server/*.js'],
      repl: ['repl/*.js'],
      tests: ['test/*.js'],
      grunt: ['grunt.js', 'grunt/**/*.js']
    },

    concat: {
      deploy: {
        src: ['tmp/amber-compiled.deploy.js'],
        dest: 'dist/amber-<%= pkg.version %>.deploy.js'
      },

      css: {
        src: [
          'css/amber.css',
          'js/lib/CodeMirror/codemirror.css',
          'js/lib/CodeMirror/amber.css'
        ],
        dest: 'tmp/amber.css'
      },

      dev: {
        src: [
          'js/lib/jQuery/jquery-ui-1.8.16.custom.min.js',
          'js/lib/jQuery/jquery.textarea.js',
          'js/lib/CodeMirror/codemirror.js',
          'js/lib/CodeMirror/smalltalk.js',
          'tmp/amber-compiled.js',
          'tmp/css.js'
        ],
        dest: 'dist/amber-<%= pkg.version %>.js'
      }
    },

    imageEmbed: {
      dev: {
        src: ['tmp/amber.css'],
        dest: 'tmp/amber-images.css',
        options: {baseDir: 'public'}
      }
    },

    mincss: {
      dev: {
        src: ['tmp/amber-images.css'],
        dest: 'tmp/amber.min.css'
      }
    },

    css2js: {
      dev: {
        src: 'tmp/amber.min.css',
        dest: 'tmp/css.js'
      }
    },

    min: {
      deploy: {
        src: 'dist/amber-<%= pkg.version %>.deploy.js',
        dest: 'dist/amber-<%= pkg.version %>.deploy.min.js'
      }
    }
  });

  grunt.registerMultiTask('css2js', 'Embed CSS into JS', function() {
    var cssContent = grunt.task.directive(grunt.file.expandFiles(this.data.src)[0], grunt.file.read);
    var content =
      'var css="' + cssContent + '";' +
      'var cssTag = document.createElement("link");' +
      'document.head = document.head || document.getElementsByTagName("head")[0];' +
      'cssTag.href = "data:text/css,"+css;' +
      'cssTag.rel = "stylesheet";' +
      'document.head.appendChild(cssTag);';

    grunt.file.write(this.data.dest, content);

    grunt.log.writeln('File "' + this.data.dest + '" created.');
  });

  grunt.registerMultiTask('pegjs', 'Generate JavaScript parser from PEG.js description', function() {
    var PEG = require('pegjs');
    var pegOptions = {
      cache: this.data.cache || false,
      trackLineAndColumn: this.data.trackLineAndColumn || false
    };
    var export_var = this.data.export_var || 'module.exports';
    var parser = PEG.buildParser(grunt.file.read(this.data.src), pegOptions);
    var content = export_var + ' = ' + parser.toSource() + ';\n';
    grunt.file.write(this.data.dest, content);
  });
};
<|endoftext|>


<commit_before>/*global module:false*/
module.exports = function(grunt) {

  // Project configuration.
  grunt.loadNpmTasks('grunt-contrib-less');
  grunt.loadNpmTasks('grunt-exec');
  grunt.initConfig({
    meta: {
      version: '0.1.0',
      banner: '/*! PROJECT_NAME - v<%= meta.version %> - ' +
        '<%= grunt.template.today("yyyy-mm-dd") %>\n' +
        '* http://PROJECT_WEBSITE/\n' +
        '* Copyright (c) <%= grunt.template.today("yyyy") %> ' +
        'YOUR_NAME; Licensed MIT */'
    },
    lint: {
      files: ['grunt.js', 'js/*.js']
    },
    qunit: {
      files: ['tests/**/*.html']
    },
    less: {
      development: {
        options: {
          paths: ["css"]
        },
        files: {
          "css/bootstrap-timepicker.css": "less/*.less"
        }
      },
      production: {
        options: {
          paths: ["css"],
          yuicompress: true
        },
        files: {
          "css/bootstrap-timepicker.min.css": "less/*.less"
        }
      }
    },
    min: {
      dist: {
        src: ['js/bootstrap-timepicker.js'],
        dest: 'js/bootstrap-timepicker.min.js'
      }
    },
    watch: {
      files: 'js/bootstrap-timepicker.js',
      tasks: 'lint qunit'
    },
    jshint: {
      options: {
        curly: true,
        eqeqeq: true,
        immed: true,
        latedef: true,
        newcap: true,
        noarg: true,
        sub: true,
        undef: true,
        boss: true,
        eqnull: true,
        browser: true
      },
      globals: {
        jQuery: true
      }
    },
    uglify: {},
    exec: {
      checkout_ghPages: {
        command: 'git checkout gh-pages -q'
      },
      copy_css: {
        command: 'git checkout master css/bootstrap-timepicker.min.css'
      },
      copy_js: {
        command: 'git checkout master js/bootstrap-timepicker.min.js'
      },
      notify: {
        command: 'echo "on branch gh-pages"'
      }
    }
  });

  // Default task.
  grunt.registerTask('default', 'min');

};

<commit_msg>Add jasmine unit testing<commit_after>/*global module:false*/
module.exports = function(grunt) {
  'use strict';

  // Project configuration.
  grunt.loadNpmTasks('grunt-contrib-less');
  grunt.loadNpmTasks('grunt-jasmine-runner');
  grunt.loadNpmTasks('grunt-exec');

  grunt.initConfig({
    meta: {
      version: '0.1.0',
      banner: '/*! PROJECT_NAME - v<%= meta.version %> - ' +
        '<%= grunt.template.today("yyyy-mm-dd") %>\n' +
        '* http://PROJECT_WEBSITE/\n' +
        '* Copyright (c) <%= grunt.template.today("yyyy") %> ' +
        'YOUR_NAME; Licensed MIT */'
    },
    lint: {
      files: ['js/bootstrap-timepicker.js', 'grunt.js']
    },
    qunit: {
      files: ['tests/**/*.html']
    },
    less: {
      development: {
        options: {
          paths: ['css']
        },
        files: {
          'css/bootstrap-timepicker.css': 'less/*.less'
        }
      },
      production: {
        options: {
          paths: ['css'],
          yuicompress: true
        },
        files: {
          'css/bootstrap-timepicker.min.css': 'less/*.less'
        }
      }
    },
    min: {
      dist: {
        src: ['js/bootstrap-timepicker.js'],
        dest: 'js/bootstrap-timepicker.min.js'
      }
    },
    jshint: {
      options: {
        browser: true,
        camelcase: true,
        curly: true,
        eqeqeq: true,
        eqnull: true,
        immed: true,
        latedef: true,
        newcap: true,
        noarg: true,
        quotmark: 'single',
        sub: true,
        strict: true,
        trailing: true,
        undef: true,
        unused: true
      },
      globals: {
        jQuery: true
      }
    },
    uglify: {},
    watch: {
      scripts: {
        files: ['spec/js/*Spec.js', 'js/bootstrap-timepicker.js'],
        tasks: 'jasmine',
        options: {
          interrupt: true
        }
      }
    },
    jasmine: {
      src : ['spec/js/libs/*.js', 'js/bootstrap-timepicker.js'],
      specs : 'spec/js/*Spec.js',
      helpers : 'spec/js/helpers/*.js',
      timeout : 100,
      junit : {
        output : 'junit/'
      },
      phantomjs : {
        'ignore-ssl-errors' : true
      }
    },
    exec: {
      checkoutGhPages: {
        command: 'git checkout gh-pages -q'
      },
      copyCss: {
        command: 'git checkout master css/bootstrap-timepicker.min.css'
      },
      copyJs: {
        command: 'git checkout master js/bootstrap-timepicker.min.js'
      },
      notify: {
        command: 'echo "on branch gh-pages"'
      }
    }
  });

  // Default task.
  grunt.registerTask('default', 'min');

};
<|endoftext|>


<commit_before>/*global module:false*/
module.exports = function (grunt) {

  // Project configuration.
  grunt.initConfig({
    pkg: '<json:aol.livebloglite.jquery.json>',
    meta: {
      banner: '/*! <%= pkg.title || pkg.name %> - v<%= pkg.version %> - ' +
        '<%= grunt.template.today("yyyy-mm-dd") %>\n' +
        '<%= pkg.homepage ? "* " + pkg.homepage + "\n" : "" %>' +
        '* Copyright (c) <%= grunt.template.today("yyyy") %> <%= pkg.author.name %>;' +
        ' Licensed <%= _.pluck(pkg.licenses, "type").join(", ") %> */'
    },
    concat: {
      dist: {
        src: ['libs/jquery/jquery-ui*.js', 'src/**/*.js'],
        dest: 'dist/<%= pkg.name %>.js'
      }
    },
    min: {
      bundle: {
        src: ['<banner:meta.banner>', '<config:concat.dist.dest>'],
        dest: 'dist/<%= pkg.name %>.min.js'
      },
      api: {
        src: ['src/liveblogliteapi.js'],
        dest: 'dist/jquery.aol.liveblogliteapi.min.js'
      },
      ui: {
        src: ['src/liveblogliteui.js'],
        dest: 'dist/jquery.aol.liveblogui.min.js'
      }
    },
    qunit: {
      files: ['test/**/*.html']
    },
    lint: {
      files: ['grunt.js', 'src/**/*.js', 'test/**/*.js']
    },
    compass: {
      dev: {
        src: 'assets/scss',
        dest: 'assets/dev/css',
        linecomments: true,
        forcecompile: true,
        debugsass: true,
        relativeassets: true,
        images: 'assets/resources/images',
        require: 'animation'
      },
      prod: {
        src: 'assets/scss',
        dest: 'assets/prod/css',
        outputstyle: 'compressed',
        linecomments: false,
        forcecompile: true,
        debugsass: false,
        relativeassets: true,
        images: 'assets/resources/images',
        require: 'animation'
      }
    },
    watch: {
      files: '<config:lint.files>',
      tasks: 'default'
    },
    //watch: {
      //files: '<config:lint.files>',
      //tasks: 'lint qunit',
      //compass: {
        //files: ['assets/scss/*.scss'],
        //tasks: ['compass:dev', 'compass:prod']
      //}
    //},
    jshint: {
      // Specifying a jshint file will be possible in Grunt soon
      options: {
        "curly": true,
        "eqeqeq": true,
        "immed": true,
        "latedef": true,
        "newcap": true,
        "noarg": true,
        "sub": true,
        "undef": true,
        "boss": true,
        "eqnull": true,
        "browser": true,
        "white": true,
        "devel": true,
        "indent": 2,
        "jquery": true,
        "predef": "twttr"
      },
      globals: {
        jQuery: true,
        twttr: true
      }
    },
    uglify: {}
  });

  grunt.loadNpmTasks('grunt-compass');

  // Default task.
  grunt.registerTask('default', 'lint qunit concat min compass:dev compass:prod');

};
<commit_msg>added watch-serve command to grunt<commit_after>/*global module:false*/
module.exports = function (grunt) {

  // Project configuration.
  grunt.initConfig({
    server: {
      port: 8000,
      base: '.'
    },
    pkg: '<json:aol.livebloglite.jquery.json>',
    meta: {
      banner: '/*! <%= pkg.title || pkg.name %> - v<%= pkg.version %> - ' +
        '<%= grunt.template.today("yyyy-mm-dd") %>\n' +
        '<%= pkg.homepage ? "* " + pkg.homepage + "\n" : "" %>' +
        '* Copyright (c) <%= grunt.template.today("yyyy") %> <%= pkg.author.name %>;' +
        ' Licensed <%= _.pluck(pkg.licenses, "type").join(", ") %> */'
    },
    concat: {
      dist: {
        src: ['libs/jquery/jquery-ui*.js', 'src/**/*.js'],
        dest: 'dist/<%= pkg.name %>.js'
      }
    },
    min: {
      bundle: {
        src: ['<banner:meta.banner>', '<config:concat.dist.dest>'],
        dest: 'dist/<%= pkg.name %>.min.js'
      },
      api: {
        src: ['src/liveblogliteapi.js'],
        dest: 'dist/jquery.aol.liveblogliteapi.min.js'
      },
      ui: {
        src: ['src/liveblogliteui.js'],
        dest: 'dist/jquery.aol.liveblogui.min.js'
      }
    },
    qunit: {
      files: ['test/**/*.html']
    },
    lint: {
      files: ['grunt.js', 'src/**/*.js', 'test/**/*.js']
    },
    compass: {
      dev: {
        src: 'assets/scss',
        dest: 'assets/dev/css',
        linecomments: true,
        forcecompile: true,
        debugsass: true,
        relativeassets: true,
        images: 'assets/resources/images',
        require: 'animation'
      },
      prod: {
        src: 'assets/scss',
        dest: 'assets/prod/css',
        outputstyle: 'compressed',
        linecomments: false,
        forcecompile: true,
        debugsass: false,
        relativeassets: true,
        images: 'assets/resources/images',
        require: 'animation'
      }
    },
    watch: {
      files: '<config:lint.files>',
      tasks: 'default'
    },
    //watch: {
      //files: '<config:lint.files>',
      //tasks: 'lint qunit',
      //compass: {
        //files: ['assets/scss/*.scss'],
        //tasks: ['compass:dev', 'compass:prod']
      //}
    //},
    jshint: {
      // Specifying a jshint file will be possible in Grunt soon
      options: {
        "curly": true,
        "eqeqeq": true,
        "immed": true,
        "latedef": true,
        "newcap": true,
        "noarg": true,
        "sub": true,
        "undef": true,
        "boss": true,
        "eqnull": true,
        "browser": true,
        "white": true,
        "devel": true,
        "indent": 2,
        "jquery": true,
        "predef": "twttr"
      },
      globals: {
        jQuery: true,
        twttr: true
      }
    },
    uglify: {}
  });

  grunt.loadNpmTasks('grunt-compass');

  // Default task.
  grunt.registerTask('default', 'lint qunit concat min compass:dev compass:prod');

  grunt.registerTask("watch-serve", "server watch");

};
<|endoftext|>


<commit_before>module.exports = function(grunt) {
	var _browsers = [
		{
			browserName: 'firefox'
		},
		{
			browserName: 'googlechrome',
			platform: 'linux'
		},
		{
			browserName: 'firefox',
			platform: 'Windows 2003',
			version: '12'
		},
		{
			browserName: 'firefox',
			platform: 'Windows 2003',
			version: '13'
		},
		{
			browserName: 'firefox',
			platform: 'Windows 2003',
			version: '14'
		},
		{
			browserName: 'firefox',
			platform: 'Windows 2003',
			version: '15'
		},
		{
			browserName: 'internet explorer',
			platform: 'Windows 2012',
			version: '10'
		},
		{
			browserName: 'opera',
			version: '11'
		},
		{
			browserName: 'opera',
			version: '12'
		}
	];

	grunt.initConfig({
		lint: {
			files: ['grunt.js', 'tasks/**/*.js']
		},
    server: {
      base: 'test',
      port: 9999
    },
    'saucelabs-qunit': {
        all: {
            urls: ['http://127.0.0.1:9999/qunit/lists-plugin.html', 'http://127.0.0.1:9999/qunit/twitter-plugin.html'],
            tunnelTimeout: 5,
            testname: 'Sauce Labs Grunt Task with QUnit',
            build: process.env.TRAVIS_JOB_ID,
            concurrency: 3,
            browsers: _browsers,
            onTestComplete: function(){
                // Called after a qunit unit is done, per page, per browser
                // Return true or false, passes or fails the test
                // Returning undefined does not alter the test result

                // For async return, call
                var done = this.async();
                setTimeout(function(){
                    // Return to this test after 1000 milliseconds
                    done(/*true or false changes the test result, undefined does not alter the result*/);
                }, 1000);
            }
        }
    }
	});
	grunt.loadTasks('tasks');
	grunt.registerTask('test', 'server saucelabs-qunit');
	grunt.registerTask('default', 'lint test');
};
<commit_msg>Added basic Jasmine test suite.<commit_after>module.exports = function(grunt) {
	var _browsers = [
		{
			browserName: 'firefox'
		},
		{
			browserName: 'googlechrome',
			platform: 'linux'
		},
		{
			browserName: 'firefox',
			platform: 'Windows 2003',
			version: '12'
		},
		{
			browserName: 'firefox',
			platform: 'Windows 2003',
			version: '13'
		},
		{
			browserName: 'firefox',
			platform: 'Windows 2003',
			version: '14'
		},
		{
			browserName: 'firefox',
			platform: 'Windows 2003',
			version: '15'
		},
		{
			browserName: 'internet explorer',
			platform: 'Windows 2012',
			version: '10'
		},
		{
			browserName: 'opera',
			version: '11'
		},
		{
			browserName: 'opera',
			version: '12'
		}
	];

	grunt.initConfig({
		lint: {
			files: ['grunt.js', 'tasks/**/*.js']
		},
    server: {
      base: 'test',
      port: 9999
    },
    'saucelabs-qunit': {
        all: {
            urls: ['http://127.0.0.1:9999/qunit/lists-plugin.html', 'http://127.0.0.1:9999/qunit/twitter-plugin.html'],
            tunnelTimeout: 5,
            testname: 'Sauce Labs Grunt Task with QUnit',
            build: process.env.TRAVIS_JOB_ID,
            concurrency: 3,
            browsers: _browsers,
            onTestComplete: function(){
                // Called after a qunit unit is done, per page, per browser
                // Return true or false, passes or fails the test
                // Returning undefined does not alter the test result

                // For async return, call
                var done = this.async();
                setTimeout(function(){
                    // Return to this test after 1000 milliseconds
                    done(/*true or false changes the test result, undefined does not alter the result*/);
                }, 1000);
            }
        }
    },
    'saucelabs-jasmine': {
        all: {
            urls: ['http://127.0.0.1:9999/jasmine/SpecRunner.html', 'http://127.0.0.1:9999/jasmine/SpecRunnerDos.html'],
            tunnelTimeout: 5,
            testname: 'Sauce Labs Grunt Task with Jasmine',
            build: process.env.TRAVIS_JOB_ID,
            concurrency: 3,
            browsers: _browsers,
            onTestComplete: function(){
                // Called after a jasmine unit is done, per page, per browser
                // Return true or false, passes or fails the test
                // Returning undefined does not alter the test result

                // For async return, call
                var done = this.async();
                setTimeout(function(){
                    // Return to this test after 1000 milliseconds
                    done(/*true or false changes the test result, undefined does not alter the result*/);
                }, 1000);
            }
        }
    }
	});
	grunt.loadTasks('tasks');
	grunt.registerTask('test', 'server saucelabs-qunit saucelabs-jasmine');
	grunt.registerTask('default', 'lint test');
};
<|endoftext|>


<commit_before>/*!
Copyright 2012 Adobe Systems Inc.;
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

/*global module:false*/

var bower = {
    name: 'topcoat',
    version: '0.1.0',
    main: []
},
    component = {
        repo: 'adobe/topcoat',
        description: 'An experimental CSS library.',
        styles: ['release/css/topcoat-min.css'],
        files: []
    },
    _ = require('underscore'),
    fs = require('fs'),
    path = require('path'),
    base = path.join(__dirname, 'release')

    module.exports = function(grunt) {

        grunt.loadNpmTasks('grunt-contrib-stylus')
        grunt.loadNpmTasks('grunt-contrib-mincss')
        grunt.loadNpmTasks('grunt-contrib-copy')

        grunt.initConfig({
            stylus: {
                compile: {
                    options: {
                        // paths: ['path/to/import', 'another/to/import'],
                        // urlfunc: 'embedurl',
                        // use embedurl('test.png') in our code to trigger Data URI embedding
                        // use: [
                            // require('nib')
                        // ]
                    },
                    files: {
                        'release/css/topcoat.css': 'src/style/topcoat.styl'
                    }
                }
            },

            copy: {
                dist: {
                    files: {
                        'release/font/': 'src/font/**',
                        'release/img/': 'src/img/**'
                    }
                }
            },

            mincss: {
                css: {
                    src: 'release/css/topcoat.css',
                    dest: 'release/css/topcoat-min.css'
                }
            },

            watch: {
                files: ['src/less/topcoat.less'],
                tasks: ['less', 'mincss']
            }
        });

        /* the manifest for component.json is used by Bower */
        grunt.registerTask('manifest', 'Generates component.json file.', function() {
            fs.readdirSync(base).forEach(function(dir) {
                var srcDir = path.join(base, dir)
                fs.readdirSync(srcDir).forEach(function(srcFile) {
                    var srcFilePath = path.join('release', dir, srcFile)
                    // I do not understand why Bower requires a manifest if it relies on git solely. But whatever.
                    bower.main.push(srcFilePath)
                    // now adding fonts and images for Component
                    if(dir != 'css') component.files.push(srcFilePath)
                })
            })
            var c = JSON.stringify(_.extend(bower, component), null, 4)
            fs.writeFileSync(path.join(__dirname, 'component.json'), c, 'utf8')
        })

        // fin
        grunt.registerTask('default', 'stylus copy mincss manifest')
    }<commit_msg>fixed grunt watch to use the stylus task<commit_after>/*!
Copyright 2012 Adobe Systems Inc.;
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

/*global module:false*/

var bower = {
    name: 'topcoat',
    version: '0.1.0',
    main: []
},
    component = {
        repo: 'adobe/topcoat',
        description: 'An experimental CSS library.',
        styles: ['release/css/topcoat-min.css'],
        files: []
    },
    _ = require('underscore'),
    fs = require('fs'),
    path = require('path'),
    base = path.join(__dirname, 'release')

    module.exports = function(grunt) {

        grunt.loadNpmTasks('grunt-contrib-stylus')
        grunt.loadNpmTasks('grunt-contrib-mincss')
        grunt.loadNpmTasks('grunt-contrib-copy')

        grunt.initConfig({
            stylus: {
                compile: {
                    options: {
                        // paths: ['path/to/import', 'another/to/import'],
                        // urlfunc: 'embedurl',
                        // use embedurl('test.png') in our code to trigger Data URI embedding
                        // use: [
                            // require('nib')
                        // ]
                    },
                    files: {
                        'release/css/topcoat.css': 'src/style/topcoat.styl'
                    }
                }
            },

            copy: {
                dist: {
                    files: {
                        'release/font/': 'src/font/**',
                        'release/img/': 'src/img/**'
                    }
                }
            },

            mincss: {
                css: {
                    src: 'release/css/topcoat.css',
                    dest: 'release/css/topcoat-min.css'
                }
            },

            watch: {
                files: ['src/style/*.styl'],
                tasks: ['stylus', 'mincss']
            }
        });

        /* the manifest for component.json is used by Bower */
        grunt.registerTask('manifest', 'Generates component.json file.', function() {
            fs.readdirSync(base).forEach(function(dir) {
                var srcDir = path.join(base, dir)
                fs.readdirSync(srcDir).forEach(function(srcFile) {
                    var srcFilePath = path.join('release', dir, srcFile)
                    // I do not understand why Bower requires a manifest if it relies on git solely. But whatever.
                    bower.main.push(srcFilePath)
                    // now adding fonts and images for Component
                    if(dir != 'css') component.files.push(srcFilePath)
                })
            })
            var c = JSON.stringify(_.extend(bower, component), null, 4)
            fs.writeFileSync(path.join(__dirname, 'component.json'), c, 'utf8')
        })

        // fin
        grunt.registerTask('default', 'stylus copy mincss manifest')
    }<|endoftext|>