<commit_before>import * as React from "react";
import { Navigation } from "./Navigation";

/**
 * Main Navigation Component
 */
export const Header = () => {
  const TITLE = "LLVM Build View";

  return (

      <Wrapper>
        {TITLE}
      </Wrapper>
      <Wrapper>
        <Navigation/>
      </Wrapper>

  );
}
<commit_msg>Change to single quotes<commit_after>import * as React from "react";
import { Navigation } from "./Navigation";

/**
 * Main Navigation Component
 */
export const Header = () => {
  const TITLE = 'LLVM Build View';

  return (

      <Wrapper>
        {TITLE}
      </Wrapper>
      <Wrapper>
        <Navigation/>
      </Wrapper>

  );
}
<|endoftext|>


<commit_before>var Conversation = function(speciesList) {
	this.lastAnswer = null;
	this.lastAction = Date.now();
	this.firstmessage = true;
	this.inFindingProcess = false;

	this.speciesList = speciesList;

	let commonNames = speciesList.map((obj)=>obj.triname);
	let scientificNames = speciesList.map((obj)=>obj.sciname);
  this.speciesNames = commonNames.concat(scientificNames);

	this.location = null;
	this.species = null;

	this.isActive = function(){
			let diff = this.lastAction - Date.now();
			let fiveMinInMs = 1000 * 60 * 5;
			return diff <= fiveMinInMs;

	};
	this.setLocation = function(location){
		this.location = location
	};
	this.processMessage = function(message) {
		console.log("Input> " + message);
    this.lastAction = Date.now();
		var splitedMessage = message.split(/[ ,]+/);

		if(this.firstmessage || match(splitedMessage,["hey", "moin", "hallo", "hi", "servus"])) {
			this.firstmessage = false;
			var startText = 'Hey du, ich bin BioDiv und kann weiterhelfen, wenn du seltene Muscheln / Säugetiere oder Fische in deiner Umgebung gesichtet hast. ';

			var answerOptions = ["Hilfe", "Fund melden"];

			return { answer: startText, answerOptions: answerOptions };
		}
		let yes = ["ja", "ok", "jo", "jup"];
		let no = ["nein", "nö", "ne", "auf gar keinen fall", "halt die fresse"];

    if(match(splitedMessage, yes.concat(no))) {
			var userAnswer = message;
			var answerOptions = [];

			this.lastAnswer = null;
			if(match(splitedMessage, yes)) {
				var jaText = "Ich halte Dich auf dem Laufenden. 👍";
				return { answer: jaText, answerOptions: answerOptions };
			} else {
				var neinText = "Ok, frag' einfach, wenn du wissen willst, wie der Status ist. 😁 Ich bin bis auf weiteres stumm. 🙈🙊🙉";
				return { answer: neinText, answerOptions: answerOptions };
			}

		}

		if(match([message], ["Fund melden"])) {
			var answerOptions = [];

			var helpText = 'ℹ Alles klar du, dann lass uns loslegen und deinen Fund zusammen aufnehmen! Was für eine Spezies hast du denn gesehen?';

      this.inFindingProcess = true;

			return { answer: helpText, answerOptions: answerOptions };
		}

		if(this.inFindingProcess){

    	console.log(splitedMessage);
    	console.log(this.speciesCommonNames);
    	console.log(this.speciesSientificNames);

    	if(match([message],["Location set"])){
        return {
          answer: "Nun weiß ich schon wo du dich befindest, Vielleicht möchtest du noch mehr angeben?",
          answerOptions: ["Nachweisquallität", "Nachweismethode", "Fund speichern"]
        };
			}
			else if(match(splitedMessage,["Nachweismethode"])){
        return {
          answer: "Okay welche der folgenden Nachweismethoden wurde verwendet?",
          answerOptions: [""]
        };
			}
			else if(match(splitedMessage,["Nachweisquallität"])){
        return {
          answer: "Wie war die genaue Nachweisquallität?",
          answerOptions: ["Nachweisquallität", "Nachweismethode"]
        };
			}
    	else if(match([message],this.speciesNames)){

				let potentialSpecies = this.speciesList.filter((species)=> {

					let nameSplits = species.triname.split(" ");
					nameSplits = nameSplits.concat(species.sciname.split(" "));

          nameSplits = nameSplits.filter((name)=> name.toLowerCase() !="muschel" && name.toLowerCase()!= "mussel")
          nameSplits = nameSplits.filter((name)=> name.toLowerCase() !="clam ");
          nameSplits = nameSplits.filter((name)=> name.toLowerCase() !="fisch" && name.toLowerCase()!= "fish")
					console.log("nameSplits",nameSplits);
					return match(splitedMessage,nameSplits )
        });

				console.log("potentialSpecies", potentialSpecies);

				if(potentialSpecies.length == 0 ){
          return {
            answer: "Irgendwas ist hier schief gelaufen :( Ich konnte irgendwie keine Spezies finden ... "
          };
				}
				else if (potentialSpecies.length == 1 ){
          return {
            answer: "Sehr schön, hab ich verstanden du hast " + message + " bei dir gesehen. " +
            "\n Es wäre super wenn du mir noch deinen Standort zeigen könntest?",
            locationRequest: true
          };
				}else {
          return {
            answer: "Huch da brauch ich noch ein wenig mehr Infos.\nEs gibt mehrere Spezies, bitte wähle die richtige aus: ",
            answerOptions: potentialSpecies.map((species)=>species.triname)
          };
				}

			}

    	else if(this.speciesName == null){

        console.log("Choose species text ", this.speciesCommonNames);
        return {
          answer: "Leider habe ich dich nicht so recht verstanden, hier einige Vorschläge was für Spezies ich so im Angebot hätte",
          answerOptions: this.speciesList.map((species)=>species.triname)
        }

			}

		}

		return {
      answer: "Ich konnte dich leider nicht verstehen... 😰",
      answerOptions: ["Hilfe"]
    }

	};

	return this;
};

function match(splitedMessage, keyWords) {

	for(var word in splitedMessage) {
		for(var keyWord in keyWords) {
			var lowerCaseWord = splitedMessage[word].toLowerCase();
			var lowerCaseKeyword = keyWords[keyWord].toLowerCase();

			if(lowerCaseWord == lowerCaseKeyword) {
				return true;
			}
		}
	}

	return false;
}

module.exports = Conversation;
<commit_msg>- Trim also all strings<commit_after>var Conversation = function(speciesList) {
	this.lastAnswer = null;
	this.lastAction = Date.now();
	this.firstmessage = true;
	this.inFindingProcess = false;

	this.speciesList = speciesList;

	let commonNames = speciesList.map((obj)=>obj.triname);
	let scientificNames = speciesList.map((obj)=>obj.sciname);
  this.speciesNames = commonNames.concat(scientificNames);

	this.location = null;
	this.species = null;

	this.isActive = function(){
			let diff = this.lastAction - Date.now();
			let fiveMinInMs = 1000 * 60 * 5;
			return diff <= fiveMinInMs;

	};
	this.setLocation = function(location){
		this.location = location
	};
	this.processMessage = function(message) {
		console.log("Input> " + message);
    this.lastAction = Date.now();
		var splitedMessage = message.split(/[ ,]+/);

		if(this.firstmessage || match(splitedMessage,["hey", "moin", "hallo", "hi", "servus"])) {
			this.firstmessage = false;
			var startText = 'Hey du, ich bin BioDiv und kann weiterhelfen, wenn du seltene Muscheln / Säugetiere oder Fische in deiner Umgebung gesichtet hast. ';

			var answerOptions = ["Hilfe", "Fund melden"];

			return { answer: startText, answerOptions: answerOptions };
		}
		let yes = ["ja", "ok", "jo", "jup"];
		let no = ["nein", "nö", "ne", "auf gar keinen fall", "halt die fresse"];

    if(match(splitedMessage, yes.concat(no))) {
			var userAnswer = message;
			var answerOptions = [];

			this.lastAnswer = null;
			if(match(splitedMessage, yes)) {
				var jaText = "Ich halte Dich auf dem Laufenden. 👍";
				return { answer: jaText, answerOptions: answerOptions };
			} else {
				var neinText = "Ok, frag' einfach, wenn du wissen willst, wie der Status ist. 😁 Ich bin bis auf weiteres stumm. 🙈🙊🙉";
				return { answer: neinText, answerOptions: answerOptions };
			}

		}

		if(match([message], ["Fund melden"])) {
			var answerOptions = [];

			var helpText = 'ℹ Alles klar du, dann lass uns loslegen und deinen Fund zusammen aufnehmen! Was für eine Spezies hast du denn gesehen?';

      this.inFindingProcess = true;

			return { answer: helpText, answerOptions: answerOptions };
		}

		if(this.inFindingProcess){

    	console.log(splitedMessage);
    	console.log(this.speciesCommonNames);
    	console.log(this.speciesSientificNames);

    	if(match([message],["Location set"])){
        return {
          answer: "Nun weiß ich schon wo du dich befindest, Vielleicht möchtest du noch mehr angeben?",
          answerOptions: ["Nachweisquallität", "Nachweismethode", "Fund speichern"]
        };
			}
			else if(match(splitedMessage,["Nachweismethode"])){
        return {
          answer: "Okay welche der folgenden Nachweismethoden wurde verwendet?",
          answerOptions: [""]
        };
			}
			else if(match(splitedMessage,["Nachweisquallität"])){
        return {
          answer: "Wie war die genaue Nachweisquallität?",
          answerOptions: ["Nachweisquallität", "Nachweismethode"]
        };
			}
    	else if(match([message],this.speciesNames)){

				let potentialSpecies = this.speciesList.filter((species)=> {

					let nameSplits = species.triname.split(" ");
					nameSplits = nameSplits.concat(species.sciname.split(" "));

          nameSplits = nameSplits.filter((name)=> name.toLowerCase().trim() !="muschel" && name.toLowerCase().trim()!= "mussel")
          nameSplits = nameSplits.filter((name)=> name.toLowerCase().trim() !="clam");
          nameSplits = nameSplits.filter((name)=> name.toLowerCase().trim() !="fisch" && name.toLowerCase().trim()!= "fish")
					console.log("nameSplits",nameSplits);
					return match(splitedMessage,nameSplits )
        });

				console.log("potentialSpecies", potentialSpecies);

				if(potentialSpecies.length == 0 ){
          return {
            answer: "Irgendwas ist hier schief gelaufen :( Ich konnte irgendwie keine Spezies finden ... "
          };
				}
				else if (potentialSpecies.length == 1 ){
          return {
            answer: "Sehr schön, hab ich verstanden du hast " + message + " bei dir gesehen. " +
            "\n Es wäre super wenn du mir noch deinen Standort zeigen könntest?",
            locationRequest: true
          };
				}else {
          return {
            answer: "Huch da brauch ich noch ein wenig mehr Infos.\nEs gibt mehrere Spezies, bitte wähle die richtige aus: ",
            answerOptions: potentialSpecies.map((species)=>species.triname)
          };
				}

			}

    	else if(this.speciesName == null){

        console.log("Choose species text ", this.speciesCommonNames);
        return {
          answer: "Leider habe ich dich nicht so recht verstanden, hier einige Vorschläge was für Spezies ich so im Angebot hätte",
          answerOptions: this.speciesList.map((species)=>species.triname)
        }

			}

		}

		return {
      answer: "Ich konnte dich leider nicht verstehen... 😰",
      answerOptions: ["Hilfe"]
    }

	};

	return this;
};

function match(splitedMessage, keyWords) {

	for(var word in splitedMessage) {
		for(var keyWord in keyWords) {
			var lowerCaseWord = splitedMessage[word].toLowerCase();
			var lowerCaseKeyword = keyWords[keyWord].toLowerCase();

			if(lowerCaseWord == lowerCaseKeyword) {
				return true;
			}
		}
	}

	return false;
}

module.exports = Conversation;
<|endoftext|>


