<commit_before>//var turn = 0, //turn based
var COLUMN_FULL = -2;
var EMPTY = -1;
var YELLOW = 0;
var RED = 1;

var gMyColor = EMPTY;
var gBoard = [];
var gCurrent = null;

function initGame() {
	Crafty.init(600, 500);
	Crafty.canvas();

	Crafty.sprite(64, "images/sprite.png", {
		red: [0,0],
		yellow: [1,0],
		empty: [2,0]
	});

  Crafty.scene("game", function() {

    //generate gBoard
    for(var i = 0; i < 7; i++) {
      gBoard[i] = []; //init gBoard
      for(var j = 0; j < 6; j++) {
        Crafty.e("2D, Canvas, empty").attr({x: i * 64, y: j * 64 + 100, z: 2});
        gBoard[i][j] = EMPTY; //set it to empty
      }
    }

		Crafty.c("piece", {
			init: function() {
				this.z = 3;
				this.requires("Mouse, Gravity, Draggable");
				this.bind("StopDrag", function() {
					console.log("STOP");
					var column = Math.round(this._x / 64);
					this.x = column * 64;
					this.gravity("stopper");
          this.unbind("mousedown");

					reset(column);
				});
			}
		});

    function reset(column) {
      var row = findEmptyRow(column);
      if(row !== COLUMN_FULL && column >= 0 && column < 7) {
        gBoard[column][row] = gMyColor;
        pieceDrop(gMyColor, column, row);
        gCurrent = null; // stop tracking this piece - it's set
      } else {
        // reset to original position
        gCurrent.destroy();
        gCurrent = null;
        setWhoTurn(Env.user.oid);
      }
    }

		var ground = Crafty.e("2D, stopper").attr({y: Crafty.viewport.height - 16, w: Crafty.viewport.width, h: 20 });
		var bg = Crafty.e("2D, Canvas, Image").image("images/bg.png").attr({z: -1});
	});

  Crafty.scene("youWon", function() {
    var bg = Crafty.e("2D, DOM, Image").image("images/win.png", "no-repeat").attr({w: 600, h: 500, z: -1});
    Crafty.e("2D, DOM, Text").attr({x: 220, y: 200}).text("You Won!").font("30pt Arial");
  });

  Crafty.scene("theyWon", function() {
    var bg = Crafty.e("2D, DOM, Image").image("images/win.png", "no-repeat").attr({w: 600, h: 500, z: -1});
    Crafty.e("2D, DOM, Text").attr({x: 220, y: 200}).text("They Won").font("30pt Arial");
  });

  Crafty.scene("tieGame", function() {
    var bg = Crafty.e("2D, DOM, Image").image("images/win.png", "no-repeat").attr({w: 600, h: 500, z: -1});
    Crafty.e("2D, DOM, Text").attr({x: 220, y: 200}).text("tie game").font("30pt Arial");
  });

};

function win(turn) {
  Crafty.scene("win");
}
function findEmptyRow(column) {
  if(!gBoard[column]) return;
  for(var i = 0; i < gBoard[column].length; i++) {
    if(gBoard[column][i] == EMPTY)
      return i;
  }
  return COLUMN_FULL;
}

/*
 function checkFour(column,row) {
 if(checkVertical(column,row)) return true;
 if(checkHorizontal(column,row)) return true;
 if(checkLeftDiagonal(column,row)) return true;
 if(checkRightDiagonal(column,row)) return true;
 return false;
 }

 function checkVertical(column,row) {
 if(row < 3) return false;
 for(var i = row; i > row-4; i--) {
 if(gBoard[column][i] != turn) return false;
 }
 return true;
 }

 function checkHorizontal(column,row) {
 var counter = 1;
 for(var i = column-1; i >= 0; i--) {
 if(gBoard[i][row] != turn) break;
 counter++;
 }

 for(var j = column+1; j < 7; j++) {
 if(gBoard[j][row] != turn) break;
 counter++;
 }
 return counter>=4;
 }

 function checkLeftDiagonal(column,row) {
 var counter = 1;
 var tmp_row = row-1;
 var tmp_column = column-1;

 while(tmp_row >= 0 && tmp_column >= 0) {
 if(gBoard[tmp_column][tmp_row] == turn) {
 counter++;
 tmp_row--;
 tmp_column--;
 } else break;
 }

 row += 1;
 column += 1;

 while(row < 6 && column < 7) {
 if(gBoard[column][row] == turn) {
 counter++;
 row++;
 column++;
 } else { break; }
 }
 return counter>=4;
 }

 function checkRightDiagonal(column,row) {
 var counter = 1;
 var tmp_row = row+1;
 var tmp_column = column-1;

 while(tmp_row < 6 && tmp_column >= 0) {
 if(gBoard[tmp_column][tmp_row] == turn) {
 counter++;
 tmp_row++;
 tmp_column--;
 } else break;
 }

 row -= 1;
 column += 1;

 while(row >= 0 && column < 7) {
 if(gBoard[column][row] == turn) {
 counter++;
 row--;
 column++;
 } else break;
 }
 return counter>=4;
 }
 */<commit_msg>fix low drop bug;<commit_after>//var turn = 0, //turn based
var COLUMN_FULL = -2;
var EMPTY = -1;
var YELLOW = 0;
var RED = 1;

var gMyColor = EMPTY;
var gBoard = [];
var gCurrent = null;

function initGame() {
	Crafty.init(600, 500);
	Crafty.canvas();

	Crafty.sprite(64, "images/sprite.png", {
		red: [0,0],
		yellow: [1,0],
		empty: [2,0]
	});

  Crafty.scene("game", function() {

    //generate gBoard
    for(var i = 0; i < 7; i++) {
      gBoard[i] = []; //init gBoard
      for(var j = 0; j < 6; j++) {
        Crafty.e("2D, Canvas, empty").attr({x: i * 64, y: j * 64 + 100, z: 2});
        gBoard[i][j] = EMPTY; //set it to empty
      }
    }

		Crafty.c("piece", {
			init: function() {
				this.z = 3;
				this.requires("Mouse, Gravity, Draggable");
				this.bind("StopDrag", function() {
					console.log("STOP");
					var column = Math.round(this._x / 64);
          this.x = column * 64;
					this.gravity("stopper");
          this.unbind("mousedown");

          if (this._y > 80) {
            column = 99;       // drop is too low, set to bad column for reset
          }
					reset(column);
				});
			}
		});

    function reset(column) {
      var row = findEmptyRow(column);
      if(row !== COLUMN_FULL && column >= 0 && column < 7) {
        gBoard[column][row] = gMyColor;
        pieceDrop(gMyColor, column, row);
        gCurrent = null; // stop tracking this piece - it's set
      } else {
        // reset to original position
        gCurrent.destroy();
        gCurrent = null;
        setWhoTurn(Env.user.oid);
      }
    }

		var ground = Crafty.e("2D, stopper").attr({y: Crafty.viewport.height - 16, w: Crafty.viewport.width, h: 20 });
		var bg = Crafty.e("2D, Canvas, Image").image("images/bg.png").attr({z: -1});
	});

  Crafty.scene("youWon", function() {
    var bg = Crafty.e("2D, DOM, Image").image("images/win.png", "no-repeat").attr({w: 600, h: 500, z: -1});
    Crafty.e("2D, DOM, Text").attr({x: 220, y: 200}).text("You Won!").font("30pt Arial");
  });

  Crafty.scene("theyWon", function() {
    var bg = Crafty.e("2D, DOM, Image").image("images/win.png", "no-repeat").attr({w: 600, h: 500, z: -1});
    Crafty.e("2D, DOM, Text").attr({x: 220, y: 200}).text("They Won").font("30pt Arial");
  });

  Crafty.scene("tieGame", function() {
    var bg = Crafty.e("2D, DOM, Image").image("images/win.png", "no-repeat").attr({w: 600, h: 500, z: -1});
    Crafty.e("2D, DOM, Text").attr({x: 220, y: 200}).text("tie game").font("30pt Arial");
  });

};

function win(turn) {
  Crafty.scene("win");
}
function findEmptyRow(column) {
  if(!gBoard[column]) return;
  for(var i = 0; i < gBoard[column].length; i++) {
    if(gBoard[column][i] == EMPTY)
      return i;
  }
  return COLUMN_FULL;
}

/*
 function checkFour(column,row) {
 if(checkVertical(column,row)) return true;
 if(checkHorizontal(column,row)) return true;
 if(checkLeftDiagonal(column,row)) return true;
 if(checkRightDiagonal(column,row)) return true;
 return false;
 }

 function checkVertical(column,row) {
 if(row < 3) return false;
 for(var i = row; i > row-4; i--) {
 if(gBoard[column][i] != turn) return false;
 }
 return true;
 }

 function checkHorizontal(column,row) {
 var counter = 1;
 for(var i = column-1; i >= 0; i--) {
 if(gBoard[i][row] != turn) break;
 counter++;
 }

 for(var j = column+1; j < 7; j++) {
 if(gBoard[j][row] != turn) break;
 counter++;
 }
 return counter>=4;
 }

 function checkLeftDiagonal(column,row) {
 var counter = 1;
 var tmp_row = row-1;
 var tmp_column = column-1;

 while(tmp_row >= 0 && tmp_column >= 0) {
 if(gBoard[tmp_column][tmp_row] == turn) {
 counter++;
 tmp_row--;
 tmp_column--;
 } else break;
 }

 row += 1;
 column += 1;

 while(row < 6 && column < 7) {
 if(gBoard[column][row] == turn) {
 counter++;
 row++;
 column++;
 } else { break; }
 }
 return counter>=4;
 }

 function checkRightDiagonal(column,row) {
 var counter = 1;
 var tmp_row = row+1;
 var tmp_column = column-1;

 while(tmp_row < 6 && tmp_column >= 0) {
 if(gBoard[tmp_column][tmp_row] == turn) {
 counter++;
 tmp_row++;
 tmp_column--;
 } else break;
 }

 row -= 1;
 column += 1;

 while(row >= 0 && column < 7) {
 if(gBoard[column][row] == turn) {
 counter++;
 row--;
 column++;
 } else break;
 }
 return counter>=4;
 }
 */<|endoftext|>


<commit_before>'use strict';

