Move card server logic test into cardGen.js module

develop
Nathan Steel 1 year ago
parent 57b0194f9b
commit ceef95712e

@ -0,0 +1,373 @@
// Need to require DB again. Apparently this is ok, as it'll
// still only have one require cross project (?)
const database = require('./database');
// cardClass, cardColourRequirement
// may want to be seperate too (as well as in cardItem), so that
// during match they can be altered by effects while keeping the OG card
// for inspecting (and compare against new stats,reqs,etc.)
// same with attack, cost, etc. things that will can be visually shown as
// changed in game
// Just grabbing everything from DB for now, as it's quite small at current
// then will rejig when needed.
// Should all cards, effects, classes etc. be loaded in on server start
// then just load decks and decklists when needed?
function getDecks(deckId, playerId, item = [], deckItem = {}){
// Await promise, once it's done get the data, if errors send err
const dPromise = new Promise((resolve, reject) => {
database.dbGetDecks().then(data => {
let decks = [];
data.forEach((deck) => {
//let itemId = item.length;
//item.push(itemId); // Add the next available item
// Add the deck info to deckItem
// deckItem[itemId] = {};
decks.push({
'deckId': deck.deckId,
'playerId': deck.playerId,
'deckName': deck.deckName,
});
});
// Resolve the decks pulled
resolve(decks);
//console.log(item);
//console.log(deckItem);
//console.log(decks);
})
.catch(err => { throw err; })
});
return dPromise;
}
//getDecks();
function getDeckList(){
const dPromise = new Promise((resolve, reject) => {
database.dbGetDeckList().then(data => {
let deckList = [];
data.forEach((listItem) => {
// Add the deck info to deckItem
deckList.push({
'deckId': listItem.deckId,
'playerId': listItem.playerId,
'cardId': listItem.cardId,
'cardCount': listItem.cardCount,
});
resolve(deckList);
});
})
.catch(err => { throw err; })
});
return dPromise;
}
//getDeckList();
function getCards(){
const dPromise = new Promise((resolve, reject) => {
database.dbGetCards().then(data => {
let cards = [];
data.forEach((card) => {
cards.push({
'id': card.id,
'cardName': card.cardName,
'cardCost': card.cardCost,
'cardType': card.cardType,
'cardAttack': card.cardAttack,
'cardRarity': card.cardRarity,
'cardClass': [],
'cardColourRequirement': [],
});
});
resolve(cards);
})
.catch(err => { throw err; })
});
return dPromise;
}
//getCards();
function getCardClasses(){
const dPromise = new Promise((resolve, reject) => {
database.dbGetCardClasses().then(data => {
let cardClasses = [];
data.forEach((cardClass) => {
cardClasses.push({
'cardId': cardClass.cardId,
'classId': cardClass.classId,
});
});
resolve(cardClasses);
})
.catch(err => { throw err; })
});
return dPromise;
}
//getCardClasses();
function getCardColourRequirement(){
const dPromise = new Promise((resolve, reject) => {
database.dbGetCardColourRequirement().then(data => {
let colourRequirements = [];
data.forEach((cardColourReq) => {
colourRequirements.push({
'cardId': cardColourReq.cardId,
'colourId': cardColourReq.colourId,
'cost': cardColourReq.cost,
});
});
resolve(colourRequirements);
})
.catch(err => { throw err; })
});
return dPromise;
}
//getCardColourRequirement();
// Then effects which will have effects with parent triggers, and unit type checks
// colour checks, all sorts. So will be more difficult. Basic (flight, etc)
// shouldn't be too bad
// something like effect_basic, card_effect, effect_trigger, effect_requirement, effect_option
// effect_stage, effect_advanced, with advanced being an id with x triggers, triggers have
// x req, advanced as with x options, x stages to be able to fine-tune fancy stuff
// combining all other effects, units, cards, colours, etc. Will be a lot of though,
// but better than hard coding anything more than basic effects and effect check logic
// TODO: effect (as above)
// request a deck in the format CURRENTLY used in the game
// decks will likely be changed around
// https://www.geeksforgeeks.org/how-to-wait-for-multiple-promises-in-javascript/
// https://medium.com/@nikolozz/using-socket-io-with-async-await-13fa8c2dc9d9
// using last example
function requestDeck(socket, playerId, deckId){
return new Promise((resolve, reject) => {
(async () => {
// Get the deck(s) requested.
// Not 100% on how to do two differening atm
// Besides all of playerId, and all of deckId. But 1,2/2,3 for instance
const [decks, deckList] =
await Promise.all([
getDecks(),
getDeckList()
// Don't need to do this for each when awaiting all
// Instead it'll wait until each is done, set the data to the const
// Then do the stuff after the variable's are set!!
/*
getDecks().then(data => {
//console.log(data);
}).catch(err => { throw err; }),
*/
]);
//console.log(decks);
//console.log(deckList);
// Now loop the deckList for the cardIds
let deckCardIds = [];
deckList.forEach((deckItem) => {
deckCardIds.push(deckItem.cardId);
});
//console.log(deckCardIds);
// Next, get the cards in the deck by their ID
// TODO: https://stackoverflow.com/a/65510676
// Change SQL to accept for just the cards passed
// Get each cards data, colourReqs, and classes
const [cards, cardClasses, cardColourRequirements] =
await Promise.all([
getCards(),
getCardClasses(),
getCardColourRequirement(),
]);
// ^^^^ Classes async? Can pass the cardsIds, then loop classes, if the class cardId
// matches the cardId in cards[] then push the class to cards[x].classes
// TODO: Build the card so far async for it's done alongside getting effects?
// Then when both done add the effects to the existing cardObjects? Yep good idea me
//console.log(cards);
//console.info(cardClasses);
//console.log(cardColourRequirements);
const [builtCards] =
await Promise.all([
buildCards(cards, cardClasses, cardColourRequirements),
// TODO: builtEffects
]);
//console.log(builtCards);
// TODO: addEffectsToCards
// TODO: Finally do the effects for each card. This will be the complicater
// since it's not 100% thought out yet... (
// Add the cards (x of how many cardObjects with cardId are in count in decklist)
// to a deck array to pass through. Or decks array with deckId specified?
//console.log(deckList);
// These are the four basic fellas for this
// from public/board.js where current game testing/logic is applied
// So creating as a test for a 'room' to see if it's simple enough to
// send and play with
// BUILD THE DATA TO SEND TO CLIENTS! (Kinda)
let item = [];
let itemCount = 0;
let deckData = {}; // New but may be useful
let deckIn = {}; // Which deck the item is in? Kinda the player/boardelement thing?
let cardData = {};
let boardElement = {};
// TODO: Set the player. For now will do this in front-end as testing currently
// Loop and create the deck first
//console.log(decks);
decks.forEach((deck) => {
item.push(itemCount); // Add new item to add stuff for
deckData[itemCount] = {'deckId':deck.deckId, 'playerId':deck.playerId, 'deckName':deck.deckName};
boardElement[itemCount] = 'realDeck';
itemCount++;
})
console.log(deckData);
console.log(deckList);
// Loop each item in the deckList
// Loop inside it X times where X is cardCount
// Add the builtCard with same cardId as deckList item X times
deckList.forEach((deckListItem) => {
let deckItem = null;
// Loop each deck, if the deck/playerIds match, add association
for(key in deckData){
//Object.keys(deckData).forEach(function(key) { // Less efficient than for
// Needs to check deck AND player id, as that's the primary key (together)
if(deckData[key].deckId == deckListItem.deckId && deckData[key].playerId == deckListItem.playerId){
deckItem = key; // Key is the `item` key
}
};
// For each new card, loop to the cardCount (how many cards in deck)
// and add to the deck
for(let i = 0; i < deckListItem.cardCount; i++){
item.push(itemCount); // Add new item to add stuff for
// ^ not using item.length incase anything in future gets deleted
// from item for instance
cardData[itemCount] = builtCards[deckListItem.cardId]; // builtCards id set to cardId from DB, so adding the builtCard object is based on the deckList's cardId (from DB)
boardElement[itemCount] = 'deck'; // Add all cards to deck at match start
// Associate the card with the deck
// TODO: Change deckIn to something more sensical
deckIn[itemCount] = deckItem;
itemCount++; // Increment item to not overwrite
}
});
// item, itemCount, deckData, cardData, boardElement
//console.log(cardData);
// Returning everything to be looped in the front-end
// This won't be looped as it will at final, instead just for deck generation
// Returned as object over array, as easier to disect when gets to front-end
let dataReturn = {
item: item,
itemCount: itemCount,
deckData: deckData,
deckIn: deckIn,
cardData: cardData,
boardElement: boardElement,
};
return resolve(dataReturn);
//return resolve(cardData);
// Promise stuff testing
})()
});
// TODO: In future the item inc. all the decks, cards, locations, and other attributes
// will come from here
// TODO: unrelated, but thought. If lots of players on, generating cards each time
// will be a big hit, as well as all the DB hits, so may need to load all cardObjects
// into memory/array when server starts. This then prevents any DB changes to alter
// things, but outside of testing that won't occur(?), may need to test this at some
// point to see. For now DB, and generating is ok, as still working on it
}
function buildCards(cards, cardClasses, cardColourRequirements){
const dPromise = new Promise((resolve, reject) => {
builtCards = {};
//console.log(cards);
// Loop the cards and build the base
cards.forEach((card) => {
let builtCard = {
id: card.id,
name: card.cardName,
colour: [],
cost: card.cardCost,
costReq: [],
type: card.cardType,
atk: card.cardAttack,
rarity: card.cardRarity,
effect: [],
cardClass: [],
};
// Give the card an easily accessible Id for compares
// and to add to the cardItem being built
builtCards[card.id] = builtCard;
});
//console.log(builtCards);
// Next loop each class, and add to the new builtCard (if cardIds match)
cardClasses.forEach((cardClass) => {
// Check the card exists (it should always, but don't want jank)
if(cardClass.cardId in builtCards){
// It's the Id for now
// TODO: Send the text too (from join) but don't use for compares
//console.log(cardClass.cardId);
//console.log(cardClass.classId);
//console.log('---');
//console.log(builtCards[cardClass.cardId]);
// Add the class to the class array (cards can have multiple)
builtCards[cardClass.cardId].cardClass.push(cardClass.classId);
// TODO: As an array [classId, className] then
// card.classes[x][0] can be compared as numeric in code
}
});
resolve(builtCards);
});
return dPromise;
}
// TODO: Add the effects onto the cards passed through
// Takes cards array (of obj), and array of effects (from DB or built, probabaly pre-built?)
function addCardsEffects(){}
module.exports = {
requestDeck
};

