Compare commits

...

6 Commits

Author SHA1 Message Date
nannal
457182504f Beta 2020-05-02 21:09:22 +03:00
nannal
2129889248 Client working, server done bug smashing time 2020-04-17 00:49:55 +03:00
nannal
d50ccb48f8 SimpleClient added, maybe other stuff 2020-03-12 20:24:53 +02:00
nannal
fc354feb20 Started adding client functions 2020-03-08 17:19:37 +02:00
nannal
9ef945e575 Client changes 2020-03-08 15:10:10 +02:00
nannal
8708bac1a2 game bar accuse, untested, buggy, vulnerable 2020-02-17 00:59:33 +02:00
16 changed files with 1722 additions and 65 deletions

39
charitygen.js Normal file
View File

@@ -0,0 +1,39 @@
var randomstring = require("randomstring");
function charityGen() {
ffnames = ["Quinn","Wendy","Erica","Rebecca","Tabitha","Yennifer","Ulanda","Irene","Omara","Penelope","Agne","Sarah","Diane","Febroch","Gillian","Hannah","Jessica","Karen","Laura","Zoe","Xephodette","Caitlyn","Violet","Betty","Noreen","Martha"]
mfnames = ["Quintin","William","Eric","Robert","Thomas","Yakov","Umber","Ian","Odin","Peter","Adam","Sam","Daniel","Fredrich","Geoff","Hubert","Jack","Kevin","Liam","Zack","Xaphod","Carl","Victor","Benjamin","Nathan","Mark"]
lnames = ["Qwerner","Windburg","Eoinson","Rasputin","Thunburgler","Yankovic","Udenminster","Irason","Onglangling","Petrovic","Ainsly","Sumpworth","Donnington","Fontain","Goodly","Henderson","Jillersworth","Kurteen","Luth","Zundar","Xembi","Coats","Veloure","Bunglesworth","Nempham","Macklesmith"]
establishments = ["Trust","Foundation","Service","Association","Fund","Philanthropic Enterprise","Centre","Endowment","Charity","Network","Service"]
acronym = randomstring.generate({length:3,charset: 'alphabetic'}).toUpperCase()
rand = Math.floor((Math.random() * 7) + 1)
charityString=""
switch(rand) {
case 1 :
charityString = "The "+ffnames[Math.floor(Math.random() * ffnames.length)]+" "+establishments[Math.floor(Math.random() * establishments.length)]
break
case 2:
charityString = "The "+ffnames[Math.floor(Math.random() * ffnames.length)]+" "+ lnames[Math.floor(Math.random() * lnames.length)] +" "+establishments[Math.floor(Math.random() * establishments.length)]
break
case 3:
charityString = "The "+mfnames[Math.floor(Math.random() * mfnames.length)]+" "+establishments[Math.floor(Math.random() * establishments.length)]
break
case 4:
charityString = "The "+mfnames[Math.floor(Math.random() * mfnames.length)]+" "+ lnames[Math.floor(Math.random() * lnames.length)] +" "+establishments[Math.floor(Math.random() * establishments.length)]
break
case 5:
charityString = "The "+lnames[Math.floor(Math.random() * lnames.length)] +" "+establishments[Math.floor(Math.random() * establishments.length)]
break
default:
charityString = acronym+" "+establishments[Math.floor(Math.random() * establishments.length)]
}
return charityString
}
module.exports = charityGen

18
client/Old/index.html Normal file
View File

@@ -0,0 +1,18 @@
<head>
<script src="https://code.jquery.com/jquery-3.4.1.min.js"
integrity="sha256-CSXorXvZcTkaix6Yvo6HppcZGetbYMGWSFlBw8HfCJo=" crossorigin="anonymous">
</script>
<script src="./index.js"></script>
</head>
<body>
<title>Embezzle</title>
<input type="text" id="location" /> <input type="button" value="send" onclick="send()" /><input type="button" value="get" onclick="get()" />
</br>
<input type="text" id="name" value="Name" />
<input type="text" id="ownerID" value="ownerID" />
<input type="text" id="gameID" value="gameID" />
<input type="text" id="seats" value="seats" />
</body>

202
client/index.css Normal file
View File

@@ -0,0 +1,202 @@
* {
box-sizing: border-box;
}
body {
margin: 0;
}
.clearfix{
clear:both;
}
.header-banner{
padding-top:35px;
padding-bottom:100px;
color:#ffffff;
font-family:Helvetica, serif;
font-weight:100;
background-image:url("//grapesjs.com/img/bg-gr-v.png"), url(none);
background-attachment:scroll, scroll;
background-position:left top, center center;
background-repeat:repeat-y, no-repeat;
background-size:contain, cover;
opacity:1;
}
.container-width{
width:90%;
max-width:1150px;
margin:0 auto;
float:none;
}
.logo-container{
float:left;
width:50%;
}
.menu{
float:right;
width:50%;
}
.lead-title{
margin:150px 0 30px 0;
font-size:40px;
}
.footer-under{
background-color:#312833;
padding-bottom:100px;
padding-top:100px;
min-height:500px;
color:#eee;
position:relative;
font-weight:100;
font-family:Helvetica,serif;
}
.footer-container{
display:flex;
flex-wrap:wrap;
align-items:stretch;
justify-content:space-around;
}
.foot-list{
float:left;
width:200px;
}
.foot-list-title{
font-weight:400;
margin-bottom:10px;
padding:0.5em 0;
}
.foot-list-item{
color:rgba(238, 238, 238, 0.8);
font-size:0.8em;
padding:0.5em 0;
}
.foot-list-item:hover{
color:rgba(238, 238, 238, 1);
}
.foot-form-cont{
width:300px;
float:right;
}
.foot-form-title{
color:rgba(255,255,255,0.75);
font-weight:400;
margin-bottom:10px;
padding:0.5em 0;
text-align:right;
font-size:2em;
}
.form{
border-radius:3px;
padding:10px 15px;
background-color:rgba(0,0,0,0.2);
}
.input{
width:100%;
margin-bottom:15px;
padding:7px 10px;
border-radius:2px;
color:#fff;
background-color:#554c57;
border:none;
align-items:flex-start;
justify-content:flex-start;
flex-direction:row;
align-self:auto;
margin:15px 0 15px 0;
height:32px;
}
.sub-input{
width:100%;
margin-bottom:15px;
padding:7px 10px;
border-radius:2px;
color:#fff;
background-color:#554c57;
border:none;
}
.label{
width:100%;
display:block;
}
.button{
width:100%;
margin:15px 0;
background-color:#785580;
border:none;
color:#fff;
border-radius:2px;
padding:7px 10px;
font-size:1em;
cursor:pointer;
align-items:flex-start;
align-self:flex-start;
}
.sub-btn{
width:100%;
margin:15px 0;
background-color:#785580;
border:none;
color:#fff;
border-radius:2px;
padding:7px 10px;
font-size:1em;
cursor:pointer;
}
.sub-btn:hover{
background-color:#91699a;
}
.sub-btn:active{
background-color:#573f5c;
}
.row{
display:flex;
justify-content:flex-start;
align-items:stretch;
flex-wrap:nowrap;
padding:10px;
}
.cell{
min-height:75px;
flex-grow:1;
flex-basis:100%;
}
#ianajd{
padding:10px;
}
#ipah9l{
align-items:stretch;
}
#in2itk{
flex-basis:286%;
}
#ilxqxl{
padding:10px;
}
#imc13f{
padding:10px;
}
#ibppca{
padding:10px;
}
#ictkx3{
padding:10px;
float:none;
font-weight:900;
text-align:center;
font-size:72px;
}
@media (max-width: 768px){
.foot-form-cont{
width:400px;
}
.foot-form-title{
width:autopx;
}
.row{
flex-wrap:wrap;
}
}
@media (max-width: 480px){
.foot-lists{
display:none;
}
}

