<commit_before>function pageViewModel(gvm) {
    // projecttitle
    gvm.projecttitle = ko.observable("");
    gvm.projectId = $("#projectHeader").data('value');

    // Page specific i18n bindings
    gvm.title = ko.computed(function (){i18n.setLocale(gvm.lang()); return gvm.app() + ' - ' + i18n.__("ProjectTitle") + ": " + gvm.projecttitle();}, gvm);
    gvm.pageHeader = ko.observable("Project");
    gvm.projectname = ko.computed(function(){i18n.setLocale(gvm.lang()); return i18n.__("ProjectName");}, gvm);
    gvm.savePage = ko.computed(function(){i18n.setLocale(gvm.lang()); return i18n.__("SaveBtn");}, gvm);

    gvm.competences = ko.observableArray([]);

    gvm.getProjectInfo = function() {
        $.getJSON('/api/project/' + gvm.projectId, function(data) {
            gvm.pageHeader(data[0].code + ' - ' + data[0].name);
        });
    };

    gvm.getAllData = function() {
         $.getJSON('/api/project/getAllData/' + gvm.projectId, function(data) {
            console.log(data);
         });
    };

    gvm.updateCompetence = function(id, code, description, max, weight) {
        var comp = new Competence(this, id, code, description, weight);
        gvm.competences.push(comp);
        return comp;
    };

    gvm.clearStructure = function() {
        gvm.competences.destroyAll();
    };
}

function initPage() {
    fetchProjectStructure();
    viewModel.getProjectInfo();
    viewModel.getAllData();

    $(".savePageBtn").click(function(){
        saveProjectScore();
    });
}

function fetchProjectScore()
{
    $.getJSON("/api/projectscore/" + projectid + "/" + studentid, function(data)
    {
        $.each(viewModel.competences(), function(i,item){
                    $.each(item.subcompetences(), function(i, subcomp)
                    {
                        $.each(subcomp.indicators(),function(i,indic)
                        {
                            for(var i = 0; i < data.length; i++) {
                            if (indic.id() == data[i].indicator) {
                                indic.score(data[i].score);
                                indic.scoreid(data[i].id);
                            }
                    }
                });
            });
        });
    });
}

function saveProjectScore()
{
    console.log("Viewmodel: " + viewModel.competences());
    $.ajax({
        type: "POST",
        url: "/api/projectscore/" + projectid + "/" + studentid,
        data: ko.toJSON(viewModel.competences),
        success: function(){
            // TODO make multilangual and with modals
            alert("Saved projectscore to server");
            //window.location = "/assess/project/" + projectid + "/students";
        }
    });
}

function fetchProjectStructure() {
    viewModel.clearStructure();

    $.getJSON("/api/projectstructure/" + projectid, function(data){
        $.each(data, function(i, item){
            var competence = viewModel.updateCompetence(item.id, item.code, item.description);

            $.each(item.subcompetences, function(i, subcomp){
                var subcompetence = new SubCompetence(competence, subcomp.id, subcomp.code, subcomp.description);
                competence.subcompetences.push(subcompetence);

                $.each(subcomp.indicators, function(i, indic){
                    subcompetence.indicators.push(new Indicator(subcompetence, indic.id, indic.name, indic.description, 0,indic.id, indic.pointType));
                });
            });
        });
        fetchProjectScore();
    });
}

function Competence(viewmodel, id, code, name, subcompetences) {
    return {
        id: ko.observable(id),
        code: ko.observable(code),
        name: ko.observable(name),
        subcompetences: ko.observableArray(subcompetences)
    };
}

function SubCompetence(parent, id, code, name, indicators) {
    return {
        id: ko.observable(id),
        code: ko.observable(code),
        name: ko.observable(name),
        indicators: ko.observableArray(indicators)
    };
}

function Indicator(parent, id, name, description, score, scoreid,pointType, checked) {
    return {
        id: ko.observable(id),
        name: ko.observable(name),
        description: ko.observable(description),
        score: ko.observable(score),
        scoreid: ko.observable(scoreid || 0),
        pointType: ko.observable(pointType),
        checked : ko.observable(checked)
    };
}<commit_msg>Document Grading<commit_after>function pageViewModel(gvm) {
    // projecttitle
    gvm.projecttitle = ko.observable("");
    gvm.projectId = $("#projectHeader").data('value');

    // Page specific i18n bindings
    gvm.title = ko.computed(function (){i18n.setLocale(gvm.lang()); return gvm.app() + ' - ' + i18n.__("ProjectTitle") + ": " + gvm.projecttitle();}, gvm);
    gvm.pageHeader = ko.observable("Project");
    gvm.projectname = ko.computed(function(){i18n.setLocale(gvm.lang()); return i18n.__("ProjectName");}, gvm);
    gvm.savePage = ko.computed(function(){i18n.setLocale(gvm.lang()); return i18n.__("SaveBtn");}, gvm);

    gvm.competences = ko.observableArray([]);

    gvm.getProjectInfo = function() {
        $.getJSON('/api/project/' + gvm.projectId, function(data) {
            gvm.pageHeader(data[0].code + ' - ' + data[0].name);
        });
    };

    gvm.getAllData = function() {
         $.getJSON('/api/project/getAllData/' + gvm.projectId, function(data) {
            console.log(data);
         });
    };

    gvm.updateCompetence = function(id, code, description, max, weight) {
        var comp = new Competence(this, id, code, description, weight);
        gvm.competences.push(comp);
        return comp;
    };

    gvm.clearStructure = function() {
        gvm.competences.destroyAll();
    };
}

function initPage() {
    fetchProjectStructure();
    viewModel.getProjectInfo();
    viewModel.getAllData();

    $(".savePageBtn").click(function(){
        saveProjectScore();
    });
}

function fetchProjectScore()
{
    $.getJSON("/api/projectscore/" + projectid + "/" + studentid, function(data)
    {
        $.each(viewModel.competences(), function(i,item){
                    $.each(item.subcompetences(), function(i, subcomp)
                    {
                        $.each(subcomp.indicators(),function(i,indic)
                        {
                            for(var i = 0; i < data.length; i++) {
                            if (indic.id() == data[i].indicator) {
                                indic.score(data[i].score);
                                indic.scoreid(data[i].id);
                            }
                    }
                });
            });
        });
    });
}

function saveProjectScore()
{
    console.log(viewModel.competences());
    $.ajax({
        type: "POST",
        url: "/api/projectscore/" + projectid + "/" + studentid,
        data: ko.toJSON(viewModel.competences),
        success: function(){
            // TODO make multilangual and with modals
            alert("Saved projectscore to server");
            //window.location = "/assess/project/" + projectid + "/students";
        }
    });
}

function fetchProjectStructure() {
    viewModel.clearStructure();

    $.getJSON("/api/projectstructure/" + projectid, function(data){
        $.each(data, function(i, item){
            var competence = viewModel.updateCompetence(item.id, item.code, item.description);

            $.each(item.subcompetences, function(i, subcomp){
                var subcompetence = new SubCompetence(competence, subcomp.id, subcomp.code, subcomp.description);
                competence.subcompetences.push(subcompetence);

                $.each(subcomp.indicators, function(i, indic){
                    subcompetence.indicators.push(new Indicator(subcompetence, indic.id, indic.name, indic.description, 0,indic.id, indic.pointType));
                });
            });
        });
        fetchProjectScore();
    });
}

function Competence(viewmodel, id, code, name, subcompetences) {
    return {
        id: ko.observable(id),
        code: ko.observable(code),
        name: ko.observable(name),
        subcompetences: ko.observableArray(subcompetences)
    };
}

function SubCompetence(parent, id, code, name, indicators) {
    return {
        id: ko.observable(id),
        code: ko.observable(code),
        name: ko.observable(name),
        indicators: ko.observableArray(indicators)
    };
}

function Indicator(parent, id, name, description, score, scoreid,pointType, checked) {
    return {
        id: ko.observable(id),
        name: ko.observable(name),
        description: ko.observable(description),
        score: ko.observable(score),
        scoreid: ko.observable(scoreid || 0),
        pointType: ko.observable(pointType),
        checked : ko.observable(checked)
    };
}<|endoftext|>


