Apps Home
|
Create an App
VotingTest
Author:
bellows3
Description
Source Code
Launch App
Current Users
Created by:
Bellows3
// https://github.com/uxitten/polyfill/blob/master/string.polyfill.js // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/padStart if (!String.prototype.padStart) { String.prototype.padStart = function padStart(targetLength, padString) { targetLength = targetLength >> 0; //truncate if number, or convert non-number to 0; padString = String(typeof padString !== 'undefined' ? padString : ' '); if (this.length >= targetLength) { return String(this); } else { targetLength = targetLength - this.length; if (targetLength > padString.length) { padString += padString.repeat(targetLength / padString.length); //append to original to ensure we are longer than needed } return padString.slice(0, targetLength) + String(this); } }; } // App Code! cb.settings_choices = [ { name: "initialAVal", type: 'str', defaultValue: "OptionA", label: "Starting Value for Option A" }, { name: "initialBVal", type: 'str', defaultValue: "OptionB", label: "Starting Value for Option B" }, { name: "initialTimer", type: 'str', defaultValue: "5m 30s", label: "Initial Timer Value.\nUse the format '1h 2m 25s' which would be 1 hour 2 minutes and 25 seconds" } ] cb.log(cb.settings) var optionA = new Set([]); var optionB = new Set([]); var openVoting = false var tipped = 0 var active = true var timeout var prevTime var tieWinner // Set by Settings var optionAVal = cb.settings.initialAVal var optionBVal = cb.settings.initialBVal var timer = parseTimer(cb.settings.initialTimer) // Debug var dumpState = () => { var state = { optionA: optionA, optionB: optionB, optionAVal: optionAVal, optionBVal: optionBVal, openVoting: openVoting, timer: timer, tipped: tipped, active: active, timeout: timeout, prevTime: prevTime } cb.sendNotice(state, cb.room_slug) } // Time Format Functions function parseTimer(string) { _timer = 0 hours = /(\d+)h/.exec(string) minutes = /(\d+)m/.exec(string) seconds = /(\d+)s/.exec(string) if(hours) { _timer += parseInt(hours[1]) * 60 * 60 } if(minutes) { _timer += parseInt(minutes[1]) * 60 } if(seconds) { _timer += parseInt(seconds[1]) } return _timer } function calcSeconds(remainingTime) { return `${remainingTime % 60}` } function calcMinutes(remainingTime) { return `${Math.floor(remainingTime/60) % 60}` } function calcHours(remainingTime) { return `${Math.floor(remainingTime / (60 * 60))}` } function timeDenomination(amount) { if(amount < 60) { return amount == 1 ? "second" : "seconds" } else if(amount < 60 * 60) { return amount / 60 === 1.0 ? "minute" : "minutes" } else { return amount / (60 * 60) === 1.0 ? "hour" : "hours" } } function timeString(remainingTime) { var timeArray if(remainingTime < 60) { timeArray = [calcSeconds(remainingTime)] } else if(remainingTime < 60 * 60) { timeArray = [ calcMinutes(remainingTime), calcSeconds(remainingTime).padStart(2, '0') ] } else { timeArray = [ calcHours(remainingTime), calcMinutes(remainingTime).padStart(2, '0'), calcSeconds(remainingTime).padStart(2, '0') ] } return `${timeArray.join(':')}` } // Scoped Helper Functions var determineWinner = () => { if(optionA.size === optionB.size) { return tieBreaker() } return optionA.size > optionB.size ? 'A' : 'B' } var tieBreaker = () => { if(tieWinner) { return tieWinner } tieWinner = Math.round(Math.random()) === 1 ? 'A' : 'B' return tieWinner } var removeUser = (user) => { if(optionA.has(user)) { optionA.delete(user) } if(optionB.has(user)) { optionB.delete(user) } } // Message Functions var voteMessage = (user, option) => { cb.sendNotice(`Thanks for voting ${user}! Your vote has been anonymously tallied for ${option}.`, user, '', '#6f0000') } var timerDoneMessage = () => { cb.sendNotice("The Timer Has Reached 0!", '', 'yellow', 'blue') winnerMessage() } var winnerMessage = () => { winner = determineWinner() === 'A' ? optionAVal : optionBVal cb.sendNotice(`The winner is: ${winner}`) } var sendVoterWelcome = (user) => { message = `Hi! The broadcaster has enabled the Voter Countdown (Better Name Pending) App on this broadcast! The goal of this App is to have you the viewer engage with your performer and your fellow viewers. Every "Goal" is set by the broadcaster after another is reached. So don't be afraid to engage with them to get the goal you want as an option. But you're also playing with and against your fellow viewers and every tip decreases the time. Don't squander an advantage if you have it. Finally, always play nice and be respectful. Be sure to tip your performers as well, they work hard.` cb.sendNotice(message, user, '', 'green', 'bold') voteHelpMessage(user) tipHelpMessage(user) } var voteHelpMessage = (user) => { message = `Voting Help --- /vote A - Vote for option A /vote B - Vote for option B --- Your vote will only count once, however you may change your vote at any time. Leaving the channel will cancel your vote. If you rejoin you will need to revote. --- The Current Options are: A: ${optionAVal} B: ${optionBVal}` cb.sendNotice(message, user) } var tipHelpMessage = (user) => { message = `Timer Help --- Every tipped token will decrease the time by one second. So a 60 token tip will decrease the time by a minute.` cb.sendNotice(message, user) } var svoHelpMessage = (user) => { message = `Set Voting Option (svo) Command Help --- /svoA - Set Voting Option A /svoB - Set Voting Option B /svoTimer - Sets the timer. /\d(h|m|s)+ / format. 1 hour 32 minute 14 seconds would be: "/svoTimer 1h 32m 14s" /svoTipped - Set tipped amount (No External Function Currently) /svoResetVote - Resets the vote counts to 0 /svoOpen - Opens the voting up if currently Closed /svoClose - Closes the voting if currently Open /svoStart - Starts the timer /svoStop - Stops the timer /svoDump - (Advanced) Debugging Tool to see the state inside of the App /svoHelp - Displays this message` cb.sendNotice(message, user) } // Timer Functions var decreaseTimer = () => { if(timer > 0) { if(tieWinner) { tieWinner = null } timer -= 1 } else if(timer < 0) { timer = 0 } } var appRefresh = () => { timeout = null if(active) { decreaseTimer() if(prevTime !== 0 && timer === 0) { timerDoneMessage() } prevTime = timer } cb.drawPanel() startTimeout() } var startTimeout = () => { if(timeout) { db.cancelTimeout(timeout) } timeout = cb.setTimeout(appRefresh, 1000) } var timerReached = () => timer <= 0 // Event Callbacks cb.onMessage((msg) => { if(msg['user'] == cb.room_slug && msg['m'].startsWith("/svo")) { msg['X-Spam'] = true if(msg['m'].startsWith("/svoA ")) { optionAVal = msg['m'].substring(5).trim() } else if(msg['m'].startsWith("/svoB ")) { optionBVal = msg['m'].substring(5).trim() } else if(msg['m'].startsWith("/svoTimer ")) { timer = parseTimer(msg['m'].substring(10)) } else if(msg['m'].startsWith("/svoTipped ")) { tipped = parseInt(msg['m'].substring(11).trim()) } else if(msg['m'].startsWith("/svoResetVote")) { optionA.clear() optionB.clear() } else if(msg['m'].startsWith("/svoOpen")) { openVoting = true cb.sendNotice(`${msg['user']} has opened up Voting!`) } else if(msg['m'].startsWith("/svoClose")) { openVoting = false cb.sendNotice(`${msg['user']} has closed Voting!`) } else if(msg['m'].startsWith("/svoDump")) { dumpState() } else if(msg['m'].startsWith("/svoStart")) { active = true cb.sendNotice(`${msg['user']} has started the timer!`) } else if(msg['m'].startsWith("/svoStop")) { active = false cb.sendNotice(`${msg['user']} has stopped the timer!`) } else { svoHelpMessage(msg['user']) } } if(msg['m'].startsWith("/vote")) { msg['X-Spam'] = true if(timerReached() && !openVoting) { var message = `Sorry, Voting has closed for this round. Wait untl next round or for voting to be reopened` cb.sendNotice(message, msg['user'], '', '#FF0000') } else { removeUser(msg['user']) if(msg['m'] === "/vote A") { optionA.add(msg['user']) voteMessage(msg['user'], optionAVal) } else if(msg['m'] === "/vote B") { optionB.add(msg['user']) voteMessage(msg['user'], optionBVal) } else { voteHelpMessage(msg['user']) } } } if(msg['m'].startsWith('/help')) { msg['X-Spam'] = true if(msg['user'] === cb.room_slug) { svoHelpMessage(msg['user']) } voteHelpMessage(msg['user']) tipHelpMessage(msg['user']) } cb.drawPanel() return msg }) cb.onLeave((user) => { removeUser(user['user']) if(user['user'] === cb.room_slug) { active = false sencNotice(`The timer has stopped because the broadcaster has left the room.\nIt will restart when they rejoin.`) } }) cb.onEnter((user) => { if(user['user'] === cb.room_slug) { active = true cb.sendNotice(`The broadcaster has rejoined and the time has started counting down again.`) } else { sendVoterWelcome(user['user']) } }) cb.onTip((tip) => { if(timerReached()) { return tip } tipAmount = parseInt(tip['amount']) timeOff = tipAmount tipped += tipAmount if(timer < tipAmount) { timeOff = timer } cb.sendNotice(`${tip['from_user']} took ${timeString(timeOff)} ${timeDenomination(timeOff)} off the clock!`) timer -= tipAmount }) cb.onDrawPanel(function(user) { if(timer <= 0 && !openVoting) { winner = determineWinner() return { 'template': '3_rows_12_22_31', 'row1_label': `A: ${optionAVal}`, 'row1_value': `${winner === 'A' ? "Winner!" : "Loser"}`, 'row2_label': `B: ${optionBVal}`, 'row2_value': `${winner === 'B' ? "Winner!" : "Loser"}`, 'row3_value': "ROUNT OVER!" } } else { return { 'template': '3_rows_12_22_31', 'row1_label': `A: ${optionAVal}`, 'row1_value': optionA.size, 'row2_label': `B: ${optionBVal}`, 'row2_value': optionB.size, 'row3_value': timeString(timer) } } }) cb.setTimeout(appRefresh, 1000)
© Copyright Chaturbate 2011- 2025. All Rights Reserved.