View File

@@ -1,15 +1,177 @@
<head> <header class="header-banner">
<script src="https://code.jquery.com/jquery-3.4.1.min.js" <!-- <img src="https://b.thumbs.redditmedia.com/DVZcy19t2uXvJWg9YIQm8dwBjSbx0HMg1cubAThOpBc.png"></img> -->
integrity="sha256-CSXorXvZcTkaix6Yvo6HppcZGetbYMGWSFlBw8HfCJo=" crossorigin="anonymous"> <link rel="stylesheet" type="text/css" href="index.css">
</script> <script src="index.js"></script>
<script src="./index.js"></script> <div class="container-width">
</head> <div class="logo-container">
<body> </div>
<title>Debug</title> <nav class="menu">
<input type="text" id="location" /> <input type="button" value="send" onclick="send()" /><input type="button" value="get" onclick="get()" /> </nav>
</br> <div class="clearfix">
<input type="text" id="name" value="Name" /> </div>
<input type="text" id="ownerID" value="ownerID" /> <div class="lead-title">Embezzle
<input type="text" id="gameID" value="gameID" /> </div>
<input type="text" id="seats" value="seats" /> </div>
</body> </header>
<footer class="footer-under">
<form class="form register">
<div class="form-group">
<label class="label">Name</label>
<input placeholder="Type here your name" class="input" id="registerName"/>
</div>
<div class="form-group">
</div>
<div class="form-group">
</div>
<div class="form-group">
<button type="button" class="button" onclick="register()">Register</button>
</div>
</form>
<form class="form">
<div class="form-group">
</div>
<div class="form-group">
</div>
<div class="form-group">
<label class="label">Number of Seats on the Board<br/></label>
</div>
<div class="form-group">
</div>
<input type="number" class="input" id="seatsSelector"/>
<div class="form-group">
<button type="button" class="button" onclick="make()">Send</button>
</div>
</form>
<form class="form game-list">
<div class="form-group">
<label class="label">Game List<br/></label>
</div>
<div class="form-group">
</div>
<div class="form-group">
</div>
<div class="form-group jsme">
<button type="button" class="button" onclick="join()">Name</button>
</div>
</form>
<form class="form game-list">
<div class="form-group">
<label class="label">Lobby<br draggable="true" id="il3dmw-2-2"/></label>
</div>
<div class="form-group">
</div>
<div class="form-group">
</div>
<div class="form-group">
</div>
<div id="ilxqxl">Players:
<br/>
</div>
<div class="row" id="it1ua4">
<div class="cell" id="in2itk">
</div>
<div class="cell" id="ibmekl">
<button type="button" class="button" onclick="start()">Start</button>
</div>
</div>
</form>
<div class="row">
<div class="cell" id="ijy5cf">
</div>
</div>
<div class="row">
<div class="cell" id="izmpsu">
<div id="imc13f">Players:
<br/>
</div>
</div>
<div class="cell" id="ig7981">
<form class="form">
<div class="form-group">
</div>
<div class="form-group">
<label class="label">Donate<br/></label>
</div>
<div class="form-group">
</div>
<div class="form-group">
<div class="row jsme" id="iu7my2">
<div class="cell" id="ipah9l">
<input type="number" class="input"/>
</div>
<div class="cell">
<button class="button" >Send</button>
</div>
</div>
</div>
</form>
</div>
<div class="cell" id="i5yvnh">
<div id="ianajd">
<div>Donation Log
</div>
</div>
</div>
</div>
<div class="row" id="i3kiue">
<div class="cell" id="i5y7xs">
<button class="button">Send</button>
</div>
<div class="cell" id="ihhmej">
<div id="ibppca">
<div draggable="true" id="iuvwil-2">Accusations
</div>
</div>
</div>
</div>
<div class="row">
<div class="cell" id="is596z">
<div id="ictkx3">Winner
<br/>
</div>
</div>
</div>
<div class="container-width">
<div class="footer-container">
<div class="foot-lists">
<div class="foot-list">
<div class="foot-list-title">About us
</div>
<div class="foot-list-item">Code
<br/>
</div>
<div class="foot-list-item">
<div>Blog
</div>
</div>
<div class="foot-list-item">Donate
</div>
</div>
<div class="foot-list">
<div class="foot-list-title">Services
</div>
<div class="foot-list-item">Community
</div>
<div class="foot-list-item">
<div>Self-Host
</div>
</div>
</div>
<div class="clearfix">
</div>
</div>
<div class="form-sub">
<div class="foot-form-cont">
<div class="foot-form-title">
<div>Give me your details
</div>
</div>
<input name="name" placeholder="Name" class="sub-input"/>
<input name="email" placeholder="Email" class="sub-input"/>
<input name="Secret" placeholder="Deepest Darkest Secret" class="sub-input"/>
<button type="button" class="sub-btn">Submit</button>
</div>
</div>
</div>
</div>
</footer>

