<commit_before>"use strict";

var f = require('util').format
  , Long = require('bson').Long;

exports['Should correctly connect server to single instance'] = {
  metadata: { requires: { topology: "single" } },

  test: function(configuration, test) {
    var Server = require('../../../lib2/topologies/server')
      , bson = require('bson').BSONPure.BSON;

    // Attempt to connect
    var server = new Server({
        host: configuration.host
      , port: configuration.port
      , bson: new bson()
    })

    // Add event listeners
    server.on('connect', function(server) {
      server.destroy();
      test.done();
    });

    // Start connection
    server.connect();
  }
}

exports['Should correctly connect server to single instance and execute ismaster'] = {
  metadata: { requires: { topology: "single" } },

  test: function(configuration, test) {
    var Server = require('../../../lib2/topologies/server')
      , bson = require('bson').BSONPure.BSON;

    // Attempt to connect
    var server = new Server({
        host: configuration.host
      , port: configuration.port
      , bson: new bson()
    })

    // Add event listeners
    server.on('connect', function(server) {
      server.command('admin.$cmd', {ismaster:true}, function(err, r) {
        test.equal(null, err);
        test.equal(true, r.result.ismaster);
        test.ok(r.connection != null)

        server.destroy();
        test.done();
      });
    });

    // Start connection
    server.connect();
  }
}

exports['Should correctly connect server to single instance and execute ismaster returning raw'] = {
  metadata: { requires: { topology: "single" } },

  test: function(configuration, test) {
    var Server = require('../../../lib2/topologies/server')
      , bson = require('bson').BSONPure.BSON;

    // Attempt to connect
    var server = new Server({
        host: configuration.host
      , port: configuration.port
      , bson: new bson()
    })

    // Add event listeners
    server.on('connect', function(server) {
      server.command('admin.$cmd', {ismaster:true}, {
        raw: true
      }, function(err, r) {
        test.equal(null, err);
        test.ok(r.result instanceof Buffer);
        test.ok(r.connection != null)

        server.destroy();
        test.done();
      });
    });

    // Start connection
    server.connect();
  }
}

exports['Should correctly connect server to single instance and execute insert'] = {
  metadata: { requires: { topology: "single" } },

  test: function(configuration, test) {
    var Server = require('../../../lib2/topologies/server')
      , bson = require('bson').BSONPure.BSON;

    // Attempt to connect
    var server = new Server({
        host: configuration.host
      , port: configuration.port
      , bson: new bson()
    })

    // Add event listeners
    server.on('connect', function(server) {
      server.insert('integration_tests.inserts', {a:1}, function(err, r) {
        test.equal(null, err);
        test.equal(1, r.result.n);

        server.insert('integration_tests.inserts', {a:1}, {ordered:false}, function(err, r) {
          test.equal(null, err);
          test.equal(1, r.result.n);

          server.destroy();
          test.done();
        });
      });
    });

    // Start connection
    server.connect();
  }
}

exports['Should correctly connect server to single instance and execute bulk insert'] = {
  metadata: { requires: { topology: "single" } },

  test: function(configuration, test) {
    var Server = require('../../../lib2/topologies/server')
      , bson = require('bson').BSONPure.BSON;

    // Attempt to connect
    var server = new Server({
        host: configuration.host
      , port: configuration.port
      , bson: new bson()
    })

    // Add event listeners
    server.on('connect', function(server) {
      server.insert('integration_tests.inserts', [{a:1}, {b:1}], function(err, r) {
        test.equal(null, err);
        test.equal(2, r.result.n);

        server.insert('integration_tests.inserts', [{a:1}, {b:1}], {ordered:false}, function(err, r) {
          test.equal(null, err);
          test.equal(2, r.result.n);

          server.destroy();
          test.done();
        });
      });
    });

    // Start connection
    server.connect();
  }
}

exports['Should correctly connect server to single instance and execute insert with w:0'] = {
  metadata: { requires: { topology: "single" } },

  test: function(configuration, test) {
    var Server = require('../../../lib2/topologies/server')
      , bson = require('bson').BSONPure.BSON;

    // Attempt to connect
    var server = new Server({
        host: configuration.host
      , port: configuration.port
      , bson: new bson()
    })

    // Add event listeners
    server.on('connect', function(server) {
      server.insert('integration_tests.inserts', {a:1}, {writeConcern: {w:0}}, function(err, r) {
        test.equal(null, err);
        test.equal(1, r.result.ok);

        server.insert('integration_tests.inserts', {a:1}, {ordered:false, writeConcern: {w:0}}, function(err, r) {
          test.equal(null, err);
          test.equal(1, r.result.ok);

          server.destroy();
          test.done();
        });
      });
    });

    // Start connection
    server.connect();
  }
}

exports['Should correctly connect server to single instance and execute update'] = {
  metadata: { requires: { topology: "single" } },

  test: function(configuration, test) {
    var Server = require('../../../lib2/topologies/server')
      , bson = require('bson').BSONPure.BSON;

    // Attempt to connect
    var server = new Server({
        host: configuration.host
      , port: configuration.port
      , bson: new bson()
    })

    // Add event listeners
    server.on('connect', function(_server) {
      _server.update('integration_tests.inserts_example2', [{
        q: {a: 1}, u: {'$set': {b:1}}, upsert:true
      }], {
        writeConcern: {w:1}, ordered:true
      }, function(err, results) {
        test.equal(null, err);
        test.equal(1, results.result.n);

        _server.destroy();
        test.done();
      });
    });

    // Start connection
    server.connect();
  }
}

exports['Should correctly connect server to single instance and execute remove'] = {
  metadata: { requires: { topology: "single" } },

  test: function(configuration, test) {
    var Server = require('../../../lib2/topologies/server')
      , bson = require('bson').BSONPure.BSON;

    // Attempt to connect
    var server = new Server({
        host: configuration.host
      , port: configuration.port
      , bson: new bson()
    })

    // Add event listeners
    server.on('connect', function(_server) {
      server.insert('integration_tests.remove_example', {a:1}, function(err, r) {
        test.equal(null, err);
        test.equal(true, r.result.ok);

        _server.remove('integration_tests.remove_example', [{q: {a:1}, limit:1}], {
          writeConcern: {w:1}, ordered:true
        }, function(err, results) {
          test.equal(null, err);
          test.equal(1, results.result.n);

          _server.destroy();
          test.done();
        });
      });
    });

    // Start connection
    server.connect();
  }
}

/**
 * @ignore
 */
exports['Should correctly recover with multiple restarts'] = {
  metadata: { requires: { topology: ['single'] } },

  // The actual test we wish to run
  test: function(configuration, test) {
    var Server = require('../../../lib2/topologies/server')
      , bson = require('bson').BSONPure.BSON;

    var done = false;

    // Attempt to connect
    var server = new Server({
        host: configuration.host
      , port: configuration.port
      , bson: new bson()
    })

    // Add event listeners
    server.on('connect', function(_server) {
      var count = 1;
      var allDone = 0;
      var ns = "integration_tests.t";

      var execute = function() {
        if(!done) {
          server.insert(ns, {a:1, count: count}, function(err, r) {
            count = count + 1;

            // Execute find
            var cursor = _server.cursor(ns, {
              find: ns, query: {}, batchSize: 2
            });

            // Execute next
            cursor.next(function(err, d) {
              setTimeout(execute, 500);
            });
          })
        } else {
          server.insert(ns, {a:1, count: count}, function(err, r) {
            test.equal(null, err);

            // Execute find
            var cursor = _server.cursor(ns, {
              find: ns, query: {}, batchSize: 2
            });

            // Execute next
            cursor.next(function(err, d) {
              test.equal(null, err);
              server.destroy();
              test.done();
            });
          })
        }
      }

      setTimeout(execute, 500);
    });

    var count = 2

    var restartServer = function() {
      if(count == 0) {
        done = true;
        return;
      }

      count = count - 1;

      configuration.manager.stop().then(function() {
        setTimeout(function() {
          configuration.manager.start().then(function() {
            setTimeout(restartServer, 1000);
          });
        }, 2000);
      });
    }

    setTimeout(restartServer, 1000);
    server.connect();
  }
}

exports['Should correctly reconnect to server with automatic reconnect enabled'] = {
  metadata: {
    requires: {
      topology: "single"
    },
    // ignore: { travis:true }
  },

  test: function(configuration, test) {
    var Server = configuration.require.Server
      , ReadPreference = configuration.require.ReadPreference;

    // Attempt to connect
    var server = new Server({
        host: configuration.host
      , port: configuration.port
      , reconnect: true
      , reconnectInterval: 50
    })

    // Test flags
    var emittedClose = false;

    // Add event listeners
    server.on('connect', function(_server) {
      // Execute the command
      _server.command("system.$cmd", {ismaster: true}, {readPreference: new ReadPreference('primary')}, function(err, result) {
        test.equal(null, err)
        _server.s.currentReconnectRetry = 10;

        // Write garbage, force socket closure
        try {
          var a = new Buffer(100);
          for(var i = 0; i < 100; i++) a[i] = i;
          result.connection.write(a);
        } catch(err) {}

        // Ensure the server died
        setTimeout(function() {
          // Attempt a proper command
          _server.command("system.$cmd", {ismaster: true}, {readPreference: new ReadPreference('primary')}, function(err, result) {
            test.ok(err != null);
          });
        }, 100);
      });
    });

    server.once('close', function() {
      emittedClose = true;
    });

    server.once('reconnect', function() {
      // console.log('!!!!!!!!!!! reconnect')
      test.equal(true, emittedClose);
      test.equal(true, server.isConnected());
      test.equal(30, server.s.pool.retriesLeft);
      server.destroy();
      test.done();
    });

    // Start connection
    server.connect();
  }
}

