<commit_before>// MongoDB stuff
// Created by Fredrik A. Madsen-Malmo

// Imports
var mongo = require('mongodb').MongoClient;
var assert = require('assert');
var Promise = require('promise');

// Mongo config
var PORT = 27017 || process.env.MONGOPORT;
var HOST = 'localhost' || process.env.MONGOHOST;
var DB = 'serverstatus' || process.env.MONGODB;

var URL = 'mongodb://' + HOST + ':' + PORT + '/' + DB;

// Base function
var WEEKDAYS = [
    'Sunday',
    'Monday',
    'Tuesday',
    'Wednesday',
    'Thursday',
    'Friday',
    'Saturday'
];

/**
 * Connects to the database and calls the anon function provided
 * @param  {Function}  Func Anon function to call
 * @return {null}      No return value
 */
var connect = function (func) {
    mongo.connect(URL, function (err, db) {
        if (err) {
            throw err;
        }

        assert.equal(null, err);
        func(db);
    });
};

// DB functions

/**
 * Callback used for the isert function
 * @param  {Object}   err     This is the Error object that describes the error encountered
 * @param  {Object}   result  This is the result, contains all info about the insert
 * @param  {Object}   db      The database object, here I use it to close the db
 * @param  {Function} resolve This is the function to be called when the script completes
 * @param  {Function} reject  This is the function to be called if the script fails
 * @return {Object}           Resolve or Reject
 */
function insertCallback (err, result, db, resolve, reject) {
    if (err) {
        reject(err);
    }

    assert.equal(err, null);

    db.close();
    resolve(result);
}

/**
 * Insert an entry into the db
 * @param  {String}   mode  either 'temp' or 'load'; what kind of entry
 * @param  {String}    value the value to insert.
 * @return {Function} A promise with the value passed in
 */
var insert = function (mode, value) {
    return new Promise(function (resolve, reject) {
        connect(function (db) {
            if (mode.toLowerCase() == 'temp') {
                db.collection('temp').insertOne({
                    "time": new Date(),
                    "temp": (parseFloat(value.replace(',', '.')))
                }, function(err, result){insertCallback(err, result, db, resolve, reject);});
                console.log(value);
            } else if (mode.toLowerCase() == 'load') {
                db.collection('load').insertOne({
                    "time": new Date(),
                    "load": ((parseFloat(value.replace(',', '.')) / 4) * 100)
                }, function(err, result){insertCallback(err, result, db, resolve, reject);});
                console.log(value);
            } else {
                db.close();
                reject('Invalid input');
            }
        });
    });
};

/**
 * Gets the 20 last entries of one mode
 * @param  {String} mode The type of entry to retrieve
 * @return {Function}    Returns either a resolve or reject function
 */
var realtime = function (mode) {
    var latest = [];

    return new Promise(function (resolve, reject) {
        connect(function (db) {
            var cursor = db.collection(mode).find({  }).limit(20).sort({time:-1});

            cursor.each(function (err, doc) {
                if (err) {
                    reject(err);
                }

                assert.equal(err, null);

                if (doc !== null) {
                    // Push [hh:mm:ss, temp|load] to latest
                    latest.push([doc.time.toTimeString().substr(0, 8),
                                 (doc.temp || doc.load)]);
                } else {
                    resolve(latest);
                    db.close();
                }
            });
        });
    });
};

/**
 * Get's the average temperature for the 20 last minutes
 * @param  {String} What type of entry to retrieve
 * @return {Array}  Two-dimentional array with HH:MM and temp|load:float
 */
var minute = function (mode) {
    var minutes = [];

    return new Promise(function (resolve, reject) {
        connect(function (db) {
            var count = -1;
            var prev = -1;
            var count_internal = 2;

            var cursor = db.collection(mode).find({}).sort({time:-1});

            cursor.each(function (err, doc) {
                if (err) {
                    reject(err);
                }

                assert.equal(err, null);

                if (doc !== null) {
                    if (count < 20 && doc.time.getMinutes() == prev) {
                        // Push [hh:mm:ss, temp|load] to minutes
                        minutes[count] = [doc.time.toTimeString().substr(0, 5),
                                          (minutes[count][1] + (doc.temp || doc.load)) / count_internal];
                        count_internal++;
                    } else if (count < 20 && doc.time.getMinutes() != prev) {
                        count++;
                        prev = doc.time.getMinutes();
                        // Push [hh:mm:ss, temp|load] to minutes
                        minutes[count] = [doc.time.toTimeString().substr(0,5),
                                          0 + (doc.temp || doc.load)];
                        count_internal = 2;
                    } else {
                        resolve(minutes);
                        db.close();
                    }
                } else {
                    resolve(minutes);
                    db.close();
                }
            });
        });
    });
};

/**
 * Get's the average temperature for the last 10 hours
 * @param  {String} What type of entry to retrieve
 * @return {Array}  Two-dimentional array with Weekday date, hour:00
 */
var hour = function(mode) {
    var hours = [];

    return new Promise(function (resolve, reject) {
        connect(function (db) {
            var count = -1;
            var prev = -1;
            var count_internal = 2;

            var cursor = db.collection(mode).find({}).sort({time:-1});

            cursor.each(function (err, doc) {
                if (err) {
                    reject(err);
                }

                assert.equal(err, null);

                if (doc !== null) {
                    if (count < 10 && doc.time.getHours() == prev) {
                        // Push [hh:mm:ss, temp|load] to hours
                        hours[count] = [WEEKDAYS[doc.time.getDay()] + ' ' +
                                        doc.time.getDate() + ', ' +
                                        doc.time.toTimeString().substr(0,2) + ':00',
                                        (hours[count][1] + (doc.temp || doc.load)) / count_internal];
                        count_internal++;
                    } else if (count < 10 && doc.time.getHours() != prev) {
                        count++;
                        prev = doc.time.getHours();
                        // Push [hh:mm:ss, temp|load] to hours
                        hours[count] = [WEEKDAYS[doc.time.getDay()] + ' ' +
                                        doc.time.getDate() + ', ' +
                                        doc.time.toTimeString().substr(0,2) + ':00',
                                        0 + (doc.temp || doc.load)];
                        count_internal = 2;
                    } else {
                        resolve(hours);
                        console.log(hours.length);
                        db.close();
                    }
                } else {
                    resolve(hours);
                    console.log(hours.length);
                    db.close();
                }
            });
        });
    });
};

/**
 * Get's the average temperature for the last week
 * @param  {String} What type of entry to retrieve
 * @return {Array}  Two-dimentional array with Weekday date/month
 */
var day = function(mode) {
    var days = [];

    return new Promise(function (resolve, reject) {
        connect(function (db) {
            var count = -1;
            var prev = -1;
            var count_internal = 2;

            var cursor = db.collection(mode).find({}).sort({time:-1});

            cursor.each(function (err, doc) {
                if (err) {
                    reject(err);
                }

                assert.equal(err, null);

                if (doc !== null) {
                    if (count < 7 && doc.time.getDate() == prev) {
                        // Push [hh:mm:ss, temp|load] to days
                        days[count] = [WEEKDAYS[doc.time.getDay()] + ' ' +
                                        doc.time.getDate() + '/' +
                                        (doc.time.getMonth() + 1),
                                        (days[count][1] + (doc.temp || doc.load)) / count_internal];
                        count_internal++;
                    } else if (count < 7 && doc.time.getDate() != prev) {
                        count++;
                        prev = doc.time.getDate();
                        // Push [hh:mm:ss, temp|load] to days
                        days[count] = [WEEKDAYS[doc.time.getDay()] + ' ' +
                                        doc.time.getDate() + '/' +
                                        (doc.time.getMonth() + 1),
                                        0 + (doc.temp || doc.load)];
                        count_internal = 2;
                    } else {
                        resolve(days);
                        db.close();
                    }
                } else {
                    resolve(days);
                    db.close();
                }
            });
        });
    });
};

// Exports

module.exports = {
    insert: insert,
    realtime: realtime,
    minute: minute,
    hour: hour,
    day: day
};
<commit_msg>fixed counts<commit_after>// MongoDB stuff
// Created by Fredrik A. Madsen-Malmo

// Imports
var mongo = require('mongodb').MongoClient;
var assert = require('assert');
var Promise = require('promise');

// Mongo config
var PORT = 27017 || process.env.MONGOPORT;
var HOST = 'localhost' || process.env.MONGOHOST;
var DB = 'serverstatus' || process.env.MONGODB;

var URL = 'mongodb://' + HOST + ':' + PORT + '/' + DB;

// Base function
var WEEKDAYS = [
    'Sunday',
    'Monday',
    'Tuesday',
    'Wednesday',
    'Thursday',
    'Friday',
    'Saturday'
];

/**
 * Connects to the database and calls the anon function provided
 * @param  {Function}  Func Anon function to call
 * @return {null}      No return value
 */
var connect = function (func) {
    mongo.connect(URL, function (err, db) {
        if (err) {
            throw err;
        }

        assert.equal(null, err);
        func(db);
    });
};

// DB functions

/**
 * Callback used for the isert function
 * @param  {Object}   err     This is the Error object that describes the error encountered
 * @param  {Object}   result  This is the result, contains all info about the insert
 * @param  {Object}   db      The database object, here I use it to close the db
 * @param  {Function} resolve This is the function to be called when the script completes
 * @param  {Function} reject  This is the function to be called if the script fails
 * @return {Object}           Resolve or Reject
 */
function insertCallback (err, result, db, resolve, reject) {
    if (err) {
        reject(err);
    }

    assert.equal(err, null);

    db.close();
    resolve(result);
}

/**
 * Insert an entry into the db
 * @param  {String}   mode  either 'temp' or 'load'; what kind of entry
 * @param  {String}    value the value to insert.
 * @return {Function} A promise with the value passed in
 */
var insert = function (mode, value) {
    return new Promise(function (resolve, reject) {
        connect(function (db) {
            if (mode.toLowerCase() == 'temp') {
                db.collection('temp').insertOne({
                    "time": new Date(),
                    "temp": (parseFloat(value.replace(',', '.')))
                }, function(err, result){insertCallback(err, result, db, resolve, reject);});
                console.log(value);
            } else if (mode.toLowerCase() == 'load') {
                db.collection('load').insertOne({
                    "time": new Date(),
                    "load": ((parseFloat(value.replace(',', '.')) / 4) * 100)
                }, function(err, result){insertCallback(err, result, db, resolve, reject);});
                console.log(value);
            } else {
                db.close();
                reject('Invalid input');
            }
        });
    });
};

/**
 * Gets the 20 last entries of one mode
 * @param  {String} mode The type of entry to retrieve
 * @return {Function}    Returns either a resolve or reject function
 */
var realtime = function (mode) {
    var latest = [];

    return new Promise(function (resolve, reject) {
        connect(function (db) {
            var cursor = db.collection(mode).find({  }).limit(20).sort({time:-1});

            cursor.each(function (err, doc) {
                if (err) {
                    reject(err);
                }

                assert.equal(err, null);

                if (doc !== null) {
                    // Push [hh:mm:ss, temp|load] to latest
                    latest.push([doc.time.toTimeString().substr(0, 8),
                                 (doc.temp || doc.load)]);
                } else {
                    resolve(latest);
                    db.close();
                }
            });
        });
    });
};