View File

@@ -0,0 +1,7 @@
FROM nginx
ADD ./ /usr/share/nginx/html
LABEL traefik.port="80"
EXPOSE 80
CMD ["nginx", "-g", "'daemon off'"]

109
client/simpleclient/index.css Executable file
View File

@@ -0,0 +1,109 @@
body{
margin:40px auto;
max-width:90%;
line-height:1.6;
font-size:18px;
color:#444;
padding:0 10px;
font-family: monospace;
}
h1,h2,h3{
line-height:1.2
}
.donateInput{
width: 35%;
}
select{
height: auto;
width: 80%;
font-size: large;
}
input{
height: auto;
width: 80%;
font-size: large;
}
button{
height: auto;
width: 18%;
font-size: large;
}
#controls{
width: 100%;
}
#Reigster-Container{
visibility: visible;
width: 100%;
}
#Make-Container{
visibility: hidden;
scale: 0;
}
#Join-Container{
visibility: hidden;
scale: 0;
}
#Start-Container{
visibility: hidden;
scale: 0;
}
#Donate-Container{
visibility: hidden;
scale: 0;
}
#Accuse-Container{
visibility: hidden;
scale: 0;
}
#messages{
visibility: hidden;
scale: 0;
}
#games{
visibility: hidden;
scale: 0;
}
#gameInfo{
visibility: hidden;
scale: 0;
}
#myCharity{
visibility: hidden;
scale: 0;
}
#charityStatus{
visibility: hidden;
scale: 0;
}
#boardFunding{
visibility: hidden;
scale: 0;
}
#transactionLog{
visibility: hidden;
scale: 0;
}
#accusationLog{
visibility: hidden;
scale: 0;
}

121
client/simpleclient/index.html Executable file
View File

@@ -0,0 +1,121 @@
<html>
<head>
<link rel="stylesheet" type="text/css" href="index.css">
<meta content="text/html;charset=utf-8" http-equiv="Content-Type">
<meta content="utf-8" http-equiv="encoding"/>
<script src="index.js"></script>
<script type="text/javascript">
//sorry
var _paq = window._paq || [];
/* tracker methods like "setCustomDimension" should be called before "trackPageView" */
_paq.push(["setDocumentTitle", document.domain + "/" + document.title]);
_paq.push(["setCookieDomain", "*.nannal.com"]);
_paq.push(['trackPageView']);
_paq.push(['enableLinkTracking']);
(function() {
var u="//matomo.nannal.com/";
_paq.push(['setTrackerUrl', u+'matomo.php']);
_paq.push(['setSiteId', '1']);
var d=document, g=d.createElement('script'), s=d.getElementsByTagName('script')[0];
g.type='text/javascript'; g.async=true; g.defer=true; g.src=u+'matomo.js'; s.parentNode.insertBefore(g,s);
})();
(function(f, a, t, h, o, m){
a[h]=a[h]||function(){
(a[h].q=a[h].q||[]).push(arguments)
};
o=f.createElement('script'),
m=f.getElementsByTagName('script')[0];
o.async=1; o.src=t; o.id='fathom-script';
m.parentNode.insertBefore(o,m)
})(document, window, '//fathom.nannal.com/tracker.js', 'fathom');
fathom('set', 'siteId', 'QYBFW');
fathom('trackPageview');
</script>
<noscript><p><img src="//matomo.nannal.com/matomo.php?idsite=1&amp;rec=1" style="border:0;" alt="" /></p></noscript>
</head>
<body>
<h1>Embezzle</h1>
<div id="controls">
<div id="Reigster-Container">
<div id="faq">
<h2>How To Play</h2>
By joining a game you become apointed to the board of a multinational company who in the name of extreme altruism (and for some significant tax breaks) must distribute some of their immesne profits to lowly charities. As the cunning fox you are, you've setup your own charity and must now redirect as much of this firehose of funds from silly rinky-dink operations like oxfam to your own back pocket.
</br>
However, you can't be <i>entierly</i> blatant about it as, after each quaters funds are distributed, a board member must be fired as they are undoubtedly performing the heinous crime of cold-heartedly stealing what few morsels of funding the benevolent company has seen fit to bestow on the worlds most needy and vulnerable. <b>The swines!</b>
<ul>Join a board of directors</ul>
<ul>Distribute funds to yourown and other's charities</ul>
<ul>Vote out one of your fellow board members</ul>
<ul>Have the most capital in your charity when only two members remain on the board to win</ul>
</div>
</br>Register a player</br>
<input id="register" type="text" placeholder="Name"/> <button onclick="register()">Register</button>
</div>
<div id="Make-Container">
</br>Make A game (Select a number of player slots)</br>
<input id="makeSeats" type="number"/> <button onclick="make()">Make</button>
</div>
<div id="Join-Container">
</br>Join a game (Using a GameID)</br>
<input id="join" type="text" placeholder="Name"/> <button onclick="join()">Join</button>
</div>
<div id="Start-Container">
</br>Start the game!</br>
<button onclick="start()">Start</button>
</div>
<div id="Donate-Container">
</br>Donate</br>
<select id="donate" name="list" class="donateInput">
<option value="stringthatbrickstheserver">If you can see this, you're being naughty</option>
</select>
<input id="amount" type="number" class="donateInput">
<button onclick="donate()">Donate</button>
</div>
<div id="Accuse-Container">
</br>Accuse a player of embezzlement</br>
<select id="accuse" name="list" class="accuseInput">
<option value="stringthatbrickstheserver">If you can see this, you're being naughty</option>
</select>
<button onclick="accuse()">Accuse</button>
</div>
</div>
<div id="info">
<div id="gameID"></div>
<div id="messages"></div>
<div id="games"></div>
<div id="gameInfo"></div>
<div id="playerInfo"></div>
<div id="myCharity"></div>
<div id="charityStatus"></div>
<div id="boardFunding"></div>
<div id="transactionLog"></div>
<div id="accusationLog"></div>
</div>
</body>
</html>

468
client/simpleclient/index.js Executable file
View File