<commit_before>$(document).ready(function () {

	/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
	/* # Variables globales */
	/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
	lastNumberAssigned = 0;
	playerName = "";

	pipePlayers = { "actions" :
			[
				{
					"kind" : "drinks",
					"prepare" : [],
					"price" : []
				}
			]
		}

	/* # Initialisation de la partie */
	gameInit();

	/* # Synchronisations */
	//setInterval(getMetrology, 12000);
	//setInterval(getPlayers, 30000);

	/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
	/* # Gestionnaires d'événements */
	/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */

	/* # Rejoindre une partie */
	$( "#formGameJoin" ).submit(function( event ) {
	  event.preventDefault();

	  /* # le joueur rejoin la partie */
	  var name = $('#name').val();
	  gameRejoin(name);

	  /* # liste de joueur */
	  getPlayers();

	});

	/* # Ajouter une recette dans le panier du joueur */
	$( "#formproduction" ).submit(function( event ) {
	  event.preventDefault();

	  getInfoRecette()

	});

	/* # raffraichir les données */
	$('#btnRefreshGameInfo').click(function() {
		getMetrology();
	})

	/* # Choix d'une recette */
	if($('#recettadd') != undefined){
		$('#recettadd').change(function() {
			getRepiceByName($(this).val())
		})
	}

	/* # supprimer une recette dans le pipe */
	callbackDelPlayerPipe()

	/* # Valider les actions : achat des recettes,... */
	$('#valideracions').click(function() {
		sendAction()
	})

	/* # Quitter la partie en cours */
	$('#btnexitgame').click(function() {
		exitGameByName()
	})

	/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
	/* # Les fonctions */
	/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */

	var rand = function() {
	    return Math.random().toString(36).substr(2); // remove `0.`
	};

	var token = function() {
	    return rand() + rand(); // to make it longer
	};

	function getInfoRecette(){
		var recette = $('#recettadd').val();
		  var prixu = $('#prixunitaire').text()
		  var quantite = parseInt($('#quantity').val());
		  var prixvente = parseFloat($('#prixvente').val());

		  if(Number.isInteger(quantite)){
		  	addPlayerPipe(recette,prixu,quantite,prixvente);
		  }
	}

	/**
	*
	*/
	function addPlayerPipe(recette,prixu,quantite,prixvente) {
		$.ajax({
			url: "/recipe/"+recette,
			type: "GET",
			contentType: 'application/json',
			success: function(result){
				var token = lastNumberAssigned++;

				var itemRecette = $('

'+result.recipe[0].rec_nom+'

'+quantite+'

'+prixvente+'

'+quantite*prixvente+'

');
				$('#additemrecette').before(itemRecette);

				/* # Event : supprimer une recette dans le pipe */
				callbackDelPlayerPipe()

				/* # Ajout dans la liste pipePlayers */
				// {"actions" : [{"kind" : "drinks","prepare" : [{"1":50},{"3":20}],"price" : [{"1":8},{"3":2}]} ]}

				var tmp1 = {};
				var tmp2 = {};
				recette = (result.recipe[0].rec_nom).toString();
				tmp1[recette] = quantite;
				tmp2[recette] = prixvente;

				pipePlayers.actions[0].prepare.push(tmp1);
				pipePlayers.actions[0].price.push(tmp2);

				//console.log(JSON.stringify(pipePlayers))
	    	}
		});

	}

	/**
	*
	*/
	function getMetrology () {
		$.ajax({
			url: "/metrology",
			type: "GET",
			contentType: 'application/json',
			success: function(result){

				$('#timer').html(result.timestamp);
				$.each(result.weather, function( index, value ) {
					if(value['dfn'] == 0)
						$('#weatherToday').html(value['weather']);
	        		else
	        			$('#weatherTomorrow').html(value['weather']);
				});
	    	}
		});
	}

	function loadTime() {

	}
	loadTime();

	/**
	*
	*/
	function getPlayers() {
		$.ajax({
			url: "/players",
			type: "GET",
			contentType: 'application/json',
			success: function(result){

				if(result.players.length > 0){
					var item = $('

');

					$('#playerList').html("");
					for (var i = 0; i < result.players.length; i++) {
						item.append($('
'+ result.players[i].pl_pseudo +'
'))
					};
					$('#playerList').append(item);
				}else{
					$('#playerList').html("Liste vide :(");
				}
	    	}
		});
	}

	function getRepices() {
		$.ajax({
			url: "/recipes",
			type: "GET",
			contentType: 'application/json',
			success: function(result){

				$.each(result.recipes, function( index, value ) {

					$('#recettadd').append($('<option value="'+ value['rec_id'] +'">'+ value['rec_nom'] +'</option>'))
				});
	    	}
		});
	}

	function getRepiceByName(rc_id) {
		$.ajax({
			url: "/recipe/"+rc_id,
			type: "GET",
			contentType: 'application/json',
			success: function(result){

				var totalCost = 0;
				$.each(result.ingredients, function( index, value ) {
					totalCost += value['ing_prix'];
				});
				$('#prixunitaire').html(totalCost)
	    	}
		});
	}

	function exitGameByName(rc_id) {
			$.ajax({
				url: "/players/"+playerName,
				type: "DELETE",
				contentType: 'application/json',
				success: function(result){

		    	}
			});
		}

	/**
	*
	*/
	function gameRejoin(name) {
		var data = {"name": name}
		$.ajax({
			url: "/players",
			data : JSON.stringify(data),
			type: "POST",
			contentType: 'application/json',
			success: function(result){
	        	resetFormGameJoin();

	        	/* Supprimer le bloque rejoindre la partie */
	        	$('#inscriptionbloc').remove();

	        	/* Mise à jour des informations relatives au player */
	        	$('#username').html(result.name);
	        	playerName = result.name
	        	$('#budgetplayer').html(result.info.cash)

	        	/* Affichage d'un message de bienvenue */
	        	var title = 'Coucou '+playerName+'. ';
	        	var msg = 'Toujours aussi BD ?';
	        	var status = 'success';
	        	showMessage(title,msg,status);

	        	/*console.log(result.info.profit)
	        	console.log(result.info.sales)
	        	console.log(result.info.drinksOffered)
	        	console.log(result.info.longitude)
	        	console.log(result.info.latitude)*/

	        	/* Afficher l'interface de simulation */
	        	$('#infogamebloc').removeClass("hidden");

	    	}
		});
	}

	/**
	*
	*/
	function resetFormGameJoin () {
		$('#name').val("");
	}

	/**
	*
	*/
	function gameInit () {

		if(playerName.length > 0){
			$('#infogamebloc').removeClass("hidden");

			/* # Confirmation du player pour quitter une partie */
			exitGame();
		}else{
			$('#infogamebloc').addClass("hidden");
		}

	  	/* # Liste de joueurs */
	  	getPlayers();

	  	if($('#blocSimul') != undefined)
	 		getRepices();

	}

	function exitGame () {
		window.onbeforeunload = function() {
		    return "Etes-vous sûr de quitter la partie ?";
		}
	}

	function callbackDelPlayerPipe () {
		/* # supprimer une recette dans le pipe */
		$('.btnSuppRecette').click(function (event) {
			var tmp  = '#'+event.target.id.split("-")[0];

			$.each(pipePlayers.actions[0].prepare, function( index, value ) {
				if (parseInt(index) == parseInt(event.target.id.split("-")[0]))
					pipePlayers.actions[0].prepare.splice(index, 1);
			});

			$.each(pipePlayers.actions[0].price, function( index, value ) {
				if (parseInt(index) == parseInt(event.target.id.split("-")[0]))
					pipePlayers.actions[0].price.splice(index, 1);
			});

			$(tmp).remove()

			//console.log(pipePlayers)

		})
	}

	/**
	*
	*/
	function sendAction() {
		console.log(pipePlayers)

		$.ajax({
			url: "/actions/"+playerName,
			pipePlayers : JSON.stringify(pipePlayers),
			type: "POST",
			contentType: 'application/json',
			success: function(result){
				var title, msg, status;

				if(result.sufficientFunds == "false"){
					title = 'Solde insuffisant';
					msg = 'Nous ne pouvez pas acheter ces boissons !';
					status = 'danger';
					showMessage(title,msg,status)
				}else if(result.sufficientFunds == "true"){
					title = 'Félicitation';
					msg = 'Vos boissons ont été ajoutés avec succès !';
					status = 'success';
					showMessage(title,msg,status)
				}
	    	}
		});
	}

	function showMessage (title,msg,status) {
		$.notify({
					title: title,
					message: msg
				},{
					type: status
				});
	}

})<commit_msg>test 13<commit_after>$(document).ready(function () {

	/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
	/* # Variables globales */
	/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
	lastNumberAssigned = 0;
	playerName = "";

	pipePlayers = { "actions" :
			[
				{
					"kind" : "drinks",
					"prepare" : [],
					"price" : []
				}
			]
		}

	/* # Initialisation de la partie */
	gameInit();

	/* # Synchronisations */
	//setInterval(getMetrology, 12000);
	//setInterval(getPlayers, 30000);

	/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
	/* # Gestionnaires d'événements */
	/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */

	/* # Rejoindre une partie */
	$( "#formGameJoin" ).submit(function( event ) {
	  event.preventDefault();

	  /* # le joueur rejoin la partie */
	  var name = $('#name').val();
	  gameRejoin(name);

	  /* # liste de joueur */
	  getPlayers();

	});

	/* # Ajouter une recette dans le panier du joueur */
	$( "#formproduction" ).submit(function( event ) {
	  event.preventDefault();

	  getInfoRecette()

	});

	/* # raffraichir les données */
	$('#btnRefreshGameInfo').click(function() {
		getMetrology();
	})

	/* # Choix d'une recette */
	if($('#recettadd') != undefined){
		$('#recettadd').change(function() {
			getRepiceByName($(this).val())
		})
	}

	/* # supprimer une recette dans le pipe */
	callbackDelPlayerPipe()

	/* # Valider les actions : achat des recettes,... */
	$('#valideracions').click(function() {
		sendAction()
	})

	/* # Quitter la partie en cours */
	$('#btnexitgame').click(function() {
		exitGameByName()
	})

	/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
	/* # Les fonctions */
	/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */

	var rand = function() {
	    return Math.random().toString(36).substr(2); // remove `0.`
	};

	var token = function() {
	    return rand() + rand(); // to make it longer
	};

	function getInfoRecette(){
		var recette = $('#recettadd').val();
		  var prixu = $('#prixunitaire').text()
		  var quantite = parseInt($('#quantity').val());
		  var prixvente = parseFloat($('#prixvente').val());

		  if(Number.isInteger(quantite)){
		  	addPlayerPipe(recette,prixu,quantite,prixvente);
		  }
	}

	/**
	*
	*/
	function addPlayerPipe(recette,prixu,quantite,prixvente) {
		$.ajax({
			url: "/recipe/"+recette,
			type: "GET",
			contentType: 'application/json',
			success: function(result){
				var token = lastNumberAssigned++;

				var itemRecette = $('

'+result.recipe[0].rec_nom+'

'+quantite+'

'+prixvente+'

'+quantite*prixvente+'

');
				$('#additemrecette').before(itemRecette);

				/* # Event : supprimer une recette dans le pipe */
				callbackDelPlayerPipe()

				/* # Ajout dans la liste pipePlayers */
				// {"actions" : [{"kind" : "drinks","prepare" : [{"1":50},{"3":20}],"price" : [{"1":8},{"3":2}]} ]}

				var tmp1 = {};
				var tmp2 = {};
				recette = (result.recipe[0].rec_nom).toString();
				tmp1[recette] = quantite;
				tmp2[recette] = prixvente;

				pipePlayers.actions[0].prepare.push(tmp1);
				pipePlayers.actions[0].price.push(tmp2);

				//console.log(JSON.stringify(pipePlayers))
	    	}
		});

	}

	/**
	*
	*/
	function getMetrology () {
		$.ajax({
			url: "/metrology",
			type: "GET",
			contentType: 'application/json',
			success: function(result){

				$('#timer').html(result.timestamp);
				$.each(result.weather, function( index, value ) {
					if(value['dfn'] == 0)
						$('#weatherToday').html(value['weather']);
	        		else
	        			$('#weatherTomorrow').html(value['weather']);
				});
	    	}
		});
	}

	function loadTime() {

	}
	loadTime();

	/**
	*
	*/
	function getPlayers() {
		$.ajax({
			url: "/players",
			type: "GET",
			contentType: 'application/json',
			success: function(result){

				if(result.players.length > 0){
					var item = $('

');

					$('#playerList').html("");
					for (var i = 0; i < result.players.length; i++) {
						item.append($('
'+ result.players[i].pl_pseudo +'
'))
					};
					$('#playerList').append(item);
				}else{
					$('#playerList').html("Liste vide :(");
				}
	    	}
		});
	}

	function getRepices() {
		$.ajax({
			url: "/recipes",
			type: "GET",
			contentType: 'application/json',
			success: function(result){

				$.each(result.recipes, function( index, value ) {

					$('#recettadd').append($('<option value="'+ value['rec_id'] +'">'+ value['rec_nom'] +'</option>'))
				});
	    	}
		});
	}

	function getRepiceByName(rc_id) {
		$.ajax({
			url: "/recipe/"+rc_id,
			type: "GET",
			contentType: 'application/json',
			success: function(result){

				var totalCost = 0;
				$.each(result.ingredients, function( index, value ) {
					totalCost += value['ing_prix'];
				});
				$('#prixunitaire').html(totalCost)
	    	}
		});
	}

	function exitGameByName(rc_id) {
			$.ajax({
				url: "/players/"+playerName,
				type: "DELETE",
				contentType: 'application/json',
				success: function(result){

		    	}
			});
		}

	/**
	*
	*/
	function gameRejoin(name) {
		var data = {"name": name}
		$.ajax({
			url: "/players",
			data : JSON.stringify(data),
			type: "POST",
			contentType: 'application/json',
			success: function(result){
	        	resetFormGameJoin();

	        	/* Supprimer le bloque rejoindre la partie */
	        	$('#inscriptionbloc').remove();

	        	/* Mise à jour des informations relatives au player */
	        	$('#username').html(result.name);
	        	playerName = result.name
	        	$('#budgetplayer').html(result.info.cash)

	        	/* Affichage d'un message de bienvenue */
	        	var title = 'Coucou '+playerName+'. ';
	        	var msg = 'Toujours aussi BD ?';
	        	var status = 'success';
	        	showMessage(title,msg,status);

	        	/*console.log(result.info.profit)
	        	console.log(result.info.sales)
	        	console.log(result.info.drinksOffered)
	        	console.log(result.info.longitude)
	        	console.log(result.info.latitude)*/

	        	/* Afficher l'interface de simulation */
	        	$('#infogamebloc').removeClass("hidden");

	    	}
		});
	}

	/**
	*
	*/
	function resetFormGameJoin () {
		$('#name').val("");
	}

	/**
	*
	*/
	function gameInit () {

		if(playerName.length > 0){
			$('#infogamebloc').removeClass("hidden");

			/* # Confirmation du player pour quitter une partie */
			exitGame();
		}else{
			$('#infogamebloc').addClass("hidden");
		}

	  	/* # Liste de joueurs */
	  	getPlayers();

	  	if($('#blocSimul') != undefined)
	 		getRepices();

	}

	function exitGame () {
		window.onbeforeunload = function() {
		    return "Etes-vous sûr de quitter la partie ?";
		}
	}

	function callbackDelPlayerPipe () {
		/* # supprimer une recette dans le pipe */
		$('.btnSuppRecette').click(function (event) {
			var tmp  = '#'+event.target.id.split("-")[0];

			$.each(pipePlayers.actions[0].prepare, function( index, value ) {
				if (parseInt(index) == parseInt(event.target.id.split("-")[0]))
					pipePlayers.actions[0].prepare.splice(index, 1);
			});

			$.each(pipePlayers.actions[0].price, function( index, value ) {
				if (parseInt(index) == parseInt(event.target.id.split("-")[0]))
					pipePlayers.actions[0].price.splice(index, 1);
			});

			$(tmp).remove()

			//console.log(pipePlayers)

		})
	}

	/**
	*
	*/
	function sendAction() {
		console.log(pipePlayers)

		$.ajax({
			url: "/actions/"+playerName,
			pipePlayers : pipePlayers,
			type: "POST",
			contentType: 'application/json',
			success: function(result){
				var title, msg, status;

				if(result.sufficientFunds == "false"){
					title = 'Solde insuffisant';
					msg = 'Nous ne pouvez pas acheter ces boissons !';
					status = 'danger';
					showMessage(title,msg,status)
				}else if(result.sufficientFunds == "true"){
					title = 'Félicitation';
					msg = 'Vos boissons ont été ajoutés avec succès !';
					status = 'success';
					showMessage(title,msg,status)
				}
	    	}
		});
	}

	function showMessage(title,msg,status) {
		$.notify({
					title: title,
					message: msg
				},{
					type: status
				});
	}

})<|endoftext|>


<commit_before>(function() {
	if (!window.navigator.mozApps) {
		return;
	}

	var installWebapp = function() {
		var manifestFile = W.File.get('/usr/share/manifests/webos.webapp');
		var request = window.navigator.mozApps.install(window.location.origin+'/'+window.location.pathname+'/'+manifestFile.get('realpath'));

		/*request.onsuccess = function () {
			// Save the App object that is returned
			var appRecord = this.result;
			alert('Installation successful!');
		};
		request.onerror = function () {
			// Display the error information from the DOMError object
			alert('Install failed, error: ' + this.error.name);
		};*/
	};

	var notificationsButtons = [
		$.w.button('Install app').click(function() {
			installWebapp();
		})
	];

	$.w.notification({
		title: 'Install '+Webos.name+' on your device',
		message: 'You can install the webos to provide a better integration with your device.',
		icon: new W.Icon('actions/document-save'),
		widgets: notificationsButtons
	});
})();<commit_msg>Improved webapps support. Now checking if the webapp is installed before asking for installation.<commit_after>(function() {
	if (!navigator.mozApps) {
		return;
	}

	var getManifestPath = function() {
		var manifestFile = W.File.get('/usr/share/manifests/webos.webapp');

		return window.location.origin+'/'+window.location.pathname+'/'+manifestFile.get('realpath');
	};

	var installWebapp = function() {
		var manifestFile = W.File.get('/usr/share/manifests/webos.webapp');
		var request = navigator.mozApps.install(getManifestPath());

		/*request.onsuccess = function () {
			// Save the App object that is returned
			var appRecord = this.result;
			alert('Installation successful!');
		};
		request.onerror = function () {
			// Display the error information from the DOMError object
			alert('Install failed, error: ' + this.error.name);
		};*/
	};

	var askForInstallation = function() {
		var notificationsButtons = [
			$.w.button('Install app').click(function() {
				installWebapp();
			})
		];

		$.w.notification({
			title: 'Install '+Webos.name+' on your device',
			message: 'You can install the webos to provide a better integration with your device.',
			icon: new W.Icon('actions/document-save'),
			widgets: notificationsButtons
		});
	};

	//Check if the app is already installed
	var request = navigator.mozApps.checkInstalled(getManifestPath());
	request.onsuccess = function() {
		if (!request.result) { //App not installed
			askForInstallation();
		}
	};
})();<|endoftext|>


<commit_before>/* ===================================================
 * bootstrap-transition.js v2.0.4
 * http://twitter.github.com/bootstrap/javascript.html#transitions
 * ===================================================
 * Copyright 2012 Twitter, Inc.
 *
 * 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.
 * ========================================================== */

!function ($) {

  $(function () {

    "use strict"; // jshint ;_;

    /* CSS TRANSITION SUPPORT (http://www.modernizr.com/)
     * ======================================================= */

    $.support.transition = (function () {

      var transitionEnd = (function () {

        var el = document.createElement('bootstrap')
          , transEndEventNames = {
               'WebkitTransition' : 'webkitTransitionEnd'
            ,  'MozTransition'    : 'transitionend'
            ,  'OTransition'      : 'otransitionend'
            ,  'msTransition'     : 'MSTransitionEnd'
            ,  'transition'       : 'transitionend'
            }
          , name

        for (name in transEndEventNames){
          if (el.style[name] !== undefined) {
            return transEndEventNames[name]
          }
        }

      }())

      return transitionEnd && {
        end: transitionEnd
      }

    })()

  })

}(window.jQuery);<commit_msg>Fix transition end name for opera 11+12<commit_after>/* ===================================================
 * bootstrap-transition.js v2.0.4
 * http://twitter.github.com/bootstrap/javascript.html#transitions
 * ===================================================
 * Copyright 2012 Twitter, Inc.
 *
 * 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.
 * ========================================================== */

!function ($) {

  $(function () {

    "use strict"; // jshint ;_;

    /* CSS TRANSITION SUPPORT (http://www.modernizr.com/)
     * ======================================================= */

    $.support.transition = (function () {

      var transitionEnd = (function () {

        var el = document.createElement('bootstrap')
          , transEndEventNames = {
               'WebkitTransition' : 'webkitTransitionEnd'
            ,  'MozTransition'    : 'transitionend'
            ,  'OTransition'      : 'oTransitionEnd otransitionend'
            ,  'msTransition'     : 'MSTransitionEnd'
            ,  'transition'       : 'transitionend'
            }
          , name

        for (name in transEndEventNames){
          if (el.style[name] !== undefined) {
            return transEndEventNames[name]
          }
        }

      }())

      return transitionEnd && {
        end: transitionEnd
      }

    })()

  })

}(window.jQuery);<|endoftext|>


<commit_before>$(function() {
  var input_date = location.search.substr(1).split('=')[1];

  $error = $("#error"),
  $body = $("body");

  function loadDate(date) {
    var parts = date.split('/');
    var d = parts[2] + '-' + parts[0] + '-' + parts[1];
    printTable(d);
  }

  function createDates(data) {
    var dates = {}

    //NOTE: dates are in: "2015-01-01 00:00:00" format
    var previous_value = 0;
    var last_date = '';
    for(var val in data) {
      var date = val.split(' ')[0];
      last_date = date;
      var current_value = data[val];

      //TODO: consider doing something different for more/less values
      if (current_value != previous_value) {
        var parts = date.split('-');
        date = parts[1] + '/' + parts[2] + '/' + parts[0];
        dates[new Date(date)] = new Date(date);
      }
      previous_value = current_value;
    }

    $(function() {
      $("#datepicker").datepicker({
        numberOfMonths: 3,
        minDate: new Date(2014, 11-1, 14),
        showButtonPanel: false,
        showOtherMonths: true,
        selectOtherMonths: true,
        onSelect: loadDate,
        beforeShowDay: function(date) {
          var annotated = dates[date];
          if (annotated) {
            return [true, 'annotated', ''];
          } else {
            return [true, '', ''];
          }
        }
      });
    });

    $("#datepicker").datepicker("setDate", "-2m");

    document.getElementById("toggle").addEventListener("click", toggleState);

    if (input_date === undefined || input_date === '') {
      printTable(last_date);
    } else {
      printTable(input_date);
    }
  }

  function printTable(date) {
    $.getJSON("/data/setadetails/", {date:date}).done(function (data) { getActiveJobs(data, date); });
  }

  function getActiveJobs(details, date) {
    $.getJSON("/data/jobtypes/").done(function (data) { outputTable(data, details, date); });
  }

  // Simple text replace of full names -> Group-Code format
  function printName(testname) {
    var retVal = testname.replace(/mochitest-browser-chrome[-]?/, 'M-bc');
    retVal = retVal.replace(/mochitest-e10s-browser-chrome[-]?/, 'Me10s-bc');
    retVal = retVal.replace(/mochitest-e10s-devtools-chrome[-]?/, 'M-dt');
    retVal = retVal.replace('mochitest-e10s', 'Me10s');
    retVal = retVal.replace(/mochitest-devtools-chrome[-]?/, 'M-dt');
    retVal = retVal.replace('mochitest-other', 'M-oth');
    retVal = retVal.replace('mochitest', 'M');
    retVal = retVal.replace('crashtest-ipc', 'R-C-ipc');
    retVal = retVal.replace('crashtest', 'R-C');
    retVal = retVal.replace('jsreftest', 'R-J');
    retVal = retVal.replace('reftest-no-accel', 'R-RU');
    retVal = retVal.replace('reftest-e10s', 'Re10s-R');
    retVal = retVal.replace('reftest', 'R-R');
    retVal = retVal.replace('xpcshell', 'O-X');
    retVal = retVal.replace('marionette', 'O-Mn');
    retVal = retVal.replace('cppunit', 'O-Cpp');
    retVal = retVal.replace(/jittest[-]?/, 'O-Jit');
    retVal = retVal.replace('web-platform-tests', 'WPT');
    return retVal;
  }

  function fixPlatform(plat) {
    retVal = plat.replace('osx10.6', 'osx-10-6');
    retVal = retVal.replace('osx10.8', 'osx-10-8');
    retVal = retVal.replace('winxp', 'windowsxp');
    retVal = retVal.replace('win7', 'windows7-32');
    retVal = retVal.replace('win8', 'windows8-64');

    return retVal
  }

  function toggleState() {
    item = document.getElementById("toggle");
    fetchData();
    if (item.value == "Show Optional Jobs") {
      item.value = "Hide Optional Jobs";
    } else {
      item.value = "Show Optional Jobs";
    }
  }

  // determine if we need a strike through or not
  function printableJobCode(rawName, partName, osMap) {
    item = document.getElementById("toggle");
    // when item.value == "Hide Optional Jobs", its true value is to "show".
    if (item.value == "Hide Optional Jobs") {
      if (osMap.indexOf(rawName) >= 0) {
        return "" + partName + " ";
      }
    }
    if (!(osMap.indexOf(rawName) >= 0)) {
      return "" + partName + " ";
    }
  }

  function buildOSJobMap(joblist) {
    var map = {}

    for (var i = 0; i < joblist.length; i++) {
      var job = joblist[i];
      key = fixPlatform(job[0]) + " " + job[1];
      if (map[key] === undefined) {
          map[key] = [];
      }
      map[key].push(job[2]);
    }
    return map;
  }

  function outputTable(active_jobs, details, date) {
    // Get the list of jobs per platform that we don't need to run
    var optional_jobs = buildOSJobMap(details['jobtypes'][date]);

    var keys = []
    for (var key in optional_jobs) {
      keys.push(key);
    }
    if (keys.length == 0) {
      $('#datedesc').replaceWith('

Sorry, there is no data for the day ' + date + "

");
      $('#seta').html('

');
      return;
    }

    // Get a list of all the active jobs on the tree
    var active_osjobs = buildOSJobMap(active_jobs['jobtypes']);

    var active_oslist = ['linux32 opt', 'linux32 debug',
                         'linux64 opt', 'linux64 asan', 'linux64 debug',
                         'osx-10-6 opt', 'osx-10-6 debug',
                         'osx-10-8 opt', 'osx-10-8 debug',
                         'windowsxp opt', 'windowsxp debug',
                         'windows7-32 opt', 'windows7-32 debug',
                         'windows8-64 opt', 'windows8-64 debug'];

    var mytable = $('#seta');
    var desc = "This is the list of jobs that would be required to run in order to catch every regression in the last 6 months";
    if (mytable.html() === undefined) {
      mytable = $('#seta');
    } else {
      mytable.html('

');
    }
    $('#datedesc').replaceWith('
' + date + " - " + desc + "
");

    // Iterate through each OS, add a row and colums
    for (var i = 0; i < active_oslist.length; i++) {
      var os = active_oslist[i];
      var row = $('

').appendTo(mytable);
      $('	').text(os).appendTo(row);
      var td_jobs = $('	').appendTo(row);
      var td_div = $('

').appendTo(td_jobs);

      var types = { 'O': {'group': 'O'},
                    'M': {'group': 'M'}, "Me10s": {'group': 'M-e10s'},
                    'R': {'group': 'R'}, 'Re10s': {'group': 'R-e10s'},
                    'WPT': {'group': 'W'}}

      for (var type in types) {
          types[type]['div'] = $('').html('').appendTo(td_div);
      }

      // Iterate through all jobs for the given OS, find a group and code
      active_osjobs[os].sort();
      for (var j = 0; j < active_osjobs[os].length; j++) {
        var jobparts = printName(active_osjobs[os][j]).split('-', 2);
        var group = jobparts[0];
        var jobcode = jobparts[1];

        if (group in types) {
          $('').html(printableJobCode(active_osjobs[os][j], jobcode, optional_jobs[os])).appendTo(types[group]['div']);
        } else {
          alert("couldn't find matching group: " + group + ", with code: " + jobcode);
        }
      }

      // remove empty groups, add group letter and () for visual grouping
      for (var type in types) {
        var leftover = types[type]['div'].html().replace(/\<\/span\>/g, '');
        leftover = leftover.replace(/\/g, '');

        if (leftover.replace(/ /g, '') == '') {
            types[type]['div'].html('');
        } else if (type != 'O') {
           types[type]['div'].html(types[type]['group'] + '(' + leftover.replace(/\s+$/g, '') + ') ');
        }
      }

    }

    if (!($('#seta').length)) {
      mytable.appendTo('body');
    } else {
      $('#seta').replaceWith(mytable);
    }

  }

  function gotsummary(data) {
    if ($error.is(":visible")) $error.hide();
    createDates(data.dates);
  }

  function fail(error) {
    $dates.hide();
    $error.text(error).show();
  }

  function fetchData(e) {
    if (e) e.preventDefault();
    $.getJSON("/data/setasummary/").done(gotsummary).fail(fail);
  }

  $(document).on("ajaxStart ajaxStop", function (e) {
    (e.type === "ajaxStart") ? $body.addClass("loading") : $body.removeClass("loading");
  });

  fetchData();

});
<commit_msg>fixed typo<commit_after>$(function() {
  var input_date = location.search.substr(1).split('=')[1];

  $error = $("#error"),
  $body = $("body");

  function loadDate(date) {
    var parts = date.split('/');
    var d = parts[2] + '-' + parts[0] + '-' + parts[1];
    printTable(d);
  }

  function createDates(data) {
    var dates = {}

    //NOTE: dates are in: "2015-01-01 00:00:00" format
    var previous_value = 0;
    var last_date = '';
    for(var val in data) {
      var date = val.split(' ')[0];
      last_date = date;
      var current_value = data[val];

      //TODO: consider doing something different for more/less values
      if (current_value != previous_value) {
        var parts = date.split('-');
        date = parts[1] + '/' + parts[2] + '/' + parts[0];
        dates[new Date(date)] = new Date(date);
      }
      previous_value = current_value;
    }

    $(function() {
      $("#datepicker").datepicker({
        numberOfMonths: 3,
        minDate: new Date(2014, 11-1, 14),
        showButtonPanel: false,
        showOtherMonths: true,
        selectOtherMonths: true,
        onSelect: loadDate,
        beforeShowDay: function(date) {
          var annotated = dates[date];
          if (annotated) {
            return [true, 'annotated', ''];
          } else {
            return [true, '', ''];
          }
        }
      });
    });

    $("#datepicker").datepicker("setDate", "-2m");

    document.getElementById("toggle").addEventListener("click", toggleState);

    if (input_date === undefined || input_date === '') {
      printTable(last_date);
    } else {
      printTable(input_date);
    }
  }

  function printTable(date) {
    $.getJSON("/data/setadetails/", {date:date}).done(function (data) { getActiveJobs(data, date); });
  }

  function getActiveJobs(details, date) {
    $.getJSON("/data/jobtypes/").done(function (data) { outputTable(data, details, date); });
  }

  // Simple text replace of full names -> Group-Code format
  function printName(testname) {
    var retVal = testname.replace(/mochitest-browser-chrome[-]?/, 'M-bc');
    retVal = retVal.replace(/mochitest-e10s-browser-chrome[-]?/, 'Me10s-bc');
    retVal = retVal.replace(/mochitest-e10s-devtools-chrome[-]?/, 'M-dt');
    retVal = retVal.replace('mochitest-e10s', 'Me10s');
    retVal = retVal.replace(/mochitest-devtools-chrome[-]?/, 'M-dt');
    retVal = retVal.replace('mochitest-other', 'M-oth');
    retVal = retVal.replace('mochitest', 'M');
    retVal = retVal.replace('crashtest-ipc', 'R-C-ipc');
    retVal = retVal.replace('crashtest', 'R-C');
    retVal = retVal.replace('jsreftest', 'R-J');
    retVal = retVal.replace('reftest-no-accel', 'R-RU');
    retVal = retVal.replace('reftest-e10s', 'Re10s-R');
    retVal = retVal.replace('reftest', 'R-R');
    retVal = retVal.replace('xpcshell', 'O-X');
    retVal = retVal.replace('marionette', 'O-Mn');
    retVal = retVal.replace('cppunit', 'O-Cpp');
    retVal = retVal.replace(/jittest[-]?/, 'O-Jit');
    retVal = retVal.replace('web-platform-tests', 'WPT');
    return retVal;
  }

  function fixPlatform(plat) {
    retVal = plat.replace('osx10.6', 'osx-10-6');
    retVal = retVal.replace('osx10.8', 'osx-10-8');
    retVal = retVal.replace('winxp', 'windowsxp');
    retVal = retVal.replace('win7', 'windows7-32');
    retVal = retVal.replace('win8', 'windows8-64');

    return retVal
  }

  function toggleState() {
    item = document.getElementById("toggle");
    fetchData();
    if (item.value == "Show Optional Jobs") {
      item.value = "Hide Optional Jobs";
    } else {
      item.value = "Show Optional Jobs";
    }
  }

  // determine if we need a strike through or not
  function printableJobCode(rawName, partName, osMap) {
    item = document.getElementById("toggle");
    // when item.value == "Hide Optional Jobs", its true value is to "show".
    if (item.value == "Hide Optional Jobs") {
      if (osMap.indexOf(rawName) >= 0) {
        return "" + partName + " ";
      }
    }
    if (!(osMap.indexOf(rawName) >= 0)) {
      return "" + partName + " ";
    }
  }

  function buildOSJobMap(joblist) {
    var map = {}

    for (var i = 0; i < joblist.length; i++) {
      var job = joblist[i];
      key = fixPlatform(job[0]) + " " + job[1];
      if (map[key] === undefined) {
          map[key] = [];
      }
      map[key].push(job[2]);
    }
    return map;
  }

  function outputTable(active_jobs, details, date) {
    // Get the list of jobs per platform that we don't need to run
    var optional_jobs = buildOSJobMap(details['jobtypes'][date]);

    var keys = []
    for (var key in optional_jobs) {
      keys.push(key);
    }
    if (keys.length == 0) {
      $('#datedesc').replaceWith('

Sorry, there is no data for the day ' + date + "

");
      $('#seta').html('

');
      return;
    }

    // Get a list of all the active jobs on the tree
    var active_osjobs = buildOSJobMap(active_jobs['jobtypes']);

    var active_oslist = ['linux32 opt', 'linux32 debug',
                         'linux64 opt', 'linux64 asan', 'linux64 debug',
                         'osx-10-6 opt', 'osx-10-6 debug',
                         'osx-10-8 opt', 'osx-10-8 debug',
                         'windowsxp opt', 'windowsxp debug',
                         'windows7-32 opt', 'windows7-32 debug',
                         'windows8-64 opt', 'windows8-64 debug'];

    var mytable = $('#seta');
    var desc = "This is the list of jobs that would be required to run in order to catch every regression in the last 6 months";
    if (mytable.html() === undefined) {
      mytable = $('#seta');
    } else {
      mytable.html('

');
    }
    $('#datedesc').replaceWith('
' + date + " - " + desc + "
");

    // Iterate through each OS, add a row and colums
    for (var i = 0; i < active_oslist.length; i++) {
      var os = active_oslist[i];
      var row = $('

').appendTo(mytable);
      $('	').text(os).appendTo(row);
      var td_jobs = $('	').appendTo(row);
      var td_div = $('

').appendTo(td_jobs);

      var types = { 'O': {'group': 'O'},
                    'M': {'group': 'M'}, "Me10s": {'group': 'M-e10s'},
                    'R': {'group': 'R'}, 'Re10s': {'group': 'R-e10s'},
                    'WPT': {'group': 'W'}}

      for (var type in types) {
          types[type]['div'] = $('').html('').appendTo(td_div);
      }

      // Iterate through all jobs for the given OS, find a group and code
      active_osjobs[os].sort();
      for (var j = 0; j < active_osjobs[os].length; j++) {
        var jobparts = printName(active_osjobs[os][j]).split('-', 2);
        var group = jobparts[0];
        var jobcode = jobparts[1];

        if (group in types) {
          $('').html(printableJobCode(active_osjobs[os][j], jobcode, optional_jobs[os])).appendTo(types[group]['div']);
        } else {
          alert("couldn't find matching group: " + group + ", with code: " + jobcode);
        }
      }

      // remove empty groups, add group letter and () for visual grouping
      for (var type in types) {
        var leftover = types[type]['div'].html().replace(/\<\/span\>/g, '');
        leftover = leftover.replace(/\/g, '');

        if (leftover.replace(/ /g, '') == '') {
            types[type]['div'].html('');
        } else if (type != 'O') {
           types[type]['div'].html(types[type]['group'] + '(' + leftover.replace(/\s+$/g, '') + ') ');
        }
      }

    }

    if (!($('#seta').length)) {
      mytable.appendTo('body');
    } else {
      $('#seta').replaceWith(mytable);
    }

  }

  function gotsummary(data) {
    if ($error.is(":visible")) $error.hide();
    createDates(data.dates);
  }

  function fail(error) {
    $dates.hide();
    $error.text(error).show();
  }

  function fetchData(e) {
    if (e) e.preventDefault();
    $.getJSON("/data/setasummary/").done(gotsummary).fail(fail);
  }

  $(document).on("ajaxStart ajaxStop", function (e) {
    (e.type === "ajaxStart") ? $body.addClass("loading") : $body.removeClass("loading");
  });

  fetchData();

});
<|endoftext|>


<commit_before>// Copyright 2014-2019, University of Colorado Boulder

/**
 * shared constants for the Energy Forms and Changes simulation
 *
 * @author John Blanco
 */

define( require => {
  'use strict';

  const energyFormsAndChanges = require( 'ENERGY_FORMS_AND_CHANGES/energyFormsAndChanges' );

  // modules
  const Color = require( 'SCENERY/util/Color' );
  const LinearFunction = require( 'DOT/LinearFunction' );
  const ScreenView = require( 'JOIST/ScreenView' );
  const Util = require( 'DOT/Util' );
  const Vector2 = require( 'DOT/Vector2' );

  // constants used for creating projections that have a 3D-ish look.
  const Z_TO_X_OFFSET_MULTIPLIER = -0.25;
  const Z_TO_Y_OFFSET_MULTIPLIER = -0.25;

  // physical temperature constants
  const ROOM_TEMPERATURE = 296; // in degrees Kelvin
  const WATER_FREEZING_POINT_TEMPERATURE = 273.15; // in degrees Kelvin

  // constants that define physical parameters of various rectangular objects.
  const BRICK_DENSITY = 3300; // in kg/m^3, source = design document plus some tweaking to keep chunk numbers reasonable
  const BRICK_SPECIFIC_HEAT = 840; // in J/kg-K, source = design document
  const BLOCK_SURFACE_WIDTH = 0.045;

  // brick constants needed for energy chunk mapping
  const BRICK_ENERGY_AT_ROOM_TEMPERATURE = Math.pow( BLOCK_SURFACE_WIDTH, 3 ) * BRICK_DENSITY * BRICK_SPECIFIC_HEAT * ROOM_TEMPERATURE; // In joules.
  const BRICK_ENERGY_AT_FREEZING_TEMPERATURE = Math.pow( BLOCK_SURFACE_WIDTH, 3 ) * BRICK_DENSITY * BRICK_SPECIFIC_HEAT * WATER_FREEZING_POINT_TEMPERATURE; // In joules.

  // constants for temperature-energy mapping functions
  const LOW_ENERGY_FOR_MAP_FUNCTION = BRICK_ENERGY_AT_FREEZING_TEMPERATURE;
  const HIGH_ENERGY_FOR_MAP_FUNCTION = BRICK_ENERGY_AT_ROOM_TEMPERATURE;

  // empirically determined
  const NUM_ENERGY_CHUNKS_IN_BRICK_AT_FREEZING = 1.25;
  const NUM_ENERGY_CHUNKS_IN_BRICK_AT_ROOM_TEMP = 2.4; // close to rounding to 3 so that little energy needed to transfer first chunk

  // time values for normal and fast-forward motion
  const FRAMES_PER_SECOND = 60.0;
  const SIM_TIME_PER_TICK_NORMAL = 1 / FRAMES_PER_SECOND;

  // colors
  const NOMINAL_WATER_OPACITY = 0.75;
  const FIRST_SCREEN_BACKGROUND_COLOR = new Color( 249, 244, 205 );
  const SECOND_SCREEN_BACKGROUND_COLOR = new Color( 249, 244, 205 );

  // mapping function that maps the energy to the number of energy chunks
  const MAP_ENERGY_TO_NUM_CHUNKS = new LinearFunction(
    LOW_ENERGY_FOR_MAP_FUNCTION,
    HIGH_ENERGY_FOR_MAP_FUNCTION,
    NUM_ENERGY_CHUNKS_IN_BRICK_AT_FREEZING,
    NUM_ENERGY_CHUNKS_IN_BRICK_AT_ROOM_TEMP
  );

  // mapping function that maps the number of chunks of energy to the energy value
  const MAP_NUM_CHUNKS_TO_ENERGY = new LinearFunction(
    NUM_ENERGY_CHUNKS_IN_BRICK_AT_FREEZING,
    NUM_ENERGY_CHUNKS_IN_BRICK_AT_ROOM_TEMP,
    LOW_ENERGY_FOR_MAP_FUNCTION,
    HIGH_ENERGY_FOR_MAP_FUNCTION
  );

  const EFACConstants = {

    // Cap large dt values, which occur when the tab containing the sim had been hidden and then re-shown
    maxDT: 0.1,

    // physical temperature constants
    ROOM_TEMPERATURE: 296, // in degrees Kelvin
    WATER_FREEZING_POINT_TEMPERATURE: WATER_FREEZING_POINT_TEMPERATURE, // in degrees Kelvin
    WATER_BOILING_POINT_TEMPERATURE: 373.15, // in degrees Kelvin
    OLIVE_OIL_BOILING_POINT_TEMPERATURE: 572.04, // in degrees Kelvin, need to confirm

    // mapping function that maps the energy to the number of energy chunks
    MAP_ENERGY_TO_NUM_CHUNKS: MAP_ENERGY_TO_NUM_CHUNKS,

    // mapping function that maps the number of chunks of energy to the energy value
    MAP_NUM_CHUNKS_TO_ENERGY: MAP_NUM_CHUNKS_TO_ENERGY,

    // time values for normal and fast-forward motion
    FRAMES_PER_SECOND: FRAMES_PER_SECOND,
    SIM_TIME_PER_TICK_NORMAL: 1 / FRAMES_PER_SECOND,
    MAX_HEAT_EXCHANGE_TIME_STEP: SIM_TIME_PER_TICK_NORMAL,

    MAP_Z_TO_XY_OFFSET: zValue => {
      return new Vector2( zValue * Z_TO_X_OFFSET_MULTIPLIER, zValue * Z_TO_Y_OFFSET_MULTIPLIER );
    },

    // for comparing temperatures
    SIGNIFICANT_TEMPERATURE_DIFFERENCE: 1E-3, // in degrees Kelvin

    ENERGY_TO_NUM_CHUNKS_MAPPER: energy => {
      return Math.max( Util.roundSymmetric( MAP_ENERGY_TO_NUM_CHUNKS( energy ) ), 0 );
    },

    ENERGY_PER_CHUNK: MAP_NUM_CHUNKS_TO_ENERGY( 2 ) - MAP_NUM_CHUNKS_TO_ENERGY( 1 ),

    // threshold for deciding when two temperatures can be considered equal
    TEMPERATURES_EQUAL_THRESHOLD: 1E-6, // in degrees Kelvin

    // Constant used by all of the "energy systems" in order to keep the amount of energy generated, converted, and
    // consumed consistent.
    MAX_ENERGY_PRODUCTION_RATE: 10000, // in joules/sec

    // colors
    NOMINAL_WATER_OPACITY: 0.7,
    WATER_COLOR_OPAQUE: new Color( 175, 238, 238 ),
    WATER_COLOR_IN_BEAKER: new Color( 175, 238, 238, NOMINAL_WATER_OPACITY ),
    WATER_STEAM_COLOR: new Color( 255, 255, 255 ),
    OLIVE_OIL_COLOR_IN_BEAKER: new Color( 255, 210, 0 ),
    OLIVE_OIL_STEAM_COLOR: new Color( 230, 230, 230 ),
    FIRST_SCREEN_BACKGROUND_COLOR: FIRST_SCREEN_BACKGROUND_COLOR,
    SECOND_SCREEN_BACKGROUND_COLOR: SECOND_SCREEN_BACKGROUND_COLOR,
    CONTROL_PANEL_BACKGROUND_COLOR: new Color( 229, 236, 255 ), // Pale gray purple. AP, AR, and CK like this.
    TEMPERATURE_SENSOR_INACTIVE_COLOR: new Color( 'white' ),

    // appearance of controls
    CONTROL_PANEL_OUTLINE_LINE_WIDTH: 1.5,
    CONTROL_PANEL_OUTLINE_STROKE: new Color( 120, 120, 120 ),
    CLOCK_CONTROL_BACKGROUND_COLOR: new Color( 160, 160, 160 ),
    ENERGY_SYMBOLS_PANEL_CORNER_RADIUS: 6,
    ENERGY_SYMBOLS_PANEL_MIN_WIDTH: 215,
    ENERGY_SYMBOLS_PANEL_TEXT_MAX_WIDTH: 180,
    CONTROL_PANEL_CORNER_RADIUS: 10,
    RESET_ALL_BUTTON_RADIUS: 20,
    PLAY_PAUSE_BUTTON_RADIUS: 20,
    STEP_FORWARD_BUTTON_RADIUS: 15,

    // used to scale down the element base image, which is used in multiple system elements
    ELEMENT_BASE_WIDTH: 72,

    // used to scale down the wire images, which are used in multiple system elements
    WIRE_IMAGE_SCALE: 0.48,

    // model-view transform scale factors for each screen - smaller zooms out, larger zooms in
    INTRO_MVT_SCALE_FACTOR: 1700,
    SYSTEMS_MVT_SCALE_FACTOR: 2200,

    // constants for energy chunks
    ENERGY_CHUNK_VELOCITY: 0.04, // in meters/sec
    ENERGY_CHUNK_WIDTH: 19, // in screen coords, which are close to pixels. Empirically determined to look nice.

    // max travel height of energy chunks, in meters. the y-center location and zoom factors are different on each
    // screen, so these were empirically determined to visually match on both screens
    INTRO_SCREEN_ENERGY_CHUNK_MAX_TRAVEL_HEIGHT: 0.85,
    SYSTEMS_SCREEN_ENERGY_CHUNK_MAX_TRAVEL_HEIGHT: 0.55,

    // constants that define physical parameters of various objects
    WATER_SPECIFIC_HEAT: 3000, // In J/kg-K.  The real value for water is 4186, but this was adjusted so that there
                               // aren't too many chunks and so that a chunk is needed as soon as heating starts.
    WATER_DENSITY: 1000.0, // In kg/m^3, source = design document (and common knowledge).
    OLIVE_OIL_SPECIFIC_HEAT: 1411, // In J/kg-K. real value is 1970 (need to confirm) but this is scaled to match water
    OLIVE_OIL_DENSITY: 916.0, // In kg/m^3, need to confirm with design doc
    BRICK_DENSITY: 3300, // in kg/m^3, source = design document plus some tweaking to keep chunk numbers reasonable
    BRICK_SPECIFIC_HEAT: 840, // in J/kg-K, source = design document
    BLOCK_SURFACE_WIDTH: 0.045,
    BLOCK_PERSPECTIVE_EDGE_PROPORTION: Math.sqrt( Math.pow( Z_TO_X_OFFSET_MULTIPLIER, 2 ) +
                                                  Math.pow( Z_TO_Y_OFFSET_MULTIPLIER, 2 ) ),
    BLOCK_PERSPECTIVE_ANGLE: Math.atan2( -Z_TO_Y_OFFSET_MULTIPLIER, -Z_TO_X_OFFSET_MULTIPLIER ),
    FADE_COEFFICIENT_IN_AIR: 0.005,

    // constants for the burners.
    INITIAL_FLUID_LEVEL: 0.5,
    BURNER_EDGE_TO_HEIGHT_RATIO: 0.2, // multiplier empirically determined for best look
    BURNER_PERSPECTIVE_ANGLE: Math.PI / 4, // positive is counterclockwise, a value of 0 produces a non-skewed rectangle

    // constants used for creating projections that have a 3D-ish look
    Z_TO_X_OFFSET_MULTIPLIER: Z_TO_X_OFFSET_MULTIPLIER,
    Z_TO_Y_OFFSET_MULTIPLIER: Z_TO_Y_OFFSET_MULTIPLIER,

    // use the default layout bounds
    SCREEN_LAYOUT_BOUNDS: ScreenView.DEFAULT_LAYOUT_BOUNDS
  };

  return energyFormsAndChanges.register( 'EFACConstants', EFACConstants );
} );<commit_msg>Update OLIVE_OIL_BOILING_POINT_TEMPERATURE to be 573.15 K, see https://github.com/phetsims/energy-forms-and-changes/issues/241<commit_after>// Copyright 2014-2019, University of Colorado Boulder

/**
 * shared constants for the Energy Forms and Changes simulation
 *
 * @author John Blanco
 */

define( require => {
  'use strict';

  const energyFormsAndChanges = require( 'ENERGY_FORMS_AND_CHANGES/energyFormsAndChanges' );

  // modules
  const Color = require( 'SCENERY/util/Color' );
  const LinearFunction = require( 'DOT/LinearFunction' );
  const ScreenView = require( 'JOIST/ScreenView' );
  const Util = require( 'DOT/Util' );
  const Vector2 = require( 'DOT/Vector2' );

  // constants used for creating projections that have a 3D-ish look.
  const Z_TO_X_OFFSET_MULTIPLIER = -0.25;
  const Z_TO_Y_OFFSET_MULTIPLIER = -0.25;

  // physical temperature constants
  const ROOM_TEMPERATURE = 296; // in degrees Kelvin
  const WATER_FREEZING_POINT_TEMPERATURE = 273.15; // in degrees Kelvin

  // constants that define physical parameters of various rectangular objects.
  const BRICK_DENSITY = 3300; // in kg/m^3, source = design document plus some tweaking to keep chunk numbers reasonable
  const BRICK_SPECIFIC_HEAT = 840; // in J/kg-K, source = design document
  const BLOCK_SURFACE_WIDTH = 0.045;

  // brick constants needed for energy chunk mapping
  const BRICK_ENERGY_AT_ROOM_TEMPERATURE = Math.pow( BLOCK_SURFACE_WIDTH, 3 ) * BRICK_DENSITY * BRICK_SPECIFIC_HEAT * ROOM_TEMPERATURE; // In joules.
  const BRICK_ENERGY_AT_FREEZING_TEMPERATURE = Math.pow( BLOCK_SURFACE_WIDTH, 3 ) * BRICK_DENSITY * BRICK_SPECIFIC_HEAT * WATER_FREEZING_POINT_TEMPERATURE; // In joules.

  // constants for temperature-energy mapping functions
  const LOW_ENERGY_FOR_MAP_FUNCTION = BRICK_ENERGY_AT_FREEZING_TEMPERATURE;
  const HIGH_ENERGY_FOR_MAP_FUNCTION = BRICK_ENERGY_AT_ROOM_TEMPERATURE;

  // empirically determined
  const NUM_ENERGY_CHUNKS_IN_BRICK_AT_FREEZING = 1.25;
  const NUM_ENERGY_CHUNKS_IN_BRICK_AT_ROOM_TEMP = 2.4; // close to rounding to 3 so that little energy needed to transfer first chunk

  // time values for normal and fast-forward motion
  const FRAMES_PER_SECOND = 60.0;
  const SIM_TIME_PER_TICK_NORMAL = 1 / FRAMES_PER_SECOND;

  // colors
  const NOMINAL_WATER_OPACITY = 0.75;
  const FIRST_SCREEN_BACKGROUND_COLOR = new Color( 249, 244, 205 );
  const SECOND_SCREEN_BACKGROUND_COLOR = new Color( 249, 244, 205 );

  // mapping function that maps the energy to the number of energy chunks
  const MAP_ENERGY_TO_NUM_CHUNKS = new LinearFunction(
    LOW_ENERGY_FOR_MAP_FUNCTION,
    HIGH_ENERGY_FOR_MAP_FUNCTION,
    NUM_ENERGY_CHUNKS_IN_BRICK_AT_FREEZING,
    NUM_ENERGY_CHUNKS_IN_BRICK_AT_ROOM_TEMP
  );

  // mapping function that maps the number of chunks of energy to the energy value
  const MAP_NUM_CHUNKS_TO_ENERGY = new LinearFunction(
    NUM_ENERGY_CHUNKS_IN_BRICK_AT_FREEZING,
    NUM_ENERGY_CHUNKS_IN_BRICK_AT_ROOM_TEMP,
    LOW_ENERGY_FOR_MAP_FUNCTION,
    HIGH_ENERGY_FOR_MAP_FUNCTION
  );

  const EFACConstants = {

    // Cap large dt values, which occur when the tab containing the sim had been hidden and then re-shown
    maxDT: 0.1,

    // physical temperature constants
    ROOM_TEMPERATURE: 296, // in degrees Kelvin
    WATER_FREEZING_POINT_TEMPERATURE: WATER_FREEZING_POINT_TEMPERATURE, // in degrees Kelvin
    WATER_BOILING_POINT_TEMPERATURE: 373.15, // in degrees Kelvin
    OLIVE_OIL_BOILING_POINT_TEMPERATURE: 573.15, // in degrees Kelvin

    // mapping function that maps the energy to the number of energy chunks
    MAP_ENERGY_TO_NUM_CHUNKS: MAP_ENERGY_TO_NUM_CHUNKS,

    // mapping function that maps the number of chunks of energy to the energy value
    MAP_NUM_CHUNKS_TO_ENERGY: MAP_NUM_CHUNKS_TO_ENERGY,

    // time values for normal and fast-forward motion
    FRAMES_PER_SECOND: FRAMES_PER_SECOND,
    SIM_TIME_PER_TICK_NORMAL: 1 / FRAMES_PER_SECOND,
    MAX_HEAT_EXCHANGE_TIME_STEP: SIM_TIME_PER_TICK_NORMAL,

    MAP_Z_TO_XY_OFFSET: zValue => {
      return new Vector2( zValue * Z_TO_X_OFFSET_MULTIPLIER, zValue * Z_TO_Y_OFFSET_MULTIPLIER );
    },

    // for comparing temperatures
    SIGNIFICANT_TEMPERATURE_DIFFERENCE: 1E-3, // in degrees Kelvin

    ENERGY_TO_NUM_CHUNKS_MAPPER: energy => {
      return Math.max( Util.roundSymmetric( MAP_ENERGY_TO_NUM_CHUNKS( energy ) ), 0 );
    },

    ENERGY_PER_CHUNK: MAP_NUM_CHUNKS_TO_ENERGY( 2 ) - MAP_NUM_CHUNKS_TO_ENERGY( 1 ),

    // threshold for deciding when two temperatures can be considered equal
    TEMPERATURES_EQUAL_THRESHOLD: 1E-6, // in degrees Kelvin

    // Constant used by all of the "energy systems" in order to keep the amount of energy generated, converted, and
    // consumed consistent.
    MAX_ENERGY_PRODUCTION_RATE: 10000, // in joules/sec

    // colors
    NOMINAL_WATER_OPACITY: 0.7,
    WATER_COLOR_OPAQUE: new Color( 175, 238, 238 ),
    WATER_COLOR_IN_BEAKER: new Color( 175, 238, 238, NOMINAL_WATER_OPACITY ),
    WATER_STEAM_COLOR: new Color( 255, 255, 255 ),
    OLIVE_OIL_COLOR_IN_BEAKER: new Color( 255, 210, 0 ),
    OLIVE_OIL_STEAM_COLOR: new Color( 230, 230, 230 ),
    FIRST_SCREEN_BACKGROUND_COLOR: FIRST_SCREEN_BACKGROUND_COLOR,
    SECOND_SCREEN_BACKGROUND_COLOR: SECOND_SCREEN_BACKGROUND_COLOR,
    CONTROL_PANEL_BACKGROUND_COLOR: new Color( 229, 236, 255 ), // Pale gray purple. AP, AR, and CK like this.
    TEMPERATURE_SENSOR_INACTIVE_COLOR: new Color( 'white' ),

    // appearance of controls
    CONTROL_PANEL_OUTLINE_LINE_WIDTH: 1.5,
    CONTROL_PANEL_OUTLINE_STROKE: new Color( 120, 120, 120 ),
    CLOCK_CONTROL_BACKGROUND_COLOR: new Color( 160, 160, 160 ),
    ENERGY_SYMBOLS_PANEL_CORNER_RADIUS: 6,
    ENERGY_SYMBOLS_PANEL_MIN_WIDTH: 215,
    ENERGY_SYMBOLS_PANEL_TEXT_MAX_WIDTH: 180,
    CONTROL_PANEL_CORNER_RADIUS: 10,
    RESET_ALL_BUTTON_RADIUS: 20,
    PLAY_PAUSE_BUTTON_RADIUS: 20,
    STEP_FORWARD_BUTTON_RADIUS: 15,

    // used to scale down the element base image, which is used in multiple system elements
    ELEMENT_BASE_WIDTH: 72,

    // used to scale down the wire images, which are used in multiple system elements
    WIRE_IMAGE_SCALE: 0.48,

    // model-view transform scale factors for each screen - smaller zooms out, larger zooms in
    INTRO_MVT_SCALE_FACTOR: 1700,
    SYSTEMS_MVT_SCALE_FACTOR: 2200,

    // constants for energy chunks
    ENERGY_CHUNK_VELOCITY: 0.04, // in meters/sec
    ENERGY_CHUNK_WIDTH: 19, // in screen coords, which are close to pixels. Empirically determined to look nice.

    // max travel height of energy chunks, in meters. the y-center location and zoom factors are different on each
    // screen, so these were empirically determined to visually match on both screens
    INTRO_SCREEN_ENERGY_CHUNK_MAX_TRAVEL_HEIGHT: 0.85,
    SYSTEMS_SCREEN_ENERGY_CHUNK_MAX_TRAVEL_HEIGHT: 0.55,

    // constants that define physical parameters of various objects
    WATER_SPECIFIC_HEAT: 3000, // In J/kg-K.  The real value for water is 4186, but this was adjusted so that there
                               // aren't too many chunks and so that a chunk is needed as soon as heating starts.
    WATER_DENSITY: 1000.0, // In kg/m^3, source = design document (and common knowledge).
    OLIVE_OIL_SPECIFIC_HEAT: 1411, // In J/kg-K. real value is 1970 (need to confirm) but this is scaled to match water
    OLIVE_OIL_DENSITY: 916.0, // In kg/m^3, need to confirm with design doc
    BRICK_DENSITY: 3300, // in kg/m^3, source = design document plus some tweaking to keep chunk numbers reasonable
    BRICK_SPECIFIC_HEAT: 840, // in J/kg-K, source = design document
    BLOCK_SURFACE_WIDTH: 0.045,
    BLOCK_PERSPECTIVE_EDGE_PROPORTION: Math.sqrt( Math.pow( Z_TO_X_OFFSET_MULTIPLIER, 2 ) +
                                                  Math.pow( Z_TO_Y_OFFSET_MULTIPLIER, 2 ) ),
    BLOCK_PERSPECTIVE_ANGLE: Math.atan2( -Z_TO_Y_OFFSET_MULTIPLIER, -Z_TO_X_OFFSET_MULTIPLIER ),
    FADE_COEFFICIENT_IN_AIR: 0.005,

    // constants for the burners.
    INITIAL_FLUID_LEVEL: 0.5,
    BURNER_EDGE_TO_HEIGHT_RATIO: 0.2, // multiplier empirically determined for best look
    BURNER_PERSPECTIVE_ANGLE: Math.PI / 4, // positive is counterclockwise, a value of 0 produces a non-skewed rectangle

    // constants used for creating projections that have a 3D-ish look
    Z_TO_X_OFFSET_MULTIPLIER: Z_TO_X_OFFSET_MULTIPLIER,
    Z_TO_Y_OFFSET_MULTIPLIER: Z_TO_Y_OFFSET_MULTIPLIER,

    // use the default layout bounds
    SCREEN_LAYOUT_BOUNDS: ScreenView.DEFAULT_LAYOUT_BOUNDS
  };

  return energyFormsAndChanges.register( 'EFACConstants', EFACConstants );
} );<|endoftext|>


<commit_before>/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
           ______     ______     ______   __  __     __     ______
          /\  == \   /\  __ \   /\__  _\ /\ \/ /    /\ \   /\__  _\
          \ \  __<   \ \ \/\ \  \/_/\ \/ \ \  _"-.  \ \ \  \/_/\ \/
           \ \_____\  \ \_____\    \ \_\  \ \_\ \_\  \ \_\    \ \_\
            \/_____/   \/_____/     \/_/   \/_/\/_/   \/_/     \/_/

This is a sample Slack bot built with Botkit.

This bot demonstrates many of the core features of Botkit:

* Connect to Slack using the real time API
* Receive messages based on "spoken" patterns
* Reply to messages
* Use the conversation system to ask questions
* Use the built in storage system to store and retrieve information
  for a user.

# RUN THE BOT:

  Get a Bot token from Slack:

    -> http://my.slack.com/services/new/bot

  Run your bot from the command line:

    token=<MY TOKEN> node slack_bot.js

# USE THE BOT:

  Find your bot inside Slack to send it a direct message.

  Say: "Hello"

  The bot will reply "Hello!"

  Say: "who are you?"

  The bot will tell you its name, where it is running, and for how long.

  Say: "Call me <nickname>"

  Tell the bot your nickname. Now you are friends.

  Say: "who am I?"

  The bot will tell you your nickname, if it knows one for you.

  Say: "shutdown"

  The bot will ask if you are sure, and then shut itself down.

  Make sure to invite your bot into other channels using /invite @<my bot>!

# EXTEND THE BOT:

  Botkit has many features for building cool and useful bots!

  Read all about it here:

    -> http://howdy.ai/botkit

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/

if (!process.env.token) {
    console.log('Error: Specify token in environment');
    process.exit(1);
}

var Botkit = require('./lib/Botkit.js');
var os = require('os');

var controller = Botkit.slackbot({
    debug: true,
});

var bot = controller.spawn({
    token: process.env.token
}).startRTM();

var initiateConversationStrings = ['des', 'de si', 'oo', 'ooo', 'oooo', 'ooooo', 'desi', 'alo', 'e', 'ee', 'eee'];
var firstSentanceStrings = ['Deste momci?', 'Svi na okupu a?', 'Deste smekeri?'];
var secondSentanceStrings = ['Radimo a?', 'Tu toma a?', 'Tu sofija a?', 'Tu milos a?', 'Tu igor a?'];
var finalSentanceStrings = ['Tu sam ja', 'Idem do tome nesto, sad cu ja'];

function getSentance (sentance) {
  return sentance[ Math.floor(Math.random() * sentance.length) ];
}

controller.hears(initiateConversationStrings, 'direct_message,direct_mention,mention', function(bot, message) {
  bot.startConversation(message, function(err, convo) {
    if (!err) {
      convo.say('Ooooo');
      var firstSentance = getSentance(firstSentanceStrings);
      var secondSentance = getSentance(secondSentanceStrings);
      convo.ask(firstSentance + " " + secondSentance, function(response, convo) {
        convo.setTimeout(2000);
        convo.onTimeout(function(convo) {
          convo.say('Oh no! The time limit has expired.');
          convo.next();
        });
        // convo.say("Vazi, vazi");
        // var finalSentance = getSentance(finalSentanceStrings);
        // convo.say(finalSentance);
        // convo.next();
      });
    }
  });
});

controller.hears(['hello', 'hi'], 'direct_message,direct_mention,mention', function(bot, message) {

    bot.api.reactions.add({
        timestamp: message.ts,
        channel: message.channel,
        name: 'robot_face',
    }, function(err, res) {
        if (err) {
            bot.botkit.log('Failed to add emoji reaction :(', err);
        }
    });

    controller.storage.users.get(message.user, function(err, user) {
        if (user && user.name) {
            bot.reply(message, 'Hello ' + user.name + '!!');
        } else {
            bot.reply(message, 'Hello.');
        }
    });
});

controller.hears(['call me (.*)', 'my name is (.*)'], 'direct_message,direct_mention,mention', function(bot, message) {
    var name = message.match[1];
    controller.storage.users.get(message.user, function(err, user) {
        if (!user) {
            user = {
                id: message.user,
            };
        }
        user.name = name;
        controller.storage.users.save(user, function(err, id) {
            bot.reply(message, 'Got it. I will call you ' + user.name + ' from now on.');
        });
    });
});

controller.hears(['what is my name', 'who am i'], 'direct_message,direct_mention,mention', function(bot, message) {

    controller.storage.users.get(message.user, function(err, user) {
        if (user && user.name) {
            bot.reply(message, 'Your name is ' + user.name);
        } else {
            bot.startConversation(message, function(err, convo) {
                if (!err) {
                    convo.say('I do not know your name yet!');
                    convo.ask('What should I call you?', function(response, convo) {
                        convo.ask('You want me to call you `' + response.text + '`?', [
                            {
                                pattern: 'yes',
                                callback: function(response, convo) {
                                    // since no further messages are queued after this,
                                    // the conversation will end naturally with status == 'completed'
                                    convo.next();
                                }
                            },
                            {
                                pattern: 'no',
                                callback: function(response, convo) {
                                    // stop the conversation. this will cause it to end with status == 'stopped'
                                    convo.stop();
                                }
                            },
                            {
                                default: true,
                                callback: function(response, convo) {
                                    convo.repeat();
                                    convo.next();
                                }
                            }
                        ]);

                        convo.next();

                    }, {'key': 'nickname'}); // store the results in a field called nickname

                    convo.on('end', function(convo) {
                        if (convo.status == 'completed') {
                            bot.reply(message, 'OK! I will update my dossier...');

                            controller.storage.users.get(message.user, function(err, user) {
                                if (!user) {
                                    user = {
                                        id: message.user,
                                    };
                                }
                                user.name = convo.extractResponse('nickname');
                                controller.storage.users.save(user, function(err, id) {
                                    bot.reply(message, 'Got it. I will call you ' + user.name + ' from now on.');
                                });
                            });

                        } else {
                            // this happens if the conversation ended prematurely for some reason
                            bot.reply(message, 'OK, nevermind!');
                        }
                    });
                }
            });
        }
    });
});

controller.hears(['shutdown'], 'direct_message,direct_mention,mention', function(bot, message) {

    bot.startConversation(message, function(err, convo) {

        convo.ask('Are you sure you want me to shutdown?', [
            {
                pattern: bot.utterances.yes,
                callback: function(response, convo) {
                    convo.say('Bye!');
                    convo.next();
                    setTimeout(function() {
                        process.exit();
                    }, 3000);
                }
            },
        {
            pattern: bot.utterances.no,
            default: true,
            callback: function(response, convo) {
                convo.say('*Phew!*');
                convo.next();
            }
        }
        ]);
    });
});

controller.hears(['uptime', 'identify yourself', 'who are you', 'what is your name'],
    'direct_message,direct_mention,mention', function(bot, message) {

        var hostname = os.hostname();
        var uptime = formatUptime(process.uptime());

        bot.reply(message,
            ':robot_face: I am a bot named <@' + bot.identity.name +
             '>. I have been running for ' + uptime + ' on ' + hostname + '.');

    });

function formatUptime(uptime) {
    var unit = 'second';
    if (uptime > 60) {
        uptime = uptime / 60;
        unit = 'minute';
    }
    if (uptime > 60) {
        uptime = uptime / 60;
        unit = 'hour';
    }
    if (uptime != 1) {
        unit = unit + 's';
    }

    uptime = uptime + ' ' + unit;
    return uptime;
}
<commit_msg>Add tomaze response<commit_after>/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
           ______     ______     ______   __  __     __     ______
          /\  == \   /\  __ \   /\__  _\ /\ \/ /    /\ \   /\__  _\
          \ \  __<   \ \ \/\ \  \/_/\ \/ \ \  _"-.  \ \ \  \/_/\ \/
           \ \_____\  \ \_____\    \ \_\  \ \_\ \_\  \ \_\    \ \_\
            \/_____/   \/_____/     \/_/   \/_/\/_/   \/_/     \/_/

This is a sample Slack bot built with Botkit.

This bot demonstrates many of the core features of Botkit:

* Connect to Slack using the real time API
* Receive messages based on "spoken" patterns
* Reply to messages
* Use the conversation system to ask questions
* Use the built in storage system to store and retrieve information
  for a user.

# RUN THE BOT:

  Get a Bot token from Slack:

    -> http://my.slack.com/services/new/bot

  Run your bot from the command line:

    token=<MY TOKEN> node slack_bot.js

# USE THE BOT:

  Find your bot inside Slack to send it a direct message.

  Say: "Hello"

  The bot will reply "Hello!"

  Say: "who are you?"

  The bot will tell you its name, where it is running, and for how long.

  Say: "Call me <nickname>"

  Tell the bot your nickname. Now you are friends.

  Say: "who am I?"

  The bot will tell you your nickname, if it knows one for you.

  Say: "shutdown"

  The bot will ask if you are sure, and then shut itself down.

  Make sure to invite your bot into other channels using /invite @<my bot>!

# EXTEND THE BOT:

  Botkit has many features for building cool and useful bots!

  Read all about it here:

    -> http://howdy.ai/botkit

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/

if (!process.env.token) {
    console.log('Error: Specify token in environment');
    process.exit(1);
}

var Botkit = require('./lib/Botkit.js');
var os = require('os');

var controller = Botkit.slackbot({
    debug: true,
});

var bot = controller.spawn({
    token: process.env.token
}).startRTM();

var initiateConversationStrings = ['des', 'de si', 'oo', 'ooo', 'oooo', 'ooooo', 'desi', 'alo', 'e', 'ee', 'eee'];
var firstSentanceStrings = ['Deste momci?', 'Svi na okupu a?', 'Deste smekeri?'];
var secondSentanceStrings = ['Radimo a?', 'Tu toma a?', 'Tu sofija a?', 'Tu milos a?', 'Tu igor a?'];
var finalSentanceStrings = ['Tu sam ja', 'Idem do tome nesto, sad cu ja'];

function getSentance (sentance) {
  return sentance[ Math.floor(Math.random() * sentance.length) ];
}

controller.hears(initiateConversationStrings, 'direct_message,direct_mention,mention', function(bot, message) {
  bot.startConversation(message, function(err, convo) {
    if (!err) {
      convo.task.timeLimit = 5000;
      convo.say('Ooooo');
      var firstSentance = getSentance(firstSentanceStrings);
      var secondSentance = getSentance(secondSentanceStrings);
      convo.ask(firstSentance + " " + secondSentance, function(response, convo) {
        convo.say("Vazi, vazi");
        var finalSentance = getSentance(finalSentanceStrings);
        convo.say(finalSentance);
        convo.next();
      });
    }
  });
});

controller.hears(['hello', 'hi'], 'direct_message,direct_mention,mention', function(bot, message) {

    bot.api.reactions.add({
        timestamp: message.ts,
        channel: message.channel,
        name: 'robot_face',
    }, function(err, res) {
        if (err) {
            bot.botkit.log('Failed to add emoji reaction :(', err);
        }
    });

    controller.storage.users.get(message.user, function(err, user) {
        if (user && user.name) {
            bot.reply(message, 'Hello ' + user.name + '!!');
        } else {
            bot.reply(message, 'Hello.');
        }
    });
});

controller.hears(['call me (.*)', 'my name is (.*)'], 'direct_message,direct_mention,mention', function(bot, message) {
    var name = message.match[1];
    controller.storage.users.get(message.user, function(err, user) {
        if (!user) {
            user = {
                id: message.user,
            };
        }
        user.name = name;
        controller.storage.users.save(user, function(err, id) {
            bot.reply(message, 'Got it. I will call you ' + user.name + ' from now on.');
        });
    });
});

controller.hears(['what is my name', 'who am i'], 'direct_message,direct_mention,mention', function(bot, message) {

    controller.storage.users.get(message.user, function(err, user) {
        if (user && user.name) {
            bot.reply(message, 'Your name is ' + user.name);
        } else {
            bot.startConversation(message, function(err, convo) {
                if (!err) {
                    convo.say('I do not know your name yet!');
                    convo.ask('What should I call you?', function(response, convo) {
                        convo.ask('You want me to call you `' + response.text + '`?', [
                            {
                                pattern: 'yes',
                                callback: function(response, convo) {
                                    // since no further messages are queued after this,
                                    // the conversation will end naturally with status == 'completed'
                                    convo.next();
                                }
                            },
                            {
                                pattern: 'no',
                                callback: function(response, convo) {
                                    // stop the conversation. this will cause it to end with status == 'stopped'
                                    convo.stop();
                                }
                            },
                            {
                                default: true,
                                callback: function(response, convo) {
                                    convo.repeat();
                                    convo.next();
                                }
                            }
                        ]);

                        convo.next();

                    }, {'key': 'nickname'}); // store the results in a field called nickname

                    convo.on('end', function(convo) {
                        if (convo.status == 'completed') {
                            bot.reply(message, 'OK! I will update my dossier...');

                            controller.storage.users.get(message.user, function(err, user) {
                                if (!user) {
                                    user = {
                                        id: message.user,
                                    };
                                }
                                user.name = convo.extractResponse('nickname');
                                controller.storage.users.save(user, function(err, id) {
                                    bot.reply(message, 'Got it. I will call you ' + user.name + ' from now on.');
                                });
                            });

                        } else {
                            // this happens if the conversation ended prematurely for some reason
                            bot.reply(message, 'OK, nevermind!');
                        }
                    });
                }
            });
        }
    });
});

controller.hears(['shutdown'], 'direct_message,direct_mention,mention', function(bot, message) {

    bot.startConversation(message, function(err, convo) {

        convo.ask('Are you sure you want me to shutdown?', [
            {
                pattern: bot.utterances.yes,
                callback: function(response, convo) {
                    convo.say('Bye!');
                    convo.next();
                    setTimeout(function() {
                        process.exit();
                    }, 3000);
                }
            },
        {
            pattern: bot.utterances.no,
            default: true,
            callback: function(response, convo) {
                convo.say('*Phew!*');
                convo.next();
            }
        }
        ]);
    });
});

controller.hears(['uptime', 'identify yourself', 'who are you', 'what is your name'],
    'direct_message,direct_mention,mention', function(bot, message) {

        var hostname = os.hostname();
        var uptime = formatUptime(process.uptime());

        bot.reply(message,
            ':robot_face: I am a bot named <@' + bot.identity.name +
             '>. I have been running for ' + uptime + ' on ' + hostname + '.');

    });

function formatUptime(uptime) {
    var unit = 'second';
    if (uptime > 60) {
        uptime = uptime / 60;
        unit = 'minute';
    }
    if (uptime > 60) {
        uptime = uptime / 60;
        unit = 'hour';
    }
    if (uptime != 1) {
        unit = unit + 's';
    }

    uptime = uptime + ' ' + unit;
    return uptime;
}
<|endoftext|>