<commit_before>// JS "enum" representing the state of the game
var GameState = Object.freeze({ "WAITING":1, "CAN_DRAW":2, "WAIT_FOR_DRAW":3,
				"CAN_PUT":4, "CAN_PUT_OR_LOSE":5, "WAIT_FOR_PUT":6, "WAIT_FOR_PUT_OR_LOSE_OR_WIN":7, "CAN_WIN":8})
// The variable that is holding the current game state
var currentState = GameState.WAITING;
var attacking = false; // true when we are attacker, false when defending
var previousState = null;

// Holds the current hand of the user (TODO: just prefilled with bogus data to see the structure)
//var hand = [{value:7, color:0}, {value:11, color:1}, {value:11, color:3}, {value:14, color:2}]
var hand = [null, null, null, null];
var FULL_HAND_COUNT = 4; // constant
// Holds the hand of the enemy - useful for handling reconnections...
var ehand = [null, null, null, null];
var eHandCount = 4;

// The cards currently down on the table
var down = [null, null, null, null, null, null, null, null];

// Holds the whole deck
var deck = [];

// The widht and heigth of the sprites
var cardWidth = 59;
var cardHeigth = 92;

// Extract the 'GET' parameters as an associative array - we need the player and the enemy
var params = GET.parameters();
console.log("player: " + params.player);
console.log("enemy: " + params.enemy);

// Create the name of the channel: This should be unique to players but the same on both sides...
var player1 = params.player < params.enemy ? params.player : params.enemy;
var player2 = params.player > params.enemy ? params.player : params.enemy;
var chName = "greasefat_" + player1 + "_" + player2;
console.log("channel: " + chName);

// Called in the onLoad event of the body of the 1v1.html
function loaded(){

	// Subscribing to the game topic (communication channel)
	COM.subscribe({
		channel: chName,
		message: onMessage,
		connect: join
	});

	// Notification about joining the game called when connection is established
	function join() {
		// Other player should see that I have joined the game...
		//COM.publish({cmd:"join", who:params.player});
		COM.publish(new CMD.Join(params.player));
	}
}

function newGameState() {
        // Remove cards from the hand
        for(i = 0; i < 4; ++i){
                hand[i] = null;
        }
        // Reset the deck
        deck = [];
        // Create a shuffled deck of 32 cards
        createShuffledDeck();
        // Reset the cards down on the table
        down = [];
}

function newGame() {
	newGameState();
	updateGUI();
}

function createShuffledDeck() {
        // Go over all the four colors
        for(c = 0; c < 4; ++c) {
                // With all the 7..14 values each
                for(v = 7; v < 15; ++v) {
                        // and create a card representation
                        deck.push({value:v, color:c});
                }
        }
        // After the deck is created, shuffle all the cards
        shuffle(deck);
}

// Shuffle and array...
function shuffle(array) {
        var counter = array.length, temp, index;

        // While there are elements in the array
        while (counter > 0) {
                // Pick a random index
                index = Math.floor(Math.random() * counter);

                // Decrease counter by 1
                counter--;

                // And swap the last element with it
                temp = array[counter];
                array[counter] = array[index];
                array[index] = temp;
        }

        return array;
}

// The main onMessage event handler function for the game topic
function onMessage(msg) {
	// Handle messages by 'me' - those should not make any effect!
	if(msg.who == params.player){
		return;
	}

	// Handle messages according to the protocol of the game, first log it out.
	console.log("onMessage(..):");
	console.log(msg);
	if(msg.cmd == CMD.CMD_JOIN){
		// See if we are waiting for a player to come and got a join
		if(currentState == GameState.WAITING) {
			// Start a new game
			console.log("<" + msg.who + "> joined to the game!");
			console.log("player: " + params.player);
			console.log("enemy: " + params.enemy);
			newGame();
			console.log("A new game has been started - you can draw cards...");
			// And set the game state so that we can draw cards
			updateCurrentState(GameState.CAN_DRAW);
			// In this case we start as an attacker!
			attacking = true;
			// Notify other player about your game start
			COM.publish(new CMD.Started(params.player));
		} else {
			// TODO: fix issues because of re-connection ;-)
			console.log("ERROR: someone joined an already going game!");
		}
	}

	if(msg.cmd == CMD.CMD_STARTED){
		if(currentState == GameState.WAITING){
			// If we come here that means that the other has started the game
			// and then we should start our game too and wait for her to draw her cards
			newGame();
			updateCurrentState(GameState.WAIT_FOR_DRAW);
			// In this case we start as a defender!
			attacking = false;
		}
	}

	if(msg.cmd == CMD.CMD_DREW){
		if(currentState == GameState.WAIT_FOR_DRAW){
			// Handle the enemy drawing her cards
			eDrawCards(msg.cards);
			// Change state according to the earlier one
			if(previousState == GameState.CAN_DRAW){
				// If the previous local state was the can-draw
				// we have drawn the cards earlier then the enemy
				// in this case we update to the can-put state...
				// (message is her reaction to our drew...)
				updateCurrentState(GameState.CAN_PUT);
			}else{
				// otherwise the enemy had drawn earlier than us
				// And we can react to their drew by drawing our cards
				updateCurrentState(GameState.CAN_DRAW);
			}
		}
	}

	if(msg.cmd == CMD.CMD_PUT){
		if(currentState == GameState.WAIT_FOR_PUT || currentState == GameState.WAIT_FOR_PUT_OR_LOSE_OR_WIN){
			// Handle the enemy putting down a card of hers
			ePutDown(msg.card);
			if(attacking){
				//TODO: Check if we have won this battle here
				// and transition to CAN_WIN when it happened.

				// When we are an attacker and the defender has put
				// down her cards, then we can decide if we put down
				// more, just lose or if we are winning. The latest is
				// decided by the game rules, but technically that is
				// also a state that this client should notify the
				// other about (just like when we choose to lose).
				updateCurrentState(GameState.CAN_PUT_OR_LOSE);
			}else{
				// If we are defending we can put, but we cannot win/lose
				// we HAVE TO put a card and win/lose will be determined
				// by the other clients actions afterwards
				updateCurrentState(GameState.CAN_PUT);
			}
		}
	}
}

// Changes the game-state to the given one
// Method is extracted early so that later logic can came in (like state-checks, previous states etc.)
function updateCurrentState(nextState) {
	previousState = currentState;
	currentState = nextState;
	console.log("State has been changed from " + previousState + " to " + currentState);
	// TODO: show the user what she can do
	updateGUI();
}

// Draw for all possible positions
// TODO: Handle cases close to the end!
function drawCards() {
	if(currentState == GameState.CAN_DRAW){
		var drawnCards = [];
		console.log("drawcards");
		// Do the draw of the cards
		for(i = 0; i < 4; ++i){
			if(hand[i] == null){
				draw(i, hand);
				drawnCards.push(hand[i]);
			}
		}

		// Update game state according to the previous state
		if(previousState == GameState.WAIT_FOR_DRAW){
			// In case previously we were waiting for the other to draw theirs
			// now we should wait for them to put a card down (to keep order)
			updateCurrentState(GameState.WAIT_FOR_PUT);
		}else{
			// Otherwise we are the first who did draw cards
			// and we now have to wait until the other draws her cards.
			updateCurrentState(GameState.WAIT_FOR_DRAW);
		}

		// Send message about what we did draw
		// this is necessary to remove it from their deck
		COM.publish(new CMD.Drew(params.player, drawnCards));
	}else{
		console.log("Current state:" + currentState + " do not enable drawing cards.");
	}
}

// Draw a card to the given index of our hand
function draw(cardIndex, hand) {
	hand[cardIndex] = deck.pop();
}

// Removes the cards drawn by the enemy from the deck of our JS model.
// This is necessary as our deck should be in sync with theirs...
// TODO: This function has a side-effect on the "cards" parameter
// - it gets removed if adding is successful!
function eDrawCards(cards) {
	console.log("eDrawCards");
	// Filter deck to contain only those cards
	deck = deck.filter(function(deckCard){
		// for which every drawn card is different
		return cards.every(function(drawnCard){
			return (drawnCard.value != deckCard.value)
				&& (drawnCard.color != deckCard.color);
		});
	});

	// Add the cards to the local representation
	for(i = 0; i < 4; ++i){
		if(ehand[i] == null){
			ehand[i] = cards.pop();
		}
	}
}

// Helper function for validating rules of the game when putting cards
// Returns true if the card can be put down on "down" according
// to the rules of the game and the current state of the game.
function isValidPut(card){
	if(attacking){
		// The attacker should always put only when the rules enable her!
		if(down.length == 0){
			// The attacker can put down anything when the length is zero
			// as that means he is putting down the first card in this battle
			return true;
		}else{
			// In case there is something on the desk
			// she can put only a card with the same value
			// as the first one on the desk (the battle-starter
			// card) or a seven which can be used instead of any card!
			downCard = down[0];
			if(card.value == 7 || downCard.value == card.value){
				return true;
			}else{
				return false;
			}
		}
	}else{
		// The defender can always put anything she wants. She HAS to put...
		return true;
	}
}

// Puts down the given card from the hand if it is possible
// The function also updates GUI, state and send messages
function putDown(index){
	if(currentState == GameState.CAN_PUT || currentState == GameState.CAN_PUT_OR_LOSE){
		// Extract the selected card by the given index
		card = hand[index];

		// Check if the card can be put on the top of "down"
		if(!isValidPut(card)){
			return;
		}

		// Put down the card from our hand
		down.push(card);
		hand[index] = null;
		updateGUI();

		if(attacking) {
			// After we have put down our card, we need
			// to wait for her to put down hers (when we attack)
			updateCurrentState(GameState.WAIT_FOR_PUT);
		}else{
			// Otherwise we wait until she put or lose or win
			// when we are a defender player. We have just reacted to
			// their attacking card right now with ours...
			updateCurrentState(GameState.WAIT_FOR_PUT_OR_LOSE_OR_WIN);
		}

		// Send the message that we have put down this card
		COM.publish(new CMD.Put(params.player, card));
	}else{
		console.log("Current state:" + currentState + " do not enable putting down cards.");
	}
}