// User routes use users controller
var users = require('../controllers/users'),
    config = require('meanio').loadConfig();

var logFB = function(req, res, next) {
  console.log(process.env.FB_CLIENT_ID);
  console.log(process.env.FB_CLIENT_SECRET);
  console.log(process.env.BASE_URL + '/auth/facebook/callback');
  next();
};

module.exports = function(MeanUser, app, auth, database, passport) {

  app.route('/logout')
    .get(users.signout);
  app.route('/users/me')
    .get(users.me);

  // Setting up the users api
  app.route('/register')
    .post(users.create);

  app.route('/forgot-password')
    .post(users.forgotpassword);

  app.route('/reset/:token')
    .post(users.resetpassword);

  // Setting up the userId param
  app.param('userId', users.user);

  // AngularJS route to check for authentication
  app.route('/loggedin')
    .get(function(req, res) {
      res.send(req.isAuthenticated() ? req.user : '0');
    });

  // Setting the local strategy route
  app.route('/login')
    .post(passport.authenticate('local', {
      failureFlash: true
    }), function(req, res) {
      res.send({
        user: req.user,
        redirect: (req.user.roles.indexOf('admin') !== -1) ? req.get('referer') : false
      });
    });

  // AngularJS route to get config of social buttons
  app.route('/get-config')
    .get(function (req, res) {
      res.send(config);
    });

  // Setting the facebook oauth routes
  app.route('/auth/facebook')
    .get(logFB, passport.authenticate('facebook', {
      scope: ['email', 'user_about_me'],
      failureRedirect: '#!/login'
    }), users.signin);

  app.route('/auth/facebook/callback')
    .get(passport.authenticate('facebook', {
      failureRedirect: '#!/login'
    }), users.authCallback);

  app.post('/auth/facebook/token',
    passport.authenticate('facebook-token'),
    function (req, res) {
      // do something with req.user
      //res.send(req.user? 200 : 401);
      res.status(200).send({});
    }
  );
  // Setting the github oauth routes
  app.route('/auth/github')
    .get(passport.authenticate('github', {
      failureRedirect: '#!/login'
    }), users.signin);

  app.route('/auth/github/callback')
    .get(passport.authenticate('github', {
      failureRedirect: '#!/login'
    }), users.authCallback);

  // Setting the twitter oauth routes
  app.route('/auth/twitter')
    .get(passport.authenticate('twitter', {
      failureRedirect: '#!/login'
    }), users.signin);

  app.route('/auth/twitter/callback')
    .get(passport.authenticate('twitter', {
      failureRedirect: '#!/login'
    }), users.authCallback);

  // Setting the google oauth routes
  app.route('/auth/google')
    .get(passport.authenticate('google', {
      failureRedirect: '#!/login',
      scope: [
        'https://www.googleapis.com/auth/userinfo.profile',
        'https://www.googleapis.com/auth/userinfo.email'
      ]
    }), users.signin);

  app.route('/auth/google/callback')
    .get(passport.authenticate('google', {
      failureRedirect: '#!/login'
    }), users.authCallback);

  // Setting the linkedin oauth routes
  app.route('/auth/linkedin')
    .get(passport.authenticate('linkedin', {
      failureRedirect: '#!/login',
      scope: ['r_emailaddress']
    }), users.signin);

  app.route('/auth/linkedin/callback')
    .get(passport.authenticate('linkedin', {
      failureRedirect: '#!/login'
    }), users.authCallback);

};
<commit_msg>added test log route<commit_after>'use strict';

// User routes use users controller
var users = require('../controllers/users'),
    config = require('meanio').loadConfig();

var logFB = function(req, res, next) {
  console.log(process.env.FB_CLIENT_ID);
  console.log(process.env.FB_CLIENT_SECRET);
  console.log(process.env.BASE_URL + '/auth/facebook/callback');
  next();
};

module.exports = function(MeanUser, app, auth, database, passport) {

  app.route('/logout')
    .get(users.signout);
  app.route('/users/me')
    .get(users.me);

  app.route('/testLog')
    .put(function(req, res) {
      console.log(req.body.logText);
      res.status(200).send({});
    });

  // Setting up the users api
  app.route('/register')
    .post(users.create);

  app.route('/forgot-password')
    .post(users.forgotpassword);

  app.route('/reset/:token')
    .post(users.resetpassword);

  // Setting up the userId param
  app.param('userId', users.user);

  // AngularJS route to check for authentication
  app.route('/loggedin')
    .get(function(req, res) {
      res.send(req.isAuthenticated() ? req.user : '0');
    });

  // Setting the local strategy route
  app.route('/login')
    .post(passport.authenticate('local', {
      failureFlash: true
    }), function(req, res) {
      res.send({
        user: req.user,
        redirect: (req.user.roles.indexOf('admin') !== -1) ? req.get('referer') : false
      });
    });

  // AngularJS route to get config of social buttons
  app.route('/get-config')
    .get(function (req, res) {
      res.send(config);
    });

  // Setting the facebook oauth routes
  app.route('/auth/facebook')
    .get(logFB, passport.authenticate('facebook', {
      scope: ['email', 'user_about_me'],
      failureRedirect: '#!/login'
    }), users.signin);

  app.route('/auth/facebook/callback')
    .get(passport.authenticate('facebook', {
      failureRedirect: '#!/login'
    }), users.authCallback);

  app.post('/auth/facebook/token',
    passport.authenticate('facebook-token'),
    function (req, res) {
      // do something with req.user
      //res.send(req.user? 200 : 401);
      res.status(200).send({});
    }
  );
  // Setting the github oauth routes
  app.route('/auth/github')
    .get(passport.authenticate('github', {
      failureRedirect: '#!/login'
    }), users.signin);

  app.route('/auth/github/callback')
    .get(passport.authenticate('github', {
      failureRedirect: '#!/login'
    }), users.authCallback);

  // Setting the twitter oauth routes
  app.route('/auth/twitter')
    .get(passport.authenticate('twitter', {
      failureRedirect: '#!/login'
    }), users.signin);

  app.route('/auth/twitter/callback')
    .get(passport.authenticate('twitter', {
      failureRedirect: '#!/login'
    }), users.authCallback);

  // Setting the google oauth routes
  app.route('/auth/google')
    .get(passport.authenticate('google', {
      failureRedirect: '#!/login',
      scope: [
        'https://www.googleapis.com/auth/userinfo.profile',
        'https://www.googleapis.com/auth/userinfo.email'
      ]
    }), users.signin);

  app.route('/auth/google/callback')
    .get(passport.authenticate('google', {
      failureRedirect: '#!/login'
    }), users.authCallback);

  // Setting the linkedin oauth routes
  app.route('/auth/linkedin')
    .get(passport.authenticate('linkedin', {
      failureRedirect: '#!/login',
      scope: ['r_emailaddress']
    }), users.signin);

  app.route('/auth/linkedin/callback')
    .get(passport.authenticate('linkedin', {
      failureRedirect: '#!/login'
    }), users.authCallback);

};
<|endoftext|>


<commit_before>
var Lab = require('lab');
var lab = exports.lab = Lab.script();

var describe = lab.describe;
var it = lab.it;
var before = lab.before;
var after = lab.after;
var Code = require('code');
var expect = Code.expect;

var SERVER_EXISTING = {
  host: process.env.MC_SERVER || 'localhost', //'89.221.255.150'
  port: process.env.MC_PORT = 25565,
};

var Query = require('../');

var globalQuery;
var globalSession;

var MockServer = require('./mock-server');
var mockServer;

describe('mcquery', function () {

  after(function (done) {
    globalQuery.close();
    done();
  });

  before(function (done) {
    if (process.env.MC_SERVER) {
      setupClient();
    }
    else {
      mockServer = new MockServer();
      mockServer.bind(function (err, socket) {
        var address = socket.address();
        SERVER_EXISTING.host =  address.address;
        SERVER_EXISTING.port = address.port;
        setupClient();
      });

    }

    function setupClient() {
      globalQuery = new Query(SERVER_EXISTING.host, SERVER_EXISTING.port);
      //this.timeout(10000);
      globalQuery.connect(function (err, session) {
        expect(err).to.not.exist;
        expect(session).to.exist;
        globalSession = session;
        done();
      });
    }

  });

  it('should have a proper session', function (done) {
    expect(globalSession).be.instanceOf(Query);
    expect(globalSession).include(['challengeToken']);
    expect(globalSession.challengeToken).be.within(1, 0XFFFFFFFF);
    done();
  });

  it('should have a correct sessionId', function (done) {
    expect(globalSession).to.include(['sessionId', 'challengeToken']);
    expect(globalSession.challengeToken).to.be.within(1, 0XFFFFFFFF);
    //test masking
    expect(globalSession.sessionId).to
    .equal(globalSession.sessionId & 0x0F0F0F0F);
    done();
  });

  it('should be able to do an .doHandshake', function (done) {
    var oldChallenge = globalSession.challengeToken;
    globalQuery.doHandshake(function (err, session) {
      expect(err).not.exist;
      expect(session.challengeToken).not.be.equal(oldChallenge);
      done();
    });

  });

  it('should be able to do an .doHandshake without callback', function (done) {
    var oldChallenge = globalSession.challengeToken;
    globalQuery.doHandshake();

    setTimeout(function () {
      expect(globalSession.challengeToken).not.be.equal(oldChallenge);
      done();
    }, 300);

  });

  it('should be able to connect twice', function (done) {
    var oldChallenge = globalSession.challengeToken;
    expect(globalQuery.online).to.equal(true);
    globalQuery.connect(function (err, session) {
      expect(err).not.exist;
      expect(session.challengeToken).not.be.equal(oldChallenge);
      done();
    });
  });

  it('should timeout', {timeout: 5000, only:true}, function (done) {
    if (!mockServer) {
      done();
    }
    mockServer.ignore = true;
    globalQuery.doHandshake(function (err) {
      expect(err).to.exist();
      done();
    });
  });

  describe('.basic_stat(err, result)', function () {
    var result, err;
    before({timeout:4000}, function (done) {
      globalQuery.connect(cnn);
      function cnn() {
        globalQuery.basic_stat(function (er, res) {
          err = er;
          result = res;
          done(err);
        });
        expect(globalQuery.outstandingRequests(), 'outstandingRequests')
        .to.equal(1);
      }

    });

    it('err should be null', function (done) {
      expect(err).not.exist;
      done();
    });

    it('result should be correct', function (done) {
      expect(result).exist;
      expect(result).to.include(['MOTD', 'gametype', 'map', 'numplayers',
        'maxplayers', 'hostport', 'hostip']);

      expect(result.numplayers).to.be.within(0, 1024);
      expect(result.maxplayers).to.be.within(0, 1024);
      expect(result.hostport).to.be.within(1, 65535);

      done();
    });

    it('should require callback', function (done) {
      expect(fn).to.throw(Error, 'no callback');
      function fn() {
        globalQuery.basic_stat();
      }
      done();
    });
  });

  describe('.full_stat(err, result)', function () {
    var err, result;
    before(function (done) {
      globalQuery.doHandshake(function (er) {
        expect(er).to.not.exist;
        globalQuery.full_stat(function (er, stat) {
          err = er;
          result = stat;
          done();
        });

      });

    });

    it('err should be null', function (done) {
      expect(err).not.exist;
      done();
    });

    it('result should be correct', function (done) {
      expect(result).to.exist;
      var props = [
        'hostname',
        'gametype',
        'numplayers',
        'maxplayers',
        'hostport',
        'hostip',
        'game_id',
        'version',
        'plugins',
        'map',
        'player_'
      ];

      for (var i = 0; i < props.length; i++) {
        expect(result).to.include(props[i]);
      }
      expect(result.player_).to.be.instanceOf(Array);
      done();

    });

    it('should require callback', function (done) {
      expect(fn).to.throw(Error, 'callback is not a function');
      function fn() {
        globalQuery.full_stat();
      }
      done();
    });
  });
});