/**
 * Get's the average temperature for the 20 last minutes
 * @param  {String} What type of entry to retrieve
 * @return {Array}  Two-dimentional array with HH:MM and temp|load:float
 */
var minute = function (mode) {
    var minutes = [];

    return new Promise(function (resolve, reject) {
        connect(function (db) {
            var count = -1;
            var prev = -1;
            var count_internal = 2;

            var cursor = db.collection(mode).find({}).sort({time:-1});

            cursor.each(function (err, doc) {
                if (err) {
                    reject(err);
                }

                assert.equal(err, null);

                if (doc !== null) {
                    if (count < 19 && doc.time.getMinutes() == prev) {
                        // Push [hh:mm:ss, temp|load] to minutes
                        minutes[count] = [doc.time.toTimeString().substr(0, 5),
                                          minutes[count][1] + (doc.temp || doc.load)];
                        count_internal++;
                    } else if (count < 19 && doc.time.getMinutes() != prev) {
                        count++;
                        prev = doc.time.getMinutes();
                        // Push [hh:mm:ss, temp|load] to minutes
                        minutes[count] = [doc.time.toTimeString().substr(0,5),
                                          0 + (doc.temp || doc.load)];
                        count_internal = 2;
                    } else {
                        resolve(minutes);
                        db.close();
                    }
                } else {
                    resolve(minutes);
                    db.close();
                }
            });
        });
    });
};

/**
 * Get's the average temperature for the last 10 hours
 * @param  {String} What type of entry to retrieve
 * @return {Array}  Two-dimentional array with Weekday date, hour:00
 */
var hour = function(mode) {
    var hours = [];

    return new Promise(function (resolve, reject) {
        connect(function (db) {
            var count = -1;
            var prev = -1;
            var count_internal = 2;

            var cursor = db.collection(mode).find({}).sort({time:-1});

            cursor.each(function (err, doc) {
                if (err) {
                    reject(err);
                }

                assert.equal(err, null);

                if (doc !== null) {
                    if (count < 9 && doc.time.getHours() == prev) {
                        // Push [hh:mm:ss, temp|load] to hours
                        hours[count] = [WEEKDAYS[doc.time.getDay()] + ' ' +
                                        doc.time.getDate() + ', ' +
                                        doc.time.toTimeString().substr(0,2) + ':00',
                                        hours[count][1] + (doc.temp || doc.load)];
                        count_internal++;
                    } else if (count < 9 && doc.time.getHours() != prev) {
                        count++;
                        prev = doc.time.getHours();
                        // Push [hh:mm:ss, temp|load] to hours
                        hours[count] = [WEEKDAYS[doc.time.getDay()] + ' ' +
                                        doc.time.getDate() + ', ' +
                                        doc.time.toTimeString().substr(0,2) + ':00',
                                        0 + (doc.temp || doc.load)];
                        count_internal = 2;
                    } else {
                        resolve(hours);
                        console.log(hours.length);
                        db.close();
                    }
                } else {
                    resolve(hours);
                    console.log(hours.length);
                    db.close();
                }
            });
        });
    });
};

/**
 * Get's the average temperature for the last week
 * @param  {String} What type of entry to retrieve
 * @return {Array}  Two-dimentional array with Weekday date/month
 */
var day = function(mode) {
    var days = [];

    return new Promise(function (resolve, reject) {
        connect(function (db) {
            var count = -1;
            var prev = -1;
            var count_internal = 2;

            var cursor = db.collection(mode).find({}).sort({time:-1});

            cursor.each(function (err, doc) {
                if (err) {
                    reject(err);
                }

                assert.equal(err, null);

                if (doc !== null) {
                    if (count < 6 && doc.time.getDate() == prev) {
                        // Push [hh:mm:ss, temp|load] to days
                        days[count] = [WEEKDAYS[doc.time.getDay()] + ' ' +
                                        doc.time.getDate() + '/' +
                                        (doc.time.getMonth() + 1),
                                        days[count][1] + (doc.temp || doc.load)];
                        count_internal++;
                    } else if (count < 6 && doc.time.getDate() != prev) {
                        count++;
                        prev = doc.time.getDate();
                        // Push [hh:mm:ss, temp|load] to days
                        days[count] = [WEEKDAYS[doc.time.getDay()] + ' ' +
                                        doc.time.getDate() + '/' +
                                        (doc.time.getMonth() + 1),
                                        0 + (doc.temp || doc.load)];
                        count_internal = 2;
                    } else {
                        resolve(days);
                        console.log(days);
                        db.close();
                    }
                } else {
                    resolve(days);
                    db.close();
                }
            });
        });
    });
};

// Exports

module.exports = {
    insert: insert,
    realtime: realtime,
    minute: minute,
    hour: hour,
    day: day
};
<|endoftext|>


<commit_before>angular.module('formyula.db', [])

.provider('$db', function() {
  var module = this;
  var dbVersion = 1;
  var dbSchema = {};
  var dbName = 'myIndexedDB';

  var server;

  module.connection = function(name, version, schema, callback) {
    dbName = name;
    dbVersion = version;
    dbSchema = schema;
  }

  this.$get = ['$q', '$rootScope', '$timeout', function($q, $rootScope, $timeout) {

    function ObjectStore(storeName) {
      this.storeName = storeName;
    }

    ObjectStore.prototype = {
      internalObjectStore: function() {
        var d = $q.defer();
        if (server) {
          d.resolve(server);
        } else {
          var prom = db.open({
            server: dbName,
            version: dbVersion,
            schema: dbSchema
          });
          prom.done(function(s) {
            server = s;
            console.log('successfully opened db');
            d.resolve(s);
          });
          prom.fail(function(e) {
            console.log('failed to open database');
            d.reject(e);
          });
        }
        return d.promise;
      },

      insert: function(value) {
        var d = $q.defer();
        var storeName = this.storeName;

        this.internalObjectStore().then(function(server) {
          var store = server[storeName];
          var prom = store.add(value);

          prom.done(function(data) {
            $rootScope.$apply(function() {
              d.resolve(data);
            });
          });

          prom.fail(function(err) {
            console.log('failed to insert:', err);
            $rootScope.$apply(function() {
              d.reject(err);
            });
          });
        }, function(e) {
          $rootScope.$apply(function() {
            d.reject(e);
          });
        });

        return d.promise;
      },

      upsert: function(value) {
        var d = $q.defer();
        var storeName = this.storeName;

        this.internalObjectStore().then(function(server) {
          var store = server[storeName];
          var prom = store.update(value);

          prom.done(function(data) {
            $rootScope.$apply(function() {
              d.resolve(data);
            });
          });

          prom.fail(function(err) {
            console.log('failed to upsert:', err);
            $rootScope.$apply(function() {
              d.reject(err);
            });
          });
        }, function(e) {
          $rootScope.$apply(function() {
            d.reject(e);
          });
        });

        return d.promise;
      },

      remove: function(key) {
        var d = $q.defer();
        var storeName = this.storeName;

        this.internalObjectStore().then(function(server) {
          var prom = server.remove(key);
          prom.done(function(key) {
            $rootScope.$apply(function() {
              d.resolve(key);
            });
          });
          prom.fail(function(err) {
            console.log('failed to remove:', err);
            $rootScope.$apply(function() {
              d.reject(err);
            });
          })
        }, function(e) {
          $rootScope.$apply(function() {
            d.reject(e);
          });
        });

        return d.promise;
      },

      find: function(key) {
        var d = $q.defer();
        var storeName = this.storeName;

        this.internalObjectStore().then(function(server) {
          var store = server[storeName];
          var prom = store.get(key);

          prom.done(function(data) {
            $rootScope.$apply(function() {
              d.resolve(data);
            });
          });

          prom.fail(function(err) {
            console.log('failed to find:', err);
            $rootScope.$apply(function() {
              d.reject(err);
            });
          });
        }, function(e) {
          $rootScope.$apply(function() {
            d.reject(e);
          });
        });

        return d.promise;
      },

      findMany: function(keys) {
        var d = $q.defer();
        var storeName = this.storeName;

        if (keys.length === 0) {
          console.log('asked for zero keys');
          $timeout(function() {
            $rootScope.$apply(function() {
              d.resolve([]);
            });
          }, 1);
          return d.promise;
        }

        this.internalObjectStore().then(function(server) {
          var store = server[storeName];
          var slots = [];
          var num = 0;

          var _resolve = function() {
            if (num == keys.length) {
              $rootScope.$apply(function() {
                var isFail = false;
                angular.forEach(slots, function(slot) {
                  if (slot === null) {
                    d.reject(slots);
                  } else {
                    d.resolve(slots);
                  }
                });
              });
            }
          }

          angular.forEach(keys, function(key, idx) {
            var i = idx;
            var prom = store.get(key);

            prom.done(function(data) {
              num++;
              slots[i] = data;
              _resolve();
            });

            prom.fail(function(err) {
              console.log('failed to find:', err);
              num++;
              slots[i] = null;
              _resolve();
            });
          });
        }, function(e) {
          $rootScope.$apply(function() {
            d.reject(e);
          });
        });

        return d.promise;
      },

      getAll: function() {
        var d = $q.defer();
        var storeName = this.storeName;

        this.internalObjectStore().then(function(server) {
          var store = server[storeName];
          var prom = store.query().filter().execute();

          prom.done(function(data) {
            $rootScope.$apply(function() {
              d.resolve(data);
            });
          });

          prom.fail(function(err) {
            console.log('failed to getAll:', err);
            $rootScope.$apply(function() {
              d.reject(err);
            });
          });
        }, function(e) {
          $rootScope.$apply(function() {
            d.reject(e);
          });
        });

        return d.promise;
      }
    }

    return {
      objectStore: function(name) {
        return new ObjectStore(name);
      }
    };
  }];
})
<commit_msg>fix remove not working properly<commit_after>angular.module('formyula.db', [])