// Should be called when we get to know that the enemy did put down
// a card. This puts it down and updates GUI
function ePutDown(card) {
	// Remove from eHand!!!
	for(i = 0; i < 4; ++i){
		// Search the element with the same value and color and make it null
		if(ehand[i] != null && ehand[i].value == card.value && ehand[i].color == card.color){
			ehand[i] = null;
		}
	}
	// "Remove" a card from the upper enemy cards
	--eHandCount;
	// push the given card down
	down.push(card);
	// update relevant things
	updateGUI();
}

// This method updates everything on the GUI
function updateGUI() {
	updateHand();
	updateEHand();
	updateDown();
	updateButtons();
}

function updateButtons() {
	// It's mine button
	if(currentState == GameState.CAN_WIN) {
		$("div#mine").css({"display":"block"});
	}else{
		$("div#mine").css({"display":"none"});
	}
	// It's yours button
	if(currentState == GameState.CAN_PUT_OR_LOSE) {
		$("div#yours").css({"display":"block"});
	}else{
		$("div#yours").css({"display":"none"});
	}
}

// This function is used to update the hand of the player:
// - The hand array will be used to change css sprites!
function updateHand() {
	$("div#hand div.card").each(function(index){
		var card = hand[index];
		updateDivCardWith($(this), card);
	});
}

// Updates the enemy hand according to eHandCount
function updateEHand() {
	$("div#ehand div.ecard").each(function(index){
		//console.log("i.eHandCount:" + index + "." + eHandCount);
		if(index < eHandCount){
			$(this).css({"display":"block"});
		} else{
			$(this).css({"display":"none"});
		}
	});
}

function updateDown() {
	$("div#down div.card").each(function(index){
		var card = down[index];
		console.log(card);
		updateDivCardWith($(this), card);
	});
}

function updateDivCardWith(div, card) {
	if(card != null) {
		// If the card is not null, show the proper sprite
		// (and re-enable display:block)
		var y = card.color * cardHeigth;
		var x = (14 - card.value) * cardWidth;
		var pos = -x + "px " + y + "px";
		console.log(pos);
		// update the card
		div.css({
			"display":"block",
			"background-position":pos,
		});
	} else {
		// If the card is null, we should not show it!
		div.css({
			"display":"none",
		});
	}
}

// Prints cards of the given array onto the JS console...
// For ex.: printCards(hand);
function printCards(cards){
	for(i = 0; i < cards.length; ++i) {
		console.log("(" + cards[i].value + ", " + cards[i].color + ")");
	}
}
<commit_msg>It seems one battle is handled by the game. Should implement in-between logic for more battles...<commit_after>// JS "enum" representing the state of the game
var GameState = Object.freeze({ "WAITING":1, "CAN_DRAW":2, "WAIT_FOR_DRAW":3,
				"CAN_PUT":4, "CAN_PUT_OR_LOSE":5, "WAIT_FOR_PUT":6, "WAIT_FOR_PUT_OR_LOSE_OR_WIN":7, "CAN_WIN":8})
// The variable that is holding the current game state
var currentState = GameState.WAITING;
var attacking = false; // true when we are attacker, false when defending
var previousState = null;

// Holds the current hand of the user (TODO: just prefilled with bogus data to see the structure)
//var hand = [{value:7, color:0}, {value:11, color:1}, {value:11, color:3}, {value:14, color:2}]
var hand = [null, null, null, null];
var FULL_HAND_COUNT = 4; // constant
// Holds the hand of the enemy - useful for handling reconnections...
var ehand = [null, null, null, null];
var eHandCount = 4;

// The cards currently down on the table
var down = [null, null, null, null, null, null, null, null];

// Holds the whole deck
var deck = [];

// The widht and heigth of the sprites
var cardWidth = 59;
var cardHeigth = 92;

// Extract the 'GET' parameters as an associative array - we need the player and the enemy
var params = GET.parameters();
console.log("player: " + params.player);
console.log("enemy: " + params.enemy);

// Create the name of the channel: This should be unique to players but the same on both sides...
var player1 = params.player < params.enemy ? params.player : params.enemy;
var player2 = params.player > params.enemy ? params.player : params.enemy;
var chName = "greasefat_" + player1 + "_" + player2;
console.log("channel: " + chName);

// Called in the onLoad event of the body of the 1v1.html
function loaded(){

	// Subscribing to the game topic (communication channel)
	COM.subscribe({
		channel: chName,
		message: onMessage,
		connect: join
	});

	// Notification about joining the game called when connection is established
	function join() {
		// Other player should see that I have joined the game...
		//COM.publish({cmd:"join", who:params.player});
		COM.publish(new CMD.Join(params.player));
	}
}

function newGameState() {
        // Remove cards from the hand
        for(i = 0; i < 4; ++i){
                hand[i] = null;
        }
        // Reset the deck
        deck = [];
        // Create a shuffled deck of 32 cards
        createShuffledDeck();
        // Reset the cards down on the table
        down = [];
}

function newGame() {
	newGameState();
	updateGUI();
}

function createShuffledDeck() {
        // Go over all the four colors
        for(c = 0; c < 4; ++c) {
                // With all the 7..14 values each
                for(v = 7; v < 15; ++v) {
                        // and create a card representation
                        deck.push({value:v, color:c});
                }
        }
        // After the deck is created, shuffle all the cards
        shuffle(deck);
}

// Shuffle and array...
function shuffle(array) {
        var counter = array.length, temp, index;

        // While there are elements in the array
        while (counter > 0) {
                // Pick a random index
                index = Math.floor(Math.random() * counter);

                // Decrease counter by 1
                counter--;

                // And swap the last element with it
                temp = array[counter];
                array[counter] = array[index];
                array[index] = temp;
        }

        return array;
}

// The main onMessage event handler function for the game topic
function onMessage(msg) {
	// Handle messages by 'me' - those should not make any effect!
	if(msg.who == params.player){
		return;
	}

	// Handle messages according to the protocol of the game, first log it out.
	console.log("onMessage(..):");
	console.log(msg);
	if(msg.cmd == CMD.CMD_JOIN){
		// See if we are waiting for a player to come and got a join
		if(currentState == GameState.WAITING) {
			// Start a new game
			console.log("<" + msg.who + "> joined to the game!");
			console.log("player: " + params.player);
			console.log("enemy: " + params.enemy);
			newGame();
			console.log("A new game has been started - you can draw cards...");
			// And set the game state so that we can draw cards
			updateCurrentState(GameState.CAN_DRAW);
			// In this case we start as an attacker!
			attacking = true;
			// Notify other player about your game start
			COM.publish(new CMD.Started(params.player));
		} else {
			// TODO: fix issues because of re-connection ;-)
			console.log("ERROR: someone joined an already going game!");
		}
	}

	if(msg.cmd == CMD.CMD_STARTED){
		if(currentState == GameState.WAITING){
			// If we come here that means that the other has started the game
			// and then we should start our game too and wait for her to draw her cards
			newGame();
			updateCurrentState(GameState.WAIT_FOR_DRAW);
			// In this case we start as a defender!
			attacking = false;
		}
	}

	if(msg.cmd == CMD.CMD_DREW){
		if(currentState == GameState.WAIT_FOR_DRAW){
			// Handle the enemy drawing her cards
			eDrawCards(msg.cards);
			// Change state according to the earlier one
			if(previousState == GameState.CAN_DRAW){
				// If the previous local state was the can-draw
				// we have drawn the cards earlier then the enemy
				// in this case we update to the can-put state...
				// (message is her reaction to our drew...)
				updateCurrentState(GameState.CAN_PUT);
			}else{
				// otherwise the enemy had drawn earlier than us
				// And we can react to their drew by drawing our cards
				updateCurrentState(GameState.CAN_DRAW);
			}
		}
	}

	if(msg.cmd == CMD.CMD_PUT){
		if(currentState == GameState.WAIT_FOR_PUT || currentState == GameState.WAIT_FOR_PUT_OR_LOSE_OR_WIN){
			// Handle the enemy putting down a card of hers
			ePutDown(msg.card);
			if(attacking){
				// Check if we have won this battle here
				// and transition to CAN_WIN when it happened.
				if(down.length > 1 && down[down.length - 2].value != down[down.length - 1].value &&
				   down[down.length - 1].value != 7) {
					updateCurrentState(GameState.CAN_WIN);
					return;
				}

				// When we are an attacker and the defender has put
				// down her cards, then we can decide if we put down
				// more, just lose or if we are winning. The latest is
				// decided by the game rules, but technically that is
				// also a state that this client should notify the
				// other about (just like when we choose to lose).
				updateCurrentState(GameState.CAN_PUT_OR_LOSE);
			}else{
				// If we are defending we can put, but we cannot win/lose
				// we HAVE TO put a card and win/lose will be determined
				// by the other clients actions afterwards
				updateCurrentState(GameState.CAN_PUT);
			}
		}
	}
}

// Changes the game-state to the given one
// Method is extracted early so that later logic can came in (like state-checks, previous states etc.)
function updateCurrentState(nextState) {
	previousState = currentState;
	currentState = nextState;
	console.log("State has been changed from " + previousState + " to " + currentState);
	// TODO: show the user what she can do
	updateGUI();
}

