From 9c1fb2013b9f99c61e2f5f5278b8922497a6b806 Mon Sep 17 00:00:00 2001 From: Cristiano Pires Date: Wed, 29 Mar 2023 23:24:27 +0100 Subject: [PATCH] League System --- controller/api.js | 310 +++++++++++++++++++++++++++++++++- models/league.js | 23 +++ models/leagueGame.js | 56 ++++++ public/css/createLeague.css | 99 +++++++++++ public/css/league.css | 227 +++++++++++++++++++++++++ public/css/leaguelistener.css | 152 +++++++++++++++++ public/css/leagues.css | 97 +++++++++++ public/js/createleague.js | 55 ++++++ public/js/dashboard.js | 3 +- public/js/league.js | 152 +++++++++++++++++ public/js/leaguelistener.js | 220 ++++++++++++++++++++++++ public/js/leagues.js | 52 ++++++ routes/routes.js | 8 + test.js | 164 ++++++++++++++++++ views/createLeague.ejs | 31 ++++ views/league.ejs | 38 +++++ views/leaguelistener.ejs | 35 ++++ views/leagues.ejs | 29 ++++ 18 files changed, 1748 insertions(+), 3 deletions(-) create mode 100644 models/league.js create mode 100644 models/leagueGame.js create mode 100644 public/css/createLeague.css create mode 100644 public/css/league.css create mode 100644 public/css/leaguelistener.css create mode 100644 public/css/leagues.css create mode 100644 public/js/createleague.js create mode 100644 public/js/league.js create mode 100644 public/js/leaguelistener.js create mode 100644 public/js/leagues.js create mode 100644 views/createLeague.ejs create mode 100644 views/league.ejs create mode 100644 views/leaguelistener.ejs create mode 100644 views/leagues.ejs diff --git a/controller/api.js b/controller/api.js index 8996251..0629a2d 100644 --- a/controller/api.js +++ b/controller/api.js @@ -1,7 +1,10 @@ const GuildM = require('../models/guilds'); const roleRulesM = require('../models/autoRoleRule'); -const feedsM = require('../models/feeds') +const feedsM = require('../models/feeds'); +const leagueGameM = require('../models/leagueGame'); +const leagueM = require('../models/league'); const xmlparser = require('xml-js') +const {isValidObjectId} = require('mongoose') exports.getUser = (io)=> { @@ -367,3 +370,308 @@ exports.deleteFeed = (req,res) => { feedsM.findOneAndDelete({_id:req.headers.feedid}).then(()=>{res.json({success:true})}).catch(error=>{res.json({error})}) } + +exports.getTournamentPage = (req,res)=> +{ + if(!req.query.league) return res.render('leagues'); + if(!isValidObjectId(req.query.league)) return res.redirect('/leagues') + leagueM.findById(req.query.league) + .then(league=> + { + if(league) res.render('leagues') + }) + .catch( + res.render('leagues') + ) +} +exports.getAllLeagues = (req, res)=> +{ + leagueM.find() + .then((leagues, err)=> + { + if(err) return res.json({Error:'Yea there was a problem.'}); + if(!leagues) return res.json({Error:'Yea there was a problem.'}); + if(leagues.length==0) return res.json({Error:'No leagues.'}) + return res.json({data:leagues}) + }) + .catch(err=>console.log('Error finding leagues.')) +} +exports.getLeague = async (req, res)=> +{ + if(!isValidObjectId(req.headers.leagueid)) return res.json({Error:'Yea this aint it chief... stop trying to mess with the system.'}) + leagueM.findById(req.headers.leagueid) + .then((league, err)=> + { + if(err) return res.json({Error:'Yea there was a problem.'}); + if(!league) return res.json({Error:'Yea there was a problem.'}); + if(league.length==0) return res.json({Error:'No leagues.'}) + return res.json({data:league}) + }) + .catch(err=>console.log()) +} +exports.getLeaguePage = (req,res)=> +{ + if(req.originalUrl == '/leagues/') return res.redirect('/leagues') + + return res.render('league') +} +exports.registerGame = async (req, res)=> +{ + const GameData = + { + result:req.body.result, + info:req.body.gameData, + id: req.headers.id, + leagueid: req.headers.leagueid + } + const data = req.body.data; + var league = await leagueM.findById(GameData.leagueid).then(league=>{return league}) + if(!league) return res.json({Error:'The league id is not valid'}) + var Game = league.Games.filter(x=>(x.gId == GameData.id && x.Played == false)); + if(Game.length == 0) return res.json({Error: 'The game id is not valid.'}) + + const gameStartTime = new Date(Date.now()-(GameData.info.gameTime*1000)).getTime(); //Epoch - gametime; + const result = GameData.result; + var update = await leagueGameM.findById(GameData.id).then(game=>{return game}); + var PA = fillPlayer(update.PA, update.PA.Name == GameData.info.PlayerA.summonerName? GameData.info.PlayerA: GameData.info.PlayerB, update.PA.Name == GameData.result.winner); + var PB = fillPlayer(update.PB, update.PB.Name == GameData.info.PlayerA.summonerName? GameData.info.PlayerA: GameData.info.PlayerB, update.PB.Name == GameData.result.winner); + update.PA = PA; + update.PB = PB; + update.Winner = result.winner; + update.WinCondition = result.winCondition; + update.Played = true; + update.PlayedTimeStamp = gameStartTime; + const updated = await leagueGameM.findByIdAndUpdate(GameData.id,update).then(()=> + { + return true + }) + .catch(()=> + { + return false + }) + if(!updated) return res.json({Error:'The game failed to register.'}) + Game[0] = { + PA:update.PA, + PB:update.PB, + Winner:update.Winner, + WinCondition:update.WinCondition, + Played:true, + PlayedTimeStamp:gameStartTime, + gId:GameData.id + } + const index = league.Games.findIndex(x=>x.gId=GameData.id); + league.Games[index] = Game[0]; + const PAIndex = league.Players.findIndex(x=>x.Name == GameData.info.PlayerA.summonerName) + const PBIndex = league.Players.findIndex(x=>x.Name == GameData.info.PlayerB.summonerName) + const originalA = league.Players[PAIndex]; + league.Players[PAIndex]={ + Name: originalA.Name, + Points: originalA.Points + (originalA.Name == result.winner?1:0), + PlayedPoints: originalA.PlayedPoints + 1, + Kills: originalA.Kills + GameData.info.PlayerA.Kills, + Deaths: originalA.Deaths + GameData.info.PlayerA.Deaths, + CreepScore: originalA.CreepScore + GameData.info.PlayerA.CS + } + const originalB = league.Players[PBIndex]; + league.Players[PBIndex]={ + Name: originalB.Name, + Points: originalB.Points + (originalB.Name == result.winner?1:0), + PlayedPoints: originalA.PlayedPoints + 1, + Kills: originalB.Kills + GameData.info.PlayerB.Kills, + Deaths: originalB.Deaths + GameData.info.PlayerB.Deaths, + CreepScore: originalB.CreepScore + GameData.info.PlayerB.CS + } + const leagueUpdated = await leagueM.findByIdAndUpdate(GameData.leagueid,league).then(()=> + { + return true; + }) + .catch(()=>{return false}) + if(!leagueUpdated) return res.json({Error:'Failed to update league.'}) + res.json({success:true}) +} +function fillPlayer(P, data,winner) +{ + P.winner = winner; + P.Kills = data.Kills; + P.Deaths = data.Deaths; + P.CS = data.CS + return P; +} +exports.getTournamentListenerPage = (req,res)=> +{ + return res.render('leaguelistener') +} + +exports.createLeague = async (req, res)=> +{ + const verification = await verifyBody(req.body); + if(verification.Error) return res.json(verification) + var LeagueReference = + { + Name:verification.name, + Players:[], + Games:[], + Owner:verification.owner + } + for(player of verification.players) + { + (async (player)=> + { + LeagueReference.Players.push( + { + Name:player, + Points:0, + PlayedPoints:0, + Kills:0, + Deaths:0, + CreepScore:0 + } + ); + })(player) + } + + var games = await scheduler(verification.players) + LeagueReference.Games=games; + var league = new leagueM(); + league.Name = LeagueReference.Name; + league.Players = LeagueReference.Players; + league.Games = LeagueReference.Games; + league.Owner = LeagueReference.Owner + league.save() + .then(leagueS=> + { + return res.json({Success:true, data:leagueS}); + }) + .catch(err=> + { + return res.json({Error:'There was an error trying to save your league, try again later.'}); + }) +} +async function verifyBody(body) +{ + if(!body.owner) return {Error:'Stop trying to mess with the system.'}; + if(!body.name) return {Error:'The league needs to be named.'}; + if(!body.players) return {Error:'The league needs to have players playing it.'} + var players = [...body.players.split(',')]; + var playerPayload = []; + var promises = []; + for (var player of players) + { + (async (player)=> + { + promises.push(new Promise ((resolve)=> + { + fetch(`https://euw1.api.riotgames.com/lol/summoner/v4/summoners/by-name/${player}`, + { + method: "GET", + headers: { + "X-Riot-Token": "RGAPI-fc17a511-f587-495b-ac01-80716870d46b" + } + }) + .then(response=>{return response.json()}) + .then(res=> + { + if(res.status) playerPayload = {Error:'Player '+player+' does not exist.'}; + try + { + playerPayload.push(res.name) + } + catch{} + resolve(); + }) + .catch(err=>{console.log(err)}) + })) + })(player) + } + var payload = await Promise.all(promises).then(() => + { + if(playerPayload.Error) return playerPayload; + return {name:body.name, owner:body.owner,players:playerPayload} + }) + return payload; +} +async function scheduler(players) +{ + var games = []; + var promises = []; + for(var player of players) + { + (async (player)=> + { + promises.push(new Promise ((resolve)=> + { + for(var i = players.length-1; i>=0;i--) + { + (async (player2)=> + { + if(player == player2) resolve(); + else + { + games.push({ + PA:{ + Name:player, + winner:false, + Kills:0, + Deaths:0, + CS:0 + }, + PB:{ + Name:player2, + winner:false, + Kills:0, + Deaths:0, + CS:0 + }, + Winner:'', + WinCondition:'', + Played:false, + PlayedTimeStamp:'', + gId:'' + }) + resolve() + } + })(players[i]) + } + })) + })(player) + } + var aux = []; + for await(var game of games) + { + (async (game)=> + { + promises.push(new Promise ((resolve)=> + { + var gameM = new leagueGameM(); + gameM.PA = game.PA; + gameM.PB = game.PB; + gameM.Winner = ' '; + gameM.WinCondition = ' '; + gameM.Played = false; + gameM.PlayedTimeStamp = ' '; + gameM.save().then((g)=> + { + game.gId = g.id; + aux.push(game) + resolve(); + }) + })); + })(game); + } + + var payload = await Promise.all(promises).then(() => + { + return aux; + }) + return payload; +} +exports.createLeaguePage = (req, res)=> +{ + return res.render('createLeague'); +} +exports.createLeaguePage = (req, res)=> +{ + //TODO: Render page; + res.render('createLeague'); +} + diff --git a/models/league.js b/models/league.js new file mode 100644 index 0000000..8b3228a --- /dev/null +++ b/models/league.js @@ -0,0 +1,23 @@ +const mongoose = require('mongoose'); +const Schema = mongoose.Schema; + + +let leagueM = +new Schema( + { + Name: {type: String, required: true, max: 20, unique:true}, + Players: {type: Array, required: true, max: 10}, + Games:{type: Array, required:true}, + Owner:{type:String, required:true} + } + ); + + + + +const League = module.exports = mongoose.model('leagues',leagueM); +module.exports.get = (callback, limit)=> +{ + League.find(callback).limit(limit); +} + \ No newline at end of file diff --git a/models/leagueGame.js b/models/leagueGame.js new file mode 100644 index 0000000..6a4506b --- /dev/null +++ b/models/leagueGame.js @@ -0,0 +1,56 @@ +const mongoose = require('mongoose'); +const Schema = mongoose.Schema; + + +let leagueGameM = +new Schema( + { + PA:{type:Object, required:true}, + PB:{type:Object, required:true}, + Winner:{type:String, required:true}, + WinCondition:{type:String, required:true}, + Played:{type:Boolean, required:true}, + PlayedTimeStamp:{type:String, required:true} + } + ); + + + + +const leagueGame = module.exports = mongoose.model('leagueGames', leagueGameM); +module.exports.get = (callback, limit)=> +{ + leagueGame.find(callback).limit(limit); +} + /** + * + result:{ + winCondition:'string' + winner:string + }, + gameData: + { + PlayerA: + { + championName:PA.championName, + items:PA.items, + level:PA.level, + runes:PA.runes, + skin:PA.skinID, + skinName:PA.skinName, + summs:PA.summonerSpells + }, + PlayerB: + { + championName:PB.championName, + items:PB.items, + level:PB.level, + runes:PB.runes, + skin:PB.skinID, + skinName:PB.skinName, + summs:PB.summonerSpells + }, + gameTime:data.gameData.gameTime + } + + */ \ No newline at end of file diff --git a/public/css/createLeague.css b/public/css/createLeague.css new file mode 100644 index 0000000..066b4d1 --- /dev/null +++ b/public/css/createLeague.css @@ -0,0 +1,99 @@ +body +{ + text-align: center; + background-color: #071c24; + position: absolute; + margin: 0; + width: 100%; + height: 100%; + align-content:center; + font-family: 'Eczar', serif; + font-weight: bold; +} + +/* width */ +::-webkit-scrollbar { + width: 10px; + } + + /* Track */ + ::-webkit-scrollbar-track { + background: #020a0e91; + margin-top: 3em; + margin-bottom: 3em; + border-radius: 30px; + } + + /* Handle */ + ::-webkit-scrollbar-thumb { + background: #076969; + border-radius: 30px; + } + + /* Handle on hover */ + ::-webkit-scrollbar-thumb:hover { + background: #064e4e; + } + + + form +{ + align-items:center; + width: 50vw; + height:30vh; + position:absolute; + top: 30%; + left:50%; + transform:translate(-50%, -50%); + align-items:center; + text-align:center; + +} +label +{ + font-size:2em; + font-family:'Eczar', serif; + color:#9fc3c3; + transform:translate(-50% , -2em); +} +textarea +{ + background-color: #00000054; + border: 2px solid transparent; + color: #9fc3c3; + text-overflow: wrap; + width: 37.5%; + height: 4em; + resize: none; + border-radius:5px; +} +input +{ + background-color: #00000054; + border: 2px solid transparent; + border-radius:5px; + width: 50%; + height:2em; + position:relative; + top:2.5em; + left:-10%; + margin-bottom:2em; + color:#9fc3c3; + +} +#name +{ + position:relative; + left:25%; +} +button +{ + border-radius: 5px; + background-color:#000000; + color:#9fc3c3; + font-size:1em; + font-family:'Eczar', serif; + width:5em; + height:2.5em; + cursor:pointer; +} diff --git a/public/css/league.css b/public/css/league.css new file mode 100644 index 0000000..d033dde --- /dev/null +++ b/public/css/league.css @@ -0,0 +1,227 @@ +body +{ + background-color: #071c24; + position: absolute; + margin: 0; + width: 100%; + height: 100%; + font-family: 'Eczar', serif; + font-weight: bold; +} + +/* width */ +::-webkit-scrollbar { + width: 10px; + } + + /* Track */ + ::-webkit-scrollbar-track { + background: #020a0e91; + margin-top: 3em; + margin-bottom: 3em; + border-radius: 30px; + } + + /* Handle */ + ::-webkit-scrollbar-thumb { + background: #076969; + border-radius: 30px; + } + + /* Handle on hover */ + ::-webkit-scrollbar-thumb:hover { + background: #064e4e; + } + + +#TableWrapper +{ + background-color:#758186a9; + width: 40%; + height:75%; + position:relative; + left:5%; + top:25%; + border:0 solid transparent; + border-radius:25px; + overflow-y:scroll; +} + +#LeagueTable +{ + width:100%; + height:100%; + margin:0; + padding:0; + border-collapse: collapse; + +} +#LeagueHeader +{ + width:70%; +} +th +{ + height:2em; + font-size:2em; + border-bottom:1px solid black; + +} +td +{ + font-size:1.3em; + text-align:center; +} +.league +{ + cursor:pointer; +} + +#span +{ + color:#9fc3c3; + font-size: 2em; + position:relative; + top:calc(100% - 1.4em); +} + +.hidden +{ + display:none; +} +.sideWrapper +{ + + width:40%; + height:75%; + position:absolute; + top:25%; + right:5%; +} +.button +{ + width:8em; + height:5%; + background-color:#758186a9; + background-position:10%; + margin:0; + position:relative; + top:0; + left:0; + float:left; + border-radius:25px 25px 0px 0px; + text-align:center; + cursor:pointer; +} +.scheduleBt +{ + margin-left:-5%; +} +.button > span +{ + position: relative; + top:calc(50% - 0.5em); +} +.active +{ + background-color:#385663; + display: block !important; + z-index:1; +} +.bg_div +{ + /* background-color:#758186a9; */ + border-radius:0px 25px 25px 25px; + position:relative; + top:10%; + left:0; + width:100%; + height:90%; +} +.results +{ + background-color:#385663; + height:105.5%; + width:100%; + position:relative; + top:-5.7%; + left:0; + border-radius:0px 25px 25px 25px; + font-weight:bold; + text-align:left; + display: none; +} +.schedule +{ + background-color:#385663; + height:105.5%; + width:100%; + position:relative; + top:-5.7%; + left:0; + border-radius:2px 25px 25px 25px; + font-weight:bold; + text-align:left; + display: none; +} +.schedule .matchPlayers +{ + cursor:pointer; +} +.winner +{ + color:green; +} +.tab +{ + font-size:1.5em; + font-family: 'Eczar', serif; + color:#9fc3c3; +} +#day +{ + color:#9fc3c3; + margin-top:0px; + width:90%; + position:relative; + left:10px; + text-align:left; + border-bottom:2px solid #9fc3c3; +} +#dayp +{ + text-align: left; +} +#day > p +{ + position:relative; + margin:0; + left:-28%; +} + +.match +{ + display:flex; + position:relative; + width:90%; + left:2%; + margin:0; + font-weight:bolder; + +} +.matchPlayers +{ + flex:1; + flex-direction: column; + justify-content: left; +} +.matchPlayers > p +{ + margin:0; + position:relative; + left:2.5%; +} +.matchResult +{ + width:15%; +} diff --git a/public/css/leaguelistener.css b/public/css/leaguelistener.css new file mode 100644 index 0000000..d960fd1 --- /dev/null +++ b/public/css/leaguelistener.css @@ -0,0 +1,152 @@ +body +{ + text-align: center; + background-color: #071c24; +} +.wrapper +{ + position: absolute; + top:60vh; + left:calc(50% - 150px); +} +.bt +{ + position: absolute; + border-bottom: 100px solid #1e252a; + border-left: 50px solid transparent; + border-right: 50px solid transparent; + border-radius: 0% 0% 50% 50%; + height: 0; + cursor: pointer; + width: 200px; +} + +.base +{ + z-index: 1; +} +.border +{ + position: relative; + left:-5px; + top: -0.23em; + z-index: 0; + border-bottom: 108px solid #0F9C94; + border-left: 52px solid transparent; + border-right: 52px solid transparent; + border-radius: 0% 0% 50% 50%; + height: 0; + width: 206px; +} + +.border2 +{ + position: relative; + top:calc(-108px + -1em); + left:calc(-5px + -1em); + z-index: -1; + border-bottom: calc(108px + 1.5em) solid #081620; + border-left: 60px solid transparent; + border-right: 60px solid transparent; + border-radius: 0% 0% 50% 50%; + height: 0; + width: calc(206px + 1em); +} +.border3 +{ + position: relative; + top:calc(-216px + -2.8em); + left:calc(-5px + -1.35em); + z-index: -2; + border-bottom: calc(108px + 2em) solid #7A6B43; + border-left: 66px solid transparent; + border-right: 66px solid transparent; + border-radius: 0% 0% 50% 50%; + height: 0; + width: calc(206px + 1em); +} +.bt_text +{ + color: #9fc3c3; + position:relative; + font-family: 'Eczar', serif; + font-weight: bold; + text-transform: uppercase; + font-size: 3em; + top:0.4em; + left:0em; +} + +h1{ + margin-top: 27vh; + color: #9fc3c3; +} +h3 +{ + color: #9fc3c3; +} + +@keyframes spin3D { + from { + transform: rotate3d(.5,.5,.5, 360deg); + } + to{ + transform: rotate3d(0deg); + } +} +.active +{ + display:flex !important; +} +.spinner { + position: absolute; + top:38vh; + left:44.5vw; + display:none; + width: 200px; + height: 200px; + justify-content: center; + align-items: center; + background-color: transparent; +} +.leo-border-1 { + position: absolute; + width: 100px; + height: 100px; + padding: 3px; + display: flex; + justify-content: center; + align-items: center; + border-radius: 50%; + background: rgb(63,249,220); + background: linear-gradient(0deg, rgba(63,249,220,0.1) 33%, rgba(63,249,220,1) 100%); + animation: spin3D 1.8s linear 0s infinite; +} + +.leo-core-1 { + width: 100%; + height: 100%; + background-color: #37474faa; + border-radius: 50%; +} + +.leo-border-2 { + position: absolute; + width: 100px; + height: 100px; + padding: 3px; + display: flex; + justify-content: center; + align-items: center; + border-radius: 50%; + background: rgb(251, 91, 83); + background: linear-gradient(0deg, rgba(251, 91, 83, 0.1) 33%, rgba(251, 91, 83, 1) 100%); + animation: spin3D 2.2s linear 0s infinite; +} + +.leo-core-2 { + width: 100%; + height: 100%; + background-color: #1d2630aa; + border-radius: 50%; +} diff --git a/public/css/leagues.css b/public/css/leagues.css new file mode 100644 index 0000000..ae06575 --- /dev/null +++ b/public/css/leagues.css @@ -0,0 +1,97 @@ +body +{ + text-align: center; + background-color: #071c24; + position: absolute; + margin: 0; + width: 100%; + height: 100%; + align-content:center; + font-family: 'Eczar', serif; + font-weight: bold; +} + +/* width */ +::-webkit-scrollbar { + width: 10px; + } + + /* Track */ + ::-webkit-scrollbar-track { + background: #020a0e91; + margin-top: 3em; + margin-bottom: 3em; + border-radius: 30px; + } + + /* Handle */ + ::-webkit-scrollbar-thumb { + background: #076969; + border-radius: 30px; + } + + /* Handle on hover */ + ::-webkit-scrollbar-thumb:hover { + background: #064e4e; + } + + +#TableWrapper +{ + background-color:#758186a9; + width: 50%; + height:50%; + position:relative; + left:25%; + top:25%; + border:0 solid transparent; + border-radius:25px; + overflow-y:scroll; + +} +#LeaguesTable +{ + width:100%; + height:100%; + margin:0; + padding:0; + border-collapse: collapse; + +} +#LeagueHeader +{ + width:70%; +} +th +{ + height:2em; + font-size:2em; + border-bottom:1px solid black; + +} +td +{ + font-size:1.3em; +} +.league +{ + cursor:pointer; +} +.CreateButton +{ + background-color:#0F9C94; + height: 3em; + width:150px; + position:absolute; + top: 1em; + right: 2em; + border-radius:25px; + cursor:pointer; +} +span +{ + color:#9fc3c3; + font-size: 2em; + position:relative; + top:calc(100% - 1.4em); +} diff --git a/public/js/createleague.js b/public/js/createleague.js new file mode 100644 index 0000000..3d746bd --- /dev/null +++ b/public/js/createleague.js @@ -0,0 +1,55 @@ +var User; + + +window.onload = async () => +{ + const fragment = new URLSearchParams(window.location.hash.slice(1)); + const [accessToken, tokenType] = [fragment.get('access_token'), fragment.get('token_type')]; + if (!accessToken) return window.location.href = '/'; + User = await getUser(accessToken, tokenType); +}; + +async function getUser(accessToken, tokenType) +{ + + return await fetch(`${window.location.origin}/api/getUser`, + { + method: "POST", + headers: { + authorization: `${tokenType} ${accessToken}`, + }, + }) + .then(result => result.json()) + .then(response => + { + return response + }) + .catch(console.error); +} +async function sendRequest(form) +{ + var leagueName = form.children[0].children[1].value; + var players = form.children[1].children[0].children[0].children[0].value + var owner= User.id + var payload = { + name:leagueName, + players, + owner + } + return await fetch(`${window.location.origin}/api/createLeague`, + { + method: "POST", + headers: { + 'Content-Type': 'application/json', + 'Accept': 'application/json', + }, + body:JSON.stringify(payload), + }) + .then(result => result.json()) + .then(response => + { + if(response.Error) alert(response.Error) + location.replace(location.origin+'/leagues?league='+response.data._id); + }) + .catch(console.error); +} \ No newline at end of file diff --git a/public/js/dashboard.js b/public/js/dashboard.js index f2656cf..59ce8cb 100644 --- a/public/js/dashboard.js +++ b/public/js/dashboard.js @@ -8,7 +8,7 @@ window.onload = async () => updateUser(accessToken, tokenType); updateGuildData(accessToken, tokenType); document.getElementById('RoleRules').onclick = handleToggleRules; - + test(); }; function updateUser(accessToken, tokenType) @@ -510,4 +510,3 @@ function _updateFeed(element) } - diff --git a/public/js/league.js b/public/js/league.js new file mode 100644 index 0000000..cd9988e --- /dev/null +++ b/public/js/league.js @@ -0,0 +1,152 @@ +var leagueID; +window.onload = async ()=> +{ + leagueID = location.href.split('/')[location.href.split('/').length-1] + var league = await fetch(`${window.location.origin}/api/getLeague`, + { + method: "GET", + headers:{ + leagueid:leagueID + } + }) + .then(res=>{return res.json()}) + .then(response=> + { + if(response.Error) alert(response.Error) + return response.data; + }) + .catch(console.error) + fillResults(league.Games); + fillSchedule(league.Games); + fillPlayers(league.Players) +} +function toggleTab (bt, oBt) +{ + bt.classList.contains('active')?bt.classList.remove('active'):bt.classList.add('active'); + oBt.classList.contains('active')?oBt.classList.remove('active'):oBt.classList.add('active'); + var results = document.getElementById('results'); + var schedule = document.getElementById('schedule'); + results.classList.contains('active')?results.classList.remove('active'):results.classList.add('active'); + schedule.classList.contains('active')?schedule.classList.remove('active'):schedule.classList.add('active'); +} + +async function fillResults(Games) +{ + //just so that I have 1 to work with + // Games[0].Played = true; + // Games[0].Winner = 'hc12'; + // Games[0].PA.Winner = true; + // Games[0].PA.Kills = 1; + // Games[0].PA.CS = 50; + // Games[0].PlayedTimeStamp = new Date(Date.now()).getDate()+'/' + (new Date(Date.now()).getMonth()+1); + // Games[0].WinCondition = "FirstBlood"; + // Games = Games.filter(x=>x.Played) + Games = Games.filter(x=>x.Played==true); + if(Games.length==0) return; + const filteredGames = Games.reduce((Game, obj) => + { + const { PlayedTimeStamp, ...rest } = obj; + Game[PlayedTimeStamp] = Game[PlayedTimeStamp] || []; + Game[PlayedTimeStamp].push(rest); + return Game; + }, {}); + var matches =[]; + var days=[]; + for await(var day of Object.keys(filteredGames)) + { + for await(var game of filteredGames[day]) + { + console.log(game) + matches.push(` +
+ +
+

+ ${game.PA.Name} x ${game.PB.Name} +

+
+
+ + 1 + + + x + + + 1 + +
+
+ `) + } + const Day = new Date(Number(day)); + days.push(` +
+
+

Day:${day?(Day.getDate()+'/' + (Day.getMonth()+1)):Object.keys(filteredGames).length}

+
+
+ ${matches.join('\n')} +
+
+ `) + } + document.getElementById('results').innerHTML = days,join('\n'); +} +async function fillSchedule(Games) +{ + Games = Games.filter(x=>x.Played==false) + var matches = []; + for await(var game of Games) + { + matches.push(` +
+
+

+ ${game.PA.Name} x ${game.PB.Name} +

+
+
+ `) + } + document.getElementById('schedule').innerHTML = matches.join('\n') + +} +async function fillPlayers(Players) +{ + Players.sort(function(a, b) { + return b.Points - a.Points; + }); + var players = []; + for await(var player of Players) + { + players.push(` + + ${player.Name} + ${player.Points} + ${player.PlayedPoints} + ${player.Kills} + ${player.Deaths} + ${player.CreepScore} + + `) + } + document.getElementById('LeagueTable').innerHTML = + ` + + Players + P + PP + K + D + CS + + ${players.join('\n')} + ` + +} + +async function listener(id) +{ + window.open(`${window.location.origin}/leagueListener?id=${id}&leagueid=${leagueID}`) +} \ No newline at end of file diff --git a/public/js/leaguelistener.js b/public/js/leaguelistener.js new file mode 100644 index 0000000..191a7bb --- /dev/null +++ b/public/js/leaguelistener.js @@ -0,0 +1,220 @@ +var interval; +var hasStarted = false; +var hasBeenAlerted = false; +var id = ''; +var leagueid = ''; +window.onload = ()=> +{ + startSpinner(); + const urlParams = new URLSearchParams(window.location.search); + const entries = urlParams.entries(); + const params = {}; + for (entry of entries) + { + params[entry[0]] = entry[1]; + } + id = params[id]; + leagueid = params[leagueid] +} +function startSpinner() +{ + var interval = setInterval(() => { + if(hasStarted) + { + document.getElementById('spinner').classList.add('active'); + clearInterval(interval); + } + }, 10); +} +function stopSpinner() +{ + document.getElementById('spinner').classList.remove('active') +} +async function start() +{ + if(hasBeenAlerted) hasBeenAlerted = false; + if(hasStarted) return console.log("Once is enough.") + hasStarted = true; + var isUp = await checkStatus(); + if(!isUp) return hasStarted = false; + console.log(isUp, hasStarted) + interval = setInterval(() => + { + fetch('https://127.0.0.1:2999/GetLiveclientdataAllgamedata', + { + method:"GET", + mode:"cors", + headers: + { + "Access-Control-Allow-Methods": "*" + } + }).then(handleRes) + .then(handleData) + .catch(handleError) + async function handleRes(res) + { + return await res.json() + } + function handleError(error) + { + return {Error:'There was an error:'+error} + } + }, 100); +} + +async function checkStatus() +{ + var x = await fetch('https://127.0.0.1:2999/help', + { + method:"GET", + mode:"cors", + option: + { + timeout:100 + }, + headers: + { + "Access-Control-Allow-Methods": "*" + } + }).then(handleRes) + .catch(handleError) + async function handleRes(res) + { + return {Error:false}; + } + function handleError(error) + { + return {Error:'There was an error:'+error} + } + return x.Error?false:true; +} +async function handleData(data) +{ + if(data.allPlayers.length!=2) return reset('Unqualified match, not enough players.'); + var playerA = data.allPlayers[0].summonerName; + var playerB = data.allPlayers[1].summonerName; + //if(data.allPlayers[0].scores.creepScore>=100 || data.allPlayers[1].scores.creepScore>=100) return handleResults(data.allPlayers[0].scores.creepScore==100?playerA:playerB, data) + if(data.events.Events.length==2) return; + data.events.Events.forEach(Event => + { + if(Event.EventName =="FirstBlood" || Event.EventName =="FirstBrick") return handleResults(Event, data); + }); + if(data.allPlayers[0].scores.creepScore>=100 && data.allPlayers[1].scores.creepScore>=100) return handleTie(data) +} +function RegisterGame(result,data) +{ + stopSpinner(); + const PA = data.allPlayers[0]; //Player A + const PB = data.allPlayers[1]; //Player B + if(!result.tie) + { + result = { + winCondition:result.EventName, + winner:result.EventName=='FirstBrick'?result.KillerName:result.Recipient + } + } + else + { + result= { + winCondition:'Tie', + winner:'Tie' + } + } + + fetch(`${window.location.origin}/api/RegisterGame`, + { + method: "POST", + mode: "cors", + headers:{ + 'Content-Type': 'application/json', + 'Accept': 'application/json', + 'id':id, + 'leagueid':leagueid + }, + body:JSON.stringify({ + result, + gameData: + { + PlayerA: + { + championName:PA.championName, + summonerName: PA.summonerName, + isBot: PA.isBot, + team: PA.team, + items:PA.items, + level:PA.level, + runes:PA.runes, + skin:PA.skinID, + skinName:PA.skinName, + summs:PA.summonerSpells, + Kills:PA.scores.kills, + Deaths:PA.scores.deaths, + CS:PA.scores.creepScore + }, + PlayerB: + { + championName:PB.championName, + summonerName: PB.summonerName, + isBot: PB.isBot, + team: PB.team, + items:PB.items, + level:PB.level, + runes:PB.runes, + skin:PB.skinID, + skinName:PB.skinName, + summs:PB.summonerSpells, + Kills:PB.scores.kills, + Deaths:PB.scores.deaths, + CS:PB.scores.creepScore + }, + gameTime:data.gameData.gameTime + }, + fullData:data, + }) + }) + .then(result => result.json()) + .then(res => + { + if(res.success) + { + location.href = '/leagues' + } + else alert(res.Error); + }) + .catch(console.error); +} + +function reset(reason) +{ + if(!hasBeenAlerted) alert(reason); + hasBeenAlerted=true; + clearInterval(interval); + hasStarted=false; +} + +function handleResults(result, data) +{ + //If it gets here there is already a clear winner. + clearInterval(interval) + var costumEvent = { + "EventID": 5000, + "EventName": "100th creep", + "EventTime": data.gameData.gameTime, + "Recipient": '', + } + if(result == 'string') + { + let cache = result; + result= costumEvent; + result.Recipient = cache + } + RegisterGame(result, data) +} + +function handleTie(data) +{ + var result = { + tie:true, + } + RegisterGame(result,data) +} \ No newline at end of file diff --git a/public/js/leagues.js b/public/js/leagues.js new file mode 100644 index 0000000..99c68f6 --- /dev/null +++ b/public/js/leagues.js @@ -0,0 +1,52 @@ +function goTo() +{ + window.open("https://discord.com/api/oauth2/authorize?client_id=356104008366030863&redirect_uri=https%3A%2F%2Frem.wordfights.com%2FcreateLeague&response_type=token&scope=identify") +} +function goToLeague(recordID) +{ + location.replace(location.origin+'/league/'+recordID) +} +window.onload = ()=> +{ + presentLeagues(); +} +async function presentLeagues() +{ + var leagues = await fetch(`${window.location.origin}/api/getAllLeagues`, + { + method: "GET", + }) + .then(res=>{return res.json()}) + .then(response=> + { + return response.data; + }) + .catch(console.error) + var table = document.getElementById('LeaguesTable'); + var rows = ''; + for(var league of leagues) + { + (async (league)=> + { + var aux = ` + + ${league.Name} + ${league.Players.length} + + ` + rows+=aux; + })(league) + } + var auxHTML = + ` + + + + + ${rows} +
LeaguePlayers +
+ ` + table.innerHTML = auxHTML; + +} diff --git a/routes/routes.js b/routes/routes.js index 6ab53b0..c7f088a 100644 --- a/routes/routes.js +++ b/routes/routes.js @@ -21,5 +21,13 @@ module.exports = (io, bot)=> router.route('/dashboard').get(dash.get(io)) .post(dash.post(io)); router.route('/getMessage').get(api.getMessage(bot)) + router.route('/leagues').get(api.getTournamentPage) + router.route('/league/:league').get(api.getLeaguePage) + router.route('/leagueListener').get(api.getTournamentListenerPage) + router.route('/api/RegisterGame').post(api.registerGame); + router.route('/api/getAllLeagues').get(api.getAllLeagues); + router.route('/api/getLeague').get(api.getLeague); + router.route('/createLeague').get(api.createLeaguePage) + router.route('/api/createLeague').post(api.createLeague) return router; }; \ No newline at end of file diff --git a/test.js b/test.js index e69de29..beca58c 100644 --- a/test.js +++ b/test.js @@ -0,0 +1,164 @@ +// works on script of a page + +// async function getGameData() +// { +// return await fetch('https://127.0.0.1:2999/GetLiveclientdataAllgamedata', +// { +// method:"GET", +// mode:"cors", +// headers: +// { +// "Access-Control-Allow-Methods": "*" +// } +// }).then(handleRes).catch(handleFailure) +// async function handleRes(res) +// { +// console.log(res) +// return await res.json(); + +// } +// function handleFailure() +// { +// return 'Failed to fetch' +// } +// } + + +// setInterval(async () => { +// console.log(await getGameData()) +// }, 1000); + + +// var skinURL = `http://ddragon.leagueoflegends.com/cdn/img/champion/splash/${championName}_${skinID}.jpg`; +var coiso = [ +{ + "championName": "Caitlyn", + "scores": { + "creepScore": 100, + "deaths": 0, + "kills": 8, + }, + "skinID": 20, + "summonerName": "hc12", + "summonerSpells": { + "summonerSpellOne": { + "displayName": "Barrier", + }, + "summonerSpellTwo": { + "displayName": "Flash", + } + }, + "team": "ORDER" +}, +{ + "championName": "Lux", + "scores": { + "assists": 0, + "creepScore": 10, + "deaths": 8, + "kills": 0, + }, + "skinID": 0, + "summonerName": "Lux Bot", + "summonerSpells": { + "summonerSpellOne": { + "displayName": "Heal", + }, + "summonerSpellTwo": { + "displayName": "Exhaust", + } + }, + "team": "CHAOS" +} +] +var events = +[ + [ + { + "EventID": 0, + "EventName": "GameStart", + "EventTime": 0.04342550039291382 + }, + { + "EventID": 1, + "EventName": "MinionsSpawning", + "EventTime": 65.07691955566406 + }, + { + "EventID": 3, + "EventName": "FirstBlood", + "EventTime": 209.65553283691406, + "Recipient": "hc12" + }, + { + "EventID": 16, + "EventName": "FirstBrick", + "EventTime": 605.8714599609375, + "KillerName": "hc12" + } + ] +] + +var id = 'coiso' +var a = +{ + coiso: + [ + { + gId:'coiso' + }, + { + gId: 'coisa' + } + ] +} +var replacement = {gId:'coisada'} +const index = a.coiso.findIndex(x=>x.gId=id); +a.coiso[index] = replacement; +console.log(a.coiso) + + +var b = { + _id: new ObjectId("642359f907f5cbd1bfba7646"), + Players: [ + { + Name: 1, + Points: 2, + PlayedPoints: 0, + Kills: 2, + Deaths: 0, + CreepScore: 0, + PointsPlayed: NaN + }, + { + Name: 'Ezreal Bot', + Points: 0, + PlayedPoints: 0, + Kills: 0, + Deaths: 0, + CreepScore: 0 + } + ], + Games: [ + { + _id: new ObjectId("642359f907f5cbd1bfba7642"), + Winner: 'hc12', + WinCondition: 'FirstBlood', + Played: true, + PlayedTimeStamp: '1680125543862', + __v: 0 + }, + { + PA: [Object], + PB: [Object], + Winner: '', + WinCondition: '', + Played: false, + PlayedTimeStamp: '', + gId: '642359f907f5cbd1bfba7642' + } + ], + Name: 'test', + Owner: '186540961650835456', + __v: 0 + } \ No newline at end of file diff --git a/views/createLeague.ejs b/views/createLeague.ejs new file mode 100644 index 0000000..a3d8a18 --- /dev/null +++ b/views/createLeague.ejs @@ -0,0 +1,31 @@ + + + + + + + + League + + + + + +
+
+
+ + +
+
+
+ +
+ +
+ + + + \ No newline at end of file diff --git a/views/league.ejs b/views/league.ejs new file mode 100644 index 0000000..c54507d --- /dev/null +++ b/views/league.ejs @@ -0,0 +1,38 @@ + + + + + + + League + + + + + +
+ + + +
+
+
+
+ + Results + +
+
+ + Schedule + +
+
+ +
+
+
+ + + diff --git a/views/leaguelistener.ejs b/views/leaguelistener.ejs new file mode 100644 index 0000000..e742a19 --- /dev/null +++ b/views/leaguelistener.ejs @@ -0,0 +1,35 @@ + + + + + + Listener + + + + + + +

Attenttion!

+

Don't change tabs: this page needs to stay open and in focus for the duration of the game.

+

Once a winner is declared an alert will be triggered and the page can be close.

+
+
+
+
+
+
+
+
+ +
+
+ Ready +
+
+
+
+ +
+ + \ No newline at end of file diff --git a/views/leagues.ejs b/views/leagues.ejs new file mode 100644 index 0000000..a3c362d --- /dev/null +++ b/views/leagues.ejs @@ -0,0 +1,29 @@ + + + + + + + + Leagues + + + + + +
+ Create +
+
+ + + + + +
LeaguePlayers +
+
+ + + + \ No newline at end of file