@@ -0,0 +1,468 @@
// Global Vars
serverAddr="https://embezzle-server.nannal.com"
ownerID=''
// ownerID='6298bc89-41cb-4cc7-84cd-7fd8e419f263'
gameID=''
//Meta Game Utils
function register(){
const data = { name: document.getElementById('register').value };
fetch(serverAddr+'/lobby/register', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(data),
})
.then((response) => response.json())
.then((data) => {
// console.log(data)
ownerID=data.ownerID
document.getElementById('register').value=data.name
//hide register
//show make & join
//show list of games
cssHide("Reigster-Container")
cssShow("Make-Container")
cssShow("Join-Container")
listGames()
})
.catch((error) => {
console.error('Error:', error);
});
}
function listGames(){
fetch(serverAddr+"/lobby/list")
.then((response) => {
return response.json();
})
.then((data) => {
gamesFormat(data)
cssShow("games")
console.log(data);
});
}
function make(){
console.log("make")
const data = {
ownerID: ownerID,
seats: document.getElementById('makeSeats').value };
fetch(serverAddr+'/lobby/make', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(data),
})
.then((response) => response.json())
.then((data) => {
// console.log(data)
gameID=data.gameID
gameData(gameID)
document.getElementById("gameID").innerHTML="<h2>Your gameID is:"+gameID+"</h2><p> share the gameID with any users you want to join your game</p>"
cssHide("games")
cssHide("Make-Container")
cssHide("Join-Container")
cssShow("messages")
cssShow("gameInfo")
cssShow("playerInfo")
cssShow("Start-Container")
})
.catch((error) => {
console.error('Error:', error);
});
}
function join(){
console.log("join")
gameID=document.getElementById('join').value
gameData(gameID)
cssHide("games")
cssHide("Make-Container")
cssHide("Join-Container")
cssShow("messages")
cssShow("gameInfo")
cssShow("playerInfo")
const data = {
ownerID: ownerID,
gameID: gameID };
// console.log(data)
fetch(serverAddr+'/lobby/join', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(data),
})
.then((response) => response.json())
.then((data) => {
document.getElementById("gameID").innerHTML="<h2>Your gameID is:"+gameID+"</h2><p> share the gameID with any users you want to join your game</p>"
// console.log(data)
})
.catch((error) => {
console.error('Error:', error);
cssShow("games")
cssShow("Make-Container")
cssShow("Join-Container")
cssHide("messages")
cssHide("gameInfo")
});
}
function gameData(gameID) {
fetch(serverAddr+'/lobby/details/'+gameID)
.then((response) => {
if (response.status == 404) {
status()
}
return response.json();
})
.then((data) => {
checkIfStarted = setInterval(function(){
gameData(gameID)
clearInterval(checkIfStarted)
}, 1000)
html="Waiting For "+data.name+" to start the game, "+data.players.length+"/"+data.seats+" seats are full</br>"
data.players.forEach(element => {
html=html+"Player: "+element.name+"</br>"
})
if (document.getElementById("messages").innerHTML != html) {
document.getElementById("messages").innerHTML=html
}
})
}
function start(){
const data = {
ownerID: ownerID,
gameID: gameID };
// console.log(data)
fetch(serverAddr+'/lobby/start', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(data),
})
.then((response) => response.json())
.then((data) => {
console.log(data)
cssHide("Start-Container")
})
.catch((error) => {
console.error('Error:', error);
});
}
// Game controls
function donate(){
console.log("donate")
// /game/:gameID/distribution
amount=document.getElementById('amount').value
doante=document.getElementById('donate').value
const data = {
ownerID: ownerID,
gameID: gameID,
charityID: doante,
amount: amount };
// console.log(data)
fetch(serverAddr+'/game/'+gameID+'/distribution', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(data),
})
.then((response) => response.json())
.then((data) => {
donateFormat(data)
// console.log(data)
// gameData(gameID)
})
.catch((error) => {
console.error('Error:', error);
});
}
function accuse(){
console.log("accuse")
name = document.getElementById('accuse').value
const data = {
ownerID: ownerID,
gameID: gameID,
player: name };
// console.log(data)
fetch(serverAddr+'/game/'+gameID+'/accuse', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(data),
})
.then((response) => response.json())
.then((data) => {
// console.log(data)
accuseFormat(data)
// gameData(gameID)
})
.catch((error) => {
console.error('Error:', error);
});
}
// Game Utils
function status() {
//the game has started, get the data
// One off updates
const data = {
ownerID: ownerID,
gameID: gameID };
fetch(serverAddr+'/game/'+gameID+'/charity', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(data),
})
.then((response) => response.json())
.then((data) => {
// console.log(data)
myCharityFormat(data)
})
.catch((error) => {
console.error('Error:', error);
});
//Quick Recurring updates
statusint = setInterval(function(){
fetch(serverAddr+'/game/'+gameID+'/boardFunding', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(data),
})
.then((response) => response.json())
.then((data) => {
boardFundingFormat(data)
// statusObj.funding=data
})
.catch((error) => {
// console.error('Error:', error);
});
fetch(serverAddr+'/game/'+gameID+'/charityList')
.then((response) => {
return response.json();
})
.then((data) => {
// console.log(data);
dropDownList=""
data.charatiesArr.forEach(element => {
dropDownList=dropDownList+'<option value="'+element.charityID+'">'+element.name+'</option>'
});
if (document.getElementById("donate").innerHTML != dropDownList){
document.getElementById("donate").innerHTML=dropDownList
// statusObj.charitylist=data
}
charityStatusFormat(data)
});
fetch(serverAddr+'/game/'+gameID+'/playerList')
.then((response) => {
return response.json();
})
.then((data) => {
playerListFormat(data)
// statusObj.playerlist=data
// console.log(data);
});
fetch(serverAddr+'/game/'+gameID+'/accuseinfo')
.then((response) => {
return response.json();
})
.then((data) => {
accuseFormat(data)
// statusObj.playerlist=data
// console.log(data);
});
fetch(serverAddr+'/game/'+gameID+'/distributioninfo')
.then((response) => {
return response.json();
})
.then((data) => {
donateFormat(data)
// statusObj.playerlist=data
// console.log(data);
});
fetch(serverAddr+'/game/'+gameID+'/statusinfo')
.then((response) => {
return response.json();
})
.then((data) => {
statusFormat(data)
// statusObj.playerlist=data
// console.log(data);
});
// fdocument.getElementById("info").innerText=prettyprint(statusObj)
}, 3000)
}
//Formating Functions
function myCharityFormat(data) {
document.getElementById("myCharity").innerText="Your Charity: "+data.charity
}
function charityStatusFormat(data) {
html=""
data.charatiesArr.forEach(element => {
html=html+"<b>"+element.name+":</b> "+element.capital+"</br>"
})
if (document.getElementById("charityStatus").innerHTML != html) {
document.getElementById("charityStatus").innerHTML=html
}
}
function boardFundingFormat(data) {
if (document.getElementById("boardFunding").innerHTML != "<b>My Funds: </b>"+data.funds) {
document.getElementById("boardFunding").innerHTML= "<b>My Funds: </b>"+data.funds
}
}
function donateFormat(data) {
html=""
data.log.forEach(element => {
html=html+element.donator+", donated "+element.amount+" to "+element.charity+"</br>"
})
if(document.getElementById("transactionLog").innerHTML != html){
document.getElementById("transactionLog").innerHTML=html
}
}
function accuseFormat(data) {
html=""
if(typeof data.winner != "undefined"){
document.getElementById("accusationLog").innerHTML="<h1>"+data.winner+" has won the game</h1>"
clearInterval(statusint)
}
else{
accusers=Object.keys(data.log)
accusers.forEach(element => {
html=html+element+" accuses "+data.log[element]+"</br>"
})
if(document.getElementById("accusationLog").innerHTML != html){
document.getElementById("accusationLog").innerHTML=html
}
}
}
function gamesFormat(data) {
html="<h4>Games:</h4></br>"
data.gamesArr.forEach(element => {
html=html+element.gameID+", "+element.name+"</br>"
})
if (document.getElementById("games").innerHTML != html) {
document.getElementById("games").innerHTML = html
}
}
function playerListFormat(data) {
html=""
accuseListFormat(data.playersArr)
data.playersArr.forEach(element => {
html=html+"<b>"+element.name+"</b>: Funds "+element.funds+", Status: "+element.status+"</br>"
})
if (document.getElementById("playerInfo").innerHTML != html){
document.getElementById("playerInfo").innerHTML=html
}
}
function statusFormat(data) {
if (document.getElementById("gameInfo").innerHTML != "<h1>Round Status: "+data.status+"</h1>") {
document.getElementById("gameInfo").innerHTML="<h1>Round Status: "+data.status+"</h1>"
}
if (data.status == "Distribution") {
cssHide("messages")
cssShow("gameInfo")
cssShow("myCharity")
cssShow("charityStatus")
cssShow("boardFunding")
cssShow("Donate-Container")
cssShow("transactionLog")
cssHide("messages")
cssHide("accusationLog")
cssHide("Accuse-Container")
}
else {
cssHide("Donate-Container")
cssShow("accusationLog")
cssShow("Accuse-Container")
}
}
function accuseListFormat(data){
dropDownList=""
data.forEach(element => {
dropDownList=dropDownList+'<option value="'+element.name+'">'+element.name+'</option>'
});
if (document.getElementById("accuse").innerHTML != dropDownList){
document.getElementById("accuse").innerHTML=dropDownList
// statusObj.charitylist=data
}
}
function cssHide(id){
if (document.getElementById(id).style.visibility != "Hidden") {
document.getElementById(id).style.lineHeight=0
document.getElementById(id).style.margin=0
document.getElementById(id).style.fontSize=0
document.getElementById(id).style.visibility="Hidden"
document.getElementById(id).style.size="0px"
document.getElementById(id).style.zIndex="100"
document.getElementById(id).style.scale="0"
}
}
function cssShow(id){
if (document.getElementById(id).style.visibility != "Visible") {
document.getElementById(id).style.lineHeight=1.6
document.getElementById(id).style.fontSize="Large"
document.getElementById(id).style.visibility="Visible"
document.getElementById(id).style.size="Auto"
document.getElementById(id).style.zIndex="0"
document.getElementById(id).style.scale="1"
}
}