<commit_msg>fixed some tests<commit_after>
var Lab = require('lab');
var lab = exports.lab = Lab.script();

var describe = lab.describe;
var it = lab.it;
var before = lab.before;
var after = lab.after;
var Code = require('code');
var expect = Code.expect;

var SERVER_EXISTING = {
  host: process.env.MC_SERVER || 'localhost', //'89.221.255.150'
  port: process.env.MC_PORT = 25565,
};

var Query = require('../');

var globalQuery;
var globalSession;

var MockServer = require('./mock-server');
var mockServer;

describe('mcquery', function () {

  after(function (done) {
    globalQuery.close();
    done();
  });

  before({timeout: 5000}, function (done) {
    if (process.env.MC_SERVER) {
      setupClient();
    }
    else {
      mockServer = new MockServer();
      mockServer.bind(function (err, socket) {
        var address = socket.address();
        SERVER_EXISTING.host =  address.address;
        SERVER_EXISTING.port = address.port;
        setupClient();
      });

    }

    function setupClient() {
      try {
        globalQuery = new Query(SERVER_EXISTING.host, SERVER_EXISTING.port);
        //this.timeout(10000);
        globalQuery.connect(function (err, session) {
          if (err) {
            return done(err);
          }
          globalSession = session;
          done(err);
        });
      }
      catch (ex) {
        done(ex);
      }
    }

  });

  it('should have a proper session', function (done) {
    expect(globalSession).be.instanceOf(Query);
    expect(globalSession).include(['challengeToken']);
    expect(globalSession.challengeToken).be.within(1, 0XFFFFFFFF);
    done();
  });

  it('should have a correct sessionId', function (done) {
    expect(globalSession).to.include(['sessionId', 'challengeToken']);
    expect(globalSession.challengeToken).to.be.within(1, 0XFFFFFFFF);
    //test masking
    expect(globalSession.sessionId).to
    .equal(globalSession.sessionId & 0x0F0F0F0F);
    done();
  });

  it('should be able to do an .doHandshake', function (done) {
    var oldChallenge = globalSession.challengeToken;
    globalQuery.doHandshake(function (err, session) {
      expect(err).not.exist;
      expect(session.challengeToken).not.be.equal(oldChallenge);
      done();
    });

  });

  it('should be able to do an .doHandshake without callback', function (done) {
    var oldChallenge = globalSession.challengeToken;
    globalQuery.doHandshake();

    setTimeout(function () {
      expect(globalSession.challengeToken).not.be.equal(oldChallenge);
      done();
    }, 300);

  });

  it('should be able to connect twice', function (done) {
    var oldChallenge = globalSession.challengeToken;
    expect(globalQuery.online).to.equal(true);
    globalQuery.connect(function (err, session) {
      expect(err).not.exist;
      expect(session.challengeToken).not.be.equal(oldChallenge);
      done();
    });
  });

  it('should timeout', {timeout: 5000, only:true}, function (done) {
    if (!mockServer) {
      return done();
    }
    mockServer.ignore = true;
    globalQuery.doHandshake(function (err) {
      expect(err).to.exist();
      done();
    });
  });

  describe('.basic_stat(err, result)', function () {
    var result, err;
    before({timeout:4000}, function (done) {
      globalQuery.connect(cnn);
      function cnn() {
        globalQuery.basic_stat(function (er, res) {
          err = er;
          result = res;
          done(err);
        });
        expect(globalQuery.outstandingRequests(), 'outstandingRequests')
        .to.equal(1);
      }

    });

    it('err should be null', function (done) {
      expect(err).not.exist;
      done();
    });

    it('result should be correct', function (done) {
      expect(result).exist;
      expect(result).to.include(['MOTD', 'gametype', 'map', 'numplayers',
        'maxplayers', 'hostport', 'hostip']);

      expect(result.numplayers).to.be.within(0, 1024);
      expect(result.maxplayers).to.be.within(0, 1024);
      expect(result.hostport).to.be.within(1, 65535);

      done();
    });

    it('should require callback', function (done) {
      expect(fn).to.throw(Error, 'no callback');
      function fn() {
        globalQuery.basic_stat();
      }
      done();
    });
  });

  describe('.full_stat(err, result)', function () {
    var err, result;
    before(function (done) {
      globalQuery.doHandshake(function (er) {
        expect(er).to.not.exist;
        globalQuery.full_stat(function (er, stat) {
          err = er;
          result = stat;
          done();
        });

      });

    });

    it('err should be null', function (done) {
      expect(err).not.exist;
      done();
    });

    it('result should be correct', function (done) {
      expect(result).to.exist;
      var props = [
        'hostname',
        'gametype',
        'numplayers',
        'maxplayers',
        'hostport',
        'hostip',
        'game_id',
        'version',
        'plugins',
        'map',
        'player_'
      ];

      for (var i = 0; i < props.length; i++) {
        expect(result).to.include(props[i]);
      }
      expect(result.player_).to.be.instanceOf(Array);
      done();

    });

    it('should require callback', function (done) {
      expect(fn).to.throw(Error, 'callback is not a function');
      function fn() {
        globalQuery.full_stat();
      }
      done();
    });
  });
});

<|endoftext|>


<commit_before>console.log("basic test");

var url, NODE, uri, should, assert;

//check if we are in browser or webview
if (typeof window == "undefined") {
  console.log("we are not in the browser");
  url = require('url');

  var request = require('superagent');

  NODE = true;
  uri = 'http://localhost:3030';
  if (typeof window !== 'undefined') {
    NODE = false;
    uri = '//' + window.location.host;
  }
  else {
    process.env.ZUUL_PORT = 3030;
    require('./support/server.js');
    uri = 'http://localhost:3030';
  }

}

//desktop
if (typeof cordova == "undefined" && typeof window == "undefined") {
    console.log("we are in the desktop");
    should = require('should');
    assert = require('assert');
}

console.log("uri:" + uri);

