var $ = jQuery; const getElement = (id) => document.getElementById(id); const ws = new WebSocket('ws://bwc.ryanpandya.com/socket'); var username = "unnamed"; var pId = 0; var cards = []; var lastCard = false; var players = []; var gameMode = "draw"; const timeFormat = 'h:mm a [PDT]'; const notification_pos = "top-right"; function range(size, startAt = 0) { return [...Array(size).keys()].map(i => i + startAt); } function heartbeat() { clearTimeout(this.pingTimeout); console.log("Ping"); this.pingTimeout = setTimeout(() => { this.terminate(); }, 30000 + 1000); } ws.onopen = (moot) => { heartbeat; var urlParams = new URLSearchParams(window.location.search); console.log('Connected to websocket.'); username = urlParams.get('username'); UIkit.notification({ message: 'Connected!', status: 'success', pos: notification_pos, timeout: 1000 }); if(username == null || username == ""){ window.location = "/"; } else{ } }; const addMessage = (e) => { var self_marker = ""; if(e.pId == pId){ self_marker = "self"; } $("ul#chatbox").append( '
  • \

    \ '+e.timestamp+'\ '+e.username+'\

    '+e.message+'

    \

    \
  • ' ); } const addUser = (newPlayer) => { var picker = ""; var existing = false; players.forEach(function(p){ // Check if we already know about this player (is this a reconnection attempt) if(p.pId == newPlayer.pId){ // Looks like it is existing = true; console.log("Hit on " + newPlayer.username); // Make note } }); if(existing){ // What to do if this is a duplicate }else{ // Otherwise notice(newPlayer.username + " has joined the game."); players.push(newPlayer); if(newPlayer.username == username){ // This user is actually us, so make the username editable picker = '
    '; u = ''; } else{ // Otherwise just display the username u = newPlayer.username; } var el = '\
  • '+picker+'
    '+u+'
  • '; $("ul.players-list").append(el); $("span#number-of-players").text(parseInt($("span#number-of-players").text())+1); // This is probably wrong and will cause duplicates } } const delUser = (username) => { } const changeMode = (data) => { $("#pick-first-turn").css({'display':'flex'}); $("#card-view").hide(); $(".active-card-controls").hide(); if(data.playerTurn.pId == pId){ notice("The game has started. Your move!"); } else{ notice("The game has started. Move: " + data.playerTurn.username); } gameMode = data.mode; changeActivePlayer(data.playerTurn, data.incompleteCard); } const decrementCardsCount = () => { var el = $("#toggle_play > .uk-badge"); var newNumber = parseInt(el.text()) - 1; console.log(newNumber); if(newNumber < 2){ el.text("last card").css({'background':'maroon',color:'white'}); } if(newNumber == 0 || newNumber == NaN){ el.text("out of cards").css({'background':'black',color:'white'}); } else{ el.html(newNumber + " cards").css({'background':'#eee',color:'#666'});; } }; const changeActivePlayer = (player, card) => { clearActiveCard(); if(player.pId == pId){ // Our turn! $(".active-card-controls").css({'display':'flex'}); if(card){ console.log("There's a card in memory already."); pullCard(card); } else{ console.log("Requesting a card from the server..."); request = { 'type': 'pullCard', 'player': player } decrementCardsCount(); ws.send(JSON.stringify(request)); } $("#game-status").text("your turn").css({'background':'palegoldenrod','color':'#666'}).fadeIn(); } else{ $("#game-status").text(player.username+"'s turn").fadeIn(); $(".turn-indicator").css({"display":"inherit"}); if(!card){ decrementCardsCount(); } else{ if(card.revealed){ $(".revealed-card-notice").show(); pullCard(card); } } } $("b.currentPlayer").text(player.username); $("li.current-player").removeClass("current-player"); $("li[data-pId="+player.pId+"]").addClass("current-player"); } const revealCard = () => { card.revealed = true; packet = { 'type': 'revealCard', 'card': card } markRevealedCard(); ws.send(JSON.stringify(packet)); } const clearActiveCard = () => { var empty = ""; $(".active-card").hide().attr('data-author',empty); $("#pick-first-turn").css({'display':'flex'}); $(".revealed-card-notice").hide(); $(".active-card-controls").hide(); $(".active-card h1.card-title").text(empty); $(".active-card img.card-picture").attr('src',empty); $(".active-card div.card-content").text(empty); $("li.reveal-card > a").text("Reveal Card").removeClass('uk-disabled').removeClass('revealed'); } const doneWithCard = () => { clearActiveCard(); $("#game-status").css({"background":"#1e87f0","color":"#fff"}); packet = { 'type': 'endTurn' } ws.send(JSON.stringify(packet)); } const addVote = (i) => { var el = $(".play-list-vote[data-pId="+i+"]"); el.text(parseInt(el.text()) + 1).css({"display":"grid", "float":"right"}); } const pullCard = (pulledCard) => { card = pulledCard; const cardAuthor = pulledCard.author; const cardTitle = pulledCard.title; const cardImage = pulledCard.image; const cardContent = pulledCard.content; $(".active-card").attr('data-author',cardAuthor); $(".active-card h1.card-title").text(cardTitle); if(cardTitle == ""){$(".active-card h1.card-title").hide()} $(".active-card img.card-picture").attr('src',cardImage); $(".active-card div.card-content").text(cardContent); if(cardAuthor == username){ $(".your-card").show(); } $("#pick-first-turn").hide(); $("#card-view").css({'display':'flex'}); if(card.revealed){ markRevealedCard(); } } const markRevealedCard = () => { $("li.reveal-card > a").text("revealed").addClass('uk-disabled revealed'); } const viewRevealedCard = (card) => { pullCard(card); if($("b.currentPlayer").first().text() != username){$(".revealed-card-notice").show()}; } const updateUsername = (i, uname) => { $(".input-username").val(uname); const url = window.location.origin + window.location.pathname; $("span.username[pId='"+i+"']").text(uname); $(".input-username").val(uname); history.pushState({}, "rename", url + "?username=" + uname ); } ws.onmessage = (event) => { event = JSON.parse(event.data); switch(event.type){ case 'init': if(event.mode == "error"){ window.location = window.origin + "?error=username"; } console.log(">> Initializing game..."); pId = event.id; console.log("You are in the game as '" + username + "' (Player " + pId + ")."); $(".input-username").val(username); event.players.forEach(function(p){ addUser(p); }); $("#toggle_play > .uk-badge").text(event.cards+1 +" cards"); decrementCardsCount(); if(event.mode == "play"){ changeMode(event); $("#toggle_play").click(); } $(".input-username").value = username; $("span#number-of-players").text(event.players.length); event.messages.forEach(function(e){ addMessage(e); }); break; case 'changeMode': changeMode(event); addMessage(event.message); break; case 'changeUsername': console.log('Got an updated username: Player %s is now "%s".', event.pId, event.username); updateUsername(event.pId, event.username); break; case 'updateCardsList': if(username == event.author){ notice("Your card was submitted."); }else{ notice(event.author + " submitted a card."); } var el = $("#toggle_play > .uk-badge"); el.html(parseInt(el.text()) + 1 +" cards"); break; case 'error': console.log(">> Error: " + event.content); if(event.err_username){ } UIkit.notification({ message: event.content, status: 'warning', pos: notification_pos, timeout: 1000 }); break; case 'notification': console.log(">> Notification: " + event.content); UIkit.notification({ message: event.content, status: 'success', pos: notification_pos, timeout: 1000 }); break; case 'gameOver': console.log(">> GAME OVER: " + event.content); UIkit.notification({ message: event.content, status: 'success', pos: notification_pos, timeout: 1000 }); $("#game-status").html("game over"); $("#play_mode").html( "

    Game over, thanks for playing!

    " ); break; case 'message': console.log(">> Got a message."); addMessage(event); break; case 'changeProfilePic': updateProfPic(event.player, event.href); break; case 'vote': addVote(event.pId); if(firstPlayerPicked){ notice("First turn starting!"); $("#draw_mode").html(""); } break; case 'revealCard': viewRevealedCard(event.card); break; case 'pulledCard': if(event.last){ notice("Last card!"); lastCard = true; } pullCard(event.card); break; case 'nextTurn': changeActivePlayer(event.playerTurn, null); break; case 'newPlayer': var player = event.player; if(player.pId != pId){ addUser(player); } break; default: console.log('Unknown event. Pasting:'); console.log(event); } }; const changeUsername = (name) => { packet = { "type": "changeUsername", "pId": pId, "username": name } console.log("Changing username to: '"+name+"'"); username = name; ws.send(JSON.stringify(packet)); }; const notice = (message) => { UIkit.notification({ message: message, status: 'primary', pos: notification_pos, timeout: 2000 }); } const error = (message) => { UIkit.notification({ message: message, status: 'danger', pos: notification_pos, timeout: 2000 }); } const urlify = (text) => { var urlRegex = /(((https?:\/\/)|(www\.))[^\s]+)/g; //var urlRegex = /(https?:\/\/[^\s]+)/g; return text.replace(urlRegex, function(url,b,c) { var url2 = (c == 'www.') ? 'http://' +url : url; return '' + url + ''; }) }; const submitMessage = () => { message = $("#message").val(); if(message.trim()){ const timestamp = new Date(); packet = { "type": "message", "pId": pId, "username": username, "message": urlify(message.trim()), "timestamp": new Date() } console.log("Sending message."); ws.send(JSON.stringify(packet)); $("#message").val(""); }}; const chooseGiphy = (url) => { $("img.card-picture").attr("src", url); $(".uk-close").click(); } const chooseProfile = (url) => { packet = { 'type': 'changeProfilePic', 'player': { 'pId': pId, 'username': username }, 'href': url } $(".change-profile > svg").hide(); $(".uk-close").click(); ws.send(JSON.stringify(packet)); } const updateProfPic = (player, url) => { $("img[data-pId="+player.pId+"]").attr('src',url); } const giphySearch = () => { var query = $("#giphySearch").val().trim().replace(/ /g, "+"); const api_url = "https://api.giphy.com/v1/gifs/search?api_key=GUHvLYHRcNgPAIKt4PNZcjYw5FBeBX0F&q="+query+"&limit=25&offset=0&rating=R&lang=en"; $.ajax({url: api_url, method: 'GET'}).done(function(response){ // This is the API response data. It's a JSON object of 25 gifs console.log(response.data); $("#giphySearchResults").html(""); response.data.forEach(function(i){ var giphyURL = i.images.fixed_height.url; $("#giphySearchResults").append( "" ); }); }); }; const voteForPlayer = (i) => { console.log("Sending in a vote."); packet = { 'type': "vote", 'pId': i } ws.send(JSON.stringify(packet)); } const playModeChangeUsername = (e) => { if(e.keyCode === 13){ changeUsername($(".player-username > input").val()); }; } $().ready(function() { $("#toggle_chat").on('click', function(e){ $(this).closest("li").toggleClass("uk-active"); }); $(".input-username").keydown(function(e){ if(e.keyCode === 13){ changeUsername(this.value); }; }); $(".input-username").focusout(function(e){ changeUsername(this.value); }); $("#message").keyup(function(e){ if(e.keyCode === 13){ submitMessage(); }; }); $("a#toggle_draw").on('click', function(e){ if(gameMode == "play"){ // Switch tabs $("#play_mode").hide();$("a#toggle_play").closest("li").removeClass("uk-active"); $("#draw_mode").show();$("a#toggle_draw").closest("li").addClass("uk-active") } }); $("a#toggle_play").on('click', function(e){ if(gameMode == "play"){ // Switch tabs $("#draw_mode").hide();$("a#toggle_draw").closest("li").removeClass("uk-active"); $("#play_mode").css({"display":"flex"});$("a#toggle_play").closest("li").addClass("uk-active") } else{ // Request server to start game console.log("Asking server to start game..."); packet = { "type": "startPlayMode", "player": username } ws.send(JSON.stringify(packet)); setTimeout(function(e){ if(gameMode == "play"){ // Switch tabs console.log("Switching tabs"); $("#draw_mode").hide();$("a#toggle_draw").closest("li").removeClass("uk-active"); $("#play_mode").css({"display":"flex"});$("a#toggle_play").closest("li").addClass("uk-active") } }, 500); } }); $("#submitCard").on('click', function(e){ submitCard(); clearCard(); }); $("#newCard").on('click', function(e) { clearCard(); }); $("#giphySearch").keyup(function(e){ if(e.keyCode == "13"){ giphySearch(); } }); $("#giphySearchButton").click(function(e){ giphySearch(); }); $("#imageInsta").click(function(e){ notice("TODO: Add insta feature"); }); $("#imageUpload").click(function(e){ notice("TODO: Add upload feature"); }); $("#imageDraw").click(function(e){ notice("TODO: Add draw feature"); }); range(22).forEach(function(e){ var profURL = "/img/profiles/"+e+".jpg"; $("#profile-options").append( "" ); }); $('#imageModalContent').on('keyup keypress', function(e) { var keyCode = e.keyCode || e.which; if (keyCode === 13) { e.preventDefault(); return false; } }); $("#manualProfile").on('keyup', function(e){ if(e.keyCode == 13){ const url = $(this).val(); $("#manual-img").attr("src", url).show(); $("#manual-img-href").attr('href', "javascript:chooseProfile(" + '"' + url + '"' +");" ); } else{ $("#manual-img").attr("src", "").hide(); } }); });