10
dockerfile Normal file
View File

@@ -0,0 +1,10 @@
FROM node
ADD ./ /emb
WORKDIR /emb
LABEL traefik.port="3000"
EXPOSE 3000
CMD ["node", "index.js"]

372
game.js Normal file
View File

@@ -0,0 +1,372 @@
var mongo = require("./mongoHelp.js")
const charityGen = require("./charitygen.js")
const uuidv4 = require('uuid/v4')
function shuffle(arr) {
var i,
j,
temp
for (i = arr.length - 1; i > 0; i--) {
j = Math.floor(Math.random() * (i + 1))
temp = arr[i]
arr[i] = arr[j]
arr[j] = temp
}
return arr
}
async function check (gameID,ownerID) {
gameObj = await mongo.get("embezzle", "gamelist", {
"gameID": gameID
})
gameObj = gameObj[0]
name = await mongo.get("embezzle", "players", {
"_id": ownerID
})
name = name[0].name
found=0
gameObj.players.forEach(element => {
if (element.name == name) {
console.log(name)
console.log(element.name)
found=1
}
})
console.log("Found: ",found)
return found
}
const game = {
init: async (gameID) => {
gameObj = await mongo.get("embezzle", "gamelist", {
"gameID": gameID
})
gameObj = gameObj[0]
//gen charities
gameObj.charities = []
gameObj.distributionLog = []
gameObj.accuseLog = {}
gameObj.status = "Distribution"
gameObj.round=1
for (let index = 0; index < gameObj.players.length; index++) {
gameObj.charities.push({
charityID: uuidv4(),
name: charityGen(),
capital: 0
})
}
//assign charities to users
gameObj.secretLink = []
gameObj.players.forEach((element, index) => {
charity = gameObj.charities[index]
let link = {
charity: charity.charityID,
owner: element.name
}
gameObj.secretLink.push(link)
})
// Randomise the order of the arrays
shuffle(gameObj.charities)
//set board funds
gameObj.players.forEach(element => {
element.funds = 100000
element.status = "Employed"
})
//update game
mongo.update("embezzle", "gamelist", {
"gameID": gameID
}, gameObj)
},
reset: async (gameID) => {
let gameObj = await mongo.get("embezzle", "gamelist", {
"gameID": gameID
})
gameObj=gameObj[0]
gameObj.players.forEach(element =>{
fundvar=100000
roundvar=fundvar+(fundvar/(gameObj.round))
if (element.status != "Fired"){
element.funds=roundvar
} else {element.funds=roundvar/gameObj.players.length}
})
gameObj.accuseLog={}
mongo.update("embezzle", "gamelist", {
"gameID": gameID
}, gameObj)
},
myCharity: async (gameID, ownerID) => {
name = await mongo.get("embezzle", "players", {
"_id": ownerID
})
name = name[0].name
let gameObj = await mongo.get("embezzle", "gamelist", {
"gameID": gameID
})
secret = gameObj[0].secretLink
mychar=""
secret.forEach(char => {
if (char.owner == name) {
mychar=char.charity
}
})
charname=""
gameObj[0].charities.forEach(element => {
if (element.charityID == mychar) {
charname=element.name
}
})
chairtyObj = {
charity: charname
}
return chairtyObj
},
charityList: async (gameID) => {
charArr = await mongo.get("embezzle", "gamelist", {
"gameID": gameID
})
charArr = charArr[0].charities
return ({
charatiesArr: charArr
})
},
playerList: async (gameID) => {
gameObj = await mongo.get("embezzle", "gamelist", {
"gameID": gameID
})
players = gameObj[0].players
return ({
playersArr: players
})
},
boardFunding: async (ownerID,gameID) => {
r=""
name = await mongo.get("embezzle", "players", {
"_id": ownerID
})
name = name[0].name
players = await mongo.get("embezzle", "gamelist", {
"gameID": gameID
})
players = players[0].players
players.forEach(element => {
if (element.name == name) {
r = {funds: element.funds}
}
})
return r
},
distribution: async (gameID, ownerID, charityID, amount) => {
if (await check(gameID, ownerID) == 0) {
return ({Error: "You're not a player"})
}
//turn the amount to an int
amount=parseInt(amount)
//get the game info
gameObj = await mongo.get("embezzle", "gamelist", {
"gameID": gameID
})
gameObj = gameObj[0]
// console.log(gameObj)
if (gameObj.status != "Distribution") {
return({error:"You have tried to distribute funds when it is not the distribution round"})
} else {
player = await mongo.get("embezzle", "players", {
"_id": ownerID
})
player = player[0]
// console.log(gameObj)
gameObj.players.forEach((element, index) => {
if (player.name == element.name){
player=gameObj.players[index]
console.log(player)
}
})
//check if user is trying to allocate too much money & set the amount so the users funds are wiped out
if (amount > player.funds) {
amount=player.funds
}
gameObj.charities.forEach( element => {
if (element.charityID == charityID) {
element.capital = element.capital+amount
player.funds = player.funds - amount
if (amount > 0 ){
gameObj.distributionLog.push({
donator: player.name,
amount: amount,
charity: element.name
})
}
}
})
reaminingFunding = 0
gameObj.players.forEach(element => {
reaminingFunding=reaminingFunding+element.funds
})
mongo.update("embezzle", "gamelist", {
"gameID": gameID
}, gameObj)
if (reaminingFunding == 0) {
game.roundStatus(gameID)
}
return ({log: gameObj.distributionLog})
}
},
accuse: async (gameID, ownerID, victim) => {
if (await check(gameID, ownerID) == 0) {
return {Error: "You're not a player"}
}
//Get votes on who should be fired
player = await mongo.get("embezzle", "players", {
"_id": ownerID
})
player = player[0]
gameObj = await mongo.get("embezzle", "gamelist", {
"gameID": gameID
})
gameObj = gameObj[0]
if (gameObj.status != "Accuse"){
return {Error: "Game status is not accuse, you'll want to distribute funds before trying to fire someone"}
}
gameObj.players.forEach(element => {
if (victim == element.name) {
gameObj.accuseLog[player.name] = victim
} else {
return gameObj.accuseLog
}
})
if (Object.keys(gameObj.accuseLog).length == gameObj.players.length){
vote={}
Object.keys(gameObj.accuseLog).forEach(accuser => {
vote[accuser]=0
Object.values(gameObj.accuseLog).forEach(accused => {
if (accuser == accused) {
vote[accuser]=vote[accuser]+1
}
})
})
sorted = Object.keys(vote).sort(function(a,b){return vote[a]-vote[b]})
console.log("Sorted: ",sorted)
fired = sorted[sorted.length-1]
console.log("Fired: ",fired)
gameObj.players.forEach(element => {
if (element.name == fired ) {
element.status="Fired"
game.roundStatus(gameID)
}
})
}
// Check if we have two players left and if so, decide on a winner
employedCount = 0
gameObj.players.forEach(element => {
if (element.status == "Employed") {
employedCount++
}
})
if (employedCount < 3) {
return game.winner(gameID)
}
//change status of the user to fired
mongo.update("embezzle", "gamelist", {
"gameID": gameID
}, gameObj)
return ({log: gameObj.accuseLog})
},
winner: async (gameID) => {
winner=""
gameObj = await mongo.get("embezzle", "gamelist", {
"gameID": gameID
})
gameObj = gameObj[0]
// Get the company with the highest value
x=gameObj.charities.sort((a, b) => parseFloat(a.capital) - parseFloat(b.capital));
winCharity=x[gameObj.charities.length-1].charityID
gameObj.secretLink.forEach(element => {
if (element.charity == winCharity) {
winner=element.owner
}
})
// Get the ID
// Tie the ID to the player using secret link
//Declare the winner
gameObj.status="Finished"
gameObj.winner=winner
mongo.update("embezzle", "gamelist", {
"gameID": gameID
}, gameObj)
return {winner: winner}
},
roundStatus: async (gameID) => {
gameObj = await mongo.get("embezzle", "gamelist", {
"gameID": gameID
})
gameObj = gameObj[0]
if (typeof gameObj.status == "Lobby" || gameObj.status == "Accuse") {
gameObj.status = "Distribution"
mongo.update("embezzle", "gamelist", {
"gameID": gameID
}, gameObj)
game.reset(gameID)
} else {
gameObj.status = "Accuse"
}
mongo.update("embezzle", "gamelist", {
"gameID": gameID
}, gameObj)
},
roundStatusInfo: async (gameID) => {
gameObj = await mongo.get("embezzle", "gamelist", {
"gameID": gameID
})
gameObj = gameObj[0]
return ({status: gameObj.status})
},
accuseInfo: async (gameID) => {
gameObj = await mongo.get("embezzle", "gamelist", {
"gameID": gameID
})
gameObj = gameObj[0]
if (typeof gameObj.winner != "undefined") {
return ({winner: gameObj.winner})
} else {
return ({log: gameObj.accuseLog})
}
},
distributionInfo: async (gameID) => {
gameObj = await mongo.get("embezzle", "gamelist", {
"gameID": gameID
})
gameObj = gameObj[0]
return ({log: gameObj.distributionLog})
},
}
module.exports = game