// Draw for all possible positions
// TODO: Handle cases close to the end!
function drawCards() {
	if(currentState == GameState.CAN_DRAW){
		var drawnCards = [];
		console.log("drawcards");
		// Do the draw of the cards
		for(i = 0; i < 4; ++i){
			if(hand[i] == null){
				draw(i, hand);
				drawnCards.push(hand[i]);
			}
		}

		// Update game state according to the previous state
		if(previousState == GameState.WAIT_FOR_DRAW){
			// In case previously we were waiting for the other to draw theirs
			// now we should wait for them to put a card down (to keep order)
			updateCurrentState(GameState.WAIT_FOR_PUT);
		}else{
			// Otherwise we are the first who did draw cards
			// and we now have to wait until the other draws her cards.
			updateCurrentState(GameState.WAIT_FOR_DRAW);
		}

		// Send message about what we did draw
		// this is necessary to remove it from their deck
		COM.publish(new CMD.Drew(params.player, drawnCards));
	}else{
		console.log("Current state:" + currentState + " do not enable drawing cards.");
	}
}

// Draw a card to the given index of our hand
function draw(cardIndex, hand) {
	hand[cardIndex] = deck.pop();
}

// Removes the cards drawn by the enemy from the deck of our JS model.
// This is necessary as our deck should be in sync with theirs...
// TODO: This function has a side-effect on the "cards" parameter
// - it gets removed if adding is successful!
function eDrawCards(cards) {
	console.log("eDrawCards");
	// Filter deck to contain only those cards
	deck = deck.filter(function(deckCard){
		// for which every drawn card is different
		return cards.every(function(drawnCard){
			return (drawnCard.value != deckCard.value)
				&& (drawnCard.color != deckCard.color);
		});
	});

	// Add the cards to the local representation
	for(i = 0; i < 4; ++i){
		if(ehand[i] == null){
			ehand[i] = cards.pop();
		}
	}
}

// Helper function for validating rules of the game when putting cards
// Returns true if the card can be put down on "down" according
// to the rules of the game and the current state of the game.
function isValidPut(card){
	if(attacking){
		// The attacker should always put only when the rules enable her!
		if(down.length == 0){
			// The attacker can put down anything when the length is zero
			// as that means he is putting down the first card in this battle
			return true;
		}else{
			// In case there is something on the desk
			// she can put only a card with the same value
			// as the first one on the desk (the battle-starter
			// card) or a seven which can be used instead of any card!
			downCard = down[0];
			if(card.value == 7 || downCard.value == card.value){
				return true;
			}else{
				return false;
			}
		}
	}else{
		// The defender can always put anything she wants. She HAS to put...
		return true;
	}
}

// Puts down the given card from the hand if it is possible
// The function also updates GUI, state and send messages
function putDown(index){
	if(currentState == GameState.CAN_PUT || currentState == GameState.CAN_PUT_OR_LOSE){
		// Extract the selected card by the given index
		card = hand[index];

		// Check if the card can be put on the top of "down"
		if(!isValidPut(card)){
			return;
		}

		// Put down the card from our hand
		down.push(card);
		hand[index] = null;
		updateGUI();

		if(attacking) {
			// After we have put down our card, we need
			// to wait for her to put down hers (when we attack)
			updateCurrentState(GameState.WAIT_FOR_PUT);
		}else{
			// Otherwise we wait until she put or lose or win
			// when we are a defender player. We have just reacted to
			// their attacking card right now with ours...
			updateCurrentState(GameState.WAIT_FOR_PUT_OR_LOSE_OR_WIN);
		}

		// Send the message that we have put down this card
		COM.publish(new CMD.Put(params.player, card));
	}else{
		console.log("Current state:" + currentState + " do not enable putting down cards.");
	}
}

// Should be called when we get to know that the enemy did put down
// a card. This puts it down and updates GUI
function ePutDown(card) {
	// Remove from eHand!!!
	for(i = 0; i < 4; ++i){
		// Search the element with the same value and color and make it null
		if(ehand[i] != null && ehand[i].value == card.value && ehand[i].color == card.color){
			ehand[i] = null;
		}
	}
	// "Remove" a card from the upper enemy cards
	--eHandCount;
	// push the given card down
	down.push(card);
	// update relevant things
	updateGUI();
}

// This method updates everything on the GUI
function updateGUI() {
	updateHand();
	updateEHand();
	updateDown();
	updateButtons();
}

function updateButtons() {
	// It's mine button
	if(currentState == GameState.CAN_WIN) {
		$("div#mine").css({"display":"block"});
	}else{
		$("div#mine").css({"display":"none"});
	}
	// It's yours button
	if(currentState == GameState.CAN_PUT_OR_LOSE) {
		$("div#yours").css({"display":"block"});
	}else{
		$("div#yours").css({"display":"none"});
	}
}

// This function is used to update the hand of the player:
// - The hand array will be used to change css sprites!
function updateHand() {
	$("div#hand div.card").each(function(index){
		var card = hand[index];
		updateDivCardWith($(this), card);
	});
}

// Updates the enemy hand according to eHandCount
function updateEHand() {
	$("div#ehand div.ecard").each(function(index){
		//console.log("i.eHandCount:" + index + "." + eHandCount);
		if(index < eHandCount){
			$(this).css({"display":"block"});
		} else{
			$(this).css({"display":"none"});
		}
	});
}

function updateDown() {
	$("div#down div.card").each(function(index){
		var card = down[index];
		console.log(card);
		updateDivCardWith($(this), card);
	});
}

function updateDivCardWith(div, card) {
	if(card != null) {
		// If the card is not null, show the proper sprite
		// (and re-enable display:block)
		var y = card.color * cardHeigth;
		var x = (14 - card.value) * cardWidth;
		var pos = -x + "px " + y + "px";
		console.log(pos);
		// update the card
		div.css({
			"display":"block",
			"background-position":pos,
		});
	} else {
		// If the card is null, we should not show it!
		div.css({
			"display":"none",
		});
	}
}

// Prints cards of the given array onto the JS console...
// For ex.: printCards(hand);
function printCards(cards){
	for(i = 0; i < cards.length; ++i) {
		console.log("(" + cards[i].value + ", " + cards[i].color + ")");
	}
}
<|endoftext|>


<commit_before>// 34567890123456789012345678901234567890123456789012345678901234567890123456789

// JSHint (this file) - TODO

// App.gs
// ======
//
// This object provides the external interface to the TrelloApp library
//
// Any of the methods can throw a special error called "AuthorizationError"
// which indicates that there may be a problem with authorisation and the
// calling script should prompt the user to re-authorise the API.
//
// The library user can also throw this error if it suspects authorisation is
// needed

/**
 * This is the entry point into this library:
 *
 *   var trelloApp = new TrelloApp.App('1', PropertiesService.getUserProperties)
 *
 *  @param {object} propertiesService The PropertiesService object to use
 *  @param {string} version [OPTIONAL] The version of the Trello API being used, defaults to 1.0
 */

function App(version) {

  Api_.setVersion(setDefault_(version, '1'))

  /**
   * If an error is thrown the first thing to try is displaying this
   * URI to the user to trigger Trello authorization pop-up, then get
   * them to try again.
   */

  // TODO - Probably a nicer way of doing that

  App.prototype.getAuthorizationUri = function() {

    return AUTHORIZATION_URI

  } // App.prototype.getAuthorizationUrl()

  /**
   *
   */

  App.prototype.reset = function() {

    Authorizer_.resetTrello()

  } // App.prototype.reset()

  /**
   * Get all of the users boards.
   *
   * @return {object} wrapped board object or null
   */

  App.prototype.getMyBoards = function() {

    var config = {
      service: 'members',
      id: 'me',
      elements: 'boards',
    }

    var responseJSON = Api_.fetch(config)

    if (responseJSON === null) {
      return null
    }

    var response = JSON.parse(responseJSON)

    var obj = {}
    obj.boards = response

    this.boards = Wrapper_.wrapObjects(this, new Board_(), obj.boards)
    return this.boards

  } // App.prototype.getMyBoards()

  /**
   * Get all of the lists for a particular board
   *
   * @return {object} wrapped list object or null
   */

  App.prototype.getBoardLists = function(boardId) {

    var config = {
      service: 'boards',
      id: boardId,
      elements: 'lists',
    }

    var responseJSON = Api_.fetch(config)

    if (responseJSON === null) {
      return null
    }

    var response = JSON.parse(responseJSON)

    var obj = {}
    obj.lists = response

    this.lists = Wrapper_.wrapObjects(this, new List_(), obj.lists)

    return this.lists

  } // App.getBoardLists()

  /**
   * Get all of the users organisations
   *
   * @return {object} wrapped organisation object or null
   */

  App.prototype.getMyOrganizations = function() {

    var config = {
      service: 'members',
      id: 'me',
      elements: 'organizations',
    }

    var responseJSON = Api_.fetch(config)

    if (responseJSON === null) {
      return null
    }

    var response = JSON.parse(responseJSON)

    var obj = {}
    obj.organizations = response

    this.organizations = Wrapper_.wrapObjects(
      this,
      new Organizations_(),
      obj.organizations)

    return this.organizations

  } // App.prototype.getMyOrganizations()

  /*
   * @param {object} config This becomes the payload for the cards API call,
   *                        so matches the
   *
   * From docs: https://developers.trello.com/advanced-reference/card#post-1-cards,
   * although the 'requirements' have changed
   *
   *   name (required) Valid Values: The name of the new card. It isn't required if the name is being copied from provided by a URL, file or card that is being copied.
   *   desc (optional) Valid Values: a string with a length from 0 to 16384
   *   pos (optional) Default: bottom Valid Values: A position. top, bottom, or a positive number.
   *   due (optional) Default: null Valid Values: A date
   *   idList (required) Valid Values: id of the list that the card should be added to
   *   idMembers (optional) Valid Values: A comma-separated list of objectIds, 24-character hex strings
   *   idLabels (optional) Valid Values: A comma-separated list of objectIds, 24-character hex strings
   *   urlSource (optional) Default: null Valid Values: A URL starting with http:// or https:// or null
   *   fileSource (optional) Valid Values: A file
   *   idCardSource (optional) Valid Values: The id of the card to copy into a new card.
   *   keepFromSource (optional) Default: all Valid Values: Properties of the card to copy over from the source.
   *
   * @return {object} response text or null
   */

  App.prototype.createCard = function(config) {

    assertStringNotEmpty_(config.name, 'App.createCard() needs a name for the card')
    assertStringNotEmpty_(config.idList, 'App.createCard() needs an id list for the card')

    setDefault_(config.due, null)
    setDefault_(config.urlSource, 'App.createCard() needs a url source for the card')

    var options = {
      httpMethod: 'POST',
      service: 'cards',
      payload: config,
    }

    var responseJSON = Api_.fetch(options)

    if (responseJSON === null) {
      return null
    }

    var response = JSON.parse(responseJSON)

    // TODO - What's this look like??
    return response

  } // createCard()

} // App()
<commit_msg>updated by GasGit automation<commit_after>// 34567890123456789012345678901234567890123456789012345678901234567890123456789