.provider('$db', function() {
  var module = this;
  var dbVersion = 1;
  var dbSchema = {};
  var dbName = 'myIndexedDB';

  var server;

  module.connection = function(name, version, schema, callback) {
    dbName = name;
    dbVersion = version;
    dbSchema = schema;
  }

  this.$get = ['$q', '$rootScope', '$timeout', function($q, $rootScope, $timeout) {

    function ObjectStore(storeName) {
      this.storeName = storeName;
    }

    ObjectStore.prototype = {
      internalObjectStore: function() {
        var d = $q.defer();
        if (server) {
          d.resolve(server);
        } else {
          var prom = db.open({
            server: dbName,
            version: dbVersion,
            schema: dbSchema
          });
          prom.done(function(s) {
            server = s;
            console.log('successfully opened db');
            d.resolve(s);
          });
          prom.fail(function(e) {
            console.log('failed to open database');
            d.reject(e);
          });
        }
        return d.promise;
      },

      insert: function(value) {
        var d = $q.defer();
        var storeName = this.storeName;

        this.internalObjectStore().then(function(server) {
          var store = server[storeName];
          var prom = store.add(value);

          prom.done(function(data) {
            $rootScope.$apply(function() {
              d.resolve(data);
            });
          });

          prom.fail(function(err) {
            console.log('failed to insert:', err);
            $rootScope.$apply(function() {
              d.reject(err);
            });
          });
        }, function(e) {
          $rootScope.$apply(function() {
            d.reject(e);
          });
        });

        return d.promise;
      },

      upsert: function(value) {
        var d = $q.defer();
        var storeName = this.storeName;

        this.internalObjectStore().then(function(server) {
          var store = server[storeName];
          var prom = store.update(value);

          prom.done(function(data) {
            $rootScope.$apply(function() {
              d.resolve(data);
            });
          });

          prom.fail(function(err) {
            console.log('failed to upsert:', err);
            $rootScope.$apply(function() {
              d.reject(err);
            });
          });
        }, function(e) {
          $rootScope.$apply(function() {
            d.reject(e);
          });
        });

        return d.promise;
      },

      remove: function(key) {
        var d = $q.defer();
        var storeName = this.storeName;

        this.internalObjectStore().then(function(server) {
          var prom = server[storeName].remove(key);
          prom.done(function(key) {
            $rootScope.$apply(function() {
              d.resolve(key);
            });
          });
          prom.fail(function(err) {
            console.log('failed to remove:', err);
            $rootScope.$apply(function() {
              d.reject(err);
            });
          })
        }, function(e) {
          $rootScope.$apply(function() {
            d.reject(e);
          });
        });

        return d.promise;
      },

      find: function(key) {
        var d = $q.defer();
        var storeName = this.storeName;

        this.internalObjectStore().then(function(server) {
          var store = server[storeName];
          var prom = store.get(key);

          prom.done(function(data) {
            $rootScope.$apply(function() {
              d.resolve(data);
            });
          });

          prom.fail(function(err) {
            console.log('failed to find:', err);
            $rootScope.$apply(function() {
              d.reject(err);
            });
          });
        }, function(e) {
          $rootScope.$apply(function() {
            d.reject(e);
          });
        });

        return d.promise;
      },

      findMany: function(keys) {
        var d = $q.defer();
        var storeName = this.storeName;

        if (keys.length === 0) {
          console.log('asked for zero keys');
          $timeout(function() {
            $rootScope.$apply(function() {
              d.resolve([]);
            });
          }, 1);
          return d.promise;
        }

        this.internalObjectStore().then(function(server) {
          var store = server[storeName];
          var slots = [];
          var num = 0;

          var _resolve = function() {
            if (num == keys.length) {
              $rootScope.$apply(function() {
                var isFail = false;
                angular.forEach(slots, function(slot) {
                  if (slot === null) {
                    d.reject(slots);
                  } else {
                    d.resolve(slots);
                  }
                });
              });
            }
          }

          angular.forEach(keys, function(key, idx) {
            var i = idx;
            var prom = store.get(key);

            prom.done(function(data) {
              num++;
              slots[i] = data;
              _resolve();
            });

            prom.fail(function(err) {
              console.log('failed to find:', err);
              num++;
              slots[i] = null;
              _resolve();
            });
          });
        }, function(e) {
          $rootScope.$apply(function() {
            d.reject(e);
          });
        });

        return d.promise;
      },

      getAll: function() {
        var d = $q.defer();
        var storeName = this.storeName;

        this.internalObjectStore().then(function(server) {
          var store = server[storeName];
          var prom = store.query().filter().execute();

          prom.done(function(data) {
            $rootScope.$apply(function() {
              d.resolve(data);
            });
          });

          prom.fail(function(err) {
            console.log('failed to getAll:', err);
            $rootScope.$apply(function() {
              d.reject(err);
            });
          });
        }, function(e) {
          $rootScope.$apply(function() {
            d.reject(e);
          });
        });

        return d.promise;
      }
    }

    return {
      objectStore: function(name) {
        return new ObjectStore(name);
      }
    };
  }];
})
<|endoftext|>


<commit_before>// Fullscreen canvas
function fc(fn, autorun, dimensions) {
  document.body.style.margin = "0px";
  document.body.style.padding = "0px";

  var canvas = document.createElement('canvas');
  document.body.appendChild(canvas);
  canvas.style.position = 'absolute';
  canvas.style.left = '0px';
  canvas.style.top = '0px';

  var ctx;
  dimensions = dimensions || 2;

  if (dimensions === 2) {
    ctx = canvas.getContext('2d');
  } else if (dimensions === 3) {
    ctx = canvas.getContext('webgl') || canvas.getContext('experimental-webgl');
  }

  if (!ctx) {
    return;
  }

  var last = 0, dirty = false, request;

  function tick(time) {
    time = time || 0;
    var delta = time-last;
    last = time;

    ctx.reset();

    dimensions === 2 && ctx.save();
    fn && fn(delta);
    dimensions === 2 && ctx.restore();
    if (autorun !== false) {
      requestAnimationFrame(tick);
    }
    dirty = false;
  }

  if (dimensions === 2) {
    ctx.reset = function() {
      canvas.width = 0;
      canvas.width = window.innerWidth;
      canvas.height = window.innerHeight;
    };

    ctx.clear = function(color) {
      var orig = ctx.fillStyle;
      ctx.fillStyle = color || "#223";
      ctx.fillRect(0, 0, canvas.width, canvas.height);
      ctx.fillStyle = orig;
    };
  } else {
    ctx.reset = function() {
      if (canvas.width !== window.innerWidth) {
        canvas.width = window.innerWidth;
      }

      if (canvas.height !== window.innerHeight) {
        canvas.height = window.innerHeight;
      }
    }
  }

  setTimeout(tick, 0);

  ctx.dirty = function() {
    if (!dirty) {
      request = requestAnimationFrame(tick);
      dirty = true;
    }
  };

  ctx.stop = function() {
    autorun = false;
    dirty = false;
    request && cancelAnimationFrame(request);
  };

  ctx.start = function() {
    autorun = true;
    requestAnimationFrame(tick);
  };

  (window.attachEvent || window.addEventListener)('resize', ctx.dirty);

  ctx.canvas = canvas;
  return ctx;
};

if (typeof module !== 'undefined' && typeof module.exports !== 'undefined') {
  module.exports = fc;
}

if (typeof window !== 'undefined') {
  window.fc = window.fc || fc;
}
<commit_msg>use window.performance.now when available<commit_after>;(function() {

  var performance = window.performance || {}
  var performanceNow =
    performance.now        ||
    performance.now        ||
    performance.mozNow     ||
    performance.msNow      ||
    performance.oNow       ||
    performance.webkitNow  ||
    function(){ return (new Date()).getTime() }
  performanceNow = performanceNow.bind(performance)

  // Fullscreen canvas
  function fc(fn, autorun, dimensions) {
    document.body.style.margin = "0px";
    document.body.style.padding = "0px";

    var canvas = document.createElement('canvas');
    document.body.appendChild(canvas);
    canvas.style.position = 'absolute';
    canvas.style.left = '0px';
    canvas.style.top = '0px';

    var ctx;
    dimensions = dimensions || 2;

    if (dimensions === 2) {
      ctx = canvas.getContext('2d');
    } else if (dimensions === 3) {
      ctx = canvas.getContext('webgl') || canvas.getContext('experimental-webgl');
    }

    if (!ctx) {
      return;
    }

    var last = performanceNow(), request;

    function tick() {
      request = null;
      var time = performanceNow();
      var delta = time-last;
      last = time;

      ctx.reset();

      dimensions === 2 && ctx.save();
      fn && fn(delta);
      dimensions === 2 && ctx.restore();
      if (autorun && !request) {
        request = requestAnimationFrame(tick);
      }
    }

    if (dimensions === 2) {
      ctx.reset = function() {
        canvas.width = 0;
        canvas.width = window.innerWidth;
        canvas.height = window.innerHeight;
      };

      ctx.clear = function(color) {
        var orig = ctx.fillStyle;
        ctx.fillStyle = color || "#223";
        ctx.fillRect(0, 0, canvas.width, canvas.height);
        ctx.fillStyle = orig;
      };
    } else {
      ctx.reset = function() {
        if (canvas.width !== window.innerWidth) {
          canvas.width = window.innerWidth;
        }

        if (canvas.height !== window.innerHeight) {
          canvas.height = window.innerHeight;
        }
      }
    }

    setTimeout(tick, 0);

    ctx.dirty = function() {
      if (!request) {
        // reset the last time so we don't get weird jumps
        last = performanceNow();

        request = requestAnimationFrame(tick);
      }
    };

    ctx.stop = function() {
      autorun = false;
      request && cancelAnimationFrame(request);
    };

    ctx.start = function() {
      autorun = true;
      if (!request) {
        request = requestAnimationFrame(tick);
      }
    };

    (window.attachEvent || window.addEventListener)('resize', ctx.dirty);

    ctx.canvas = canvas;
    return ctx;
  };

  if (typeof module !== 'undefined' && typeof module.exports !== 'undefined') {
    module.exports = fc;
  }

  if (typeof window !== 'undefined') {
    window.fc = window.fc || fc;
  }
})();
<|endoftext|>


<commit_before>function FN() { return this; }

FN.prototype.any = function(lst, cb) {
  var result = false;
  if(lst instanceof Array) {
    lst.forEach(function(element, index, array) {
      if(element) result = true;
    });
  }

  if(cb !== undefined && result) cb();
  else return result;
};

FN.prototype.all = function(lst, cb) {
  var result = true;
  if(lst instanceof Array && lst.length > 0) {
    lst.forEach(function(element, index, array) {
      if(!element) result = false;
    });

    if(cb !== undefined && result) cb();
    else return result;
  }
  else return false;
};

FN.prototype.first = function(lst, cb) {
  if(lst instanceof Array) {
    if(cb !== undefined && lst[0] !== undefined) cb();
    else return (lst instanceof Array) ? lst[0] : undefined;
  }
  return undefined;
};

FN.prototype.last = function(lst, cb) {
  if(lst instanceof Array && lst.length > 0) {
    if(cb !== undefined) cb(lst[lst.length-1]);
    else return lst[lst.length-1];
  }
  return undefined;
};

// Stick with zero indexing.
FN.prototype.nth = function(lst, nth, cb) {
  if(lst instanceof Array && nth <= lst.length) {
    if(cb !== undefined) cb(lst[nth])
    else return lst[nth];
  }
  return undefined;
};

FN.prototype.rest = function(lst, cb) {
  if(lst instanceof Array && lst.length > 0) {
    if(cb !== undefined) cb(lst.slice(1));
    else return lst.slice(1);
  }
  return undefined;
};

var fn = new FN();
var all = fn.all;
var any = fn.any;
var first = fn.first;
var last = fn.last;
var nth = fn.nth;
var rest = fn.rest;
<commit_msg>Fixed a bug where the first element in 'first' wasn't passed into the callback.<commit_after>function FN() { return this; }

