Bots Home
|
Create an App
Auction King Test
Author:
greenandsexy
Description
Source Code
Launch Bot
Current Users
Created by:
Greenandsexy
// Simple auction application // // Author: mark54321 // Version: 1.0 // // This app keeps track of the total amount each user has tipped // during the auction of some good or service. // Broadcasters may set: // * The minimum total amount required in order to win the auction // * An optional minimum tip value to be included in the auction total for any user // * An optional time limit for the auction // * An optional extended time limit in case of a tie // * The broadcaster may also set the auction time remaining at any time var AuctionApp = function () { var self, tipTotals = [], startTime = -1, auctionComplete = false, auctionTimeRemaining = -1, timerSet = false; // Fore- and background colors for the chat messages of auction participants var msgColors = [ {background: "rgba(255,0,0,0.4)", color: "#c00"}, // Top bidder {background: "rgba(0,0,255,0.4)", color: "#007"}, // Second highest {background: "rgba(0,255,0,0.4)", color: "#070"} // All other participants ]; return { // Initializes the app // This should be called after the broadcaster settting have been made init: function () { if (cb.settings.maxTime > 0) { self.initTimer(); } // Update the room subject self.updateSubject(); // Show the auction rules self.showRules(); }, // Helper function to initialize the timer and auction time keeping initTimer: function (interval) { // Set the start time to "now" startTime = new Date().getTime(); // Set up the timer if (typeof interval === 'undefined') { interval = 60000; } if (!timerSet) { cb.setTimeout(self.onTimer, interval); timerSet = true; } }, // Sets up and returns the broadcaster app settings template getSettingChoices: function () { self = this; return [ { name: "description", label: "Describe the goods or services being auctioned (max 255 characters).", type: "str", minLength: 1, maxLength: 255 }, { name: "minTotal", label: "Minimum bid (a given user's total auction tips) to win.", type: "int", minValue: 1, defaultValue: 200 }, { name: "minTip", label: "Minimum tip to be included in the auction totals for a user.", type: "int", minValue: 1, defaultValue: 10 }, { name: "maxTime", label: "The time, in minutes, for the auction to last. Set to 0 for no time limit.", type: "int", minValue: 0, defaultValue: 0 }, { name: "additionalTime", label: "In a timed auction, in case of a tie, the additional time, in minutes, for the auction to last. Set to 0 for no time limit.", type: "int", minValue: 0, defaultValue: 0 } ]; }, // Updates the app GUI onUpdatePanel: function (user, timeRemaining) { var panel = { template: "3_rows_of_labels", row1_label: "", row1_value: "", row2_label: "Highest Bid:", row2_value: (tipTotals.length ? tipTotals[0].name + " (" + tipTotals[0].total + ")" : "None"), row3_label: "", row3_value: "" }; if (auctionComplete) { // If the auction is finsihed announce it var result = self.getAuctionResult(); if (result === 1) { panel.row1_label = "Auction Winner"; panel.row1_value = tipTotals[0].name; } else if (result === -1) { panel.row1_label = "Auction Winner"; panel.row1_value = "It's a tie"; } else { panel.row1_label = "Auction Winner"; panel.row1_value = "No winner"; } } else { // If it is a timed auction, the first row is of the format // auction min bid / user min tip / time remaining // otherwise the first row format is // auction min bid / user min tip if (cb.settings.maxTime > 0) { var remaining = auctionTimeRemaining >= 0 ? auctionTimeRemaining : self.getTimeRemaining(); var units = ""; if (remaining <= 60) { units = "sec"; } else { units = "min"; remaining = Math.round(remaining / 60); } panel.row1_label = "Min. Bid/Min. Tip/Time (" + units + ")"; panel.row1_value = cb.settings.minTotal + "/" + cb.settings.minTip + "/" + remaining + " " + units; } else { panel.row1_label = "Min. Bid/Min. Tip"; panel.row1_value = cb.settings.minTotal + "/" + cb.settings.minTip; } if (tipTotals.length > 1) { panel.row3_label = "Next Highest"; panel.row3_value = tipTotals[1].name + " (" + tipTotals[1].total + ")"; } } return panel; }, // Called when a tip has been sent onTip: function (tip) { // Update the user's total self.updateTotals(tip); // Update the room subject self.updateSubject(); // Update the panel cb.drawPanel(); }, // Called when a message has been sent onMessage: function (msg) { // Is this a command? //var parts = msg["m"].split(" "); var parts = msg.m.split(" "); if (parts[0] == "/rules") { // Output the rules self.showRules(); // Prevent the command from being output to chat msg['X-Spam'] = true; } else if (parts[0] == "/stats") { // Output the current bidding status self.showStats(); // Prevent the command from being output to chat msg['X-Spam'] = true; } else if (parts[0] == "/help") { // Output the help self.showHelp((msg.user == cb.room_slug)); // Prevent the command from being output to chat msg['X-Spam'] = true; } else if (parts[0] == "/time") { // Handle the command self.handleTimeCmd(msg); // Prevent the command from being output to chat msg['X-Spam'] = true; } else { // Get the back- and foreground message colors for this user var colors = self.getMsgColors(msg); if (colors) { msg.background = colors.background; msg.c = colors.color; } } return msg; }, // Updates the room subject updateSubject: function () { var subject = cb.room_slug + " is holding an auction:\n\n"; subject += cb.settings.description; cb.changeRoomSubject(subject); }, // Helper function to update the tip totals updateTotals: function (tip) { // the tip must be greater than the settings.minTip value to be included in the user's total if (tip.amount >= cb.settings.minTip) { var found = false; for (var i = 0; i < tipTotals.length; i++) { if (tipTotals[i].name == tip.from_user) { tipTotals[i].total += parseInt(tip.amount, 10); found = true; break; } } // If not updated above if (!found) { // Add the user tipTotals.push( {name: tip.from_user, total: parseInt(tip.amount, 10)} ); } // Sort the list tipTotals.sort(function (a, b) { // We want to sort decending, i.e. highest value first var totalA = (a !== "undefined") ? a.total : 0; var totalB = (b !== "undefined") ? b.total : 0; return totalB - totalA; }); } else { // Output why it wasn't included in the user's total var msg = "The minimum tip to be included in your auction total is " + cb.settings.minTip + " tokens."; cb.chatNotice(msg); } }, // Helper function to handle the /time command handleTimeCmd: function (msg) { var parts = msg.m.split(" "); // Only the broadcaster can set the time remaining if (msg.user == cb.room_slug) { // Set the remaining time var remaining = parts.length == 2 ? parseInt(parts[1], 10) : -1; if (remaining !== -1) { // Set the time remaining setting (it's in minutes) cb.settings.maxTime = remaining; // Reset the timer self.initTimer(self.getTimerInterval()); // Turn off the flag so the broadcaster can add more time if needed auctionComplete = false; // Update the panel cb.drawPanel(); } else { var output = "Invalid time command format: /time <minutes>.\n"; output += "For example \"/time 5\" (without the quotes) to set 5 minutes remaining."; cb.chatNotice(output); } } else { cb.chatNotice("Only the broadcaster can set the remaining auction time."); } }, // Helper function to output the auction rules showRules: function () { var msg = cb.room_slug + " is holding an auction:\n\n"; msg += cb.settings.description + "\n\n"; msg += "Each user's total tips during the auction represent their auction bid.\n"; msg += "The user with the highest bid wins the auction.\n"; // Is there a minimum to be included in the user's total? if (cb.settings.minTip > 1) { msg += "You must tip at least " + cb.settings.minTip + " tokens for the tip to be included in your auction total.\n"; } msg += "As with all auctions, there is a minimum highest bid in order for somebody to win.\n"; msg += "The minumum bid (total tips by a user during the auction) is " + cb.settings.minTotal + " tokens.\n"; // Do we have a highest bid yet? if (tipTotals.length) { msg += "Highest Bid so far: " + tipTotals[0].name + " (" + tipTotals[0].total + ")\n"; } // Is this a timed auction? if (cb.settings.maxTime > 0) { msg += "Auction Time Remaining: " + Math.round(self.getTimeRemaining() / 60) + " minutes."; } // Output the rules cb.chatNotice(msg); }, // Helper function to output the auction current standings showStats: function () { var msg = "Current Auction Standing:\n"; if (tipTotals.length) { // Show user bids for (var i = 0; i < tipTotals.length; i++) { msg += tipTotals[i].name + ": " + tipTotals[i].total + " tokens\n"; } } else { msg += "No bids yet\n"; } // Minimum Bid msg += "The minumum bid (total tips by a user during the auction) is " + cb.settings.minTotal + " tokens.\n"; // Is this a timed auction? if (cb.settings.maxTime > 0) { var remaining = self.getTimeRemaining(); if (remaining > 0) { var units = ""; if (remaining <= 60) { units = "sec"; } else { units = "min"; remaining = Math.round(remaining / 60); } msg += "Auction Time Remaining: " + remaining + " " + units + "\n"; } else { // Time has run out. See if we have a winner var result = self.getAuctionResult(); if (result == 1) { msg += "The winner is " + tipTotals[0].name + "\n"; } else if (result == 0) { // No winner msg += "Nobody bid above the minimum\n"; } else { // A tie msg += "We have a tie at " + tipTotals[0].total + " tokens\n"; } } } // Output the stats cb.chatNotice(msg); }, // Helper function to output the help message showHelp: function (isBroadcaster) { var msg = "Auction Help:\n"; msg += "Each user's \"bid\" is the sum of all their tips during the auction\n"; msg += "An auction can have a minimum bid in order for a user to win.\n"; msg += "It may also have a minimum tip for the tip to be counted as part of a user's bid.\n"; msg += "Finally, an auction can have a time limit.\n"; msg += "In a timed auction, the user with the highest bid and which exceeds the minimum is declared the winner.\n"; msg += "In case of a tie, additional time can be specified, or the broadcaster can decide another way to settle the auction.\n\n"; msg += "Commands:\n"; msg += "/rules Outputs the auction rules\n"; msg += "/stats Outputs the the current auction standings\n"; msg += "/help Outputs this message\n"; if (isBroadcaster) { msg += "/time <minutes> Sets the remaining time in the auction. For example \"/time 5\"\n"; msg += " sets the remaining auction time to 5 minutes.\n"; msg += " This is useful in non-timed auctions to set an end for the auction\n"; msg += " or to help settle a tie.\n"; } // Output the help cb.chatNotice(msg); }, // Helper function to output the auction result showResult: function (result) { auctionComplete = true; var msg = ""; if (result === 1) { // We have a winners msg = "And the winner is...\n"; msg += tipTotals[0].name + "\n"; msg += "Congratulations!"; } else if (result === -1) { // It's a tie var bid = tipTotals[0].total; msg = "The auction is a tie at " + bid + " tokens between\n"; for (var i = 0; i < tipTotals.length; i++) { if (tipTotals[i].total != bid) { break; } msg += tipTotals[i].name + "\n"; } } else { msg = "The auction time has expired without a winner"; } // Output the result cb.chatNotice(msg); // Update the panel cb.drawPanel(null); }, // Helper function to return the fore- abd background colors for a given user's message getMsgColors: function (msg) { // The top 2 bidders each get their own colors. Anyone else who has bid also gets highlighted. // Otherwise we return null and the standard colors are used var i =0; for (i = 0; i < tipTotals.length; i++) { if (tipTotals[i].name == msg["user"]) { // Have a participant. If not in the top 2 then get the default // participant colors if (i > 1) { return msgColors[2]; } else { // Top 2 bidders return msgColors[i]; } } } // User not found so return default return null; }, // Helper function to return the auction time remaining, in seconds, if a timed auction. Otherwise returns -1. getTimeRemaining: function () { if (startTime === -1) { return startTime; } // Get the current time var now = new Date().getTime(); // Calculate the elapsed time (in seconds) var elapsed = Math.round((now - startTime) / 1000); // Calculate the time remaining (maxTime is in minutes) var remaining = (cb.settings.maxTime * 60) - elapsed; cb.log("getTimeRemaining: elapsed=" + elapsed + " remaining=" + remaining); // Return the time remaining or 0 if time has run out return remaining >= 0 ? remaining : 0; }, // Helper function to determine the outcome of the auction. // Returns 0 if we have no winner, 1 if there is a winner, and -1 if there is a tie. // This is only used in a timed auction. getAuctionResult: function () { var res = 0; var bidCount = tipTotals.length; if (bidCount) { // Have at least 1 bid. See if it meets the minimum requirements var firstPlace = tipTotals[0].total; if (firstPlace >= cb.settings.minTotal) { // It does. Now check for a tie var secondPlace = bidCount > 1 ? tipTotals[1].total : 0; res = (secondPlace == firstPlace ? -1 : 1); } } return res; }, // Helper function to calculate the timer interval. getTimerInterval: function () { // When there is little time left we want to update more often // Default interval is 1 minute var res = 60000; var remaining = self.getTimeRemaining(); if (remaining <= 60) { // 1 minute or less left. Update every second res = 1000; } return res; }, // Our "on timer" callback onTimer: function () { // Get the time remaining var timeRemaining = self.getTimeRemaining(); if (timeRemaining == 0) { // Reset our "time set" flag timerSet = false; // Time has run out. See if we have a winner var result = self.getAuctionResult(); if (result === 1) { // We have a winner. Output and we're done self.showResult(result); cb.drawPanel(); } else if(result === -1) { // We have a tie if (cb.settings.additionalTime > 0) { // Output what's happening var msg = "The auction is a tie!\n"; msg += "Adding additional time for the tie-breaker."; cb.chatNotice(msg); // Set additional time cb.settings.maxTime = cb.settings.additionalTime; // Reset the timer self.initTimer(self.getTimerInterval()); // Update the panel and we're done cb.drawPanel(); } else { // It's a tie and no extra time configured so let // the broadcaster settle it somehow. self.showResult(result); } } else { // No winner and time expired self.showResult(result); } // Don't need to set the timer anymore return; } // When we get to the last minute we want to update more frequently. // When updating at 5 second intervals we want to update only on some multiple of 5 var updateGui = false; var msg = ""; if (timeRemaining <= 60) { // We'll update if under 10 seconds or some multiple of 5 if (timeRemaining <= 10 || (timeRemaining % 5 == 0)) { updateGui = true; // Also output to the chat window msg = timeRemaining + " seconds left in the auction!"; } } else { updateGui = true; // Output time remaining every 5 minutes, or every minute, the last 5 minutes var remaining = Math.round(timeRemaining / 60); if (remaining <= 5 || remaining % 5 == 0) { msg = remaining + " minutes left in the auction!"; } } if (updateGui) { // Output to the window if (msg.length) { cb.chatNotice(msg); } // Update the panel with the new time remaining auctionTimeRemaining = timeRemaining; cb.drawPanel(null); } // Reset the timer cb.setTimeout(self.onTimer, self.getTimerInterval()); } }; }; // Create the app var theApp = new AuctionApp(); // Setup the broadcaster settings cb.settings_choices = theApp.getSettingChoices(); // Jack into the cb API // onDrawPanel event cb.onDrawPanel(function(user) { return theApp.onUpdatePanel(user); }); // onTip event cb.onTip(function(tip) { theApp.onTip(tip); }); // onMessage event cb.onMessage(function(msg) { theApp.onMessage(msg); }); // Initialize the app theApp.init();
© Copyright Chaturbate 2011- 2024. All Rights Reserved.