exports['Should correctly reconnect to server with automatic reconnect disabled'] = {
  metadata: {
    requires: {
      topology: "single"
    },
    // ignore: { travis:true }
  },

  test: function(configuration, test) {
    var Server = configuration.require.Server
      , ReadPreference = configuration.require.ReadPreference;

    // Attempt to connect
    var server = new Server({
        host: configuration.host
      , port: configuration.port
      , reconnect: false
      , size: 1
    })

    // Test flags
    var emittedClose = false;
    var emittedError = false;

    // Add event listeners
    server.on('connect', function(_server) {
      // Execute the command
      _server.command("system.$cmd", {ismaster: true}, {readPreference: new ReadPreference('primary')}, function(err, result) {
        test.equal(null, err)
        // Write garbage, force socket closure
        try {
          result.connection.destroy();
        } catch(err) {}

        process.nextTick(function() {
          // Attempt a proper command
          _server.command("system.$cmd", {ismaster: true}, {readPreference: new ReadPreference('primary')}, function(err, result) {
            test.ok(err != null);
          });
        });
      });
    });

    server.on('close', function() {
      emittedClose = true;
    });

    server.on('error', function() {
      emittedError = true;
    });

    setTimeout(function() {
      test.equal(true, emittedClose);
      test.equal(false, server.isConnected());
      server.destroy();
      test.done();
    }, 500);

    // Start connection
    server.connect();
  }
}

exports['Should reconnect when initial connection failed'] = {
  metadata: {
    requires: {
      topology: 'single'
    },
    // ignore: { travis:true }
  },

  test: function(configuration, test) {
    var Server = configuration.require.Server
      , ReadPreference = configuration.require.ReadPreference
      , manager = configuration.manager;

    manager.stop('SIGINT').then(function() {
      // Attempt to connect while server is down
      var server = new Server({
          host: configuration.host
        , port: configuration.port
        , reconnect: true
        , reconnectTries: 2
        , size: 1
        , emitError: true
      });

      var errors = [];

      server.on('connect', function() {
        test.done();
        server.destroy();
      });

      server.on('reconnect', function() {
        test.done();
        server.destroy();
      });

      server.on('error', function(err) {
        test.ok(err);
        test.ok(err.message.indexOf('failed to') != -1);
        manager.start().then(function() {});
      });

      server.connect();
    })
  }
}

exports['Should correctly place new connections in available list on reconnect'] = {
  metadata: {
    requires: {
      topology: "single"
    },
    // ignore: { travis:true }
  },

  test: function(configuration, test) {
    var Server = configuration.require.Server
      , ReadPreference = configuration.require.ReadPreference;

    // Attempt to connect
    var server = new Server({
        host: configuration.host
      , port: configuration.port
      , reconnect: true
      , reconnectInterval: 50
    })

    // Test flags
    var emittedClose = false;

    // Add event listeners
    server.on('connect', function(_server) {
      // Execute the command
      _server.command("system.$cmd", {ismaster: true}, {readPreference: new ReadPreference('primary')}, function(err, result) {
        test.equal(null, err)
        _server.s.currentReconnectRetry = 10;

        // Write garbage, force socket closure
        try {
          var a = new Buffer(100);
          for(var i = 0; i < 100; i++) a[i] = i;
          result.connection.write(a);
        } catch(err) {}
      });
    });

    server.once('close', function() {
      emittedClose = true;
    });

    server.once('reconnect', function() {
      for(var i = 0; i < 100; i++) {
        server.command("system.$cmd", {ismaster: true}, function(err, result) {
          test.equal(null, err);
        });
      }

      server.command("system.$cmd", {ismaster: true}, function(err, result) {
        test.equal(null, err);

        setTimeout(function() {
          test.ok(server.s.pool.availableConnections.length > 0);
          test.equal(0, server.s.pool.inUseConnections.length);
          test.equal(0, server.s.pool.connectingConnections.length);

          server.destroy();
          test.done();
        }, 1000);
      });
    });

    // Start connection
    server.connect();
  }
}
<commit_msg>disabled test on travis<commit_after>"use strict";

var f = require('util').format
  , Long = require('bson').Long;

exports['Should correctly connect server to single instance'] = {
  metadata: { requires: { topology: "single" } },

  test: function(configuration, test) {
    var Server = require('../../../lib2/topologies/server')
      , bson = require('bson').BSONPure.BSON;

    // Attempt to connect
    var server = new Server({
        host: configuration.host
      , port: configuration.port
      , bson: new bson()
    })

    // Add event listeners
    server.on('connect', function(server) {
      server.destroy();
      test.done();
    });

    // Start connection
    server.connect();
  }
}

exports['Should correctly connect server to single instance and execute ismaster'] = {
  metadata: { requires: { topology: "single" } },

  test: function(configuration, test) {
    var Server = require('../../../lib2/topologies/server')
      , bson = require('bson').BSONPure.BSON;

    // Attempt to connect
    var server = new Server({
        host: configuration.host
      , port: configuration.port
      , bson: new bson()
    })

    // Add event listeners
    server.on('connect', function(server) {
      server.command('admin.$cmd', {ismaster:true}, function(err, r) {
        test.equal(null, err);
        test.equal(true, r.result.ismaster);
        test.ok(r.connection != null)

        server.destroy();
        test.done();
      });
    });

    // Start connection
    server.connect();
  }
}

exports['Should correctly connect server to single instance and execute ismaster returning raw'] = {
  metadata: { requires: { topology: "single" } },

  test: function(configuration, test) {
    var Server = require('../../../lib2/topologies/server')
      , bson = require('bson').BSONPure.BSON;

    // Attempt to connect
    var server = new Server({
        host: configuration.host
      , port: configuration.port
      , bson: new bson()
    })

    // Add event listeners
    server.on('connect', function(server) {
      server.command('admin.$cmd', {ismaster:true}, {
        raw: true
      }, function(err, r) {
        test.equal(null, err);
        test.ok(r.result instanceof Buffer);
        test.ok(r.connection != null)

        server.destroy();
        test.done();
      });
    });

    // Start connection
    server.connect();
  }
}

exports['Should correctly connect server to single instance and execute insert'] = {
  metadata: { requires: { topology: "single" } },

  test: function(configuration, test) {
    var Server = require('../../../lib2/topologies/server')
      , bson = require('bson').BSONPure.BSON;

    // Attempt to connect
    var server = new Server({
        host: configuration.host
      , port: configuration.port
      , bson: new bson()
    })

    // Add event listeners
    server.on('connect', function(server) {
      server.insert('integration_tests.inserts', {a:1}, function(err, r) {
        test.equal(null, err);
        test.equal(1, r.result.n);

        server.insert('integration_tests.inserts', {a:1}, {ordered:false}, function(err, r) {
          test.equal(null, err);
          test.equal(1, r.result.n);

          server.destroy();
          test.done();
        });
      });
    });

    // Start connection
    server.connect();
  }
}

exports['Should correctly connect server to single instance and execute bulk insert'] = {
  metadata: { requires: { topology: "single" } },

  test: function(configuration, test) {
    var Server = require('../../../lib2/topologies/server')
      , bson = require('bson').BSONPure.BSON;

    // Attempt to connect
    var server = new Server({
        host: configuration.host
      , port: configuration.port
      , bson: new bson()
    })

    // Add event listeners
    server.on('connect', function(server) {
      server.insert('integration_tests.inserts', [{a:1}, {b:1}], function(err, r) {
        test.equal(null, err);
        test.equal(2, r.result.n);

        server.insert('integration_tests.inserts', [{a:1}, {b:1}], {ordered:false}, function(err, r) {
          test.equal(null, err);
          test.equal(2, r.result.n);

          server.destroy();
          test.done();
        });
      });
    });

    // Start connection
    server.connect();
  }
}

exports['Should correctly connect server to single instance and execute insert with w:0'] = {
  metadata: { requires: { topology: "single" } },

  test: function(configuration, test) {
    var Server = require('../../../lib2/topologies/server')
      , bson = require('bson').BSONPure.BSON;

    // Attempt to connect
    var server = new Server({
        host: configuration.host
      , port: configuration.port
      , bson: new bson()
    })

    // Add event listeners
    server.on('connect', function(server) {
      server.insert('integration_tests.inserts', {a:1}, {writeConcern: {w:0}}, function(err, r) {
        test.equal(null, err);
        test.equal(1, r.result.ok);

        server.insert('integration_tests.inserts', {a:1}, {ordered:false, writeConcern: {w:0}}, function(err, r) {
          test.equal(null, err);
          test.equal(1, r.result.ok);

          server.destroy();
          test.done();
        });
      });
    });

    // Start connection
    server.connect();
  }
}

exports['Should correctly connect server to single instance and execute update'] = {
  metadata: { requires: { topology: "single" } },

  test: function(configuration, test) {
    var Server = require('../../../lib2/topologies/server')
      , bson = require('bson').BSONPure.BSON;

    // Attempt to connect
    var server = new Server({
        host: configuration.host
      , port: configuration.port
      , bson: new bson()
    })

    // Add event listeners
    server.on('connect', function(_server) {
      _server.update('integration_tests.inserts_example2', [{
        q: {a: 1}, u: {'$set': {b:1}}, upsert:true
      }], {
        writeConcern: {w:1}, ordered:true
      }, function(err, results) {
        test.equal(null, err);
        test.equal(1, results.result.n);

        _server.destroy();
        test.done();
      });
    });

    // Start connection
    server.connect();
  }
}

exports['Should correctly connect server to single instance and execute remove'] = {
  metadata: { requires: { topology: "single" } },

  test: function(configuration, test) {
    var Server = require('../../../lib2/topologies/server')
      , bson = require('bson').BSONPure.BSON;

    // Attempt to connect
    var server = new Server({
        host: configuration.host
      , port: configuration.port
      , bson: new bson()
    })

    // Add event listeners
    server.on('connect', function(_server) {
      server.insert('integration_tests.remove_example', {a:1}, function(err, r) {
        test.equal(null, err);
        test.equal(true, r.result.ok);

        _server.remove('integration_tests.remove_example', [{q: {a:1}, limit:1}], {
          writeConcern: {w:1}, ordered:true
        }, function(err, results) {
          test.equal(null, err);
          test.equal(1, results.result.n);

          _server.destroy();
          test.done();
        });
      });
    });

    // Start connection
    server.connect();
  }
}

/**
 * @ignore
 */
