<commit_before>var path      = require('path');
var Promise   = require('bluebird');

function Manager(bookshelf, options) {

  if (!(arguments.length > 0 && bookshelf && bookshelf.VERSION)) {
    throw new Error('Manager requires a Bookshelf instance');
  }

  this.root = options && options.root ? path.normalize(options.root) : null;

  this.initialize(bookshelf);
}

Manager.plugin = function(bookshelf, options) {
  return new Manager(bookshelf, options);
};

Manager.prototype.register = function(model, name) {

  if (!(arguments.length >= 2 && model && typeof name === 'string')) {
    throw new Error('Manager.register must be called with a model and a model name');
  }

  var Model = this.get(model);

  if (this.isModel(Model)) {
    this.bookshelf.model(name, Model);
  } else if (this.isCollection(Model)) {
    this.bookshelf.collection(name, Model);
  }

  return Model;
};

Manager.prototype.initialize = function(bookshelf) {
  this.bookshelf  = bookshelf;
  this.knex       = this.bookshelf.knex;
  this.schema     = this.knex.schema;

  bookshelf.plugin('registry');

  // Expose the Bookshelf Manager instance on the Bookshelf instance
  bookshelf.manager = this;

  return this;
};

Manager.prototype.create = function(name, properties, options) {
  var Model = this.get(name);
  var model = new Model();

  return this.save(model, properties, options).catch(function(error) {
    console.error(error.stack);
    throw error;
  });
};

Manager.prototype.fetch = function(name, properties, related, options) {
  var model = this.forge(name, properties);

  return model.fetch({
    withRelated: related,
    transacting: options && options.transacting ? options.transacting : null
  });
};

Manager.prototype.findRelated = function(properties, paths) {
  var related = [];

  properties  = properties || {};
  paths       = paths || [];

  for (var key in properties) {
    var value = properties[key];
    var ctor  = value ? value.constructor : null;

    if (ctor === Array) {
      related.push(paths.concat([key]).join('.'));

      if (value.length) {
        related = related.concat(this.findRelated(value[0], paths.concat([key])));
      }
    }

    if (ctor === Object) {
      related.push(paths.concat([key]).join('.'));

      related = related.concat(this.findRelated(value, paths.concat([key])));
    }
  }

  return related;
};

Manager.prototype.forge = function(name, properties) {
  var Model = this.get(name);

  // Model may already be instantiated
  if (Model instanceof this.bookshelf.Model) {
    Model = Model.constructor;
  }

  return Model.forge(properties);
};

Manager.prototype.get = function(Model) {
  if (!this.bookshelf) {
    throw new Error('Manager has not been initialized with instance of Bookshelf');
  }

  var name;

  if (typeof Model === 'string') {
    name = Model;

    Model = this.bookshelf.collection(name) || this.bookshelf.model(name);

    if (this.isModelOrCollection(Model)) {
      return Model;
    }

    if (this.root) {

      var file = path.join(this.root, name);

      try {
        Model = require(file);
      } catch (e) {
        throw new Error('Could not find module `' + name + '` at `' + file + '.js`');
      }
    } else {
      throw new Error('No model named `' + name + '` has been registered and no model directory was specified');
    }
  }

  if (!this.isModelOrCollection(Model)) {
    Model = Model(this.bookshelf);
  }

  if (!this.isModelOrCollection(Model)) {
    throw new Error('Expected a String, Model, or Collection, got: ' + typeof Model);
  }

  if (this.isCollection(Model) && typeof Model.prototype.model === 'string') {
    Model.prototype.model = this.get(Model.prototype.model);
  }

  if (name) {
    if (this.isModel(Model)) {
      this.bookshelf.model(name, Model);
    } else if (this.isCollection(Model)) {
      this.bookshelf.collection(name, Model);
    }
  }

  return Model;
};

Manager.prototype.isModelOrCollection = function(model) {
  return (this.isModel(model) || this.isCollection(model));
};

Manager.prototype.isModel = function(model) {
  if (!model || this.isCollection(model)) {
    return false;
  }

  return model instanceof this.bookshelf.Model || model.prototype instanceof this.bookshelf.Model;
};

Manager.prototype.isCollection = function(model) {
  if (!model) {
    return false;
  }

  return model instanceof this.bookshelf.Collection || model.prototype instanceof this.bookshelf.Collection;
};

Manager.prototype.save = function(model, properties, options) {
  if (this.isModel(model)) {
    return this.saveModel(model, properties, options);
  } else if (this.isCollection(model)) {
    return this.saveCollection(model, properties, options);
  }

  throw new Error('Object should be an instance of Model or Collection, not ' + typeof model);
};

Manager.prototype.saveCollection = function(collection, models, options) {
  return collection.mapThen(function(model) {
    return (model.isNew() || model.hasChanged()) ? model.save(null, options) : model;
  }).then(function() {
    return this.setCollection(collection, models, options);
  }.bind(this)).then(function(targets) {
    return targets.mapThen(function(target) {
      collection.add(target);

      return (target.isNew() || target.hasChanged()) ? target.save(null, options) : target;
    });
  }).then(function() {
    return collection;
  }).catch(function(error) {
    console.error(error.stack);
    throw error;
  });
};

Manager.prototype.saveModel = function(model, properties, options) {
  return this.setModel(model, properties, options).then(function(result) {
    return (result.isNew() || result.hasChanged()) ? result.save(null, options) : result;
  }).catch(function(error) {
    console.error(error.stack);
    throw error;
  });
};

Manager.prototype.set = function(model, properties, options) {
  if (this.isModel(model)) {
    return this.setModel(model, properties, options);
  } else if (this.isCollection(model)) {
    return this.setCollection(model, properties, options);
  }

  throw new Error('Object should be an instance of Model or Collection, not ' + typeof model);
};

Manager.prototype.setModel = function(model, properties, options) {
  var promises = [];

  properties = (typeof properties === 'object' && !Array.isArray(properties) && properties !== null) ? properties : {};

  if (model.isNew() && properties && properties.id) {
    promises.push(function() {
      return this.fetch(model, { id: properties.id }, this.findRelated(properties), options).then(function(result) {
        return result;
      });
    }.bind(this));
  } else {
    promises.push(function() {
      return model;
    });
  }

  function setProperties(propertyType) {

    Object.keys(properties).forEach(function(key) {
      var value     = properties[key];
      var relation  = (model[key] instanceof Function && (typeof value === 'object' || Array.isArray(value))) ? model[key].call(model) : null;
      var type      = relation ? relation.relatedData.type : 'scalar';
      var method    = 'set' + type.charAt(0).toUpperCase() + type.slice(1);
      var setter    = this[method].bind(this);

      if ((type === 'scalar' && propertyType === 'scalar') || (type !== 'scalar' && propertyType === 'related')) {
        promises.push(function(result) {
          return setter(result, key, value, relation, options).then(function() {
            return result;
          });
        });
      }
    }.bind(this));
  }

  setProperties.bind(this)('scalar');

  promises.push(function(result) {
    return (result.isNew() || result.hasChanged()) ? result.save(null, options) : result;
  });

  setProperties.bind(this)('related');

  return Promise.reduce(promises, function(result, promise) {
    return promise(result);
  }, []);
};

Manager.prototype.setBelongsTo = function(model, key, value, relation, options) {
  var Target    = relation.relatedData.target;
  var existing  = model.related(key);
  var target    = existing.isNew() ? Target.forge() : existing.clone();
  var fk = relation.relatedData.foreignKey;

  if (value === null) {
    if (model.get(fk)) {
      model.set(fk, null);
    }
    if (existing.isNew()) {
      return Promise.resolve(model);
    }
  }

  return this.save(target, value, options).then(function(target) {
    if (model.get(fk) !== target.id) {
      model.set(fk, target.id);
    }

    model.relations[key] = target;

    return (model.isNew() || model.hasChanged()) ? model.save(null, options) : model;
  });
};

Manager.prototype.setBelongsToMany = function(model, key, models, relation, options) {
  var existing = model.related(key);

  return Promise.cast(existing.length ? existing : existing.fetch(options)).then(function() {
    return this.setCollection(existing, models, options);
  }.bind(this)).then(function(targets) {
    // Enforce attach/detach IDs
    existing.relatedData.parentId = model.id;
    existing.relatedData.parentFk = model.id;

    return targets.mapThen(function(target) {
      if (!existing.findWhere({ id: target.id })) {
        return existing.attach(target, options);
      }
    }).then(function() {
      return existing.mapThen(function(target) {
        if (!targets.findWhere({ id: target.id })) {
          return existing.detach(target, options);
        }
      });
    });
  }).then(function() {
    return model;
  });
};

Manager.prototype.setHasMany = function(model, key, models, relation, options) {
  var existing = model.related(key);

  var fk = relation.relatedData.foreignKey;

  if (!fk) {
    throw new Error('`' + model.tableName + '#' + key + '` relation is missing `foreignKey` in `this.hasMany(Target, foreignKey)`');
  }

  models = models.map(function(target) {
    if (!target[fk]) {
      target[fk] = model.id;
    }
    return target;
  });

  return this.setCollection(existing, models, options).then(function(targets) {

    targets.forEach(function(target) {
      existing.add(target);
    });

    return existing.mapThen(function(target) {
      if (!targets.findWhere({ id: target.id })) {
        return target.destroy(options);
      }
    });
  }).then(function() {
    return model;
  });
};