View File

@@ -1,5 +1,5 @@
const lobby = require("./lobby.js") const lobby = require("./lobby.js")
const game = require("./game.js")
const express = require('express') const express = require('express')
const bodyParser = require('body-parser'); const bodyParser = require('body-parser');
const app = express() const app = express()
@@ -7,6 +7,7 @@ app.use(bodyParser.json(),function (req, res, next) {
res.setHeader('Access-Control-Allow-Origin', '*') res.setHeader('Access-Control-Allow-Origin', '*')
res.setHeader('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE') res.setHeader('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE')
res.setHeader('Access-Control-Allow-Headers', 'Content-Type') res.setHeader('Access-Control-Allow-Headers', 'Content-Type')
res.setHeader('Content-Type', 'application/json')
res.setHeader('Access-Control-Allow-Credentials', true) res.setHeader('Access-Control-Allow-Credentials', true)
next() next()
}) })
@@ -19,16 +20,18 @@ app.use(bodyParser.json(),function (req, res, next) {
app.get('/lobby/list' , async function (req, res) { app.get('/lobby/list' , async function (req, res) {
lobby.list().then(r => { lobby.list().then(r => {
console.log(r)
res.send(JSON.stringify({gamesArr: r })) res.send(JSON.stringify({gamesArr: r }))
}) })
}) })
//get game details //get game details
app.get('/lobby/details/:gameID', function (req, res) { app.get('/lobby/details/:gameID', function (req, res) {
let obj=req.body lobby.details(req.params.gameID).then(r => {
lobby.details(obj.gameID).then(r => { if (r.length == 0){
res.send(JSON.stringify(r)) res.status(404)
}
res.send(JSON.stringify(r[0]))
}) })
}) })
@@ -36,7 +39,6 @@ app.get('/lobby/details/:gameID', function (req, res) {
//post register player //post register player
app.post('/lobby/register', function (req, res) { app.post('/lobby/register', function (req, res) {
let obj=req.body let obj=req.body
console.log(req.body)
response=JSON.stringify(lobby.register(obj.name)) response=JSON.stringify(lobby.register(obj.name))
res.send(response) res.send(response)
}) })
@@ -51,8 +53,10 @@ app.post('/lobby/join', function (req, res) {
//get an empty game made //get an empty game made
app.post('/lobby/make', function (req, res) { app.post('/lobby/make', function (req, res) {
let obj=req.body let obj=req.body
response=JSON.stringify(lobby.make(obj.ownerID,obj.seats)) lobby.make(obj.ownerID,obj.seats).then(result => {
res.send(response) res.send(JSON.stringify(result))
})
}) })
//start a game //start a game
@@ -61,21 +65,75 @@ app.post('/lobby/start', function (req, res) {
response=JSON.stringify(lobby.start(obj.ownerID, obj.gameID)) response=JSON.stringify(lobby.start(obj.ownerID, obj.gameID))
res.send(response) res.send(response)
}) })
//gamelevel (??) //myCharity
app.post('/game/:gameID/charity', function (req, res) {
game.myCharity(req.params.gameID, req.body.ownerID).then(r => {
res.send(JSON.stringify(r))
})
})
// charityList
app.get('/game/:gameID/charityList', function (req, res) {
game.charityList(req.params.gameID).then(r => {
res.send(JSON.stringify(r))
})
})
//playerList
app.get('/game/:gameID/playerList', function (req, res) {
game.playerList(req.params.gameID).then(r => {
res.send(JSON.stringify(r))
})
})
// boardFunding
app.post('/game/:gameID/boardFunding', function (req, res) {
game.boardFunding(req.body.ownerID,req.params.gameID).then(r => {
res.send(JSON.stringify(r))
})
})
// distribution
app.post('/game/:gameID/distribution', function (req, res) {
game.distribution(req.params.gameID, req.body.ownerID, req.body.charityID, req.body.amount).then(r => {
res.send(JSON.stringify(r))
})
})
// accuse
app.post('/game/:gameID/accuse', function (req, res) {
game.accuse(req.params.gameID, req.body.ownerID, req.body.player).then(r => {
res.send(JSON.stringify(r))
})
})
// get this game players app.get('/game/:gameID/statusinfo', function (req, res) {
game.roundStatusInfo(req.params.gameID).then(r => {
res.send(JSON.stringify(r))
})
})
// get charity details app.get('/game/:gameID/distributioninfo', function (req, res) {
game.distributionInfo(req.params.gameID).then(r => {
res.send(JSON.stringify(r))
})
})
// get board funding details (how much money team has to work with) app.get('/game/:gameID/accuseinfo', function (req, res) {
game.accuseInfo(req.params.gameID).then(r => {
res.send(JSON.stringify(r))
})
})
// post distribution app.get('/game/:gameID/distributioninfo', function (req, res) {
game.distributIoninfo(req.params.gameID).then(r => {
res.send(JSON.stringify(r))
})
})
// post accusation
// get winner // roundStatus -- this should not be public wtf?
// app.get('/game/:gameID/roundStatus', function (req, res) {
// game.roundStatus(req.params.gameID).then(r => {
// res.send(JSON.stringify(r))
// })
// })
// get round status
console.log("Up") console.log("Up")
app.listen(3000) app.listen(3000)