exports['Should correctly recover with multiple restarts'] = {
  metadata: {
    requires: { topology: ['single'] },
    ignore: { travis: true }
  },

  // The actual test we wish to run
  test: function(configuration, test) {
    var Server = require('../../../lib2/topologies/server')
      , bson = require('bson').BSONPure.BSON;

    var done = false;

    // Attempt to connect
    var server = new Server({
        host: configuration.host
      , port: configuration.port
      , bson: new bson()
    })

    // Add event listeners
    server.on('connect', function(_server) {
      var count = 1;
      var allDone = 0;
      var ns = "integration_tests.t";

      var execute = function() {
        if(!done) {
          server.insert(ns, {a:1, count: count}, function(err, r) {
            count = count + 1;

            // Execute find
            var cursor = _server.cursor(ns, {
              find: ns, query: {}, batchSize: 2
            });

            // Execute next
            cursor.next(function(err, d) {
              setTimeout(execute, 500);
            });
          })
        } else {
          server.insert(ns, {a:1, count: count}, function(err, r) {
            test.equal(null, err);

            // Execute find
            var cursor = _server.cursor(ns, {
              find: ns, query: {}, batchSize: 2
            });

            // Execute next
            cursor.next(function(err, d) {
              test.equal(null, err);
              server.destroy();
              test.done();
            });
          })
        }
      }

      setTimeout(execute, 500);
    });

    var count = 2

    var restartServer = function() {
      if(count == 0) {
        done = true;
        return;
      }

      count = count - 1;

      configuration.manager.stop().then(function() {
        setTimeout(function() {
          configuration.manager.start().then(function() {
            setTimeout(restartServer, 1000);
          });
        }, 2000);
      });
    }

    setTimeout(restartServer, 1000);
    server.connect();
  }
}

exports['Should correctly reconnect to server with automatic reconnect enabled'] = {
  metadata: {
    requires: {
      topology: "single"
    },
    // ignore: { travis:true }
  },

  test: function(configuration, test) {
    var Server = configuration.require.Server
      , ReadPreference = configuration.require.ReadPreference;

    // Attempt to connect
    var server = new Server({
        host: configuration.host
      , port: configuration.port
      , reconnect: true
      , reconnectInterval: 50
    })

    // Test flags
    var emittedClose = false;

    // Add event listeners
    server.on('connect', function(_server) {
      // Execute the command
      _server.command("system.$cmd", {ismaster: true}, {readPreference: new ReadPreference('primary')}, function(err, result) {
        test.equal(null, err)
        _server.s.currentReconnectRetry = 10;

        // Write garbage, force socket closure
        try {
          var a = new Buffer(100);
          for(var i = 0; i < 100; i++) a[i] = i;
          result.connection.write(a);
        } catch(err) {}

        // Ensure the server died
        setTimeout(function() {
          // Attempt a proper command
          _server.command("system.$cmd", {ismaster: true}, {readPreference: new ReadPreference('primary')}, function(err, result) {
            test.ok(err != null);
          });
        }, 100);
      });
    });

    server.once('close', function() {
      emittedClose = true;
    });

    server.once('reconnect', function() {
      // console.log('!!!!!!!!!!! reconnect')
      test.equal(true, emittedClose);
      test.equal(true, server.isConnected());
      test.equal(30, server.s.pool.retriesLeft);
      server.destroy();
      test.done();
    });

    // Start connection
    server.connect();
  }
}

exports['Should correctly reconnect to server with automatic reconnect disabled'] = {
  metadata: {
    requires: {
      topology: "single"
    },
    // ignore: { travis:true }
  },

  test: function(configuration, test) {
    var Server = configuration.require.Server
      , ReadPreference = configuration.require.ReadPreference;

    // Attempt to connect
    var server = new Server({
        host: configuration.host
      , port: configuration.port
      , reconnect: false
      , size: 1
    })

    // Test flags
    var emittedClose = false;
    var emittedError = false;

    // Add event listeners
    server.on('connect', function(_server) {
      // Execute the command
      _server.command("system.$cmd", {ismaster: true}, {readPreference: new ReadPreference('primary')}, function(err, result) {
        test.equal(null, err)
        // Write garbage, force socket closure
        try {
          result.connection.destroy();
        } catch(err) {}

        process.nextTick(function() {
          // Attempt a proper command
          _server.command("system.$cmd", {ismaster: true}, {readPreference: new ReadPreference('primary')}, function(err, result) {
            test.ok(err != null);
          });
        });
      });
    });

    server.on('close', function() {
      emittedClose = true;
    });

    server.on('error', function() {
      emittedError = true;
    });

    setTimeout(function() {
      test.equal(true, emittedClose);
      test.equal(false, server.isConnected());
      server.destroy();
      test.done();
    }, 500);

    // Start connection
    server.connect();
  }
}

exports['Should reconnect when initial connection failed'] = {
  metadata: {
    requires: {
      topology: 'single'
    },
    // ignore: { travis:true }
  },

  test: function(configuration, test) {
    var Server = configuration.require.Server
      , ReadPreference = configuration.require.ReadPreference
      , manager = configuration.manager;

    manager.stop('SIGINT').then(function() {
      // Attempt to connect while server is down
      var server = new Server({
          host: configuration.host
        , port: configuration.port
        , reconnect: true
        , reconnectTries: 2
        , size: 1
        , emitError: true
      });

      var errors = [];

      server.on('connect', function() {
        test.done();
        server.destroy();
      });

      server.on('reconnect', function() {
        test.done();
        server.destroy();
      });

      server.on('error', function(err) {
        test.ok(err);
        test.ok(err.message.indexOf('failed to') != -1);
        manager.start().then(function() {});
      });

      server.connect();
    })
  }
}

exports['Should correctly place new connections in available list on reconnect'] = {
  metadata: {
    requires: {
      topology: "single"
    },
    // ignore: { travis:true }
  },

  test: function(configuration, test) {
    var Server = configuration.require.Server
      , ReadPreference = configuration.require.ReadPreference;

    // Attempt to connect
    var server = new Server({
        host: configuration.host
      , port: configuration.port
      , reconnect: true
      , reconnectInterval: 50
    })

    // Test flags
    var emittedClose = false;

    // Add event listeners
    server.on('connect', function(_server) {
      // Execute the command
      _server.command("system.$cmd", {ismaster: true}, {readPreference: new ReadPreference('primary')}, function(err, result) {
        test.equal(null, err)
        _server.s.currentReconnectRetry = 10;

        // Write garbage, force socket closure
        try {
          var a = new Buffer(100);
          for(var i = 0; i < 100; i++) a[i] = i;
          result.connection.write(a);
        } catch(err) {}
      });
    });

    server.once('close', function() {
      emittedClose = true;
    });

    server.once('reconnect', function() {
      for(var i = 0; i < 100; i++) {
        server.command("system.$cmd", {ismaster: true}, function(err, result) {
          test.equal(null, err);
        });
      }

      server.command("system.$cmd", {ismaster: true}, function(err, result) {
        test.equal(null, err);

        setTimeout(function() {
          test.ok(server.s.pool.availableConnections.length > 0);
          test.equal(0, server.s.pool.inUseConnections.length);
          test.equal(0, server.s.pool.connectingConnections.length);

          server.destroy();
          test.done();
        }, 1000);
      });
    });

    // Start connection
    server.connect();
  }
}
<|endoftext|>


<commit_before>import config from 'config';
import Promise from 'bluebird';
import moment from 'moment-timezone';
import _ from 'lodash';
import models from '../../server/models';
import activities from '../../server/constants/activities';
import slackLib from '../../server/lib/slack';
import expenseStatus from '../../server/constants/expense_status';
onlyExecuteInProdOnMondays();

const {
  Activity,
  Expense,
  Group,
  Transaction
} = models;

const createdLastWeek = getTimeFrame('createdAt');
const updatedLastWeek = getTimeFrame('updatedAt');

const donation = { where: { DonationId: { $not: null } } };

const pendingExpense = { where: { status: expenseStatus.PENDING } };
const approvedExpense = { where: { status: expenseStatus.APPROVED } };
const rejectedExpense = { where: { status: expenseStatus.REJECTED } };
const paidExpense = { where : { status: expenseStatus.PAID } };

const excludeOcTeam = { where: {
  UserId: {
    $notIn: [
      2,  // xdamman
      8,  // aseem
      30, // pmancini
      40, // opencollective
      41, // asood123
    ]
  },
  GroupId: {
    $not: 1 // OpenCollective group
  }
} };

const lastWeekDonations = _.merge({}, createdLastWeek, donation, excludeOcTeam);
const lastWeekExpenses = _.merge({}, updatedLastWeek, excludeOcTeam);

const pendingLastWeekExpenses = _.merge({}, lastWeekExpenses, pendingExpense);
const approvedLastWeekExpenses = _.merge({}, lastWeekExpenses, approvedExpense);
const rejectedLastWeekExpenses = _.merge({}, lastWeekExpenses, rejectedExpense);
const paidLastWeekExpenses = _.merge({}, lastWeekExpenses, paidExpense);

const groupByCurrency = {
  plain: false,
  group: ['currency'],
  attributes: ['currency'],
  order: ['currency']
};

const stripeReceived = { where: { type: activities.WEBHOOK_STRIPE_RECEIVED } };
const paypalReceived = { where: { type: activities.WEBHOOK_PAYPAL_RECEIVED } };

const distinct = {
  plain: false,
  distinct: true
};