// JSHint (this file) - TODO

// App.gs
// ======
//
// This object provides the external interface to the TrelloApp library
//
// Any of the methods can throw a special error called "AuthorizationError"
// which indicates that there may be a problem with authorisation and the
// calling script should prompt the user to re-authorise the API.
//
// The library user can also throw this error if it suspects authorisation is
// needed

// TODO - Use the Log library throughout the code

/**
 * This is the entry point into this library:
 *
 *   var trelloApp = new TrelloApp.App({
 *     version: '1',
 *     log: Log,
 *   })
 *
 * @param {object} {
 *   version: {string} version [OPTIONAL] The version of the Trello API being used, defaults to 1.0
 *   log: {object} logging library [OPTIONAL] a logging object that provides an API similar to Log (MqTFuiXcPtS5rVUZ_jC9Z4tnfWGfgtIUb) - see EmptyLogLibrary
 * }
 */

function App(config) {

  // Extract the config parameters

  var version = config.hasOwnProperty('version') ? config.version : '1'
  Api_.setVersion(version)

  var spreadsheet = SpreadsheetApp.getActiveSpreadsheet()

  if (config.hasOwnProperty('log') && spreadsheet !== null) {

    // This library is running in the context of a spreadsheet so use
    // it for trace logging

    Log_ = config.log

    Log_.init({
      level: LOG_LEVEL,
      sheetId: spreadsheet.getId(),
      displayFunctionNames: LOG_DISPLAY_FUNCTION_NAMES})
  }

  /**
   * If an error is thrown the first thing to try is displaying this
   * URI to the user to trigger Trello authorization pop-up, then get
   * them to try again.
   */

  // TODO - Probably a nicer way of doing that

  App.prototype.getAuthorizationUri = function() {

    return AUTHORIZATION_URI

  } // App.prototype.getAuthorizationUrl()

  /**
   *
   */

  App.prototype.reset = function() {

    Authorizer_.resetTrello()

  } // App.prototype.reset()

  /**
   * Get the users boards
   *
   * @param {object} params
   *   filter: {string} one of the Trello API filter values
   *
   * @return {object} wrapped board object or null
   */

  App.prototype.getMyBoards = function(params) {

    var config = {
      service: 'members',
      id: 'me',
      elements: 'boards',
    }

    if (typeof params !== 'undefined' && params.hasOwnProperty('filter')) {
      config.filter = params.filter
    }

    var responseJSON = Api_.fetch(config)

    if (responseJSON === null) {
      return null
    }

    var response = JSON.parse(responseJSON)

    var obj = {}
    obj.boards = response

    this.boards = Wrapper_.wrapObjects(this, new Board_(), obj.boards)
    return this.boards

  } // App.prototype.getMyBoards()

  /**
   * Get all of the lists for a particular board
   *
   * @return {object} wrapped list object or null
   */

  App.prototype.getBoardLists = function(boardId) {

    var config = {
      service: 'boards',
      id: boardId,
      elements: 'lists',
    }

    var responseJSON = Api_.fetch(config)

    if (responseJSON === null) {
      return null
    }

    var response = JSON.parse(responseJSON)

    var obj = {}
    obj.lists = response

    this.lists = Wrapper_.wrapObjects(this, new List_(), obj.lists)

    return this.lists

  } // App.getBoardLists()

  /**
   * Get all of the users organisations
   *
   * @return {object} wrapped organisation object or null
   */

  App.prototype.getMyOrganizations = function() {

    var config = {
      service: 'members',
      id: 'me',
      elements: 'organizations',
    }

    var responseJSON = Api_.fetch(config)

    if (responseJSON === null) {
      return null
    }

    var response = JSON.parse(responseJSON)

    var obj = {}
    obj.organizations = response

    this.organizations = Wrapper_.wrapObjects(
      this,
      new Organizations_(),
      obj.organizations)

    return this.organizations

  } // App.prototype.getMyOrganizations()

  /*
   * @param {object} config This becomes the payload for the cards API call,
   *                        so matches the
   *
   * From docs: https://developers.trello.com/advanced-reference/card#post-1-cards,
   * although the 'requirements' have changed
   *
   *   name (required) Valid Values: The name of the new card. It isn't required if the name is being copied from provided by a URL, file or card that is being copied.
   *   desc (optional) Valid Values: a string with a length from 0 to 16384
   *   pos (optional) Default: bottom Valid Values: A position. top, bottom, or a positive number.
   *   due (optional) Default: null Valid Values: A date
   *   idList (required) Valid Values: id of the list that the card should be added to
   *   idMembers (optional) Valid Values: A comma-separated list of objectIds, 24-character hex strings
   *   idLabels (optional) Valid Values: A comma-separated list of objectIds, 24-character hex strings
   *   urlSource (optional) Default: null Valid Values: A URL starting with http:// or https:// or null
   *   fileSource (optional) Valid Values: A file
   *   idCardSource (optional) Valid Values: The id of the card to copy into a new card.
   *   keepFromSource (optional) Default: all Valid Values: Properties of the card to copy over from the source.
   *
   * @return {object} response text or null
   */

  App.prototype.createCard = function(config) {

    assertStringNotEmpty_(config.name, 'App.createCard() needs a name for the card')
    assertStringNotEmpty_(config.idList, 'App.createCard() needs an id list for the card')

    setDefault_(config.due, null)
    setDefault_(config.urlSource, 'App.createCard() needs a url source for the card')

    var options = {
      httpMethod: 'POST',
      service: 'cards',
      payload: config,
    }

    var responseJSON = Api_.fetch(options)

    if (responseJSON === null) {
      return null
    }

    var response = JSON.parse(responseJSON)

    // TODO - What's this look like??
    return response

  } // createCard()

} // App()
<|endoftext|>