<commit_before>(function () {

	var ie = !!window.ActiveXObject,
		ie6 = ie && !window.XMLHttpRequest,

		// terrible browser detection to work around Safari / iOS / Android browser bugs
		// see TileLayer._addTile and debug/hacks/jitter.html

		ua = navigator.userAgent.toLowerCase(),
		webkit = ua.indexOf("webkit") !== -1,
		chrome = ua.indexOf("chrome") !== -1,
		android = ua.indexOf("android") !== -1,
		android23 = ua.search("android [23]") !== -1,

		mobile = typeof orientation !== undefined + '',
		msTouch = (window.navigator && window.navigator.msPointerEnabled && window.navigator.msMaxTouchPoints),
		retina = (('devicePixelRatio' in window && window.devicePixelRatio > 1) ||
				('matchMedia' in window && window.matchMedia("(min-resolution:144dpi)").matches)),

		doc = document.documentElement,
		ie3d = ie && ('transition' in doc.style),
		webkit3d = ('WebKitCSSMatrix' in window) && ('m11' in new window.WebKitCSSMatrix()),
		gecko3d = 'MozPerspective' in doc.style,
		opera3d = 'OTransition' in doc.style,
		any3d = !window.L_DISABLE_3D && (ie3d || webkit3d || gecko3d || opera3d);

	var touch = !window.L_NO_TOUCH && (function () {

		var startName = 'ontouchstart';

		// IE10+ (We simulate these into touch* events in L.DomEvent and L.DomEvent.MsTouch) or WebKit, etc.
		if (msTouch || (startName in doc)) {
			return true;
		}

		// Firefox/Gecko
		var div = document.createElement('div'),
			supported = false;

		if (!div.setAttribute) {
			return false;
		}
		div.setAttribute(startName, 'return;');

		if (typeof div[startName] === 'function') {
			supported = true;
		}

		div.removeAttribute(startName);
		div = null;

		return supported;
	}());

	L.Browser = {
		ie6: ie6,
		webkit: webkit,

		android: android,
		android23: android23,

		chrome: chrome,

		ie3d: ie3d,
		webkit3d: webkit3d,
		gecko3d: gecko3d,
		opera3d: opera3d,
		any3d: any3d,

		mobile: mobile,
		mobileWebkit: mobile && webkit,
		mobileWebkit3d: mobile && webkit3d,
		mobileOpera: mobile && opera,

		touch: touch,
		msTouch: msTouch,

		retina: retina
	};

}());
<commit_msg>fix typo in browser detection<commit_after>(function () {

	var ie = !!window.ActiveXObject,
		ie6 = ie && !window.XMLHttpRequest,

		// terrible browser detection to work around Safari / iOS / Android browser bugs
		// see TileLayer._addTile and debug/hacks/jitter.html

		ua = navigator.userAgent.toLowerCase(),
		webkit = ua.indexOf("webkit") !== -1,
		chrome = ua.indexOf("chrome") !== -1,
		android = ua.indexOf("android") !== -1,
		android23 = ua.search("android [23]") !== -1,

		mobile = typeof orientation !== undefined + '',
		msTouch = (window.navigator && window.navigator.msPointerEnabled && window.navigator.msMaxTouchPoints),
		retina = (('devicePixelRatio' in window && window.devicePixelRatio > 1) ||
				('matchMedia' in window && window.matchMedia("(min-resolution:144dpi)").matches)),

		doc = document.documentElement,
		ie3d = ie && ('transition' in doc.style),
		webkit3d = ('WebKitCSSMatrix' in window) && ('m11' in new window.WebKitCSSMatrix()),
		gecko3d = 'MozPerspective' in doc.style,
		opera3d = 'OTransition' in doc.style,
		any3d = !window.L_DISABLE_3D && (ie3d || webkit3d || gecko3d || opera3d);

	var touch = !window.L_NO_TOUCH && (function () {

		var startName = 'ontouchstart';

		// IE10+ (We simulate these into touch* events in L.DomEvent and L.DomEvent.MsTouch) or WebKit, etc.
		if (msTouch || (startName in doc)) {
			return true;
		}

		// Firefox/Gecko
		var div = document.createElement('div'),
			supported = false;

		if (!div.setAttribute) {
			return false;
		}
		div.setAttribute(startName, 'return;');

		if (typeof div[startName] === 'function') {
			supported = true;
		}

		div.removeAttribute(startName);
		div = null;

		return supported;
	}());

	L.Browser = {
		ie6: ie6,
		webkit: webkit,

		android: android,
		android23: android23,

		chrome: chrome,

		ie3d: ie3d,
		webkit3d: webkit3d,
		gecko3d: gecko3d,
		opera3d: opera3d,
		any3d: any3d,

		mobile: mobile,
		mobileWebkit: mobile && webkit,
		mobileWebkit3d: mobile && webkit3d,
		mobileOpera: mobile && window.opera,

		touch: touch,
		msTouch: msTouch,

		retina: retina
	};

}());
<|endoftext|>


<commit_before>"use strict"

var ObjectId = require("mongodb").ObjectId;
require("mongodb-toolkit");
var DLModels = require("dl-models");
var map = DLModels.map;
var Buyer = DLModels.master.Buyer;
var BaseManager = require("module-toolkit").BaseManager;
var i18n = require("dl-i18n");

module.exports = class BuyerManager extends BaseManager {
    constructor(db, user) {
        super(db, user);
        this.collection = this.db.use(map.master.collection.Buyer);
    }

    _getQuery(paging) {
        var _default = {
            _deleted: false
        },
            pagingFilter = paging.filter || {},
            keywordFilter = {},
            query = {};

        if (paging.keyword) {
            var regex = new RegExp(paging.keyword, "i");
            var codeFilter = {
                "code": {
                    "$regex": regex
                }
            };
            var nameFilter = {
                "name": {
                    "$regex": regex
                }
            };
            keywordFilter["$or"] = [codeFilter, nameFilter];
        }
        query["$and"] = [_default, keywordFilter, pagingFilter];
        return query;
    }

    _validate(buyer) {
        var errors = {};
        var valid = buyer;
        // 1. begin: Declare promises.
        var getBuyerPromise = this.collection.singleOrDefault({
            _id: {
                "$ne": new ObjectId(valid._id)
            },
            code: valid.code
        });
        // 2. begin: Validation.
        return Promise.all([getBuyerPromise])
            .then(results => {
                var _module = results[0];

                if (!valid.code || valid.code == "")
                    errors["code"] = i18n.__("Buyer.code.isRequired:%s is required", i18n.__("Buyer.code._:Code")); // "Kode harus diisi";
                else if (_module) {
                    errors["code"] = i18n.__("Buyer.code.isExists:%s is already exists", i18n.__("Buyer.code._:Code")); //"Kode sudah ada";
                }
                if (!valid.name || valid.name == '')
                    errors["name"] = i18n.__("Buyer.name.isRequired:%s is required", i18n.__("Buyer.name._:Name")); //"Nama Harus diisi";

                if (valid.tempo < 0)
                    errors["tempo"] = i18n.__("Buyer.tempo.isNumeric:%s must be 0 or more", i18n.__("Buyer.tempo._:Tempo")); //"Tempo harus lebih atau sama dengan 0";

                if (!valid.country || valid.country == "")
                    errors["country"] = i18n.__("Buyer.country.isRequired:%s is required", i18n.__("Buyer.country._:Country")); // "Silakan pilih salah satu negara";

                // 2c. begin: check if data has any error, reject if it has.
                if (Object.getOwnPropertyNames(errors).length > 0) {
                    var ValidationError = require("module-toolkit").ValidationError;
                    return Promise.reject(new ValidationError("data does not pass validation", errors));
                }
                if (!valid.tempo || valid.tempo == '')
                    valid.tempo = 0;

                valid = new Buyer(valid);
                valid.stamp(this.user.username, "manager");
                return Promise.resolve(valid);
            });
    }

    getBuyer() {
        return new Promise((resolve, reject) => {
            var query = {
                _deleted: false
            };

            this.collection
                .where(query)
                .execute()
                .then(buyers => {
                    resolve(buyers);
                })
                .catch(e => {
                    reject(e);
                });
        });
    }

    insert(dataFile) {
        return new Promise((resolve, reject) => {
            var buyer;
            var countries = ["AFGHANISTAN", "ALBANIA", "ALGERIA", "ANDORRA", "ANGOLA", "ANGUILLA", "ANTIGUA AND BARBUDA", "ARGENTINA", "ARMENIA", "ARUBA", "AUSTRALIA", "AUSTRIA", "AZERBAIJAN", "BAHAMAS", "BAHRAIN", "BANGLADESH", "BARBADOS", "BELARUS", "BELGIUM", "BELIZE", "BENIN", "BERMUDA", "BHUTAN", "BOLIVIA", "BOSNIA AND HERZEGOVINA", "BOTSWANA", "BRAZIL", "BRITISH VIRGIN ISLANDS", "BRUNEI", "BULGARIA", "BURKINA FASO", "BURUNDI", "CAMBODIA", "CAMEROON", "CAPE VERDE", "CAYMAN ISLANDS", "CHAD", "CHILE", "CHINA", "COLOMBIA", "CONGO", "COOK ISLANDS", "COSTA RICA", "COTE D IVOIRE", "CROATIA", "CRUISE SHIP", "CUBA", "CYPRUS", "CZECH REPUBLIC", "DENMARK", "DJIBOUTI", "DOMINICA", "DOMINICAN REPUBLIC", "ECUADOR", "EGYPT", "EL SALVADOR", "EQUATORIAL GUINEA", "ESTONIA", "ETHIOPIA", "FALKLAND ISLANDS", "FAROE ISLANDS", "FIJI", "FINLAND", "FRANCE", "FRENCH POLYNESIA", "FRENCH WEST INDIES", "GABON", "GAMBIA", "GEORGIA", "GERMANY", "GHANA", "GIBRALTAR", "GREECE", "GREENLAND", "GRENADA", "GUAM", "GUATEMALA", "GUERNSEY", "GUINEA", "GUINEA BISSAU", "GUYANA", "HAITI", "HONDURAS", "HONG KONG", "HUNGARY", "ICELAND", "INDIA", "INDONESIA", "IRAN", "IRAQ", "IRELAND", "ISLE OF MAN", "ISRAEL", "ITALY", "JAMAICA", "JAPAN", "JERSEY", "JORDAN", "KAZAKHSTAN", "KENYA", "KUWAIT", "KYRGYZ REPUBLIC", "LAOS", "LATVIA", "LEBANON", "LESOTHO", "LIBERIA", "LIBYA", "LIECHTENSTEIN", "LITHUANIA", "LUXEMBOURG", "MACAU", "MACEDONIA", "MADAGASCAR", "MALAWI", "MALAYSIA", "MALDIVES", "MALI", "MALTA", "MAURITANIA", "MAURITIUS", "MEXICO", "MOLDOVA", "MONACO", "MONGOLIA", "MONTENEGRO", "MONTSERRAT", "MOROCCO", "MOZAMBIQUE", "NAMIBIA", "NEPAL", "NETHERLANDS", "NETHERLANDS ANTILLES", "NEW CALEDONIA", "NEW ZEALAND", "NICARAGUA", "NIGER", "NIGERIA", "NORWAY", "OMAN", "PAKISTAN", "PALESTINE", "PANAMA", "PAPUA NEW GUINEA", "PARAGUAY", "PERU", "PHILIPPINES", "POLAND", "PORTUGAL", "PUERTO RICO", "QATAR", "REUNION", "ROMANIA", "RUSSIA", "RWANDA", "SAINT PIERRE AND MIQUELON", "SAMOA", "SAN MARINO", "SATELLITE", "SAUDI ARABIA", "SENEGAL", "SERBIA", "SEYCHELLES", "SIERRA LEONE", "SINGAPORE", "SLOVAKIA", "SLOVENIA", "SOUTH AFRICA", "SOUTH KOREA", "SPAIN", "SRI LANKA", "ST KITTS AND NEVIS", "ST LUCIA", "ST VINCENT", "ST. LUCIA", "SUDAN", "SURINAME", "SWAZILAND", "SWEDEN", "SWITZERLAND", "SYRIA", "TAIWAN", "TAJIKISTAN", "TANZANIA", "THAILAND", "TIMOR L'ESTE", "TOGO", "TONGA", "TRINIDAD AND TOBAGO", "TUNISIA", "TURKEY", "TURKMENISTAN", "TURKS AND CAICOS", "UGANDA", "UKRAINE", "UNITED ARAB EMIRATES", "UNITED KINGDOM", "URUGUAY", "UZBEKISTAN", "VENEZUELA", "VIETNAM", "VIRGIN ISLANDS (US)", "YEMEN", "ZAMBIA", "ZIMBABWE"];
            this.getBuyer()
                .then(results => {
                    buyer = results.data;
                    var data = [];
                    if (dataFile != "") {
                        for (var i = 1; i < dataFile.length; i++) {
                            data.push({
                                "code": dataFile[i][0].trim(),
                                "name": dataFile[i][1].trim(),
                                "address": dataFile[i][2].trim(),
                                "city": dataFile[i][3].trim(),
                                "country": dataFile[i][4].trim(),
                                "NPWP": dataFile[i][5].trim(),
                                "type": dataFile[i][6].trim(),
                                "contact": dataFile[i][7].trim(),
                                "tempo": dataFile[i][8].trim()
                            });
                        }
                    }
                    var dataError = [], errorMessage;
                    for (var i = 0; i < data.length; i++) {
                        errorMessage = "";
                        if (data[i]["code"] === "" || data[i]["code"] === undefined) {
                            errorMessage = errorMessage + "Kode tidak boleh kosong, ";
                        }
                        if (data[i]["name"] === "" || data[i]["name"] === undefined) {
                            errorMessage = errorMessage + "Nama tidak boleh kosong, ";
                        }
                        if (data[i]["type"] === "" || data[i]["type"] === undefined) {
                            errorMessage = errorMessage + "Jenis Buyer tidak boleh kosong, ";
                        } else {
                            if (data[i]["type"] !== "Lokal") {
                                if (data[i]["type"] !== "Ekspor") {
                                    if (data[i]["type"] !== "Internal") {
                                        errorMessage = errorMessage + "Jenis Buyer harus salah satu dari  Lokal, Ekspor, Internal ";
                                    }
                                }
                            }
                        }
                        if (data[i]["country"] === "" || data[i]["country"] === undefined) {
                            errorMessage = errorMessage + "Negara tidak boleh kosong, ";
                        } else {
                            if (countries.indexOf(data[i]["country"]) == -1) {
                                errorMessage = errorMessage + "Negara tidak terdaftar di list Negara,";
                            }
                        }
                        for (var j = 0; j < buyer.length; j++) {
                            if (buyer[j]["code"] === data[i]["code"]) {
                                errorMessage = errorMessage + "Kode tidak boleh duplikat";
                            }
                        }

                        if (errorMessage !== "") {
                            dataError.push({
                                "code": data[i]["code"],
                                "name": data[i]["name"],
                                "address": data[i]["address"],
                                "city": data[i]["city"],
                                "country": data[i]["country"],
                                "NPWP": data[i]["NPWP"],
                                "type": data[i]["type"],
                                "contact": data[i]["contact"],
                                "tempo": data[i]["tempo"],
                                "Error": errorMessage
                            });
                        }
                    }
                    if (dataError.length === 0) {
                        var newBuyer = [];
                        for (var i = 0; i < data.length; i++) {
                            var valid = new Buyer(data[i]);
                            valid.stamp(this.user.username, 'manager');
                            this.collection.insert(valid)
                                .then(id => {
                                    this.getSingleById(id)
                                        .then(resultItem => {
                                            newBuyer.push(resultItem)
                                            resolve(newBuyer);
                                        })
                                        .catch(e => {
                                            reject(e);
                                        });
                                })
                                .catch(e => {
                                    reject(e);
                                });
                        }

                    } else {
                        resolve(dataError);
                    }
                })
        })
    }

    _createIndexes() {
        var dateIndex = {
            name: `ix_${map.master.collection.Buyer}__updatedDate`,
            key: {
                _updatedDate: -1
            }
        };

        var codeIndex = {
            name: `ix_${map.master.collection.Buyer}_code`,
            key: {
                code: 1
            },
            unique: true
        };

        return this.collection.createIndexes([dateIndex, codeIndex]);
    }
}
<commit_msg>update buyer<commit_after>"use strict"