Manager.prototype.setScalar = Promise.method(function(model, key, value) {
  if (key.indexOf('_pivot_') === 0) {
    return model;
  }

  if (model.get(key) === value) {
    return model;
  }

  model.set(key, value);

  return model;
});

Manager.prototype.setCollection = function(existing, models, options) {
  models = models || [];

  return Promise.map(models, function(properties) {
    var model = existing.findWhere({ id: properties.id }) || existing.model.forge();

    return this.save(model, properties, options);
  }.bind(this)).then(function(results) {
    return this.bookshelf.Collection.forge(results);
  }.bind(this));
};

module.exports = Manager;
<commit_msg>Meant to always short-circuit if setBelongsTo value is null<commit_after>var path      = require('path');
var Promise   = require('bluebird');

function Manager(bookshelf, options) {

  if (!(arguments.length > 0 && bookshelf && bookshelf.VERSION)) {
    throw new Error('Manager requires a Bookshelf instance');
  }

  this.root = options && options.root ? path.normalize(options.root) : null;

  this.initialize(bookshelf);
}

Manager.plugin = function(bookshelf, options) {
  return new Manager(bookshelf, options);
};

Manager.prototype.register = function(model, name) {

  if (!(arguments.length >= 2 && model && typeof name === 'string')) {
    throw new Error('Manager.register must be called with a model and a model name');
  }

  var Model = this.get(model);

  if (this.isModel(Model)) {
    this.bookshelf.model(name, Model);
  } else if (this.isCollection(Model)) {
    this.bookshelf.collection(name, Model);
  }

  return Model;
};

Manager.prototype.initialize = function(bookshelf) {
  this.bookshelf  = bookshelf;
  this.knex       = this.bookshelf.knex;
  this.schema     = this.knex.schema;

  bookshelf.plugin('registry');

  // Expose the Bookshelf Manager instance on the Bookshelf instance
  bookshelf.manager = this;

  return this;
};

Manager.prototype.create = function(name, properties, options) {
  var Model = this.get(name);
  var model = new Model();

  return this.save(model, properties, options).catch(function(error) {
    console.error(error.stack);
    throw error;
  });
};

Manager.prototype.fetch = function(name, properties, related, options) {
  var model = this.forge(name, properties);

  return model.fetch({
    withRelated: related,
    transacting: options && options.transacting ? options.transacting : null
  });
};

Manager.prototype.findRelated = function(properties, paths) {
  var related = [];

  properties  = properties || {};
  paths       = paths || [];

  for (var key in properties) {
    var value = properties[key];
    var ctor  = value ? value.constructor : null;

    if (ctor === Array) {
      related.push(paths.concat([key]).join('.'));

      if (value.length) {
        related = related.concat(this.findRelated(value[0], paths.concat([key])));
      }
    }

    if (ctor === Object) {
      related.push(paths.concat([key]).join('.'));

      related = related.concat(this.findRelated(value, paths.concat([key])));
    }
  }

  return related;
};

Manager.prototype.forge = function(name, properties) {
  var Model = this.get(name);

  // Model may already be instantiated
  if (Model instanceof this.bookshelf.Model) {
    Model = Model.constructor;
  }

  return Model.forge(properties);
};

Manager.prototype.get = function(Model) {
  if (!this.bookshelf) {
    throw new Error('Manager has not been initialized with instance of Bookshelf');
  }

  var name;

  if (typeof Model === 'string') {
    name = Model;

    Model = this.bookshelf.collection(name) || this.bookshelf.model(name);

    if (this.isModelOrCollection(Model)) {
      return Model;
    }

    if (this.root) {

      var file = path.join(this.root, name);

      try {
        Model = require(file);
      } catch (e) {
        throw new Error('Could not find module `' + name + '` at `' + file + '.js`');
      }
    } else {
      throw new Error('No model named `' + name + '` has been registered and no model directory was specified');
    }
  }

  if (!this.isModelOrCollection(Model)) {
    Model = Model(this.bookshelf);
  }

  if (!this.isModelOrCollection(Model)) {
    throw new Error('Expected a String, Model, or Collection, got: ' + typeof Model);
  }

  if (this.isCollection(Model) && typeof Model.prototype.model === 'string') {
    Model.prototype.model = this.get(Model.prototype.model);
  }

  if (name) {
    if (this.isModel(Model)) {
      this.bookshelf.model(name, Model);
    } else if (this.isCollection(Model)) {
      this.bookshelf.collection(name, Model);
    }
  }

  return Model;
};

Manager.prototype.isModelOrCollection = function(model) {
  return (this.isModel(model) || this.isCollection(model));
};

Manager.prototype.isModel = function(model) {
  if (!model || this.isCollection(model)) {
    return false;
  }

  return model instanceof this.bookshelf.Model || model.prototype instanceof this.bookshelf.Model;
};

Manager.prototype.isCollection = function(model) {
  if (!model) {
    return false;
  }

  return model instanceof this.bookshelf.Collection || model.prototype instanceof this.bookshelf.Collection;
};

Manager.prototype.save = function(model, properties, options) {
  if (this.isModel(model)) {
    return this.saveModel(model, properties, options);
  } else if (this.isCollection(model)) {
    return this.saveCollection(model, properties, options);
  }

  throw new Error('Object should be an instance of Model or Collection, not ' + typeof model);
};

Manager.prototype.saveCollection = function(collection, models, options) {
  return collection.mapThen(function(model) {
    return (model.isNew() || model.hasChanged()) ? model.save(null, options) : model;
  }).then(function() {
    return this.setCollection(collection, models, options);
  }.bind(this)).then(function(targets) {
    return targets.mapThen(function(target) {
      collection.add(target);

      return (target.isNew() || target.hasChanged()) ? target.save(null, options) : target;
    });
  }).then(function() {
    return collection;
  }).catch(function(error) {
    console.error(error.stack);
    throw error;
  });
};

Manager.prototype.saveModel = function(model, properties, options) {
  return this.setModel(model, properties, options).then(function(result) {
    return (result.isNew() || result.hasChanged()) ? result.save(null, options) : result;
  }).catch(function(error) {
    console.error(error.stack);
    throw error;
  });
};

Manager.prototype.set = function(model, properties, options) {
  if (this.isModel(model)) {
    return this.setModel(model, properties, options);
  } else if (this.isCollection(model)) {
    return this.setCollection(model, properties, options);
  }

  throw new Error('Object should be an instance of Model or Collection, not ' + typeof model);
};

Manager.prototype.setModel = function(model, properties, options) {
  var promises = [];

  properties = (typeof properties === 'object' && !Array.isArray(properties) && properties !== null) ? properties : {};

  if (model.isNew() && properties && properties.id) {
    promises.push(function() {
      return this.fetch(model, { id: properties.id }, this.findRelated(properties), options).then(function(result) {
        return result;
      });
    }.bind(this));
  } else {
    promises.push(function() {
      return model;
    });
  }

  function setProperties(propertyType) {

    Object.keys(properties).forEach(function(key) {
      var value     = properties[key];
      var relation  = (model[key] instanceof Function && (typeof value === 'object' || Array.isArray(value))) ? model[key].call(model) : null;
      var type      = relation ? relation.relatedData.type : 'scalar';
      var method    = 'set' + type.charAt(0).toUpperCase() + type.slice(1);
      var setter    = this[method].bind(this);

      if ((type === 'scalar' && propertyType === 'scalar') || (type !== 'scalar' && propertyType === 'related')) {
        promises.push(function(result) {
          return setter(result, key, value, relation, options).then(function() {
            return result;
          });
        });
      }
    }.bind(this));
  }

  setProperties.bind(this)('scalar');

  promises.push(function(result) {
    return (result.isNew() || result.hasChanged()) ? result.save(null, options) : result;
  });

  setProperties.bind(this)('related');

  return Promise.reduce(promises, function(result, promise) {
    return promise(result);
  }, []);
};

Manager.prototype.setBelongsTo = function(model, key, value, relation, options) {
  var Target    = relation.relatedData.target;
  var existing  = model.related(key);
  var target    = existing.isNew() ? Target.forge() : existing.clone();
  var fk = relation.relatedData.foreignKey;

  if (value === null) {
    if (model.get(fk)) {
      model.set(fk, null);
    }
    return Promise.resolve(model);
  }

  return this.save(target, value, options).then(function(target) {
    if (model.get(fk) !== target.id) {
      model.set(fk, target.id);
    }

    model.relations[key] = target;

    return (model.isNew() || model.hasChanged()) ? model.save(null, options) : model;
  });
};

Manager.prototype.setBelongsToMany = function(model, key, models, relation, options) {
  var existing = model.related(key);

  return Promise.cast(existing.length ? existing : existing.fetch(options)).then(function() {
    return this.setCollection(existing, models, options);
  }.bind(this)).then(function(targets) {
    // Enforce attach/detach IDs
    existing.relatedData.parentId = model.id;
    existing.relatedData.parentFk = model.id;

    return targets.mapThen(function(target) {
      if (!existing.findWhere({ id: target.id })) {
        return existing.attach(target, options);
      }
    }).then(function() {
      return existing.mapThen(function(target) {
        if (!targets.findWhere({ id: target.id })) {
          return existing.detach(target, options);
        }
      });
    });
  }).then(function() {
    return model;
  });
};