@ -842,8 +842,6 @@ function loadBoard(data) {
// Decks can be as-is for getting deckLists for deckselection, but // Decks can be as-is for getting deckLists for deckselection, but
// TODO: for matches need something to generate and return every item, and attribute // TODO: for matches need something to generate and return every item, and attribute
console.log(cardData[0]);
// Temp solution // Temp solution
// Loop all items, and set their related missing attributes // Loop all items, and set their related missing attributes
// TODO: some more jank to get it 'playable' with DB entries // TODO: some more jank to get it 'playable' with DB entries
@ -1277,15 +1275,12 @@ function calculateItemSizePosition(itemKey){
positionY = 60; positionY = 60;
width = cardWidth*1.5; width = cardWidth*1.5;
height = cardHeight*1.5; height = cardHeight*1.5;
console.log('HELLO 1');
} }
if(itemPlayer == 0 && itemElement == 'realDeck'){ if(itemPlayer == 0 && itemElement == 'realDeck'){
positionX = canvas.width-cardWidth*1.5-40; positionX = canvas.width-cardWidth*1.5-40;
positionY = canvas.height-cardHeight*1.5-60; positionY = canvas.height-cardHeight*1.5-60;
width = cardWidth*1.5; width = cardWidth*1.5;
height = cardHeight*1.5; height = cardHeight*1.5;
console.log('HELLO 0');
} }
if(itemPlayer == 1 && itemElement == 'board'){ if(itemPlayer == 1 && itemElement == 'board'){

@ -1,6 +1,7 @@
const express = require('express'); const express = require('express');
const database = require('./database'); const database = require('./database');
const cardGen = require('./cardGen');
const app = express(); const app = express();
const http = require('http').Server(app); const http = require('http').Server(app);
const port = process.env.PORT || 3000; const port = process.env.PORT || 3000;
@ -39,326 +40,8 @@ for (let roomId = 1; roomId <= numRoomsToPreGen; roomId++) {
createRoom(roomId); createRoom(roomId);
} }
// For testing DB/makeshift ORM/building my objects
// Maybe if this works, put it into a deck and card module
// Doing similar to I have to other stuff, that will need to be
// migrated serverside anyways.
/*
let item = [];
let deckItem = {};
let deckList = {};
let cardItem = {};
*/
// cardClass, cardColourRequirement
// may want to be seperate too (as well as in cardItem), so that
// during match they can be altered by effects while keeping the OG card
// for inspecting (and compare against new stats,reqs,etc.)
// same with attack, cost, etc. things that will can be visually shown as
// changed in game
// Just grabbing everything from DB for now, as it's quite small at current
// then will rejig when needed.
// Should all cards, effects, classes etc. be loaded in on server start
// then just load decks and decklists when needed?
function getDecks(deckId, playerId, item = [], deckItem = {}){
// Await promise, once it's done get the data, if errors send err
const dPromise = new Promise((resolve, reject) => {
database.dbGetDecks().then(data => {
let decks = [];
data.forEach((deck) => {
//let itemId = item.length;
//item.push(itemId); // Add the next available item
// Add the deck info to deckItem
// deckItem[itemId] = {};
decks.push({
'deckId': deck.deckId,
'playerId': deck.playerId,
'deckName': deck.deckName,
});
});
// Resolve the decks pulled
resolve(decks);
//console.log(item);
//console.log(deckItem);
//console.log(decks);
})
.catch(err => { throw err; })
});
return dPromise;
}
//getDecks();
function getDeckList(){
const dPromise = new Promise((resolve, reject) => {
database.dbGetDeckList().then(data => {
let deckList = [];
data.forEach((listItem) => {
// Add the deck info to deckItem
deckList.push({
'deckId': listItem.deckId,
'playerId': listItem.playerId,
'cardId': listItem.cardId,
'cardCount': listItem.cardCount,
});
resolve(deckList);
});
})
.catch(err => { throw err; })
});
return dPromise;
}
//getDeckList();
function getCards(){
const dPromise = new Promise((resolve, reject) => {
database.dbGetCards().then(data => {
let cards = [];
data.forEach((card) => {
cards.push({
'id': card.id,
'cardName': card.cardName,
'cardCost': card.cardCost,
'cardType': card.cardType,
'cardAttack': card.cardAttack,
'cardRarity': card.cardRarity,
'cardClass': [],
'cardColourRequirement': [],
});
});
resolve(cards);
})
.catch(err => { throw err; })
});
return dPromise;
}
//getCards();
function getCardClasses(){
const dPromise = new Promise((resolve, reject) => {
database.dbGetCardClasses().then(data => {
let cardClasses = [];
data.forEach((cardClass) => {
cardClasses.push({
'cardId': cardClass.cardId,
'classId': cardClass.classId,
});
});
resolve(cardClasses);
})
.catch(err => { throw err; })
});
return dPromise;
}
//getCardClasses();
function getCardColourRequirement(){
const dPromise = new Promise((resolve, reject) => {
database.dbGetCardColourRequirement().then(data => {
let colourRequirements = [];
data.forEach((cardColourReq) => {
colourRequirements.push({
'cardId': cardColourReq.cardId,
'colourId': cardColourReq.colourId,
'cost': cardColourReq.cost,
});
});
resolve(colourRequirements);
})
.catch(err => { throw err; })
});
return dPromise;
}
//getCardColourRequirement();
// Then effects which will have effects with parent triggers, and unit type checks
// colour checks, all sorts. So will be more difficult. Basic (flight, etc)
// shouldn't be too bad
// something like effect_basic, card_effect, effect_trigger, effect_requirement, effect_option
// effect_stage, effect_advanced, with advanced being an id with x triggers, triggers have
// x req, advanced as with x options, x stages to be able to fine-tune fancy stuff
// combining all other effects, units, cards, colours, etc. Will be a lot of though,
// but better than hard coding anything more than basic effects and effect check logic
// TODO: effect (as above)
// request a deck in the format CURRENTLY used in the game
// decks will likely be changed around
// https://www.geeksforgeeks.org/how-to-wait-for-multiple-promises-in-javascript/
// https://medium.com/@nikolozz/using-socket-io-with-async-await-13fa8c2dc9d9
// using last example
function requestDeck(socket, playerId, deckId){
return new Promise((resolve, reject) => {
(async () => {
// Get the deck(s) requested.
// Not 100% on how to do two differening atm
// Besides all of playerId, and all of deckId. But 1,2/2,3 for instance
const [decks, deckList] =
await Promise.all([
getDecks(),
getDeckList()
// Don't need to do this for each when awaiting all
// Instead it'll wait until each is done, set the data to the const
// Then do the stuff after the variable's are set!!
/*
getDecks().then(data => {
//console.log(data);
}).catch(err => { throw err; }),
*/
]);
//console.log(decks);
//console.log(deckList);
// Now loop the deckList for the cardIds
let deckCardIds = [];
deckList.forEach((deckItem) => {
deckCardIds.push(deckItem.cardId);
});
//console.log(deckCardIds);
// Next, get the cards in the deck by their ID
// TODO: https://stackoverflow.com/a/65510676
// Change SQL to accept for just the cards passed
// Get each cards data, colourReqs, and classes
const [cards, cardClasses, cardColourRequirements] =
await Promise.all([
getCards(),
getCardClasses(),
getCardColourRequirement(),
]);
// ^^^^ Classes async? Can pass the cardsIds, then loop classes, if the class cardId
// matches the cardId in cards[] then push the class to cards[x].classes
// TODO: Build the card so far async for it's done alongside getting effects?
// Then when both done add the effects to the existing cardObjects? Yep good idea me
//console.log(cards);
//console.info(cardClasses);
//console.log(cardColourRequirements);
const [builtCards] =
await Promise.all([
buildCards(cards, cardClasses, cardColourRequirements),
// TODO: builtEffects
]);
//console.log(builtCards);
// TODO: addEffectsToCards
// TODO: Finally do the effects for each card. This will be the complicater
// since it's not 100% thought out yet... (
// Add the cards (x of how many cardObjects with cardId are in count in decklist)
// to a deck array to pass through. Or decks array with deckId specified?
//console.log(deckList);
// These are the four basic fellas for this
// from public/board.js where current game testing/logic is applied
// So creating as a test for a 'room' to see if it's simple enough to
// send and play with
// BUILD THE DATA TO SEND TO CLIENTS! (Kinda)
let item = [];
let itemCount = 0;
let deckData = {}; // New but may be useful
let deckIn = {}; // Which deck the item is in? Kinda the player/boardelement thing?
let cardData = {};
let boardElement = {};
// TODO: Set the player. For now will do this in front-end as testing currently
// Loop and create the deck first
//console.log(decks);
decks.forEach((deck) => {
item.push(itemCount); // Add new item to add stuff for
deckData[itemCount] = {'deckId':deck.deckId, 'playerId':deck.playerId, 'deckName':deck.deckName};
boardElement[itemCount] = 'realDeck';
itemCount++;
})
console.log(deckData);
console.log(deckList);
// Loop each item in the deckList
// Loop inside it X times where X is cardCount
// Add the builtCard with same cardId as deckList item X times
deckList.forEach((deckListItem) => {
let deckItem = null;
// Loop each deck, if the deck/playerIds match, add association
for(key in deckData){
//Object.keys(deckData).forEach(function(key) { // Less efficient than for
// Needs to check deck AND player id, as that's the primary key (together)
if(deckData[key].deckId == deckListItem.deckId && deckData[key].playerId == deckListItem.playerId){
deckItem = key; // Key is the `item` key
}
};
// For each new card, loop to the cardCount (how many cards in deck)
// and add to the deck
for(let i = 0; i < deckListItem.cardCount; i++){
item.push(itemCount); // Add new item to add stuff for
// ^ not using item.length incase anything in future gets deleted
// from item for instance
cardData[itemCount] = builtCards[deckListItem.cardId]; // builtCards id set to cardId from DB, so adding the builtCard object is based on the deckList's cardId (from DB)
boardElement[itemCount] = 'deck'; // Add all cards to deck at match start
// Associate the card with the deck
// TODO: Change deckIn to something more sensical
deckIn[itemCount] = deckItem;
itemCount++; // Increment item to not overwrite
}
});
// item, itemCount, deckData, cardData, boardElement
//console.log(cardData);
// Returning everything to be looped in the front-end
// This won't be looped as it will at final, instead just for deck generation
// Returned as object over array, as easier to disect when gets to front-end
let dataReturn = {
item: item,
itemCount: itemCount,
deckData: deckData,
deckIn: deckIn,
cardData: cardData,
boardElement: boardElement,
};
return resolve(dataReturn);
//return resolve(cardData);
// Promise stuff testing
})()
});
// TODO: In future the item inc. all the decks, cards, locations, and other attributes
// will come from here
// TODO: unrelated, but thought. If lots of players on, generating cards each time
// will be a big hit, as well as all the DB hits, so may need to load all cardObjects
// into memory/array when server starts. This then prevents any DB changes to alter
// things, but outside of testing that won't occur(?), may need to test this at some
// point to see. For now DB, and generating is ok, as still working on it
}
// For testing // For testing
requestDeck(); cardGen.requestDeck();
function requestDeckStart(socket){ function requestDeckStart(socket){
// For future: // For future:
@ -369,7 +52,7 @@ function requestDeckStart(socket){
// whatever functions, and stuff needs to happen // whatever functions, and stuff needs to happen
// Wasted so much time trying to do async server-client stuff. Don't bother // Wasted so much time trying to do async server-client stuff. Don't bother
response = {success: false, message: 'Failed requestDeckStart() server.js'}; response = {success: false, message: 'Failed requestDeckStart() server.js'};
requestDeck().then(data => { cardGen.requestDeck().then(data => {
response.success = true; response.success = true;
response.message = data; response.message = data;
io.to(socket.id).emit('responseGetDeck', response); io.to(socket.id).emit('responseGetDeck', response);
@ -380,66 +63,6 @@ function requestDeckStart(socket){
io.to(socket.id).emit('responseGetDeck', err); io.to(socket.id).emit('responseGetDeck', err);
}); });
} }
function buildCards(cards, cardClasses, cardColourRequirements){
const dPromise = new Promise((resolve, reject) => {
builtCards = {};
//console.log(cards);
// Loop the cards and build the base
cards.forEach((card) => {
let builtCard = {
id: card.id,
name: card.cardName,
colour: [],
cost: card.cardCost,
costReq: [],
type: card.cardType,
atk: card.cardAttack,
rarity: card.cardRarity,
effect: [],
cardClass: [],
};
// Give the card an easily accessible Id for compares
// and to add to the cardItem being built
builtCards[card.id] = builtCard;
});
//console.log(builtCards);
// Next loop each class, and add to the new builtCard (if cardIds match)
cardClasses.forEach((cardClass) => {
// Check the card exists (it should always, but don't want jank)
if(cardClass.cardId in builtCards){
// It's the Id for now
// TODO: Send the text too (from join) but don't use for compares
//console.log(cardClass.cardId);
//console.log(cardClass.classId);
//console.log('---');
//console.log(builtCards[cardClass.cardId]);
// Add the class to the class array (cards can have multiple)
builtCards[cardClass.cardId].cardClass.push(cardClass.classId);
// TODO: As an array [classId, className] then
// card.classes[x][0] can be compared as numeric in code
}
});
resolve(builtCards);
});
return dPromise;
}
// TODO: Add the effects onto the cards passed through
// Takes cards array (of obj), and array of effects (from DB or built, probabaly pre-built?)
function addCardsEffects(){}
// End For testing // End For testing
function onConnection(socket){ function onConnection(socket){

Loading…
Cancel
Save