var ObjectId = require("mongodb").ObjectId;
require("mongodb-toolkit");
var DLModels = require("dl-models");
var map = DLModels.map;
var Buyer = DLModels.master.Buyer;
var BaseManager = require("module-toolkit").BaseManager;
var i18n = require("dl-i18n");

module.exports = class BuyerManager extends BaseManager {
    constructor(db, user) {
        super(db, user);
        this.collection = this.db.use(map.master.collection.Buyer);
    }

    _getQuery(paging) {
        var _default = {
            _deleted: false
        },
            pagingFilter = paging.filter || {},
            keywordFilter = {},
            query = {};

        if (paging.keyword) {
            var regex = new RegExp(paging.keyword, "i");
            var codeFilter = {
                "code": {
                    "$regex": regex
                }
            };
            var nameFilter = {
                "name": {
                    "$regex": regex
                }
            };
            keywordFilter["$or"] = [codeFilter, nameFilter];
        }
        query["$and"] = [_default, keywordFilter, pagingFilter];
        return query;
    }

    _validate(buyer) {
        var errors = {};
        var valid = buyer;
        // 1. begin: Declare promises.
        var getBuyerPromise = this.collection.singleOrDefault({
            _id: {
                "$ne": new ObjectId(valid._id)
            },
            code: valid.code
        });
        // 2. begin: Validation.
        return Promise.all([getBuyerPromise])
            .then(results => {
                var _module = results[0];

                if (!valid.code || valid.code == "")
                    errors["code"] = i18n.__("Buyer.code.isRequired:%s is required", i18n.__("Buyer.code._:Code")); // "Kode harus diisi";
                else if (_module) {
                    errors["code"] = i18n.__("Buyer.code.isExists:%s is already exists", i18n.__("Buyer.code._:Code")); //"Kode sudah ada";
                }
                if (!valid.name || valid.name == '')
                    errors["name"] = i18n.__("Buyer.name.isRequired:%s is required", i18n.__("Buyer.name._:Name")); //"Nama Harus diisi";

                if (valid.tempo < 0)
                    errors["tempo"] = i18n.__("Buyer.tempo.isNumeric:%s must be 0 or more", i18n.__("Buyer.tempo._:Tempo")); //"Tempo harus lebih atau sama dengan 0";

                if (!valid.country || valid.country == "")
                    errors["country"] = i18n.__("Buyer.country.isRequired:%s is required", i18n.__("Buyer.country._:Country")); // "Silakan pilih salah satu negara";

                // 2c. begin: check if data has any error, reject if it has.
                if (Object.getOwnPropertyNames(errors).length > 0) {
                    var ValidationError = require("module-toolkit").ValidationError;
                    return Promise.reject(new ValidationError("data does not pass validation", errors));
                }
                if (!valid.tempo || valid.tempo == '')
                    valid.tempo = 0;

                valid = new Buyer(valid);
                valid.stamp(this.user.username, "manager");
                return Promise.resolve(valid);
            });
    }

    getBuyer() {
        return new Promise((resolve, reject) => {
            var query = {
                _deleted: false
            };

            this.collection
                .where(query)
                .execute()
                .then(buyers => {
                    resolve(buyers);
                })
                .catch(e => {
                    reject(e);
                });
        });
    }

    insert(dataFile) {
        return new Promise((resolve, reject) => {
            var buyer;
            var countries = ["AFGHANISTAN", "ALBANIA", "ALGERIA", "ANDORRA", "ANGOLA", "ANGUILLA", "ANTIGUA AND BARBUDA", "ARGENTINA", "ARMENIA", "ARUBA", "AUSTRALIA", "AUSTRIA", "AZERBAIJAN", "BAHAMAS", "BAHRAIN", "BANGLADESH", "BARBADOS", "BELARUS", "BELGIUM", "BELIZE", "BENIN", "BERMUDA", "BHUTAN", "BOLIVIA", "BOSNIA AND HERZEGOVINA", "BOTSWANA", "BRAZIL", "BRITISH VIRGIN ISLANDS", "BRUNEI", "BULGARIA", "BURKINA FASO", "BURUNDI", "CAMBODIA", "CAMEROON", "CAPE VERDE", "CAYMAN ISLANDS", "CHAD", "CHILE", "CHINA", "COLOMBIA", "CONGO", "COOK ISLANDS", "COSTA RICA", "COTE D IVOIRE", "CROATIA", "CRUISE SHIP", "CUBA", "CYPRUS", "CZECH REPUBLIC", "DENMARK", "DJIBOUTI", "DOMINICA", "DOMINICAN REPUBLIC", "ECUADOR", "EGYPT", "EL SALVADOR", "EQUATORIAL GUINEA", "ESTONIA", "ETHIOPIA", "FALKLAND ISLANDS", "FAROE ISLANDS", "FIJI", "FINLAND", "FRANCE", "FRENCH POLYNESIA", "FRENCH WEST INDIES", "GABON", "GAMBIA", "GEORGIA", "GERMANY", "GHANA", "GIBRALTAR", "GREECE", "GREENLAND", "GRENADA", "GUAM", "GUATEMALA", "GUERNSEY", "GUINEA", "GUINEA BISSAU", "GUYANA", "HAITI", "HONDURAS", "HONG KONG", "HUNGARY", "ICELAND", "INDIA", "INDONESIA", "IRAN", "IRAQ", "IRELAND", "ISLE OF MAN", "ISRAEL", "ITALY", "JAMAICA", "JAPAN", "JERSEY", "JORDAN", "KAZAKHSTAN", "KENYA", "KUWAIT", "KYRGYZ REPUBLIC", "LAOS", "LATVIA", "LEBANON", "LESOTHO", "LIBERIA", "LIBYA", "LIECHTENSTEIN", "LITHUANIA", "LUXEMBOURG", "MACAU", "MACEDONIA", "MADAGASCAR", "MALAWI", "MALAYSIA", "MALDIVES", "MALI", "MALTA", "MAURITANIA", "MAURITIUS", "MEXICO", "MOLDOVA", "MONACO", "MONGOLIA", "MONTENEGRO", "MONTSERRAT", "MOROCCO", "MOZAMBIQUE", "NAMIBIA", "NEPAL", "NETHERLANDS", "NETHERLANDS ANTILLES", "NEW CALEDONIA", "NEW ZEALAND", "NICARAGUA", "NIGER", "NIGERIA", "NORWAY", "OMAN", "PAKISTAN", "PALESTINE", "PANAMA", "PAPUA NEW GUINEA", "PARAGUAY", "PERU", "PHILIPPINES", "POLAND", "PORTUGAL", "PUERTO RICO", "QATAR", "REUNION", "ROMANIA", "RUSSIA", "RWANDA", "SAINT PIERRE AND MIQUELON", "SAMOA", "SAN MARINO", "SATELLITE", "SAUDI ARABIA", "SENEGAL", "SERBIA", "SEYCHELLES", "SIERRA LEONE", "SINGAPORE", "SLOVAKIA", "SLOVENIA", "SOUTH AFRICA", "SOUTH KOREA", "SPAIN", "SRI LANKA", "ST KITTS AND NEVIS", "ST LUCIA", "ST VINCENT", "ST. LUCIA", "SUDAN", "SURINAME", "SWAZILAND", "SWEDEN", "SWITZERLAND", "SYRIA", "TAIWAN", "TAJIKISTAN", "TANZANIA", "THAILAND", "TIMOR L'ESTE", "TOGO", "TONGA", "TRINIDAD AND TOBAGO", "TUNISIA", "TURKEY", "TURKMENISTAN", "TURKS AND CAICOS", "UGANDA", "UKRAINE", "UNITED ARAB EMIRATES", "UNITED KINGDOM", "URUGUAY", "UZBEKISTAN", "VENEZUELA", "VIETNAM", "VIRGIN ISLANDS (US)", "YEMEN", "ZAMBIA", "ZIMBABWE"];
            this.getBuyer()
                .then(results => {
                    buyer = results.data;
                    var data = [];
                    if (dataFile != "") {
                        for (var i = 1; i < dataFile.length; i++) {
                            data.push({
                                "code": dataFile[i][0].trim(),
                                "name": dataFile[i][1].trim(),
                                "address": dataFile[i][2].trim(),
                                "city": dataFile[i][3].trim(),
                                "country": dataFile[i][4].trim(),
                                "NPWP": dataFile[i][5].trim(),
                                "type": dataFile[i][6].trim(),
                                "contact": dataFile[i][7].trim(),
                                "tempo": dataFile[i][8].trim()
                            });
                        }
                    }
                    var dataError = [], errorMessage;
                    for (var i = 0; i < data.length; i++) {
                        errorMessage = "";
                        if (data[i]["code"] === "" || data[i]["code"] === undefined) {
                            errorMessage = errorMessage + "Kode tidak boleh kosong, ";
                        }
                        if (data[i]["name"] === "" || data[i]["name"] === undefined) {
                            errorMessage = errorMessage + "Nama tidak boleh kosong, ";
                        }
                        if (data[i]["type"] === "" || data[i]["type"] === undefined) {
                            errorMessage = errorMessage + "Jenis Buyer tidak boleh kosong, ";
                        } else {
                            if (data[i]["type"] !== "Lokal") {
                                if (data[i]["type"] !== "Ekspor") {
                                    if (data[i]["type"] !== "Internal") {
                                        errorMessage = errorMessage + "Jenis Buyer harus salah satu dari  Lokal, Ekspor, Internal ";
                                    }
                                }
                            }
                        }
                        if (data[i]["country"] === "" || data[i]["country"] === undefined) {
                            errorMessage = errorMessage + "Negara tidak boleh kosong, ";
                        } else {
                            if (countries.indexOf(data[i]["country"].toUpperCase()) == -1) {
                                errorMessage = errorMessage + "Negara tidak terdaftar di list Negara,";
                            }
                        }
                        for (var j = 0; j < buyer.length; j++) {
                            if (buyer[j]["code"] === data[i]["code"]) {
                                errorMessage = errorMessage + "Kode tidak boleh duplikat";
                            }
                        }

                        if (errorMessage !== "") {
                            dataError.push({
                                "code": data[i]["code"],
                                "name": data[i]["name"],
                                "address": data[i]["address"],
                                "city": data[i]["city"],
                                "country": data[i]["country"],
                                "NPWP": data[i]["NPWP"],
                                "type": data[i]["type"],
                                "contact": data[i]["contact"],
                                "tempo": data[i]["tempo"],
                                "Error": errorMessage
                            });
                        }
                    }
                    if (dataError.length === 0) {
                        var newBuyer = [];
                        for (var i = 0; i < data.length; i++) {
                            var valid = new Buyer(data[i]);
                            valid.stamp(this.user.username, 'manager');
                            this.collection.insert(valid)
                                .then(id => {
                                    this.getSingleById(id)
                                        .then(resultItem => {
                                            newBuyer.push(resultItem)
                                            resolve(newBuyer);
                                        })
                                        .catch(e => {
                                            reject(e);
                                        });
                                })
                                .catch(e => {
                                    reject(e);
                                });
                        }

                    } else {
                        resolve(dataError);
                    }
                })
        })
    }

    _createIndexes() {
        var dateIndex = {
            name: `ix_${map.master.collection.Buyer}__updatedDate`,
            key: {
                _updatedDate: -1
            }
        };

        var codeIndex = {
            name: `ix_${map.master.collection.Buyer}_code`,
            key: {
                code: 1
            },
            unique: true
        };

        return this.collection.createIndexes([dateIndex, codeIndex]);
    }
}
<|endoftext|>