129
lobby.js
View File

@@ -1,46 +1,117 @@
var mongo = require("./mongoHelp.js") var mongo = require("./mongoHelp.js")
const uuidv4 = require('uuid/v4'); const uuidv4 = require('uuid/v4')
const game = require("./game.js")
var lobby = { var lobby = {
list: async () => { list: async () => {
result = await mongo.get("embezzle", "gamelist", {}) result = await mongo.get("embezzle", "gamelist", {})
return(result) pubArr = []
result.forEach(element => {
if (element.status == "Lobby") {
obj = {
gameID: element.gameID,
name: element.name,
seats: element.seats,
players: element.players,
}
pubArr.push(obj)
}
})
return (pubArr)
}, },
details: async (gameID) => { details: async (search) => {
result = await mongo.get("embezzle","gamelist",{"gameID":gameID}) result = await mongo.get("embezzle", "gamelist", {
return (result) gameID: search
})
pubArr = []
result.forEach(element => {
if (element.status == "Lobby") {
obj = {
gameID: element.gameID,
name: element.name,
seats: element.seats,
players: element.players,
}
pubArr.push(obj)
}
})
return (pubArr)
}, },
register: (name) => { register: (name) => {
id = uuidv4() id = uuidv4()
mongo.put("embezzle","players",{_id:id,name:name}) name=encodeURIComponent(name.substring(0,16))+'-'+id.split('-')[3]
console.log("yoohoo") mongo.put("embezzle", "players", {
return({ownerID:id}) _id: id,
}, name: name
make: (ownerID,seats) => {
gameID=uuidv4()
//todo write charity name generator
name="Charity Name Example"
mongo.put("embezzle","gamelist",{gameID:gameID,ownerID:ownerID,name:name,seats:seats, status:"lobby", players: []})
// this.join(ownerID,gameID)
return({gameID:gameID})
},
join: (ownerID,gameID) => {
mongo.get("embezzle","gamelist",{"gameID":gameID}).then(value => {
console.log(value[0])
value[0].players.push(ownerID)
mongo.update("embezzle","gamelist",{"gameID":gameID},value[0])
}) })
return({gameID:gameID}) return ({
ownerID: id,
name: name
})
},
make: async (ownerID, seats) => {
gameID = uuidv4()
//Name the game after the person that makes it.
name = await mongo.get("embezzle", "players", {
"_id": ownerID
})
name = name[0].name
mongo.put("embezzle", "gamelist", {
gameID: gameID,
ownerID: ownerID,
name: name,
seats: seats,
status: "Lobby",
players: []
})
lobby.join(ownerID, gameID)
return ({
gameID: gameID
})
// return({gameID:gameID})
},
join: async (ownerID, gameID) => {
//TODO: Stop players joining the game more than once.
value = await mongo.get("embezzle", "gamelist", {
"gameID": gameID
})
gameObj = value[0]
player = await mongo.get("embezzle", "players", {
"_id": ownerID
})
player=player[0]
playerObj = {
name: player.name
}
if (gameObj.status != "Lobby" || gameObj.players.length == gameObj.seats) {
return {error:"Unable to join game"}
} else {
gameObj.players.push(playerObj)
mongo.update("embezzle", "gamelist", {
"gameID": gameID
}, gameObj)
return ({
gameID: gameID
})
}
}, },
start: (ownerID, gameID) => { start: (ownerID, gameID) => {
mongo.get("embezzle","gamelist",{"gameID":gameID}).then(value => { mongo.get("embezzle", "gamelist", {
console.log(value[0]) "ownerID": ownerID,
value[0].status="playing" "gameID": gameID
mongo.update("embezzle","gamelist",{"gameID":gameID,"ownerID":ownerID}, value[0]) }).then(value => {
value[0].status = "Playing"
mongo.update("embezzle", "gamelist", {
"gameID": gameID,
"ownerID": ownerID
}, value[0])
game.init(gameID)
}) })
return(gameID) return ({
gameID: gameID
})
}, },
} }