Promise.props({

  // Donation statistics

  donationCount: Transaction.count(lastWeekDonations),

  donationAmount: Transaction
    .aggregate('amount', 'SUM', _.merge({}, lastWeekDonations, groupByCurrency))
    .map(row => `${row.SUM/100} ${row.currency}`),

  stripeReceivedCount: Activity.count(_.merge({}, createdLastWeek, stripeReceived)),

  paypalReceivedCount: Activity.count(_.merge({}, createdLastWeek, paypalReceived)),

  // Expense statistics

  pendingExpenseCount: Expense.count(pendingLastWeekExpenses),

  approvedExpenseCount: Expense.count(approvedLastWeekExpenses),

  rejectedExpenseCount: Expense.count(rejectedLastWeekExpenses),

  paidExpenseCount: Expense.count(paidLastWeekExpenses),

  pendingExpenseAmount: Expense
    .aggregate('amount', 'SUM', _.merge({}, pendingLastWeekExpenses, groupByCurrency))
    .map(row => `${-row.SUM/100} ${row.currency}`),

  approvedExpenseAmount: Expense
    .aggregate('amount', 'SUM', _.merge({}, approvedLastWeekExpenses, groupByCurrency))
    .map(row => `${-row.SUM/100} ${row.currency}`),

  rejectedExpenseAmount: Expense
    .aggregate('amount', 'SUM', _.merge({}, rejectedLastWeekExpenses, groupByCurrency))
    .map(row => `${-row.SUM/100} ${row.currency}`),

  paidExpenseAmount: Expense
    .aggregate('amount', 'SUM', _.merge({}, paidLastWeekExpenses, groupByCurrency))
    .map(row => `${-row.SUM/100} ${row.currency}`),

  // Collective statistics

  activeCollectivesWithTransactions: Transaction
    .findAll(_.merge({attributes: ['GroupId'] }, updatedLastWeek, distinct, excludeOcTeam))
    .map(row => row.GroupId),

  activeCollectivesWithExpenses: Expense
    .findAll(_.merge({attributes: ['GroupId'] }, updatedLastWeek, distinct, excludeOcTeam))
    .map(row => row.GroupId),

  newCollectives: Group
    .findAll(_.merge({}, { attributes: ['slug']}, createdLastWeek))
    .map(group => group.dataValues.slug)

}).then(results => {
  results.activeCollectiveCount = _.union(results.activeCollectivesWithTransactions, results.activeCollectivesWithExpenses).length
  const report = reportString(results);
  console.log(report);
  return slackLib.postMessage(report, config.slack.webhookUrl, { channel: config.slack.privateActivityChannel });
}).then(() => {
  console.log('Weekly reporting done!');
  process.exit();
}).catch(err => {
  console.log('err', err);
  process.exit();
});

/**
 * Heroku scheduler only has daily or hourly cron jobs, we only want to run
 * this script once per week on Monday (1). If the day is not Monday on production
 * we won't execute the script
 */
function onlyExecuteInProdOnMondays() {
  const today = new Date();
  if (process.env.NODE_ENV === 'production' && today.getDay() !== 1) {
    console.log('NODE_ENV is production and day is not Monday, script aborted!');
    process.exit();
  }
}

function getTimeFrame(propName) {
  const thisWeekStartRaw = moment()
    .tz('America/New_York')
    .startOf('isoWeek')
    .add(9, 'hours');
  const thisWeekStart = thisWeekStartRaw.format();
  const lastWeekStart = thisWeekStartRaw.subtract(1, 'week').format();

  return {
    where: {
      [propName]: {
        $gt: lastWeekStart,
        $lt: thisWeekStart
      }
    }
  };
}

function reportString(results) {
  return `Weekly activity summary (excluding OC team):
\`\`\`
* Donations:
  - ${results.donationCount} donations received${displayTotals(results.donationAmount)}
  - ${results.stripeReceivedCount} donations received via Stripe Webhook (only recurring)
  - ${results.paypalReceivedCount} donations received via PayPal
* Expenses:
  - ${results.pendingExpenseCount} pending expenses${displayTotals(results.pendingExpenseAmount)}
  - ${results.approvedExpenseCount} approved expenses${displayTotals(results.approvedExpenseAmount)}
  - ${results.rejectedExpenseCount} rejected expenses${displayTotals(results.rejectedExpenseAmount)}
  - ${results.paidExpenseCount} paid expenses${displayTotals(results.paidExpenseAmount)}
* Collectives:
  - ${results.activeCollectiveCount} active collectives
  - ${results.newCollectives.length} new collectives${displayCollectives(results.newCollectives)}
\`\`\``;
}

function displayTotals(totals) {
  if (totals.length > 0) {
    return ` totaling:\n    * ${totals.join('\n    * ').trim()}`;
  }
  return "";
}

function displayCollectives(collectives) {
  if (collectives.length > 0) {
    return `:\n    * ${collectives.join('\n    * ').trim()}`;
  }
  return "";
}
<commit_msg>only include transactions that are real donations<commit_after>import config from 'config';
import Promise from 'bluebird';
import moment from 'moment-timezone';
import _ from 'lodash';
import models from '../../server/models';
import activities from '../../server/constants/activities';
import slackLib from '../../server/lib/slack';
import expenseStatus from '../../server/constants/expense_status';
onlyExecuteInProdOnMondays();

const {
  Activity,
  Expense,
  Group,
  Transaction
} = models;

const createdLastWeek = getTimeFrame('createdAt');
const updatedLastWeek = getTimeFrame('updatedAt');

const donation = {
  where: {
    DonationId: {
      $not: null
    },
    platformFeeInTxnCurrency: {
      $gt: 0
    }
  }
};

const pendingExpense = { where: { status: expenseStatus.PENDING } };
const approvedExpense = { where: { status: expenseStatus.APPROVED } };
const rejectedExpense = { where: { status: expenseStatus.REJECTED } };
const paidExpense = { where : { status: expenseStatus.PAID } };

const excludeOcTeam = { where: {
  UserId: {
    $notIn: [
      2,  // xdamman
      8,  // aseem
      30, // pmancini
      40, // opencollective
      41, // asood123
    ]
  },
  GroupId: {
    $not: 1 // OpenCollective group
  }
} };

const lastWeekDonations = _.merge({}, createdLastWeek, donation, excludeOcTeam);
const lastWeekExpenses = _.merge({}, updatedLastWeek, excludeOcTeam);

const pendingLastWeekExpenses = _.merge({}, lastWeekExpenses, pendingExpense);
const approvedLastWeekExpenses = _.merge({}, lastWeekExpenses, approvedExpense);
const rejectedLastWeekExpenses = _.merge({}, lastWeekExpenses, rejectedExpense);
const paidLastWeekExpenses = _.merge({}, lastWeekExpenses, paidExpense);

const groupByCurrency = {
  plain: false,
  group: ['currency'],
  attributes: ['currency'],
  order: ['currency']
};

const stripeReceived = { where: { type: activities.WEBHOOK_STRIPE_RECEIVED } };
const paypalReceived = { where: { type: activities.WEBHOOK_PAYPAL_RECEIVED } };

const distinct = {
  plain: false,
  distinct: true
};

Promise.props({

  // Donation statistics

  donationCount: Transaction.count(lastWeekDonations),

  donationAmount: Transaction
    .aggregate('amount', 'SUM', _.merge({}, lastWeekDonations, groupByCurrency))
    .map(row => `${row.SUM/100} ${row.currency}`),

  stripeReceivedCount: Activity.count(_.merge({}, createdLastWeek, stripeReceived)),

  paypalReceivedCount: Activity.count(_.merge({}, createdLastWeek, paypalReceived)),

  // Expense statistics

  pendingExpenseCount: Expense.count(pendingLastWeekExpenses),

  approvedExpenseCount: Expense.count(approvedLastWeekExpenses),

  rejectedExpenseCount: Expense.count(rejectedLastWeekExpenses),

  paidExpenseCount: Expense.count(paidLastWeekExpenses),

  pendingExpenseAmount: Expense
    .aggregate('amount', 'SUM', _.merge({}, pendingLastWeekExpenses, groupByCurrency))
    .map(row => `${-row.SUM/100} ${row.currency}`),

  approvedExpenseAmount: Expense
    .aggregate('amount', 'SUM', _.merge({}, approvedLastWeekExpenses, groupByCurrency))
    .map(row => `${-row.SUM/100} ${row.currency}`),

  rejectedExpenseAmount: Expense
    .aggregate('amount', 'SUM', _.merge({}, rejectedLastWeekExpenses, groupByCurrency))
    .map(row => `${-row.SUM/100} ${row.currency}`),

  paidExpenseAmount: Expense
    .aggregate('amount', 'SUM', _.merge({}, paidLastWeekExpenses, groupByCurrency))
    .map(row => `${-row.SUM/100} ${row.currency}`),

  // Collective statistics

  activeCollectivesWithTransactions: Transaction
    .findAll(_.merge({attributes: ['GroupId'] }, updatedLastWeek, distinct, excludeOcTeam))
    .map(row => row.GroupId),

  activeCollectivesWithExpenses: Expense
    .findAll(_.merge({attributes: ['GroupId'] }, updatedLastWeek, distinct, excludeOcTeam))
    .map(row => row.GroupId),

  newCollectives: Group
    .findAll(_.merge({}, { attributes: ['slug']}, createdLastWeek))
    .map(group => group.dataValues.slug)

}).then(results => {
  results.activeCollectiveCount = _.union(results.activeCollectivesWithTransactions, results.activeCollectivesWithExpenses).length
  const report = reportString(results);
  console.log(report);
  return slackLib.postMessage(report, config.slack.webhookUrl, { channel: config.slack.privateActivityChannel });
}).then(() => {
  console.log('Weekly reporting done!');
  process.exit();
}).catch(err => {
  console.log('err', err);
  process.exit();
});

/**
 * Heroku scheduler only has daily or hourly cron jobs, we only want to run
 * this script once per week on Monday (1). If the day is not Monday on production
 * we won't execute the script
 */
function onlyExecuteInProdOnMondays() {
  const today = new Date();
  if (process.env.NODE_ENV === 'production' && today.getDay() !== 1) {
    console.log('NODE_ENV is production and day is not Monday, script aborted!');
    process.exit();
  }
}

function getTimeFrame(propName) {
  const thisWeekStartRaw = moment()
    .tz('America/New_York')
    .startOf('isoWeek')
    .add(9, 'hours');
  const thisWeekStart = thisWeekStartRaw.format();
  const lastWeekStart = thisWeekStartRaw.subtract(1, 'week').format();

  return {
    where: {
      [propName]: {
        $gt: lastWeekStart,
        $lt: thisWeekStart
      }
    }
  };
}