<commit_before>import CorridorSprite from './CorridorSprite';
const Directions = ["vertical", "horizontal"];
const WallSize = 16;

class Corridor extends Phaser.Group {

  constructor(game, parent, x, y, width, height, direction) {
    super(game, parent, "corridor", true, true, Phaser.Physics.ARCADE);
    if(!Directions.includes(direction)) {
      console.error(`Corridor:constructor : ${direction} is a not a value possible [${Directions}]`);
    }
    this.addWalls(game, x, y, width, height, direction);
  }

  addWalls(game, x,y, width, height, direction) {
    if(direction === "vertical") {
      this.addVerticalWall(game, x, y, width, height);
    } else {
      this.addHorizontalWall(game, x, y, width, height);
    }
  }

  addVerticalWall(game, x, y, width, height) {
    const corridorSprite = new CorridorSprite(game, x, y, width, height);
     for(let i = y; i < y + height; i += WallSize) {
      const upWall = game.add.sprite(x - WallSize, i, 'Wall');
      const bottomWall = game.add.sprite(x + width, i, 'Wall');
      this.add(upWall);
      this.add(bottomWall);
    }
    this.add(corridorSprite);
  }

  addHorizontalWall(game, x, y, width, height) {
    const corridorSprite = new CorridorSprite(game, x, y, width, height);
    for(let i = x; i < x + width; i += WallSize) {
      const upWall = game.add.sprite(i, y - WallSize, 'Wall');
      const bottomWall = game.add.sprite(i, y + height, 'Wall');
      this.add(upWall);
      this.add(bottomWall);
    }
    this.add(corridorSprite);
  }

  getCorridorSprite() {
    const corridorSprite = this.children.find(child => {return child.name === "corridorSprite"; });
    if(!corridorSprite) {
      //to avoid undefined attribute
      return {x: -1, y: -1, width:-1, height:-1};
    }
    return corridorSprite;
  }
}

export default Corridor;<commit_msg>add tools method to build walls<commit_after>import CorridorSprite from './CorridorSprite';
const Directions = ["vertical", "horizontal"];
const WallSize = 16;

class Corridor extends Phaser.Group {

  constructor(game, parent, x, y, width, height, direction) {
    super(game, parent, "corridor", true, true, Phaser.Physics.ARCADE);
    if(!Directions.includes(direction)) {
      console.error(`Corridor:constructor : ${direction} is a not a value possible [${Directions}]`);
    }
    this.addWalls(game, x, y, width, height, direction);
  }

  addWalls(game, x,y, width, height, direction) {
    if(direction === "vertical") {
      this.addVerticalWall(game, x, y, width, height);
    } else {
      this.addHorizontalWall(game, x, y, width, height);
    }
  }

  addVerticalWall(game, x, y, width, height) {
    const corridorSprite = new CorridorSprite(game, x, y, width, height);
     for(let i = y; i < y + height; i += WallSize) {
      let leftWall = this.addWall(game, x - WallSize, i);
      let rightWall = this.addWall(game, x + width, i);
      this.add(leftWall);
      this.add(rightWall);
    }
    this.add(corridorSprite);
  }

  addHorizontalWall(game, x, y, width, height) {
    const corridorSprite = new CorridorSprite(game, x, y, width, height);
    for(let i = x; i < x + width; i += WallSize) {
      let upWall = this.addWall(game, i, y - WallSize);
      let bottomWall = this.addWall(game, i, y + height);
      this.add(upWall);
      this.add(bottomWall);
    }
    this.add(corridorSprite);
  }

  addWall(game, x, y) {
    let wall = game.add.sprite(x, y, 'Wall');
    wall.name = "colissionWall";
    game.physics.enable(wall, Phaser.Physics.ARCADE);
    wall.body.immovable = true;
    return wall;
  }

  //remove useless return in anonymous function
  getCorridorSprite() {
    const corridorSprite = this.children.find(child => {return child.name === "corridorSprite"; });
    if(!corridorSprite) {
      //to avoid undefined attribute
      return {x: -1, y: -1, width:-1, height:-1};
    }
    return corridorSprite;
  }

  walls() {
    return this.children.filter(child => {return child.name == "colissionWall"; });
  }

}

export default Corridor;<|endoftext|>


<commit_before>import { call, put, select, takeLatest } from 'redux-saga/effects';
import { getLayers } from '../../ducks/panel-layers/map-panel-layers';
import { getStraatbeeldYear } from '../../../shared/ducks/straatbeeld/straatbeeld';
import { SET_MAP_CLICK_LOCATION, UPDATE_MAP } from '../../ducks/map/map';
import { getMapZoom } from '../../ducks/map/map-selectors';
import { REQUEST_GEOSEARCH, REQUEST_NEAREST_DETAILS } from '../geosearch/geosearch';
import {
  getSelectionType,
  SELECTION_TYPE,
  setSelection
} from '../../../shared/ducks/selection/selection';
import { getImageDataByLocation } from '../../../shared/services/straatbeeld-api/straatbeeld-api';
import { toPanorama } from '../../../app/routes';

function getHeadingDegrees([x1, y1], [x2, y2]) {
  return (Math.atan2(y2 - y1, x2 - x1) * 180) / Math.PI;
}

const latitudeLongitudeToArray = (location) => [location.latitude, location.longitude];

export function* switchClickAction(action) {
  const zoom = yield select(getMapZoom);
  const layers = yield select(getLayers);
  const selectionType = yield select(getSelectionType);

  if (selectionType === SELECTION_TYPE.PANORAMA) {
    const year = yield select(getStraatbeeldYear);
    const { location } = action.payload;
    const locationArray = latitudeLongitudeToArray(location);
    const imageData = yield call(getImageDataByLocation, locationArray, year);

      // The view direction should be towards the location that the user clicked
    const heading = getHeadingDegrees(imageData.location, locationArray);

    yield put(toPanorama(imageData.id, heading));
  } else {
    if (layers.length) {
      yield put({
        type: REQUEST_NEAREST_DETAILS,
        payload: {
          location: action.location,
          layers,
          zoom
        }
      });
    } else {
      yield put(setSelection(SELECTION_TYPE.POINT, action.location));
      yield put({
        type: REQUEST_GEOSEARCH,
        payload: [action.location.latitude, action.location.longitude]
      });
    }

    yield put({
      type: UPDATE_MAP,
      payload: {
        query: {
          selectedLocation: `${action.location.latitude},${action.location.longitude}`
        }
      }
    });
  }
}

export default function* watchMapClick() {
  yield takeLatest(SET_MAP_CLICK_LOCATION, switchClickAction);
}
<commit_msg>SET_MAP_CLICK_ACTION flux standard action<commit_after>import { call, put, select, takeLatest } from 'redux-saga/effects';
import { getLayers } from '../../ducks/panel-layers/map-panel-layers';
import { getStraatbeeldYear } from '../../../shared/ducks/straatbeeld/straatbeeld';
import { SET_MAP_CLICK_LOCATION, UPDATE_MAP } from '../../ducks/map/map';
import { getMapZoom } from '../../ducks/map/map-selectors';
import { REQUEST_GEOSEARCH, REQUEST_NEAREST_DETAILS } from '../geosearch/geosearch';
import {
  getSelectionType,
  SELECTION_TYPE,
  setSelection
} from '../../../shared/ducks/selection/selection';
import { getImageDataByLocation } from '../../../shared/services/straatbeeld-api/straatbeeld-api';
import { toPanorama } from '../../../app/routes';

function getHeadingDegrees([x1, y1], [x2, y2]) {
  return (Math.atan2(y2 - y1, x2 - x1) * 180) / Math.PI;
}

const latitudeLongitudeToArray = (location) => [location.latitude, location.longitude];

