<commit_before>var db = require('../modules/database');
var steam_fetch = require('../modules/steam');
var Cache = require('../modules/cache');
var Q = require('q');

// Collections
var Games = db.collection('games');
var Achievements = db.collection('achievements_index');
var Categories = db.collection('category_types');
var CategoriesIndex = db.collection('categories_index');
var DevelopersIndex = db.collection('developers_index');
var Genres = db.collection('genres_types');
var GenresIndex = db.collection('genres_index');
var DemosIndex = db.collection('demos_index');
var LanguagesIndex = db.collection('languages_index');
var MetacriticIndex = db.collection('metacritic_index');
var PlatformsIndex = db.collection('platforms_index');
var PublishersIndex = db.collection('publishers_index');
var RecommendationsIndex = db.collection('recommendations_index');

/**
 * Add game to the cache
 * @param id
 * @param game
 */
function addToCache(id,game){
    game.name = escape(game.name);
    game.detailed_description = escape(game.detailed_description);
    if(game.legal_notice){
        game.legal_notice = escape(game.legal_notice);
    }
    Cache.put('app-'+id,game,7200);
}

/**
 * Return in the same format that steam returns {<app_id>: { data: <game> }}
 * @param id
 * @param data
 * @returns {{}}
 * @param escaped
 */
function responseFormat(id,data,escaped){
    var response = {};
    if(escaped){
        data.name = unescape(data.name);
        data.detailed_description = unescape(data.detailed_description);
        if(data.legal_notice){
            data.legal_notice = unescape(data.legal_notice);
        }
    }
    response[id] = {data: data};
    return response;
}

/**
 * Fetches a given game from the ID, first tries to fetch from local DB, otherwise fetches from Steam API and adds to DB
 * @param id
 * @param callback
 */
exports.getGameById = function(id,callback){
    Cache.get('app-'+id, function (error, data) {
        if(!data || error){
            Games.findOne({
                steam_appid: id
            },function(err, data){
                if(err || data == null){
                    steam_fetch('appdetails?appids=' + id,function(data){
                        var game = JSON.parse(data);
                        if(game){
                            game = game[id].data;
                            game.steam_appid = parseInt(game.steam_appid,10);
                            indexGame(id,game);
                            Games.save(game);
                            addToCache(id,game);
                        }
                        callback(data);
                    });
                } else {
                    addToCache(id,data);
                    callback(responseFormat(id,data,false));
                }
            });
        } else {
            callback(responseFormat(id,data,true));
        }
    });
};

/**
 * Get a game by query
 * @param params {{}}
 * @param callback function
 */
exports.getGame = function(params,callback){
    var limit = 25;
    var query = {};

    if(params.name){
        query.name = params.name.replace(/\W/g, '');
    }

    if(params.genre){
        query.genre = '';
    }

    // Set new limit if it's a number
    if(params.limit){
        params.limit = parseInt(params.limit,10);
        limit = (!isNaN(params.limit))? Math.abs(params.limit) : limit;
    }

    Games.find(query,function(err, data){
        callback(err || data);
    }).limit(limit || 25);
};

/**
 * Parses information from a game to build the search indexes
 * @param id
 * @param game
 */
var indexGame = function(id,game){
    var i;
    var len;

    // Save the total achievement count for the game
    if(typeof game.achievements === 'object'){
        Achievements.save({id: id, total: game.achievements.total});
    }

    // Save if it has a demo
    if(typeof game.demos === 'object'){
        DemosIndex.save({hasDemo: id, demos: game.demos});
    }

    // Save the game categories
    if(typeof game.categories === 'object'){
        i = 0;
        len = game.categories.length;

        while(i < len){
            var category = game.categories[i];
            category.id = parseInt(category.id,10);
            updateCategoryType(category,id);
            i++;
        }
    }

    // Save the game developers
    if(typeof game.developers === 'object'){
        i = 0;
        len = game.developers.length;

        while(i < len){
            updateDevelopers(game.developers[i],id);
            i++;
        }
    }

    // Save the genres
    if(typeof game.genres === 'object'){
        i = 0;
        len = game.genres.length;

        while(i < len){
            var genre = game.genres[i];
            genre.id = parseInt(genre.id,10);
            updateGenreType(genre,id);
            i++;
        }
    }

    // Save the metacritic score
    if(typeof game.metacritic === 'object'){
        MetacriticIndex.save({id: id, score: game.metacritic.score});
    }

    // Save the platforms
    if(typeof game.platforms === 'object'){
        updatePlatforms(game.platforms,id);
    }

    // Save the publishers
    if(typeof game.publishers === 'object'){
        i = 0;
        len = game.publishers.length;

        while(i < len){
            updatePublishers(game.publishers[i],id);
            i++;
        }
    }

    // Save the recommendations
    if(typeof game.recommendations === 'object'){
        RecommendationsIndex.save({id: id, total: game.recommendations.total});
    }

    // Save the languages
    if(typeof game.supported_languages === 'object'){
        game.supported_languages.split(',').forEach(function(lang){
            updateLanguages(lang.split('<')[0],id);
        });
    }
};

/**
 * If category not found, creates category and category index, otherwise adds the game to that category's list array
 * @param category
 * @param id
 */
var updateCategoryType = function(category,id){
    Categories.findOne({id:category.id},function(err,res){
        if(err || res == null){
            // Create the category type
            category.games = [id];
            category.total = 1;
            CategoriesIndex.save(category);
        } else {
            // Append new game to the category index
            CategoriesIndex.findAndModify({
                query: {id: category.id},
                update: {
                    $addToSet: {games: id},
                    $inc: {total: 1}
                }
            });
        }
    });
};

/**
 * Creates/updates the developers with a game id array
 * @param developer
 * @param id
 */
var updateDevelopers = function(developer,id){
    DevelopersIndex.findAndModify({
        query: {name: developer},
        update: {$addToSet: {games: id}},
        upset: true
    });
};

/**
 * If genre not found, creates genre and genre index, otherwise adds the game to that genre's list array
 * @param genre
 * @param id
 */
var updateGenreType = function(genre,id){
    Genres.findOne({id:genre.id},function(err,res){
        if(err || res == null){
            // Create the genre type
            genre.games = [id];
            genre.total = 1;
            GenresIndex.save(genre);
        } else {
            // Append new game to the genre index
            GenresIndex.findAndModify({
                query: {id: genre.id},
                update: {
                    $addToSet: {games: id},
                    $inc: {total: 1}
                }
            });
        }
    });
};

/**
 * Creates/updates the platforms with a game id array, or removes the game from a platform
 * @param platforms
 * @param id
 */
var updatePlatforms = function(platforms,id){
    for(var platform in platforms){
        var available = platforms[platform];
        var action = available ? {$addToSet: {games: id}} : {$pull: {games: id}};

        PlatformsIndex.findAndModify({
            query: {name: platform},
            update: action,
            upset: true
        });
    }
};

/**
 * Creates/updates the publishers with a game id array
 * @param publisher
 * @param id
 */
var updatePublishers = function(publisher,id){
    PublishersIndex.findAndModify({
        query: {name: publisher},
        update: {$addToSet: {games: id}},
        upset: true
    });
};

/**
 * If language not found, creates language and language index, otherwise adds the game to that language's list array
 * @param language
 * @param id
 */
var updateLanguages = function(language,id){
    LanguagesIndex.findAndModify({
        query: {name: language},
        update: {$addToSet: {games: id}},
        upset: true
    });
};<commit_msg>Forgot to change the collections for genres/categories find<commit_after>var db = require('../modules/database');
var steam_fetch = require('../modules/steam');
var Cache = require('../modules/cache');
var Q = require('q');

// Collections
var Games = db.collection('games');
var Achievements = db.collection('achievements_index');
var CategoriesIndex = db.collection('categories_index');
var DevelopersIndex = db.collection('developers_index');
var GenresIndex = db.collection('genres_index');
var DemosIndex = db.collection('demos_index');
var LanguagesIndex = db.collection('languages_index');
var MetacriticIndex = db.collection('metacritic_index');
var PlatformsIndex = db.collection('platforms_index');
var PublishersIndex = db.collection('publishers_index');
var RecommendationsIndex = db.collection('recommendations_index');

/**
 * Add game to the cache
 * @param id
 * @param game
 */
function addToCache(id,game){
    game.name = escape(game.name);
    game.detailed_description = escape(game.detailed_description);
    if(game.legal_notice){
        game.legal_notice = escape(game.legal_notice);
    }
    Cache.put('app-'+id,game,7200);
}

/**
 * Return in the same format that steam returns {<app_id>: { data: <game> }}
 * @param id
 * @param data
 * @returns {{}}
 * @param escaped
 */
function responseFormat(id,data,escaped){
    var response = {};
    if(escaped){
        data.name = unescape(data.name);
        data.detailed_description = unescape(data.detailed_description);
        if(data.legal_notice){
            data.legal_notice = unescape(data.legal_notice);
        }
    }
    response[id] = {data: data};
    return response;
}

/**
 * Fetches a given game from the ID, first tries to fetch from local DB, otherwise fetches from Steam API and adds to DB
 * @param id
 * @param callback
 */
exports.getGameById = function(id,callback){
    Cache.get('app-'+id, function (error, data) {
        if(!data || error){
            Games.findOne({
                steam_appid: id
            },function(err, data){
                if(err || data == null){
                    steam_fetch('appdetails?appids=' + id,function(data){
                        var game = JSON.parse(data);
                        if(game){
                            game = game[id].data;
                            game.steam_appid = parseInt(game.steam_appid,10);
                            indexGame(id,game);
                            Games.save(game);
                            addToCache(id,game);
                        }
                        callback(data);
                    });
                } else {
                    addToCache(id,data);
                    callback(responseFormat(id,data,false));
                }
            });
        } else {
            callback(responseFormat(id,data,true));
        }
    });
};

/**
 * Get a game by query
 * @param params {{}}
 * @param callback function
 */
exports.getGame = function(params,callback){
    var limit = 25;
    var query = {};

    if(params.name){
        query.name = params.name.replace(/\W/g, '');
    }

    if(params.genre){
        query.genre = '';
        CategoriesIndex.find({id:params.genre.id});
    }

    // Set new limit if it's a number
    if(params.limit){
        params.limit = parseInt(params.limit,10);
        limit = (!isNaN(params.limit))? Math.abs(params.limit) : limit;
    }

    Games.find(query,function(err, data){
        callback(err || data);
    }).limit(limit || 25);
};

/**
 * Parses information from a game to build the search indexes
 * @param id
 * @param game
 */