function reportString(results) {
  return `Weekly activity summary (excluding OC team):
\`\`\`
* Donations:
  - ${results.donationCount} donations received${displayTotals(results.donationAmount)}
  - ${results.stripeReceivedCount} donations received via Stripe Webhook (only recurring)
  - ${results.paypalReceivedCount} donations received via PayPal
* Expenses:
  - ${results.pendingExpenseCount} pending expenses${displayTotals(results.pendingExpenseAmount)}
  - ${results.approvedExpenseCount} approved expenses${displayTotals(results.approvedExpenseAmount)}
  - ${results.rejectedExpenseCount} rejected expenses${displayTotals(results.rejectedExpenseAmount)}
  - ${results.paidExpenseCount} paid expenses${displayTotals(results.paidExpenseAmount)}
* Collectives:
  - ${results.activeCollectiveCount} active collectives
  - ${results.newCollectives.length} new collectives${displayCollectives(results.newCollectives)}
\`\`\``;
}

function displayTotals(totals) {
  if (totals.length > 0) {
    return ` totaling:\n    * ${totals.join('\n    * ').trim()}`;
  }
  return "";
}

function displayCollectives(collectives) {
  if (collectives.length > 0) {
    return `:\n    * ${collectives.join('\n    * ').trim()}`;
  }
  return "";
}
<|endoftext|>


<commit_before>function getValues(filters, sets) {
  const content = filters.content;
  if (!content) {
    return [];
  } else if (Array.isArray(content)) {
    return content.reduce((acc, c) => [...acc, ...getValues(c, sets)], []);
  } else {
    return [
      []
        .concat(content.value || [])
        .map(
          v =>
            v.includes('set_id:')
              ? sets[v.replace('set_id:', '')] || 'input set'
              : v,
        ),
    ];
  }
}

const MAX_VALUES = 6;
export default function({
  filters,
  max = MAX_VALUES,
  sets,
  length = Infinity,
}) {
  if (!filters) return '';
  const values = getValues(
    filters,
    Object.values(sets).reduce((a, b) => ({ ...a, ...b }), {}),
  );
  let total = 0;
  const name = values
    .reduce((acc, value, i, arr) => {
      if (total >= MAX_VALUES) return acc;
      const joined = value.slice(0, MAX_VALUES - total).join(' / ');
      total += value.length;
      return acc.concat(
        `${joined}${total > MAX_VALUES ||
        (total === MAX_VALUES && i < arr.length - 1)
          ? '...'
          : ''}`,
      );
    }, [])
    .join(', ');
  return name.length <= length
    ? name
    : name.slice(0, length - 3).replace(/[, ./]*$/, '...');
}
<commit_msg>:bug: SaveSetModal opens if range filter in query (#2133)<commit_after>function getValues(filters, sets) {
  const content = filters.content;
  if (!content) {
    return [];
  } else if (Array.isArray(content)) {
    return content.reduce((acc, c) => [...acc, ...getValues(c, sets)], []);
  } else {
    return [
      []
        .concat(content.value || [])
        .map(
          v =>
            typeof v === 'string' && v.includes('set_id:')
              ? sets[v.replace('set_id:', '')] || 'input set'
              : v,
        ),
    ];
  }
}

const MAX_VALUES = 6;
export default function({
  filters,
  max = MAX_VALUES,
  sets,
  length = Infinity,
}) {
  if (!filters) return '';
  const values = getValues(
    filters,
    Object.values(sets).reduce((a, b) => ({ ...a, ...b }), {}),
  );
  let total = 0;
  const name = values
    .reduce((acc, value, i, arr) => {
      if (total >= MAX_VALUES) return acc;
      const joined = value.slice(0, MAX_VALUES - total).join(' / ');
      total += value.length;
      return acc.concat(
        `${joined}${total > MAX_VALUES ||
        (total === MAX_VALUES && i < arr.length - 1)
          ? '...'
          : ''}`,
      );
    }, [])
    .join(', ');
  return name.length <= length
    ? name
    : name.slice(0, length - 3).replace(/[, ./]*$/, '...');
}
<|endoftext|>


<commit_before>/**
 * @author Russell Toris - rctoris@wpi.edu
 */

/**
 * Create a grid object.
 *
 * @constructor
 * @param options - object with following keys:
 *
 *  * size (optional) - The number of cells of the grid
 *  * color (optional) - the line color of the grid, like '#cccccc'
 *  * lineWidth (optional) - the width of the lines in the grid
 *  * cellSize (optional) - The length, in meters, of the side of each cell
 */
ROS3D.Grid = function(options) {
  options = options || {};
  var size = options.size || 10;
  var color = options.color || '#cccccc';
  var lineWidth = options.lineWidth || 1;
  var cellSize = options.cellSize || 1;

  THREE.Object3D.call(this);

  var material = new THREE.LineBasicMaterial({
    color: color,
    linewidth: lineWidth
  });

  for (var i = 0; i <= size; ++i) {
    var edge = cellSize * size / 2;
    var position = edge - (i * cellSize);
    var geometryH = new THREE.Geometry();
    geometryH.vertices.push(
      new THREE.Vector3( -edge, position, 0 ),
      new THREE.Vector3( edge, position, 0 )
    );
    var geometryV = new THREE.Geometry();
    geometryV.vertices.push(
      new THREE.Vector3( position, -edge, 0 ),
      new THREE.Vector3( position, edge, 0 )
    );
    this.add(new THREE.Line(geometryH, material));
    this.add(new THREE.Line(geometryV, material));
  }
};

ROS3D.Grid.prototype.__proto__ = THREE.Object3D.prototype;
<commit_msg>Update Grid.js<commit_after>/**
 * @author Russell Toris - rctoris@wpi.edu
 */

/**
 * Create a grid object.
 *
 * @constructor
 * @param options - object with following keys:
 *
 *  * size (optional) - Size of the grid in meters
 *  * color (optional) - the line color of the grid, like '#cccccc'
 *  * lineWidth (optional) - the width of the lines in the grid
 *  * cellSize (optional) - The length, in meters, of the side of each cell
 */
ROS3D.Grid = function(options) {
  options = options || {};
  var size = options.size || 10;
  var color = options.color || '#cccccc';
  var lineWidth = options.lineWidth || 1;
  var cellSize = options.cellSize || 1;

  THREE.Object3D.call(this);

  var material = new THREE.LineBasicMaterial({
    color: color,
    linewidth: lineWidth
  });

  for (var i = 0; i <= size/cellSize; ++i) {
    var edge = size / 2;
    var position = edge - (i * cellSize);
    var geometryH = new THREE.Geometry();
    geometryH.vertices.push(
      new THREE.Vector3( -edge, position, 0 ),
      new THREE.Vector3( edge, position, 0 )
    );
    var geometryV = new THREE.Geometry();
    geometryV.vertices.push(
      new THREE.Vector3( position, -edge, 0 ),
      new THREE.Vector3( position, edge, 0 )
    );
    this.add(new THREE.Line(geometryH, material));
    this.add(new THREE.Line(geometryV, material));
  }
};

ROS3D.Grid.prototype.__proto__ = THREE.Object3D.prototype;
<|endoftext|>


<commit_before>frappe.ui.form.on("System Settings", {
	refresh: function (frm) {
		frappe.call({
			method: "frappe.core.doctype.system_settings.system_settings.load",
			callback: function (data) {
				frappe.all_timezones = data.message.timezones;
				frm.set_df_property("time_zone", "options", frappe.all_timezones);

				$.each(data.message.defaults, function (key, val) {
					frm.set_value(key, val);
					frappe.sys_defaults[key] = val;
				});
				if (frm.re_setup_moment) {
					frappe.app.setup_moment();
					delete frm.re_setup_moment;
				}
			},
		});
	},
	enable_password_policy: function (frm) {
		if (frm.doc.enable_password_policy == 0) {
			frm.set_value("minimum_password_score", "");
		} else {
			frm.set_value("minimum_password_score", "2");
		}
	},
	enable_two_factor_auth: function (frm) {
		if (frm.doc.enable_two_factor_auth == 0) {
			frm.set_value("bypass_2fa_for_retricted_ip_users", 0);
			frm.set_value("bypass_restrict_ip_check_if_2fa_enabled", 0);
		}
	},
	enable_prepared_report_auto_deletion: function (frm) {
		if (frm.doc.enable_prepared_report_auto_deletion) {
			if (!frm.doc.prepared_report_expiry_period) {
				frm.set_value("prepared_report_expiry_period", 7);
			}
		}
	},
	on_update: function (frm) {
		if (frappe.boot.time_zone && frappe.boot.time_zone.system !== frm.doc.time_zone) {
			// Clear cache after saving to refresh the values of boot.
			frappe.ui.toolbar.clear_cache();
		}
	},
	first_day_of_the_week(frm) {
		frm.re_setup_moment = true;
	},
});
<commit_msg>fix: Do not show "Not Saved" on loading System Settings (#17967)<commit_after>frappe.ui.form.on("System Settings", {
	refresh: function (frm) {
		frappe.call({
			method: "frappe.core.doctype.system_settings.system_settings.load",
			callback: function (data) {
				frappe.all_timezones = data.message.timezones;
				frm.set_df_property("time_zone", "options", frappe.all_timezones);

				$.each(data.message.defaults, function (key, val) {
					frm.set_value(key, val, null, true);
					frappe.sys_defaults[key] = val;
				});
				if (frm.re_setup_moment) {
					frappe.app.setup_moment();
					delete frm.re_setup_moment;
				}
			},
		});
	},
	enable_password_policy: function (frm) {
		if (frm.doc.enable_password_policy == 0) {
			frm.set_value("minimum_password_score", "");
		} else {
			frm.set_value("minimum_password_score", "2");
		}
	},
	enable_two_factor_auth: function (frm) {
		if (frm.doc.enable_two_factor_auth == 0) {
			frm.set_value("bypass_2fa_for_retricted_ip_users", 0);
			frm.set_value("bypass_restrict_ip_check_if_2fa_enabled", 0);
		}
	},
	enable_prepared_report_auto_deletion: function (frm) {
		if (frm.doc.enable_prepared_report_auto_deletion) {
			if (!frm.doc.prepared_report_expiry_period) {
				frm.set_value("prepared_report_expiry_period", 7);
			}
		}
	},
	on_update: function (frm) {
		if (frappe.boot.time_zone && frappe.boot.time_zone.system !== frm.doc.time_zone) {
			// Clear cache after saving to refresh the values of boot.
			frappe.ui.toolbar.clear_cache();
		}
	},
	first_day_of_the_week(frm) {
		frm.re_setup_moment = true;
	},
});
<|endoftext|>