export function* switchClickAction(action) {
  const zoom = yield select(getMapZoom);
  const layers = yield select(getLayers);
  const selectionType = yield select(getSelectionType);
  const { location } = action.payload;

  if (selectionType === SELECTION_TYPE.PANORAMA) {
    const year = yield select(getStraatbeeldYear);
    const locationArray = latitudeLongitudeToArray(location);
    const imageData = yield call(getImageDataByLocation, locationArray, year);

      // The view direction should be towards the location that the user clicked
    const heading = getHeadingDegrees(imageData.location, locationArray);

    yield put(toPanorama(imageData.id, heading));
  } else {
    if (layers.length) {
      yield put({
        type: REQUEST_NEAREST_DETAILS,
        payload: {
          location: location,
          layers,
          zoom
        }
      });
    } else {
      yield put(setSelection(SELECTION_TYPE.POINT, location));
      yield put({
        type: REQUEST_GEOSEARCH,
        payload: [location.latitude, location.longitude]
      });
    }

    yield put({
      type: UPDATE_MAP,
      payload: {
        query: {
          selectedLocation: `${location.latitude},${location.longitude}`
        }
      }
    });
  }
}

export default function* watchMapClick() {
  yield takeLatest(SET_MAP_CLICK_LOCATION, switchClickAction);
}
<|endoftext|>


<commit_before>"use strict";

function addTimeoutService(module) {
    module.factory("$timeout", ["$async", "$promise"], function($async, $promise) {
        var deferreds = {};

        var $timeout = function(timeMs) {
            var deferred = $promise.defer();

            var id = $async(function() {
                delete deferreds[id];
                deferred.resolve(id);
            }, timeMs);

            deferred.promise._$timeoutId = id;
            deferreds[id] = deferred;

            return deferred.promise;
        };

        return extend($timeout, {
            cancel: function(promise) {
                if (!promise || !deferreds.hasOwnProperty(promise._$timeoutId)) {
                    return;
                }

                var id = promise._$timeoutId;

                $async.cancel(id);

                deferreds[id].reject("canceled");
                delete deferreds[id];
            }
        });
    });
}<commit_msg>no need to resolve with ID value<commit_after>"use strict";

function addTimeoutService(module) {
    module.factory("$timeout", ["$async", "$promise"], function($async, $promise) {
        var deferreds = {};

        var $timeout = function(timeMs) {
            var deferred = $promise.defer();

            var id = $async(function() {
                delete deferreds[id];
                deferred.resolve();
            }, timeMs);

            deferred.promise._$timeoutId = id;
            deferreds[id] = deferred;

            return deferred.promise;
        };

        return extend($timeout, {
            cancel: function(promise) {
                if (!promise || !deferreds.hasOwnProperty(promise._$timeoutId)) {
                    return;
                }

                var id = promise._$timeoutId;

                $async.cancel(id);

                deferreds[id].reject("canceled");
                delete deferreds[id];
            }
        });
    });
}<|endoftext|>


<commit_before>/**
 * Copyright 2015 CANAL+ Group
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

const { Observable } = require("rxjs/Observable");
const { BehaviorSubject } = require("rxjs/BehaviorSubject");
const { BufferedRanges } = require("./ranges");

// time changes interval in milliseconds
const TIMINGS_SAMPLING_INTERVAL = 1000;

// time in seconds protecting live buffer to prevent ahead of time
// buffering
const LIVE_PROTECTION = 10;

// stall gap in seconds
const STALL_GAP = 0.5;
const RESUME_GAP = 5;

// seek gap in seconds
const SEEK_GAP = 2;

// waiting time differs between a "seeking" stall and
// a buffering stall
function resumeGap(stalled) {
  return (stalled.name == "seeking")
    ? STALL_GAP
    : RESUME_GAP;
}

function isEnding(gap, range, duration) {
  if (range) {
    return (duration - (gap + range.end)) <= STALL_GAP;
  } else {
    return false;
  }
}

class Timings {
  constructor(ts,
              buffered,
              duration,
              gap,
              name,
              playback,
              range,
              readyState,
              stalled,
              paused) {
    this.ts = ts;
    this.buffered = buffered;
    this.duration = duration;
    this.gap = gap;
    this.name = name;
    this.playback = playback;
    this.range = range;
    this.readyState = readyState;
    this.stalled = stalled;
    this.paused = paused;
  }

  clone() {
    return new Timings(this.ts,
                       this.buffered,
                       this.duration,
                       this.gap,
                       this.name,
                       this.playback,
                       this.range,
                       this.readyState,
                       this.stalled,
                       this.paused);
  }
}

function getEmptyTimings() {
  return new Timings(0,
                     new BufferedRanges(),
                     0,
                     Infinity,
                     "timeupdate",
                     1,
                     null,
                     0,
                     null,
                     null);
}

function getTimings(video, name) {
  const ts = video.currentTime;
  const paused = video.paused;
  const buffered = new BufferedRanges(video.buffered);
  return new Timings(ts,
                     buffered,
                     video.duration,
                     buffered.getGap(ts),
                     name,
                     video.playbackRate,
                     buffered.getRange(ts),
                     video.readyState,
                     null,
                     paused);
}

/**
 * Timings observable.
 *
 * This streams samples snapshots of player's current state:
 *   * time position
 *   * playback rate
 *   * current buffered range
 *   * gap with current buffered range ending
 *   * video duration
 *
 * In addition to sampling, this stream also reacts to "seeking" and "play"
 * events.
 *
 * Observable is shared for performance reason: reduces the number of event
 * listeners and intervals/timeouts but also limit access to <video>
 * properties and gap calculations.
 *
 * The sampling is manual instead of based on "timeupdate" to reduce the
 * number of events.
 */
function timingsSampler(video) {

  function scanTimingsSamples(prevTimings, timingEventType) {
    const currentTimings = getTimings(video, timingEventType);

    const wasStalled = prevTimings.stalled;
    const currentGap = currentTimings.gap;
    const ending = isEnding(currentGap, currentTimings.range, currentTimings.duration);

    const mayStall = (
      timingEventType != "loadedmetadata" &&
      !wasStalled &&
      !ending
    );

    const shouldStall = (
      mayStall &&
      (currentGap <= STALL_GAP || currentGap === Infinity)
    );

    const hasUnexpectedlyStalled = (
      mayStall &&
      timingEventType == "timeupdate" &&
      !currentTimings.paused && currentTimings.ts !== 0 && currentTimings.ts === prevTimings.ts
    );

    let stalled;
    if (shouldStall || hasUnexpectedlyStalled) {
      stalled = {
        name: currentTimings.name,
        playback: currentTimings.playback,
      };
    }
    else if (wasStalled && currentGap < Infinity && (currentGap > resumeGap(wasStalled) || ending)) {
      stalled = null;
    }
    else if (timingEventType === "canplay") {
      stalled = null;
    }
    else {
      stalled = wasStalled;
    }

    currentTimings.stalled = stalled;
    return currentTimings;
  }

  return Observable.create((obs) => {
    let prevTimings = getTimings(video, "init");

    function emitSample(evt) {
      const timingEventType = evt && evt.type || "timeupdate";
      prevTimings = scanTimingsSamples(prevTimings, timingEventType);
      obs.next(prevTimings);
    }

    const samplerInterval = setInterval(emitSample, TIMINGS_SAMPLING_INTERVAL);

    video.addEventListener("canplay", emitSample);
    video.addEventListener("play", emitSample);
    video.addEventListener("progress", emitSample);
    video.addEventListener("seeking", emitSample);
    video.addEventListener("seeked", emitSample);
    video.addEventListener("loadedmetadata", emitSample);

    obs.next(prevTimings);

    return () => {
      clearInterval(samplerInterval);

      video.removeEventListener("canplay", emitSample);
      video.removeEventListener("play", emitSample);
      video.removeEventListener("progress", emitSample);
      video.removeEventListener("seeking", emitSample);
      video.removeEventListener("seeked", emitSample);
      video.removeEventListener("loadedmetadata", emitSample);
    };
  })
    .multicast(() => new BehaviorSubject({ name: "init", stalled: null }))
    .refCount();
}

function seekingsSampler(timingsSampling) {
  return timingsSampling
    .filter((t) => (
      t.name == "seeking" &&
      ( t.gap === Infinity ||
        t.gap < -SEEK_GAP )
    ))
    // skip the first seeking event generated by the set of the
    // initial seeking time in the video
    .skip(1)
    .startWith(true);
}

function toWallClockTime(ts, manifest) {
  return new Date((ts + manifest.availabilityStartTime) * 1000);
}

function fromWallClockTime(timeInMs, manifest) {
  return normalizeWallClockTime(timeInMs, manifest) / 1000 - manifest.availabilityStartTime;
}

function normalizeWallClockTime(timeInMs, manifest) {
  const {
    suggestedPresentationDelay,
    presentationLiveGap,
    timeShiftBufferDepth,
  } = manifest;

  if (typeof timeInMs != "number") {
    timeInMs = timeInMs.getTime();
  }

  const now = Date.now();
  const max = now - (presentationLiveGap + suggestedPresentationDelay) * 1000;
  const min = now - (timeShiftBufferDepth) * 1000;
  return Math.max(Math.min(timeInMs, max), min);
}

function getLiveGap(ts, manifest) {
  if (!manifest.isLive) {
    return Infinity;
  }

  const {
    availabilityStartTime,
    presentationLiveGap,
  } = manifest;

  const liveGap = (Date.now() / 1000 - ts);
  return (liveGap - (availabilityStartTime + presentationLiveGap + LIVE_PROTECTION));
}

module.exports = {
  getEmptyTimings,
  getTimings,
  timingsSampler,
  seekingsSampler,
  getLiveGap,
  toWallClockTime,
  fromWallClockTime,
};
<commit_msg>timings: fix unexpected stall condition<commit_after>/**
 * Copyright 2015 CANAL+ Group
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

const { Observable } = require("rxjs/Observable");
const { BehaviorSubject } = require("rxjs/BehaviorSubject");
const { BufferedRanges } = require("./ranges");

// time changes interval in milliseconds
const TIMINGS_SAMPLING_INTERVAL = 1000;

// time in seconds protecting live buffer to prevent ahead of time
// buffering
const LIVE_PROTECTION = 10;

// stall gap in seconds
const STALL_GAP = 0.5;
const RESUME_GAP = 5;

// seek gap in seconds
const SEEK_GAP = 2;

// waiting time differs between a "seeking" stall and
// a buffering stall
function resumeGap(stalled) {
  return (stalled.name == "seeking")
    ? STALL_GAP
    : RESUME_GAP;
}

function isEnding(gap, range, duration) {
  if (range) {
    return (duration - (gap + range.end)) <= STALL_GAP;
  } else {
    return false;
  }
}

class Timings {
  constructor(ts,
              buffered,
              duration,
              gap,
              name,
              playback,
              range,
              readyState,
              stalled,
              paused) {
    this.ts = ts;
    this.buffered = buffered;
    this.duration = duration;
    this.gap = gap;
    this.name = name;
    this.playback = playback;
    this.range = range;
    this.readyState = readyState;
    this.stalled = stalled;
    this.paused = paused;
  }

  clone() {
    return new Timings(this.ts,
                       this.buffered,
                       this.duration,
                       this.gap,
                       this.name,
                       this.playback,
                       this.range,
                       this.readyState,
                       this.stalled,
                       this.paused);
  }
}

function getEmptyTimings() {
  return new Timings(0,
                     new BufferedRanges(),
                     0,
                     Infinity,
                     "timeupdate",
                     1,
                     null,
                     0,
                     null,
                     null);
}

function getTimings(video, name) {
  const ts = video.currentTime;
  const paused = video.paused;
  const buffered = new BufferedRanges(video.buffered);
  return new Timings(ts,
                     buffered,
                     video.duration,
                     buffered.getGap(ts),
                     name,
                     video.playbackRate,
                     buffered.getRange(ts),
                     video.readyState,
                     null,
                     paused);
}

/**
 * Timings observable.
 *
 * This streams samples snapshots of player's current state:
 *   * time position
 *   * playback rate
 *   * current buffered range
 *   * gap with current buffered range ending
 *   * video duration
 *
 * In addition to sampling, this stream also reacts to "seeking" and "play"
 * events.
 *
 * Observable is shared for performance reason: reduces the number of event
 * listeners and intervals/timeouts but also limit access to <video>
 * properties and gap calculations.
 *
 * The sampling is manual instead of based on "timeupdate" to reduce the
 * number of events.
 */
