Initial commit for deckard and company

This commit is contained in:
bluesaxman 2020-06-09 13:48:19 -06:00
commit 030195bfb2
5 changed files with 360 additions and 0 deletions

79
API/decard.pl Normal file
View File

@ -0,0 +1,79 @@
#!/usr/bin/perl -w
use strict;
use warnings;
use JSON;
# use database engine
sub get_request_info {
my $clientIP = ($ENV{"REMOTE_ADDR"} or "0.0.0.0");
my $proto = ($ENV{"REQUEST_SCHEME"} or "http");
my $get_query = (split(/\?/,($ENV{"QUERY_STRING"} or "")))[0];
my $post_query = "";
if ( $ENV{"CONTENT_LENGTH"} ) { read( <STDIN>, $post_query, $ENV{"CONTENT_LENGTH"}); }
my $referrer = ($ENV{"HTTP_REFERER"} or "");
return ($proto,$clientIP,$get_query,$post_query,$referrer);
}
sub http_status {
my ($status,$content,$target) = @_;
my $header = "";
$header .= "status: ".$status."\r\n";
$header .= "Location: ".$target."\r\n" if $target;
$header .= "Content-Type: ".$content."\r\n" if $content;
$header .= "\r\n";
return $header;
}
sub html_tag {
if ($_[1]) { return "<".($_[0] or "div").($_[2] or "").">".($_[1] or "")."</".($_[0] or "div").">\n";
} else {return "<".($_[0] or "div").($_[2] or "")." />\n";
}
}
sub html_content {
return html_tag("html", html_tag( "head", html_tag( "title", shift ) . shift ) . html_tag( "body", shift ) );
}
sub soft_die {
print http_status(500,"text/html; charset=utf-8");
print html_content("500","",shift);
exit;
}
sub clean_input {
my $input = shift;
if ($input =~ m!%2F!) { soft_die( "Location/hax\r\n\r\n"; }
$input =~ s!%(..)!chr hex $1!ge;
$input =~ s!\+! !g;
return $input;
}
my @request = get_request_info();
my @get_params = split( "!", clean_input($request[2]) );
# my @post_params
my $directive = shift(@get_params);
if ( "new" eq $directive ) {
# new session, new deck, new location
# if deck/location parent sessionID
# if location public/private
# returns id and key of new object
} elsif ( "shuffle" eq $directive ) {
# shuffle - deckID - full/current - deckKey
# sheffles all cards in deckID's locationID if deckKey matches
} elsif ( "move" eq $directive ) {
# move - cardID - current locationID - current locationKey - destination locationID
# changes ownership of cardID to destination locationID if cardID is owned by current locationID and the current locationKey matchs
} elsif ( "getLocations" eq $directive ) {
# getLocations - sessionID - sessionKey
# return all locationIDs associated with sessionID as long as sessionKey matches
} elsif ( "getCards" eq $directive ) {
# getCards - locationID - locationKey
# returns all cardIDs for locationID as long as its public or the locationKey matches
} elsif ( "getDecks" eq $directive ) {
# getDecks - sessionID - sessionKey
# returns all deckIDs associated with sessionID provided sessionKey matchs.
} else {
print http_status(200,"text/json");
print '{"error":"No input or incorrect input", "input":"'.$directive.'!'.join("!",@get_params).'"}';
}

24
Database/base.sql Normal file
View File

@ -0,0 +1,24 @@
create tablespace deckard_space
OWNER deckard
LOCATION '\tmp\deckard';
create database deckard WITH
OWNER=deckard
TABLESPACE=deckard_space;
create table sessions (
sessionID UUID PRIMARY KEY,
sessionKey VARCHAR (256) NOT NULL,
last_update TIMESTAMP NOT NULL
);
create table locations (
locationID UUID PRIMARY KEY,
sessionID UUID REFERENCES sessions(sessionID),
locationType text CHECK (locationType = 'deck' or 'hand' or 'discard'),
showPublic boolean NOT NULL
);
create table cards (
cardID UUID PRIMARY KEY
sessionID UUID REFERENCES sessions(sessionID),
locationID UUID REFERENCES locations(locationID),
cardContent text NOT NULL,
position integer NOT NULL
);

24
README.md Normal file
View File

@ -0,0 +1,24 @@
## Deckard and company
This project is an exansion on my original idea with [Deckard](https://labs.murkfall.net/bluesaxman/deckard), with this project I aim to make decard a fully over the internet multiplayer experience.
### Goals:
* Implement database backend
* Implement API backend
* Session creation
* Deck upload and sanitization
* Multipul Mixed and Separate decks per session
* Multipul Players per session.
* Multipul Discard piles
### Installation
Not yet written
### Basic Play instructions
Not yet written
### Original Deckard project
[For developing new decks](https://labs.murkfall.net/bluesaxman/deckard)

126
UI/css.css Normal file
View File

@ -0,0 +1,126 @@
*|* {
margin:0;
padding:0;
}
body {
display: flex;
flex-direction: column;
justify-content:center;
align-items:center;
}
#disc {
display:block;
width:80%;
min-height:60%;
text-align:center;
}
#menu {
display:flex;
justify-content: space-around;
align-items: center;
width:100%;
}
#display {
display: flex;
justify-content: space-around;
align-items: stretch;
height: 80vh;
width: 100%;
}
#deck, #deckDisp {
display: flex;
justify-content: center;
align-items: center;
}
#deck {
width: 50%;
max-width: 50%;
}
#hand {
display: flex;
width: 50%;
max-width: 50%;
overflow: auto;
justify-content: left;
align-items: center;
}
.library {
background: rgba(200,200,200,1);
text-align:left;
margin:5px 5px -15px 5px;
padding:5px 5px 20px 5px;
min-height:10%;
border:solid 1px rgba(140,140,140,1);
border-radius:10px 10px 0px 0px;
}
.button {
display: inline-block;
background: rgba(150,150,150,0.7);
user-select: none;
margin:1px;
padding:2px;
border:solid 1px rgba(90,90,90,0.5);
border-radius:5px;
cursor:pointer;
}
.button:hover {
background: rgba(140,140,140,1);
margin:0px;
padding:3px;
transition:0.2s;
}
.dialog_back {
position:absolute;
display:flex;
justify-content:center;
align-items:center;
top:0;
left:0;
width:100%;
height:100%;
background: rgba(0,0,0,0.7);
}
.dialog_window {
display:flex;
flex-direction:column;
background: rgba(255,255,255,1);
border-radius:5px;
}
.dialog_title {
display: flex;
align-items: center;
justify-content: space-between;
background: rgba(0,0,0,0.3);
padding: 0px 0px 0px 5px;
}
.dialog_content {
padding: 5px;
}
.card {
height: 3in;
width: 2in;
display: inline-block;
border: 1px rgba(0,0,0,1) solid;
border-radius: 5px;
min-height: 3in;
min-width: 2in;
max-height:3in;
max-width:5in;
overflow: auto;
background: rgb(216, 206, 184);
}