<commit_before>define([
    'd3',
    'lodash',
    'models/hook'
], function(d3, _, Hook) {

    //constant time formats
    var time_formats = {
        "year": d3.time.format("%Y"),
        "month": d3.time.format("%Y-%m"),
        "week": d3.time.format("%Y-W%W"),
        "day": d3.time.format("%Y-%m-%d"),
        "hour": d3.time.format("%Y-%m-%d %H"),
        "minute": d3.time.format("%Y-%m-%d %H:%M"),
        "second": d3.time.format("%Y-%m-%d %H:%M:%S")
    };

    var Axis = Hook.extend(   {

        /**
         * Initializes the color hook
         * @param {Object} values The initial values of this model
         * @param parent A reference to the parent model
         * @param {Object} bind Initial events to bind
         */
        init: function(values, parent, bind) {

            this._type = "axis";
            values = _.extend({
                use: "value",
                value: undefined
            }, values);
            this._super(values, parent, bind);
        },

        /**
         * Validates a color hook
         */
        validate: function() {

            var possibleScales = ["log", "linear", "time", "pow"];
            if (!this.scale || (this.use === "indicator" && possibleScales.indexOf(this.scale) === -1)) {
                this.scale = 'linear';
            }

            if (!this.unit && this.use === "indicator") {
                this.unit = 1;
            }

            if (this.use !== "indicator" && this.scale !== "ordinal") {
                this.scale = "ordinal";
            }

            //TODO: add min and max to validation

        },
        /**
         * Gets tick values for this hook
         * @returns {Number|String} value The value for this tick
         */
        getTick: function(tick_value) {
            var value = tick_value;
            if(_.isDate(tick_value)) {
                //TODO: generalize for any time unit
                value = time_formats["year"](tick_value);
            }else if (this.use == "indicator") {
                value = parseFloat(value) / this.unit;
            }
            return value;
        },

        /**
         * Gets the domain for this hook
         * @returns {Array} domain
         */
        getDomain: function() {
            var domain,
                scale = this.scale || "linear";

            if(this.value=="time"){
                var limits = this.getLimits(this.value);
                return d3.time.scale().domain([limits.min, limits.max]);
            }

            switch (this.use) {
                case "indicator":
                    var limits = this.getLimits(this.value),
                        margin = (limits.max - limits.min) / 10;
                    domain = [(limits.min - margin), (limits.max + margin)];
                    if(scale == "log") {
                        domain = [limits.min/2, (limits.max + limits.max/2)];
                    }

                    break;
                case "property":
                    domain = this.getUnique(this.value);
                    break;
                case "value":
                default:
                    domain = [this.value];
                    break;
            }

            return d3.scale[scale]().domain(domain);
        }

    });

    return Axis;
});<commit_msg>Tuning domain margins. Closes #78 "This x-axis should be labeled using doubling labels"<commit_after>define([
    'd3',
    'lodash',
    'models/hook'
], function(d3, _, Hook) {

    //constant time formats
    var time_formats = {
        "year": d3.time.format("%Y"),
        "month": d3.time.format("%Y-%m"),
        "week": d3.time.format("%Y-W%W"),
        "day": d3.time.format("%Y-%m-%d"),
        "hour": d3.time.format("%Y-%m-%d %H"),
        "minute": d3.time.format("%Y-%m-%d %H:%M"),
        "second": d3.time.format("%Y-%m-%d %H:%M:%S")
    };

    var Axis = Hook.extend(   {

        /**
         * Initializes the color hook
         * @param {Object} values The initial values of this model
         * @param parent A reference to the parent model
         * @param {Object} bind Initial events to bind
         */
        init: function(values, parent, bind) {

            this._type = "axis";
            values = _.extend({
                use: "value",
                value: undefined
            }, values);
            this._super(values, parent, bind);
        },

        /**
         * Validates a color hook
         */
        validate: function() {

            var possibleScales = ["log", "linear", "time", "pow"];
            if (!this.scale || (this.use === "indicator" && possibleScales.indexOf(this.scale) === -1)) {
                this.scale = 'linear';
            }

            if (!this.unit && this.use === "indicator") {
                this.unit = 1;
            }

            if (this.use !== "indicator" && this.scale !== "ordinal") {
                this.scale = "ordinal";
            }

            //TODO: add min and max to validation

        },
        /**
         * Gets tick values for this hook
         * @returns {Number|String} value The value for this tick
         */
        getTick: function(tick_value) {
            var value = tick_value;
            if(_.isDate(tick_value)) {
                //TODO: generalize for any time unit
                value = time_formats["year"](tick_value);
            }else if (this.use == "indicator") {
                value = parseFloat(value) / this.unit;
            }
            return value;
        },

        /**
         * Gets the domain for this hook
         * @returns {Array} domain
         */
        getDomain: function() {
            var domain,
                scale = this.scale || "linear";

            if(this.value=="time"){
                var limits = this.getLimits(this.value);
                return d3.time.scale().domain([limits.min, limits.max]);
            }

            switch (this.use) {
                case "indicator":
                    var limits = this.getLimits(this.value),
                        margin = (limits.max - limits.min) / 10;
                    domain = [(limits.min - margin), (limits.max + margin)];
                    if(scale == "log") {
                        domain = [(limits.min-limits.min/3), (limits.max + limits.max/3)];
                    }

                    break;
                case "property":
                    domain = this.getUnique(this.value);
                    break;
                case "value":
                default:
                    domain = [this.value];
                    break;
            }

            return d3.scale[scale]().domain(domain);
        }

    });

    return Axis;
});<|endoftext|>


<commit_before>var q = require('q');

var mongoose = require('mongoose');

var logger = require('../utils/logger');

var messageSchema = new mongoose.Schema({
    createdAt: { type: Date, default: Date.now },
    updatedAt: { type: Date, default: Date.now },
    contents: { type: String, required: true },
    createdBy: { type: mongoose.Schema.Types.ObjectId, ref: 'profile' }
});

var postSchema = new mongoose.Schema({
    createdAt: { type: Date, default: Date.now },
    updatedAt: { type: Date, default: Date.now },
    views: { type: Number, default: 0 },
    title: { type: String, required: true },
    slug: String,
    contents: String,
    messageCount: { type: Number, default: 0 },
    messages: [messageSchema],
    createdBy: { type: mongoose.Schema.Types.ObjectId, ref: 'profile' }
});

postSchema.statics.createPost = function (data) {

    var deferred = new q.defer();

    var post = new this({
        title: data.title,
        slug: data.title.toLowerCase().replace(/[^a-z]+/g, '-').replace(/^\-|\-$/g, ''),
        contents: data.contents,
        createdBy: data.createdBy
    });

    post.save(function (err, post) {

        if (err || !post) {

            logger.err('Error creating new post.', err, data);

            deferred.reject({
                status: 500,
                message: 'Internal Server Error'
            });

        } else { deferred.resolve(post); }

    });

    return deferred.promise;

};

postSchema.statics.addMessageToPostById = function (postId, data) {

    var deferred = new q.defer();

    this.findById(postId)
        .exec(function (err, post) {

            post.messages.push({
                contents: data.contents,
                createdBy: data.createdBy
            });

            post.save(function (err, post) {

                if (err || !post) {

                    logger.err('Error creating new message.', err, data);

                    deferred.reject({
                        status: 500,
                        message: 'Internal Server Error'
                    });

                } else { deferred.resolve(post); }

            });

        });

    return deferred.promise;

};

postSchema.statics.showPostById = function (postId) {

    var deferred = new q.defer();

    this.findByIdAndUpdate(postId, { $inc: { views: 1 } })
        .populate('createdBy')
        .populate('messages.createdBy')
        .exec(function (err, post) {

            if (err || !post) {

                logger.err('Post id ' + postId + ' not found.');

                deferred.reject({
                    status: 404,
                    message: 'Post not found.'
                });

            } else { deferred.resolve(post); }

        });

    return deferred.promise;

};

postSchema.statics.listPosts = function () {

    var deferred = new q.defer();

    this.find()
        .populate('createdBy')
        .sort({ updatedAt: -1 })
        .select('createdAt updatedAt views title slug contents messageCount createdBy')
        .exec(function (err, posts) {

            if (err || !posts) {

                logger.err('Error retrieving post list.', err);

                deferred.reject({
                    status: 500,
                    message: 'Internal Server Error'
                });

            } else { deferred.resolve(posts); }

        });

    return deferred.promise;

};

postSchema.statics.searchPosts = function (query) {

    var deferred = new q.defer();

    if (query) {

        query = query.trim().toLowerCase();
        query = query.replace(/[^0-9a-z]+/, '|').replace(/^\||\|$/, '');

        if (query) {

            this.find({ title: { $regex: new RegExp(query, 'i') } })
                .populate('createdBy')
                .sort({ updatedAt: -1 })
                .select('createdAt updatedAt views title slug contents messageCount createdBy')
                .exec(function (err, posts) {

                    if (err || !posts) {

                        logger.err('Error retrieving search results.', err, query);

                        deferred.reject({
                            status: 500,
                            message: 'Internal Server Error'
                        });

                    } else { deferred.resolve(posts); }

                });

        } else {

            deferred.resolve([]);

        }

    } else {

        deferred.resolve([]);

    }

    return deferred.promise;

};

postSchema.pre('save', function (next) {

    this.updatedAt = Date.now();
    this.messageCount = this.messages.length;

    next();

});

module.exports = mongoose.model('post', postSchema);
<commit_msg>Added basic pinned post support.<commit_after>var q = require('q');

var mongoose = require('mongoose');

var logger = require('../utils/logger');

var messageSchema = new mongoose.Schema({
    createdAt: { type: Date, default: Date.now },
    updatedAt: { type: Date, default: Date.now },
    contents: { type: String, required: true },
    createdBy: { type: mongoose.Schema.Types.ObjectId, ref: 'profile' }
});

var postSchema = new mongoose.Schema({
    createdAt: { type: Date, default: Date.now },
    updatedAt: { type: Date, default: Date.now },
    views: { type: Number, default: 0 },
    title: { type: String, required: true },
    slug: String,
    contents: String,
    messageCount: { type: Number, default: 0 },
    messages: [messageSchema],
    pinned: { type: Boolean, default: false },
    createdBy: { type: mongoose.Schema.Types.ObjectId, ref: 'profile' }
});