function timingsSampler(video) {

  function scanTimingsSamples(prevTimings, timingEventType) {
    const currentTimings = getTimings(video, timingEventType);

    const {
      name: currentName,
      gap: currentGap,
      ts: currentTs,
      range,
      duration,
      paused,
      playback,
    } = currentTimings;

    const wasStalled = prevTimings.stalled;
    const ending = isEnding(currentGap, range, duration);

    const mayStall = (
      currentName != "loadedmetadata" &&
      !wasStalled &&
      !ending
    );

    const shouldStall = (
      mayStall &&
      (currentGap <= STALL_GAP || currentGap === Infinity)
    );

    // If between two timeupdate events the currentTime (ts) has not
    // changed while not in pause and not already stalled, we consider
    // that we have unexpectedly stall the player.
    const hasUnexpectedlyStalled = (
      mayStall && !paused && currentTs > 0 &&
      currentName == "timeupdate" && prevTimings.name == "timeupdate" &&
      currentTs === prevTimings.ts
    );

    let stalled;
    if (shouldStall || hasUnexpectedlyStalled) {
      stalled = { name: currentName, playback };
    }
    else if (wasStalled && currentGap < Infinity && (currentGap > resumeGap(wasStalled) || ending)) {
      stalled = null;
    }
    else if (currentName === "canplay") {
      stalled = null;
    }
    else {
      stalled = wasStalled;
    }

    currentTimings.stalled = stalled;
    return currentTimings;
  }

  return Observable.create((obs) => {
    let prevTimings = getTimings(video, "init");

    function emitSample(evt) {
      const timingEventType = evt && evt.type || "timeupdate";
      prevTimings = scanTimingsSamples(prevTimings, timingEventType);
      obs.next(prevTimings);
    }

    const samplerInterval = setInterval(emitSample, TIMINGS_SAMPLING_INTERVAL);

    video.addEventListener("canplay", emitSample);
    video.addEventListener("play", emitSample);
    video.addEventListener("progress", emitSample);
    video.addEventListener("seeking", emitSample);
    video.addEventListener("seeked", emitSample);
    video.addEventListener("loadedmetadata", emitSample);

    obs.next(prevTimings);

    return () => {
      clearInterval(samplerInterval);

      video.removeEventListener("canplay", emitSample);
      video.removeEventListener("play", emitSample);
      video.removeEventListener("progress", emitSample);
      video.removeEventListener("seeking", emitSample);
      video.removeEventListener("seeked", emitSample);
      video.removeEventListener("loadedmetadata", emitSample);
    };
  })
    .multicast(() => new BehaviorSubject({ name: "init", stalled: null }))
    .refCount();
}

function seekingsSampler(timingsSampling) {
  return timingsSampling
    .filter((t) => (
      t.name == "seeking" &&
      ( t.gap === Infinity ||
        t.gap < -SEEK_GAP )
    ))
    // skip the first seeking event generated by the set of the
    // initial seeking time in the video
    .skip(1)
    .startWith(true);
}

function toWallClockTime(ts, manifest) {
  return new Date((ts + manifest.availabilityStartTime) * 1000);
}

function fromWallClockTime(timeInMs, manifest) {
  return normalizeWallClockTime(timeInMs, manifest) / 1000 - manifest.availabilityStartTime;
}

function normalizeWallClockTime(timeInMs, manifest) {
  const {
    suggestedPresentationDelay,
    presentationLiveGap,
    timeShiftBufferDepth,
  } = manifest;

  if (typeof timeInMs != "number") {
    timeInMs = timeInMs.getTime();
  }

  const now = Date.now();
  const max = now - (presentationLiveGap + suggestedPresentationDelay) * 1000;
  const min = now - (timeShiftBufferDepth) * 1000;
  return Math.max(Math.min(timeInMs, max), min);
}

function getLiveGap(ts, manifest) {
  if (!manifest.isLive) {
    return Infinity;
  }

  const {
    availabilityStartTime,
    presentationLiveGap,
  } = manifest;

  const liveGap = (Date.now() / 1000 - ts);
  return (liveGap - (availabilityStartTime + presentationLiveGap + LIVE_PROTECTION));
}

module.exports = {
  getEmptyTimings,
  getTimings,
  timingsSampler,
  seekingsSampler,
  getLiveGap,
  toWallClockTime,
  fromWallClockTime,
};
<|endoftext|>


<commit_before>(function () {

  /**
   * Override _setObjectScale and add Textbox specific resizing behavior. Resizing
   * a Textbox doesn't scale text, it only changes width and makes text wrap automatically.
   */
  var setObjectScaleOverridden = fabric.Canvas.prototype._setObjectScale;

  fabric.Canvas.prototype._setObjectScale = function (localMouse, transform,
                                                      lockScalingX, lockScalingY, by, lockScalingFlip) {

    var t = transform.target;
    if (t instanceof fabric.Textbox) {
      var w = t.width * ((localMouse.x / transform.scaleX) / (t.width + t.strokeWidth));
      if (w >= t.getMinWidth()) {
        t.set('width', w);
      }
    }
    else {
      setObjectScaleOverridden.call(fabric.Canvas.prototype, localMouse, transform,
        lockScalingX, lockScalingY, by, lockScalingFlip);
    }
  };

  /**
   * Sets controls of this group to the Textbox's special configuration if
   * one is present in the group. Deletes _controlsVisibility otherwise, so that
   * it gets initialized to default value at runtime.
   */
  fabric.Group.prototype._refreshControlsVisibility = function () {
    if (typeof fabric.Textbox === 'undefined') {
      return;
    }
    for (var i = this._objects.length; i--;) {
      if (this._objects[i] instanceof fabric.Textbox) {
        this.setControlsVisibility(fabric.Textbox.getTextboxControlVisibility());
        return;
      }
    }
  };

  var clone = fabric.util.object.clone;

  fabric.util.object.extend(fabric.Textbox.prototype, /** @lends fabric.IText.prototype */ {
    /**
     * @private
     */
    _removeExtraneousStyles: function () {
      for (var prop in this._styleMap) {
        if (!this._textLines[prop]) {
          delete this.styles[this._styleMap[prop].line];
        }
      }
    },

    /**
     * Inserts style object for a given line/char index
     * @param {Number} lineIndex Index of a line
     * @param {Number} charIndex Index of a char
     * @param {Object} [style] Style object to insert, if given
     */
    insertCharStyleObject: function (lineIndex, charIndex, style) {
      // adjust lineIndex and charIndex
      var map = this._styleMap[lineIndex];
      lineIndex = map.line;
      charIndex = map.offset + charIndex;

      this.callSuper('insertCharStyleObject', lineIndex, charIndex, style);
    },

    /**
     * Inserts new style object
     * @param {Number} lineIndex Index of a line
     * @param {Number} charIndex Index of a char
     * @param {Boolean} isEndOfLine True if it's end of line
     */
    insertNewlineStyleObject: function (lineIndex, charIndex, isEndOfLine) {
      // adjust lineIndex and charIndex
      var map = this._styleMap[lineIndex];
      lineIndex = map.line;
      charIndex = map.offset + charIndex;

      this.callSuper('insertNewlineStyleObject', lineIndex, charIndex, isEndOfLine);
    },

    /**
     * Shifts line styles up or down. This function is slightly different than the one in
     * itext_behaviour as it takes into account the styleMap.
     *
     * @param {Number} lineIndex Index of a line
     * @param {Number} offset Can be -1 or +1
     */
    shiftLineStyles: function (lineIndex, offset) {
      // shift all line styles by 1 upward
      var clonedStyles = clone(this.styles);

      // adjust line index
      var map = this._styleMap[lineIndex];
      lineIndex = map.line;

      for (var line in this.styles) {
        var numericLine = parseInt(line, 10);

        if (numericLine > lineIndex) {
          this.styles[numericLine + offset] = clonedStyles[numericLine];

          if (!clonedStyles[numericLine - offset]) {
            delete this.styles[numericLine];
          }
        }
      }
      //TODO: evaluate if delete old style lines with offset -1
    },

    /**
     * Figure out programatically the text on previous actual line (actual = separated by \n);
     *
     * @param {Number} lineIndex
     * @returns {String}
     * @private
     */
    _getTextOnPreviousLine: function (lineIndex) {
      var textOnPreviousLine = this._textLines[lineIndex - 1];

      while (this._styleMap[lineIndex - 2] && this._styleMap[lineIndex - 2].line === this._styleMap[lineIndex - 1].line) {
        textOnPreviousLine = this._textLines[lineIndex - 2] + textOnPreviousLine;

        lineIndex--;
      }

      return textOnPreviousLine;
    },

    /**
     * Removes style object
     * @param {Boolean} isBeginningOfLine True if cursor is at the beginning of line
     * @param {Number} [index] Optional index. When not given, current selectionStart is used.
     */
    removeStyleObject: function (isBeginningOfLine, index) {

      var cursorLocation = this.get2DCursorLocation(index),
          map            = this._styleMap[cursorLocation.lineIndex],
          lineIndex      = map.line,
          charIndex      = map.offset + cursorLocation.charIndex;

      if (isBeginningOfLine) {
        var textOnPreviousLine     = this._getTextOnPreviousLine(cursorLocation.lineIndex),
            newCharIndexOnPrevLine = textOnPreviousLine ? textOnPreviousLine.length : 0;

        if (!this.styles[lineIndex - 1]) {
          this.styles[lineIndex - 1] = {};
        }

        for (charIndex in this.styles[lineIndex]) {
          this.styles[lineIndex - 1][parseInt(charIndex, 10) + newCharIndexOnPrevLine]
            = this.styles[lineIndex][charIndex];
        }

        this.shiftLineStyles(cursorLocation.lineIndex, -1);

      }
      else {
        var currentLineStyles = this.styles[lineIndex];

        if (currentLineStyles) {
          delete currentLineStyles[charIndex];
          //console.log('deleting', lineIndex, charIndex + offset);
        }

        var currentLineStylesCloned = clone(currentLineStyles);

        // shift all styles by 1 backwards
        for (var i in currentLineStylesCloned) {
          var numericIndex = parseInt(i, 10);
          if (numericIndex >= charIndex && numericIndex !== 0) {
            currentLineStyles[numericIndex - 1] = currentLineStylesCloned[numericIndex];
            delete currentLineStyles[numericIndex];
          }
        }
      }
    }
  });
})();
<commit_msg>fix callSuper()'s inside mixins<commit_after>(function () {

  /**
   * Override _setObjectScale and add Textbox specific resizing behavior. Resizing
   * a Textbox doesn't scale text, it only changes width and makes text wrap automatically.
   */
  var setObjectScaleOverridden = fabric.Canvas.prototype._setObjectScale;

  fabric.Canvas.prototype._setObjectScale = function (localMouse, transform,
                                                      lockScalingX, lockScalingY, by, lockScalingFlip) {

    var t = transform.target;
    if (t instanceof fabric.Textbox) {
      var w = t.width * ((localMouse.x / transform.scaleX) / (t.width + t.strokeWidth));
      if (w >= t.getMinWidth()) {
        t.set('width', w);
      }
    }
    else {
      setObjectScaleOverridden.call(fabric.Canvas.prototype, localMouse, transform,
        lockScalingX, lockScalingY, by, lockScalingFlip);
    }
  };

  /**
   * Sets controls of this group to the Textbox's special configuration if
   * one is present in the group. Deletes _controlsVisibility otherwise, so that
   * it gets initialized to default value at runtime.
   */
  fabric.Group.prototype._refreshControlsVisibility = function () {
    if (typeof fabric.Textbox === 'undefined') {
      return;
    }
    for (var i = this._objects.length; i--;) {
      if (this._objects[i] instanceof fabric.Textbox) {
        this.setControlsVisibility(fabric.Textbox.getTextboxControlVisibility());
        return;
      }
    }
  };

  var clone = fabric.util.object.clone;

  fabric.util.object.extend(fabric.Textbox.prototype, /** @lends fabric.IText.prototype */ {
    /**
     * @private
     */
    _removeExtraneousStyles: function () {
      for (var prop in this._styleMap) {
        if (!this._textLines[prop]) {
          delete this.styles[this._styleMap[prop].line];
        }
      }
    },

    /**
     * Inserts style object for a given line/char index
     * @param {Number} lineIndex Index of a line
     * @param {Number} charIndex Index of a char
     * @param {Object} [style] Style object to insert, if given
     */
    insertCharStyleObject: function (lineIndex, charIndex, style) {
      // adjust lineIndex and charIndex
      var map = this._styleMap[lineIndex];
      lineIndex = map.line;
      charIndex = map.offset + charIndex;

      fabric.IText.prototype.insertCharStyleObject.apply(this, [lineIndex, charIndex, style]);
    },

    /**
     * Inserts new style object
     * @param {Number} lineIndex Index of a line
     * @param {Number} charIndex Index of a char
     * @param {Boolean} isEndOfLine True if it's end of line
     */
    insertNewlineStyleObject: function (lineIndex, charIndex, isEndOfLine) {
      // adjust lineIndex and charIndex
      var map = this._styleMap[lineIndex];
      lineIndex = map.line;
      charIndex = map.offset + charIndex;

      fabric.IText.prototype.insertNewlineStyleObject.apply(this, [lineIndex, charIndex, isEndOfLine]);
    },

    /**
     * Shifts line styles up or down. This function is slightly different than the one in
     * itext_behaviour as it takes into account the styleMap.
     *
     * @param {Number} lineIndex Index of a line
     * @param {Number} offset Can be -1 or +1
     */
    shiftLineStyles: function (lineIndex, offset) {
      // shift all line styles by 1 upward
      var clonedStyles = clone(this.styles);

      // adjust line index
      var map = this._styleMap[lineIndex];
      lineIndex = map.line;

      for (var line in this.styles) {
        var numericLine = parseInt(line, 10);

        if (numericLine > lineIndex) {
          this.styles[numericLine + offset] = clonedStyles[numericLine];

          if (!clonedStyles[numericLine - offset]) {
            delete this.styles[numericLine];
          }
        }
      }
      //TODO: evaluate if delete old style lines with offset -1
    },

    /**
     * Figure out programatically the text on previous actual line (actual = separated by \n);
     *
     * @param {Number} lineIndex
     * @returns {String}
     * @private
     */
    _getTextOnPreviousLine: function (lineIndex) {
      var textOnPreviousLine = this._textLines[lineIndex - 1];

      while (this._styleMap[lineIndex - 2] && this._styleMap[lineIndex - 2].line === this._styleMap[lineIndex - 1].line) {
        textOnPreviousLine = this._textLines[lineIndex - 2] + textOnPreviousLine;

        lineIndex--;
      }

      return textOnPreviousLine;
    },

    /**
     * Removes style object
     * @param {Boolean} isBeginningOfLine True if cursor is at the beginning of line
     * @param {Number} [index] Optional index. When not given, current selectionStart is used.
     */
    removeStyleObject: function (isBeginningOfLine, index) {

      var cursorLocation = this.get2DCursorLocation(index),
          map            = this._styleMap[cursorLocation.lineIndex],
          lineIndex      = map.line,
          charIndex      = map.offset + cursorLocation.charIndex;

      if (isBeginningOfLine) {
        var textOnPreviousLine     = this._getTextOnPreviousLine(cursorLocation.lineIndex),
            newCharIndexOnPrevLine = textOnPreviousLine ? textOnPreviousLine.length : 0;

        if (!this.styles[lineIndex - 1]) {
          this.styles[lineIndex - 1] = {};
        }

        for (charIndex in this.styles[lineIndex]) {
          this.styles[lineIndex - 1][parseInt(charIndex, 10) + newCharIndexOnPrevLine]
            = this.styles[lineIndex][charIndex];
        }

        this.shiftLineStyles(cursorLocation.lineIndex, -1);

      }
      else {
        var currentLineStyles = this.styles[lineIndex];

        if (currentLineStyles) {
          delete currentLineStyles[charIndex];
          //console.log('deleting', lineIndex, charIndex + offset);
        }

        var currentLineStylesCloned = clone(currentLineStyles);

        // shift all styles by 1 backwards
        for (var i in currentLineStylesCloned) {
          var numericIndex = parseInt(i, 10);
          if (numericIndex >= charIndex && numericIndex !== 0) {
            currentLineStyles[numericIndex - 1] = currentLineStylesCloned[numericIndex];
            delete currentLineStyles[numericIndex];
          }
        }
      }
    }
  });
})();
<|endoftext|>