FN.prototype.any = function(lst, cb) {
  var result = false;
  if(lst instanceof Array) {
    lst.forEach(function(element, index, array) {
      if(element) result = true;
    });
  }

  if(cb !== undefined && result) cb();
  else return result;
};

FN.prototype.all = function(lst, cb) {
  var result = true;
  if(lst instanceof Array && lst.length > 0) {
    lst.forEach(function(element, index, array) {
      if(!element) result = false;
    });

    if(cb !== undefined && result) cb();
    else return result;
  }
  else return false;
};

FN.prototype.first = function(lst, cb) {
  if(lst instanceof Array) {
    if(cb !== undefined && lst[0] !== undefined) cb(lst[0]);
    else return (lst instanceof Array) ? lst[0] : undefined;
  }
  return undefined;
};

FN.prototype.last = function(lst, cb) {
  if(lst instanceof Array && lst.length > 0) {
    if(cb !== undefined) cb(lst[lst.length-1]);
    else return lst[lst.length-1];
  }
  return undefined;
};

// Stick with zero indexing.
FN.prototype.nth = function(lst, nth, cb) {
  if(lst instanceof Array && nth <= lst.length) {
    if(cb !== undefined) cb(lst[nth])
    else return lst[nth];
  }
  return undefined;
};

FN.prototype.rest = function(lst, cb) {
  if(lst instanceof Array && lst.length > 0) {
    if(cb !== undefined) cb(lst.slice(1));
    else return lst.slice(1);
  }
  return undefined;
};

var fn = new FN();
var all = fn.all;
var any = fn.any;
var first = fn.first;
var last = fn.last;
var nth = fn.nth;
var rest = fn.rest;
<|endoftext|>


<commit_before>// Analytics for Vaadin Components

(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
  (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
  m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
})(window,document,'script','//www.google-analytics.com/analytics.js','ga');

ga('create', 'UA-658457-6', 'auto');

function locationHashChanged() {
  if(/vaadin/.test(window.location.hostname)) {
    var pageViewUrl = (window.location.pathname + window.location.hash)
      .replace(/vaadin-components\/latest\/(.+)\/demo/, 'components-examples/$1')
      .replace('#', '/');
    ga('send', 'pageview', pageViewUrl)
  }
}

window.onhashchange = locationHashChanged;
locationHashChanged();
<commit_msg>Set new path in ga.js<commit_after>// Analytics for Vaadin Components

(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
  (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
  m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
})(window,document,'script','//www.google-analytics.com/analytics.js','ga');

ga('create', 'UA-658457-6', 'auto');

function locationHashChanged() {
  if(/vaadin/.test(window.location.hostname)) {
    var pageViewUrl = (window.location.pathname + window.location.hash)
      .replace(/vaadin-elements\/latest\/(.+)\/demo/, 'components-examples/$1')
      .replace('#', '/');
    ga('send', 'pageview', pageViewUrl)
  }
}

window.onhashchange = locationHashChanged;
locationHashChanged();
<|endoftext|>