<commit_before>!function(e){"use strict";var n=e.document,t=function(e,n){if("undefined"!=typeof XMLHttpRequest){var t;t=new XMLHttpRequest,t.onreadystatechange=function(){4===t.readyState&&200===t.status&&n(t.responseText)},t.open("GET",e,!0),t.send()}},a=function(e){return n.createElement(e)},i=function(e,t){t=t||"alert";var i=a("div"),l=a("div"),d=a("div"),c=a("div"),f=a("div"),u="modal "+t;if(s(i,u),s(l,"modal-wrapper"),s(d,"modal-content"),s(c,"text"),c.innerHTML='
'+e.firstLine+'

'+e.secondLine+"
",d.appendChild(c),l.appendChild(d),i.appendChild(l),"confirm"===t){s(f,"confirmBox"),f.innerHTML='
Show All WordsHide Bad Words
',d.appendChild(f);var m=f.getElementsByTagName("a");r(m,"click",function(e){var t=e.target.hash.replace("#","");t.length>0&&("nope"===t&&s(n.body,"hide-harsh"),"okay"===t&&o(n.body,"hide-harsh"),o(i,"open"),s(i,"close"),o(n.getElementById("main"),"blur")),e.preventDefault()})}s(n.getElementById("main"),"blur"),n.body.appendChild(i),setTimeout(function(){s(i,"open")},100)},s=function(e,n){if(e){var t=e.className;return-1===t.indexOf(n)&&(null===t||""===t?e.className=n:e.className+=" "+n),e}},o=function(e,n){var t=e.className;return-1!==t.indexOf(" "+n)?void(e.className=e.className.replace(" "+n,"")):-1!==t.indexOf(n+" ")?void(e.className=e.className.replace(n+" ","")):-1!==t.indexOf(n)?void(e.className=e.className.replace(n,"")):e},r=function(n,t,a){var i=function(n){e.addEventListener?n.addEventListener(t,a,!1):e.attachEvent&&n.attachEvent(t,a,!1)};if("object"==typeof n&&n.length>0)for(var s=0;s<n.length;s++)i(n[s]);else i(n)};e.utils={ajax:t,listenEvent:r,addClass:s,removeClass:o,simpleModal:i}}(this),function(e,n,t){"use strict";var a=function(){return confirm("Are you sure?")},i=function(){var e=n.getElementById("shittyVersion");t.ajax("/manifest.json",function(n){e.innerHTML="v"+JSON.parse(n).version})},s=function(n){n.addEventListener("click",function(n){if(n.preventDefault(),"hire-me"===n.target.className&&!a())return!1;var t=-1!==n.target.protocol.search("http")&&!0;return t&&n.target.host!==e.location.hostname?e.open(n.target.href,"_blank"):void(e.location.href=n.target.href)},!1)},o=function(){var e=n.getElementById("yearsOld"),t=(new Date).getFullYear()-1982;e.innerHTML=t},r=function(){for(var e=n.getElementsByTagName("a"),t=0;t<e.length;t++)s(e[t])},l=function(e){var t=n.getElementsByTagName("html")[0];t.className=t.className.replace("no-js",""),e&&(t.className=t.className+" "+e)},d=function(){t.addClass(n.getElementById("preloader"),"displayHide"),t.removeClass(n.getElementById("main"),"hide"),t.simpleModal({firstLine:"“True spirit of Zen, allowing your bright side coexist with your dark one.”",secondLine:'This website contain an harsh language that could offendsomeone as well as isn\'t such professional. So, if you are thinkingto propose me a job choose "Hide Bad Words" below.'},"confirm")},c=function(){l(),o(),r(),i()};t.listenEvent(n,"DOMContentLoaded",c),t.listenEvent(e,"load",d)}(this,this.document,this.utils);<commit_msg>New build v0.1.0<commit_after>!function(e){"use strict";var n=e.document,t=function(e,n){if("undefined"!=typeof XMLHttpRequest){var t;t=new XMLHttpRequest,t.onreadystatechange=function(){4===t.readyState&&200===t.status&&n(t.responseText)},t.open("GET",e,!0),t.send()}},a=function(e){return n.createElement(e)},i=function(e,t){t=t||"alert";var i=a("div"),l=a("div"),d=a("div"),c=a("div"),f=a("div"),u="modal "+t;if(s(i,u),s(l,"modal-wrapper"),s(d,"modal-content"),s(c,"text"),c.innerHTML='
'+e.firstLine+'

'+e.secondLine+"
",d.appendChild(c),l.appendChild(d),i.appendChild(l),"confirm"===t){s(f,"confirmBox"),f.innerHTML='
Show All WordsHide Bad Words
',d.appendChild(f);var m=f.getElementsByTagName("a");r(m,"click",function(e){var t=e.target.hash.replace("#","");t.length>0&&("nope"===t&&s(n.body,"hide-harsh"),"okay"===t&&o(n.body,"hide-harsh"),o(i,"open"),s(i,"close"),o(n.getElementById("main"),"blur")),e.preventDefault()})}s(n.getElementById("main"),"blur"),n.body.appendChild(i),setTimeout(function(){s(i,"open")},100)},s=function(e,n){if(e){var t=e.className;return-1===t.indexOf(n)&&(null===t||""===t?e.className=n:e.className+=" "+n),e}},o=function(e,n){var t=e.className;return-1!==t.indexOf(" "+n)?void(e.className=e.className.replace(" "+n,"")):-1!==t.indexOf(n+" ")?void(e.className=e.className.replace(n+" ","")):-1!==t.indexOf(n)?void(e.className=e.className.replace(n,"")):e},r=function(n,t,a){var i=function(n){e.addEventListener?n.addEventListener(t,a,!1):e.attachEvent&&n.attachEvent(t,a,!1)};if("object"==typeof n&&n.length>0)for(var s=0;s<n.length;s++)i(n[s]);else i(n)};e.utils={ajax:t,listenEvent:r,addClass:s,removeClass:o,simpleModal:i}}(this),function(e,n,t){"use strict";var a=function(){return confirm("Are you sure?")},i=function(){var e=n.getElementById("shittyVersion");t.ajax("/manifest.json",function(n){e.innerHTML="v"+JSON.parse(n).version})},s=function(n){n.addEventListener("click",function(n){if(n.preventDefault(),"hire-me"===n.target.className&&!a())return!1;var t=-1!==n.target.protocol.search("http")&&!0;return t&&n.target.host!==e.location.hostname?e.open(n.target.href,"_blank"):void(e.location.href=n.target.href)},!1)},o=function(){var e=n.getElementById("yearsOld"),t=(new Date).getFullYear()-1982;e.innerHTML=t},r=function(){for(var e=n.getElementsByTagName("a"),t=0;t<e.length;t++)s(e[t])},l=function(e){var t=n.getElementsByTagName("html")[0];t.className=t.className.replace("no-js",""),e&&(t.className=t.className+" "+e)},d=function(){t.addClass(n.getElementById("preloader"),"displayHide"),t.removeClass(n.getElementById("main"),"hide"),t.simpleModal({firstLine:"“True spirit of Zen, allowing your bright side coexist with your dark one.”",secondLine:'This website contain an harsh language that could offend someone as well as isn\'t such professional. So, if you are thinking to propose me a job choose "Hide Bad Words" below.'},"confirm")},c=function(){l(),o(),r(),i()};t.listenEvent(n,"DOMContentLoaded",c),t.listenEvent(e,"load",d)}(this,this.document,this.utils);<|endoftext|>


<commit_before>'use strict';

