diff --git a/lib/currency.js b/lib/currency.js
index 4a4f3be..bb23f14 100644
--- a/lib/currency.js
+++ b/lib/currency.js
@@ -134,6 +134,17 @@ function Currency(irc, db, commands, options) {
__self.bets_response_timer = 3000;
__self.bets_response_reset = true;
+ // voting settings
+ __self.votes_status = false;
+ __self.votes_board = [];
+ __self.votes_viewers = [];
+ __self.votes_payout = false;
+ __self.votes_total = 0;
+ __self.votes_flood = [];
+ __self.votes_response = null;
+ __self.votes_response_timer = 3000;
+ __self.votes_response_reset = true;
+
// high score table
__self.score_bet_pool = 0;
__self.score_bet_single = 0;
@@ -283,6 +294,33 @@ Currency.prototype.commands = function (data) {
break;
}
}
+
+ // open / close voting system
+ if (data[4] === 'vote') {
+ console.log("vote command found");
+ switch (data[5]) {
+ case 'open':
+ console.log("vote open command found");
+ if (data[6] && data[7]) {
+ __self.votes(true, data);
+ } else {
+ __self.irc.emit('message', {message:__self.pre_text + 'Unable to open voting, need at least two items to vote for'});
+ }
+ break;
+ case 'close':
+ __self.votes(false, null);
+ break;
+ case 'pool':
+ __self.votes('pool', null);
+ break;
+ case 'winner':
+ __self.votes('winner', data[6]);
+ break;
+ case 'cancel':
+ __self.votes('cancel');
+ break;
+ }
+ }
// TODO: create a log file that monitors just add/remove/push - greedy mods :D
// add currency
@@ -432,6 +470,19 @@ Currency.prototype.commands = function (data) {
}
}
}
+ // cast a vote
+ if (__self.votes_status === true) {
+ for (var i = 0; i < __self.votes_board.length; i++) {
+ if (data[3].slice(1) === '!' + __self.votes_board[i].name) {
+ if (isNaN(parseInt(data[4], 10)) === false) {
+ if (data[4] >= 0 && data[4] % 1 === 0) {
+ __self.collect_votes(__self.irc.caller(data[0]), __self.votes_board[i], parseInt(data[4], 10));
+ break;
+ }
+ }
+ }
+ }
+ }
};
/**
@@ -956,48 +1007,50 @@ Currency.prototype.auction = function (status) {
switch (status) {
case true:
- if (!__self.bets_status) {
- if (!__self.raffle_status) {
- if (!__self.auction_status) {
- // open up the auction
- __self.auction_status = true;
+ if (!__self.votes_status) {
+ if (!__self.bets_status) {
+ if (!__self.raffle_status) {
+ if (!__self.auction_status) {
+ // open up the auction
+ __self.auction_status = true;
- // request toggle
- if (__self.temp.raffle_toggle) {
- __self.temp.auction_toggle = __self.temp.raffle_toggle;
- } else {
- __self.temp.auction_toggle = __self.coin_toggle;
- }
- __self.coin_toggle = false;
+ // request toggle
+ if (__self.temp.raffle_toggle) {
+ __self.temp.auction_toggle = __self.temp.raffle_toggle;
+ } else {
+ __self.temp.auction_toggle = __self.coin_toggle;
+ }
+ __self.coin_toggle = false;
- // default request timer
- if (__self.temp.raffle_timer && __self.temp.raffle_timer_reset) {
- __self.temp.auction_timer = __self.temp.raffle_timer;
- __self.temp.auction_timer_reset = __self.temp.raffle_timer_reset;
- } else {
- __self.temp.auction_timer = __self.coin_response_timer;
- __self.temp.auction_timer_reset = __self.coin_response_reset;
- }
- __self.coin_response_timer = 3000;
- __self.coin_response_reset = true;
+ // default request timer
+ if (__self.temp.raffle_timer && __self.temp.raffle_timer_reset) {
+ __self.temp.auction_timer = __self.temp.raffle_timer;
+ __self.temp.auction_timer_reset = __self.temp.raffle_timer_reset;
+ } else {
+ __self.temp.auction_timer = __self.coin_response_timer;
+ __self.temp.auction_timer_reset = __self.coin_response_reset;
+ }
+ __self.coin_response_timer = 3000;
+ __self.coin_response_reset = true;
- // clear previous bids
- __self.auction_bids = [];
- __self.auction_previous_bid = {};
+ // clear previous bids
+ __self.auction_bids = [];
+ __self.auction_previous_bid = {};
- // auction open response
- __self.irc.emit('message', {message:__self.pre_text + 'Auction opened, accepting bids'})
+ // auction open response
+ __self.irc.emit('message', {message:__self.pre_text + 'Auction opened, accepting bids'})
+ } else {
+ // auction is already open response
+ __self.irc.emit('message', {message:__self.pre_text + 'Auction already in progress'});
+ }
} else {
- // auction is already open response
- __self.irc.emit('message', {message:__self.pre_text + 'Auction already in progress'});
+ // raffle currently running
+ __self.irc.emit('message', {message:__self.pre_text + 'You must close the raffle before you can open an auction'});
}
} else {
- // raffle currently running
- __self.irc.emit('message', {message:__self.pre_text + 'You must close the raffle before you can open an auction'});
+ // gambling currently running
+ __self.irc.emit('message', {message:__self.pre_text + 'Betting must be closed before you can open an auction'});
}
- } else {
- // gambling currently running
- __self.irc.emit('message', {message:__self.pre_text + 'Betting must be closed before you can open an auction'});
}
break;
case false:
@@ -1229,54 +1282,56 @@ Currency.prototype.raffle = function (status) {
switch (status) {
case true:
- if (!__self.bets_status) {
- if (!__self.auction_status) {
- if (!__self.raffle_status) {
- // open up a raffle
- __self.raffle_status = true;
+ if (!__self.votes_status) {
+ if (!__self.bets_status) {
+ if (!__self.auction_status) {
+ if (!__self.raffle_status) {
+ // open up a raffle
+ __self.raffle_status = true;
- // request toggle
- if (__self.temp.auction_toggle) {
- __self.temp.raffle_toggle = __self.temp.auction_toggle;
- } else {
- __self.temp.raffle_toggle = __self.coin_toggle;
- }
- __self.coin_toggle = false;
+ // request toggle
+ if (__self.temp.auction_toggle) {
+ __self.temp.raffle_toggle = __self.temp.auction_toggle;
+ } else {
+ __self.temp.raffle_toggle = __self.coin_toggle;
+ }
+ __self.coin_toggle = false;
- // default request timer
- if (__self.temp.auction_timer && __self.temp.auction_timer_reset) {
- __self.temp.raffle_timer = __self.temp.auction_timer;
- __self.temp.raffle_timer_reset = __self.temp.auction_timer_reset;
- } else {
- __self.temp.raffle_timer = __self.coin_response_timer;
- __self.temp.raffle_timer_reset = __self.coin_response_reset;
- }
- __self.coin_response_timer = 3000;
- __self.coin_response_reset = true;
+ // default request timer
+ if (__self.temp.auction_timer && __self.temp.auction_timer_reset) {
+ __self.temp.raffle_timer = __self.temp.auction_timer;
+ __self.temp.raffle_timer_reset = __self.temp.auction_timer_reset;
+ } else {
+ __self.temp.raffle_timer = __self.coin_response_timer;
+ __self.temp.raffle_timer_reset = __self.coin_response_reset;
+ }
+ __self.coin_response_timer = 3000;
+ __self.coin_response_reset = true;
- // save previous raffle settings in case
- // a new one is opened on accident
- __self.raffle_restore_ticket_requests = __self.raffle_ticket_requests;
- __self.raffle_restore_tickets = __self.raffle_tickets;
+ // save previous raffle settings in case
+ // a new one is opened on accident
+ __self.raffle_restore_ticket_requests = __self.raffle_ticket_requests;
+ __self.raffle_restore_tickets = __self.raffle_tickets;
- // clear previous tickets
- __self.raffle_ticket_requests = [];
- __self.raffle_tickets = [];
+ // clear previous tickets
+ __self.raffle_ticket_requests = [];
+ __self.raffle_tickets = [];
- // raffle open response
- __self.irc.emit('message',{message:__self.pre_text + 'Raffle opened'});
- __self.irc.emit('message',{message:'+ Tickets cost ' + __self.raffle_ticket_cost + ' ' + __self.config.currency.toLowerCase() + ' / Maximum of ' + __self.raffle_max_tickets + ' tickets per viewer'});
+ // raffle open response
+ __self.irc.emit('message',{message:__self.pre_text + 'Raffle opened'});
+ __self.irc.emit('message',{message:'+ Tickets cost ' + __self.raffle_ticket_cost + ' ' + __self.config.currency.toLowerCase() + ' / Maximum of ' + __self.raffle_max_tickets + ' tickets per viewer'});
+ } else {
+ // raffle in progress response
+ __self.irc.emit('message',{message:__self.pre_text + 'Raffle already in progress'});
+ }
} else {
- // raffle in progress response
- __self.irc.emit('message',{message:__self.pre_text + 'Raffle already in progress'});
+ // auction in progress
+ __self.irc.emit('message', {message:__self.pre_text + 'You must close the auction before you can open an a raffle'});
}
} else {
- // auction in progress
- __self.irc.emit('message', {message:__self.pre_text + 'You must close the auction before you can open an a raffle'});
+ // gambling currently running
+ __self.irc.emit('message', {message:__self.pre_text + 'Betting must be closed before you can open a raffle'});
}
- } else {
- // gambling currently running
- __self.irc.emit('message', {message:__self.pre_text + 'Betting must be closed before you can open a raffle'});
}
break;
case false:
@@ -1497,6 +1552,274 @@ Currency.prototype.next_raffle_winner = function () {
}
};
+/*
+ * VOTING SYSTEM
+ * ------------
+ */
+Currency.prototype.votes = function(status, data) {
+ var __self = this;
+
+ switch(status){
+ case true:
+ if (!__self.bets_status) {
+ if (!__self.auction_status) {
+ if (!__self.raffle_status) {
+ if (!__self.votes_status && !__self.votes_payout) {
+ var wager_msg = '';
+
+ __self.votes_status = true;
+ __self.votes_payout = true;
+
+ __self.votes_board = [];
+ __self.votes_viewers = [];
+ __self.votes_total = 0;
+
+ __self.votes_board = data.join().split(',').filter(function(n){return n}).slice(6).map(function(n){return {name: n, num: 0, total: 0};});
+ for (var i = 0; i < __self.votes_board.length; i++) {
+ __self.votes_board[i].idx = i;
+ }
+
+ for (var i = 0; i < __self.votes_board.length; i++) {
+ if (i !== __self.votes_board.length - 1) {
+ wager_msg += '"!' + __self.votes_board[i].name + '" / ';
+ } else {
+ wager_msg += '"!' + __self.votes_board[i].name + '"';
+ }
+ }
+
+ // output to chat
+ __self.irc.emit('message', {message:__self.pre_text + 'Voting is now open'});
+ __self.irc.emit('message', {message:'+ Type ' + wager_msg + ' and the vote amount to enter'});
+ } else {
+ if (__self.votes_payout) {
+ // payout pending message
+ __self.irc.emit('message', {message:__self.pre_text + 'Unable to take new votes until the last has been decided'});
+ } else {
+ __self.irc.emit('message', {message:__self.pre_text + 'Voting already in progress'});
+ }
+ }
+ // FIXME: messages below should be "cant open a vote until X is over/closed" instead? test it
+ } else {
+ // raffle in progress
+ __self.irc.emit('message', {message:__self.pre_text + 'Voting must be closed before you can open a raffle'});
+ }
+ } else {
+ // auction currently running
+ __self.irc.emit('message', {message:__self.pre_text + 'Voting must be closed before you can open an auction'});
+ }
+ }
+ break;
+ case false:
+ if (__self.votes_status && __self.votes_payout) {
+ __self.votes_status = false;
+
+ __self.votes_deduct_votes();
+
+ // output to chat
+ if (__self.votes_viewers.length > 0) {
+ __self.irc.emit('message', {message:__self.pre_text + 'Voting is now closed'});
+ for (var i = 0; i < __self.votes_board.length; i++) {
+ __self.irc.emit('message', {message:'+ ' + __self.votes_board[i].name + ' with ' + __self.votes_board[i].num + ' supporters totaling ' + __self.votes_board[i].total + ' votes'});
+ }
+
+ //
+ } else {
+ __self.irc.emit('message', {message:__self.pre_text + 'Voting closed, no votes were cast.'});
+ }
+ }
+ break;
+ case 'pool':
+ function do_work() {
+ if (__self.votes_board.length > 0) {
+ __self.irc.emit('message', {message:__self.pre_text + 'Current voting pool is:'});
+ for (var i = 0; i < __self.votes_board.length; i++) {
+ __self.irc.emit('message', {message:'+ ' + __self.votes_board[i].name + ' with ' + __self.votes_board[i].num + ' supporters totaling ' + __self.votes_board[i].total + ' votes'});
+ }
+ } else {
+ __self.irc.emit('message', {message:__self.pre_text + 'No current vote.'});
+ }
+ }
+ if (__self.votes_response_reset) {
+ __self.votes_response = setTimeout(function () {do_work();}, __self.votes_response_timer);
+ } else {
+ setTimeout(function () {do_work();}, __self.votes_response_timer);
+ }
+ break;
+ case 'winner':
+ if (!__self.votes_status) {
+ if (__self.votes_payout) {
+ for (var i = 0; i < __self.votes_board.length; i++) {
+ if (data == __self.votes_board[i].name) {
+ __self.votes_award_winner(__self.votes_board[i]);
+ __self.irc.emit('message', {message:__self.pre_text + 'Winner:' + data + 'had the most votes!'});
+ }
+ }
+ } else {
+ __self.irc.emit('message', {message:__self.pre_text + 'A winner has already been decided.'});
+ }
+ } else {
+ __self.irc.emit('message', {message:__self.pre_text + 'Voting must be closed before you can have a winner'});
+ }
+ break;
+ case 'cancel':
+ if (!__self.votes_status) {
+ // Return all the currency back to original owners
+ if (__self.votes_payout) {
+ sql = '';
+ for (var i = 0; i < __self.votes_viewers.length; i++) {
+ if (__self.votes_viewers[i].amount > 0) {
+ if (sql.length > 0) {
+ sql += '; ';
+ }
+ sql += 'UPDATE viewers ';
+ sql += 'SET points = points + ' + __self.votes_viewers[i].amount + ' ';
+ sql += 'WHERE user = \'' + __self.votes_viewers[i].viewer + '\'';
+ }
+ }
+ __self.db.execute(sql, function() {
+ __self.irc.emit('message', {message:__self.pre_text + 'Vote was canceled, all ' + __self.config.currency.toLowerCase() + ' returned.'});
+ });
+ __self.votes_payout = false;
+ } else {
+ __self.irc.emit('message', {message:__self.pre_text + 'No vote to cancel.'});
+ }
+ } else {
+ __self.votes_status = false;
+ __self.votes_payout = false;
+ __self.irc.emit('message', {message:__self.pre_text + 'Current vote was canceled.'});
+ }
+ break;
+ }
+};
+
+Currency.prototype.collect_votes = function (caller, vote, amount) {
+ var __self = this, has_vote = false;
+
+ function do_work() {
+ var multi_response = [];
+ for (var i = 0; i < __self.votes_board.length; i++) {
+ multi_response.push([]);
+ }
+
+ if (__self.votes_flood.length > 0) {// send flood requests
+ var vote;
+ // setup vote response
+ for (var i = 0; i < __self.votes_flood.length; i++) {
+ vote = __self.votes_viewers[__self.votes_flood[i]];
+ multi_response[vote.vote].push(vote.viewer + ' (' + vote.amount + ')');
+
+ }
+ for (var i = 0; i < __self.votes_board.length; i++) {
+ if (multi_response[i].length > 0) {
+ __self.irc.emit('message', {message:'New votes for ' + __self.votes_board[i].name + ': ' + multi_response[i].join(', '), timer: 1});
+ }
+ }
+
+ }
+
+ // clear flood requests
+ __self.votes_flood = [];
+ }
+
+ // Bound amount by positive currency
+ __self.query_coins(caller, function (rows) {
+ for (var i = 0; i < rows.length; i++) {
+ amount = Math.min(amount, rows[i].points);
+ }
+
+ if (__self.votes_viewers.length > 0) {
+ for (var i = 0; i < __self.votes_viewers.length; i++) {
+ if (__self.votes_viewers[i].viewer === caller) {
+ has_vote = true;
+ if (amount > __self.votes_viewers[i].amount) {
+ __self.votes_board[__self.votes_viewers[i].vote].num -= 1;
+ __self.votes_board[__self.votes_viewers[i].vote].total -= __self.votes_viewers[i].amount;
+ __self.votes_viewers[i].vote = vote.idx;
+ __self.votes_viewers[i].amount = amount;
+ __self.votes_board[vote.idx].num += 1;
+ __self.votes_board[vote.idx].total += amount;
+ // add flood users to array
+ if (__self.votes_flood.indexOf(i) < 0) {
+ __self.votes_flood.push(i);
+ }
+ }
+ break;
+ }
+ }
+ if (!has_vote && amount >= 1 && amount !== 0) {
+ __self.votes_viewers.push({viewer: caller, vote: vote.idx, amount: amount});
+ __self.votes_board[vote.idx].num += 1;
+ __self.votes_board[vote.idx].total += amount;
+ __self.votes_flood.push(__self.votes_viewers.length - 1);
+ }
+ } else {
+ if (amount >= 1 && amount !== 0) {
+ __self.votes_viewers.push({viewer: caller, vote: vote.idx, amount: amount});
+ __self.votes_board[vote.idx].num += 1;
+ __self.votes_board[vote.idx].total += amount;
+ __self.votes_flood.push(__self.votes_viewers.length - 1);
+ }
+ }
+ console.log(__self.votes_viewers);
+
+ // check if flood has a set amount of requests and output
+ // if not, set the output timer
+ if (__self.votes_flood.length === __self.max_requests) {
+ do_work();
+ } else {
+ if (__self.votes_response_reset) {
+ __self.votes_response = setTimeout(function () {do_work();}, __self.votes_response_timer);
+ } else {
+ setTimeout(function () {do_work();}, __self.votes_response_timer);
+ }
+ }
+ });
+};
+
+Currency.prototype.votes_deduct_votes = function () {
+ var __self = this;
+
+ if (__self.votes_viewers.length > 0) {
+ // Don't trust the on-the-fly numbers
+ for (var i = 0; i < __self.votes_board.length; i++) {
+ __self.votes_board[i].num = 0;
+ __self.votes_board[i].total = 0;
+ }
+ __self.votes_total = 0;
+ // Remove the points and add them to an escrow
+ sql = '';
+ for (var i = 0; i < __self.votes_viewers.length; i++) {
+ if (__self.votes_viewers[i].amount > 0) {
+ if (sql.length > 0) {
+ sql += '; ';
+ }
+ sql += 'UPDATE viewers ';
+ sql += 'SET points = points - ' + __self.votes_viewers[i].amount + ' ';
+ sql += 'WHERE user = \'' + __self.votes_viewers[i].viewer + '\'';
+ __self.votes_board[__self.votes_viewers[i].vote].num += 1;
+ __self.votes_board[__self.votes_viewers[i].vote].total += __self.votes_viewers[i].amount;
+ __self.votes_total += __self.votes_viewers[i].amount;
+ }
+ }
+ __self.db.execute(sql, function() {});
+ }
+};
+
+Currency.prototype.votes_award_winner = function (winner) {
+ var __self = this;
+
+ if (__self.votes_payout) {
+ // set payout to complete
+ __self.votes_payout = false;
+ }
+
+ // Clear the board
+ __self.votes_board = [];
+ __self.votes_viewers = [];
+ __self.votes_total = 0;
+};
+
+
/**
* ============================================
* BETTING SYSTEM
diff --git a/lib/initialize.js b/lib/initialize.js
index 970c635..2f92ae7 100644
--- a/lib/initialize.js
+++ b/lib/initialize.js
@@ -39,7 +39,7 @@ exports.initialize = function(options) {
modpowers : config.currency.modpowers,
ignorelist : config.ignorelist
});
- web = require('./web.js')(db, {
+ web = require('./web.js')(db, currency, {
port : config.web.port,
title : config.twitch.channel,
slogan : config.web.slogan,
diff --git a/lib/web.js b/lib/web.js
index bf93716..68c1985 100644
--- a/lib/web.js
+++ b/lib/web.js
@@ -2,10 +2,11 @@ var express = require('express'),
https = require('https');
//---- Construct ----
-function WEB(db, options) {
+function WEB(db, currency, options) {
var __self = this;
__self.db = db;
+ __self.currency = currency;
__self.port = options.port || 9000;
__self.title = options.title;
@@ -38,6 +39,10 @@ WEB.prototype.start = function () {
__self.db.execute(sql, function(rows) {
var opts = __self.render_opts;
opts.rows = rows;
+ opts.bet_status = __self.currency.bets_status;
+ opts.bet_board = __self.currency.bets_board;
+ opts.bet_viewers = __self.currency.bets_viewers;
+
res.render('index', opts);
});
});
@@ -79,6 +84,6 @@ WEB.prototype.start = function () {
};
-module.exports = function (db, options) {
- return new WEB(db, options);
+module.exports = function (db, currency, options) {
+ return new WEB(db, currency, options);
};
diff --git a/web/templates/index.jade b/web/templates/index.jade
index 8528665..c63eb6f 100755
--- a/web/templates/index.jade
+++ b/web/templates/index.jade
@@ -8,6 +8,27 @@ block content
h2 #{title} is
span#status offline.
div#streambox
+ br
+ div#betstats
+ span.uk-text-bold Betting is currently:
+ #{bet_status}
+ if bet_status === true
+ span.uk-text-bold.uk-text-success Active
+ else
+ span.uk-text-bold.uk-text-danger Inactive
+ if bet_board
+ table.uk-table
+ caption Current Betting Pool
+ thead
+ tr
+ th Option
+ th Total
+ tbody
+ each option in bet_board
+ tr
+ td !#{option.name}
+ td #{option.total}
+ br
div.uk-width-1-2
div.uk-panel.uk-panel-box
table.uk-table.uk-table-hover.uk-table-striped
@@ -33,6 +54,7 @@ block postscript
$("#streambox").append("
");;
} else {
$("#streambox").append("