<commit_before> window.onload = init;
 var gridSize = 50;
 var boardState = new Array();
 var TimeLeft = new Array();
 var PlayerColor = 1;
 var AIColor = 0;
 var MaxLifeTime = 6;
 var EMPTY = -1;
 var GameStartFlag = 0;
 var PlayerFirst = 1;
 var HasWinner = 0;
 var ClickLock = 0;
 var HighLightType = {
 	p1x: -1,
 	p1y: -1,
 	p2x: -1,
 	p2y: -1,
 	p3x: -1,
 	p3y: -1,
 };
 function init() {
 	for (var i = 0; i < 3; i++) {
 		boardState[i] = new Array();
 		TimeLeft[i] = new Array();
 		for (var j = 0; j < 3; j++) {
 			boardState[i][j] = EMPTY;
 			TimeLeft[i][j] = 0;
 		    document.getElementById("grid"+(i+1)+(j+1)).onclick = MouseClick;
 		};
 	};
 	ClickLock = 0;
 }

 function IsPlayerFirst() {
 	var radio = document.getElementsByName("radio");
 	return radio[0].checked == true ? 1 : 0;
 }

 function StartGame() {
 	if (HasWinner) {
 		GameStartFlag = 1;
 		HasWinner = 0;
 	}
 	if (!GameStartFlag) {
 		GameStartFlag = 1;
 		if (!IsPlayerFirst()) AIMove();
 		document.getElementById("startGame").innerHTML = "结束游戏";
 	} else {
 		GameStartFlag = 0;
 		document.getElementById("startGame").innerHTML = "开始游戏";
 		init();
 		DrawGame();
 	}
 	DrawGame();
 	document.getElementById("cp_dilg").innerHTML = "战个痛！！";
 }

 function MouseClick(event) {
 	if (!GameStartFlag) return;
 	if (ClickLock) return;
	gridId = this.id;
	y = parseInt(gridId.charAt(4))-1;
	x = parseInt(gridId.charAt(5))-1;

 	var result = SetGame(y, x, boardState, TimeLeft, PlayerColor);
 	DrawGame();
 	if (result == -1) {
 		ClickLock = 1;
 		setTimeout('AIMove()',800);
 	} else if (result == AIColor) {
 		document.getElementById("cp_dilg").innerHTML = "哇咔咔，我赢了！！";
 		GameStartFlag = 0;
 		HasWinner = 1;
 	} else if (result == PlayerColor) {
 		document.getElementById("cp_dilg").innerHTML = "你。。。居然赢了我。。这不科学！！";
 		GameStartFlag = 0;
 		HasWinner = 1;
 		DrawGame();
 	}
 }

 function SetGame(x, y, mboardState, mTimeLeft, IsPlayerMove) {
 	if (mboardState[x][y] != EMPTY)
 		return;
 	mboardState[x][y] = IsPlayerMove;
 	mTimeLeft[x][y] = MaxLifeTime + 1;
 	for (var i = 0; i < 3; i++) {
 		for (var j = 0; j < 3; j++) {
 			if (mTimeLeft[i][j] > 0) mTimeLeft[i][j]--;
 			if (mTimeLeft[i][j] == 0) mboardState[i][j] = EMPTY;
 		};
 	};
 	return GameFinished(mboardState);
 }

 function DrawGame() {
 	for (var i = 0; i < 3; i++) {
 		for (var j = 0; j < 3; j++) {
 			var grid = document.getElementById("grid" + (i + 1) + (j + 1)).getElementsByTagName("div");
 			grid[0].style.color="#000";
 			if (boardState[i][j] == PlayerColor) grid[0].innerHTML = "X";
 			else if (boardState[i][j] == AIColor) grid[0].innerHTML = "O";
 			else {
 				grid[0].innerHTML = " ";
 				grid[1].innerHTML = " ";
 			}

 			if (TimeLeft[i][j] != 0)
 				grid[1].innerHTML = TimeLeft[i][j] - 1;
 		}
 	}
 	if (HasWinner) {
 		grid = document.getElementById("grid" + (HighLightType.p1x + 1) + (HighLightType.p1y + 1)).getElementsByTagName("div");
 		grid[0].style.color="#F00";
 		grid = document.getElementById("grid" + (HighLightType.p2x + 1) + (HighLightType.p2y + 1)).getElementsByTagName("div");
 		grid[0].style.color="#F00";
 		grid = document.getElementById("grid" + (HighLightType.p3x + 1) + (HighLightType.p3y + 1)).getElementsByTagName("div");
 		grid[0].style.color="#F00";
 	};
 }

 function GameFinished(mboardState) {
 	for (var i = 0; i < 3; i++) {
 		if (mboardState[i][0] != EMPTY &&
 			mboardState[i][1] == mboardState[i][0] &&
 			mboardState[i][2] == mboardState[i][0]) {
 			HighLightType = {
 				p1x: i,
 				p1y: 0,
 				p2x: i,
 				p2y: 1,
 				p3x: i,
 				p3y: 2,
 			};
 			return mboardState[i][0];
 		}
 		if (mboardState[0][i] != EMPTY &&
 			mboardState[1][i] == mboardState[0][i] &&
 			mboardState[2][i] == mboardState[0][i]) {
 			HighLightType = HighLightType = {
 				p1x: 0,
 				p1y: i,
 				p2x: 1,
 				p2y: i,
 				p3x: 2,
 				p3y: i,
 			};
 			return mboardState[0][i];
 		}
 	}
 	if (mboardState[0][0] != EMPTY &&
 		mboardState[0][0] == mboardState[1][1] &&
 		mboardState[1][1] == mboardState[2][2]) {
 		HighLightType = HighLightType = {
 			p1x: 0,
 			p1y: 0,
 			p2x: 1,
 			p2y: 1,
 			p3x: 2,
 			p3y: 2,
 		};
 		return mboardState[0][0];
 	}
 	if (mboardState[2][0] != EMPTY &&
 		mboardState[2][0] == mboardState[1][1] &&
 		mboardState[1][1] == mboardState[0][2]) {
 		HighLightType = HighLightType = {
 			p1x: 2,
 			p1y: 0,
 			p2x: 1,
 			p2y: 1,
 			p3x: 0,
 			p3y: 2,
 		};
 		return mboardState[0][2];
 	}
 	return -1;
 }

 function AIMove() {
 	var MaxScore = -999999;
 	var bestmove = {
 		x: -1,
 		y: -1
 	};
 	for (var i = 0; i < 3; i++) {
 		for (var j = 0; j < 3; j++) {
 			if (boardState[i][j] != EMPTY)
 				continue;
 			var boardState_t = Array2DClone(boardState);
 			var TimeLeft_t = Array2DClone(TimeLeft);

 			var result = SetGame(i, j, boardState_t, TimeLeft_t, AIColor);
 			if (result == AIColor) {
 				MaxScore = 999999;
 				bestmove = {
 					x: i,
 					y: j
 				};
 			} else {
 				var score = MinMax(boardState_t, TimeLeft_t, 0, IsPlayerFirst() ? 3 : 10);
 				if (score >= MaxScore) {
 					bestmove = {
 						x: i,
 						y: j
 					};
 					MaxScore = score;
 				};
 			}
 		}
 	}
 	if (MaxScore == 1) {
 		document.getElementById("cp_dilg").innerHTML = "我已经看到结局了！！";
 	}
 	if (AIColor == SetGame(bestmove.x, bestmove.y, boardState, TimeLeft, AIColor)) {
 		document.getElementById("cp_dilg").innerHTML = "哇咔咔，我赢了！！";
 		HasWinner = 1;
 		GameStartFlag = 0;
 	}
 	DrawGame();
 	ClickLock = 0;
 }

 function MinMax(mboardState, mTimeLeft, AITurn, Depth) {
 	var curscore = 99999 * (AITurn == 1 ? -1 : 1);
 	Depth--;
 	if (!Depth) return 0;
 	for (var i = 0; i < 3; i++) {
 		for (var j = 0; j < 3; j++) {
 			if (mboardState[i][j] != EMPTY)
 				continue;
 			var boardState_t = Array2DClone(mboardState);
 			var TimeLeft_t = Array2DClone(mTimeLeft);

 			var judge = SetGame(i, j, boardState_t, TimeLeft_t, AITurn ? AIColor : PlayerColor);
 			if (judge == AIColor) return 1;
 			if (judge == PlayerColor) return -1;

 			var temp_score = MinMax(boardState_t, TimeLeft_t, AITurn ? 0 : 1, Depth);
 			if (AITurn && temp_score > curscore) {
 				curscore = temp_score;
 			} else if (!AITurn && temp_score < curscore) {
 				curscore = temp_score;
 			}
 			if(AITurn && curscore == 1)	return 1;
 			else if(!AITurn && curscore == -1) return -1;
 		}
 	}
 	return curscore;
 }

 function Array2DClone(src) {
 	var dst = new Array();
 	for (var i = 0; i < 3; i++) {
 		dst[i] = new Array();
 		for (var j = 0; j < 3; j++) {
 			dst[i][j] = src[i][j];
 		};
 	};
 	return dst;
 }<commit_msg>ai update<commit_after> window.onload = init;
 var gridSize = 50;
 var boardState = new Array();
 var TimeLeft = new Array();
 var PlayerColor = 1;
 var AIColor = 0;
 var MaxLifeTime = 6;
 var EMPTY = -1;
 var GameStartFlag = 0;
 var PlayerFirst = 1;
 var HasWinner = 0;
 var ClickLock = 0;
 var HighLightType = {
 	p1x: -1,
 	p1y: -1,
 	p2x: -1,
 	p2y: -1,
 	p3x: -1,
 	p3y: -1,
 };
 function init() {
 	for (var i = 0; i < 3; i++) {
 		boardState[i] = new Array();
 		TimeLeft[i] = new Array();
 		for (var j = 0; j < 3; j++) {
 			boardState[i][j] = EMPTY;
 			TimeLeft[i][j] = 0;
 		    document.getElementById("grid"+(i+1)+(j+1)).onclick = MouseClick;
 		};
 	};
 	ClickLock = 0;
 }

 function IsPlayerFirst() {
 	var radio = document.getElementsByName("radio");
 	return radio[0].checked == true ? 1 : 0;
 }

 function StartGame() {
 	if (HasWinner) {
 		GameStartFlag = 1;
 		HasWinner = 0;
 	}
 	if (!GameStartFlag) {
 		GameStartFlag = 1;
 		if (!IsPlayerFirst()) AIMove();
 		document.getElementById("startGame").innerHTML = "结束游戏";
 	} else {
 		GameStartFlag = 0;
 		document.getElementById("startGame").innerHTML = "开始游戏";
 		init();
 		DrawGame();
 	}
 	DrawGame();
 	document.getElementById("cp_dilg").innerHTML = "战个痛！！";
 }

 function MouseClick(event) {
 	if (!GameStartFlag) return;
 	if (ClickLock) return;
	gridId = this.id;
	y = parseInt(gridId.charAt(4))-1;
	x = parseInt(gridId.charAt(5))-1;

 	var result = SetGame(y, x, boardState, TimeLeft, PlayerColor);
 	DrawGame();
 	if (result == -1) {
 		ClickLock = 1;
 		setTimeout('AIMove()',800);
 	} else if (result == AIColor) {
 		document.getElementById("cp_dilg").innerHTML = "哇咔咔，我赢了！！";
 		GameStartFlag = 0;
 		HasWinner = 1;
 	} else if (result == PlayerColor) {
 		document.getElementById("cp_dilg").innerHTML = "你。。。居然赢了我。。这不科学！！";
 		GameStartFlag = 0;
 		HasWinner = 1;
 		DrawGame();
 	}
 }

 function SetGame(x, y, mboardState, mTimeLeft, IsPlayerMove) {
 	if (mboardState[x][y] != EMPTY)
 		return;
 	mboardState[x][y] = IsPlayerMove;
 	mTimeLeft[x][y] = MaxLifeTime + 1;
 	for (var i = 0; i < 3; i++) {
 		for (var j = 0; j < 3; j++) {
 			if (mTimeLeft[i][j] > 0) mTimeLeft[i][j]--;
 			if (mTimeLeft[i][j] == 0) mboardState[i][j] = EMPTY;
 		};
 	};
 	return GameFinished(mboardState);
 }

 function DrawGame() {
 	for (var i = 0; i < 3; i++) {
 		for (var j = 0; j < 3; j++) {
 			var grid = document.getElementById("grid" + (i + 1) + (j + 1)).getElementsByTagName("div");
 			grid[0].style.color="#000";
 			if (boardState[i][j] == PlayerColor) grid[0].innerHTML = "X";
 			else if (boardState[i][j] == AIColor) grid[0].innerHTML = "O";
 			else {
 				grid[0].innerHTML = " ";
 				grid[1].innerHTML = " ";
 			}

 			if (TimeLeft[i][j] != 0)
 				grid[1].innerHTML = TimeLeft[i][j] - 1;
 		}
 	}
 	if (HasWinner) {
 		grid = document.getElementById("grid" + (HighLightType.p1x + 1) + (HighLightType.p1y + 1)).getElementsByTagName("div");
 		grid[0].style.color="#F00";
 		grid = document.getElementById("grid" + (HighLightType.p2x + 1) + (HighLightType.p2y + 1)).getElementsByTagName("div");
 		grid[0].style.color="#F00";
 		grid = document.getElementById("grid" + (HighLightType.p3x + 1) + (HighLightType.p3y + 1)).getElementsByTagName("div");
 		grid[0].style.color="#F00";
 	};
 }

 function GameFinished(mboardState) {
 	for (var i = 0; i < 3; i++) {
 		if (mboardState[i][0] != EMPTY &&
 			mboardState[i][1] == mboardState[i][0] &&
 			mboardState[i][2] == mboardState[i][0]) {
 			HighLightType = {
 				p1x: i,
 				p1y: 0,
 				p2x: i,
 				p2y: 1,
 				p3x: i,
 				p3y: 2,
 			};
 			return mboardState[i][0];
 		}
 		if (mboardState[0][i] != EMPTY &&
 			mboardState[1][i] == mboardState[0][i] &&
 			mboardState[2][i] == mboardState[0][i]) {
 			HighLightType = HighLightType = {
 				p1x: 0,
 				p1y: i,
 				p2x: 1,
 				p2y: i,
 				p3x: 2,
 				p3y: i,
 			};
 			return mboardState[0][i];
 		}
 	}
 	if (mboardState[0][0] != EMPTY &&
 		mboardState[0][0] == mboardState[1][1] &&
 		mboardState[1][1] == mboardState[2][2]) {
 		HighLightType = HighLightType = {
 			p1x: 0,
 			p1y: 0,
 			p2x: 1,
 			p2y: 1,
 			p3x: 2,
 			p3y: 2,
 		};
 		return mboardState[0][0];
 	}
 	if (mboardState[2][0] != EMPTY &&
 		mboardState[2][0] == mboardState[1][1] &&
 		mboardState[1][1] == mboardState[0][2]) {
 		HighLightType = HighLightType = {
 			p1x: 2,
 			p1y: 0,
 			p2x: 1,
 			p2y: 1,
 			p3x: 0,
 			p3y: 2,
 		};
 		return mboardState[0][2];
 	}
 	return -1;
 }

 function AIMove() {
 	var MaxScore = -999999;
 	var bestmove = {
 		x: -1,
 		y: -1
 	};
 	for (var i = 0; i < 3; i++) {
 		for (var j = 0; j < 3; j++) {
 			if (boardState[i][j] != EMPTY)
 				continue;
 			var boardState_t = Array2DClone(boardState);
 			var TimeLeft_t = Array2DClone(TimeLeft);

 			var result = SetGame(i, j, boardState_t, TimeLeft_t, AIColor);
 			if (result == AIColor) {
 				MaxScore = 999999;
 				bestmove = {
 					x: i,
 					y: j
 				};
 			} else {
 				var score = MinMax(boardState_t, TimeLeft_t, 0, IsPlayerFirst() ? 10 : 10);
 				if (score >= MaxScore) {
 					bestmove = {
 						x: i,
 						y: j
 					};
 					MaxScore = score;
 				};
 			}
 		}
 	}
 	if (MaxScore == 1) {
 		document.getElementById("cp_dilg").innerHTML = "我已经看到结局了！！";
 	}
 	if (AIColor == SetGame(bestmove.x, bestmove.y, boardState, TimeLeft, AIColor)) {
 		document.getElementById("cp_dilg").innerHTML = "哇咔咔，我赢了！！";
 		HasWinner = 1;
 		GameStartFlag = 0;
 	}
 	DrawGame();
 	ClickLock = 0;
 }

 function MinMax(mboardState, mTimeLeft, AITurn, Depth) {
 	var curscore = 99999 * (AITurn == 1 ? -1 : 1);
 	Depth--;
 	if (!Depth) return 0;
 	for (var i = 0; i < 3; i++) {
 		for (var j = 0; j < 3; j++) {
 			if (mboardState[i][j] != EMPTY)
 				continue;
 			var boardState_t = Array2DClone(mboardState);
 			var TimeLeft_t = Array2DClone(mTimeLeft);

 			var judge = SetGame(i, j, boardState_t, TimeLeft_t, AITurn ? AIColor : PlayerColor);
 			if (judge == AIColor) return 1;
 			if (judge == PlayerColor) return -1;

 			var temp_score = MinMax(boardState_t, TimeLeft_t, AITurn ? 0 : 1, Depth);
 			if (AITurn && temp_score > curscore) {
 				curscore = temp_score;
 			} else if (!AITurn && temp_score < curscore) {
 				curscore = temp_score;
 			}
 			if(AITurn && curscore == 1)	return 1;
 			else if(!AITurn && curscore == -1) return -1;
 		}
 	}
 	return curscore;
 }

 function Array2DClone(src) {
 	var dst = new Array();
 	for (var i = 0; i < 3; i++) {
 		dst[i] = new Array();
 		for (var j = 0; j < 3; j++) {
 			dst[i][j] = src[i][j];
 		};
 	};
 	return dst;
 }<|endoftext|>