var indexGame = function(id,game){
    var i;
    var len;

    // Save the total achievement count for the game
    if(typeof game.achievements === 'object'){
        Achievements.save({id: id, total: game.achievements.total});
    }

    // Save if it has a demo
    if(typeof game.demos === 'object'){
        DemosIndex.save({hasDemo: id, demos: game.demos});
    }

    // Save the game categories
    if(typeof game.categories === 'object'){
        i = 0;
        len = game.categories.length;

        while(i < len){
            var category = game.categories[i];
            category.id = parseInt(category.id,10);
            updateCategoryType(category,id);
            i++;
        }
    }

    // Save the game developers
    if(typeof game.developers === 'object'){
        i = 0;
        len = game.developers.length;

        while(i < len){
            updateDevelopers(game.developers[i],id);
            i++;
        }
    }

    // Save the genres
    if(typeof game.genres === 'object'){
        i = 0;
        len = game.genres.length;

        while(i < len){
            var genre = game.genres[i];
            genre.id = parseInt(genre.id,10);
            updateGenreType(genre,id);
            i++;
        }
    }

    // Save the metacritic score
    if(typeof game.metacritic === 'object'){
        MetacriticIndex.save({id: id, score: game.metacritic.score});
    }

    // Save the platforms
    if(typeof game.platforms === 'object'){
        updatePlatforms(game.platforms,id);
    }

    // Save the publishers
    if(typeof game.publishers === 'object'){
        i = 0;
        len = game.publishers.length;

        while(i < len){
            updatePublishers(game.publishers[i],id);
            i++;
        }
    }

    // Save the recommendations
    if(typeof game.recommendations === 'object'){
        RecommendationsIndex.save({id: id, total: game.recommendations.total});
    }

    // Save the languages
    if(typeof game.supported_languages === 'object'){
        game.supported_languages.split(',').forEach(function(lang){
            updateLanguages(lang.split('<')[0],id);
        });
    }
};

/**
 * If category not found, creates category and category index, otherwise adds the game to that category's list array
 * @param category
 * @param id
 */
var updateCategoryType = function(category,id){
    CategoriesIndex.findOne({id:category.id},function(err,res){
        if(err || res == null){
            // Create the category type
            category.games = [id];
            category.total = 1;
            CategoriesIndex.save(category);
        } else {
            // Append new game to the category index
            CategoriesIndex.findAndModify({
                query: {id: category.id},
                update: {
                    $addToSet: {games: id},
                    $inc: {total: 1}
                }
            });
        }
    });
};

/**
 * Creates/updates the developers with a game id array
 * @param developer
 * @param id
 */
var updateDevelopers = function(developer,id){
    DevelopersIndex.findAndModify({
        query: {name: developer},
        update: {$addToSet: {games: id}},
        upset: true
    });
};

/**
 * If genre not found, creates genre and genre index, otherwise adds the game to that genre's list array
 * @param genre
 * @param id
 */
var updateGenreType = function(genre,id){
    GenresIndex.findOne({id:genre.id},function(err,res){
        if(err || res == null){
            // Create the genre type
            genre.games = [id];
            genre.total = 1;
            GenresIndex.save(genre);
        } else {
            // Append new game to the genre index
            GenresIndex.findAndModify({
                query: {id: genre.id},
                update: {
                    $addToSet: {games: id},
                    $inc: {total: 1}
                }
            });
        }
    });
};

/**
 * Creates/updates the platforms with a game id array, or removes the game from a platform
 * @param platforms
 * @param id
 */
var updatePlatforms = function(platforms,id){
    for(var platform in platforms){
        var available = platforms[platform];
        var action = available ? {$addToSet: {games: id}} : {$pull: {games: id}};

        PlatformsIndex.findAndModify({
            query: {name: platform},
            update: action,
            upset: true
        });
    }
};

/**
 * Creates/updates the publishers with a game id array
 * @param publisher
 * @param id
 */
var updatePublishers = function(publisher,id){
    PublishersIndex.findAndModify({
        query: {name: publisher},
        update: {$addToSet: {games: id}},
        upset: true
    });
};

/**
 * If language not found, creates language and language index, otherwise adds the game to that language's list array
 * @param language
 * @param id
 */
var updateLanguages = function(language,id){
    LanguagesIndex.findAndModify({
        query: {name: language},
        update: {$addToSet: {games: id}},
        upset: true
    });
};<|endoftext|>


<commit_before>
/*!
 * Module dependencies.
 */

var request = require('request');
var battleNetService = require('../services/battleNetService.js');

mapCharacterData = function (data) {
  if(typeof data.id === 'undefined') return data;
  var res = {
    id: data.id,
    name: data.name,
    class: data.class,
    level: data.level,
    paragonLevel: data.paragonLevel,
    skills: data.skills,
    items: {
      Head: data.items.head,
      Neck: data.items.neck,
      Shoulders: data.items.shoulders,
      Torso: data.items.torso,
      Bracers: data.items.bracers,
      Hands: data.items.hands,
      LeftFinger: data.items.leftFinger,
      RightFinger: data.items.rightFinger,
      Waist: data.items.waist,
      Legs: data.items.legs,
      Feet: data.items.feet,
      MainHand: data.items.mainHand,
      OffHand: data.items.offHand
    },
    stats: {
      life: data.stats.life,
      damage: data.stats.damage.toFixed(0),
      toughness: data.stats.toughness,
      healing: data.stats.healing,
      attackSpeed: data.stats.attackSpeed.toFixed(2),
      armor: data.stats.armor,
      strength: data.stats.strength,
      dexterity: data.stats.dexterity,
      vitality: data.stats.vitality,
      intelligence: data.stats.intelligence,
      lifeOnHit: data.stats.lifeOnHit
    },
    kills: data.kills
  };
  return res;
};

exports.index = function (req, res) {
  res.render('home/index', {
    title: 'Character Differ'
  });
};

exports.start = function (req, res) {
  res.render('home/start', {
    title: 'Select a character to begin'
  });
};

exports.compare = function (req, res) {
  var context = {
    title: 'Compare ',
    characterA: '',
    characterB: ''
  };
  battleNetService.getCharacter(req.params.region1, req.params.battletag1, req.params.id1, function(err, response){
    var charA = {
      layout: false,
      cdata: mapCharacterData(response)
    };
    req.app.render('partials/character-info', charA, function(err, html){
      if(!err){
        context.characterA = html;
        context.title += charA.cdata.name + ' ';
      }
    });
    battleNetService.getCharacter(req.params.region2, req.params.battletag2, req.params.id2, function(err, response){
      var charB = {
        layout: false,
        cdata: mapCharacterData(response)
      };
      req.app.render('partials/character-info', charB, function(err, html){
        if(!err){
          context.characterB = html;
          context.title += 'to ' + charB.cdata.name;
        }
        res.render('home/compare', context);
      });
    });
  });
};

exports.characterInfo = function (req, res) {
  var context = {
    layout: false,
    cdata: {}
  };
  battleNetService.getCharacter(req.params.region, req.params.battletag, req.params.id, function(err, response){
    context.cdata = mapCharacterData(response);
    res.render('partials/character-info', context);
  });
};
<commit_msg>- Fixing number format issues<commit_after>
/*!
 * Module dependencies.
 */

var request = require('request');
var battleNetService = require('../services/battleNetService.js');

mapCharacterData = function (data) {
  if(typeof data.id === 'undefined') return data;
  var res = {
    id: data.id,
    name: data.name,
    class: data.class,
    level: data.level,
    paragonLevel: data.paragonLevel,
    skills: data.skills,
    items: {
      Head: data.items.head,
      Neck: data.items.neck,
      Shoulders: data.items.shoulders,
      Torso: data.items.torso,
      Bracers: data.items.bracers,
      Hands: data.items.hands,
      LeftFinger: data.items.leftFinger,
      RightFinger: data.items.rightFinger,
      Waist: data.items.waist,
      Legs: data.items.legs,
      Feet: data.items.feet,
      MainHand: data.items.mainHand,
      OffHand: data.items.offHand
    },
    stats: {
      life: data.stats.life,
      damage: data.stats.damage.toFixed(0),
      toughness: data.stats.toughness.toFixed(0),
      healing: data.stats.healing.toFixed(0),
      attackSpeed: data.stats.attackSpeed.toFixed(2),
      armor: data.stats.armor.toFixed(0),
      strength: data.stats.strength,
      dexterity: data.stats.dexterity,
      vitality: data.stats.vitality,
      intelligence: data.stats.intelligence,
      lifeOnHit: data.stats.lifeOnHit
    },
    kills: data.kills
  };
  return res;
};

exports.index = function (req, res) {
  res.render('home/index', {
    title: 'Character Differ'
  });
};

exports.start = function (req, res) {
  res.render('home/start', {
    title: 'Select a character to begin'
  });
};

exports.compare = function (req, res) {
  var context = {
    title: 'Compare ',
    characterA: '',
    characterB: ''
  };
  battleNetService.getCharacter(req.params.region1, req.params.battletag1, req.params.id1, function(err, response){
    var charA = {
      layout: false,
      cdata: mapCharacterData(response)
    };
    req.app.render('partials/character-info', charA, function(err, html){
      if(!err){
        context.characterA = html;
        context.title += charA.cdata.name + ' ';
      }
    });
    battleNetService.getCharacter(req.params.region2, req.params.battletag2, req.params.id2, function(err, response){
      var charB = {
        layout: false,
        cdata: mapCharacterData(response)
      };
      req.app.render('partials/character-info', charB, function(err, html){
        if(!err){
          context.characterB = html;
          context.title += 'to ' + charB.cdata.name;
        }
        res.render('home/compare', context);
      });
    });
  });
};

exports.characterInfo = function (req, res) {
  var context = {
    layout: false,
    cdata: {}
  };
  battleNetService.getCharacter(req.params.region, req.params.battletag, req.params.id, function(err, response){
    context.cdata = mapCharacterData(response);
    res.render('partials/character-info', context);
  });
};
<|endoftext|>


<commit_before>import Ember from "ember";