//test if we are using mocha
if(typeof describe != "undefined") {
    console.log("run mocha tests!");

    if (typeof window.request != "undefined"){
        var request = window.request;
    }
    console.log("typeof request:" + typeof request);

    describe('request', function () {

        describe('with a callback', function () {
            it('should invoke .end()', function (done) {
                $.get(uri + '/login', function (data){console.log("data:" + JSON.stringifY(data))});

                request
                    .get(uri + '/login', function (err, res) {
                        console.log("result" + JSON.stringify([err,res]));
                        assert(res.status == 200);
                        done();
                    })
            })
        })

        describe('.end()', function () {
            it('should issue a request', function (done) {
                request
                    .get(uri + '/login')
                    .end(function (err, res) {
                        assert(res.status == 200);
                        done();
                    });
            })
        })

        describe('res.error', function () {
            it('should should be an Error object', function (done) {
                request
                    .get(uri + '/error')
                    .end(function (err, res) {
                        if (NODE) {
                            res.error.message.should.equal('cannot GET /error (500)');
                        }
                        else {
                            res.error.message.should.equal('cannot GET ' + uri + '/error (500)');
                        }
                        assert(res.error.status === 500);
                        assert(err, 'should have an error for 500');
                        assert.equal(err.message, 'Internal Server Error');
                        done();
                    });
            })
        })

        describe('res.header', function () {
            it('should be an object', function (done) {
                request
                    .get(uri + '/login')
                    .end(function (err, res) {
                        assert('Express' == res.header['x-powered-by']);
                        done();
                    });
            })
        })

        describe('res.charset', function () {
            it('should be set when present', function (done) {
                request
                    .get(uri + '/login')
                    .end(function (err, res) {
                        res.charset.should.equal('utf-8');
                        done();
                    });
            })
        })

        describe('res.statusType', function () {
            it('should provide the first digit', function (done) {
                request
                    .get(uri + '/login')
                    .end(function (err, res) {
                        assert(!err, 'should not have an error for success responses');
                        assert(200 == res.status);
                        assert(2 == res.statusType);
                        done();
                    });
            })
        })

        describe('res.type', function () {
            it('should provide the mime-type void of params', function (done) {
                request
                    .get(uri + '/login')
                    .end(function (err, res) {
                        res.type.should.equal('text/html');
                        res.charset.should.equal('utf-8');
                        done();
                    });
            })
        })

        describe('req.set(field, val)', function () {
            it('should set the header field', function (done) {
                request
                    .post(uri + '/echo')
                    .set('X-Foo', 'bar')
                    .set('X-Bar', 'baz')
                    .end(function (err, res) {
                        assert('bar' == res.header['x-foo']);
                        assert('baz' == res.header['x-bar']);
                        done();
                    })
            })
        })

        describe('req.set(obj)', function () {
            it('should set the header fields', function (done) {
                request
                    .post(uri + '/echo')
                    .set({'X-Foo': 'bar', 'X-Bar': 'baz'})
                    .end(function (err, res) {
                        assert('bar' == res.header['x-foo']);
                        assert('baz' == res.header['x-bar']);
                        done();
                    })
            })
        })

        describe('req.type(str)', function () {
            it('should set the Content-Type', function (done) {
                request
                    .post(uri + '/echo')
                    .type('text/x-foo')
                    .end(function (err, res) {
                        res.header['content-type'].should.equal('text/x-foo');
                        done();
                    });
            })

            it('should map "json"', function (done) {
                request
                    .post(uri + '/echo')
                    .type('json')
                    .send('{"a": 1}')
                    .end(function (err, res) {
                        res.should.be.json;
                        done();
                    });
            })

            it('should map "html"', function (done) {
                request
                    .post(uri + '/echo')
                    .type('html')
                    .end(function (err, res) {
                        res.header['content-type'].should.equal('text/html');
                        done();
                    });
            })
        })

        describe('req.accept(str)', function () {
            it('should set Accept', function (done) {
                request
                    .get(uri + '/echo')
                    .accept('text/x-foo')
                    .end(function (err, res) {
                        res.header['accept'].should.equal('text/x-foo');
                        done();
                    });
            })

            it('should map "json"', function (done) {
                request
                    .get(uri + '/echo')
                    .accept('json')
                    .end(function (err, res) {
                        res.header['accept'].should.equal('application/json');
                        done();
                    });
            })

            it('should map "xml"', function (done) {
                request
                    .get(uri + '/echo')
                    .accept('xml')
                    .end(function (err, res) {
                        res.header['accept'].should.equal('application/xml');
                        done();
                    });
            })

            it('should map "html"', function (done) {
                request
                    .get(uri + '/echo')
                    .accept('html')
                    .end(function (err, res) {
                        res.header['accept'].should.equal('text/html');
                        done();
                    });
            })
        })

        describe('req.send(str)', function () {
            it('should write the string', function (done) {
                request
                    .post(uri + '/echo')
                    .type('json')
                    .send('{"name":"tobi"}')
                    .end(function (err, res) {
                        res.text.should.equal('{"name":"tobi"}');
                        done();
                    });
            })
        })

        describe('req.send(Object)', function () {
            it('should default to json', function (done) {
                request
                    .post(uri + '/echo')
                    .send({name: 'tobi'})
                    .end(function (err, res) {
                        res.should.be.json
                        res.text.should.equal('{"name":"tobi"}');
                        done();
                    });
            })

            describe('when called several times', function () {
                it('should merge the objects', function (done) {
                    request
                        .post(uri + '/echo')
                        .send({name: 'tobi'})
                        .send({age: 1})
                        .end(function (err, res) {
                            res.should.be.json
                            if (NODE) {
                                res.buffered.should.be.true;
                            }
                            res.text.should.equal('{"name":"tobi","age":1}');
                            done();
                        });
                })
            })
        })

        describe('.end(fn)', function () {
            it('should check arity', function (done) {
                request
                    .post(uri + '/echo')
                    .send({name: 'tobi'})
                    .end(function (err, res) {
                        assert(null == err);
                        res.text.should.equal('{"name":"tobi"}');
                        done();
                    });
            })

            it('should emit request', function (done) {
                var req = request.post(uri + '/echo');
                req.on('request', function (request) {
                    assert(req == request);
                    done();
                });
                req.end();
            })

            it('should emit response', function (done) {
                request
                    .post(uri + '/echo')
                    .send({name: 'tobi'})
                    .on('response', function (res) {
                        res.text.should.equal('{"name":"tobi"}');
                        done();
                    })
                    .end();
            })
        })

        describe('.abort()', function () {
            it('should abort the request', function (done) {
                var req = request
                    .get(uri + '/delay/3000')
                    .end(function (err, res) {
                        assert(false, 'should not complete the request');
                    });

                req.on('abort', done);

                setTimeout(function () {
                    req.abort();
                }, 1000);
            })
        })
    })

}<commit_msg>update superagent tests<commit_after>console.log("basic test");

var url, NODE, uri, should, assert;

//check if we are in browser or webview
if (typeof window === "undefined") {
  console.log("we are not in the browser");
  url = require('url');

  var request = require('superagent');

  NODE = true;
  uri = 'http://localhost:3030';

    process.env.ZUUL_PORT = 3030;
    require('./support/server.js');
    uri = 'http://localhost:3030';

} else {

    NODE = false;
    uri = '//' + window.location.host;

}

//desktop
if (typeof cordova == "undefined" && typeof window == "undefined") {
    console.log("we are in the desktop");
    should = require('should');
    assert = require('assert');
}

console.log("uri:" + uri);

//test if we are using mocha
if(typeof describe != "undefined") {
    console.log("run mocha tests!");

    if (typeof window.request != "undefined"){
        var request = window.request;
    }
    console.log("typeof request:" + typeof request);

    describe('request', function () {

        describe('with a callback', function () {
            it('should invoke .end()', function (done) {
                $.get(uri + '/login', function (data){console.log("data:" + JSON.stringifY(data))});

                request
                    .get(uri + '/login', function (err, res) {
                        console.log("result" + JSON.stringify([err,res]));
                        assert(res.status == 200);
                        done();
                    })
            })
        })

        describe('.end()', function () {
            it('should issue a request', function (done) {
                request
                    .get(uri + '/login')
                    .end(function (err, res) {
                        assert(res.status == 200);
                        done();
                    });
            })
        })

        describe('res.error', function () {
            it('should should be an Error object', function (done) {
                request
                    .get(uri + '/error')
                    .end(function (err, res) {
                        if (NODE) {
                            res.error.message.should.equal('cannot GET /error (500)');
                        }
                        else {
                            res.error.message.should.equal('cannot GET ' + uri + '/error (500)');
                        }
                        assert(res.error.status === 500);
                        assert(err, 'should have an error for 500');
                        assert.equal(err.message, 'Internal Server Error');
                        done();
                    });
            })
        })

        describe('res.header', function () {
            it('should be an object', function (done) {
                request
                    .get(uri + '/login')
                    .end(function (err, res) {
                        assert('Express' == res.header['x-powered-by']);
                        done();
                    });
            })
        })

        describe('res.charset', function () {
            it('should be set when present', function (done) {
                request
                    .get(uri + '/login')
                    .end(function (err, res) {
                        res.charset.should.equal('utf-8');
                        done();
                    });
            })
        })

        describe('res.statusType', function () {
            it('should provide the first digit', function (done) {
                request
                    .get(uri + '/login')
                    .end(function (err, res) {
                        assert(!err, 'should not have an error for success responses');
                        assert(200 == res.status);
                        assert(2 == res.statusType);
                        done();
                    });
            })
        })

        describe('res.type', function () {
            it('should provide the mime-type void of params', function (done) {
                request
                    .get(uri + '/login')
                    .end(function (err, res) {
                        res.type.should.equal('text/html');
                        res.charset.should.equal('utf-8');
                        done();
                    });
            })
        })

        describe('req.set(field, val)', function () {
            it('should set the header field', function (done) {
                request
                    .post(uri + '/echo')
                    .set('X-Foo', 'bar')
                    .set('X-Bar', 'baz')
                    .end(function (err, res) {
                        assert('bar' == res.header['x-foo']);
                        assert('baz' == res.header['x-bar']);
                        done();
                    })
            })
        })

        describe('req.set(obj)', function () {
            it('should set the header fields', function (done) {
                request
                    .post(uri + '/echo')
                    .set({'X-Foo': 'bar', 'X-Bar': 'baz'})
                    .end(function (err, res) {
                        assert('bar' == res.header['x-foo']);
                        assert('baz' == res.header['x-bar']);
                        done();
                    })
            })
        })

        describe('req.type(str)', function () {
            it('should set the Content-Type', function (done) {
                request
                    .post(uri + '/echo')
                    .type('text/x-foo')
                    .end(function (err, res) {
                        res.header['content-type'].should.equal('text/x-foo');
                        done();
                    });
            })

            it('should map "json"', function (done) {
                request
                    .post(uri + '/echo')
                    .type('json')
                    .send('{"a": 1}')
                    .end(function (err, res) {
                        res.should.be.json;
                        done();
                    });
            })

            it('should map "html"', function (done) {
                request
                    .post(uri + '/echo')
                    .type('html')
                    .end(function (err, res) {
                        res.header['content-type'].should.equal('text/html');
                        done();
                    });
            })
        })

        describe('req.accept(str)', function () {
            it('should set Accept', function (done) {
                request
                    .get(uri + '/echo')
                    .accept('text/x-foo')
                    .end(function (err, res) {
                        res.header['accept'].should.equal('text/x-foo');
                        done();
                    });
            })

            it('should map "json"', function (done) {
                request
                    .get(uri + '/echo')
                    .accept('json')
                    .end(function (err, res) {
                        res.header['accept'].should.equal('application/json');
                        done();
                    });
            })

            it('should map "xml"', function (done) {
                request
                    .get(uri + '/echo')
                    .accept('xml')
                    .end(function (err, res) {
                        res.header['accept'].should.equal('application/xml');
                        done();
                    });
            })

            it('should map "html"', function (done) {
                request
                    .get(uri + '/echo')
                    .accept('html')
                    .end(function (err, res) {
                        res.header['accept'].should.equal('text/html');
                        done();
                    });
            })
        })

        describe('req.send(str)', function () {
            it('should write the string', function (done) {
                request
                    .post(uri + '/echo')
                    .type('json')
                    .send('{"name":"tobi"}')
                    .end(function (err, res) {
                        res.text.should.equal('{"name":"tobi"}');
                        done();
                    });
            })
        })

        describe('req.send(Object)', function () {
            it('should default to json', function (done) {
                request
                    .post(uri + '/echo')
                    .send({name: 'tobi'})
                    .end(function (err, res) {
                        res.should.be.json
                        res.text.should.equal('{"name":"tobi"}');
                        done();
                    });
            })

            describe('when called several times', function () {
                it('should merge the objects', function (done) {
                    request
                        .post(uri + '/echo')
                        .send({name: 'tobi'})
                        .send({age: 1})
                        .end(function (err, res) {
                            res.should.be.json
                            if (NODE) {
                                res.buffered.should.be.true;
                            }
                            res.text.should.equal('{"name":"tobi","age":1}');
                            done();
                        });
                })
            })
        })

        describe('.end(fn)', function () {
            it('should check arity', function (done) {
                request
                    .post(uri + '/echo')
                    .send({name: 'tobi'})
                    .end(function (err, res) {
                        assert(null == err);
                        res.text.should.equal('{"name":"tobi"}');
                        done();
                    });
            })

            it('should emit request', function (done) {
                var req = request.post(uri + '/echo');
                req.on('request', function (request) {
                    assert(req == request);
                    done();
                });
                req.end();
            })

            it('should emit response', function (done) {
                request
                    .post(uri + '/echo')
                    .send({name: 'tobi'})
                    .on('response', function (res) {
                        res.text.should.equal('{"name":"tobi"}');
                        done();
                    })
                    .end();
            })
        })

        describe('.abort()', function () {
            it('should abort the request', function (done) {
                var req = request
                    .get(uri + '/delay/3000')
                    .end(function (err, res) {
                        assert(false, 'should not complete the request');
                    });

                req.on('abort', done);

                setTimeout(function () {
                    req.abort();
                }, 1000);
            })
        })
    })

}<|endoftext|>