<commit_before>/*
Copyright 2012 - $Date $ by PeopleWare n.v.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

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

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

define([],
  function() {

    function typeOf(obj) {
      // summary:
      //   A better type then Object.toString() or typeof.
      // description:
      //      toType(undefined); //"undefined"
      //      toType(new); //"null"
      //      toType({a: 4}); //"object"
      //      toType([1, 2, 3]); //"array"
      //      (function() {console.log(toType(arguments))})(); //arguments
      //      toType(new ReferenceError); //"error"
      //      toType(new Date); //"date"
      //      toType(/a-z/); //"regexp"
      //      toType(Math); //"math"
      //      toType(JSON); //"json"
      //      toType(new Number(4)); //"number"
      //      toType(new String("abc")); //"string"
      //      toType(new Boolean(true)); //"boolean"

      /* based on
       http://javascriptweblog.wordpress.com/2011/08/08/fixing-the-javascript-typeof-operator/
       */

      if (obj === null) {
        // workaround for eopdf; it seems that js.typeOf(null) is returned by eopdf as "domwindow"
        return "null";
      }
      var result = Object.prototype.toString.call(obj).match(/\s([a-zA-Z]+)/)[1].toLowerCase();
      // on some browsers, the main window returns as "global" (WebKit) or "window" (FF), but this is an object too
      if (result === "global" || result == "window") {
        result = "object";
      }
      return result; // return String
    }

    function getPrototypeChain(/*Object*/ obj) {
      // summary:
      //   Returns an array where result[i] is the prototype
      //   of result[i-1], with obj === result[0]. result[length]
      //   is thus Object.prototype.

      function recursive(acc, o) {
        if (!o) {
          return acc;
        }
        else {
          acc.push(o);
          return recursive(acc, Object.getPrototypeOf(o));
        }
      }

      return recursive([], obj);
    }

    function getAllKeys(/*Object*/ obj) {
      // summary:
      //   Returns an array containing the names of all given objects enumerable properties.
      //   Like keys, but for the entire prototype chain. The array starts with the properties
      //   of Object.prototype, and works down the chain.

      return getPrototypeChain(obj).reduceRight(
        function(acc, proto) {
          return nub(acc.concat(Object.keys(proto)));
        },
        []
      );
    }

    function isInt(/*Number*/ n) {
      // summary:
      //   True if n is an integer.
      //   n must be a number.

      return n % 1 === 0;
    }

    function nub(/*Array*/ array, /*Boolean?*/ removeNull) {
      // summary:
      //   Returns an array that has all the elements of `array`, in order, but with later duplicates removed.
      //   If `removeNull` is given and thruthy, nulls and undefineds are removed too.

      if (!array) {
        return array;
      }
      var result = array.reduce(
        function(acc, el) {
          if ((!removeNull || el) && acc.indexOf(el) < 0) {
            acc.push(el);
          }
          return acc;
        },
        []
      );
      return result;
    }

    function substitute(/*String*/ str, /*Object*/ context) {
      // summary:
      //  All occurrences of "${...}$" in `str` are replaced by the result of the
      //  execution of what is between the curly brackets as JavaScript, with `context`
      //  as `this`.

      //   Like dojo/string.substitute, but evals full code.
      //   No formatting (yet).
      return str.replace( // return String
        /\$\{(.+?)\}\$/gm,
        function(match, pattern) {
          var value;
          try {
            var executor = new Function("return (" + pattern + ");");
            value = executor.call(context);
          }
          catch (err) {
            // IDEA: consider logger
            console.error("Executing pattern substitution of ${" + pattern + "}$ in '" + str + "' with context " + context, err);
            return "?? ${" + pattern  + "}$ -- " + (err.message || err) + " ??";
          }
          return value || value === "" ? value.toString() : "?" + pattern  + "?";
        }
      );
    }

    function sortComparable(/*Object*/ c1, /*Object*/ c2) {
      // summary:
      //   A sort function for objects that have a compare function.
      //   undefined < null < the compare function of the objects

      return c1 === undefined ? (
               c2 === undefined ? 0 : -1
             )
             : (
               c1 === null ? (
                 c2 === undefined ?
                   +1 :
                   c2 === null ? 0 : -1
               )
               : (
                 !c2 ? +1 : c1.compare(c2)
               )
             );
    }

    function sortReversed(/*Function*/ sort) {
      // summary:
      //   Produces a compare function that does the reverse sort defined by sort.

      return function(o1, o2) {
        return -sort(o1, o2);
      }
    }

    function sortVersionNumbers(/*Array*/ arrayToSort) {
      /**
       * Compares two software version numbers (e.g. "1.7.1" or "1.2b").
       *
       * This function was born in http://stackoverflow.com/a/6832721.
       *
       * @param {string} v1 The first version to be compared.
       * @param {string} v2 The second version to be compared.
       * @param {object} [options] Optional flags that affect comparison behavior:
       *

       *

       *         <tt>lexicographical: true</tt> compares each part of the version strings lexicographically instead of
       *         naturally; this allows suffixes such as "b" or "dev" but will cause "1.10" to be considered smaller than
       *         "1.2".
       *

       *

       *         <tt>zeroExtend: true</tt> changes the result if one version string has less parts than the other. In
       *         this case the shorter string will be padded with "zero" parts instead of being considered smaller.
       *

       *

       * @returns {number|NaN}
       *

       *
0 if the versions are equal

       *
a negative integer iff v1 < v2

       *
a positive integer iff v1 > v2

       *
NaN if either version string is in the wrong format

       *

       *
       * @copyright by Jon Papaioannou (["john", "papaioannou"].join(".") + "@gmail.com")
       * @license This function is in the public domain. Do what you want with it, no strings attached.
       */
      arrayToSort.sort(function(/*String*/ v1, /*String*/ v2, /*Object*/ options) {
        var lexicographical = options && options.lexicographical,
          zeroExtend = options && options.zeroExtend,
          v1parts = v1.split('.'),
          v2parts = v2.split('.');

        function isValidPart(x) {
          return (lexicographical ? /^\d+[A-Za-z]*$/ : /^\d+$/).test(x);
        }

        if (!v1parts.every(isValidPart) || !v2parts.every(isValidPart)) {
          return NaN;
        }

        if (zeroExtend) {
          while (v1parts.length < v2parts.length) {
            v1parts.push("0");
          }
          while (v2parts.length < v1parts.length) {
            v2parts.push("0");
          }
        }

        if (!lexicographical) {
          v1parts = v1parts.map(Number);
          v2parts = v2parts.map(Number);
        }

        for (var i = 0; i < v1parts.length; ++i) {
          if (v2parts.length == i) {
            return 1;
          }

          if (v1parts[i] == v2parts[i]) {
            // continue; go to next loop cycle
          }
          else if (v1parts[i] > v2parts[i]) {
            return 1;
          }
          else {
            return -1;
          }
        }

        if (v1parts.length != v2parts.length) {
          return -1;
        }

        return 0;
      });
    }

    function string2CharCode(str) {
      // summary:
      //   Transform a string into an array of CharCodes.

      return str.split("").map(function(c) {return c.charCodeAt(0);});
    }

    function charCode2String(charCodes) {
      // summary:
      //   Transform an array of CharCodes into a String.

      return charCodes.map(function(charCode) {return String.fromCharCode(charCode);}).join("");
    }

    //noinspection MagicNumberJS
    var MAX_INT = 9007199254740992;
    //noinspection MagicNumberJS
    var MIN_INT = -9007199254740992;

    // From https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Math/random
    // Returns a random integer between min and max
    // Using Math.round() will give you a non-uniform distribution!
    function randomInt(min, max) {
      var myMin = min || min === 0 ? min : MIN_INT;
      var myMax = max || max === 0 ? max : MAX_INT;
      return Math.floor(Math.random() * (myMax - myMin + 1)) + myMin;
    }

    function randomInts(min, max, nr) {
      var result = [];
      var r = undefined;
      for (var i = 0; i < nr; i++) {
        while (!r || result.some(function(earlierR) {//noinspection JSReferencingMutableVariableFromClosure
          return r === earlierR;})) {
          r = randomInt(min, max);
        }
        result[i] = r;
        r = undefined;
      }
      return result;
    }

    function haveSameElements(a1, a2) {
      // summary:
      //   Returns true if array a1 and array a2 have the samen elements, irrespective of their order.
      //   Duplicates are allowed.

      return a1.every(function(a1i) {return a2.indexOf(a1i) >= 0;}) &&
        a2.every(function(a2i) {return a1.indexOf(a2i) >= 0;});
    }

    function flatten(/*Array*/ arr) {
      return arr.reduce(
        function(acc, el) {
          if (typeOf(el) === "array") {
            return acc.concat(flatten(el));
          }
          else {
            acc.push(el);
            return acc;
          }
        },
        []
      );
    }

    function compactPath(path) {
      // summary:
      //   Function copied from require.compactPath. It is not available there after a build.
      // Description:
      //   Normalizes a path.
      //   A '.' is removed from the path.
      //   '..' is optimized by removing the preceding part from the path.
      //   If the path parameter goes up too many levels in the directory structure, this will be ignored.
      //   It only goes up until the base path is reached.

      var result = [];
      var segment;
      var lastSegment;
      var p = path.replace(/\\/g, '/').split('/');
      while(p.length) {
        segment = p.shift();
        if(segment === ".." && result.length && lastSegment !== "..") {
          result.pop();
          lastSegment = result[result.length - 1];
        }
        else if (segment!=="." && segment !== "..") {
          lastSegment = segment;
          result.push(lastSegment);
        }
        // else ignore "."
      }
      return result.join("/");
    }

    var js = {
      // summary:
      //   Methods to aid with the JavaScript language.
      typeOf: typeOf,
      getPrototypeChain: getPrototypeChain,
      getAllKeys: getAllKeys,
      isInt: isInt,
      nub: nub,
      flatten: flatten,
      substitute: substitute,
      sortComparable: sortComparable,
      sortReversed: sortReversed,
      sortVersionNumbers: sortVersionNumbers,
      string2CharCode: string2CharCode,
      charCode2String: charCode2String,
      MAX_INT: MAX_INT,
      MIN_INT: MIN_INT,
      randomInt: randomInt,
      randomInts: randomInts,
      haveSameElements: haveSameElements,
      compactPath: compactPath
    };

    return js;
  }
);
<commit_msg>Code inspection: Fix warning about imported code.<commit_after>/*
Copyright 2012 - $Date $ by PeopleWare n.v.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

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

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

define([],
  function() {

    function typeOf(obj) {
      // summary:
      //   A better type then Object.toString() or typeof.
      // description:
      //      toType(undefined); //"undefined"
      //      toType(new); //"null"
      //      toType({a: 4}); //"object"
      //      toType([1, 2, 3]); //"array"
      //      (function() {console.log(toType(arguments))})(); //arguments
      //      toType(new ReferenceError); //"error"
      //      toType(new Date); //"date"
      //      toType(/a-z/); //"regexp"
      //      toType(Math); //"math"
      //      toType(JSON); //"json"
      //      toType(new Number(4)); //"number"
      //      toType(new String("abc")); //"string"
      //      toType(new Boolean(true)); //"boolean"

      /* based on
       http://javascriptweblog.wordpress.com/2011/08/08/fixing-the-javascript-typeof-operator/
       */

      if (obj === null) {
        // workaround for eopdf; it seems that js.typeOf(null) is returned by eopdf as "domwindow"
        return "null";
      }
      var result = Object.prototype.toString.call(obj).match(/\s([a-zA-Z]+)/)[1].toLowerCase();
      // on some browsers, the main window returns as "global" (WebKit) or "window" (FF), but this is an object too
      if (result === "global" || result == "window") {
        result = "object";
      }
      return result; // return String
    }

    function getPrototypeChain(/*Object*/ obj) {
      // summary:
      //   Returns an array where result[i] is the prototype
      //   of result[i-1], with obj === result[0]. result[length]
      //   is thus Object.prototype.

      function recursive(acc, o) {
        if (!o) {
          return acc;
        }
        else {
          acc.push(o);
          return recursive(acc, Object.getPrototypeOf(o));
        }
      }

      return recursive([], obj);
    }

    function getAllKeys(/*Object*/ obj) {
      // summary:
      //   Returns an array containing the names of all given objects enumerable properties.
      //   Like keys, but for the entire prototype chain. The array starts with the properties
      //   of Object.prototype, and works down the chain.

      return getPrototypeChain(obj).reduceRight(
        function(acc, proto) {
          return nub(acc.concat(Object.keys(proto)));
        },
        []
      );
    }

    function isInt(/*Number*/ n) {
      // summary:
      //   True if n is an integer.
      //   n must be a number.

      return n % 1 === 0;
    }

    function nub(/*Array*/ array, /*Boolean?*/ removeNull) {
      // summary:
      //   Returns an array that has all the elements of `array`, in order, but with later duplicates removed.
      //   If `removeNull` is given and thruthy, nulls and undefineds are removed too.

      if (!array) {
        return array;
      }
      var result = array.reduce(
        function(acc, el) {
          if ((!removeNull || el) && acc.indexOf(el) < 0) {
            acc.push(el);
          }
          return acc;
        },
        []
      );
      return result;
    }

    function substitute(/*String*/ str, /*Object*/ context) {
      // summary:
      //  All occurrences of "${...}$" in `str` are replaced by the result of the
      //  execution of what is between the curly brackets as JavaScript, with `context`
      //  as `this`.

      //   Like dojo/string.substitute, but evals full code.
      //   No formatting (yet).
      return str.replace( // return String
        /\$\{(.+?)\}\$/gm,
        function(match, pattern) {
          var value;
          try {
            var executor = new Function("return (" + pattern + ");");
            value = executor.call(context);
          }
          catch (err) {
            // IDEA: consider logger
            console.error("Executing pattern substitution of ${" + pattern + "}$ in '" + str + "' with context " + context, err);
            return "?? ${" + pattern  + "}$ -- " + (err.message || err) + " ??";
          }
          return value || value === "" ? value.toString() : "?" + pattern  + "?";
        }
      );
    }

    function sortComparable(/*Object*/ c1, /*Object*/ c2) {
      // summary:
      //   A sort function for objects that have a compare function.
      //   undefined < null < the compare function of the objects

      return c1 === undefined ? (
               c2 === undefined ? 0 : -1
             )
             : (
               c1 === null ? (
                 c2 === undefined ?
                   +1 :
                   c2 === null ? 0 : -1
               )
               : (
                 !c2 ? +1 : c1.compare(c2)
               )
             );
    }

    function sortReversed(/*Function*/ sort) {
      // summary:
      //   Produces a compare function that does the reverse sort defined by sort.

      return function(o1, o2) {
        return -sort(o1, o2);
      }
    }

    function sortVersionNumbers(/*Array*/ arrayToSort) {
      //noinspection OverlyComplexFunctionJS
      /**
       * Compares two software version numbers (e.g. "1.7.1" or "1.2b").
       *
       * This function was born in http://stackoverflow.com/a/6832721.
       *
       * @param {string} v1 The first version to be compared.
       * @param {string} v2 The second version to be compared.
       * @param {object} [options] Optional flags that affect comparison behavior:
       *

       *

       *         <tt>lexicographical: true</tt> compares each part of the version strings lexicographically instead of
       *         naturally; this allows suffixes such as "b" or "dev" but will cause "1.10" to be considered smaller than
       *         "1.2".
       *

       *

       *         <tt>zeroExtend: true</tt> changes the result if one version string has less parts than the other. In
       *         this case the shorter string will be padded with "zero" parts instead of being considered smaller.
       *

       *

       * @returns {number|NaN}
       *

       *
0 if the versions are equal

       *
a negative integer iff v1 < v2

       *
a positive integer iff v1 > v2

       *
NaN if either version string is in the wrong format

       *

       *
       * @copyright by Jon Papaioannou (["john", "papaioannou"].join(".") + "@gmail.com")
       * @license This function is in the public domain. Do what you want with it, no strings attached.
       */
      arrayToSort.sort(function(/*String*/ v1, /*String*/ v2, /*Object*/ options) {
        var lexicographical = options && options.lexicographical,
          zeroExtend = options && options.zeroExtend,
          v1parts = v1.split('.'),
          v2parts = v2.split('.');

        function isValidPart(x) {
          return (lexicographical ? /^\d+[A-Za-z]*$/ : /^\d+$/).test(x);
        }

        if (!v1parts.every(isValidPart) || !v2parts.every(isValidPart)) {
          return NaN;
        }

        if (zeroExtend) {
          while (v1parts.length < v2parts.length) {
            v1parts.push("0");
          }
          while (v2parts.length < v1parts.length) {
            v2parts.push("0");
          }
        }

        if (!lexicographical) {
          v1parts = v1parts.map(Number);
          v2parts = v2parts.map(Number);
        }

        for (var i = 0; i < v1parts.length; ++i) {
          if (v2parts.length == i) {
            return 1;
          }

          if (v1parts[i] == v2parts[i]) {
            // continue; go to next loop cycle
          }
          else if (v1parts[i] > v2parts[i]) {
            return 1;
          }
          else {
            return -1;
          }
        }

        if (v1parts.length != v2parts.length) {
          return -1;
        }

        return 0;
      });
    }

    function string2CharCode(str) {
      // summary:
      //   Transform a string into an array of CharCodes.

      return str.split("").map(function(c) {return c.charCodeAt(0);});
    }

    function charCode2String(charCodes) {
      // summary:
      //   Transform an array of CharCodes into a String.

      return charCodes.map(function(charCode) {return String.fromCharCode(charCode);}).join("");
    }

    //noinspection MagicNumberJS
    var MAX_INT = 9007199254740992;
    //noinspection MagicNumberJS
    var MIN_INT = -9007199254740992;

    // From https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Math/random
    // Returns a random integer between min and max
    // Using Math.round() will give you a non-uniform distribution!
    function randomInt(min, max) {
      var myMin = min || min === 0 ? min : MIN_INT;
      var myMax = max || max === 0 ? max : MAX_INT;
      return Math.floor(Math.random() * (myMax - myMin + 1)) + myMin;
    }

    function randomInts(min, max, nr) {
      var result = [];
      var r = undefined;
      for (var i = 0; i < nr; i++) {
        while (!r || result.some(function(earlierR) {//noinspection JSReferencingMutableVariableFromClosure
          return r === earlierR;})) {
          r = randomInt(min, max);
        }
        result[i] = r;
        r = undefined;
      }
      return result;
    }

    function haveSameElements(a1, a2) {
      // summary:
      //   Returns true if array a1 and array a2 have the samen elements, irrespective of their order.
      //   Duplicates are allowed.

      return a1.every(function(a1i) {return a2.indexOf(a1i) >= 0;}) &&
        a2.every(function(a2i) {return a1.indexOf(a2i) >= 0;});
    }

    function flatten(/*Array*/ arr) {
      return arr.reduce(
        function(acc, el) {
          if (typeOf(el) === "array") {
            return acc.concat(flatten(el));
          }
          else {
            acc.push(el);
            return acc;
          }
        },
        []
      );
    }

    function compactPath(path) {
      // summary:
      //   Function copied from require.compactPath. It is not available there after a build.
      // Description:
      //   Normalizes a path.
      //   A '.' is removed from the path.
      //   '..' is optimized by removing the preceding part from the path.
      //   If the path parameter goes up too many levels in the directory structure, this will be ignored.
      //   It only goes up until the base path is reached.

      var result = [];
      var segment;
      var lastSegment;
      var p = path.replace(/\\/g, '/').split('/');
      while(p.length) {
        segment = p.shift();
        //noinspection JSUnusedAssignment
        if(segment === ".." && result.length && lastSegment !== "..") {
          result.pop();
          lastSegment = result[result.length - 1];
        }
        else if (segment!=="." && segment !== "..") {
          lastSegment = segment;
          result.push(lastSegment);
        }
        // else ignore "."
      }
      return result.join("/");
    }

    var js = {
      // summary:
      //   Methods to aid with the JavaScript language.
      typeOf: typeOf,
      getPrototypeChain: getPrototypeChain,
      getAllKeys: getAllKeys,
      isInt: isInt,
      nub: nub,
      flatten: flatten,
      substitute: substitute,
      sortComparable: sortComparable,
      sortReversed: sortReversed,
      sortVersionNumbers: sortVersionNumbers,
      string2CharCode: string2CharCode,
      charCode2String: charCode2String,
      MAX_INT: MAX_INT,
      MIN_INT: MIN_INT,
      randomInt: randomInt,
      randomInts: randomInts,
      haveSameElements: haveSameElements,
      compactPath: compactPath
    };

    return js;
  }
);
<|endoftext|>