View File

@@ -1,6 +1,6 @@
var MongoClient = require('mongodb').MongoClient var MongoClient = require('mongodb').MongoClient
var url = 'mongodb://localhost:27017' var url = process.env.mongo||'mongodb://embmongo'
var options= { var options= {
useNewUrlParser: true, useNewUrlParser: true,
useUnifiedTopology: true, useUnifiedTopology: true,

18
package-lock.json generated
View File

@@ -58,6 +58,11 @@
"resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz",
"integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=" "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI="
}, },
"array-uniq": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.2.tgz",
"integrity": "sha1-X8w3OSB3VyPP1k1lxkvvU7+eum0="
},
"balanced-match": { "balanced-match": {
"version": "1.0.0", "version": "1.0.0",
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz",
@@ -741,6 +746,11 @@
"resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz", "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz",
"integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==" "integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw=="
}, },
"nodaemon": {
"version": "0.0.5",
"resolved": "https://registry.npmjs.org/nodaemon/-/nodaemon-0.0.5.tgz",
"integrity": "sha512-4rfEhcDMZX/av809P6Yu9mxQf3qQL66fCOrAex+k6HkMnWKDd57IesiT4VCXUK4FTZWQ9MrvSZ76VrKgvSjnDg=="
},
"nodemon": { "nodemon": {
"version": "2.0.2", "version": "2.0.2",
"resolved": "https://registry.npmjs.org/nodemon/-/nodemon-2.0.2.tgz", "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-2.0.2.tgz",
@@ -892,6 +902,14 @@
"resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz", "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz",
"integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==" "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ=="
}, },
"randomstring": {
"version": "1.1.5",
"resolved": "https://registry.npmjs.org/randomstring/-/randomstring-1.1.5.tgz",
"integrity": "sha1-bfBij3XL1ZMpMNn+OrTpVqGFGMM=",
"requires": {
"array-uniq": "1.0.2"
}
},
"range-parser": { "range-parser": {
"version": "1.2.1", "version": "1.2.1",
"resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz",

View File

@@ -16,6 +16,8 @@
"body-parser": "^1.19.0", "body-parser": "^1.19.0",
"express": "^4.17.1", "express": "^4.17.1",
"mongodb": "^3.4.1", "mongodb": "^3.4.1",
"nodaemon": "0.0.5",
"randomstring": "^1.1.5",
"uuid": "^3.4.0" "uuid": "^3.4.0"
}, },
"devDependencies": { "devDependencies": {