<commit_before>'use strict';

const fs = require('fs');
const util = require('util');
const zlib = require('zlib');
const stream = require('stream');
const fetch = require('node-fetch');
const tarStream = require('tar-stream');
const getStream = require('get-stream');
const { chromium } = require('playwright');
const { PNG } = require('pngjs');
const pixelmatch = require('pixelmatch');
const { optimize } = require('../lib/svgo.js');

const pipeline = util.promisify(stream.pipeline);

const readSvgFiles = async () => {
  const svgFiles = [];
  const response = await fetch(
    'https://www.w3.org/Graphics/SVG/Test/20110816/archives/W3C_SVG_11_TestSuite.tar.gz'
  );
  const extract = tarStream.extract();
  extract.on('entry', async (header, stream, next) => {
    try {
      if (header.name.startsWith('svg/')) {
        if (header.name.endsWith('.svg')) {
          // strip folder and extension
          const name = header.name.slice('svg/'.length, -'.svg'.length);
          const string = await getStream(stream);
          svgFiles.push([name, string]);
        }
        if (header.name.endsWith('.svgz')) {
          // strip folder and extension
          const name = header.name.slice('svg/'.length, -'.svgz'.length);
          const string = await getStream(stream.pipe(zlib.createGunzip()));
          svgFiles.push([name, string]);
        }
      }
    } catch (error) {
      console.error(error);
      process.exit(1);
    }
    stream.resume();
    next();
  });
  await pipeline(response.body, extract);
  return svgFiles;
};

const optimizeSvgFiles = (svgFiles) => {
  const optimizedFiles = new Map();
  let failed = 0;
  for (const [name, string] of svgFiles) {
    try {
      const result = optimize(string, { path: name, floatPrecision: 4 });
      if (result.error) {
        console.error(result.error);
        console.error(`File: ${name}`);
        failed += 1;
        continue;
      } else {
        optimizedFiles.set(name, result.data);
      }
    } catch (error) {
      console.error(error);
      console.error(`File: ${name}`);
      failed += 1;
      continue;
    }
  }
  if (failed !== 0) {
    throw Error(`Failed to optimize ${failed} cases`);
  }
  return optimizedFiles;
};

const chunkInto = (array, chunksCount) => {
  // take upper bound to include tail
  const chunkSize = Math.ceil(array.length / chunksCount);
  const result = [];
  for (let i = 0; i < chunksCount; i += 1) {
    const offset = i * chunkSize;
    result.push(array.slice(offset, offset + chunkSize));
  }
  return result;
};

const runTests = async ({ svgFiles }) => {
  const optimizedFiles = optimizeSvgFiles(svgFiles);
  let skipped = 0;
  let mismatched = 0;
  let passed = 0;
  console.info('Start browser...');
  const processFile = async (page, name, string) => {
    if (
      // hard to detect the end of animation
      name.startsWith('animate-') ||
      // breaks because of optimisation despite of script
      name === 'interact-pointer-04-f' ||
      // messed gradients
      name === 'pservers-grad-18-b' ||
      // animated filter
      name === 'filters-light-04-f' ||
      // removing wrapping <g> breaks :first-child pseudo-class
      name === 'styling-pres-04-f' ||
      // messed case insensitivity while inlining styles
      name === 'styling-css-10-f' ||
      // rect is converted to path which matches wrong styles
      name === 'styling-css-08-f' ||
      // external image
      name === 'struct-image-02-b' ||
      // complex selectors are messed becase of converting shapes to paths
      name === 'struct-use-10-f' ||
      name === 'struct-use-11-f' ||
      name === 'styling-css-01-b' ||
      name === 'styling-css-03-b' ||
      name === 'styling-css-04-f' ||
      // strange artifact breaks inconsistently  breaks regression tests
      name === 'filters-conv-05-f'
    ) {
      console.info(`${name} is skipped`);
      skipped += 1;
      return;
    }
    const optimized = optimizedFiles.get(name);
    const width = 960;
    const height = 720;
    await page.goto(`data:image/svg+xml,${encodeURIComponent(string)}`);
    await page.setViewportSize({ width, height });
    const originalBuffer = await page.screenshot({
      omitBackground: true,
      clip: { x: 0, y: 0, width, height },
    });
    await page.goto(`data:image/svg+xml,${encodeURIComponent(optimized)}`);
    const optimizedBuffer = await page.screenshot({
      omitBackground: true,
      clip: { x: 0, y: 0, width, height },
    });
    const originalPng = PNG.sync.read(originalBuffer);
    const optimizedPng = PNG.sync.read(optimizedBuffer);
    const diff = new PNG({ width, height });
    const matched = pixelmatch(
      originalPng.data,
      optimizedPng.data,
      diff.data,
      width,
      height
    );
    // ignore small aliasing issues
    if (matched <= 4) {
      console.info(`${name} is passed`);
      passed += 1;
    } else {
      mismatched += 1;
      console.error(`${name} is mismatched`);
      if (process.env.NO_DIFF == null) {
        await fs.promises.mkdir('diffs', { recursive: true });
        await fs.promises.writeFile(
          `diffs/${name}.diff.png`,
          PNG.sync.write(diff)
        );
      }
    }
  };
  const browser = await chromium.launch();
  const context = await browser.newContext({ javaScriptEnabled: false });
  const chunks = chunkInto(svgFiles, 8);
  await Promise.all(
    chunks.map(async (chunk) => {
      const page = await context.newPage();
      for (const [name, string] of chunk) {
        await processFile(page, name, string);
      }
      await page.close();
    })
  );
  await browser.close();
  console.info(`Skipped: ${skipped}`);
  console.info(`Mismatched: ${mismatched}`);
  console.info(`Passed: ${passed}`);
  return mismatched === 0;
};

(async () => {
  try {
    const start = process.hrtime.bigint();
    console.info('Download W3C SVG 1.1 Test Suite and extract svg files');
    const svgFiles = await readSvgFiles();
    const passed = await runTests({ svgFiles });
    const end = process.hrtime.bigint();
    const diff = (end - start) / BigInt(1e6);
    if (passed) {
      console.info(`Regression tests successfully completed in ${diff}ms`);
    } else {
      console.error(`Regression tests failed in ${diff}ms`);
      process.exit(1);
    }
  } catch (error) {
    console.error(error);
    process.exit(1);
  }
})();
<commit_msg>Serve svg for regressions and cache w3c test suite<commit_after>'use strict';

const fs = require('fs');
const path = require('path');
const util = require('util');
const zlib = require('zlib');
const http = require('http');
const stream = require('stream');
const fetch = require('node-fetch');
const tarStream = require('tar-stream');
const getStream = require('get-stream');
const { chromium } = require('playwright');
const { PNG } = require('pngjs');
const pixelmatch = require('pixelmatch');
const { optimize } = require('../lib/svgo.js');

const pipeline = util.promisify(stream.pipeline);

const readSvgFiles = async () => {
  const cachedArchiveFile = path.join(
    process.cwd(),
    'node_modules/.cache/W3C_SVG_11_TestSuite.tar.gz'
  );
  const svgFiles = new Map();
  let fileStream;
  try {
    await fs.promises.access(cachedArchiveFile);
    fileStream = fs.createReadStream(cachedArchiveFile);
  } catch {
    const response = await fetch(
      'https://www.w3.org/Graphics/SVG/Test/20110816/archives/W3C_SVG_11_TestSuite.tar.gz'
    );
    fileStream = response.body;
    fileStream.pipe(fs.createWriteStream(cachedArchiveFile));
  }
  const extract = tarStream.extract();
  extract.on('entry', async (header, stream, next) => {
    try {
      if (header.name.startsWith('svg/')) {
        if (header.name.endsWith('.svg')) {
          // strip folder and extension
          const name = header.name.slice('svg/'.length, -'.svg'.length);
          const string = await getStream(stream);
          svgFiles.set(name, string);
        }
        if (header.name.endsWith('.svgz')) {
          // strip folder and extension
          const name = header.name.slice('svg/'.length, -'.svgz'.length);
          const string = await getStream(stream.pipe(zlib.createGunzip()));
          svgFiles.set(name, string);
        }
      }
    } catch (error) {
      console.error(error);
      process.exit(1);
    }
    stream.resume();
    next();
  });
  await pipeline(fileStream, extract);
  return svgFiles;
};

const optimizeSvgFiles = (svgFiles) => {
  const optimizedFiles = new Map();
  let failed = 0;
  for (const [name, string] of svgFiles) {
    try {
      const result = optimize(string, { path: name, floatPrecision: 4 });
      if (result.error) {
        console.error(result.error);
        console.error(`File: ${name}`);
        failed += 1;
        continue;
      } else {
        optimizedFiles.set(name, result.data);
      }
    } catch (error) {
      console.error(error);
      console.error(`File: ${name}`);
      failed += 1;
      continue;
    }
  }
  if (failed !== 0) {
    throw Error(`Failed to optimize ${failed} cases`);
  }
  return optimizedFiles;
};