107
UI/index.html Normal file
View File

@ -0,0 +1,107 @@
<html>
<head>
<title>Deckard</title>
<link href="css.css" rel="stylesheet">
<script src="https://labs.murkfall.net/bluesaxman/blue.js/raw/master/libs/bluecore.js"></script>
</head>
<body>
<h1>Welcome to Deckard<h1>
</body>
<script>
window.deck = [];
window.hand = [];
function updateEvent() {
window.UI.deck.innerHTML = "";
window.UI.hand.innerHTML = "";
var theDeck = elementPlace("#deck","deckDisp","card","div");
theDeck.innerHTML = "<div>"+window.deck.length+"</div>";
window.hand.forEach(function (card,index) {
if (index < 10) {
var currentCard = elementPlace("#hand",null,"card","li");
currentCard.innerHTML = card;
}
});
}
function generateDeck(DDF) {
var cards = [""];
for (var attribute in DDF) {
var tempcards = [];
cards.forEach( function (current) {
DDF[attribute].forEach( function (value) {
tempcards.push(current+value);
} );
} );
cards = tempcards.slice();
}
return cards;
}
function shuffleDeck(deck) {
deck.forEach(function (card,index) {
var swapCardIndex = Math.floor( Math.random() * deck.length );
var swapCard = deck[swapCardIndex];
deck[swapCardIndex] = card;
deck[index] = swapCard;
});
}
function deckFromJSON(ourFile) {
if ( Array.isArray(ourFile) ) {
ourFile.forEach(function (deck) {
window.deck = window.deck.concat(generateDeck(deck));
});
} else {
window.deck = window.deck.concat(generateDeck(ourFile));
}
}
elementPlace("body","menu",null,"div");
buttonAdd("#menu","upload","Upload Deck", function () {
popupDialog("deckLoader","Select Deck definition File",true,inputDialog,{"inputType":"file"},function (f) {
var myFile = new FileReader();
myFile.onload = function (file) {
// Probably validate the file somehow befor eating it
var ourFile = JSON.parse(file.target.result);
window.deck = [];
deckFromJSON(ourFile);
window.hand = [];
updateEvent();
}
myFile.readAsText(f[0]);
});
},null,"div");
buttonAdd("#menu","add","Add Deck", function () {
popupDialog("deckLoader","Select Deck definition to add",true,inputDialog,{"inputType":"file"},function (f) {
var myFile = new FileReader();
myFile.onload = function (file) {
var ourFile = JSON.parse(file.target.result);
deckFromJSON(ourFile);
updateEvent();
}
myFile.readAsText(f[0]);
});
}, null, "div");
buttonAdd("#menu","shuffle", "Shuffle Deck", function () {
shuffleDeck(window.deck);
}, null, "div");
buttonAdd("#menu","shuffleAll", "Shuffle Whole Deck", function () {
window.deck = window.deck.concat(window.hand);
window.hand = [];
shuffleDeck(window.deck);
updateEvent();
}, null, "div");
buttonAdd("#menu","draw", "Draw Card", function () {
if (window.deck.length > 0) {
window.hand.unshift(window.deck.shift());
updateEvent();
}
}, null, "div");
elementPlace("body","display",null,"div");
window.UI = {};
window.UI.deck = elementPlace("#display","deck",null,"div");
window.UI.hand = elementPlace("#display","hand",null,"ol");
</script>
</html>