Manager.prototype.setHasMany = function(model, key, models, relation, options) {
  var existing = model.related(key);

  var fk = relation.relatedData.foreignKey;

  if (!fk) {
    throw new Error('`' + model.tableName + '#' + key + '` relation is missing `foreignKey` in `this.hasMany(Target, foreignKey)`');
  }

  models = models.map(function(target) {
    if (!target[fk]) {
      target[fk] = model.id;
    }
    return target;
  });

  return this.setCollection(existing, models, options).then(function(targets) {

    targets.forEach(function(target) {
      existing.add(target);
    });

    return existing.mapThen(function(target) {
      if (!targets.findWhere({ id: target.id })) {
        return target.destroy(options);
      }
    });
  }).then(function() {
    return model;
  });
};

Manager.prototype.setScalar = Promise.method(function(model, key, value) {
  if (key.indexOf('_pivot_') === 0) {
    return model;
  }

  if (model.get(key) === value) {
    return model;
  }

  model.set(key, value);

  return model;
});

Manager.prototype.setCollection = function(existing, models, options) {
  models = models || [];

  return Promise.map(models, function(properties) {
    var model = existing.findWhere({ id: properties.id }) || existing.model.forge();

    return this.save(model, properties, options);
  }.bind(this)).then(function(results) {
    return this.bookshelf.Collection.forge(results);
  }.bind(this));
};

module.exports = Manager;
<|endoftext|>


<commit_before>// client.js
var server = io.connect('/client');
server.on('welcome', function(data){
  console.log(data);
});
// TEST CODE
server.on('changeColor', function(data){
  $("#wrapper").hide();
  console.log(data.color);
  $('body').css({'background-color': data.color});
});

server.on('randomColor', function(data){
  var i = Math.floor(Math.random() * 10);
  var color = data.color[i];
  console.log(color);
  $('body').css({'background-color': color});
});

$(document).ready(function() {
  $('body').on("touchstart",function(){
      removeMotionListener();
  });
  server.on('switchPainting', function(data){
    data.paint ? initMotionListener() : removeMotionListener();
  });

  $('#modelWindow button').on('click touchend', closeModelMessage, false);
});

var initMotionListener = function() {
  $('#wrapper').fadeIn();
  window.addEventListener('devicemotion', function(event) {
    var aX = Math.floor(event.acceleration.x);
    var aY = Math.floor(event.acceleration.y);
    var aZ = Math.floor(event.acceleration.z);
    console.log(aX,aY,aZ);
    server.emit('paint',{
      aX: aX,
      aY: aY,
      aZ: aZ
    });
  }, false);
};

// TODO: Fix removeMotionListener
var removeMotionListener = function() {
  $('#wrapper').fadeOut();
  alert('inside removeMotionListener')
  window.removeEventListener('devicemotion', function(event) {
    var aX = Math.floor(event.acceleration.x);
    var aY = Math.floor(event.acceleration.y);
    var aZ = Math.floor(event.acceleration.z);
  }, false);
};

var makeModelMessage = function(headline, message) {
  $('#modelWindow h1').text(headline);
  $('#modelWindow p').text(message);
  $('#modelMask').fadeIn(300, function() {
    $('#modelWindow').fadeIn(400);
  });
};

var closeModelMessage = function(e) {
  e.preventDefault();
  $('#modelWindow').fadeOut(300, function() {
    $('#modelMask').fadeOut(200);
    $('#modelWindow h1').text('');
    $('#modelWindow p').text('');
  });
};<commit_msg>clean up comments<commit_after>var server = io.connect('/client');

server.on('welcome', function(data){
  console.log(data);
});

server.on('changeColor', function(data){
  $("#wrapper").hide();
  console.log(data.color);
  $('body').css({'background-color': data.color});
});

server.on('randomColor', function(data){
  var i = Math.floor(Math.random() * 10);
  var color = data.color[i];
  console.log(color);
  $('body').css({'background-color': color});
});

$(document).ready(function() {
  $('body').on("touchstart",function(){
      removeMotionListener();
  });
  server.on('switchPainting', function(data){
    data.paint ? initMotionListener() : removeMotionListener();
  });

  $('#modelWindow button').on('click touchend', closeModelMessage, false);
});

var initMotionListener = function() {
  $('#wrapper').fadeIn();
  window.addEventListener('devicemotion', function(event) {
    var aX = Math.floor(event.acceleration.x);
    var aY = Math.floor(event.acceleration.y);
    var aZ = Math.floor(event.acceleration.z);
    console.log(aX,aY,aZ);
    server.emit('paint',{
      aX: aX,
      aY: aY,
      aZ: aZ
    });
  }, false);
};

// TODO: Fix removeMotionListener
var removeMotionListener = function() {
  $('#wrapper').fadeOut();
  alert('inside removeMotionListener')
  window.removeEventListener('devicemotion', function(event) {
    var aX = Math.floor(event.acceleration.x);
    var aY = Math.floor(event.acceleration.y);
    var aZ = Math.floor(event.acceleration.z);
  }, false);
};

// Message Functions for Later
var makeModelMessage = function(headline, message) {
  $('#modelWindow h1').text(headline);
  $('#modelWindow p').text(message);
  $('#modelMask').fadeIn(300, function() {
    $('#modelWindow').fadeIn(400);
  });
};

var closeModelMessage = function(e) {
  e.preventDefault();
  $('#modelWindow').fadeOut(300, function() {
    $('#modelMask').fadeOut(200);
    $('#modelWindow h1').text('');
    $('#modelWindow p').text('');
  });
};<|endoftext|>