const chunkInto = (array, chunksCount) => {
  // take upper bound to include tail
  const chunkSize = Math.ceil(array.length / chunksCount);
  const result = [];
  for (let i = 0; i < chunksCount; i += 1) {
    const offset = i * chunkSize;
    result.push(array.slice(offset, offset + chunkSize));
  }
  return result;
};

const runTests = async ({ svgFiles }) => {
  let skipped = 0;
  let mismatched = 0;
  let passed = 0;
  console.info('Start browser...');
  const processFile = async (page, name) => {
    if (
      // hard to detect the end of animation
      name.startsWith('animate-') ||
      // breaks because of optimisation despite of script
      name === 'interact-pointer-04-f' ||
      // messed gradients
      name === 'pservers-grad-18-b' ||
      // animated filter
      name === 'filters-light-04-f' ||
      // removing wrapping <g> breaks :first-child pseudo-class
      name === 'styling-pres-04-f' ||
      // messed case insensitivity while inlining styles
      name === 'styling-css-10-f' ||
      // rect is converted to path which matches wrong styles
      name === 'styling-css-08-f' ||
      // external image
      name === 'struct-image-02-b' ||
      // complex selectors are messed becase of converting shapes to paths
      name === 'struct-use-10-f' ||
      name === 'struct-use-11-f' ||
      name === 'styling-css-01-b' ||
      name === 'styling-css-03-b' ||
      name === 'styling-css-04-f' ||
      // strange artifact breaks inconsistently  breaks regression tests
      name === 'filters-conv-05-f'
    ) {
      console.info(`${name} is skipped`);
      skipped += 1;
      return;
    }
    const width = 960;
    const height = 720;
    await page.goto(`http://localhost:5000/original/${name}`);
    await page.setViewportSize({ width, height });
    const originalBuffer = await page.screenshot({
      omitBackground: true,
      clip: { x: 0, y: 0, width, height },
    });
    await page.goto(`http://localhost:5000/optimized/${name}`);
    const optimizedBuffer = await page.screenshot({
      omitBackground: true,
      clip: { x: 0, y: 0, width, height },
    });
    const originalPng = PNG.sync.read(originalBuffer);
    const optimizedPng = PNG.sync.read(optimizedBuffer);
    const diff = new PNG({ width, height });
    const matched = pixelmatch(
      originalPng.data,
      optimizedPng.data,
      diff.data,
      width,
      height
    );
    // ignore small aliasing issues
    if (matched <= 4) {
      console.info(`${name} is passed`);
      passed += 1;
    } else {
      mismatched += 1;
      console.error(`${name} is mismatched`);
      if (process.env.NO_DIFF == null) {
        await fs.promises.mkdir('diffs', { recursive: true });
        await fs.promises.writeFile(
          `diffs/${name}.diff.png`,
          PNG.sync.write(diff)
        );
      }
    }
  };
  const browser = await chromium.launch();
  const context = await browser.newContext({ javaScriptEnabled: false });
  const chunks = chunkInto(svgFiles, 8);
  await Promise.all(
    chunks.map(async (chunk) => {
      const page = await context.newPage();
      for (const name of chunk) {
        await processFile(page, name);
      }
      await page.close();
    })
  );
  await browser.close();
  console.info(`Skipped: ${skipped}`);
  console.info(`Mismatched: ${mismatched}`);
  console.info(`Passed: ${passed}`);
  return mismatched === 0;
};

(async () => {
  try {
    const start = process.hrtime.bigint();
    console.info('Download W3C SVG 1.1 Test Suite and extract svg files');
    const svgFiles = await readSvgFiles();
    const optimizedFiles = optimizeSvgFiles(svgFiles);
    const server = http.createServer((req, res) => {
      if (req.url.startsWith('/original/')) {
        const name = req.url.slice('/original/'.length);
        if (svgFiles.has(name)) {
          res.setHeader('Content-Type', 'image/svg+xml');
          res.end(svgFiles.get(name));
          return;
        }
      }
      if (req.url.startsWith('/optimized/')) {
        const name = req.url.slice('/optimized/'.length);
        if (optimizedFiles.has(name)) {
          res.setHeader('Content-Type', 'image/svg+xml');
          res.end(optimizedFiles.get(name));
          return;
        }
      }
      res.statusCode = 404;
      res.end();
    });
    await new Promise((resolve) => {
      server.listen(5000, resolve);
    });
    const passed = await runTests({ svgFiles: Array.from(svgFiles.keys()) });
    server.close();
    const end = process.hrtime.bigint();
    const diff = (end - start) / BigInt(1e6);
    if (passed) {
      console.info(`Regression tests successfully completed in ${diff}ms`);
    } else {
      console.error(`Regression tests failed in ${diff}ms`);
      process.exit(1);
    }
  } catch (error) {
    console.error(error);
    process.exit(1);
  }
})();
<|endoftext|>


<commit_before>// ----------------------------
// Consts
// ----------------------------

var Queries = (function() {
    var queryStr = window.location.search;
    var result = {};
    if (queryStr.length <= 1) {
        return result;
    }
    var queries = queryStr.substring(1, queryStr.length).split('&');
    for (var i=0; i<queries.length; i++) {
        var query = queries[i].split('=');
        var key = decodeURIComponent(query[0]);
        var value = (query.length === 1) ? null : decodeURIComponent(query[1]);
        result[key] = value;
    }
    return result;
})();
console.log(Queries);
var Settings = {
    isLocal: (function() {
        if (window.location.host.indexOf('192.168.') === 0) {
            return true;
        }
        return false;
    })(),
    OID: Queries.OID || null,
    RID: Queries.RID || null,
};
Settings.STUN_URL = Settings.isLocal ?
    'stun:stun.l.google.com:19302' :
    'stun:stun.synou.com';
Settings.SERVER_URL = Settings.isLocal ?
    'http://192.168.31.6:8888' :
//    ?  'http://192.168.24.74:8888' :
    'http://stun2.synou.com';
console.log('Settings', Settings);

$(function() {
    var startTime = Date.now(); // TEST

    // ----------------------------
    // Libs
    // ----------------------------

    var stateEl = $('#state').empty().text('通話サービスへ接続しています…。');

    var meetup = Meetup.create({
        // the id/element dom element that will hold "our" video
        localVideoEl: 'localVideo',
        // the id/element dom element that will hold remote videos
        remoteVideosEl: 'remoteVideos',
        // immediately ask for camera access. default false
        //autoRequestMedia: true,
        debug: true,
        peerConnectionConfig: {
            iceServers: [{
                "url": Settings.STUN_URL
            }]
        },
        peerConnectionContraints: {
            optional: [{
                DtlsSrtpKeyAgreement: true
            }, {
                RtpDataChannels: true
            }]
        },
        autoAdjustMic: false,
        media: {
            audio: true,
            video: true
        },
        detectSpeakingEvents: true,
        enableDataChannels: true,
        url: Settings.SERVER_URL

        // adjustPeerVolume: true,
        // peerVolumeWhenSpeaking: 0.25
    }).login(Settings.OID, function(err) {
        if (err) {
            // ログイン失敗
            stateEl.text('ログインに失敗しました。企業IDが見つかりません。');
            return;
        }
        // ログイン成功

        // ルームIDがなければ、招待待ちを行う。
        if (!Settings.RID) {
            stateEl.text('ユーザを待っています…。');
            return;
        }

        stateEl.text('カメラとマイクの許可をしてください。');
        meetup.ready(function(err, sessionId) {
            console.log('ready, sessionId=', sessionId);
            //$('#alert-permit').remove();
            $('#waiting').remove();
            $('#meetup').show();

            // ready
            this.joinRoom(Settings.RID, function(err, roomDescription) {
                console.log('joinRoom', err);
                if (err) {
                    alert(err.message);
                    this.stopLocalVideo();
                    return;
                }
            }).speaking(function(event) {
                $('#localVideo').addClass('speaking');
            }).stoppedSpeaking(function(event) {
                $('#localVideo').removeClass('speaking');
            }).addedPeer(function(peer) {
                Meetup.notify({
                    title: peer.id + 'が会議に参加しました。'
                }).show();
                refreshList(this.members);
            }).removedPeer(function(peer) {
                refreshList(this.members);
            });
        }).denied(function(event) {
            var msg = 'カメラとマイクへのアクセスが許可されていません。\n許可した後、リロードしてください。';
            stateEl.text(msg);

            console.log('deniedTime=', Date.now() - startTime);
        });
    });

    function refreshList(members) {
        var el = $('#list-presence').empty();
        for (var id in members) {
            var member = members[id];

            $('<li/>').text(member.peer.id).appendTo(el);
        }
    }

    // ----------------------------
    // DOM
    // ----------------------------
    var webrtc = meetup.get();

    $('#room-name').text('会議室 - (' + Settings.RID + ')');
    $('#permission-error').text();
    var notifyEl = $('#btn-notify');
    if (Meetup.notify.permission() === 'granted') {
        notifyEl.hide();
    } else if (Meetup.notify.permission() === 'denied') {
        notifyEl.attr('disabled', 'disabled');
    } else {
        notifyEl.click(function(evt) {
            console.log('request notify');
            Notification.requestPermission(function (status) {
                console.log('status', status);

                if (status === 'granted') {
                    // 通知が有効になりました。
                    notifyEl.hide();
                } else if (status === 'denied') {
                    notifyEl.attr('disabled', 'disabled');
                } else {
                    // default
                }
            });
        });
    }

    var isStopping = false;
    $('#localVideo').click(function(e) {
        start();
    });

    function start() {
        if (isStopping) {
            webrtc.startLocalMedia({
                video: true,
                audio: true,
            }, function (err, stream) {
                if (err) {
                    console.log('error!!', err);
                    webrtc.emit(err);
                } else {
                    webrtc.attachMediaStream(stream, webrtc.getLocalVideoContainer(), {
                        muted: true, mirror: true
                    });
                }
            });
        } else {
            webrtc.stopLocalVideo();
        }
    }

    $('#mute').click(function() {
        meetup.mute();
    });
    $('#unmute').click(function() {
        meetup.unmute();
    });
    $('#pause').click(function() {
        meetup.pause();
    });
    $('#resume').click(function() {
        meetup.resume();
    });
    $('#stopVideo').click(function() {
        meetup.stopLocalVideo();
    });
    $('#startVideo').click(function() {
        meetup.startLocalVideo();
    });
    $('#volume').change(function(evt) {
        console.log('volume', evt);
        var volume = $(this).val();
        webrtc.setVolumeForAll(volume);
    }).mouseup(function(evt) {
        console.log('mouseup', evt);
    });

});