<commit_before>#!/usr/bin/env node

"use strict";
var debug = debug = require("debug")("tile-squirrel-add-bbox"),
  SphericalMercator = require("SphericalMercator"),
  QueueWriter =  require("../lib/queueWriter");

var nomnom = require("nomnom")
  .options({
    sources: {
      position: 0,
      help: "source names to queue",
      list: true
    },
    config: {
      abbr: "c",
      metavar: "CONFIG",
      help: "Provide a configuration file"
    },
    zoom: {
      abbr: "z",
      metavar: "ZOOM",
      help: "zoom, can be a single number or a range like 5-10",
      list: true
    },
    bbox: {
      abbr: "b",
      metavar: "BBOX",
      help: "BBOX in W,S,E,N format",
      default: "-180,-85.0511287798066,180,85.0511287798066"
    },
    xSize: {
      metavar: "size",
      help: "Max x size",
      default: 8
    },
    ySize: {
      metavar: "size",
      help: "Max y size",
      default: 8
    },
    version: {
      abbr: "v",
      flag: true,
      help: "Show version info",
      callback: function() {
        return "tile-squirrel v" + require("../package.json").version;
      }
    }
  })
  .help("A zoom, or range of zooms is required.");

var opts = nomnom.parse();

if(!opts.zoom) {
  console.log("Zoom paramater is required.")
  process.exit(-1);
}

if(!opts.sources || opts.sources.length == 0) {
  console.log("At least 1 source name is required.");
  process.exit(-1);
}

var minZoom = 0,
  maxZoom = 0;

if((typeof opts.zoom) === "number") {
  minZoom = maxZoom = opts.zoom;
} else if(opts.zoom.toString().search("-") == -1) {
  minZoom = maxZoom = parseInt(opts.zoom.toString());
} else {
  var zoomComponents = opts.zoom.toString().split("-");
  if(zoomComponents.length != 2) {
    console.log("Error: zoom range must be 2 numbers seperated by a -");
    process.exit(-1);
  }

  minZoom = parseInt(zoomComponents[0]);
  maxZoom = parseInt(zoomComponents[1]);
}

debug("Zoom range: " + minZoom + "-" + maxZoom);

var bbox = opts.bbox.split(",");
if(bbox.length != 4) {
  console.log("BBOX must have 4 numbers seperated by ,");
  process.exit(-1);
}

for(var i = 0; i < bbox.length; i++) {
  bbox[i] = parseFloat(bbox[i]);
}

var merc = new SphericalMercator({
    size: 256
});

function iterateTiles(queueWriter) {
  for(var zoom = minZoom; zoom <= maxZoom; zoom++) {
    var tileBounds = merc.xyz(bbox, zoom);
    debug(zoom, tileBounds);
    var zoomString = zoom.toString();
    for(var x = tileBounds.minX; x <= tileBounds.maxX; x += opts.xSize) {
      var maxX = Math.min(x + opts.xSize - 1, tileBounds.maxX);
      var xRangeString;
      if(x == maxX) {
        xRangeString = x.toString();
      } else {
        xRangeString = x.toString() + "-" + maxX.toString();
      }
      for(var y = tileBounds.minY; y <= tileBounds.maxY; y += opts.ySize) {
        var maxY = Math.min(y + opts.ySize - 1, tileBounds.maxY);
        var yRangeString;
        if(y == maxY) {
          yRangeString = y.toString();
        } else {
          yRangeString = y.toString() + "-" + maxY.toString();
        }
        var tileRangeName = zoomString + "/" + xRangeString + "/" +  yRangeString;
        debug(tileRangeName);
        queueWriter.putTile(tileRangeName);
      }
    }
  }
  queueWriter.tileStream.end();
};

new QueueWriter(opts.sources, {}, function(err, queueWriter) {
  iterateTiles(queueWriter);
});
<commit_msg>verify that source exists if a config is passed to add-bbox<commit_after>#!/usr/bin/env node

"use strict";
var debug = debug = require("debug")("tile-squirrel-add-bbox"),
  path = require("path"),
  SphericalMercator = require("SphericalMercator"),
  QueueWriter =  require("../lib/queueWriter");

var nomnom = require("nomnom")
  .options({
    sources: {
      position: 0,
      help: "source names to queue",
      list: true
    },
    config: {
      abbr: "c",
      metavar: "CONFIG",
      help: "Provide a configuration file"
    },
    zoom: {
      abbr: "z",
      metavar: "ZOOM",
      help: "zoom, can be a single number or a range like 5-10",
      list: true
    },
    bbox: {
      abbr: "b",
      metavar: "BBOX",
      help: "BBOX in W,S,E,N format",
      default: "-180,-85.0511287798066,180,85.0511287798066"
    },
    xSize: {
      metavar: "size",
      help: "Max x size",
      default: 8
    },
    ySize: {
      metavar: "size",
      help: "Max y size",
      default: 8
    },
    version: {
      abbr: "v",
      flag: true,
      help: "Show version info",
      callback: function() {
        return "tile-squirrel v" + require("../package.json").version;
      }
    }
  })
  .help("A zoom, or range of zooms is required.");

var opts = nomnom.parse();

if(!opts.zoom) {
  console.log("Zoom paramater is required.")
  process.exit(-1);
}

if(!opts.sources || opts.sources.length == 0) {
  console.log("At least 1 source name is required.");
  process.exit(-1);
}

//Check if source exists if a config was specified
if(opts.config) {
  var config = require(path.resolve(opts.config));
  for (var i = 0; i < opts.sources.length; i++) {
    if(!config[opts.sources[i]]) {
      console.log("Source " + opts.sources[i] + " not found in config");
      process.exit(-1);
    }
  }
}

var minZoom = 0,
  maxZoom = 0;

if((typeof opts.zoom) === "number") {
  minZoom = maxZoom = opts.zoom;
} else if(opts.zoom.toString().search("-") == -1) {
  minZoom = maxZoom = parseInt(opts.zoom.toString());
} else {
  var zoomComponents = opts.zoom.toString().split("-");
  if(zoomComponents.length != 2) {
    console.log("Error: zoom range must be 2 numbers seperated by a -");
    process.exit(-1);
  }

  minZoom = parseInt(zoomComponents[0]);
  maxZoom = parseInt(zoomComponents[1]);
}

debug("Zoom range: " + minZoom + "-" + maxZoom);

var bbox = opts.bbox.split(",");
if(bbox.length != 4) {
  console.log("BBOX must have 4 numbers seperated by ,");
  process.exit(-1);
}

for(var i = 0; i < bbox.length; i++) {
  bbox[i] = parseFloat(bbox[i]);
}

var merc = new SphericalMercator({
    size: 256
});