<commit_before>/*global defineSuite*/
defineSuite([
         'Scene/Sun',
         'Specs/createCamera',
         'Specs/createFrameState',
         'Specs/createScene',
         'Specs/destroyScene',
         'Core/Cartesian3',
         'Scene/SceneMode'
     ], function(
         Sun,
         createCamera,
         createFrameState,
         createScene,
         destroyScene,
         Cartesian3,
         SceneMode) {
    "use strict";
    /*global jasmine,describe,xdescribe,it,xit,expect,beforeEach,afterEach,beforeAll,afterAll,spyOn,runs,waits,waitsFor*/

    var scene;

    beforeAll(function() {
        scene = createScene();
    });

    afterAll(function() {
        destroyScene(scene);
    });

    it('draws in 3D', function() {
        scene.sun = new Sun();
        scene.initializeFrame();
        scene.render();

        var us = scene.getContext().getUniformState();
        var camera = scene.getCamera();

        var sunPosition = us.getSunPositionWC();
        var cameraPosition = sunPosition.normalize().multiplyByScalar(1e8);
        camera.controller.lookAt(sunPosition, cameraPosition, Cartesian3.UNIT_Z);

        scene.initializeFrame();
        scene.render();
        expect(scene.getContext().readPixels()).toNotEqual([0, 0, 0, 0]);
    });

    it('draws in Columbus view', function() {
        scene.sun = new Sun();

        scene.mode = SceneMode.COLUMBUS_VIEW;
        scene.initializeFrame();
        scene.render();

        var us = scene.getContext().getUniformState();
        var camera = scene.getCamera();

        var sunPosition = us.getSunPositionColumbusView();
        var cameraPosition = sunPosition.normalize().multiplyByScalar(1e8);
        camera.controller.lookAt(sunPosition, cameraPosition, Cartesian3.UNIT_Z);

        scene.initializeFrame();
        scene.render();
        expect(scene.getContext().readPixels()).toNotEqual([0, 0, 0, 0]);
    });

    it('does not render when show is false', function() {
        var sun = new Sun();
        sun.show = false;

        var context = scene.getContext();

        var frameState = createFrameState(createCamera(context, undefined, undefined, undefined, 1.0, 1.0e10));
        var us = context.getUniformState();
        us.update(frameState);

        var sunPosition = us.getSunPositionWC();
        var cameraPosition = sunPosition.normalize().multiplyByScalar(1e8);
        frameState.camera.controller.lookAt(sunPosition, cameraPosition, Cartesian3.UNIT_Z);

        us.update(frameState);

        var command = sun.update(context, frameState);
        expect(command).not.toBeDefined();

        sun.destroy();
    });

    it('does not render in 2D', function() {
        var sun = new Sun();

        var context = scene.getContext();

        var frameState = createFrameState(createCamera(context, undefined, undefined, undefined, 1.0, 1.0e10));
        frameState.mode = SceneMode.SCENE2D;
        var us = context.getUniformState();
        us.update(frameState);

        var sunPosition = us.getSunPositionWC();
        var cameraPosition = sunPosition.normalize().multiplyByScalar(1e8);
        frameState.camera.controller.lookAt(sunPosition, cameraPosition, Cartesian3.UNIT_Z);

        us.update(frameState);

        var command = sun.update(context, frameState);
        expect(command).not.toBeDefined();

        sun.destroy();
    });

    it('does not render without a color pass', function() {
        var sun = new Sun();

        var context = scene.getContext();

        var frameState = createFrameState(createCamera(context, undefined, undefined, undefined, 1.0, 1.0e10));
        frameState.passes.color = false;
        var us = context.getUniformState();
        us.update(frameState);

        var sunPosition = us.getSunPositionWC();
        var cameraPosition = sunPosition.normalize().multiplyByScalar(1e8);
        frameState.camera.controller.lookAt(sunPosition, cameraPosition, Cartesian3.UNIT_Z);

        us.update(frameState);

        var command = sun.update(context, frameState);
        expect(command).not.toBeDefined();

        sun.destroy();
    });

    it('can set glow factor', function() {
        var sun = scene.sun = new Sun();
        sun.setGlowFactor(0.0);
        expect(sun.getGlowFactor()).toEqual(0.0);
        sun.setGlowFactor(2.0);
        expect(sun.getGlowFactor()).toEqual(2.0);
    });

    it('draws without lens flare', function() {
        scene.sun = new Sun();
        scene.sun.setGlowFactor(0.0);
        scene.initializeFrame();
        scene.render();

        var us = scene.getContext().getUniformState();
        var camera = scene.getCamera();

        var sunPosition = us.getSunPositionWC();
        var cameraPosition = sunPosition.normalize().multiplyByScalar(1e8);
        camera.controller.lookAt(sunPosition, cameraPosition, Cartesian3.UNIT_Z);

        scene.initializeFrame();
        scene.render();
        expect(scene.getContext().readPixels()).toNotEqual([0, 0, 0, 0]);
    });

    it('isDestroyed', function() {
        var sun = new Sun();
        expect(sun.isDestroyed()).toEqual(false);
        sun.destroy();
        expect(sun.isDestroyed()).toEqual(true);
    });
});<commit_msg>Fix tests.<commit_after>/*global defineSuite*/
defineSuite([
         'Scene/Sun',
         'Specs/createCamera',
         'Specs/createFrameState',
         'Specs/createScene',
         'Specs/destroyScene',
         'Core/Cartesian3',
         'Scene/SceneMode'
     ], function(
         Sun,
         createCamera,
         createFrameState,
         createScene,
         destroyScene,
         Cartesian3,
         SceneMode) {
    "use strict";
    /*global jasmine,describe,xdescribe,it,xit,expect,beforeEach,afterEach,beforeAll,afterAll,spyOn,runs,waits,waitsFor*/

    var scene;

    beforeAll(function() {
        scene = createScene();
    });

    afterAll(function() {
        destroyScene(scene);
    });

    it('draws in 3D', function() {
        scene.sun = new Sun();
        scene.initializeFrame();
        scene.render();

        var us = scene.getContext().getUniformState();
        var camera = scene.getCamera();

        var sunPosition = us.getSunPositionWC();
        var cameraPosition = sunPosition.normalize().multiplyByScalar(1e8);
        camera.controller.lookAt(sunPosition, cameraPosition, Cartesian3.UNIT_Z);

        scene.initializeFrame();
        scene.render();
        expect(scene.getContext().readPixels()).toNotEqual([0, 0, 0, 0]);
    });

    it('draws in Columbus view', function() {
        scene.sun = new Sun();

        scene.mode = SceneMode.COLUMBUS_VIEW;
        scene.initializeFrame();
        scene.render();

        var us = scene.getContext().getUniformState();
        var camera = scene.getCamera();

        var sunPosition = us.getSunPositionColumbusView();
        var cameraPosition = sunPosition.normalize().multiplyByScalar(1e8);
        camera.controller.lookAt(sunPosition, cameraPosition, Cartesian3.UNIT_Z);

        scene.initializeFrame();
        scene.render();
        expect(scene.getContext().readPixels()).toNotEqual([0, 0, 0, 0]);
    });

    it('does not render when show is false', function() {
        var sun = new Sun();
        sun.show = false;

        var context = scene.getContext();

        var frameState = createFrameState(createCamera(context, undefined, undefined, undefined, 1.0, 1.0e10));
        var us = context.getUniformState();
        us.update(frameState);

        var sunPosition = us.getSunPositionWC();
        var cameraPosition = sunPosition.normalize().multiplyByScalar(1e8);
        frameState.camera.controller.lookAt(sunPosition, cameraPosition, Cartesian3.UNIT_Z);

        us.update(frameState);

        var command = sun.update(context, frameState);
        expect(command).not.toBeDefined();

        sun.destroy();
    });

    it('does not render in 2D', function() {
        var sun = new Sun();

        var context = scene.getContext();

        var frameState = createFrameState(createCamera(context, undefined, undefined, undefined, 1.0, 1.0e10));
        frameState.mode = SceneMode.SCENE2D;
        var us = context.getUniformState();
        us.update(frameState);

        var sunPosition = us.getSunPositionWC();
        var cameraPosition = sunPosition.normalize().multiplyByScalar(1e8);
        frameState.camera.controller.lookAt(sunPosition, cameraPosition, Cartesian3.UNIT_Z);

        us.update(frameState);

        var command = sun.update(context, frameState);
        expect(command).not.toBeDefined();

        sun.destroy();
    });

    it('does not render without a color pass', function() {
        var sun = new Sun();

        var context = scene.getContext();

        var frameState = createFrameState(createCamera(context, undefined, undefined, undefined, 1.0, 1.0e10));
        frameState.passes.color = false;
        var us = context.getUniformState();
        us.update(frameState);

        var sunPosition = us.getSunPositionWC();
        var cameraPosition = sunPosition.normalize().multiplyByScalar(1e8);
        frameState.camera.controller.lookAt(sunPosition, cameraPosition, Cartesian3.UNIT_Z);

        us.update(frameState);

        var command = sun.update(context, frameState);
        expect(command).not.toBeDefined();

        sun.destroy();
    });

    it('can set glow factor', function() {
        var sun = scene.sun = new Sun();
        sun.glowFactor = 0.0;
        expect(sun.glowFactor).toEqual(0.0);
        sun.glowFactor = 2.0;
        expect(sun.glowFactor).toEqual(2.0);
    });

    it('draws without lens flare', function() {
        scene.sun = new Sun();
        scene.sun.glowFactor = 0.0;
        scene.initializeFrame();
        scene.render();

        var us = scene.getContext().getUniformState();
        var camera = scene.getCamera();

        var sunPosition = us.getSunPositionWC();
        var cameraPosition = sunPosition.normalize().multiplyByScalar(1e8);
        camera.controller.lookAt(sunPosition, cameraPosition, Cartesian3.UNIT_Z);

        scene.initializeFrame();
        scene.render();
        expect(scene.getContext().readPixels()).toNotEqual([0, 0, 0, 0]);
    });

    it('isDestroyed', function() {
        var sun = new Sun();
        expect(sun.isDestroyed()).toEqual(false);
        sun.destroy();
        expect(sun.isDestroyed()).toEqual(true);
    });
});<|endoftext|>


<commit_before>// init
var fs = require('fs-extra');
var epub = require('epub-gen');
var kg = require('./kindlegen.js');
var pathF = require('path');