<commit_msg>本番サーバURL修正<commit_after>// ----------------------------
// Consts
// ----------------------------

var Queries = (function() {
    var queryStr = window.location.search;
    var result = {};
    if (queryStr.length <= 1) {
        return result;
    }
    var queries = queryStr.substring(1, queryStr.length).split('&');
    for (var i=0; i<queries.length; i++) {
        var query = queries[i].split('=');
        var key = decodeURIComponent(query[0]);
        var value = (query.length === 1) ? null : decodeURIComponent(query[1]);
        result[key] = value;
    }
    return result;
})();
console.log(Queries);
var Settings = {
    isLocal: (function() {
        if (window.location.host.indexOf('192.168.') === 0) {
            return true;
        }
        return false;
    })(),
    OID: Queries.OID || null,
    RID: Queries.RID || null,
};
Settings.STUN_URL = Settings.isLocal ?
    'stun:stun.l.google.com:19302' :
    'stun:stun.synou.com';
Settings.SERVER_URL = Settings.isLocal ?
//    'http://192.168.31.6:8888' :
    'http://192.168.24.74:8888' :
    'http://stun2.synou.com:8888';
console.log('Settings', Settings);

$(function() {
    var startTime = Date.now(); // TEST

    // ----------------------------
    // Libs
    // ----------------------------

    var stateEl = $('#state').empty().text('通話サービスへ接続しています…。');

    var meetup = Meetup.create({
        // the id/element dom element that will hold "our" video
        localVideoEl: 'localVideo',
        // the id/element dom element that will hold remote videos
        remoteVideosEl: 'remoteVideos',
        // immediately ask for camera access. default false
        //autoRequestMedia: true,
        debug: true,
        peerConnectionConfig: {
            iceServers: [{
                "url": Settings.STUN_URL
            }]
        },
        peerConnectionContraints: {
            optional: [{
                DtlsSrtpKeyAgreement: true
            }, {
                RtpDataChannels: true
            }]
        },
        autoAdjustMic: false,
        media: {
            audio: true,
            video: true
        },
        detectSpeakingEvents: true,
        enableDataChannels: true,
        url: Settings.SERVER_URL

        // adjustPeerVolume: true,
        // peerVolumeWhenSpeaking: 0.25
    }).login(Settings.OID, function(err) {
        if (err) {
            // ログイン失敗
            stateEl.text('ログインに失敗しました。企業IDが見つかりません。');
            return;
        }
        // ログイン成功

        // ルームIDがなければ、招待待ちを行う。
        if (!Settings.RID) {
            stateEl.text('ユーザを待っています…。');
            return;
        }

        stateEl.text('カメラとマイクの許可をしてください。');
        meetup.ready(function(err, sessionId) {
            console.log('ready, sessionId=', sessionId);
            //$('#alert-permit').remove();
            $('#waiting').remove();
            $('#meetup').show();

            // ready
            this.joinRoom(Settings.RID, function(err, roomDescription) {
                console.log('joinRoom', err);
                if (err) {
                    alert(err.message);
                    this.stopLocalVideo();
                    return;
                }
            }).speaking(function(event) {
                $('#localVideo').addClass('speaking');
            }).stoppedSpeaking(function(event) {
                $('#localVideo').removeClass('speaking');
            }).addedPeer(function(peer) {
                Meetup.notify({
                    title: peer.id + 'が会議に参加しました。'
                }).show();
                refreshList(this.members);
            }).removedPeer(function(peer) {
                refreshList(this.members);
            });
        }).denied(function(event) {
            var msg = 'カメラとマイクへのアクセスが許可されていません。\n許可した後、リロードしてください。';
            stateEl.text(msg);

            console.log('deniedTime=', Date.now() - startTime);
        });
    });

    function refreshList(members) {
        var el = $('#list-presence').empty();
        for (var id in members) {
            var member = members[id];

            $('<li/>').text(member.peer.id).appendTo(el);
        }
    }

    // ----------------------------
    // DOM
    // ----------------------------
    var webrtc = meetup.get();

    $('#room-name').text('会議室 - (' + Settings.RID + ')');
    $('#permission-error').text();
    var notifyEl = $('#btn-notify');
    if (Meetup.notify.permission() === 'granted') {
        notifyEl.hide();
    } else if (Meetup.notify.permission() === 'denied') {
        notifyEl.attr('disabled', 'disabled');
    } else {
        notifyEl.click(function(evt) {
            console.log('request notify');
            Notification.requestPermission(function (status) {
                console.log('status', status);

                if (status === 'granted') {
                    // 通知が有効になりました。
                    notifyEl.hide();
                } else if (status === 'denied') {
                    notifyEl.attr('disabled', 'disabled');
                } else {
                    // default
                }
            });
        });
    }

    var isStopping = false;
    $('#localVideo').click(function(e) {
        start();
    });

    function start() {
        if (isStopping) {
            webrtc.startLocalMedia({
                video: true,
                audio: true,
            }, function (err, stream) {
                if (err) {
                    console.log('error!!', err);
                    webrtc.emit(err);
                } else {
                    webrtc.attachMediaStream(stream, webrtc.getLocalVideoContainer(), {
                        muted: true, mirror: true
                    });
                }
            });
        } else {
            webrtc.stopLocalVideo();
        }
    }

    $('#mute').click(function() {
        meetup.mute();
    });
    $('#unmute').click(function() {
        meetup.unmute();
    });
    $('#pause').click(function() {
        meetup.pause();
    });
    $('#resume').click(function() {
        meetup.resume();
    });
    $('#stopVideo').click(function() {
        meetup.stopLocalVideo();
    });
    $('#startVideo').click(function() {
        meetup.startLocalVideo();
    });
    $('#volume').change(function(evt) {
        console.log('volume', evt);
        var volume = $(this).val();
        webrtc.setVolumeForAll(volume);
    }).mouseup(function(evt) {
        console.log('mouseup', evt);
    });

});

<|endoftext|>