function iterateTiles(queueWriter) {
  for(var zoom = minZoom; zoom <= maxZoom; zoom++) {
    var tileBounds = merc.xyz(bbox, zoom);
    debug(zoom, tileBounds);
    var zoomString = zoom.toString();
    for(var x = tileBounds.minX; x <= tileBounds.maxX; x += opts.xSize) {
      var maxX = Math.min(x + opts.xSize - 1, tileBounds.maxX);
      var xRangeString;
      if(x == maxX) {
        xRangeString = x.toString();
      } else {
        xRangeString = x.toString() + "-" + maxX.toString();
      }
      for(var y = tileBounds.minY; y <= tileBounds.maxY; y += opts.ySize) {
        var maxY = Math.min(y + opts.ySize - 1, tileBounds.maxY);
        var yRangeString;
        if(y == maxY) {
          yRangeString = y.toString();
        } else {
          yRangeString = y.toString() + "-" + maxY.toString();
        }
        var tileRangeName = zoomString + "/" + xRangeString + "/" +  yRangeString;
        debug(tileRangeName);
        queueWriter.putTile(tileRangeName);
      }
    }
  }
  queueWriter.tileStream.end();
};

new QueueWriter(opts.sources, {}, function(err, queueWriter) {
  iterateTiles(queueWriter);
});
<|endoftext|>


<commit_before>var async = require('async');
var cheerio = require('cheerio'); // HTML parsing
var fs = require('fs');
var https = require('https');
var mustache = require('mustache'); // templating
var normalize = require('normalize-package-data');
var packageJSON = require('package-json');
var parseGitHub = require('parse-github-url');
var path = require('path');
var spdx = require('spdx'); // license string validation
var githubPackageJSON = require('github-package-json');

var offsets = [];
for (var i = 0; i < 1000; i += 36) {
  offsets.push(i);
}

var number = 0;

function packageNames(html) {
  var $ = cheerio.load(html);
  return $('a.name')
    .map(function() {
      return cheerio(this).text();
    })
    .get();
}

function getFixItURL(repository) {
  var repoURL = repository.url;
  if (repoURL && repoURL.indexOf('github.com') > -1) {
    // github-url-to-object fails with git+<protocol>:// URLs
    var parsed = parseGitHub(repoURL.replace(/^git\+/, ''));
    if (parsed) {
      // TODO: use the default branch since master doesn't always
      // exist
      return (
        'https://github.com' +
        '/' + parsed.user +
        '/' + parsed.repo +
        '/edit' +
        '/master' +
        '/package.json'
      );
    }
  }
}

function isValid(json) {
  return typeof json.license === 'string' &&
    spdx.valid(json.license) === true;
}

function addRepoFixes(repository, result, callback) {
  setTimeout(function() {
    githubPackageJSON.master(
      repository.url,
      function(err, repositoryJSON) {
        if (!err && isValid(repositoryJSON)) {
          result.fixedInRepo = true;

          return callback(null, result);
        }

        setTimeout(function() {
          githubPackageJSON.pullRequests(
            repository.url,
            function(err, packageJSONs) {
              if (!err) {
                var validPRs = packageJSONs
                  .filter(function(pullRequest) {
                    return isValid(pullRequest.json);
                  });

                if (validPRs.length > 0) {
                  result.fixedInPRs = validPRs
                    .map(function(pullRequest) {
                      delete pullRequest.json;
                      return pullRequest;
                    });

                  return callback(null, result);
                }
              }

              result.fixItURL = getFixItURL(repository);

              callback(null, result);
            }
          );
        }, 750);
      }
    );
  }, 750);
}

function processPackages(packages, callback) {
  async.mapSeries(
    packages,
    function(name, cbMap) {
      var packageNumber = ++number;
      packageJSON(name, 'latest', function(error, json) {
        normalize(json);
        if (error) {
          cbMap(error);
        } else {
          var missing = !json.license;
          var valid = (
            !missing && isValid(json)
          );
          var invalid = !valid && !missing;
          var result = {
            number: packageNumber,
            package: name,
            version: json.version,
            homepage: encodeURI(json.homepage),
            license: (
              json.license ?
                JSON.stringify(json.license) :
                json.hasOwnProperty('licenses') ?
                  'Using deprecated "licenses"' :
                  'None'
            ),
            valid: valid,
            invalid: invalid,
            missing: missing,
            displayClass: (
              valid ? 'success' :
              invalid ? 'warning' :
              'danger'
            ),
            dependencies: json.dependencies,
            devDependencies: json.devDependencies
          };
          if ((invalid || missing) && json.repository) {
            return addRepoFixes(json.repository, result, cbMap);
          }
          cbMap(null, result);
        }
      });
    },
    callback
  );
}

function getMostDependedPage(offset, callback) {
  https.get({
    hostname: 'www.npmjs.com',
    path: '/browse/depended?offset=' + offset
  }, function(response) {
    var buffer = '';
    response
      .on('data', function(data) {
        buffer += data.toString();
      })
      .on('end', function() {
        callback(buffer);
      });
  });
}

async.concatSeries(
  offsets,
  function(offset, callback) {
    getMostDependedPage(offset, function(html) {
      processPackages(packageNames(html), callback);
    });
  },
  function(error, packages) {
    if (error) {
      throw error;
    } else {
      packages = packages
        .slice(0, 1000);
      var mostWanted = packages
        .filter(function(package) {
          return !package.valid;
        });
      var context = {
        date: new Date().toUTCString(),
        valid: packages.reduce(function(count, element) {
          return count + (element.valid ? 1 : 0);
        }, 0) / packages.length * 100,
        invalid: packages.reduce(function(count, element) {
          return count + (element.invalid ? 1 : 0);
        }, 0) / packages.length * 100,
        missing: packages.reduce(function(count, element) {
          return count + (element.missing ? 1 : 0);
        }, 0) / packages.length * 100,
        mostWanted: mostWanted
      };
      ['valid', 'invalid', 'missing'].forEach(function(count) {
        context[count + 'Rounded'] = Math.round(context[count]);
      });
      console.log(
        mustache.render(
          fs.readFileSync(
            path.join(__dirname, '..', 'templates', 'index.html')
          ).toString(),
          context
        )
      );
    }
  }
);
<commit_msg>pass repoURL directly to parseGithub<commit_after>var async = require('async');
var cheerio = require('cheerio'); // HTML parsing
var fs = require('fs');
var https = require('https');
var mustache = require('mustache'); // templating
var normalize = require('normalize-package-data');
var packageJSON = require('package-json');
var parseGitHub = require('parse-github-url');
var path = require('path');
var spdx = require('spdx'); // license string validation
var githubPackageJSON = require('github-package-json');

var offsets = [];
for (var i = 0; i < 1000; i += 36) {
  offsets.push(i);
}

var number = 0;

function packageNames(html) {
  var $ = cheerio.load(html);
  return $('a.name')
    .map(function() {
      return cheerio(this).text();
    })
    .get();
}

function getFixItURL(repository) {
  var repoURL = repository.url;
  if (repoURL && repoURL.indexOf('github.com') > -1) {
    // github-url-to-object fails with git+<protocol>:// URLs
    var parsed = parseGitHub(repoURL);
    if (parsed) {
      // TODO: use the default branch since master doesn't always
      // exist
      return (
        'https://github.com' +
        '/' + parsed.user +
        '/' + parsed.repo +
        '/edit' +
        '/master' +
        '/package.json'
      );
    }
  }
}

function isValid(json) {
  return typeof json.license === 'string' &&
    spdx.valid(json.license) === true;
}

function addRepoFixes(repository, result, callback) {
  setTimeout(function() {
    githubPackageJSON.master(
      repository.url,
      function(err, repositoryJSON) {
        if (!err && isValid(repositoryJSON)) {
          result.fixedInRepo = true;

          return callback(null, result);
        }

        setTimeout(function() {
          githubPackageJSON.pullRequests(
            repository.url,
            function(err, packageJSONs) {
              if (!err) {
                var validPRs = packageJSONs
                  .filter(function(pullRequest) {
                    return isValid(pullRequest.json);
                  });

                if (validPRs.length > 0) {
                  result.fixedInPRs = validPRs
                    .map(function(pullRequest) {
                      delete pullRequest.json;
                      return pullRequest;
                    });

                  return callback(null, result);
                }
              }

              result.fixItURL = getFixItURL(repository);

              callback(null, result);
            }
          );
        }, 750);
      }
    );
  }, 750);
}

function processPackages(packages, callback) {
  async.mapSeries(
    packages,
    function(name, cbMap) {
      var packageNumber = ++number;
      packageJSON(name, 'latest', function(error, json) {
        normalize(json);
        if (error) {
          cbMap(error);
        } else {
          var missing = !json.license;
          var valid = (
            !missing && isValid(json)
          );
          var invalid = !valid && !missing;
          var result = {
            number: packageNumber,
            package: name,
            version: json.version,
            homepage: encodeURI(json.homepage),
            license: (
              json.license ?
                JSON.stringify(json.license) :
                json.hasOwnProperty('licenses') ?
                  'Using deprecated "licenses"' :
                  'None'
            ),
            valid: valid,
            invalid: invalid,
            missing: missing,
            displayClass: (
              valid ? 'success' :
              invalid ? 'warning' :
              'danger'
            ),
            dependencies: json.dependencies,
            devDependencies: json.devDependencies
          };
          if ((invalid || missing) && json.repository) {
            return addRepoFixes(json.repository, result, cbMap);
          }
          cbMap(null, result);
        }
      });
    },
    callback
  );
}

function getMostDependedPage(offset, callback) {
  https.get({
    hostname: 'www.npmjs.com',
    path: '/browse/depended?offset=' + offset
  }, function(response) {
    var buffer = '';
    response
      .on('data', function(data) {
        buffer += data.toString();
      })
      .on('end', function() {
        callback(buffer);
      });
  });
}

async.concatSeries(
  offsets,
  function(offset, callback) {
    getMostDependedPage(offset, function(html) {
      processPackages(packageNames(html), callback);
    });
  },
  function(error, packages) {
    if (error) {
      throw error;
    } else {
      packages = packages
        .slice(0, 1000);
      var mostWanted = packages
        .filter(function(package) {
          return !package.valid;
        });
      var context = {
        date: new Date().toUTCString(),
        valid: packages.reduce(function(count, element) {
          return count + (element.valid ? 1 : 0);
        }, 0) / packages.length * 100,
        invalid: packages.reduce(function(count, element) {
          return count + (element.invalid ? 1 : 0);
        }, 0) / packages.length * 100,
        missing: packages.reduce(function(count, element) {
          return count + (element.missing ? 1 : 0);
        }, 0) / packages.length * 100,
        mostWanted: mostWanted
      };
      ['valid', 'invalid', 'missing'].forEach(function(count) {
        context[count + 'Rounded'] = Math.round(context[count]);
      });
      console.log(
        mustache.render(
          fs.readFileSync(
            path.join(__dirname, '..', 'templates', 'index.html')
          ).toString(),
          context
        )
      );
    }
  }
);
<|endoftext|>


<commit_before>var w = 600;
var h = 400;

void setup() {
  size(w, h);
}

void draw() {
  fill(255,0,0);
  ellipse(200,200,10,10);
  //rect(200,205,10,10);
  //fill(255,255,255);
  //text('e',200,210);
  /*
  fill(player.skin[0],player.skin[1],player.skin[2]);
  ellipse(player.x-player.face-3,player.y-10,6+player.face*2,10);
  fill(player.tColor[0],player.tColor[1],player.tColor[2]);
  rect(player.x-5,player.y,10,10);
  fill(255,255,255);
  text(player.tshirt,290,195);
  */
}
<commit_msg>Update drawgame.js<commit_after>var w = 600;
var h = 400;

void setup() {
  size(w, h);
}

void draw() {
  //fill(255,0,0);
  //ellipse(200,200,10,10);
  //rect(200,205,10,10);
  //fill(255,255,255);
  //text('e',200,210);

  fill(player.skin[0],player.skin[1],player.skin[2]);
  ellipse(player.x-player.face-3,player.y-10,6+player.face*2,10);
  fill(player.tColor[0],player.tColor[1],player.tColor[2]);
  rect(player.x-5,player.y,10,10);
  fill(255,255,255);
  text(player.tshirt,290,195);

}
<|endoftext|>