export default Ember.Controller.extend({
    session: Ember.inject.service(),
    storage: Ember.inject.service(),

    reload_status: null,

    points_text: Ember.computed("model.max_score", function(){
        var points = this.get("model.max_score");
        if (points === 1) { return "bod"; }
        else if ((points === 2) || (points === 3) || (points === 4)) { return "body"; }
        else { return "bodů"; }
    }),

    // Reload task when deployed in another browser window.
    taskToReload: function() {
        var task_id = this.get("storage.taskToReload");
        if (task_id === this.get("model.id")) { this.send("updateTask"); }
    }.observes("storage.reloadTask"),

    actions: {
        // Aktualizovat ulohu, detaily a vsechny moduly.
        updateTask: function() {
            var self = this;
            this.set("reload_status", "Aktualizuji...");

            this.get("model").reload().then(function(task) {
                task.get("details").then(function(details) {
                    details.reload().then(function(details) {
                        details.get("modules").forEach(function(module) {
                            module.reload();
                        });
                        self.set("reload_status", "Aktualizováno
"+(new Date()).toLocaleFormat('%H:%M:%S'));
                        MathJax.Hub.Queue(["Typeset", MathJax.Hub]);
                    });

                });
            });
       },

        hideUpdate: function() {
            this.set("reload_status", null);
        },
    },

    init: function() {
        this.set("storage.reloadTask", false);
    }
});
<commit_msg>fixing js errror (depredicated)<commit_after>import Ember from "ember";

export default Ember.Controller.extend({
    session: Ember.inject.service(),
    storage: Ember.inject.service(),

    reload_status: null,

    points_text: Ember.computed("model.max_score", function(){
        var points = this.get("model.max_score");
        if (points === 1) { return "bod"; }
        else if ((points === 2) || (points === 3) || (points === 4)) { return "body"; }
        else { return "bodů"; }
    }),

    // Reload task when deployed in another browser window.
    taskToReload: function() {
        var task_id = this.get("storage.taskToReload");
        if (task_id === this.get("model.id")) { this.send("updateTask"); }
    }.observes("storage.reloadTask"),

    actions: {
        // Aktualizovat ulohu, detaily a vsechny moduly.
        updateTask: function() {
            var self = this;
            this.set("reload_status", "Aktualizuji...");

            this.get("model").reload().then(function(task) {
                task.get("details").then(function(details) {
                    details.reload().then(function(details) {
                        details.get("modules").forEach(function(module) {
                            module.reload();
                        });
                        self.set("reload_status", "Aktualizováno
"+(new Date()).toLocaleTimeString("cs"));
                        MathJax.Hub.Queue(["Typeset", MathJax.Hub]);
                    });

                });
            });
       },

        hideUpdate: function() {
            this.set("reload_status", null);
        },
    },

    init: function() {
        this.set("storage.reloadTask", false);
    }
});
<|endoftext|>


<commit_before>var mongoose = require('mongoose'),
    User = mongoose.model('User'),
    Account = mongoose.model('Account'),
    Assignment = mongoose.model('Assignment')

exports.try = function(req, res) {
  Assignment
      .find({
      })
      .exec(function(err, assignmentResult) {
        if(err) return next(err);

        var ID = [];
        var Numbers = {};

        var both, one, neither;
        both = one = neither = 0;

        for(assignment in assignmentResult) {
          if(assignmentResult[assignment].assignmentNumber == "" && assignmentResult[assignment].subAssignment == "")
            both++;
          else if(assignmentResult[assignment].assignmentNumber == "" || assignmentResult[assignment].subAssignment == "") {
            one++;
          } else
            neither++;

          ID.push(assignmentResult[assignment].assignmentID)

          if(Numbers.hasOwnProperty(assignmentResult[assignment].assignmentNumber)) {
            Numbers[assignmentResult[assignment].assignmentNumber] += 1;
          } else {
            Numbers[assignmentResult[assignment].assignmentNumber] = 0;
          }
        }

        console.log("Unique IDs " + ID.length)
        // for(i in ID) {
        //   console.log(ID[i])
        // }

        console.log("Groups of Assignment IDS ")
        for(var i in Numbers) {
          console.log(i, Numbers[i]);
        }

        console.log("--");
        console.log("With both: ", both)
        console.log("With one: ", one)
        console.log("With neither: ", neither)

      })
}

exports.testing = function(req, res, next) {

  Assignment
      .find({
        "assignmentNumber": {$exists: false},
        "subAssignment": {$exists: false},
        "assignmentID": /./
      })
      .limit(100)
      .exec(function(err, assignmentResult) {
        if(err) return next(err);

        return next(assignmentResult.length);

        var numUpdated = 0;
        var numDeleted = 0;
        var numTotal = assignmentResult.length;
        var numToModify = 0;

        for(assignment in assignmentResult) {
          // if(assignmentResult[assignment].assignmentNumber == "" || assignmentResult[assignment].subAssignment == "") {
            numToModify++;
            var assignmentID = assignmentResult[assignment].assignmentID;
            var assignmentRaw = assignmentID.split(".");
            var assignmentNumber = assignmentRaw[0];
            var subAssignment = assignmentRaw[1] || "";

              // Update assignments, deleting any with erroneous assignmentID

              if(subAssignment.length > 2) {
                 //remove all assignments with ridiculous decimal subAssignment
                Assignment
                  .remove({
                    "assignmentID": assignmentID
                  })
                  .exec(function(err, result){
                      if(err) return next(err)
                      numDeleted++;
                  })
                } else {

                //Update assignments to all use assignmentNumber and subAssignment number! (Won't delete anything)
                Assignment
                  .update(
                      {
                        "assignmentID": assignmentID
                      },
                      {
                        $set: {"assignmentNumber": assignmentNumber, "subAssignment": subAssignment}
                      }
                    ).exec(function(err, result) {
                      if(err) return next(err)
                      //console.log("updated assignment ", assignmentID)
                      numUpdated++;

                    })

                }
        }

        return next("Started with " + numTotal + ", Num to modify: " + numToModify + ", Num deleted " + numDeleted + ", Number updated " + numUpdated)
      });

}
<commit_msg>attempting to test updates<commit_after>var mongoose = require('mongoose'),
    User = mongoose.model('User'),
    Account = mongoose.model('Account'),
    Assignment = mongoose.model('Assignment')

exports.try = function(req, res) {
  Assignment
      .find({
      })
      .exec(function(err, assignmentResult) {
        if(err) return next(err);

        var ID = [];
        var Numbers = {};

        var both, one, neither;
        both = one = neither = 0;

        for(assignment in assignmentResult) {
          if(assignmentResult[assignment].assignmentNumber == "" && assignmentResult[assignment].subAssignment == "")
            both++;
          else if(assignmentResult[assignment].assignmentNumber == "" || assignmentResult[assignment].subAssignment == "") {
            one++;
          } else
            neither++;

          ID.push(assignmentResult[assignment].assignmentID)

          if(Numbers.hasOwnProperty(assignmentResult[assignment].assignmentNumber)) {
            Numbers[assignmentResult[assignment].assignmentNumber] += 1;
          } else {
            Numbers[assignmentResult[assignment].assignmentNumber] = 0;
          }
        }

        console.log("Unique IDs " + ID.length)
        // for(i in ID) {
        //   console.log(ID[i])
        // }

        console.log("Groups of Assignment IDS ")
        for(var i in Numbers) {
          console.log(i, Numbers[i]);
        }

        console.log("--");
        console.log("With both: ", both)
        console.log("With one: ", one)
        console.log("With neither: ", neither)

      })
}

exports.testing = function(req, res, next) {

  Assignment
      .find({
        "assignmentNumber": {$exists: false},
        "subAssignment": {$exists: false},
        "assignmentID": /./
      })
      .limit(100)
      .exec(function(err, assignmentResult) {
        if(err) return next(err);

        //return next(assignmentResult.length);

        var numUpdated = 0;
        var numDeleted = 0;
        var numTotal = assignmentResult.length;
        var numToModify = 0;

        for(assignment in assignmentResult) {
          // if(assignmentResult[assignment].assignmentNumber == "" || assignmentResult[assignment].subAssignment == "") {
            numToModify++;
            var assignmentID = assignmentResult[assignment].assignmentID;
            var assignmentRaw = assignmentID.split(".");
            var assignmentNumber = assignmentRaw[0];
            var subAssignment = assignmentRaw[1] || "";

              // Update assignments, deleting any with erroneous assignmentID

              if(subAssignment.length > 2) {
                 //remove all assignments with ridiculous decimal subAssignment
                Assignment
                  .remove({
                    "assignmentID": assignmentID
                  })
                  .exec(function(err, result){
                      if(err) return next(err)
                      numDeleted++;
                  })
                } else {

                //Update assignments to all use assignmentNumber and subAssignment number! (Won't delete anything)
                Assignment
                  .update(
                      {
                        "assignmentID": assignmentID
                      },
                      {
                        $set: {"assignmentNumber": assignmentNumber, "subAssignment": subAssignment}
                      }
                    ).exec(function(err, result) {
                      if(err) return next(err)
                      //console.log("updated assignment ", assignmentID)
                      numUpdated++;

                    })

                }
        }

        return next("Started with " + numTotal + ", Num to modify: " + numToModify + ", Num deleted " + numDeleted + ", Number updated " + numUpdated)
      });

}
<|endoftext|>


<commit_before>// Backbone.Validation v0.1.1
//
// Copyright (C)2011 Thomas Pedersen
// Distributed under MIT License
//
// Documentation and full license availabe at:
// http://github.com/thedersen/backbone.validation
// ----------------------------
// Backbone.Validation
// ----------------------------
Backbone.Validation = (function(Backbone, _) {
	var getValidators = function(model, attr) {
		var validation = model.validation[attr],
		    validators = [];

		if (_.isFunction(validation)) {
			return validation;
		} else {
			for (attr in validation) {
				if (attr !== 'msg' && validation.hasOwnProperty(attr)) {
					validators.push({
						fn: Backbone.Validation.validators[attr],
						val: validation[attr],
						msg: validation['msg']
					});
				}
			}
			return validators;
		}
	};

	var validateAttr = function(model, attr, value) {
		var validators = getValidators(model, attr),
		    error = '',
		    validator,
		    result;

		if (_.isFunction(validators)) {
			return validators(value);
		} else {
			for (var i = 0; i < validators.length; i++) {
				validator = validators[i];
				result = validator.fn(value, attr, validator.msg, validator.val);
				if (result) {
					error += result;
				}
			};
			return error;
		}
	};

	return {
		version: '0.1.1',

		bind: function(view, options) {
			options = options || {};
			var model = view.model,
			    validFn = options.valid || Backbone.Validation.callbacks.valid,
				invalidFn = options.invalid || Backbone.Validation.callbacks.invalid;

			model.validate = function(attrs) {
				var invalidAttr = false,
				    isValid = true,
				    error;

				for (changedAttr in attrs) {
					if (changedAttr === 'isValid') {
						return false;
					}

					error = validateAttr(model, changedAttr, attrs[changedAttr]);
					if (error) {
						invalidAttr = true;
						invalidFn(view, changedAttr, error);
					} else {
						validFn(view, changedAttr);
					}
				}

				if (invalidAttr) {
					model.set({
						isValid: false
					});
				} else {
					for (attr in model.validation) {
						if (_.isUndefined(attrs[attr]) && validateAttr(model, attr, model.get(attr))) {
							isValid = false;
							break;
						}
					}
					model.set({
						isValid: isValid
					});
				}

				return invalidAttr;
			};
		},

		unbind: function(view) {
			view.model.validate = undefined;
		}
	};
} (Backbone, _));

Backbone.Validation.callbacks = {
	valid: function(view, attr) {
		view.$('#' + attr).removeClass('invalid');
		view.$('#' + attr).removeAttr('data-error');
	},

	invalid: function(view, attr, error) {
		view.$('#' + attr).addClass('invalid');
		view.$('#' + attr).attr('data-error', error);
	}
};

Backbone.Validation.patterns = {
	number: /^\d$/,
	email: /^([a-zA-Z0-9_\.\-])+\@(([a-zA-Z0-9\-])+\.)+([a-zA-Z0-9]{2,4})+$/,
	url: /^(https?|ftp):\/\/(((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:)*@)?(((\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5]))|((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?)(:\d*)?)(\/((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)+(\/(([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)*)*)?)?(\?((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|[\uE000-\uF8FF]|\/|\?)*)?(\#((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|\/|\?)*)?$/i
};

Backbone.Validation.validators = (function(_, $) {
	return {
		required: function(value, attr, msg) {
			var isEmptyString = _.isString(value) && $.trim(value) === '';
			var isFalseBoolean = _.isBoolean(value) && value === false;

			if (_.isNull(value) || _.isUndefined(value) || isEmptyString || isFalseBoolean) {
				return msg || attr + ' is required';
			}
		},
		min: function(value, attr, msg, minValue) {
			value = parseInt(value, 10);
			if (!_.isNumber(value) || value < minValue) {
				return msg || attr + ' must be larger than or equal to ' + minValue;
			}
		},
		max: function(value, attr, msg, maxValue) {
			value = parseInt(value, 10);
			if (!_.isNumber(value) || value > maxValue) {
				return msg || attr + ' must be less than or equal to ' + maxValue;
			}
		},
		minLength: function(value, attr, msg, minLength) {
			value = $.trim(value);
			if (_.isString(value) && value.length < minLength) {
				return msg || attr + ' must be longer than or equal to ' + minLength + ' characters';
			}
		},
		maxLength: function(value, attr, msg, maxLength) {
			value = $.trim(value);
			if (_.isString(value) && value.length > maxLength) {
				return msg || attr + ' must be shorter than or equal to' + maxLength + ' characters';
			}
		},
		pattern: function(value, attr, msg, pattern) {
			pattern = Backbone.Validation.patterns[pattern] || pattern;
			if (_.isString(value) && !value.match(pattern)) {
				return msg || attr + ' is not a valid ' + pattern;
			}
		}
	};
} (_, jQuery));
<commit_msg>Bumped version to 0.1.2<commit_after>// Backbone.Validation v0.1.2
//
// Copyright (C)2011 Thomas Pedersen
// Distributed under MIT License
//
// Documentation and full license availabe at:
// http://github.com/thedersen/backbone.validation
// ----------------------------
// Backbone.Validation
// ----------------------------
Backbone.Validation = (function(Backbone, _) {
	var getValidators = function(model, attr) {
		var validation = model.validation[attr],
		    validators = [];

		if (_.isFunction(validation)) {
			return validation;
		} else {
			for (attr in validation) {
				if (attr !== 'msg' && validation.hasOwnProperty(attr)) {
					validators.push({
						fn: Backbone.Validation.validators[attr],
						val: validation[attr],
						msg: validation['msg']
					});
				}
			}
			return validators;
		}
	};

	var validateAttr = function(model, attr, value) {
		var validators = getValidators(model, attr),
		    error = '',
		    validator,
		    result;

		if (_.isFunction(validators)) {
			return validators(value);
		} else {
			for (var i = 0; i < validators.length; i++) {
				validator = validators[i];
				result = validator.fn(value, attr, validator.msg, validator.val);
				if (result) {
					error += result;
				}
			};
			return error;
		}
	};

	return {
		version: '0.1.2',

		bind: function(view, options) {
			options = options || {};
			var model = view.model,
			    validFn = options.valid || Backbone.Validation.callbacks.valid,
				invalidFn = options.invalid || Backbone.Validation.callbacks.invalid;

			model.validate = function(attrs) {
				var invalidAttr = false,
				    isValid = true,
				    error;

				for (changedAttr in attrs) {
					if (changedAttr === 'isValid') {
						return false;
					}

					error = validateAttr(model, changedAttr, attrs[changedAttr]);
					if (error) {
						invalidAttr = true;
						invalidFn(view, changedAttr, error);
					} else {
						validFn(view, changedAttr);
					}
				}

				if (invalidAttr) {
					model.set({
						isValid: false
					});
				} else {
					for (attr in model.validation) {
						if (_.isUndefined(attrs[attr]) && validateAttr(model, attr, model.get(attr))) {
							isValid = false;
							break;
						}
					}
					model.set({
						isValid: isValid
					});
				}

				return invalidAttr;
			};
		},

		unbind: function(view) {
			view.model.validate = undefined;
		}
	};
} (Backbone, _));

Backbone.Validation.callbacks = {
	valid: function(view, attr) {
		view.$('#' + attr).removeClass('invalid');
		view.$('#' + attr).removeAttr('data-error');
	},

	invalid: function(view, attr, error) {
		view.$('#' + attr).addClass('invalid');
		view.$('#' + attr).attr('data-error', error);
	}
};

Backbone.Validation.patterns = {
	number: /^\d$/,
	email: /^([a-zA-Z0-9_\.\-])+\@(([a-zA-Z0-9\-])+\.)+([a-zA-Z0-9]{2,4})+$/,
	url: /^(https?|ftp):\/\/(((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:)*@)?(((\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5]))|((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?)(:\d*)?)(\/((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)+(\/(([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)*)*)?)?(\?((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|[\uE000-\uF8FF]|\/|\?)*)?(\#((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|\/|\?)*)?$/i
};

Backbone.Validation.validators = (function(_, $) {
	return {
		required: function(value, attr, msg) {
			var isEmptyString = _.isString(value) && $.trim(value) === '';
			var isFalseBoolean = _.isBoolean(value) && value === false;

			if (_.isNull(value) || _.isUndefined(value) || isEmptyString || isFalseBoolean) {
				return msg || attr + ' is required';
			}
		},
		min: function(value, attr, msg, minValue) {
			value = parseInt(value, 10);
			if (!_.isNumber(value) || value < minValue) {
				return msg || attr + ' must be larger than or equal to ' + minValue;
			}
		},
		max: function(value, attr, msg, maxValue) {
			value = parseInt(value, 10);
			if (!_.isNumber(value) || value > maxValue) {
				return msg || attr + ' must be less than or equal to ' + maxValue;
			}
		},
		minLength: function(value, attr, msg, minLength) {
			value = $.trim(value);
			if (_.isString(value) && value.length < minLength) {
				return msg || attr + ' must be longer than or equal to ' + minLength + ' characters';
			}
		},
		maxLength: function(value, attr, msg, maxLength) {
			value = $.trim(value);
			if (_.isString(value) && value.length > maxLength) {
				return msg || attr + ' must be shorter than or equal to' + maxLength + ' characters';
			}
		},
		pattern: function(value, attr, msg, pattern) {
			pattern = Backbone.Validation.patterns[pattern] || pattern;
			if (_.isString(value) && !value.match(pattern)) {
				return msg || attr + ' is not a valid ' + pattern;
			}
		}
	};
} (_, jQuery));
<|endoftext|>


<commit_before>// Backbone.Validation v0.1.3
//
// Copyright (C)2011 Thomas Pedersen
// Distributed under MIT License
//
// Documentation and full license availabe at:
// http://github.com/thedersen/backbone.validation
// ----------------------------
// Backbone.Validation
// ----------------------------
Backbone.Validation = (function(Backbone, _) {
    var getValidators = function(model, attr) {
        var validation = model.validation[attr],
            validators = [];

        if (_.isFunction(validation)) {
            return validation;
        } else if(_.isString(validation)) {
            return model[validation];
        } else {
            for (var validator in validation) {
                if (validator !== 'msg' && validation.hasOwnProperty(validator)) {
                    validators.push({
                        fn: Backbone.Validation.validators[validator],
                        val: validation[validator],
                        msg: validation.msg
                    });
                }
            }
            return validators;
        }
    };

    var validateAttr = function(model, attr, value) {
        var validators = getValidators(model, attr),
            error = '',
            validator,
            result;

        if (_.isFunction(validators)) {
            return validators.call(model, value);
        } else {
            for (var i = 0; i < validators.length; i++) {
                validator = validators[i];
                result = validator.fn(value, attr, validator.val);
                if (result) {
                    error += validator.msg || result;
                }
            };
            return error;
        }
    };

    return {
        version: '0.1.3',

        bind: function(view, options) {
            options = options || {};
            var model = view.model,
                validFn = options.valid || Backbone.Validation.callbacks.valid,
                invalidFn = options.invalid || Backbone.Validation.callbacks.invalid;

            model.validate = function(attrs) {
                var invalidAttr = false,
                    isValid = true,
                    error;

                for (var changedAttr in attrs) {
                    if (changedAttr === 'isValid') {
                        return false;
                    }

                    error = validateAttr(model, changedAttr, attrs[changedAttr]);
                    if (error) {
                        invalidAttr = true;
                        invalidFn(view, changedAttr, error);
                    } else {
                        validFn(view, changedAttr);
                    }
                }

                if (invalidAttr) {
                    model.set({
                        isValid: false
                    });
                } else {
                    for (var validatedAttr in model.validation) {
                        if (_.isUndefined(attrs[validatedAttr]) && validateAttr(model, validatedAttr, model.get(validatedAttr))) {
                            isValid = false;
                            break;
                        }
                    }
                    model.set({
                        isValid: isValid
                    });
                }

                return invalidAttr;
            };
        },

        unbind: function(view) {
            view.model.validate = undefined;
        }
    };
} (Backbone, _));

Backbone.Validation.callbacks = {
    valid: function(view, attr) {
        view.$('#' + attr).removeClass('invalid');
        view.$('#' + attr).removeAttr('data-error');
    },

    invalid: function(view, attr, error) {
        view.$('#' + attr).addClass('invalid');
        view.$('#' + attr).attr('data-error', error);
    }
};

Backbone.Validation.patterns = {
    number: /^-?\d+$/,
    email: /^([a-zA-Z0-9_\.\-])+\@(([a-zA-Z0-9\-])+\.)+([a-zA-Z0-9]{2,4})+$/,
    url: /^(https?|ftp):\/\/(((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:)*@)?(((\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5]))|((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?)(:\d*)?)(\/((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)+(\/(([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)*)*)?)?(\?((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|[\uE000-\uF8FF]|\/|\?)*)?(\#((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|\/|\?)*)?$/i
};

Backbone.Validation.validators = (function(patterns, _, $) {
    var numberPattern = patterns.number;
    var isNumber = function(value){
        return _.isNumber(value) || (_.isString(value) && value.match(numberPattern));
    };

    return {
        required: function(value, attr) {
            var isEmptyString = _.isString(value) && $.trim(value) === '';
            var isFalseBoolean = _.isBoolean(value) && value === false;

            if (_.isNull(value) || _.isUndefined(value) || isEmptyString || isFalseBoolean) {
                return attr + ' is required';
            }
        },
        min: function(value, attr, minValue) {
            if (!isNumber(value) || value < minValue) {
                return attr + ' must be larger than or equal to ' + minValue;
            }
        },
        max: function(value, attr, maxValue) {
            if (!isNumber(value) || value > maxValue) {
                return attr + ' must be less than or equal to ' + maxValue;
            }
        },
        length: function(value, attr, length) {
          value = $.trim(value);
            if (_.isString(value) && value.length !== length) {
                return attr + ' must have exact ' + length + ' characters';
            }
        },
        minLength: function(value, attr, minLength) {
            value = $.trim(value);
            if (_.isString(value) && value.length < minLength) {
                return attr + ' must be longer than or equal to ' + minLength + ' characters';
            }
        },
        maxLength: function(value, attr, maxLength) {
            value = $.trim(value);
            if (_.isString(value) && value.length > maxLength) {
                return attr + ' must be shorter than or equal to' + maxLength + ' characters';
            }
        },
        pattern: function(value, attr, pattern) {
            pattern = patterns[pattern] || pattern;
            if (_.isString(value) && !value.match(pattern)) {
                return attr + ' is not a valid ' + pattern;
            }
        }
    };
} (Backbone.Validation.patterns, _, jQuery));
<commit_msg>Removed dependency to jQuery in the Backbone.Validation.validators function<commit_after>// Backbone.Validation v0.1.3
//
// Copyright (C)2011 Thomas Pedersen
// Distributed under MIT License
//
// Documentation and full license availabe at:
// http://github.com/thedersen/backbone.validation
// ----------------------------
// Backbone.Validation
// ----------------------------
Backbone.Validation = (function(Backbone, _) {
    var getValidators = function(model, attr) {
        var validation = model.validation[attr],
            validators = [];

        if (_.isFunction(validation)) {
            return validation;
        } else if(_.isString(validation)) {
            return model[validation];
        } else {
            for (var validator in validation) {
                if (validator !== 'msg' && validation.hasOwnProperty(validator)) {
                    validators.push({
                        fn: Backbone.Validation.validators[validator],
                        val: validation[validator],
                        msg: validation.msg
                    });
                }
            }
            return validators;
        }
    };

    var validateAttr = function(model, attr, value) {
        var validators = getValidators(model, attr),
            error = '',
            validator,
            result;

        if (_.isFunction(validators)) {
            return validators.call(model, value);
        } else {
            for (var i = 0; i < validators.length; i++) {
                validator = validators[i];
                result = validator.fn(value, attr, validator.val);
                if (result) {
                    error += validator.msg || result;
                }
            };
            return error;
        }
    };

    return {
        version: '0.1.3',

        bind: function(view, options) {
            options = options || {};
            var model = view.model,
                validFn = options.valid || Backbone.Validation.callbacks.valid,
                invalidFn = options.invalid || Backbone.Validation.callbacks.invalid;

            model.validate = function(attrs) {
                var invalidAttr = false,
                    isValid = true,
                    error;

                for (var changedAttr in attrs) {
                    if (changedAttr === 'isValid') {
                        return false;
                    }

                    error = validateAttr(model, changedAttr, attrs[changedAttr]);
                    if (error) {
                        invalidAttr = true;
                        invalidFn(view, changedAttr, error);
                    } else {
                        validFn(view, changedAttr);
                    }
                }

                if (invalidAttr) {
                    model.set({
                        isValid: false
                    });
                } else {
                    for (var validatedAttr in model.validation) {
                        if (_.isUndefined(attrs[validatedAttr]) && validateAttr(model, validatedAttr, model.get(validatedAttr))) {
                            isValid = false;
                            break;
                        }
                    }
                    model.set({
                        isValid: isValid
                    });
                }

                return invalidAttr;
            };
        },

        unbind: function(view) {
            view.model.validate = undefined;
        }
    };
} (Backbone, _));

Backbone.Validation.callbacks = {
    valid: function(view, attr) {
        view.$('#' + attr).removeClass('invalid');
        view.$('#' + attr).removeAttr('data-error');
    },

    invalid: function(view, attr, error) {
        view.$('#' + attr).addClass('invalid');
        view.$('#' + attr).attr('data-error', error);
    }
};

Backbone.Validation.patterns = {
    number: /^-?\d+$/,
    email: /^([a-zA-Z0-9_\.\-])+\@(([a-zA-Z0-9\-])+\.)+([a-zA-Z0-9]{2,4})+$/,
    url: /^(https?|ftp):\/\/(((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:)*@)?(((\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5]))|((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?)(:\d*)?)(\/((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)+(\/(([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)*)*)?)?(\?((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|[\uE000-\uF8FF]|\/|\?)*)?(\#((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|\/|\?)*)?$/i
};

Backbone.Validation.validators = (function(patterns, _) {
    var numberPattern = patterns.number;
    var isNumber = function(value){
        return _.isNumber(value) || (_.isString(value) && value.match(numberPattern));
    };

    var trim = String.prototype.trim ?
    		function(text) {
    			return text == null ?
    				"" :
    				String.prototype.trim.call(text);
    		} :
    		function(text) {
    		    var trimLeft = /^\s+/,
                    trimRight = /\s+$/;

    			return text == null ?
    				"" :
    				text.toString().replace(trimLeft, "").replace(trimRight, "");
    		};

    return {
        required: function(value, attr) {
            var isEmptyString = _.isString(value) && trim(value) === '';
            var isFalseBoolean = _.isBoolean(value) && value === false;

            if (_.isNull(value) || _.isUndefined(value) || isEmptyString || isFalseBoolean) {
                return attr + ' is required';
            }
        },
        min: function(value, attr, minValue) {
            if (!isNumber(value) || value < minValue) {
                return attr + ' must be larger than or equal to ' + minValue;
            }
        },
        max: function(value, attr, maxValue) {
            if (!isNumber(value) || value > maxValue) {
                return attr + ' must be less than or equal to ' + maxValue;
            }
        },
        length: function(value, attr, length) {
          value = trim(value);
            if (_.isString(value) && value.length !== length) {
                return attr + ' must have exact ' + length + ' characters';
            }
        },
        minLength: function(value, attr, minLength) {
            value = trim(value);
            if (_.isString(value) && value.length < minLength) {
                return attr + ' must be longer than or equal to ' + minLength + ' characters';
            }
        },
        maxLength: function(value, attr, maxLength) {
            value = trim(value);
            if (_.isString(value) && value.length > maxLength) {
                return attr + ' must be shorter than or equal to' + maxLength + ' characters';
            }
        },
        pattern: function(value, attr, pattern) {
            pattern = patterns[pattern] || pattern;
            if (_.isString(value) && !value.match(pattern)) {
                return attr + ' is not a valid ' + pattern;
            }
        }
    };
} (Backbone.Validation.patterns, _));
<|endoftext|>


<commit_before>"use strict";
var Settings = {
  cache: Object.create(null),
  bufferToLoad: null,
  extWhiteList: null,
  globalCommand: null,
  Init: null,
  SetIconBuffer: null,
  get: function(key, forCache) {
    if (key in this.cache) {
      return this.cache[key];
    }
    var initial = this.defaults[key];
    var value = !(key in localStorage) ? initial
        : typeof initial === "string" ? localStorage[key]
        : initial === false || initial === true ? localStorage[key] === "true"
        : JSON.parse(localStorage[key]);
    if (forCache) {
      this.cache[key] = value;
    }
    return value;
  },
  set: function(key, value) {
    var ref, initial;
    this.cache[key] = value;
    if (!(key in this.nonPersistent)) {
      initial = this.defaults[key];
      if (value === initial) {
        localStorage.removeItem(key);
        this.Sync.set(key, null);
      } else {
        localStorage[key] = typeof initial === "string" ? value : JSON.stringify(value);
        this.Sync.set(key, value);
      }
    }
    if (ref = this.updateHooks[key]) {
      ref.call(this, value, key);
    }
  },
  postUpdate: function(key, value) {
    this.updateHooks[key].call(this, value !== undefined ? value : this.get(key), key);
  },
  broadcast: function (request) {
    var ref = this.indexPorts(), tabId, frames, i;
    for (tabId in ref) {
      frames = ref[tabId];
      for (i = frames.length; 0 < --i; ) {
        frames[i].postMessage(request);
      }
    }
  },
  updateHooks: {
    __proto__: null,
    bufferToLoad: function() {
      var _i, key, ref = this.valuesToLoad, ref2;
      ref2 = this.bufferToLoad = Object.create(null);
      for (_i = ref.length; 0 <= --_i;) {
        key = ref[_i];
        ref2[key] = this.get(key);
      }
    },
    extWhiteList: function(val) {
      var arr = val.split("\n"), i, map;
      map = this.extWhiteList = Object.create(null);
      for (i = arr.length; 0 <= --i; ) {
        if ((val = arr[i]) && (val = val.trim()).length === 32) {
          map[val] = true;
        }
      }
    },
    newTabUrl: function(url) {
      url = /^\/?pages\/[a-z]+.html\b/i.test(url)
        ? chrome.runtime.getURL(url) : Utils.convertToUrl(url);
      this.set('newTabUrl_f', url);
    },
    searchEngines: function() {
      this.set("searchEngineMap", Object.create(null));
    },
    searchEngineMap: function(value) {
      Utils.parseSearchEngines("~:" + this.get("searchUrl"), value);
      var rules = Utils.parseSearchEngines(this.get("searchEngines"), value);
      this.set("searchEngineRules", rules);
    },
    searchUrl: function(str) {
      var map, obj, ind;
      if (str) {
        Utils.parseSearchEngines("~:" + str, map = this.cache.searchEngineMap);
        obj = map["~"];
        str = obj.url.replace(Utils.spacesRe, "%20");
        if (obj.name) { str += " " + obj.name; }
        if (str !== arguments[0]) {
          this.set("searchUrl", str);
          return;
        }
      } else if (str = this.get("newTabUrl_f", true)) {
        this.updateHooks.newTabUrl_f(str);
        return;
      } else {
        str = this.get("searchUrl");
        ind = str.indexOf(" ");
        if (ind > 0) { str = str.substring(0, ind); }
        this.get("searchEngineMap", true)["~"] = { url: str };
      }
      this.postUpdate("newTabUrl");
    },
    baseCss: function(css) {
      this.CONST.BaseCssLength = css.length;
      css += this.get("userDefinedCss");
      this.cache.baseCss = null;
      this.set("innerCss", css);
    },
    vimSync: function(value) {
      if (value) {
        setTimeout(alert, 17, "Warning: the current settings will be OVERRIDDEN the next time Vimium++ starts!\n"
          + 'Please back up your settings using the "Export Settings" button RIGHT NOW!');
      }
      if (value || !this.Sync.HandleStorageUpdate) { return; }
      setTimeout(function() {
        chrome.storage.onChanged.removeListener(Settings.Sync.HandleStorageUpdate);
        Settings.Sync = { set: function() {} };
      }, 100);
    },
    userDefinedCss: function(css) {
      css = this.cache.innerCss.substring(0, this.CONST.BaseCssLength) + css;
      this.set("innerCss", css);
      this.broadcast({
        name: "insertInnerCss",
        css: this.cache.innerCss
      });
    },
    userDefinedOuterCss: function(css) {
      this.broadcast({
        name: "insertCSS",
        css: css
      });
    }
  },
  indexFrame: null,
  indexPorts: null,
  fetchFile: function(file, callback) {
    if (this.cache[file]) { return callback && callback(); }
    Utils.fetchHttpContents(this.files[file], function() {
      Settings.set(file, this.responseText);
      callback && callback();
      return;
    });
  },
  contentScripts: function(callback) {
    setTimeout(function() { callback(Settings.CONST.ContentScripts); }, 18);
    return true;
  },
  // clear localStorage & sync, if value === @defaults[key]
  // the default of any dict field must be set to null for compatibility with @Sync.set
  defaults: {
    __proto__: null,
    deepHints: false,
    exclusionListenHash: true,
    exclusionOnlyFirstMatch: false,
    exclusionRules: [{pattern: "^https?://mail.google.com/", passKeys: ""}],
    extWhiteList: "# hdnehngglnbnehkfcidabjckinphnief",
    findModeRawQueryList: "",
    grabBackFocus: true,
    hideHud: false,
    keyboard: [500, 33],
    keyMappings: "",
    linkHintCharacters: "sadjklewcmpgh",
    localeEncoding: "gbk",
    newTabUrl: "",
    newTabUrl_f: "",
    nextPatterns: "\u4e0b\u9875,\u4e0b\u4e00\u9875,\u4e0b\u4e00\u7ae0,\u540e\u4e00\u9875"
      + ",next,more,newer,>,\u203a,\u2192,\xbb,\u226b,>>",
    previousPatterns: "\u4e0a\u9875,\u4e0a\u4e00\u9875,\u4e0a\u4e00\u7ae0,\u524d\u4e00\u9875"
      + ",prev,previous,back,older,<,\u2039,\u2190,\xab,\u226a,<<",
    regexFindMode: false,
    scrollStepSize: 100,
    searchUrl: "https://www.baidu.com/s?ie=UTF-8&wd=$s Baidu",
    searchEngines: "b|ba|baidu|Baidu: https://www.baidu.com/s?ie=UTF-8&wd=$s \u767e\u5ea6\n\
g|go|gg|google|Google: https://www.google.com/search?q=$s Google\n\
js\\:|Js: javascript:\\ $S; Javascript\n\
w|wiki:\\\n  http://www.wikipedia.org/w/index.php?search=$s Wikipedia (en-US)",
    searchEngineMap: {}, // may be modified, but this action is safe
    showActionIcon: true,
    showAdvancedCommands: false,
    showAdvancedOptions: false,
    smoothScroll: true,
    tinyMemory: false,
    userDefinedCss: "",
    userDefinedOuterCss: "",
    vimSync: false
  },
  // not set localStorage, neither sync, if key in @nonPersistent
  // not clean if exists (for simpler logic)
  nonPersistent: { __proto__: null,
    baseCss: 1, exclusionTemplate: 1, helpDialog: 1, innerCss: 1,
    searchEngineMap: 1, searchEngineRules: 1, vomnibar: 1
  },
  files: {
    __proto__: null,
    baseCss: "front/vimium.min.css",
    exclusionTemplate: "front/exclusions.html",
    helpDialog: "front/help_dialog.html",
    vomnibar: "front/vomnibar.html"
  },
  icons: {
    disabled: { "19": "icons/disabled_19.png", "38": "icons/disabled_38.png" },
    enabled: { "19": "icons/enabled_19.png", "38": "icons/enabled_38.png" },
    partial: { "19": "icons/partial_19.png", "38": "icons/partial_38.png" }
  },
  valuesToLoad: ["deepHints" //
    , "grabBackFocus", "hideHud", "keyboard" //
    , "linkHintCharacters", "nextPatterns", "previousPatterns" //
    , "scrollStepSize", "smoothScroll" //
  ],
  Sync: {
    set: function() {}
  },
  CONST: {
    ChromeInnerNewTab: "chrome-search://local-ntp/local-ntp.html", // should keep lower case
    ChromeVersion: 37, ContentScripts: null, CurrentVersion: "",
    BaseCssLength: 0,
    OnMac: false, OptionsPage: ""
  }
};

// note: if changed, ../pages/newtab.js also needs change.
Settings.defaults.newTabUrl = Settings.CONST.ChromeInnerNewTab;
Settings.CONST.ChromeVersion = +navigator.appVersion.match(/Chrom(?:e|ium)\/(\d+\.\d+)/)[1];

setTimeout(function() {
  chrome.runtime.getPlatformInfo(function(info) {
    Settings.CONST.OnMac = info.os === "mac";
  });

  var ref, origin = location.origin, prefix = origin + "/",
  func = function(path) {
    return (path.charCodeAt(0) === 47 ? origin : prefix) + path;
  };
  ref = chrome.runtime.getManifest();
  Settings.CONST.CurrentVersion = ref.version;
  Settings.CONST.OptionsPage = func(ref.options_page);
  ref = ref.content_scripts[0].js;
  ref[ref.length - 1] = "/content/inject_end.js";
  Settings.CONST.ContentScripts = ref.map(func);
  Settings.contentScripts = function(callback) { callback(this.CONST.ContentScripts); };
}, 17);
<commit_msg>set tinyMemory to true for better memory and battery cost<commit_after>"use strict";
var Settings = {
  cache: Object.create(null),
  bufferToLoad: null,
  extWhiteList: null,
  globalCommand: null,
  Init: null,
  SetIconBuffer: null,
  get: function(key, forCache) {
    if (key in this.cache) {
      return this.cache[key];
    }
    var initial = this.defaults[key];
    var value = !(key in localStorage) ? initial
        : typeof initial === "string" ? localStorage[key]
        : initial === false || initial === true ? localStorage[key] === "true"
        : JSON.parse(localStorage[key]);
    if (forCache) {
      this.cache[key] = value;
    }
    return value;
  },
  set: function(key, value) {
    var ref, initial;
    this.cache[key] = value;
    if (!(key in this.nonPersistent)) {
      initial = this.defaults[key];
      if (value === initial) {
        localStorage.removeItem(key);
        this.Sync.set(key, null);
      } else {
        localStorage[key] = typeof initial === "string" ? value : JSON.stringify(value);
        this.Sync.set(key, value);
      }
    }
    if (ref = this.updateHooks[key]) {
      ref.call(this, value, key);
    }
  },
  postUpdate: function(key, value) {
    this.updateHooks[key].call(this, value !== undefined ? value : this.get(key), key);
  },
  broadcast: function (request) {
    var ref = this.indexPorts(), tabId, frames, i;
    for (tabId in ref) {
      frames = ref[tabId];
      for (i = frames.length; 0 < --i; ) {
        frames[i].postMessage(request);
      }
    }
  },
  updateHooks: {
    __proto__: null,
    bufferToLoad: function() {
      var _i, key, ref = this.valuesToLoad, ref2;
      ref2 = this.bufferToLoad = Object.create(null);
      for (_i = ref.length; 0 <= --_i;) {
        key = ref[_i];
        ref2[key] = this.get(key);
      }
    },
    extWhiteList: function(val) {
      var arr = val.split("\n"), i, map;
      map = this.extWhiteList = Object.create(null);
      for (i = arr.length; 0 <= --i; ) {
        if ((val = arr[i]) && (val = val.trim()).length === 32) {
          map[val] = true;
        }
      }
    },
    newTabUrl: function(url) {
      url = /^\/?pages\/[a-z]+.html\b/i.test(url)
        ? chrome.runtime.getURL(url) : Utils.convertToUrl(url);
      this.set('newTabUrl_f', url);
    },
    searchEngines: function() {
      this.set("searchEngineMap", Object.create(null));
    },
    searchEngineMap: function(value) {
      Utils.parseSearchEngines("~:" + this.get("searchUrl"), value);
      var rules = Utils.parseSearchEngines(this.get("searchEngines"), value);
      this.set("searchEngineRules", rules);
    },
    searchUrl: function(str) {
      var map, obj, ind;
      if (str) {
        Utils.parseSearchEngines("~:" + str, map = this.cache.searchEngineMap);
        obj = map["~"];
        str = obj.url.replace(Utils.spacesRe, "%20");
        if (obj.name) { str += " " + obj.name; }
        if (str !== arguments[0]) {
          this.set("searchUrl", str);
          return;
        }
      } else if (str = this.get("newTabUrl_f", true)) {
        this.updateHooks.newTabUrl_f(str);
        return;
      } else {
        str = this.get("searchUrl");
        ind = str.indexOf(" ");
        if (ind > 0) { str = str.substring(0, ind); }
        this.get("searchEngineMap", true)["~"] = { url: str };
      }
      this.postUpdate("newTabUrl");
    },
    baseCss: function(css) {
      this.CONST.BaseCssLength = css.length;
      css += this.get("userDefinedCss");
      this.cache.baseCss = null;
      this.set("innerCss", css);
    },
    vimSync: function(value) {
      if (value) {
        setTimeout(alert, 17, "Warning: the current settings will be OVERRIDDEN the next time Vimium++ starts!\n"
          + 'Please back up your settings using the "Export Settings" button RIGHT NOW!');
      }
      if (value || !this.Sync.HandleStorageUpdate) { return; }
      setTimeout(function() {
        chrome.storage.onChanged.removeListener(Settings.Sync.HandleStorageUpdate);
        Settings.Sync = { set: function() {} };
      }, 100);
    },
    userDefinedCss: function(css) {
      css = this.cache.innerCss.substring(0, this.CONST.BaseCssLength) + css;
      this.set("innerCss", css);
      this.broadcast({
        name: "insertInnerCss",
        css: this.cache.innerCss
      });
    },
    userDefinedOuterCss: function(css) {
      this.broadcast({
        name: "insertCSS",
        css: css
      });
    }
  },
  indexFrame: null,
  indexPorts: null,
  fetchFile: function(file, callback) {
    if (this.cache[file]) { return callback && callback(); }
    Utils.fetchHttpContents(this.files[file], function() {
      Settings.set(file, this.responseText);
      callback && callback();
      return;
    });
  },
  contentScripts: function(callback) {
    setTimeout(function() { callback(Settings.CONST.ContentScripts); }, 18);
    return true;
  },
  // clear localStorage & sync, if value === @defaults[key]
  // the default of any dict field must be set to null for compatibility with @Sync.set
  defaults: {
    __proto__: null,
    deepHints: false,
    exclusionListenHash: true,
    exclusionOnlyFirstMatch: false,
    exclusionRules: [{pattern: "^https?://mail.google.com/", passKeys: ""}],
    extWhiteList: "# hdnehngglnbnehkfcidabjckinphnief",
    findModeRawQueryList: "",
    grabBackFocus: true,
    hideHud: false,
    keyboard: [500, 33],
    keyMappings: "",
    linkHintCharacters: "sadjklewcmpgh",
    localeEncoding: "gbk",
    newTabUrl: "",
    newTabUrl_f: "",
    nextPatterns: "\u4e0b\u9875,\u4e0b\u4e00\u9875,\u4e0b\u4e00\u7ae0,\u540e\u4e00\u9875"
      + ",next,more,newer,>,\u203a,\u2192,\xbb,\u226b,>>",
    previousPatterns: "\u4e0a\u9875,\u4e0a\u4e00\u9875,\u4e0a\u4e00\u7ae0,\u524d\u4e00\u9875"
      + ",prev,previous,back,older,<,\u2039,\u2190,\xab,\u226a,<<",
    regexFindMode: false,
    scrollStepSize: 100,
    searchUrl: "https://www.baidu.com/s?ie=UTF-8&wd=$s Baidu",
    searchEngines: "b|ba|baidu|Baidu: https://www.baidu.com/s?ie=UTF-8&wd=$s \u767e\u5ea6\n\
g|go|gg|google|Google: https://www.google.com/search?q=$s Google\n\
js\\:|Js: javascript:\\ $S; Javascript\n\
w|wiki:\\\n  http://www.wikipedia.org/w/index.php?search=$s Wikipedia (en-US)",
    searchEngineMap: {}, // may be modified, but this action is safe
    showActionIcon: true,
    showAdvancedCommands: false,
    showAdvancedOptions: false,
    smoothScroll: true,
    tinyMemory: true,
    userDefinedCss: "",
    userDefinedOuterCss: "",
    vimSync: false
  },
  // not set localStorage, neither sync, if key in @nonPersistent
  // not clean if exists (for simpler logic)
  nonPersistent: { __proto__: null,
    baseCss: 1, exclusionTemplate: 1, helpDialog: 1, innerCss: 1,
    searchEngineMap: 1, searchEngineRules: 1, vomnibar: 1
  },
  files: {
    __proto__: null,
    baseCss: "front/vimium.min.css",
    exclusionTemplate: "front/exclusions.html",
    helpDialog: "front/help_dialog.html",
    vomnibar: "front/vomnibar.html"
  },
  icons: {
    disabled: { "19": "icons/disabled_19.png", "38": "icons/disabled_38.png" },
    enabled: { "19": "icons/enabled_19.png", "38": "icons/enabled_38.png" },
    partial: { "19": "icons/partial_19.png", "38": "icons/partial_38.png" }
  },
  valuesToLoad: ["deepHints" //
    , "grabBackFocus", "hideHud", "keyboard" //
    , "linkHintCharacters", "nextPatterns", "previousPatterns" //
    , "scrollStepSize", "smoothScroll" //
  ],
  Sync: {
    set: function() {}
  },
  CONST: {
    ChromeInnerNewTab: "chrome-search://local-ntp/local-ntp.html", // should keep lower case
    ChromeVersion: 37, ContentScripts: null, CurrentVersion: "",
    BaseCssLength: 0,
    OnMac: false, OptionsPage: ""
  }
};

// note: if changed, ../pages/newtab.js also needs change.
Settings.defaults.newTabUrl = Settings.CONST.ChromeInnerNewTab;
Settings.CONST.ChromeVersion = +navigator.appVersion.match(/Chrom(?:e|ium)\/(\d+\.\d+)/)[1];

setTimeout(function() {
  chrome.runtime.getPlatformInfo(function(info) {
    Settings.CONST.OnMac = info.os === "mac";
  });

  var ref, origin = location.origin, prefix = origin + "/",
  func = function(path) {
    return (path.charCodeAt(0) === 47 ? origin : prefix) + path;
  };
  ref = chrome.runtime.getManifest();
  Settings.CONST.CurrentVersion = ref.version;
  Settings.CONST.OptionsPage = func(ref.options_page);
  ref = ref.content_scripts[0].js;
  ref[ref.length - 1] = "/content/inject_end.js";
  Settings.CONST.ContentScripts = ref.map(func);
  Settings.contentScripts = function(callback) { callback(this.CONST.ContentScripts); };
}, 17);
<|endoftext|>


<commit_before>// Initializes barchart into namespace
PolymerD3.barChart = {};

Polymer({
  is: 'bar-chart',
  properties: {
    title: '',
    inputs: {
      notify: true,
      type: Array,
      value: () => {
        return [{
          input: 'x',
          txt: 'Pick Dimension',
          selectedValue: [],
          scaleType: '',
          format: '',
          selectedObjs: [],
          uitype: 'single-value',
          displayName: 'myXAxis',
          maxSelectableValues: 1
        }, {
          input: 'y',
          txt: 'Pick Measures',
          selectedValue: [],
          format: '',
          scaleType: '',
          selectedObjs: [],
          uitype: 'multi-value',
          displayName: 'myYAxis',
          maxSelectableValues: 2,
          supportedType: ''
        }, {
          input: 'z',
          txt: 'Pick Z',
          selectedValue: [],
          format: '',
          scaleType: '',
          selectedObjs: [],
          uitype: 'multi-value',
          displayName: 'myZAxis',
          maxSelectableValues: 2,
          supportedType: ''
        }];
      }
    },
    settings: {
      notify: true,
      type: Object,
      value: () => {
        return [];
      }
    },
    chartType: {
      type: Object,
      value: () => {
        return [];
      }
    },
    hideSettings: true,
    source: Array,
    external: Array,
    chart: Object,
    dataMutated: false,
    isStacked: {
      type: Boolean,
      value: true
    },
    configurator: {
      type: Object,
      value: function() {
        return {};
      }
    }
  },

  behaviors: [
    PolymerD3.chartBehavior,
    PolymerD3.chartConfigCbBehavior
  ],

  attached: function() {
    // this._loadDiffdata();
    //  this._loadHeatmap();
    // this._loadWaterfall();
    // this._loadSingleCol();
    // PolymerD3.fileReader('bar-data.csv', [1, 2, 3, 4, 5, 6, 7], [], undefined, this._setSource.bind(this));
  },

  draw: function() {
    var me = this;
    // Experimental: Debounce draw, to avoid getting called multiple times
    this.debounce('darwDebounce', () => {
      let xIndex = this.getInputsProperty('x');
      let yIndices = this.getInputsProperty('y');
      let zGroup = this.getInputsProperty('z');
      let z = this.setLegendColor.bind(this);
      this.resize();
      // requireed indices not selected
      if (xIndex === -1 || !yIndices || yIndices.length < 1 || !this.source ||
        PolymerD3.utilities.isEmptyObject(this.configurator) || this.source.length < 1
      ) {
        console.warn('Fill all required inputs using drag and drop');
        return false;
      }

      let headers = this.externals.map(e => {
        return e.key;
      });

      if (this.parentG) {
        this.parentG.html("");
      }

      var conf = this.configurator.conf.call(this);
      if (conf.chartType == 'heatmap' && (!zGroup || !zGroup.length)) {
        console.warn('Select z-attribute to select a fill color');
        return false;
      }

      // cloning the source to keep it intact
      let _src = JSON.parse(JSON.stringify(this.source));

      // for waterfall chart
      if (conf.chartType === 'waterfall') {
        let sum = 0;
        _src.forEach(value =>  {
          sum += value[yIndices[0]];
        });
        var total = {};
        total[xIndex] = 'Total';
        total[yIndices[0]] = sum;
        _src.push(total);
      }

      // if z/group-by is selected, data should be grouped by values in coloumn zGroup
      let _isGrouped = false;
      if (zGroup && zGroup.length) {
        _isGrouped = true;
        conf.stackIndex = zGroup[0];
      }

      var myGroup = PolymerD3
        .groupingBehavior
        .group_by(
          (_isGrouped) ? zGroup : yIndices,
          xIndex, yIndices, headers, conf.chartType, _isGrouped
        );
      var nChartConfig = this.chartConfig(conf, _src, myGroup.process);

      let stackData = myGroup.getStack();
      // if (_isGrouped) {
      //   stackData = myGroup.getGroups();
      // } else {
      //   stackData = myGroup.getStack();
      // }

      // Temporary hack to pass stackData's length to processor
      nChartConfig.stackDataLength = stackData.length;

      var translations = this.configurator.processors(nChartConfig);

      let layer = this.parentG.selectAll('.layer')
        .data(stackData)
        .enter().append('g')
        .attr('transform', translations.translate)
        .attr('class', 'layer')
        .style('fill', function(d) {
          // Logic to generate legends initialy
          var color = z(d);
          var keyPresent = false;
          me.legendSettings.colors.forEach((c) => {
            if (c.label == d.key) {
              color = c.color;
              keyPresent = true;
            }
          });
          // Create new entry if legend isn't present
          // TO do: remove &&d.key =>  something's wrong with generate stackData meathod
          // d.key comes as undefined check `PolymerD3.groupingBehavior`
          if (!keyPresent && d.key) {
            me.legendSettings.colors.push({
              color: color,
              label: d.key
            });
          }
          return color;
        })
        .attr('class', 'stroked-elem') // to set stroke
        .attr('data-legend', function(d) {
          return d.key;
        });
      // this.attachLegend(this.parentG);

      var rects = layer.selectAll('rect')
        .data(function(d) {
          return d.values;
        })
        .enter().append('rect')
        .attr('x', translations.rectX)
        .attr('y', translations.rectY)
        .attr('height', translations.rectHeight)
        .attr('width', translations.barWidth)
        // .attr('data-legend', translations.legendF)
        .attr('class', translations.classF);

      if (conf.chartType === 'heatmap') {
        var colorRange = this.getAreaProperty('colorRange')
        if (!colorRange) {
          colorRange = {
            input: 'colorRange',
            txt: 'Select color range',
            uitype: 'colorRangePicker',
            from: '#ffffff',
            to: '#ff0000',
            callBack: 'draw'
          }
          this.push('area', colorRange);
        }
        var color = d3.scale.linear()
          .domain(d3.extent(stackData[0].values.map(aobj => aobj.z)))
          .range([colorRange.from, colorRange.to])
          .interpolate(d3.interpolateLab);
        rects.style('fill', d => color(d.z));
      }

      function htmlCbForHeatMap(d) {
        return '' + headers[zGroup[0]] + ':	' + d.z + '	';
      }
      var htmlCallback = d => { // retained as arrow function to access `this.inputs[]`
        var str = '
' +
          '
' +
          '' + this.inputs[0].displayName + ':	' +
          '' + nChartConfig.formatX(d[0]) + '	' +
          '
' +
          '
' +
          '' + this.inputs[1].displayName + ':	' +
          '' + nChartConfig.formatY(d[1]) + '	' +
          '
' + (conf.chartType == 'heatmap' ? htmlCbForHeatMap(d) : '') +
          '
';
        return str;
      };
      this.attachToolTip(this.parentG, rects, 'vertalBars', htmlCallback);

      this.attachLegend(this.parentG);
    }, 500);
  },

  initGroupedBarChart: function() {
    this.set('inputs', [{
      input: 'x',
      txt: 'Pick Dimension',
      selectedValue: [],
      scaleType: '',
      format: '',
      selectedObjs: [],
      uitype: 'single-value',
      displayName: 'myXAxis',
      maxSelectableValues: 1
    }, {
      input: 'y',
      txt: 'Pick Measures',
      selectedValue: [],
      format: '',
      scaleType: '',
      selectedObjs: [],
      uitype: 'multi-value',
      displayName: 'myYAxis',
      maxSelectableValues: 5,
      supportedType: ''
    }, {
      input: 'z',
      txt: 'Pick Z',
      selectedValue: [],
      format: '',
      scaleType: '',
      selectedObjs: [],
      uitype: 'multi-value',
      displayName: 'myZAxis',
      maxSelectableValues: 1,
      supportedType: ''
    }]);
    this.set('configurator', new PolymerD3.barChart.grouped());
  },

  initStackedBarChart: function() {
    this.set('inputs', [{
      input: 'x',
      txt: 'Pick Dimension',
      selectedValue: [],
      scaleType: '',
      format: '',
      selectedObjs: [],
      uitype: 'single-value',
      displayName: 'myXAxis',
      maxSelectableValues: 1
    }, {
      input: 'y',
      txt: 'Pick Measures',
      selectedValue: [],
      format: '',
      scaleType: '',
      selectedObjs: [],
      uitype: 'multi-value',
      displayName: 'myYAxis',
      maxSelectableValues: 5,
      supportedType: ''
    }, {
      input: 'z',
      txt: 'Pick Z',
      selectedValue: [],
      format: '',
      scaleType: '',
      selectedObjs: [],
      uitype: 'multi-value',
      displayName: 'myZAxis',
      maxSelectableValues: 1,
      supportedType: ''
    }]);
    this.set('configurator', new PolymerD3.barChart.stacked());
  },

  initWaterfallChart: function() {
    this.set('inputs', [{
      input: 'x',
      txt: 'Pick Dimension',
      selectedValue: [],
      scaleType: '',
      format: '',
      selectedObjs: [],
      uitype: 'single-value',
      displayName: 'myXAxis',
      maxSelectableValues: 1
    }, {
      input: 'y',
      txt: 'Pick Measures',
      selectedValue: [],
      format: '',
      scaleType: '',
      selectedObjs: [],
      uitype: 'multi-value',
      displayName: 'myYAxis',
      maxSelectableValues: 1,
      supportedType: ''
    }]);
    this.set('configurator', new PolymerD3.barChart.waterfall());
  },

  initDiffrenceChart: function() {
    this.set('inputs', [{
      input: 'x',
      txt: 'Pick Dimension',
      selectedValue: [],
      scaleType: '',
      format: '',
      selectedObjs: [],
      uitype: 'single-value',
      displayName: 'myXAxis',
      maxSelectableValues: 1
    }, {
      input: 'y',
      txt: 'Pick Measures',
      selectedValue: [],
      format: '',
      scaleType: '',
      selectedObjs: [],
      uitype: 'multi-value',
      displayName: 'myYAxis',
      maxSelectableValues: 2,
      supportedType: ''
    }]);
    this.set('configurator', new PolymerD3.barChart.difference());
  },

  initHeatMap: function() {
    this.set('inputs', [{
      input: 'x',
      txt: 'Pick Dimension',
      selectedValue: [],
      scaleType: '',
      format: '',
      selectedObjs: [],
      uitype: 'single-value',
      displayName: 'myXAxis',
      maxSelectableValues: 1
    }, {
      input: 'y',
      txt: 'Pick Measures',
      selectedValue: [],
      format: '',
      scaleType: '',
      selectedObjs: [],
      uitype: 'multi-value',
      displayName: 'myYAxis',
      maxSelectableValues: 1,
      supportedType: ''
    }, {
      input: 'z',
      txt: 'Pick Z',
      selectedValue: [],
      format: '',
      scaleType: '',
      selectedObjs: [],
      uitype: 'multi-value',
      displayName: 'myZAxis',
      maxSelectableValues: 1,
      supportedType: ''
    }]);
    this.set('configurator', new PolymerD3.barChart.heatMap());
  }
});
<commit_msg>Give separate setting for individual bar charts<commit_after>// Initializes barchart into namespace
PolymerD3.barChart = {};

Polymer({
  is: 'bar-chart',
  properties: {
    title: '',
    inputs: {
      notify: true,
      type: Array,
      value: () => {
        return [{
          input: 'x',
          txt: 'Pick Dimension',
          selectedValue: [],
          scaleType: '',
          format: '',
          selectedObjs: [],
          uitype: 'single-value',
          displayName: 'myXAxis',
          maxSelectableValues: 1
        }, {
          input: 'y',
          txt: 'Pick Measures',
          selectedValue: [],
          format: '',
          scaleType: '',
          selectedObjs: [],
          uitype: 'multi-value',
          displayName: 'myYAxis',
          maxSelectableValues: 2,
          supportedType: ''
        }, {
          input: 'z',
          txt: 'Pick Z',
          selectedValue: [],
          format: '',
          scaleType: '',
          selectedObjs: [],
          uitype: 'multi-value',
          displayName: 'myZAxis',
          maxSelectableValues: 2,
          supportedType: ''
        }];
      }
    },
    settings: {
      notify: true,
      type: Object,
      value: () => {
        return [];
      }
    },
    chartType: {
      type: Object,
      value: () => {
        return [];
      }
    },
    hideSettings: true,
    source: Array,
    external: Array,
    chart: Object,
    dataMutated: false,
    isStacked: {
      type: Boolean,
      value: true
    },
    configurator: {
      type: Object,
      value: function() {
        return {};
      }
    }
  },

  behaviors: [
    PolymerD3.chartBehavior,
    PolymerD3.chartConfigCbBehavior
  ],

  attached: function() {
    // this._loadDiffdata();
    //  this._loadHeatmap();
    // this._loadWaterfall();
    // this._loadSingleCol();
    // PolymerD3.fileReader('bar-data.csv', [1, 2, 3, 4, 5, 6, 7], [], undefined, this._setSource.bind(this));
  },

  draw: function() {
    var me = this;
    // Experimental: Debounce draw, to avoid getting called multiple times
    this.debounce('darwDebounce', () => {
      let xIndex = this.getInputsProperty('x');
      let yIndices = this.getInputsProperty('y');
      let zGroup = this.getInputsProperty('z');
      let z = this.setLegendColor.bind(this);
      this.resize();
      // requireed indices not selected
      if (xIndex === -1 || !yIndices || yIndices.length < 1 || !this.source ||
        PolymerD3.utilities.isEmptyObject(this.configurator) || this.source.length < 1
      ) {
        console.warn('Fill all required inputs using drag and drop');
        return false;
      }

      let headers = this.externals.map(e => {
        return e.key;
      });

      if (this.parentG) {
        this.parentG.html("");
      }

      var conf = this.configurator.conf.call(this);
      if (conf.chartType == 'heatmap' && zGroup == null) {
        console.warn('Select z-attribute to select a fill color');
        return false;
      }

      // cloning the source to keep it intact
      let _src = JSON.parse(JSON.stringify(this.source));

      // for waterfall chart
      if (conf.chartType === 'waterfall') {
        let sum = 0;
        _src.forEach(value =>  {
          sum += value[yIndices[0]];
        });
        var total = {};
        total[xIndex] = 'Total';
        total[yIndices[0]] = sum;
        _src.push(total);
      }

      // if z/group-by is selected, data should be grouped by values in coloumn zGroup
      let _isGrouped = false;
      if (zGroup != null) {
        _isGrouped = true;
        conf.stackIndex = zGroup;
      }

      var myGroup = PolymerD3
        .groupingBehavior
        .group_by(
          (_isGrouped) ? [zGroup] : yIndices,
          xIndex, yIndices, headers, conf.chartType, _isGrouped
        );
      var nChartConfig = this.chartConfig(conf, _src, myGroup.process);

      let stackData = myGroup.getStack();
      // if (_isGrouped) {
      //   stackData = myGroup.getGroups();
      // } else {
      //   stackData = myGroup.getStack();
      // }

      // Temporary hack to pass stackData's length to processor
      nChartConfig.stackDataLength = stackData.length;

      var translations = this.configurator.processors(nChartConfig);

      let layer = this.parentG.selectAll('.layer')
        .data(stackData)
        .enter().append('g')
        .attr('transform', translations.translate)
        .attr('class', 'layer')
        .style('fill', function(d) {
          // Logic to generate legends initialy
          var color = z(d);
          var keyPresent = false;
          me.legendSettings.colors.forEach((c) => {
            if (c.label == d.key) {
              color = c.color;
              keyPresent = true;
            }
          });
          // Create new entry if legend isn't present
          // TO do: remove &&d.key =>  something's wrong with generate stackData meathod
          // d.key comes as undefined check `PolymerD3.groupingBehavior`
          if (!keyPresent && d.key) {
            me.legendSettings.colors.push({
              color: color,
              label: d.key
            });
          }
          return color;
        })
        .attr('class', 'stroked-elem') // to set stroke
        .attr('data-legend', function(d) {
          return d.key;
        });
      // this.attachLegend(this.parentG);

      var rects = layer.selectAll('rect')
        .data(function(d) {
          return d.values;
        })
        .enter().append('rect')
        .attr('x', translations.rectX)
        .attr('y', translations.rectY)
        .attr('height', translations.rectHeight)
        .attr('width', translations.barWidth)
        // .attr('data-legend', translations.legendF)
        .attr('class', translations.classF);

      if (conf.chartType === 'heatmap') {
        var colorRange = this.getAreaProperty('colorRange')
        if (!colorRange) {
          colorRange = {
            input: 'colorRange',
            txt: 'Select color range',
            uitype: 'colorRangePicker',
            from: '#ffffff',
            to: '#ff0000',
            callBack: 'draw'
          }
          this.push('area', colorRange);
        }
        var color = d3.scale.linear()
          .domain(d3.extent(stackData[0].values.map(aobj => aobj.z)))
          .range([colorRange.from, colorRange.to])
          .interpolate(d3.interpolateLab);
        rects.style('fill', d => color(d.z));
      }

      function htmlCbForHeatMap(d) {
        return '' + headers[zGroup] + ':	' + d.z + '	';
      }
      var htmlCallback = d => { // retained as arrow function to access `this.inputs[]`
        var str = '
' +
          '
' +
          '' + this.inputs[0].displayName + ':	' +
          '' + nChartConfig.formatX(d[0]) + '	' +
          '
' +
          '
' +
          '' + this.inputs[1].displayName + ':	' +
          '' + nChartConfig.formatY(d[1]) + '	' +
          '
' + (conf.chartType == 'heatmap' ? htmlCbForHeatMap(d) : '') +
          '
';
        return str;
      };
      this.attachToolTip(this.parentG, rects, 'vertalBars', htmlCallback);

      this.attachLegend(this.parentG);
    }, 500);
  },

  initGroupedBarChart: function() {
    this.set('inputs', [{
      input: 'x',
      txt: 'Pick Dimension',
      selectedValue: [],
      scaleType: '',
      format: '',
      selectedObjs: [],
      uitype: 'single-value',
      displayName: 'myXAxis',
      maxSelectableValues: 1
    }, {
      input: 'y',
      txt: 'Pick Measures',
      selectedValue: [],
      format: '',
      scaleType: '',
      selectedObjs: [],
      uitype: 'multi-value',
      displayName: 'myYAxis',
      maxSelectableValues: 5,
      supportedType: ''
    }, {
      input: 'z',
      txt: 'Pick Z',
      selectedValue: [],
      format: '',
      scaleType: '',
      selectedObjs: [],
      uitype: 'multi-value',
      displayName: 'myZAxis',
      maxSelectableValues: 1,
      supportedType: ''
    }]);
    this.set('configurator', new PolymerD3.barChart.grouped());
  },

  initStackedBarChart: function() {
    this.set('inputs', [{
      input: 'x',
      txt: 'Pick Dimension',
      selectedValue: [],
      scaleType: '',
      format: '',
      selectedObjs: [],
      uitype: 'single-value',
      displayName: 'myXAxis',
      maxSelectableValues: 1
    }, {
      input: 'y',
      txt: 'Pick Measures',
      selectedValue: [],
      format: '',
      scaleType: '',
      selectedObjs: [],
      uitype: 'multi-value',
      displayName: 'myYAxis',
      maxSelectableValues: 5,
      supportedType: ''
    }, {
      input: 'z',
      txt: 'Pick Z',
      selectedValue: [],
      format: '',
      scaleType: '',
      selectedObjs: [],
      uitype: 'multi-value',
      displayName: 'myZAxis',
      maxSelectableValues: 1,
      supportedType: ''
    }]);
    this.set('configurator', new PolymerD3.barChart.stacked());
  },

  initWaterfallChart: function() {
    this.set('inputs', [{
      input: 'x',
      txt: 'Pick Dimension',
      selectedValue: [],
      scaleType: '',
      format: '',
      selectedObjs: [],
      uitype: 'single-value',
      displayName: 'myXAxis',
      maxSelectableValues: 1
    }, {
      input: 'y',
      txt: 'Pick Measures',
      selectedValue: [],
      format: '',
      scaleType: '',
      selectedObjs: [],
      uitype: 'multi-value',
      displayName: 'myYAxis',
      maxSelectableValues: 1,
      supportedType: ''
    }]);
    this.set('configurator', new PolymerD3.barChart.waterfall());
  },

  initDiffrenceChart: function() {
    this.set('inputs', [{
      input: 'x',
      txt: 'Pick Dimension',
      selectedValue: [],
      scaleType: '',
      format: '',
      selectedObjs: [],
      uitype: 'single-value',
      displayName: 'myXAxis',
      maxSelectableValues: 1
    }, {
      input: 'y',
      txt: 'Pick Measures',
      selectedValue: [],
      format: '',
      scaleType: '',
      selectedObjs: [],
      uitype: 'multi-value',
      displayName: 'myYAxis',
      maxSelectableValues: 2,
      supportedType: ''
    }]);
    this.set('configurator', new PolymerD3.barChart.difference());
  },

  initHeatMap: function() {
    this.set('inputs', [{
      input: 'x',
      txt: 'Pick Dimension',
      selectedValue: [],
      scaleType: '',
      format: '',
      selectedObjs: [],
      uitype: 'single-value',
      displayName: 'myXAxis',
      maxSelectableValues: 1
    }, {
      input: 'y',
      txt: 'Pick Measures',
      selectedValue: [],
      format: '',
      scaleType: '',
      selectedObjs: [],
      uitype: 'multi-value',
      displayName: 'myYAxis',
      maxSelectableValues: 1,
      supportedType: ''
    }, {
      input: 'z',
      txt: 'Pick Z',
      selectedValue: [],
      format: '',
      scaleType: '',
      selectedObjs: [],
      uitype: 'multi-value',
      displayName: 'myZAxis',
      maxSelectableValues: 1,
      supportedType: ''
    }]);
    this.set('configurator', new PolymerD3.barChart.heatMap());
  }
});
<|endoftext|>