<commit_before>$(document).ready(function() {
    'use strict';

    var MAX_NAME_LENGTH = 50;
    var BANNER_HEIGHT = 160;

    // Prep templates located in the HTML
    var name_tmpl = $('#name_tmpl').html();
    var progress_tmpl = $('#progress_tmpl').html();
    var progress_container_tmpl = $('#progress_container_tmpl').html();
    var progress_popover_tmpl = $('#progress_popover_tmpl').html();

    // Compile templates for speedup
    Mustache.parse(name_tmpl);
    Mustache.parse(progress_tmpl);
    Mustache.parse(progress_container_tmpl);
    Mustache.parse(progress_popover_tmpl);

    // Handle vertical resizing of the table
    function calcHeight() {
        return $(window).height() - BANNER_HEIGHT;
    }

    $(window).on('resize', function() {
        // The joy of fitting vertically!
        $('.dataTables_scrollBody').height(calcHeight()).css('max-height', 'inherit');
    });

    // Cluster status table.
    var cluster_table = $("#yarn_status").DataTable({
        ajax: YARNITOR_BASE_URL+"/api/cluster",
        paging: false,
        searching: false,
        ordering: false,
        dom: 't',
        columns: [
            {
                data: "totalNodes",
                title: "Nodes",
                render: function(data, type, row) {
                    return (row['activeNodes']) + ' / ' + data;
                }
            },
            {
                data: "totalVirtualCores",
                title: "VCPUs",
                render: function(data, type, row) {
                    return row['availableVirtualCores'] + ' / ' + data;
                }
            },
            {
               data: "totalMB",
               title: "RAM (GB)",
               render: function(data, type, row) {
                    return Math.round(row['availableMB'] / 1024) + ' / ' + Math.round(data / 1024);
               }
            }
        ]
    });

    // Main applications table
    var table = $('#yarn_applications').DataTable({
        ajax: YARNITOR_BASE_URL+"/api/applications",
        rowId: "id",
        scrollX: true,
        scrollY: calcHeight(),
        paging: false,
        colReorder: true,
        stateSave: true,
        order: [[4, 'desc']],
        buttons: [
            {
                extend: 'colvis',
                className: 'btn-sm'
            }
        ],
        language: {
            "search": "",
            "searchPlaceholder": "Filter records",
            "buttons": {
                "colvis": ''
            }
        },
        dom: ("<'row'<'col-xs-8'l><'col-xs-4 dataTables_controls'Bf>>" +
             "<'row'<'col-xs-12'tr>>" +
             "<'row'<'col-xs-6'i><'col-xs-6 dataTables_refreshed'>>"),
        columns: [
            {
                data: "name",
                title: "Name",
                render: function(data, type, row, meta) {
                    if(data.length > MAX_NAME_LENGTH) {
                        data = data.substr(0, MAX_NAME_LENGTH) + '...';
                    }
                    var html = Mustache.render(name_tmpl, {
                        name: data,
                        trackingUrl: row.trackingUrl,
                        id: row.id
                    });
                    return html;
                }
            },
            {data: "user", title: "User"},
            {data: "state", title: "State"},
            {
                title: "Progress",
                render: function(data, type, row, meta) {
                    // progress bars
                    var bar_htmls = row.progress.map(function(progress) {
                        var total = progress.completed + progress.running + progress.failed;
                        total = (progress.total > total) ? progress.total : total;
                        var args = {
                            completed: progress.completed,
                            completed_ratio: progress.completed / progress.total * 100,
                            running: progress.running,
                            running_ratio: progress.running / progress.total * 100,
                            failed: progress.failed,
                            failed_ratio: progress.failed / progress.total * 100,
                            total: progress.total
                        };

                        return Mustache.render(progress_tmpl, args);
                    });

                    return Mustache.render(progress_container_tmpl, {
                        progress_html: bar_htmls.join('\n'),
                        popover_html : Mustache.render(progress_popover_tmpl, row)
                    });
                }
            },
            {data: "allocatedVCores", title: "VCPUs"},
            {
                data: "vcoreSeconds",
                title: "VCPU-Hours",
                render: function(data, type, row, meta) {
                    return (row.vcoreSeconds / 3600).toFixed(2);
                }
            },
            {
                data: "allocatedMB",
                title: "RAM (GB)",
                render: function(data) {
                    return Math.round(data / 1024);
                }
            },
            {
                data: "memorySeconds",
                title: "RAM (GB)-Hours",
                render: function(data, type, row, meta) {
                    return (row.memorySeconds / 1024 / 3600).toFixed(2);
                }
            },
            {
              title: "RAM/VCPU Ratio",
              render: function(data, type, row, meta) {
                return (row.allocatedMB / row.allocatedVCores / 1024).toFixed(2);
              }
            },
            {"data": "applicationType", "title": "Job Type"},
            {"data": "queue", "title": "Queue"},
            {
                "data": "startedTime",
                "type": "date",
                "title": "Local Start Time",
                "render": function(data, type, row, meta) {
                    return (new Date(data)).toLocaleString();
                }
            },
            {
                "data": "startedTime",
                "sortable": false,
                "title": "Uptime",
                "render": function(data, type, row, meta) {
                    return moment.duration(moment.utc() - moment(data)).humanize();
                }
            },
            {"data": "id", "title": "Application ID", "visible": false},
        ]
    });

    var pageScrollPos = 0;

    table.on('search.dt', function() {
        history.replaceState(undefined, undefined, '#'+table.search());
    });

    table.on('draw.dt', function() {
        console.log('yarnitor:draw.dt');
        // Remove shown popovers
        $('.popover').remove();
        $('[data-toggle="popover"]').popover();
        // rescroll
        $('div.dataTables_scrollBody').scrollTop(pageScrollPos);
    });

    table.on('xhr.dt', function() {
        console.log('yarnitor:xhr.dt');
        // destroy the popovers before the draw phase kicks in.
        $('[data-toggle="popover"]').popover("destroy");
        pageScrollPos = $('div.dataTables_scrollBody').scrollTop();
    });

    var reloadDatetime = function() {
        $.get({
            url: YARNITOR_BASE_URL+"/api/status",
            dataType: 'json'
        }).done(function(data) {
            // Show datetime data was last refreshed from the YARN API
            // if that information is available, else leave the display alone
            if(data.refresh_datetime) {
                var d = (new Date(data.refresh_datetime)).toLocaleString();
                $('.dataTables_refreshed').text('Showing data from ' + d);
            }
        });
    }

    setInterval(function() {
        console.log('yarnitor:refresh');
        table.ajax.reload();
        cluster_table.ajax.reload();
        reloadDatetime();
    }, YARNITOR_REFRESH_INTERVAL_S * 1000);

    // Throw exceptions in the console, not in alert dialogs
    $.fn.dataTable.ext.errMode = 'throw';
    // Immediately try to fetch datetime of last data refresh
    reloadDatetime();
    // Set the initial filter text by pulling it from the URL hash
    table.search(window.location.hash.substr(1));

    console.log('yarnitor:dom-ready');
});
<commit_msg>Add title to show/hide columns button<commit_after>$(document).ready(function() {
    'use strict';

    var MAX_NAME_LENGTH = 50;
    var BANNER_HEIGHT = 160;

    // Prep templates located in the HTML
    var name_tmpl = $('#name_tmpl').html();
    var progress_tmpl = $('#progress_tmpl').html();
    var progress_container_tmpl = $('#progress_container_tmpl').html();
    var progress_popover_tmpl = $('#progress_popover_tmpl').html();

    // Compile templates for speedup
    Mustache.parse(name_tmpl);
    Mustache.parse(progress_tmpl);
    Mustache.parse(progress_container_tmpl);
    Mustache.parse(progress_popover_tmpl);

    // Handle vertical resizing of the table
    function calcHeight() {
        return $(window).height() - BANNER_HEIGHT;
    }

    $(window).on('resize', function() {
        // The joy of fitting vertically!
        $('.dataTables_scrollBody').height(calcHeight()).css('max-height', 'inherit');
    });

    // Cluster status table.
    var cluster_table = $("#yarn_status").DataTable({
        ajax: YARNITOR_BASE_URL+"/api/cluster",
        paging: false,
        searching: false,
        ordering: false,
        dom: 't',
        columns: [
            {
                data: "totalNodes",
                title: "Nodes",
                render: function(data, type, row) {
                    return (row['activeNodes']) + ' / ' + data;
                }
            },
            {
                data: "totalVirtualCores",
                title: "VCPUs",
                render: function(data, type, row) {
                    return row['availableVirtualCores'] + ' / ' + data;
                }
            },
            {
               data: "totalMB",
               title: "RAM (GB)",
               render: function(data, type, row) {
                    return Math.round(row['availableMB'] / 1024) + ' / ' + Math.round(data / 1024);
               }
            }
        ]
    });

    // Main applications table
    var table = $('#yarn_applications').DataTable({
        ajax: YARNITOR_BASE_URL+"/api/applications",
        rowId: "id",
        scrollX: true,
        scrollY: calcHeight(),
        paging: false,
        colReorder: true,
        stateSave: true,
        order: [[4, 'desc']],
        buttons: [
            {
                extend: 'colvis',
                className: 'btn-sm'
            }
        ],
        language: {
            "search": "",
            "searchPlaceholder": "Filter records",
            "buttons": {
                "colvis": ''
            }
        },
        dom: ("<'row'<'col-xs-8'l><'col-xs-4 dataTables_controls'Bf>>" +
             "<'row'<'col-xs-12'tr>>" +
             "<'row'<'col-xs-6'i><'col-xs-6 dataTables_refreshed'>>"),
        columns: [
            {
                data: "name",
                title: "Name",
                render: function(data, type, row, meta) {
                    if(data.length > MAX_NAME_LENGTH) {
                        data = data.substr(0, MAX_NAME_LENGTH) + '...';
                    }
                    var html = Mustache.render(name_tmpl, {
                        name: data,
                        trackingUrl: row.trackingUrl,
                        id: row.id
                    });
                    return html;
                }
            },
            {data: "user", title: "User"},
            {data: "state", title: "State"},
            {
                title: "Progress",
                render: function(data, type, row, meta) {
                    // progress bars
                    var bar_htmls = row.progress.map(function(progress) {
                        var total = progress.completed + progress.running + progress.failed;
                        total = (progress.total > total) ? progress.total : total;
                        var args = {
                            completed: progress.completed,
                            completed_ratio: progress.completed / progress.total * 100,
                            running: progress.running,
                            running_ratio: progress.running / progress.total * 100,
                            failed: progress.failed,
                            failed_ratio: progress.failed / progress.total * 100,
                            total: progress.total
                        };

                        return Mustache.render(progress_tmpl, args);
                    });

                    return Mustache.render(progress_container_tmpl, {
                        progress_html: bar_htmls.join('\n'),
                        popover_html : Mustache.render(progress_popover_tmpl, row)
                    });
                }
            },
            {data: "allocatedVCores", title: "VCPUs"},
            {
                data: "vcoreSeconds",
                title: "VCPU-Hours",
                render: function(data, type, row, meta) {
                    return (row.vcoreSeconds / 3600).toFixed(2);
                }
            },
            {
                data: "allocatedMB",
                title: "RAM (GB)",
                render: function(data) {
                    return Math.round(data / 1024);
                }
            },
            {
                data: "memorySeconds",
                title: "RAM (GB)-Hours",
                render: function(data, type, row, meta) {
                    return (row.memorySeconds / 1024 / 3600).toFixed(2);
                }
            },
            {
              title: "RAM/VCPU Ratio",
              render: function(data, type, row, meta) {
                return (row.allocatedMB / row.allocatedVCores / 1024).toFixed(2);
              }
            },
            {"data": "applicationType", "title": "Job Type"},
            {"data": "queue", "title": "Queue"},
            {
                "data": "startedTime",
                "type": "date",
                "title": "Local Start Time",
                "render": function(data, type, row, meta) {
                    return (new Date(data)).toLocaleString();
                }
            },
            {
                "data": "startedTime",
                "sortable": false,
                "title": "Uptime",
                "render": function(data, type, row, meta) {
                    return moment.duration(moment.utc() - moment(data)).humanize();
                }
            },
            {"data": "id", "title": "Application ID", "visible": false},
        ]
    });

    var pageScrollPos = 0;

    table.on('search.dt', function() {
        history.replaceState(undefined, undefined, '#'+table.search());
    });

    table.on('draw.dt', function() {
        console.log('yarnitor:draw.dt');
        // Remove shown popovers
        $('.popover').remove();
        $('[data-toggle="popover"]').popover();
        // rescroll
        $('div.dataTables_scrollBody').scrollTop(pageScrollPos);
    });

    table.on('xhr.dt', function() {
        console.log('yarnitor:xhr.dt');
        // destroy the popovers before the draw phase kicks in.
        $('[data-toggle="popover"]').popover("destroy");
        pageScrollPos = $('div.dataTables_scrollBody').scrollTop();
    });

    var reloadDatetime = function() {
        $.get({
            url: YARNITOR_BASE_URL+"/api/status",
            dataType: 'json'
        }).done(function(data) {
            // Show datetime data was last refreshed from the YARN API
            // if that information is available, else leave the display alone
            if(data.refresh_datetime) {
                var d = (new Date(data.refresh_datetime)).toLocaleString();
                $('.dataTables_refreshed').text('Showing data from ' + d);
            }
        });
    }

    setInterval(function() {
        console.log('yarnitor:refresh');
        table.ajax.reload();
        cluster_table.ajax.reload();
        reloadDatetime();
    }, YARNITOR_REFRESH_INTERVAL_S * 1000);

    // Throw exceptions in the console, not in alert dialogs
    $.fn.dataTable.ext.errMode = 'throw';
    // Immediately try to fetch datetime of last data refresh
    reloadDatetime();
    // Set the initial filter text by pulling it from the URL hash
    table.search(window.location.hash.substr(1));

    console.log('yarnitor:dom-ready');
});
<|endoftext|>