var main = function() {

    var serverUrl = 'https://jalgoarena.herokuapp.com';

    var editor = ace.edit("editor");
    editor.setTheme("ace/theme/tomorrow_night_eighties");
    editor.getSession().setMode("ace/mode/java");

    var $problems = $('#problems');

    $problems.on('click', '.problem', function (e) {
        $('#output').html('
Submit your code to see results
');
        $('.problem.active').removeClass('active');
        var problemId = e.currentTarget.id;
        $('#' + problemId).addClass('active');

        $.ajax({
            type: "GET",
            dataType: 'json',
            url: serverUrl + '/problems/' + problemId,
            crossDomain: true
        }).done(function (problem) {
            $('#problem-title').text(problem.title);
            $('#problem-description').text(problem.description);
            $('#problem-example-input').text(problem.example.input);
            $('#problem-example-output').text(problem.example.output);
            $('#problem-example-time-limit').text(problem.time_limit);
            $('#problem-example-memory-limit').text(problem.memory_limit);

            $.ajax({
                type: "GET",
                dataType: 'text',
                url: serverUrl + '/problems/' + problemId + '/skeletonCode',
                crossDomain: true
            }).done(function (skeletonCode) {
                editor.setValue(skeletonCode, 1);
            });
        });
    });

    $.ajax({
        type: "GET",
        dataType: 'json',
        url: serverUrl + '/problems/',
        crossDomain: true
    }).done(function (problems) {

        var first = true;
        problems.forEach(function (problem) {
            if (first) {
                $problems.append(
                    '
' + problem + '(current)
'
                );
                first = false;
            } else {
                $problems.append('
' + problem + '
')
            }
        });

        $problems.children().first().click();
    });

    $('#submit-code').click(function () {
        var problemId = $('.problem.active').attr('id');
        var sourceCode = editor.getValue();

        $.ajax({
            type: "POST",
            data: sourceCode,
            processData: false,
            contentType: 'text/plain',
            url: serverUrl + '/problems/' + problemId + '/solution',
            crossDomain: true
        }).done(function (result) {

            var $output = $('#output');

            switch (result.status_code) {
                case 'ACCEPTED':
                    $output.html('
All test cases passed, congratulations!
');

                    result.testcase_results.forEach(function(testCasePassed, i) {
                        $output.append(
                            '
' +
                            ' Test Case #' + (i + 1)  +
                            '
');
                    });
                    break;
                case 'WRONG_ANSWER':
                    $output.html('
Wrong Answer
');

                    result.testcase_results.forEach(function(testCasePassed, i) {
                        $output.append(
                            '
' +
                                ' Test Case #' + (i + 1)  +
                            '
');
                    });

                    break;
                case 'COMPILE_ERROR':
                    $output.html('
Compilation Error
');
                    $output.append('
' + result.error_message + '
');
                    break;
                case 'RUNTIME_ERROR':
                    $output.html(
                        '
Runtime Error: ' + result.error_message + '
'
                    );
                    break;
                case 'TIME_LIMIT_EXCEEDED':
                    $output.html('
Time Limit Exceeded
');
                    break;
                case 'MEMORY_LIMIT_EXCEEDED':
                    $output.html('
Memory Limit Exceeded!
');
                    break;
            }
        });
    });
};

$(document).ready(main);<commit_msg>- cleanup code a bit<commit_after>'use strict';

var main = function() {

    var serverUrl = 'https://jalgoarena.herokuapp.com';

    var editor = ace.edit("editor");
    editor.setTheme("ace/theme/tomorrow_night_eighties");
    editor.getSession().setMode("ace/mode/java");

    var $problems = $('#problems');

    var updateProblem = function (problem, problemId) {
        $('#problem-title').text(problem.title);
        $('#problem-description').text(problem.description);
        $('#problem-example-input').text(problem.example.input);
        $('#problem-example-output').text(problem.example.output);
        $('#problem-example-time-limit').text(problem.time_limit);
        $('#problem-example-memory-limit').text(problem.memory_limit);

        $.ajax({
            type: "GET",
            dataType: 'text',
            url: serverUrl + '/problems/' + problemId + '/skeletonCode',
            crossDomain: true
        }).done(function (skeletonCode) {
            editor.setValue(skeletonCode, 1);
        });
    };

    $problems.on('click', '.problem', function (e) {
        $('#output').html('
Submit your code to see results
');
        $('.problem.active').removeClass('active');
        var problemId = e.currentTarget.id;
        $('#' + problemId).addClass('active');

        $.ajax({
            type: "GET",
            dataType: 'json',
            url: serverUrl + '/problems/' + problemId,
            crossDomain: true
        }).done(function (problem) {
            updateProblem(problem, problemId);
        });
    });

    var updateProblems = function (problems) {
        var first = true;
        problems.forEach(function (problem) {
            if (first) {
                $problems.append(
                    '
' + problem + '(current)
'
                );
                first = false;
            } else {
                $problems.append('
' + problem + '
')
            }
        });

        $problems.children().first().click();
    };
    $.ajax({
        type: "GET",
        dataType: 'json',
        url: serverUrl + '/problems/',
        crossDomain: true
    }).done(updateProblems);

    var processSubmission = function (result) {
        var $output = $('#output');

        switch (result.status_code) {
            case 'ACCEPTED':
                $output.html('
All test cases passed, congratulations!
');

                result.testcase_results.forEach(function (testCasePassed, i) {
                    $output.append(
                        '
' +
                        ' Test Case #' + (i + 1) +
                        '
');
                });
                break;
            case 'WRONG_ANSWER':
                $output.html('
Wrong Answer
');

                result.testcase_results.forEach(function (testCasePassed, i) {
                    $output.append(
                        '
' +
                        ' Test Case #' + (i + 1) +
                        '
');
                });

                break;
            case 'COMPILE_ERROR':
                $output.html('
Compilation Error
');
                $output.append('
' + result.error_message + '
');
                break;
            case 'RUNTIME_ERROR':
                $output.html(
                    '
Runtime Error: ' + result.error_message + '
'
                );
                break;
            case 'TIME_LIMIT_EXCEEDED':
                $output.html('
Time Limit Exceeded
');
                break;
            case 'MEMORY_LIMIT_EXCEEDED':
                $output.html('
Memory Limit Exceeded!
');
                break;
        }
    };

    $('#submit-code').click(function () {
        var problemId = $('.problem.active').attr('id');
        var sourceCode = editor.getValue();

        $.ajax({
            type: "POST",
            data: sourceCode,
            processData: false,
            contentType: 'text/plain',
            url: serverUrl + '/problems/' + problemId + '/solution',
            crossDomain: true
        }).done(processSubmission);
    });
};

$(document).ready(main);
<|endoftext|>


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

.controller('eccFormController', ['$scope', function($scope) {
  var b0 = new BN('0', 10);
  var b1 = new BN('1', 10);
  var b2 = new BN('2', 10);
  var b3 = new BN('3', 10);
  var b23 = new BN('23', 10);

  var c23 = {
    prime: b23,
    equation: 'y\u00b2 = x\u00b3 + x',
    a: b1,
    b: b0,
    generators: [
      [new BN('11', 10), new BN('13', 10)],
      [new BN('17', 10), new BN('13', 10)],
      [new BN('19', 10), new BN('22', 10)],
      [new BN('21', 10), new BN('17', 10)]
    ],
    pOnCurve: function(p) {
      var valid = true;
      //invalid x coordinate
      if(p[0].cmp(b0) < 0 || p[0].cmp(b23) >= 0 ) valid = false;
      //invalid y coordinate
      if(p[1].cmp(b0) < 0 || p[1].cmp(b23) >= 0 ) valid = false;
      //doesn't satisfy y^2=x^3+x
      if(p[1].pow(b2).umod(b23)
          .cmp( p[0].pow(b3).iadd(p[0]).umod(b23) ) !== 0) valid = false;
      if(!valid) console.log('point p: ' + p.toString() + ' is not on curve.');
      return valid;
    }
  };

  var addPoints = function(p, q) {
    var valid = true;
    if( p === Number.POSITIVE_INFINITY ) return q;
    if( !validP(p, c23) || !validP(q, c23) ) valid = false;
    if(p[0].cmp(q[0]) === 0 && p[1].cmp(q[1]) === 0) valid = false;
    if(p[0].cmp(q[0]) === 0 && q[1].cmp(p[1].neg().umod(c23.prime)) === 0) valid = false;
    if(!valid) {
      console.log('point p or q can\'t add. p:' + p + ' q:' + q);
      return valid;
    }

    var s = p[1].sub(q[1]).mul(p[0].sub(q[0]).invm(c23.prime)).umod(c23.prime);
    var xR = s.pow(b2).sub(p[0]).sub(q[0]).umod(c23.prime);
    var yR = s.mul(p[0].sub(xR)).sub(p[1]).umod(c23.prime);
    return [xR, yR];
  };

  var doubleP = function(p) {
    var valid = true;
    if( !validP(p, c23) || p[1].cmp(b0) === 0 ) valid = false;
    if( p === Number.POSITIVE_INFINITY ) valid = false;
    if(!valid) {
      console.log('point p can\'t be doubled. p:' + p);
      return valid;
    }

    //Double
    var s = p[0].pow(b2).mul(b3).add(c23.a).mul(p[1].mul(b2).invm(c23.prime)).umod(c23.prime);
    var xR = s.pow(b2).sub(p[0].mul(b2)).umod(c23.prime);
    var yR = s.mul(p[0].sub(xR)).sub(p[1]).umod(c23.prime);
    return [xR, yR];
  }

  var scalarMult = function(p, k) {
    if( !validP(p, c23) || k.cmp(b0) < 1 || p === Number.POSITIVE_INFINITY ) {
      console.log('point p can\'t be multiplied by k. p:' + p + ' k:' + k.toString());
      return false;
    }

    var len = k.bitLength();
    var R = Number.POSITIVE_INFINITY;
    var N = [p[0].clone(), p[1].clone()];
    for(var bit = 0; bit < len; bit++) {
      if(k.testn(bit)) {
        R = addPoints(R, N);
      }
      N = doubleP(N);
    }
    return R;
  }

  var validP = function(p, c) {
    //Using Infinity as the '0 point' in ECC
    if( p === Number.POSITIVE_INFINITY ) return true;
    var valid;
    if( Object.prototype.toString.call(p) !== '[object Array]' ||
        p.length !== 2 ) {
      valid = false;
    } else {
     valid = c.pOnCurve(p);
    }
    if(!valid) console.log('point was not valid on curve. p:' + p.toString());
    return valid;
  };

  $scope.curve = c23;
  $scope.genChoice = '0';
  $scope.cPoints = [];
  $scope.genPoints = function() {
    var g = c23.generators[parseInt($scope.genChoice, 10)];
    $scope.cPoints = [];
    for(var i=1; i<=c23.prime; i++) {
      $scope.cPoints.push(scalarMult(g, new BN(i.toString(), 10)));
    }
  };

}]);
<commit_msg>Added some much needed comments<commit_after>angular.module('eccApp',[])

.controller('eccFormController', ['$scope', function($scope) {

/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~v Necessary Vars v~~~~~~~~~~~~~~~~~~~~~~~~~~ */

  //commonly used 'big' numbers
  var b0 = new BN('0', 10);
  var b1 = new BN('1', 10);
  var b2 = new BN('2', 10);
  var b3 = new BN('3', 10);
  var b23 = new BN('23', 10);

  //data about example curve
  var c23 = {
    prime: b23,
    equation: 'y\u00b2 = x\u00b3 + x',
    a: b1,
    b: b0,
    generators: [
      [new BN('11', 10), new BN('13', 10)],
      [new BN('17', 10), new BN('13', 10)],
      [new BN('19', 10), new BN('22', 10)],
      [new BN('21', 10), new BN('17', 10)]
    ],
    pOnCurve: function(p) {
      var valid = true;
      //invalid x coordinate
      if(p[0].cmp(b0) < 0 || p[0].cmp(b23) >= 0 ) valid = false;
      //invalid y coordinate
      if(p[1].cmp(b0) < 0 || p[1].cmp(b23) >= 0 ) valid = false;
      //doesn't satisfy y^2=x^3+x
      if(p[1].pow(b2).umod(b23)
          .cmp( p[0].pow(b3).iadd(p[0]).umod(b23) ) !== 0) valid = false;
      if(!valid) console.log('point p: ' + p.toString() + ' is not on curve.');
      return valid;
    }
  };

/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~v ECC op. functions v~~~~~~~~~~~~~~~~~~~~~~~~~ */

  // P + Q = R, where P != Q && P != -Q
  var addPoints = function(p, q) {
    var valid = true;
    if( p === Number.POSITIVE_INFINITY ) return q;
    if( !validP(p, c23) || !validP(q, c23) ) valid = false;
    if(p[0].cmp(q[0]) === 0 && p[1].cmp(q[1]) === 0) valid = false;
    if(p[0].cmp(q[0]) === 0 && q[1].cmp(p[1].neg().umod(c23.prime)) === 0) valid = false;
    if(!valid) {
      console.log('point p or q can\'t add. p:' + p + ' q:' + q);
      return valid;
    }

    var s = p[1].sub(q[1]).mul(p[0].sub(q[0]).invm(c23.prime)).umod(c23.prime);
    var xR = s.pow(b2).sub(p[0]).sub(q[0]).umod(c23.prime);
    var yR = s.mul(p[0].sub(xR)).sub(p[1]).umod(c23.prime);
    return [xR, yR];
  };

  // 2P = R
  var doubleP = function(p) {
    var valid = true;
    if( !validP(p, c23) || p[1].cmp(b0) === 0 ) valid = false;
    if( p === Number.POSITIVE_INFINITY ) valid = false;
    if(!valid) {
      console.log('point p can\'t be doubled. p:' + p);
      return valid;
    }

    //Double
    var s = p[0].pow(b2).mul(b3).add(c23.a).mul(p[1].mul(b2).invm(c23.prime)).umod(c23.prime);
    var xR = s.pow(b2).sub(p[0].mul(b2)).umod(c23.prime);
    var yR = s.mul(p[0].sub(xR)).sub(p[1]).umod(c23.prime);
    return [xR, yR];
  }

  // kP = R, 0 < k <= prime, P != '0'
  var scalarMult = function(p, k) {
    if( !validP(p, c23) || k.cmp(b0) < 1 || p === Number.POSITIVE_INFINITY ) {
      console.log('point p can\'t be multiplied by k. p:' + p + ' k:' + k.toString());
      return false;
    }

    var len = k.bitLength();
    var R = Number.POSITIVE_INFINITY;
    var N = [p[0].clone(), p[1].clone()];
    for(var bit = 0; bit < len; bit++) {
      if(k.testn(bit)) {
        R = addPoints(R, N);
      }
      N = doubleP(N);
    }
    return R;
  }

  // P is valid for usage && on curve
  var validP = function(p, c) {
    //Using Infinity as the '0 point' in ECC
    if( p === Number.POSITIVE_INFINITY ) return true;
    var valid;
    if( Object.prototype.toString.call(p) !== '[object Array]' ||
        p.length !== 2 ) {
      valid = false;
    } else {
     valid = c.pOnCurve(p);
    }
    if(!valid) console.log('point was not valid on curve. p:' + p.toString());
    return valid;
  };

/* ~~~~~~~~~~~~~~~~~~~~~~~~~v AngularJS gadgetry v~~~~~~~~~~~~~~~~~~~~~~~~~~ */

  //General usage vars
  $scope.curve = c23;

  //Point generation vars and functions
  $scope.genChoice = '0';
  $scope.cPoints = [];
  $scope.clearPoints = function() {
    $scope.cPoints = [];
  };
  $scope.genPoints = function() {
    var g = c23.generators[parseInt($scope.genChoice, 10)];
    $scope.cPoints = [];
    for(var i=1; i<=c23.prime; i++) {
      $scope.cPoints.push(scalarMult(g, new BN(i.toString(), 10)));
    }
  };

}]);
<|endoftext|>


<commit_before>require('log-timestamp');

const exec = require('child_process').exec;
const args = process.argv.slice(2);

if (args.length < 4) {
  console.error('\x1b[31m', 'Please provide paths to node_modules, the input and the output directory and output file');
} else {
  exec(`node ${args[0]}/.bin/node-sass ${args[1]} -o ${args[2]} --source-map true --include-path ${args[0]}`, (err) => {
    if (err) {
      return console.error('\x1b[31m', err);
    }

    console.log('\x1b[32m', `CSS built to file ${args[3]}`);
  });
}
<commit_msg>Update css script to use sass isntead of node-sass.<commit_after>require('log-timestamp');

const exec = require('child_process').exec;
const args = process.argv.slice(2);

if (args.length < 4) {
  console.error('\x1b[31m', 'Please provide paths to node_modules, the input and the output directory and output file');
} else {
  exec(`npx sass -I ${args[0]} ${args[1]}:${args[2]}`, (err) => {
    if (err) {
      return console.error('\x1b[31m', err);
    }

    console.log('\x1b[32m', `CSS built to file ${args[3]}`);
  });
}
<|endoftext|>


<commit_before>define(["jquery", "gmaps", "events"], function($, gmaps, events) {

  function Map(selector, mapOptions) {

    var map = new gmaps.Map($(selector)[0], mapOptions);
    var overlays = [];
    var currentTrackPointIcon = {
      path: "m-8,0 a8,8 0 1,0 16,0 a8,8 0 1,0 -16,0 m3,0 a5,5 0 1,0 10,0 a5,5 0 1,0 -10,0",
      strokeColor: "white",
      strokeWeight: 2,
      strokeOpacity: 0.6,
      fillColor: "blue",
      fillOpacity: 1
    };
    var currentTrackPoint = new gmaps.Marker({
      map: map,
      zIndex: gmaps.Marker.MAX_ZINDEX,
      icon: currentTrackPointIcon
    });
    var currentTrackRanges = [];
    var openedInfoWindow = null;

    events.handle(events.TRACK_POINT_HOVER, function(event) {
      var trackPoint = event.data.trackPoint;
      if (trackPoint) {
        currentTrackPoint.setPosition(trackPoint.position);
        if (currentTrackPoint.map == null) {
          currentTrackPoint.setMap(map);
        }
      }
      else {
        currentTrackPoint.setMap(null);
      }
    });

    events.handle(events.TRACK_RANGE_CHANGE, function(event) {
      var track = event.data.track;
      var trackPoints = event.data.trackPoints;
      var path = $.map(trackPoints, function(trackPoint) { return trackPoint.position; });
      var trackRange = currentTrackRanges[track.id];
      if (trackRange) {
        trackRange.setPath(path);
        fitAndCenter(path);
      }
    });

    function drawMarker(opts) {
      opts.map = map;
      var marker = new gmaps.Marker(opts);
      overlays.push(marker);
      return marker;
    }

    function drawPolyline(opts) {
      opts.map = map;
      var polyline = new gmaps.Polyline(opts);
      overlays.push(polyline);
      return polyline;
    }

    function fitAndCenter(points) {
      var bounds = new gmaps.LatLngBounds();
      $.each(points, function() { bounds.extend(this); });
      map.fitBounds(bounds);
    }

    this.drawWayPoints = function(wayPoints, icon) {
      $.each(wayPoints, function() {
        var marker = drawMarker({
          position: this.position,
          icon: icon
        });
        var infoWindow = new gmaps.InfoWindow({
          content: "
" + this.name + "

" + this.desc + "
"
        });
        gmaps.event.addListener(marker, "click", function() {
          if (openedInfoWindow) {
            openedInfoWindow.close();
          }
          infoWindow.open(map, marker);
          openedInfoWindow= infoWindow;
        });
      });
    };

    this.drawTrack = function(track) {
      var path = track.toPath();
      drawPolyline({ path: path, clickable: false });
      var trackRange = drawPolyline({
        path: path,
        zIndex: gmaps.Marker.MAX_ZINDEX - 1,
        strokeColor: "red",
        strokeOpacity: 0.5,
        strokeWeight: 20
       });
      currentTrackRanges[track.id] = trackRange;
      drawMarker({
        position: path[0],
        zIndex: gmaps.Marker.MAX_ZINDEX - 3,
        icon: "http://maps.google.com/mapfiles/dd-start.png",
        title: "Start"
      });
      drawMarker({
        position: path[path.length - 1],
        zIndex: gmaps.Marker.MAX_ZINDEX - 2,
        icon: "http://maps.google.com/mapfiles/dd-end.png",
        title: "End"
      });
      var trackPointsWithName = $.grep(track.trackPoints, function(trackPoint) {
        return trackPoint.name;
      });
      this.drawWayPoints(trackPointsWithName, {
        path: gmaps.SymbolPath.CIRCLE,
        scale: 5,
        strokeColor: "white",
        strokeWeight: 2,
        strokeOpacity: 0.6,
        fillColor: "blue",
        fillOpacity: 1
      });
      gmaps.event.addListener(trackRange, 'mousemove', function(event) {
        events.fire(events.TRACK_POINT_HOVER, { trackPoint: track.findNearestTrackPoint(event.latLng) });
      });
      gmaps.event.addListener(trackRange, 'mouseout', function(event) {
        events.fire(events.TRACK_POINT_HOVER, { trackPoint: null });
      });
      fitAndCenter(path);
    };

    this.clear = function() {
      $.each(overlays, function() { this.setMap(null); });
    };
  }

  function create(selector) {
    var myLatLng = new google.maps.LatLng(0, -180);
    var mapOptions = {
      zoom: 3,
      center: myLatLng,
      mapTypeId: google.maps.MapTypeId.TERRAIN
    };
    return new Map(selector, mapOptions);
  }

  return {
    create: create
  };

});

// vim: et:si:sw=2:sts=2
<commit_msg>Use blue for track range.<commit_after>define(["jquery", "gmaps", "events"], function($, gmaps, events) {

  function Map(selector, mapOptions) {

    var map = new gmaps.Map($(selector)[0], mapOptions);
    var overlays = [];
    var currentTrackPointIcon = {
      path: "m-8,0 a8,8 0 1,0 16,0 a8,8 0 1,0 -16,0 m3,0 a5,5 0 1,0 10,0 a5,5 0 1,0 -10,0",
      strokeColor: "white",
      strokeWeight: 2,
      strokeOpacity: 0.6,
      fillColor: "blue",
      fillOpacity: 1
    };
    var currentTrackPoint = new gmaps.Marker({
      map: map,
      zIndex: gmaps.Marker.MAX_ZINDEX,
      icon: currentTrackPointIcon
    });
    var currentTrackRanges = [];
    var openedInfoWindow = null;

    events.handle(events.TRACK_POINT_HOVER, function(event) {
      var trackPoint = event.data.trackPoint;
      if (trackPoint) {
        currentTrackPoint.setPosition(trackPoint.position);
        if (currentTrackPoint.map == null) {
          currentTrackPoint.setMap(map);
        }
      }
      else {
        currentTrackPoint.setMap(null);
      }
    });

    events.handle(events.TRACK_RANGE_CHANGE, function(event) {
      var track = event.data.track;
      var trackPoints = event.data.trackPoints;
      var path = $.map(trackPoints, function(trackPoint) { return trackPoint.position; });
      var trackRange = currentTrackRanges[track.id];
      if (trackRange) {
        trackRange.setPath(path);
        fitAndCenter(path);
      }
    });

    function drawMarker(opts) {
      opts.map = map;
      var marker = new gmaps.Marker(opts);
      overlays.push(marker);
      return marker;
    }

    function drawPolyline(opts) {
      opts.map = map;
      var polyline = new gmaps.Polyline(opts);
      overlays.push(polyline);
      return polyline;
    }

    function fitAndCenter(points) {
      var bounds = new gmaps.LatLngBounds();
      $.each(points, function() { bounds.extend(this); });
      map.fitBounds(bounds);
    }

    this.drawWayPoints = function(wayPoints, icon) {
      $.each(wayPoints, function() {
        var marker = drawMarker({
          position: this.position,
          icon: icon
        });
        var infoWindow = new gmaps.InfoWindow({
          content: "
" + this.name + "

" + this.desc + "
"
        });
        gmaps.event.addListener(marker, "click", function() {
          if (openedInfoWindow) {
            openedInfoWindow.close();
          }
          infoWindow.open(map, marker);
          openedInfoWindow= infoWindow;
        });
      });
    };

    this.drawTrack = function(track) {
      var path = track.toPath();
      drawPolyline({ path: path, clickable: false });
      var trackRange = drawPolyline({
        path: path,
        zIndex: gmaps.Marker.MAX_ZINDEX - 1,
        strokeColor: "blue",
        strokeOpacity: 0.5,
        strokeWeight: 20
       });
      currentTrackRanges[track.id] = trackRange;
      drawMarker({
        position: path[0],
        zIndex: gmaps.Marker.MAX_ZINDEX - 3,
        icon: "http://maps.google.com/mapfiles/dd-start.png",
        title: "Start"
      });
      drawMarker({
        position: path[path.length - 1],
        zIndex: gmaps.Marker.MAX_ZINDEX - 2,
        icon: "http://maps.google.com/mapfiles/dd-end.png",
        title: "End"
      });
      var trackPointsWithName = $.grep(track.trackPoints, function(trackPoint) {
        return trackPoint.name;
      });
      this.drawWayPoints(trackPointsWithName, {
        path: gmaps.SymbolPath.CIRCLE,
        scale: 5,
        strokeColor: "white",
        strokeWeight: 2,
        strokeOpacity: 0.6,
        fillColor: "blue",
        fillOpacity: 1
      });
      gmaps.event.addListener(trackRange, 'mousemove', function(event) {
        events.fire(events.TRACK_POINT_HOVER, { trackPoint: track.findNearestTrackPoint(event.latLng) });
      });
      gmaps.event.addListener(trackRange, 'mouseout', function(event) {
        events.fire(events.TRACK_POINT_HOVER, { trackPoint: null });
      });
      fitAndCenter(path);
    };

    this.clear = function() {
      $.each(overlays, function() { this.setMap(null); });
    };
  }

  function create(selector) {
    var myLatLng = new google.maps.LatLng(0, -180);
    var mapOptions = {
      zoom: 3,
      center: myLatLng,
      mapTypeId: google.maps.MapTypeId.TERRAIN
    };
    return new Map(selector, mapOptions);
  }

  return {
    create: create
  };

});

// vim: et:si:sw=2:sts=2
<|endoftext|>


<commit_before>/* Gas Jot state shape design */

{
    userInterface: {

    },
    serverSnapshot: {
        _links: {},
        _embedded: {
            vehicles: {},
            fuelstations: {},
            fplogs: {},
            envlogs: {}
        }
    }
}<commit_msg>removing unneeded file<commit_after><|endoftext|>


<commit_before>
// JSON example
var candidates = [ {
  "name": "Ellie Phanta",
  "party": "Republican",
  "stances" : [1,1]
  },
  {
  "name": "Jack Bass",
  "party": "Democrat",
  "stances" : [1,1]
  },
  {
  "name": "Paul Stanton",
  "party": "Libertarian",
  "stances" : [5,5]
  }
 ];

Questions = [
  {
  "Issue" : "Force",
  "Question" : "Should goods and services be provided by force?",
  "Responses" : [
    ["Absolutely",1],
    ["Yes", 2],
    ["Maybe", 3],
    ["No", 4],
    ["Never", 5]]
},
   {
  "Issue" : "Roads",
  "Question" : "Without government, Who will build the roads?",
  "Responses" : [
    ["No one at all",1],
    ["Shady people you can't trust", 2],
    ["Someone might maybe possibly", 3],
    ["Construction companies", 4],
    ["Where we're going, we won't need roads.", 5]]
}
];

Imports = [["Could not care less",1],["Don't care",2],["Might care",3],["Care",4],["Care a lot",5]];

responses = [];
importance = [];
results = [];

for (i = 0; i < Questions.length; i++) {
  responses.push(3);
  importance.push(3);
}

for (j = 0; j < candidates.length; j++) {
  results.push(responses);
}

function loadQuestions() {
  var chunk = '';
  for (i = 0; i < Questions.length; i++) {
    chunk += '
';
    chunk += '
' + Questions[i].Question + '
';
    chunk += '
';
    for (j = 0; j < Questions[i].Responses.length; j++) {
     var qr = Questions[i].Responses[j];
     chunk += '<button onclick="tally(' + i + ',' + qr[1] + ')">' + qr[0] + '</button>';
    }
    chunk += '
';
    chunk += '
';
    for (k = 0; k < Imports.length; k++) {
     chunk += '<button onclick="tallyImports(' + i + ',' + Imports[k][1] + ')">' + Imports[k][0] + '</button>';
    }
    chunk += '

';
  }
  chunk += '
<button onclick="compareToCandidates()">Calculate</button>
';
  document.getElementById("questionArea").innerHTML = chunk;
};

function tally(questionNumber,response) {
  //qId = 'q' + questionNumber;
  responses[questionNumber] = response;
  document.getElementById("test").innerHTML = responses;
  //document.getElementById(qId).innerHTML = 'Response Recorded';
};

function tallyImports(questionNumber,response) {
  //qId = 'q' + questionNumber;
  importance[questionNumber] = response;
  document.getElementById("test2").innerHTML = importance;
  //document.getElementById(qId).innerHTML = 'Response Recorded';
};

function max(QuestionNumber) {
  qa = Questions[QuestionNumber].Responses;
  var max = 0;
  var test = 0;
  for (i = 1; i < qa.length; i++) {
    for (j = 0; j  max) {
        max = test;
      }
    }
  }
  return max;
};

function compareToCandidates() {
  var resultsStr = '

Candidates	';
  var max = 20;
  var dif = 0;
  var weightedDiff = 0;
  var diffDiff = 0;
  var perc = 0;

  for (i = 0; i < Questions.length; i++) {
    resultsStr += '' + Questions[i].Issue + '	';
  }
  resultsStr += '
';
  for (i = 0; i < candidates.length; i++) {
    resultsStr += '' + candidates[i].name + '	';
    for (j = 0; j < Questions.length; j++) {
      max = max(j); // Maximum possible difference
      dif = Math.abs(responses[j] - candidates[i].stances[j]); // difference between candidate score and your score

      perc = 100 - Math.round(dif/max*100);
      resultsStr += '' + perc.toString() + '%	';

      weightedDiff = diffDiff*importance[j]; // Difference weighted based on importance
      results[i][j] = weightedDiff;
    }
    resultsStr += '
';
  }
  resultsStr += '
';
  document.getElementById("results").innerHTML = resultsStr;
  document.getElementById("test3").innerHTML = results;
};

loadQuestions();
<commit_msg>Update wme.js<commit_after>
// JSON example
var candidates = [ {
  "name": "Ellie Phanta",
  "party": "Republican",
  "stances" : [1,1]
  },
  {
  "name": "Jack Bass",
  "party": "Democrat",
  "stances" : [1,1]
  },
  {
  "name": "Paul Stanton",
  "party": "Libertarian",
  "stances" : [5,5]
  }
 ];

Questions = [
  {
  "Issue" : "Force",
  "Question" : "Should goods and services be provided by force?",
  "Responses" : [
    ["Absolutely",1],
    ["Yes", 2],
    ["Maybe", 3],
    ["No", 4],
    ["Never", 5]]
},
   {
  "Issue" : "Roads",
  "Question" : "Without government, Who will build the roads?",
  "Responses" : [
    ["No one at all",1],
    ["Shady people you can't trust", 2],
    ["Someone might maybe possibly", 3],
    ["Construction companies", 4],
    ["Where we're going, we won't need roads.", 5]]
}
];

Imports = [["Could not care less",1],["Don't care",2],["Might care",3],["Care",4],["Care a lot",5]];

responses = [];
importance = [];
results = [];

for (i = 0; i < Questions.length; i++) {
  responses.push(3);
  importance.push(3);
}

for (j = 0; j < candidates.length; j++) {
  results.push(responses);
}

function loadQuestions() {
  var chunk = '';
  for (i = 0; i < Questions.length; i++) {
    chunk += '
';
    chunk += '
' + Questions[i].Question + '
';
    chunk += '
';
    for (j = 0; j < Questions[i].Responses.length; j++) {
     var qr = Questions[i].Responses[j];
     chunk += '<button onclick="tally(' + i + ',' + qr[1] + ')">' + qr[0] + '</button>';
    }
    chunk += '
';
    chunk += '
';
    for (k = 0; k < Imports.length; k++) {
     chunk += '<button onclick="tallyImports(' + i + ',' + Imports[k][1] + ')">' + Imports[k][0] + '</button>';
    }
    chunk += '

';
  }
  chunk += '
<button onclick="compareToCandidates()">Calculate</button>
';
  document.getElementById("questionArea").innerHTML = chunk;
};

function tally(questionNumber,response) {
  //qId = 'q' + questionNumber;
  responses[questionNumber] = response;
  document.getElementById("test").innerHTML = responses;
  //document.getElementById(qId).innerHTML = 'Response Recorded';
};

function tallyImports(questionNumber,response) {
  //qId = 'q' + questionNumber;
  importance[questionNumber] = response;
  document.getElementById("test2").innerHTML = importance;
  //document.getElementById(qId).innerHTML = 'Response Recorded';
};

function maxi(QuestionNumber) {
  qa = Questions[QuestionNumber].Responses;
  var max = 0;
  var test = 0;
  for (i = 1; i < qa.length; i++) {
    for (j = 0; j  max) {
        max = test;
      }
    }
  }
  return max;
};

function compareToCandidates() {
  var resultsStr = '

Candidates	';
  var max = 20;
  var dif = 0;
  var weightedDiff = 0;
  var diffDiff = 0;
  var perc = 0;

  for (i = 0; i < Questions.length; i++) {
    resultsStr += '' + Questions[i].Issue + '	';
  }
  resultsStr += '
';
  for (i = 0; i < candidates.length; i++) {
    resultsStr += '' + candidates[i].name + '	';
    for (j = 0; j < Questions.length; j++) {
      max = maxi(j); // Maximum possible difference
      dif = Math.abs(responses[j] - candidates[i].stances[j]); // difference between candidate score and your score

      perc = 100 - Math.round(dif/max*100);
      resultsStr += '' + perc.toString() + '%	';

      weightedDiff = diffDiff*importance[j]; // Difference weighted based on importance
      results[i][j] = weightedDiff;
    }
    resultsStr += '
';
  }
  resultsStr += '
';
  document.getElementById("results").innerHTML = resultsStr;
  document.getElementById("test3").innerHTML = results;
};

loadQuestions();
<|endoftext|>