postSchema.statics.createPost = function (data) {

    var deferred = new q.defer();

    var post = new this({
        title: data.title,
        slug: data.title.toLowerCase().replace(/[^a-z]+/g, '-').replace(/^\-|\-$/g, ''),
        contents: data.contents,
        createdBy: data.createdBy
    });

    post.save(function (err, post) {

        if (err || !post) {

            logger.err('Error creating new post.', err, data);

            deferred.reject({
                status: 500,
                message: 'Internal Server Error'
            });

        } else { deferred.resolve(post); }

    });

    return deferred.promise;

};

postSchema.statics.addMessageToPostById = function (postId, data) {

    var deferred = new q.defer();

    this.findById(postId)
        .exec(function (err, post) {

            post.messages.push({
                contents: data.contents,
                createdBy: data.createdBy
            });

            post.save(function (err, post) {

                if (err || !post) {

                    logger.err('Error creating new message.', err, data);

                    deferred.reject({
                        status: 500,
                        message: 'Internal Server Error'
                    });

                } else { deferred.resolve(post); }

            });

        });

    return deferred.promise;

};

postSchema.statics.showPostById = function (postId) {

    var deferred = new q.defer();

    this.findByIdAndUpdate(postId, { $inc: { views: 1 } })
        .populate('createdBy')
        .populate('messages.createdBy')
        .exec(function (err, post) {

            if (err || !post) {

                logger.err('Post id ' + postId + ' not found.');

                deferred.reject({
                    status: 404,
                    message: 'Post not found.'
                });

            } else { deferred.resolve(post); }

        });

    return deferred.promise;

};

postSchema.statics.listPosts = function () {

    var deferred = new q.defer();

    this.find()
        .populate('createdBy')
        .sort({ pinned: -1, updatedAt: -1 })
        .select('createdAt updatedAt views title slug contents messageCount createdBy')
        .exec(function (err, posts) {

            if (err || !posts) {

                logger.err('Error retrieving post list.', err);

                deferred.reject({
                    status: 500,
                    message: 'Internal Server Error'
                });

            } else { deferred.resolve(posts); }

        });

    return deferred.promise;

};

postSchema.statics.searchPosts = function (query) {

    var deferred = new q.defer();

    if (query) {

        query = query.trim().toLowerCase();
        query = query.replace(/[^0-9a-z]+/, '|').replace(/^\||\|$/, '');

        if (query) {

            this.find({ title: { $regex: new RegExp(query, 'i') } })
                .populate('createdBy')
                .sort({ updatedAt: -1 })
                .select('createdAt updatedAt views title slug contents messageCount createdBy')
                .exec(function (err, posts) {

                    if (err || !posts) {

                        logger.err('Error retrieving search results.', err, query);

                        deferred.reject({
                            status: 500,
                            message: 'Internal Server Error'
                        });

                    } else { deferred.resolve(posts); }

                });

        } else {

            deferred.resolve([]);

        }

    } else {

        deferred.resolve([]);

    }

    return deferred.promise;

};

postSchema.pre('save', function (next) {

    this.updatedAt = Date.now();
    this.messageCount = this.messages.length;

    next();

});

module.exports = mongoose.model('post', postSchema);
<|endoftext|>


<commit_before>'use strict';
const commander = require('commander');
const fs = require('fs');
const _ = require('lodash');
const moment = require('moment');
const {min, max, floor, ceil} = Math;
const db = require('../../../lib/schemes');

commander
    .option('--source [path]', '(required) Source tsv file')
    .option('--output [path]', 'Output file path (default: stdout)')
    .option('--start [date]', '(required) Start date (e.g, 2017-04-01)')
    .option('--end [date]', '(required) End date (e.g., 2017-05-01)')
    .parse(process.argv);

if (!commander.source || !commander.start || !commander.end) {
    process.stderr.write(commander.helpInformation());
    process.exit(1);
}

main(commander)
    .then(() => {
        console.log('Completed.\n');
        process.exit(0);
    })
    .catch(e => {
        console.error(e);
        process.exit(1);
    });

async function main ({source: sourcePath, output: outputPath, start: startDate, end: endDate}) {
    const works = loadTsv(sourcePath);

    await expandWorks(works);

    const usernames = _.uniq(works.map(x => x.user.username));
    const costValues = _.uniq(works.map(x => x.cost.value));

    for (let username of usernames) {
        for (let costValue of costValues) {
            const filteredWorks = works.filter(x => x.user.username === username && x.cost.value === costValue);
            if (!filteredWorks.length) { continue; }

            const timelines = convertToTimeline(filteredWorks, startDate, endDate);

            const outstr = convertToTsv(timelines);

            if (outputPath) {
                const matched = outputPath.match(/(.*)\.(\w+)$/);
                let path;
                if (matched) {
                    path = `${matched[1]}_${username}_${costValue}.${matched[2]}`;
                } else {
                    path = `${outputPath}_${username}_${costValue}`;
                }

                fs.writeFileSync(path, outstr);
                console.log(`${path} was created`);
            } else {
                console.log(outstr);
            }
        }
    }
}

async function expandWorks (works) {
    const memoTasks = {};
    const memoUsers = {};
    const memoCosts = {};

    for (let work of works) {
        const {taskId, userId} = work;

        let task = memoTasks[taskId];
        if (!task) {
            task = (await db.Task.findOne({where: {id: taskId}})).toJSON();
            memoTasks[taskId] = task;
        }

        let user = memoUsers[userId];
        if (!user) {
            user = (await db.User.findOne({where: {id: userId}})).toJSON();
            memoUsers[userId] = user;
        }

        const costId = task.costId;
        let cost = memoCosts[costId];
        if (!cost) {
            cost = (await db.Cost.findOne({where: {id: costId}})).toJSON();
            memoCosts[costId] = cost;
        }

        work.task = task;
        work.user = user;
        work.cost = cost;
    }
}

function loadTsv (path) {
    const contents = fs.readFileSync(path, 'utf8');
    const lines = contents.split('\n').filter(x => x).map(line => line.split('\t'));
    const header = lines.shift();
    return lines.map(line => _.zipObject(header, line));
}

function convertToTimeline (src, startDate, endDate) {
    const taskIds = _.chain(src).map('taskId').uniq().value();
    const timelines = {}; // timelines[taskId][elapsed hour] = continuous work time
    const startMoment = moment(startDate);
    const endMoment = moment(endDate);
    const duration = endMoment.diff(startMoment, 'hours') + 1;

    taskIds.forEach(taskId => {
        const works = _.sortBy(src.filter(work => work.taskId === taskId), 'startTime');
        const timeline = Array(duration).fill(0);

        works.forEach(work => {
            const workStartMoment = moment(work.startTime);
            const workEndMoment = moment(work.endTime);
            const s = floor(max(min(endMoment.diff(workStartMoment, 'seconds') / 60 / 60, duration - 1), 0));
            const e = floor(max(min(endMoment.diff(workEndMoment, 'seconds') / 60 / 60 + 1, duration - 1), 0));
            const e2 = ceil(max(min(endMoment.diff(workEndMoment, 'seconds') / 60 / 60 + 1, duration - 1), 0));
            for (let i = floor(s), lim = ceil(e); i < lim; ++i) {
                timeline[i] += 1;
            }

            const diff = workEndMoment.diff(workStartMoment, 'seconds') / 60 / 60;
            timeline[e2] += diff - floor(diff);
        });

        let sum = 0;
        for (let i = 0; i < duration; ++i) {
            if (timeline[i]) {
                if (i) {
                    timeline[i - 1] = sum;
                }
                sum += timeline[i];
                timeline[i] = sum;
            } else {
                timeline[i] = null;
            }
        }

        timelines[taskId] = timeline;
    });

    return timelines;
}

function convertToTsv (timelines) {
    const taskIds = Object.keys(timelines);
    if (!taskIds.length) { return ''; }

    const lines = [['Days'].concat(taskIds.slice())];
    const n = timelines[taskIds[0]].length;

    for (let i = 0; i < n; ++i) {
        const line = taskIds.map(taskId => timelines[taskId][i]);
        const days = floor(i / 24);
        const hours = i % 24;
        line.unshift(`${days}:${hours}`);
        lines.push(line);
    }

    return lines.map(line => line.join('\t')).join('\n');
}
<commit_msg>add filter of work timeline generator<commit_after>'use strict';
const commander = require('commander');
const fs = require('fs');
const _ = require('lodash');
const moment = require('moment');
const {min, max, floor, ceil} = Math;
const db = require('../../../lib/schemes');
const Predictor = require('../models/predictor');

commander
    .option('--source [path]', '(required) Source tsv file')
    .option('--output [path]', 'Output file path (default: stdout)')
    .option('--start [date]', '(required) Start date (e.g, 2017-04-01)')
    .option('--end [date]', '(required) End date (e.g., 2017-05-01)')
    .parse(process.argv);

if (!commander.source || !commander.start || !commander.end) {
    process.stderr.write(commander.helpInformation());
    process.exit(1);
}

main(commander)
    .then(() => {
        console.log('Completed.\n');
        process.exit(0);
    })
    .catch(e => {
        console.error(e);
        process.exit(1);
    });

async function main ({source: sourcePath, output: outputPath, start: startDate, end: endDate}) {
    const works = loadTsv(sourcePath);

    await expandWorks(works);

    const users = _.uniqBy(works.map(x => x.user), 'username');
    const costValues = _.uniq(works.map(x => x.cost.value));

    for (let user of users) {
        for (let costValue of costValues) {
            const filteredWorks = works.filter(x => x.user.username === user.username && x.cost.value === costValue);
            if (!filteredWorks.length) { continue; }

            const timelines = convertToTimeline(filteredWorks, startDate, endDate);

            const predict = predictWorktimeAllTimeline(filteredWorks, user.id, costValue, startDate, endDate);

            const outstr = convertToTsv(timelines);

            process.exit(0);

            if (outputPath) {
                const matched = outputPath.match(/(.*)\.(\w+)$/);
                let path;
                if (matched) {
                    path = `${matched[1]}_${username}_${costValue}.${matched[2]}`;
                } else {
                    path = `${outputPath}_${username}_${costValue}`;
                }

                fs.writeFileSync(path, outstr);
                console.log(`${path} was created`);
            } else {
                console.log(outstr);
            }
        }
    }
}