var converter = function() {

    var self = this;
    var path = 'data/books/';
    var taskPath = 'data/tasks/converter.task';
    var tempEpudPath = 'node_modules/epub_gen/tempDir';
    var tempCleanCount = 0;  // clean temp dir if count > 3
    var maxTempCleanCount = 5;
    var taskList = [];
    var status;

    const READY = 0,
        WORKING = 1;

    this.init = function() {

        fs.readJson(taskPath, function(err, t) {

            status = READY;

            if (!err) {
                taskList = t;

            } else {

                taskList = [];
            }

            console.log('Converter > Initialized.', taskList.length, 'tasks waiting.');

            if (taskList.length > 0) self.convertBook();
        });
    };

    this.isDuplicate = function (task) {

        var result = false;

        taskList.forEach(function (e, i, a) {

            if (e.cid == task.cid && e.bookInfo.id == task.bookInfo.id) result = true;

        });

        return result;

    }

    this.valid = function (task) {

        // check if the book was converted within 1 day

        var result = false;

        var one_hour = 1000 * 60 * 60;

        var lastConvert = task.bookInfo.chapters[task.cid].lastConvert;
        var diff = ((Date.now() - lastConvert) / one_hour).toFixed(0);

        if (!lastConvert || lastConvert == 0 || diff >= 20) result = true;

        return result;

    }

    this.queue = function (cid, bookInfo, callback) {

        // callback(err, type{'epup' || 'mobi' || 'busy'}, bookInfo)

        var task = {
            cid: cid,
            bookInfo: bookInfo,
            callback: callback
        };

        // check duplicate

        if (self.isDuplicate(task)) {

            if (callback) callback(new Error('task is already in the list'));

            console.log('Converter > Task is already in the list!');

            return false;
        }

        // check if the book is updated within 1 day.

        if (!self.valid(task)) {

            if (callback) callback(new Error('Task has been converted within 1 day.'));

            console.log('Converter > Task has been converted within 1 day.');

            return false;
        }

        fs.access('data/books/' + bookInfo.id + '/txt/' + bookInfo.chapters[cid].vid + '.txt', fs.R_OK | fs.W_OK, (err) => {

            if (!err) {

                // no error opening the file

                console.log('Converter > Queued task:', bookInfo.title, bookInfo.chapters[cid].title);

                taskList.push(task);

                self.saveTask();
                self.convertBook();

                if (taskList.length > 0) {
                    if (callback) callback(null, 'busy', bookInfo);
                }

                console.log('Converter > Tasks:', taskList.length);

            } else {

                console.log('Converter > Failed to queue task:', bookInfo.title, bookInfo.chapters[cid].title);
                callback(err, null);

            }
        });

        //self.convertBook();

        return true;
    }

    this.convertBook = function () {

        // check status
        if (status == READY && taskList.length > 0) {

            if (!taskList[0].bookInfo) {

                taskList[0].callback(new Error('bookInfo is empty'), null);

                // if no bookinfo, remove then return.
                self.remove(0);

                // after converted to mobi, keep convert
                self.convertBook();

            }

            // set status to busy

            status = WORKING;

            // if no callback set default callback

            if(!taskList[0].callback) taskList[0].callback = function(){

                console.log('Converter > No callback!');
            };

            // Start

            var chapters;

            self.readBook(taskList[0].cid, taskList[0].bookInfo, function(err, c) {

                if (!err) {
                    // no err parse the book, start converting
                    console.log('Converter > Start converting!');

                    // start generating epub
                    var vPath = path + taskList[0].bookInfo.id;
                    var epubPath = vPath + "/epub/" + taskList[0].bookInfo.chapters[taskList[0].cid].vid + '.epub'

                    if (taskList[0].bookInfo.chapters[taskList[0].cid].images[0]) {

                        // if there is a cover for chapter exist

                        var coverPath = taskList[0].bookInfo.chapters[taskList[0].cid].images[0];

                        if (coverPath.startsWith('./')) coverPath = pathF.resolve(__dirname + '/../',coverPath);

                    } else {

                        // else use the default cover image

                        var coverPath = './' + vPath + '/image.jpg';

                    }
                    var option = {
                        title: taskList[0].bookInfo.title + ' ' + taskList[0].bookInfo.chapters[taskList[0].cid].title, // *Required, title of the book.
                        author: taskList[0].bookInfo.author,
                        publisher: taskList[0].bookInfo.publisher,
                        cover: coverPath,
                        appendChapterTitles: false,
                        content: [],
                        description: taskList[0].bookInfo.desc,
                    };

                    console.log('Converter > Finished init epub generate options.');

                    // add title page

                    var chapter = {
                        title: taskList[0].bookInfo.title,
                        data: '

' + taskList[0].bookInfo.chapters[taskList[0].cid].title + '

内容简介

' + taskList[0].bookInfo.desc + '
'
                    };

                    option.content.push(chapter);

                    // add chapters

                    c.forEach(function (element, index, array) {

                        var chapter;

                        if (element.title.includes('插图')) {

                            // if the chapter is image chapter

                            console.log('Converter > Adding images to the book.');

                            var images = taskList[0].bookInfo.chapters[taskList[0].cid].images;
                            var data = '

' + element.title + '

';

                            images.forEach(function (element, index, array) {

                                if (element.startsWith('./')) {

                                    data += '
';
                                } else {

                                    data += '
';
                                }

                            });

                            data += element.content + '
';

                            chapter = {

                                title: element.title,
                                data: data

                            };

                        } else {

                            // if it isnt image chapter

                            chapter = {
                                title: element.title,
                                data: '

' + element.title + '

' + element.content + '
'
                            };
                        }

                        option.content.push(chapter);

                        console.log('Converter > Added chapter', element.title);
                    });

                    var chapter = {
                        title: 'Kindle Light',
                        data: '
本图书由Kindle Light 在线生成工具自动生成的哦！看更多的Kindle轻小说，请来: Kindle Light!

'
                    };

                    option.content.push(chapter);

                    console.log('Converter > Chapters setup complete.');

                    // start converting

                    fs.ensureDir(vPath + "/epub/", function(err) {

                        if (!err) {

                            // no error ensure the dir : /epub/

                            new epub(option, epubPath).promise.then(function() {

                                console.log("Converter > Ebook Generated Successfully!");

                                // callback epub file generated

                                taskList[0].callback(null, 'epub', taskList[0].cid, taskList[0].bookInfo);

                                // start convert the book to .mobi

                                // sudo ./bin/kindlegen/kindlegen -c2 ./data/books/1657/epub/57218.epub -o 57218.mobi

                                fs.ensureDir(vPath + '/mobi/', function(err) {

                                    if (!err) {

                                        // empty the temp files

                                        if (tempCleanCount >= maxTempCleanCount) {

                                            fs.emptyDir(tempEpudPath, function (err) {
                                                if (!err) console.log('Converter > Clean temp file successful!')
                                            });

                                            tempCleanCount = 0;

                                        } else {

                                            tempCleanCount ++;
                                        }

                                        // no error when ensuring the mobi dir

                                        //start converting

                                        console.log('Converter > Converting .epub to .mobi.');

                                        var epubPath = vPath + "/epub/" + taskList[0].bookInfo.chapters[taskList[0].cid].vid + '.epub';
                                        var mobiPath = vPath + "/mobi/" + taskList[0].bookInfo.chapters[taskList[0].cid].vid + '.mobi';
                                        var orimobiPath = vPath + "/epub/" + taskList[0].bookInfo.chapters[taskList[0].cid].vid + '.mobi';

                                        // start converting , from epub to mobi

                                        kg.convert(epubPath, function(err, out) {

                                            fs.move(orimobiPath, mobiPath, {
                                                clobber: true // set overwrite
                                            }, function(err) {

                                                if (!err) {
                                                    // no err moving the file

                                                    console.log('Converter > Convert successful! File:', mobiPath);

                                                    taskList[0].callback(null, 'mobi', taskList[0].cid, taskList[0].bookInfo);

                                                } else {

                                                    // err moving the file

                                                    console.log('Converter > Error moving the file! File:', mobiPath);

                                                }

                                                self.remove(0);

                                                // after converted to mobi, keep convert
                                                self.convertBook();
                                            });

                                        });

                                        // done converting epub

                                    }

                                });

                                // keep convert

                            }, function (err) {

                                // err when converting to epub

                                console.error("Converter > Failed to generate Ebook because of ", err);

                                taskList[0].callback(err);

                                // err

                                self.remove(0);

                                console.log('Converter > Error when converting:', err);

                                // keep convert

                                self.convertBook();
                            });

                        } else {

                            // error when ensure /epub/ dir

                            taskList[0].callback(err);

                            // err

                            self.remove(0);

                            console.log('Converter > Error when converting:', err);

                            // keep convert

                            self.convertBook();

                        }

                    })

                } else {

                    // Error parse the book

                    taskList[0].callback(err);

                    // err

                    self.remove(0);

                    console.log('Converter > Error when reading file:', err);

                    // keep convert

                    self.convertBook();

                }

            });

        } else {

            console.log('Converter > No task to do or Converter is working.');

            if (status == READY) taskList = [];

            //self.saveTask();
        }

    }

    this.readBook = function(cid, bookInfo, callback) {

        var cid = cid;
        var chapters = [];
        var title = bookInfo.chapters[cid].title.replace('\r\n', '');
        var file = path + bookInfo.id + '/txt/' + bookInfo.chapters[cid].vid + '.txt';

        // open file

        console.log('Converter > Reading local file:', file);

        fs.readFile(file, function(err, data) {

            if (!err) {

                // file opened

                console.log('Converter > Parsing Book.');

                // parse the book/chapters

                var book = String(data).replace('undefined', '').split(title);
                var chapters = [];

                // remove the first chapter : ★☆★☆★☆轻小说文库(Www.WenKu8.com)☆★☆★☆★
                book.splice(0, 1);

                book.forEach(function(element, index, array) {

                    var ctitle = element.substr(1, element.indexOf('\r\n', 1)).replace('\r', '');
                    var cdata = element.substr(element.indexOf('\r\n', 1), element.length).replace(/(\r\n|\n|\r)/g, '
');

                    chapters.push({
                        id: index,
                        title: ctitle,
                        content: cdata
                    });

                });

                callback(err, chapters);

            } else {

                console.log('Conveter > Err opening file', file);

                callback(err, null);

                self.remove(0);
            }

        });

    };

    this.remove = function(id) {

        if (taskList[id])
            taskList.splice(id, 1);
        status = READY;

        self.saveTask();
    }

    this.saveTask = function() {

        console.log('Converter > Saving tasks..');

        fs.outputJson(taskPath, taskList, function(err) {

            if (!err) {

                console.log('Converter > Task list saved.');

            } else {

                console.log('Converter > Task list save failed.');
            }

        });
    }

    this.getTaskNum = function () {

        return taskList.length;

    }

}

// export module
module.exports = new converter();
<commit_msg>converter error<commit_after>// init
var fs = require('fs-extra');
var epub = require('epub-gen');
var kg = require('./kindlegen.js');
var pathF = require('path');

var converter = function() {

    var self = this;
    var path = 'data/books/';
    var taskPath = 'data/tasks/converter.task';
    var tempEpudPath = 'node_modules/epub_gen/tempDir';
    var tempCleanCount = 0;  // clean temp dir if count > 3
    var maxTempCleanCount = 5;
    var taskList = [];
    var status;

    const READY = 0,
        WORKING = 1;

    this.init = function() {

        fs.readJson(taskPath, function(err, t) {

            status = READY;

            if (!err) {
                taskList = t;

            } else {

                taskList = [];
            }

            console.log('Converter > Initialized.', taskList.length, 'tasks waiting.');

            if (taskList.length > 0) self.convertBook();
        });
    };

    this.isDuplicate = function (task) {

        var result = false;

        taskList.forEach(function (e, i, a) {

            if (e.cid == task.cid && e.bookInfo.id == task.bookInfo.id) result = true;

        });

        return result;

    }

    this.valid = function (task) {

        // check if the book was converted within 1 day

        var result = false;

        var one_hour = 1000 * 60 * 60;

        var lastConvert = task.bookInfo.chapters[task.cid].lastConvert;
        var diff = ((Date.now() - lastConvert) / one_hour).toFixed(0);

        if (!lastConvert || lastConvert == 0 || diff >= 20) result = true;

        return result;

    }

    this.queue = function (cid, bookInfo, callback) {

        // callback(err, type{'epup' || 'mobi' || 'busy'}, bookInfo)

        var task = {
            cid: cid,
            bookInfo: bookInfo,
            callback: callback
        };

        // check duplicate

        if (self.isDuplicate(task)) {

            if (callback) callback(new Error('task is already in the list'));

            console.log('Converter > Task is already in the list!');

            return false;
        }

        // check if the book is updated within 1 day.

        if (!self.valid(task)) {

            if (callback) callback(new Error('Task has been converted within 1 day.'));

            console.log('Converter > Task has been converted within 1 day.');

            return false;
        }

        fs.access('data/books/' + bookInfo.id + '/txt/' + bookInfo.chapters[cid].vid + '.txt', fs.R_OK | fs.W_OK, (err) => {

            if (!err) {

                // no error opening the file

                console.log('Converter > Queued task:', bookInfo.title, bookInfo.chapters[cid].title);

                taskList.push(task);

                self.saveTask();
                self.convertBook();

                if (taskList.length > 0) {
                    if (callback) callback(null, 'busy', bookInfo);
                }

                console.log('Converter > Tasks:', taskList.length);

            } else {

                console.log('Converter > Failed to queue task:', bookInfo.title, bookInfo.chapters[cid].title);
                callback(err, null);

            }
        });

        //self.convertBook();

        return true;
    }

    this.convertBook = function () {

        // check status
        if (status == READY && taskList.length > 0) {

            if (!taskList[0].bookInfo) {

                taskList[0].callback(new Error('bookInfo is empty'), null);

                // if no bookinfo, remove then return.
                self.remove(0);

                // after converted to mobi, keep convert
                self.convertBook();

            }

            // set status to busy

            status = WORKING;

            // if no callback set default callback

            if(!taskList[0].callback) taskList[0].callback = function(){

                console.log('Converter > No callback!');
            };

            // Start

            var chapters;

            self.readBook(taskList[0].cid, taskList[0].bookInfo, function(err, c) {

                if (!err) {
                    // no err parse the book, start converting
                    console.log('Converter > Start converting!');

                    // start generating epub
                    var vPath = path + taskList[0].bookInfo.id;
                    var epubPath = vPath + "/epub/" + taskList[0].bookInfo.chapters[taskList[0].cid].vid + '.epub'

                    if (taskList[0].bookInfo.chapters[taskList[0].cid].images[0]) {

                        // if there is a cover for chapter exist

                        var coverPath = taskList[0].bookInfo.chapters[taskList[0].cid].images[0];

                        if (coverPath.startsWith('./')) coverPath = pathF.resolve(__dirname + '/../',coverPath);

                    } else {

                        // else use the default cover image

                        var coverPath = './' + vPath + '/image.jpg';

                    }
                    var option = {
                        title: taskList[0].bookInfo.title + ' ' + taskList[0].bookInfo.chapters[taskList[0].cid].title, // *Required, title of the book.
                        author: taskList[0].bookInfo.author,
                        publisher: taskList[0].bookInfo.publisher,
                        cover: coverPath,
                        appendChapterTitles: false,
                        content: [],
                        description: taskList[0].bookInfo.desc,
                    };

                    console.log('Converter > Finished init epub generate options.');

                    // add title page

                    var chapter = {
                        title: taskList[0].bookInfo.title,
                        data: '

' + taskList[0].bookInfo.chapters[taskList[0].cid].title + '

内容简介

' + taskList[0].bookInfo.desc + '
'
                    };

                    option.content.push(chapter);

                    // add chapters

                    c.forEach(function (element, index, array) {

                        var chapter;

                        if (element.title.includes('插图')) {

                            // if the chapter is image chapter

                            console.log('Converter > Adding images to the book.');

                            var images = taskList[0].bookInfo.chapters[taskList[0].cid].images;
                            var data = '

' + element.title + '

';

                            images.forEach(function (element, index, array) {

                                if (element.startsWith('./')) {

                                    data += '
';
                                } else {

                                    data += '
';
                                }

                            });

                            data += element.content + '
';

                            chapter = {

                                title: element.title,
                                data: data

                            };

                        } else {

                            // if it isnt image chapter

                            chapter = {
                                title: element.title,
                                data: '

' + element.title + '

' + element.content + '
'
                            };
                        }

                        option.content.push(chapter);

                        console.log('Converter > Added chapter', element.title);
                    });

                    var chapter = {
                        title: 'Kindle Light',
                        data: '
本图书由Kindle Light 在线生成工具自动生成的哦！看更多的Kindle轻小说，请来: Kindle Light!

'
                    };

                    option.content.push(chapter);

                    console.log('Converter > Chapters setup complete.');

                    // start converting

                    fs.ensureDir(vPath + "/epub/", function(err) {

                        if (!err) {

                            // no error ensure the dir : /epub/

                            new epub(option, epubPath).promise.then(function() {

                                console.log("Converter > Ebook Generated Successfully!");

                                // callback epub file generated

                                taskList[0].callback(null, 'epub', taskList[0].cid, taskList[0].bookInfo);

                                // start convert the book to .mobi

                                // sudo ./bin/kindlegen/kindlegen -c2 ./data/books/1657/epub/57218.epub -o 57218.mobi

                                fs.ensureDir(vPath + '/mobi/', function(err) {

                                    if (!err) {

                                        // no error when ensuring the mobi dir

                                        //start converting

                                        console.log('Converter > Converting .epub to .mobi.');

                                        var epubPath = vPath + "/epub/" + taskList[0].bookInfo.chapters[taskList[0].cid].vid + '.epub';
                                        var mobiPath = vPath + "/mobi/" + taskList[0].bookInfo.chapters[taskList[0].cid].vid + '.mobi';
                                        var orimobiPath = vPath + "/epub/" + taskList[0].bookInfo.chapters[taskList[0].cid].vid + '.mobi';

                                        // start converting , from epub to mobi

                                        kg.convert(epubPath, function (err, out) {

                                            fs.move(orimobiPath, mobiPath, {
                                                clobber: true // set overwrite
                                            }, function (err) {

                                                if (!err) {
                                                    // no err moving the file

                                                    console.log('Converter > Convert successful! File:', mobiPath);

                                                    taskList[0].callback(null, 'mobi', taskList[0].cid, taskList[0].bookInfo);

                                                } else {

                                                    // err moving the file

                                                    console.log('Converter > Error moving the file! File:', mobiPath);

                                                }

                                                self.remove(0);

                                                // after converted to mobi, keep convert
                                                self.convertBook();
                                            });

                                        });

                                        // done converting epub

                                    } else {

                                        // err ensuring mobi path
                                        console.log('Converter > Error ensoring mobi folder');

                                        self.remove(0);

                                        // after converted to mobi, keep convert
                                        self.convertBook();

                                    }

                                });

                                // keep convert

                            }, function (err) {

                                // err when converting to epub

                                console.error("Converter > Failed to generate Ebook because of ", err);

                                taskList[0].callback(err);

                                // err

                                self.remove(0);

                                console.log('Converter > Error when converting:', err);

                                // keep convert

                                self.convertBook();
                            });

                        } else {

                            // error when ensure /epub/ dir

                            taskList[0].callback(err);

                            // err

                            self.remove(0);

                            console.log('Converter > Error when converting:', err);

                            // keep convert

                            self.convertBook();

                        }

                    })

                } else {

                    // Error parse the book

                    taskList[0].callback(err);

                    // err

                    self.remove(0);

                    console.log('Converter > Error when reading file:', err);

                    // keep convert

                    self.convertBook();

                }

            });

        } else {

            console.log('Converter > No task to do or Converter is working.');

            if (status == READY) taskList = [];

            //self.saveTask();

            // empty the temp files

            if (tempCleanCount >= maxTempCleanCount) {

                fs.emptyDir(tempEpudPath, function (err) {
                    if (!err) console.log('Converter > Clean temp file successful!')
                });

                tempCleanCount = 0;

            } else {

                tempCleanCount++;
            }

        }

    }

    this.readBook = function(cid, bookInfo, callback) {

        var cid = cid;
        var chapters = [];
        var title = bookInfo.chapters[cid].title.replace('\r\n', '');
        var file = path + bookInfo.id + '/txt/' + bookInfo.chapters[cid].vid + '.txt';

        // open file

        console.log('Converter > Reading local file:', file);

        fs.readFile(file, function(err, data) {

            if (!err) {

                // file opened

                console.log('Converter > Parsing Book.');

                // parse the book/chapters

                var book = String(data).replace('undefined', '').split(title);
                var chapters = [];

                // remove the first chapter : ★☆★☆★☆轻小说文库(Www.WenKu8.com)☆★☆★☆★
                book.splice(0, 1);

                book.forEach(function(element, index, array) {

                    var ctitle = element.substr(1, element.indexOf('\r\n', 1)).replace('\r', '');
                    var cdata = element.substr(element.indexOf('\r\n', 1), element.length).replace(/(\r\n|\n|\r)/g, '
');

                    chapters.push({
                        id: index,
                        title: ctitle,
                        content: cdata
                    });

                });

                callback(err, chapters);

            } else {

                console.log('Conveter > Err opening file', file);

                callback(err, null);

                self.remove(0);
            }

        });

    };

    this.remove = function(id) {

        if (taskList[id])
            taskList.splice(id, 1);
        status = READY;

        self.saveTask();
    }

    this.saveTask = function() {

        console.log('Converter > Saving tasks..');

        fs.outputJson(taskPath, taskList, function(err) {

            if (!err) {

                console.log('Converter > Task list saved.');

            } else {

                console.log('Converter > Task list save failed.');
            }

        });
    }

    this.getTaskNum = function () {

        return taskList.length;

    }

}

// export module
module.exports = new converter();
<|endoftext|>


<commit_before>//collect.js gets gets pages and runs them through the data pipeline

//  Output schema:
///    this page's URL                  url        str
///    the next closest root to Dada    url        str (will need to recalc this in post-processing)
///    the page's title                 words      str
///    the page's image, if it has one  url        str
///    links from this page             mapsTo     []
///    pages linking to this one        mapsFrom   []
///    metaData from wiki's data page   metaData   {}

var request = require('request');
var fs = require('fs');
var async = require('async');
var d3 = require('d3');

//local modules
var dataScrape = require('./s-wikiData');
var mF = require('./s-mapsFrom');
var mT = require('./s-mainPage');
var detect = require('./s-detect');

var pagesIn = JSON.parse(fs.readFileSync('randomSample.json'));
    // pagesIn_2 = JSON.parse(fs.readFileSync('mapsTo_Crawl.json'));

// pagesIn = pagesIn.concat(pagesIn_2);

var dups = JSON.parse(fs.readFileSync('dups.json'));

//data
var pages = [],
    lastBatch = 0;

//c = count, s = stop, d = done (boolean)
var nl_c = 0,
    nl_s = 10,
    mapsToDone = false,
    mapsFromDone = false,
    urlArr,                       // urlArr to scrape
    filenames = [],               // store filenames
    t_c = 0,                      // inner counter
    t_s = 10,                     // inner stop point (init value is random)
    delay = [1200,3600];          // delay for timeout

// test URLs - 'Francis_Picabia' - 'Ann%C3%A9es_folles' - 'Dada'

var exceptions = [
  'wikisource.org',
  '.jpg',
  '.png',
  '.gif',
  'Book:'
]

var fullSkip = [
  'wikipedia',      // no foriegn pages (not in scope)
  'wiktionary.org', // no wiktionary pages
  'wikiquote',      // no wikiquote pages
  '_talk:',         // no talk pages
  'Draft:'
]

// check for exceptions
function skip(link, exc) {
  var fact = false;
  for (var c in exc) {
    if (link.includes(exc[c])) {
      fact = true;
      break;
    }
  }
  return fact;
}

function getRando(min, max) {
  return Math.floor(Math.random() * (max - min) + min);
}

function writeDataFile(location, counter) {
  //counter++;
  if (counter>=t_s || counter%250==0) { //if last loop or if counter is divisible by 250, write the file

    var maps = function() { if (mapsToDone) { return 'mapsFrom'; } else { return 'mapsTo'; } }
    var filename = 'data/'+maps()+'-index'+location+'-batch'+lastBatch+'-'+counter+'.json';
    fs.writeFile(filename, JSON.stringify(pages), function(err) {
        if (err) {throw err;}
        console.log(filename+' written');
        filenames.push(filename);
        lastBatch = counter;
        pages = [];
    });

  }
}

function crawler() {           //  create a loop function
   setTimeout(function () {    //  call a 3s setTimeout when the loop is called

        // check for already scraped urls
        if(!dups.hasOwnProperty(urlArr[t_c])) {

          var page = new Object;
          page.distance = 2;
          page.root = pagesIn[nl_c].url;
          page.url =  urlArr[t_c];        // testURL_1;
          dups[urlArr[t_c]] = 1;          // add to dups
          delay = [1200,3600];

          var url = 'https://en.wikipedia.org/wiki/'+page.url;
          var mapsFromURL = 'https://en.wikipedia.org/w/index.php?title=Special:WhatLinksHere/'+page.url+'&limit=3000';

          //check for fullSkip (pages not scraping) pages
          if (!skip(page.url, fullSkip)) {

          // collect links pointing at this page
          request(mapsFromURL, function(err, resp, body) {
            if (err) {throw err;}
              console.log('scraping mapsFrom '+mapsFromURL);
              page.mapsFrom = mF.scrape(body);
             if (!skip(page.url, exceptions)) {

              // collect links pointing outwards from the page
              request(url, function(err, resp, body) {
                 if (err) {throw err;}
                  console.log('scraping mainPage '+url);
                  var s = mT.scrape(body, url);
                  page.mapsTo = s.mapsTo;
                  page.wikiData = s.wikiData;
                  page.image = s.image;
                  page.title = s.title;

                 if (page.wikiData!=undefined) {
                   // collect wikiData (categorical info)
                   request(page.wikiData, function(err, resp, body) {
                      if (err) {throw err;}
                       console.log('scraping wikiData '+page.wikiData);
                       page.metaData = dataScrape.scrape(body);
                       pages.push(page);
                       writeDataFile(nl_c, t_c);
                   });
                 } else {
                   // case no wikiData
                   page.metaData = null;
                   pages.push(page);
                   writeDataFile(nl_c, t_c);
                 }
              }); // end mainPage request
            } else {
              // some page types don't have link info, push as-is
              pages.push(page);
              writeDataFile(nl_c, t_c);
            }
          });
        } else {
          page.noScrape = 1;
          pages.push(page);
          console.log('-NO SCRAPE-');
          writeDataFile(nl_c, t_c);
        } // end fullSkip conditional
      } else {
        // track url distribution
        dups[urlArr[t_c]]++;
        // no delay on dups
        delay = [0,0];
      } // end dups conditional

    // iterator
    if (t_c < t_s) { //pagesIn[pgI].mapsTo.length-1
      console.log(t_c+' of '+ t_s);
      t_c++;
      crawler();
    } else {
      console.log('CRAWL COMPLETE: '+nl_c+' OF '+nl_s);
      // clear memory with setTimeout (recursion results in stack overflow)
      setTimeout( function() {
        writeDataFile(nl_c, t_c);
        isDone();
      }, 0 );
    }

  //set delay between 1200 and 3600 milliseconds per request
}, getRando(delay[0],delay[1]))
}
// ------------------------------------------------------------------------------

function nextList() {

  nl_s =  pagesIn.length-1;

  // if the page does not have url attr, mark it done
  if (!pagesIn[nl_c].hasOwnProperty('mapsTo') || pagesIn[nl_c].mapsTo.length==0) mapsToDone = true;
  if (!pagesIn[nl_c].hasOwnProperty('mapsFrom') || pagesIn[nl_c].mapsFrom.length==0) mapsFromDone = true;

  if (!mapsToDone) {
    t_s = pagesIn[nl_c].mapsTo.length-1;
    urlArr = pagesIn[nl_c].mapsTo;
  } else if (!mapsFromDone) {
    t_s = pagesIn[nl_c].mapsFrom.length-1;
    urlArr = pagesIn[nl_c].mapsFrom;
  }

  crawler(); // tester();

}

function isDone() {  // if inner loop is complete

  if (nl_c < nl_s) {  // if not end of array of obj

    // iterate nLCount, reset inner count
    t_c = 0;
    lastBatch = 0;
    console.log(nl_s);

    if (!mapsToDone) {
      console.log('MAPS TO DONE');
      mapsToDone = true;
      nextList();
    } else {
      console.log('MAPS FROM DONE');
      mapsFromDone = true;
    }

    // only iterate nl_c if it has done mapsTo and mapsFrom
    if (mapsToDone && mapsFromDone) {
      nl_c++;
      mapsToDone = false;
      mapsFromDone = false;
      writeFilenames();
      nextList();
    }

  } else {
    console.log('done');
    writeFilenames();
  }
}

nextList();
// console.log(pagesIn_2[42].mapsTo);
// console.log(dups);

//periodically update the names of files written so far
function writeFilenames() {
  fs.writeFile('data/filenames.json', JSON.stringify(filenames), function(err) {
      if (err) {throw err;}
      console.log('filenames written');
  });

  fs.writeFile('data/dups.json', JSON.stringify(dups), function(err) {
      if (err) {throw err;}
      console.log('dups written');
  });
}

// for debugging
function tester() {
  if(!dups.hasOwnProperty(urlArr[t_c])) {
    console.log('T: '+t_c);
    // console.log('URL: '+urlArr[t_c]);
    dups[urlArr[t_c]] = 1;
  } else {
    // console.log('DUP');
  }
  // check for stop condition, if not, iterate, call self
  if (t_c < t_s) {
    t_c++;
    tester();
  } else {
    // clear memory with setTimeout (recursion results in stack overflow)
    setTimeout( function() {
      isDone();
    }, 0 );
  }
}
<commit_msg>1 scraped, 16 to go<commit_after>//collect.js gets gets pages and runs them through the data pipeline

//  Output schema:
///    this page's URL                  url        str
///    the next closest root to Dada    url        str (will need to recalc this in post-processing)
///    the page's title                 words      str
///    the page's image, if it has one  url        str
///    links from this page             mapsTo     []
///    pages linking to this one        mapsFrom   []
///    metaData from wiki's data page   metaData   {}

var request = require('request');
var fs = require('fs');
var async = require('async');
var d3 = require('d3');

//local modules
var dataScrape = require('./s-wikiData');
var mF = require('./s-mapsFrom');
var mT = require('./s-mainPage');
var detect = require('./s-detect');

var pagesIn = JSON.parse(fs.readFileSync('randomSample.json'));
    // pagesIn_2 = JSON.parse(fs.readFileSync('mapsTo_Crawl.json'));

// pagesIn = pagesIn.concat(pagesIn_2);

var dups = JSON.parse(fs.readFileSync('dups.json'));

//data
var pages = [],
    lastBatch = 0;

//c = count, s = stop, d = done (boolean)
var nl_c = 1,
    nl_s = 10,
    mapsToDone = false,
    mapsFromDone = false,
    urlArr,                       // urlArr to scrape
    filenames = [],               // store filenames
    t_c = 0,                      // inner counter
    t_s = 10,                     // inner stop point (init value is random)
    delay = [1200,3600];          // delay for timeout

// test URLs - 'Francis_Picabia' - 'Ann%C3%A9es_folles' - 'Dada'

var exceptions = [
  'wikisource.org',
  '.jpg',
  '.png',
  '.gif',
  'Book:'
]

var fullSkip = [
  'wikipedia',      // no foriegn pages (not in scope)
  'wiktionary.org', // no wiktionary pages
  'wikiquote',      // no wikiquote pages
  '_talk:',         // no talk pages
  'Draft:'
]

// check for exceptions
function skip(link, exc) {
  var fact = false;
  for (var c in exc) {
    if (link.includes(exc[c])) {
      fact = true;
      break;
    }
  }
  return fact;
}

function getRando(min, max) {
  return Math.floor(Math.random() * (max - min) + min);
}

function writeDataFile(location, counter) {
  //counter++;
  if (counter>=t_s || counter%250==0) { //if last loop or if counter is divisible by 250, write the file

    var maps = function() { if (mapsToDone) { return 'mapsFrom'; } else { return 'mapsTo'; } }
    var filename = 'data/'+maps()+'-index'+location+'-batch'+lastBatch+'-'+counter+'.json';
    fs.writeFile(filename, JSON.stringify(pages), function(err) {
        if (err) {throw err;}
        console.log(filename+' written');
        filenames.push(filename);
        lastBatch = counter;
        pages = [];
    });

  }
}

function crawler() {           //  create a loop function
   setTimeout(function () {    //  call a 3s setTimeout when the loop is called

        // check for already scraped urls
        if(!dups.hasOwnProperty(urlArr[t_c])) {

          var page = new Object;
          page.distance = 2;
          page.root = pagesIn[nl_c].url;
          page.url =  urlArr[t_c];        // testURL_1;
          dups[urlArr[t_c]] = 1;          // add to dups
          delay = [1200,3600];

          var url = 'https://en.wikipedia.org/wiki/'+page.url;
          var mapsFromURL = 'https://en.wikipedia.org/w/index.php?title=Special:WhatLinksHere/'+page.url+'&limit=3000';

          //check for fullSkip (pages not scraping) pages
          if (!skip(page.url, fullSkip)) {

          // collect links pointing at this page
          request(mapsFromURL, function(err, resp, body) {
            if (err) {throw err;}
              console.log('scraping mapsFrom '+mapsFromURL);
              page.mapsFrom = mF.scrape(body);
             if (!skip(page.url, exceptions)) {

              // collect links pointing outwards from the page
              request(url, function(err, resp, body) {
                 if (err) {throw err;}
                  console.log('scraping mainPage '+url);
                  var s = mT.scrape(body, url);
                  page.mapsTo = s.mapsTo;
                  page.wikiData = s.wikiData;
                  page.image = s.image;
                  page.title = s.title;

                 if (page.wikiData!=undefined) {
                   // collect wikiData (categorical info)
                   request(page.wikiData, function(err, resp, body) {
                      if (err) {throw err;}
                       console.log('scraping wikiData '+page.wikiData);
                       page.metaData = dataScrape.scrape(body);
                       pages.push(page);
                       writeDataFile(nl_c, t_c);
                   });
                 } else {
                   // case no wikiData
                   page.metaData = null;
                   pages.push(page);
                   writeDataFile(nl_c, t_c);
                 }
              }); // end mainPage request
            } else {
              // some page types don't have link info, push as-is
              pages.push(page);
              writeDataFile(nl_c, t_c);
            }
          });
        } else {
          page.noScrape = 1;
          pages.push(page);
          console.log('-NO SCRAPE-');
          writeDataFile(nl_c, t_c);
        } // end fullSkip conditional
      } else {
        // track url distribution
        dups[urlArr[t_c]]++;
        // no delay on dups
        delay = [0,0];
      } // end dups conditional

    // iterator
    if (t_c < t_s) { //pagesIn[pgI].mapsTo.length-1
      console.log(t_c+' of '+ t_s);
      t_c++;
      crawler();
    } else {
      console.log('CRAWL COMPLETE: '+nl_c+' OF '+nl_s);
      // clear memory with setTimeout (recursion results in stack overflow)
      setTimeout( function() {
        writeDataFile(nl_c, t_c);
        isDone();
      }, 0 );
    }

  //set delay between 1200 and 3600 milliseconds per request
}, getRando(delay[0],delay[1]))
}
// ------------------------------------------------------------------------------

function nextList() {

  nl_s =  pagesIn.length-1;

  // if the page does not have url attr, mark it done
  if (!pagesIn[nl_c].hasOwnProperty('mapsTo') || pagesIn[nl_c].mapsTo.length==0) mapsToDone = true;
  if (!pagesIn[nl_c].hasOwnProperty('mapsFrom') || pagesIn[nl_c].mapsFrom.length==0) mapsFromDone = true;

  if (!mapsToDone) {
    t_s = pagesIn[nl_c].mapsTo.length-1;
    urlArr = pagesIn[nl_c].mapsTo;
  } else if (!mapsFromDone) {
    t_s = pagesIn[nl_c].mapsFrom.length-1;
    urlArr = pagesIn[nl_c].mapsFrom;
  }

  crawler(); // tester();

}

function isDone() {  // if inner loop is complete

  if (nl_c < nl_s) {  // if not end of array of obj

    // iterate nLCount, reset inner count
    t_c = 0;
    lastBatch = 0;
    console.log(nl_s);

    if (!mapsToDone) {
      console.log('MAPS TO DONE');
      mapsToDone = true;
      nextList();
    } else {
      console.log('MAPS FROM DONE');
      mapsFromDone = true;
    }

    // only iterate nl_c if it has done mapsTo and mapsFrom
    if (mapsToDone && mapsFromDone) {
      nl_c++;
      mapsToDone = false;
      mapsFromDone = false;
      writeFilenames();
      nextList();
    }

  } else {
    console.log('done');
    writeFilenames();
  }
}

nextList();
// console.log(pagesIn_2[42].mapsTo);
// console.log(dups);

//periodically update the names of files written so far
function writeFilenames() {
  fs.writeFile('data/filenames.json', JSON.stringify(filenames), function(err) {
      if (err) {throw err;}
      console.log('filenames written');
  });

  fs.writeFile('data/dups.json', JSON.stringify(dups), function(err) {
      if (err) {throw err;}
      console.log('dups written');
  });
}

// for debugging
function tester() {
  if(!dups.hasOwnProperty(urlArr[t_c])) {
    console.log('T: '+t_c);
    // console.log('URL: '+urlArr[t_c]);
    dups[urlArr[t_c]] = 1;
  } else {
    // console.log('DUP');
  }
  // check for stop condition, if not, iterate, call self
  if (t_c < t_s) {
    t_c++;
    tester();
  } else {
    // clear memory with setTimeout (recursion results in stack overflow)
    setTimeout( function() {
      isDone();
    }, 0 );
  }
}
<|endoftext|>