<commit_before>$(document).ready(function() {
  $('p').append('
This might work???
');
})
<commit_msg>making this hopefully better<commit_after>$(document).ready(function() {
  $('p').after('
This might work???
');
})
<|endoftext|>


<commit_before>/**
 * ns.js is a plugin without any of other modules
 * it is just for namespace organize
 * our aim is easier for javascript package
 *
 * @author:donghui or called phiz
 * Apache License 2.0
 */
;
(function (name, propertis) {
    var topKey = "window" in this ? "window" : "global" in this ? "global" : "basic";
    var existKey = "|break|do|instanceof|typeof|\
                case|else|new|var|\
                catch|finally|return|void|\
                continue|for|switch|while|\
                debugger|function|this|with|\
                default|if|throw|delete|\
                in|try|abstract|enum|int|\
                short|boolean|export|interface|static\
                byte|extends|long|super|\
                char|final|native|synchronized|\
                class|float|package|throws|\
                const|goto|private|transient|\
                debugger|implements|protected|volatile|\
                double|import|public|\
                class|enum|extends|super|\
                const|export|import|\
                implements|package|public|interface|\
                private|static|let|protected|\
                yield|global|root|window|";

    var orange = function () {
        Object.defineProperty(this, "pluginCatch", { value: {}, enumerable: true });
        Object.defineProperty(this, "variableCatch", { value: {}, enumerable: true });

        function fn() {
            var args = slice.call(arguments),
                len = args.length,
                last = len - 1,
                first = 0,
                paramEnd = last - 1,
                pluginKey = args[first],
                plugin = args[first + 1],
                params = args[first + 2],
                cover = args[last],
                switchKey = len,
                o = orange

            if (!o.isPluginKey(pluginKey)) {
                o.LOGGER.throw("pluginKey should be string type and not be empty")
            }
            if (len > 1 && !o.isPlugin(plugin)) {
                o.LOGGER.throw("plugin should not be null")
            }
            if (len > 2) {
                if (!o.isPlugin(cover) && o.isBoolean(params)) {
                    cover = params;
                }
                if (o.isBoolean(cover)) {
                    paramEnd -= 1;
                } else {
                    cover = false;
                }
                if (o.isArray(params)) {
                    params.concat(o.splice.call(args, 3, paramEnd));
                } else if (switchKey == 3 && params == cover) {
                    params = null;
                } else {
                    params = o.splice.call(args, 2, paramEnd);
                }
            }
            if (switchKey === 1) {
                return this.getVariable(pluginKey);
            }
            return this.setVariable(pluginKey, plugin, params, cover);

        }
        this.fn = fn.bind(this);
        this.fn.extra = function (obj) {
            var o = orange;
            if (!o.isObject(obj)) {
                o.LOGGER.error('param should be an object');
                obj = {}
            }
            for (var key in obj) {
                if (o.isFunction(obj[key]) && !(key in o)) {
                    o.fn[key] = obj[key];
                }
            }
            return this;
        }
        return this.fn;
    }

    orange.slice = slice = Array.prototype.slice;
    orange.splice = Array.prototype.splice;
    orange.isPluginKey = function (o) { return typeof o === 'string' && o.trim() !== ""; }
    orange.isBoolean = function (o) { return typeof o === 'boolean' }
    orange.isFunction = function (o) { return typeof o === 'function'; }
    orange.isObject = function (o) { return typeof o === 'object' && !orange.isArray(o); }
    orange.isArray = function (o) { return o instanceof Array; }
    orange.isPlugin = function (o) { return o != null; }
    orange.LOGGER = {
        info: function (msg) { this.log("INFO", msg) },
        debug: function (msg) { this.log("DEBUG", msg) },
        error: function (msg) { this.log("ERROR", msg) },
        log: function (type, msg) { console["info" || type.toLowerCase()]("[" + type + "]", ">>>", msg); },
        throw: function (msg) { throw Error("[ ERROR ] >>> " + msg); }
    }
    orange.fn = orange.prototype = {
        constructor:orange,
        exist: function (pluginKey) { return pluginKey in this.pluginCatch || pluginKey in this.variableCatch; },
        get: function (pluginKey) { return this.getVariable(pluginKey || this._prekey); },
        set: function (plugin, params) { return this.setVariable(this._prekey, plugin, params, true); },
        exec: function () {
            var object = this.get(), o = orange, params = o.slice.call(arguments), index = 0;
            try {
                if (o.isObject(object) || o.isArray(object)) {
                    for (var i in object) {
                        if (o.isFunction(object[i])) {
                            object[i].call(this, params[index++]);
                        }
                    }
                } else if (o.isFunction(object)) {
                    object.apply(this, params);
                } else {
                    return false;
                }
            } catch (e) {
                console.error(e);
                return false;
            }
            return true;
        },
        getVariable: function (pluginKey, must) {
            let val = this.pluginCatch[pluginKey] || this.variableCatch[pluginKey];
            if (!this.exist(pluginKey)) {
                orange.LOGGER.error("[ " + pluginKey + " ] should be define");
            }
            return val;
        },
        setVariable: function (pluginKey, plugin, params, cover) {
            if (this.exist(pluginKey) && !cover) {
                orange.LOGGER.throw("[ " + pluginKey + " ] try to set plugin but it is exist and cover is false")
            }
            if (orange.isArray(params)) {
                this.setVariableWithParams(pluginKey, plugin, params, cover);
            }
            else if (orange.isFunction(plugin)) {
                delete this.variableCatch[pluginKey];
                this.pluginCatch[pluginKey] = plugin;
            } else {
                delete this.pluginCatch[pluginKey];
                this.variableCatch[pluginKey] = plugin;
            }
            this._prekey = pluginKey;
            return this;
        },
        setVariableWithParams: function (pluginKey, plugin, params, cover) {
            if (orange.isFunction(plugin)) {
                delete this.pluginCatch[pluginKey];
                delete this.variableCatch[pluginKey];
                let val = plugin.apply(this, params);
                if (orange.isFunction(val)) {
                    this.pluginCatch[pluginKey] = val;
                } else {
                    this.variableCatch[pluginKey] = val;
                }
            }
        }
    }
    function init(name) {
        var name = name;
        validKeyword(name, topKey);
        this[name] = function (ns) {
            validKeyword(ns, topKey);
            this[ns] = new orange();
        }
    };
    function validKeyword(ns, name) {
        if (this[ns] !== undefined) { orange.LOGGER.throw("[ " + ns + " ] has already exist in << " + name + " >>") }
        if (!orange.isPluginKey(ns) || new RegExp("\\|" + ns + "\\|").test(existKey)) { orange.LOGGER.throw("[ " + ns + " ] is not a valid keyword") }
    }
    init(name);
})("ns");<commit_msg>添加初始化时的日志配置 或者定义全局的日志配置情况 定义对象function体内也可以使用日志记录<commit_after>/**
 * ns.js is a plugin without any of other modules
 * it is just for namespace organize
 * our aim is easier for javascript package
 *
 * @author:donghui or called phiz
 * Apache License 2.0
 */
;
(function (name, propertis) {
    var topKey = "window" in this ? "window" : "global" in this ? "global" : "basic";
    var existKey = "|break|do|instanceof|typeof|\
                case|else|new|var|\
                catch|finally|return|void|\
                continue|for|switch|while|\
                debugger|function|this|with|\
                default|if|throw|delete|\
                in|try|abstract|enum|int|\
                short|boolean|export|interface|static\
                byte|extends|long|super|\
                char|final|native|synchronized|\
                class|float|package|throws|\
                const|goto|private|transient|\
                debugger|implements|protected|volatile|\
                double|import|public|\
                class|enum|extends|super|\
                const|export|import|\
                implements|package|public|interface|\
                private|static|let|protected|\
                yield|global|root|window|";

    var orange = function (params) {
        Object.defineProperty(this, "pluginCatch", { value: {}, enumerable: true });
        Object.defineProperty(this, "variableCatch", { value: {}, enumerable: true });
        orange.params = params;
        function fn() {
            var args = slice.call(arguments),
                len = args.length,
                last = len - 1,
                first = 0,
                paramEnd = last - 1,
                pluginKey = args[first],
                plugin = args[first + 1],
                params = args[first + 2],
                cover = args[last],
                switchKey = len,
                o = orange

            if (!o.isPluginKey(pluginKey)) {
                o.fn.LOGGER.throw("pluginKey should be string type and not be empty")
            }
            if (len > 1 && !o.isPlugin(plugin)) {
                o.fn.LOGGER.throw("plugin should not be null")
            }
            if (len > 2) {
                if (!o.isPlugin(cover) && o.isBoolean(params)) {
                    cover = params;
                }
                if (o.isBoolean(cover)) {
                    paramEnd -= 1;
                } else {
                    cover = false;
                }
                if (o.isArray(params)) {
                    params.concat(o.splice.call(args, 3, paramEnd));
                } else if (switchKey == 3 && params == cover) {
                    params = null;
                } else {
                    params = o.splice.call(args, 2, paramEnd);
                }
            }
            if (switchKey === 1) {
                return this.getVariable(pluginKey);
            }
            return this.setVariable(pluginKey, plugin, params, cover);

        }
        this.fn = fn.bind(this);
        this.fn.extra = function (obj) {
            var o = orange;
            if (!o.isObject(obj)) {
                o.fn.LOGGER.error('param should be an object');
                obj = {}
            }
            for (var key in obj) {
                if (o.isFunction(obj[key]) && !(key in o)) {
                    o.fn[key] = obj[key];
                }
            }
            return this;
        }
        return this.fn;
    }

    orange.slice = slice = Array.prototype.slice;
    orange.splice = Array.prototype.splice;
    orange.isPluginKey = function (o) { return typeof o === 'string' && o.trim() !== ""; }
    orange.isBoolean = function (o) { return typeof o === 'boolean' }
    orange.isFunction = function (o) { return typeof o === 'function'; }
    orange.isObject = function (o) { return typeof o === 'object' && !orange.isArray(o); }
    orange.isArray = function (o) { return o instanceof Array; }
    orange.isPlugin = function (o) { return o != null; }

    orange.fn = orange.prototype = {
        constructor: orange,
        LOGGER: {
            debug: function (msg) { if (orange.params.loglevel <= 0) this.log("DEBUG", msg) },
            info: function (msg) { if (orange.params.loglevel <= 1) this.log("INFO", msg) },
            error: function (msg) { if (orange.params.loglevel <= 2) this.log("ERROR", msg) },
            throw: function (msg) { if (orange.params.loglevel <= 3) throw Error("[ ERROR ] >>> " + msg); },
            log: function (type, msg) { console[type.toLowerCase() || "log"]("[" + type + "]", ">>>", msg); }
        },
        exist: function (pluginKey) { return pluginKey in this.pluginCatch || pluginKey in this.variableCatch; },
        get: function (pluginKey) { return this.getVariable(pluginKey || this._prekey); },
        set: function (plugin, params) { return this.setVariable(this._prekey, plugin, params, true); },
        exec: function () {
            var object = this.get(), o = orange, params = o.slice.call(arguments), index = 0;
            try {
                if (o.isObject(object) || o.isArray(object)) {
                    for (var i in object) {
                        if (o.isFunction(object[i])) {
                            object[i].call(this, params[index++]);
                        }
                    }
                } else if (o.isFunction(object)) {
                    object.apply(this, params);
                } else {
                    return false;
                }
            } catch (e) {
                console.error(e);
                return false;
            }
            return true;
        },
        getVariable: function (pluginKey, must) {
            let val = this.pluginCatch[pluginKey] || this.variableCatch[pluginKey];
            if (!this.exist(pluginKey)) {
                this.LOGGER.error("[ " + pluginKey + " ] should be define");
            }
            return val;
        },
        setVariable: function (pluginKey, plugin, params, cover) {
            if (this.exist(pluginKey) && !cover) {
                this.LOGGER.throw("[ " + pluginKey + " ] try to set plugin but it is exist and cover is false")
            }
            if (orange.isArray(params)) {
                this.setVariableWithParams(pluginKey, plugin, params, cover);
            }
            else if (orange.isFunction(plugin)) {
                delete this.variableCatch[pluginKey];
                this.pluginCatch[pluginKey] = plugin;
            } else {
                delete this.pluginCatch[pluginKey];
                this.variableCatch[pluginKey] = plugin;
            }
            this._prekey = pluginKey;
            return this;
        },
        setVariableWithParams: function (pluginKey, plugin, params, cover) {
            if (orange.isFunction(plugin)) {
                this.LOGGER.debug("execute " + pluginKey)
                delete this.pluginCatch[pluginKey];
                delete this.variableCatch[pluginKey];
                let val = plugin.apply(this, params);
                if (orange.isFunction(val)) {
                    this.pluginCatch[pluginKey] = val;
                } else {
                    this.variableCatch[pluginKey] = val;
                }
            }
        }
    }
    function init(name) {
        var name = name;
        validKeyword(name, topKey);
        this[name] = function (ns, args) {
            validKeyword(ns, topKey);
            this[ns] = new orange(args);
        }
    };
    function validKeyword(ns, name) {
        if (this[ns] !== undefined) { orange.fn.LOGGER.throw("[ " + ns + " ] has already exist in << " + name + " >>") }
        if (!orange.isPluginKey(ns) || new RegExp("\\|" + ns + "\\|").test(existKey)) { orange.fn.LOGGER.throw("[ " + ns + " ] is not a valid keyword") }
    }
    init(name);
})("ns");<|endoftext|>