async function expandWorks (works) {
    const memoTasks = {};
    const memoUsers = {};
    const memoCosts = {};

    for (let work of works) {
        const {taskId, userId} = work;

        let task = memoTasks[taskId];
        if (!task) {
            task = (await db.Task.findOne({where: {id: taskId}})).toJSON();
            memoTasks[taskId] = task;
        }

        let user = memoUsers[userId];
        if (!user) {
            user = (await db.User.findOne({where: {id: userId}})).toJSON();
            memoUsers[userId] = user;
        }

        const costId = task.costId;
        let cost = memoCosts[costId];
        if (!cost) {
            cost = (await db.Cost.findOne({where: {id: costId}})).toJSON();
            memoCosts[costId] = cost;
        }

        work.task = task;
        work.user = user;
        work.cost = cost;
    }
}

function loadTsv (path) {
    const contents = fs.readFileSync(path, 'utf8');
    const lines = contents.split('\n').filter(x => x).map(line => line.split('\t'));
    const header = lines.shift();
    return lines.map(line => _.zipObject(header, line));
}

function convertToTimeline (src, startDate, endDate) {
    const taskIds = _.chain(src).map('taskId').uniq().value();
    const timelines = {}; // timelines[taskId][elapsed hour] = continuous work time
    const startMoment = moment(startDate);
    const endMoment = moment(endDate);
    const duration = endMoment.diff(startMoment, 'hours') + 1;

    taskIds.forEach(taskId => {
        const works = _.sortBy(src.filter(work => work.taskId === taskId), 'startTime');
        const timeline = Array(duration).fill(0);

        works.forEach(work => {
            const workStartMoment = moment(work.startTime);
            const workEndMoment = moment(work.endTime);
            const s = floor(max(min(endMoment.diff(workStartMoment, 'seconds') / 60 / 60, duration - 1), 0));
            const e = floor(max(min(endMoment.diff(workEndMoment, 'seconds') / 60 / 60 + 1, duration - 1), 0));
            const e2 = ceil(max(min(endMoment.diff(workEndMoment, 'seconds') / 60 / 60 + 1, duration - 1), 0));
            for (let i = floor(s), lim = ceil(e); i < lim; ++i) {
                timeline[i] += 1;
            }

            const diff = workEndMoment.diff(workStartMoment, 'seconds') / 60 / 60;
            timeline[e2] += diff - floor(diff);
        });

        let sum = 0;
        for (let i = 0; i < duration; ++i) {
            if (timeline[i]) {
                if (i) {
                    timeline[i - 1] = sum;
                }
                sum += timeline[i];
                timeline[i] = sum;
            } else {
                timeline[i] = null;
            }
        }

        timelines[taskId] = timeline;
    });

    return timelines;
}

function convertToTsv (timelines) {
    const taskIds = Object.keys(timelines);
    if (!taskIds.length) { return ''; }

    const lines = [['Days'].concat(taskIds.slice())];
    const n = timelines[taskIds[0]].length;

    for (let i = 0; i < n; ++i) {
        const line = taskIds.map(taskId => timelines[taskId][i]);
        const days = floor(i / 24);
        const hours = i % 24;
        line.unshift(`${days}:${hours}`);
        lines.push(line);
    }

    return lines.map(line => line.join('\t')).join('\n');
}

async function predictWorktimeAllTimeline (tasks, userId, cost, startDate, endDate) {
    const timeline = [];
    const endMoment = moment(endDate);
    let currentMoment = moment(startDate);

    let beforeLength = null;
    let before = null;

    while (currentMoment.isBefore(endMoment)) {
        currentMoment.add(1, 'days');

        const filteredTasks = tasks.filter(x => currentMoment.isAfter(x.completedAt));
        if (filteredTasks.length === beforeLength) {
            timeline.push(before);
        } else {
            const predicted = await predictWorkTime(filteredTasks, userId, cost);
            console.log(predicted);
            beforeLength = filteredTasks.length;
            before = predicted;
            timeline.push(predicted);
        }
    }

    return timeline;
}

async function predictWorkTime (tasks, userId, cost) {
    return Predictor._execChild(tasks, [userId], [cost]);
}
<|endoftext|>


<commit_before>function Phase2Moves() {
  this.cornerMoves = new Uint16Array(403200);
  this.edgeMoves = new Uint16Array(403200);
  this.sliceMoves = new Uint16Array(240);

  var perm8 = perms.allPerms(8);
  this._generateCornerMoves(perm8);
  this._generateEdgeMoves(perm8);
  this._generateSliceMoves();
}

Phase2Moves.prototype._generateCornerMoves = function(perm8) {
  for (var i = 0; i < 403200; ++i) {
    this.cornerMoves[i] = 0xffff;
  }

  // Apply every move to every corner state.
  for (var state = 0; state < 40320; ++state) {
    var perm = perm8[state];
    var corners = new Corners();
    for (var j = 0; j < 8; ++j) {
      corners.corners[j].piece = perm[j];
    }

    // Loop through all 10 moves and apply them.
    for (var m = 0; m < 10; ++m) {
      if (this.cornerMoves[state*10 + m] !== 0xffff) {
        continue;
      }

      // Record the end state of this move.
      var c = corners.copy();
      c.move(p2MoveMove(m, 1));
      var endState = encodeYCornerPerm(c);
      res.cornerMoves[state*10 + m] = endState;

      // Set the inverse of this state.
      res.cornerMoves[endState*10 + p2MoveInverse(m)] = state;
    }
  }
};

Phase2Moves.prototype._generateEdgeMoves = function(perm8) {
  // TODO: this
};

Phase2Moves.prototype._generateSliceMoves = function() {
  // TODO: this
};

// p2MoveFace returns the face of a phase-2 move.
function p2MoveFace(m) {
  return [2, 3, 4, 5, 0, 0, 0, 1, 1, 1][m] + 1;
}

// p2MoveInverse finds the inverse of a phase-2 move.
function p2MoveInverse(m) {
  return [0, 1, 2, 3, 5, 4, 6, 8, 7, 9][m];
}

// p2MoveMove returns the Move for a phase-2 move.
function p2MoveMove(m, axis) {
  var num = [
    [14, 15, 12, 13, 5, 11, 17, 4, 10, 16],
		[14, 15, 16, 17, 0, 6, 12, 1, 7, 13],
		[13, 12, 16, 17, 2, 8, 14, 3, 9, 15]
  ][axis][m];
}<commit_msg>drafted edges and corners in Phase2Moves<commit_after>function Phase2Moves() {
  this.cornerMoves = new Uint16Array(403200);
  this.edgeMoves = new Uint16Array(403200);
  this.sliceMoves = new Uint16Array(240);

  var perm8 = perms.allPerms(8);
  this._generateCornerMoves(perm8);
  this._generateEdgeMoves(perm8);
  this._generateSliceMoves();
}

Phase2Moves.prototype._generateCornerMoves = function(perm8) {
  for (var i = 0; i < 403200; ++i) {
    this.cornerMoves[i] = 0xffff;
  }

  // Apply every move to every corner state.
  for (var state = 0; state < 40320; ++state) {
    var perm = perm8[state];
    var corners = new Corners();
    for (var j = 0; j < 8; ++j) {
      corners.corners[j].piece = perm[j];
    }

    // Loop through all 10 moves and apply them.
    for (var m = 0; m < 10; ++m) {
      if (this.cornerMoves[state*10 + m] !== 0xffff) {
        continue;
      }

      // Record the end state of this move.
      var c = corners.copy();
      c.move(p2MoveMove(m, 1));
      var endState = encodeYCornerPerm(c);
      res.cornerMoves[state*10 + m] = endState;

      // Set the inverse of this state.
      res.cornerMoves[endState*10 + p2MoveInverse(m)] = state;
    }
  }
};

Phase2Moves.prototype._generateEdgeMoves = function(perm8) {
  for (var i = 0; i < 403200; ++i) {
    this.edgeMoves[i] = 0xffff;
  }

  // Apply every move to every edge state.
  for (var state = 0; state < 40320; ++state) {
    var perm = perm8[state];
    var edges = new Edges();
    // Permute the UD edges for the current case.
    for (var j = 0; j < 8; ++j) {
      var slot = [6, 5, 0, 4, 8, 11, 2, 10][j];
      var piece = [6, 5, 0, 4, 8, 11, 2, 10][perm[j]];
      edges[slot].piece = piece;
    }
    // Apply all 10 moves to the cube.
    for (var m = 0; m < 10; ++m) {
      if (this.edgeMoves[state*10 + m] !== 0xffff) {
        continue;
      }

      var e = edges.copy();
      e.move(p2MoveMove(m, 1));
      var endState = encodeUDEdges(e);
      this.edgeMoves[state*10 + m] = endState;

      // Set the inverse of this state.
      this.edgeMoves[endState*10 + p2MoveInverse(m)] = state;
    }
  }
};

Phase2Moves.prototype._generateSliceMoves = function() {
  // TODO: this
};

function encodeUDEdges(edges) {
  // TODO: this
}

function encodeYCornerPerm(corners) {
  // TODO: this
}

// p2MoveFace returns the face of a phase-2 move.
function p2MoveFace(m) {
  return [2, 3, 4, 5, 0, 0, 0, 1, 1, 1][m] + 1;
}

// p2MoveInverse finds the inverse of a phase-2 move.
function p2MoveInverse(m) {
  return [0, 1, 2, 3, 5, 4, 6, 8, 7, 9][m];
}

// p2MoveMove returns the Move for a phase-2 move.
function p2MoveMove(m, axis) {
  var num = [
    [14, 15, 12, 13, 5, 11, 17, 4, 10, 16],
		[14, 15, 16, 17, 0, 6, 12, 1, 7, 13],
		[13, 12, 16, 17, 2, 8, 14, 3, 9, 15]
  ][axis][m];
}<|endoftext|>