I am trying to design a hangman game in lucidchart. Just start to thinking about the data. If I decide to store them in database, what kinds of columns do I need?
I can think of columns:
(1) word: To store the actual word; (2) numberOfWrongGuesses: To store the wrong guess number (3) currentWord: The word currently has guessed etc.
One problem is once the user done the game or prepare to start a new game, the database needs to be cleaned up right?
If I decide to store them in database, what kinds of columns do I
need?
It depends on how you want the game to work, not just gameplay (guessing the current word) but also managing what happens once the current game is finished - did you want to keep score, etc?
I don't know how Lucid chart works (what sort of runtime, API and programming environment it supports; or how users will interact with it, can it maintain state, etc), but you may be able to run the game entirely in-memory and not need a database at all.
Before diving straight into the physical columns, do a logical design on paper or a whiteboard.
One problem is once the user done the game or prepare to start a new
game, the database needs to be cleaned up right?
That also depends on how you want the game to work. It also depends how many people will be playing this - if two people play it at once, they'll need their own separate set of data.
Cleaning up the data helps keep the database size smaller over time, but it also means you wouldn't be able to track a players history, or allow you to see things like "hardest 5 letter words of all time" etc.
Not necessary, you can create a js file with let object like this:
data.js
const words = [
{ id: 1, name: 'spring' },
{ id: 2, name: 'promise' },
];
after you import this file to your html file.
In general: Start with an analysis of what you want the application to do. Only after that, you can decide if you need persistent storage, and if a database would be the best persistent storage for your application.
Note that databases are used for persistent storage. Since you are thinking about wiping the database after each game, this makes me think you do not need a database.
In this case, I think that you might not need any storage at all. Since you mention Javascript, you might be building a game that runs in the browser. Perhaps cookies would be enough to keep track of the score of your user.
Related
I have a socket.io server that powers a multiplayer browser game. The separate ongoing matches are stored inside a single object in-memory on the server-side:
const matches = {};
When a player creates a match, I add a new unique key to this object for tracking information about that particular game. So when players make a move, I do something like this (simplified for example code):
matches[uniqueKeyForMatch] = newValidatedMatchState;
--where newValidatedMatchState is a large tree of data describing this particular match. "Large" in this case meaning in total its various sub-dictionaries and sub-arrays contain several hundred individual pieces of numerical, boolean, and string data. Around 200-800 individual pieces of data like 5 or "some text", per match.
What I'm wondering is, if I have 100 concurrent matches, can the matches object store that much data efficiently? From this question I see there is some limitation, but I'm not sure what else I could really do other than literally have two variables like matches1 and matches2 and split the data between them. Are there more efficient ways of doing this?
As mentioned in that other question, it's not really an issue. Realistically you'll run out of memory before you hit any other kind of limit. Storing a few hundred/thousand matches doesn't sound like an issue though.
Should your matches be more a kind of persistent data you want to store for a longer period, you'd start storing your matches in files or databases.
Should storing it in databases not fit your needs, or your application just gets too much traffic that the databases can't keep up, split up your application. Have multiple game servers. Your "main server" would just tell the users "your game is available at <server1>".
Also, you might find Map interesting, a better key-value storage object than regular JS objects.
I have a game with a worldwide highscore feature. It uses the firebase database, and writes the user's score if it is the highscore. The rules state that anyone can read or write, so other people can view the highscore.
My problem is that it's easy to manipulate the highscore without actually getting a score. How can I make it so when you achieve a new highscore, it is written to the database, but if you go into the console and change the data, it won't allow you to change it?
if (score > worldScore) {
database.ref().update({highscore: score});
}
You can see that it is very easy to change the data.
In the Firebase console, there is never any restrictions on what you can read or write in the database. Security rules never apply there.
Strictly speaking, unless you involve some serverside component that can one way or another confirm the score was achieved legitimately, this is not possible. Clientside data is always subject to user manipulation; any confirmation checks on that data which you perform on the client would also be subject to user manipulation.
(As for how to actually perform that serverside confirmation: it'll depend on the details of the game, but one way might be to have the client periodically send significant game data to the server; if the server can determine that any of the data has changed in ways that should be impossible according to the game rules -- like a score jumping too far in too short a period of time -- then ignore any future score submissions from that user. Even this isn't perfect: the user can still cheat by manipulating the data that gets sent in that periodic poll, but they'd have to keep their changes at least within the bounds of plausibility.)
Typically you'll want to store not just the score, but also the way the player achieved that score. For example: if it is a board game, write their moves in addition tot he result. If you have both you can:
Verify that the score they wrote is indeed the score that is gotten by applying the moves.
Perform some analysis to detect if the moves seem likely to be computer generated.
Both of these processes are cases of "trusted code", i.e. code that should be running in a trusted environment. For this you can use either an environment you control (a private server, your laptop, etc), Cloud Functions for Firebase, or (in some cases) Firebase's server side security rules. Which ones are feasible depends on your exact use-case, and your available time.
TL;DR:
I'm making an app for a canteen. I have a collection with the persons and a collection where I "log" every meat took. I need to know those who DIDN'T take the meal.
Long version:
I'm making an application for my local Red Cross.
I'm trying to optimize this situation:
there is a canteen at wich the helped people can take food at breakfast, lunch and supper. We need to know how many took the meal (and this is easy).
if they are present they HAVE TO take the meal and eat, so we need to know how many (and who) HAVEN'T eat (this is the part that I need to optimize).
When they take the meal the "cashier" insert their barcode, the program log the "transaction" in the log collection.
Actually, on creation of the template "canteen" I create a local collection "meals" and populate it with the data of all the people in the DB, (so ID, name, fasting/satiated), then I use this collection for my counters and to display who took the meal and who didn't.
(the variable "mealKind" is = "breakfast" OR "lunch" OR "dinner" depending on the actual serving.)
Template.canteen.created = function(){
Meals=new Mongo.Collection(null);
var today= new Date();today.setHours(0,0,1);
var pers=Persons.find({"status":"present"},{fields:{"Name":1,"Surname":1,"barcode":1}}).fetch();
pers.forEach(function(uno){
var vediamo=Log.findOne({"dest":uno.codice,"what":mealKind, "when":{"$gte": today}});
if(typeof vediamo=="object"){
uno['eat']="satiated";
}else{
uno['eat']="fasting";
}
Meals.insert(uno);
});
};
Template.canteen.destroyed = function(){
meals.remove({});
};
From the meal collection I estrapolate the two colums of people satiated (with name, surname and barcode) and fasting, and I also use two helpers:
fasting:function(){
return Meals.find({"eat":"fasting"});
}
"countFasting":function(){
return Meals.find({"eat":"fasting"}).count();
}
//same for satiated
This was ok, but now the number of people is really increasing (we are arount 1000 and counting) and the creation of the page is very very slow, and usually it stops with errors so I can read that "100 fasting, 400 satiated" but I have around 1000 persons in the DB.
I can't figure out how to optimize the workflow, every other method that I tried involved (in a manner or another) more queries to the DB; I think that I missed the point and now I cannot see it.
I'm not sure about aggregation at this level and inside meteor, because of minimongo.
Although making this server side and not client side is clever, the problem here is HOW discriminate "fasting" vs "satiated" without cycling all the person collection.
+1 if the solution is compatibile with aleed:tabular
EDIT
I am still not sure about what is causing your performance issue (too many things in client memory / minimongo, too many calls to it?), but you could at least try different approaches, more traditionally based on your server.
By the way, you did not mention either how you display your data or how you get the incorrect reading for your number of already served / missing Persons?
If you are building a classic HTML table, please note that browsers struggle rendering more than a few hundred rows. If you are in that case, you could implement a client-side table pagination / infinite scrolling. Look for example at jQuery DataTables plugin (on which is based aldeed:tabular). Skip the step of building an actual HTML table, and fill it directly using $table.rows.add(myArrayOfData).draw() to avoid the browser limitation.
Original answer
I do not exactly understand why you need to duplicate your Persons collection into a client-side Meals local collection?
This requires that you have first all documents of Persons sent from server to client (this may not be problematic if your server is well connected / local. You may also still have autopublish package on, so you would have already seen that penalty), and then cloning all documents (checking for your Logs collection to retrieve any previous passages), effectively doubling your memory need.
Is your server and/or remote DB that slow to justify your need to do everything locally (client side)?
Could be much more problematic, should you have more than one "cashier" / client browser open, their Meals local collections will not be synchronized.
If your server-client connection is good, there is no reason to do everything client side. Meteor will automatically cache just what is needed, and provide optimistic DB modification to keep your user experience fast (should you structure your code correctly).
With aldeed:tabular package, you can easily display your Persons big table by "pages".
You can also link it with your Logs collection using the dburles:collection-helpers (IIRC there is an example en the aldeed:tabular home page).
Let's say I'm making an HTML5 game using JavaScript and the <canvas> The varaibles are stored in the DOM such as level, exp, current_map, and the like.
Obviously, they can be edited client-side using Firebug. What would I have to do to maximize security, so it would be really hard to edit (and cheat)?
Don't store the variables in the DOM if you wish a reasonable level of security. JavaScript, even if obfuscated, can easily be reverse engineered. That defeats any local encryption mechanisms.
Store key variables server-side and use https to maximize security. Even so, the client code (JavaScript) is quite vulnerable to hacking.
You can use Object.freeze or a polyfill or a framework which does the hiding for you.
Check out http://netjs.codeplex.com/
You could also optionally implement some type of signing system but nothing is really impenetrable. For instance objects locked with Object.freeze or Object.watch can still be manually modified in memory.
What are you really trying to accomplish in the end?
What you could do is send a representation of the matrix of the game or the game itself or a special hash or a combination of both and tally the score at the server... causing the user to not only have to modify the score but to correctly modify the state of the game.
Server-side game logic
You need to keep the sensitive data on the server and a local copy on the browser for display purposes only. Then for every action that changes these values the server should be the one responsible for verifying them. For example if the player needs to solve a puzzle you should never verify the solution client side, but take for example the hash value of the ordered pieces represented as a string and send it to the server to verify that the hash value is correct. Then increase the xp/level of the player and send the information back to the client.
Anything that is living in the client can be modified. That is because in MMORPG the character's data is living on the server, so players can't hack their characters using any memory tools, hex editor, etc (they actually "can", but because the server keep the correct version of the character's data is useless).
A good example was Diablo 2: you have actually two different characters: one for single player (and Network playing with other players where one was the server), and one for Battle.net. In the first case, people could "hack" the character's level and points just editing the memory on the fly or the character file with an hex editor. But that wasn't possible with the character you was using on Battle.net.
Another simple example could be a quiz where you have a limited time to answer. If you handle everything on client side, players could hack it and modify the elapsed time and always get the best score: so you need to store the timestamp on the server as well, and use that value as comparison when you get the answer.
To sum up, it doesn't matter if it's JavaScript, C++ or Assembly: the rule is always "Don't rely on client". If you need security for you game data, you have to use something where the clients have no access: the server.
I'm starting my hand at creating a multi-player game using HTML 5 / Javascript.
I'm currently doing some prototypes on different ideas on how to stop people from cheating. Now I know I need to do everything server side and just have the client sending "actions".
My issue is I can't workout the best way to store the game state for each player.
So just looking at something basic; Two players running round a empty map.
Currently my idea is
Both clients(sockets.io) send their actions to a Node.JS server that then responds with a X/Y coord. This is fine. But obviously both clients need to know where the other player is.
I thought about doing this by creating a new database table for each game and having the game state stored in there so the two node.js connections can talk to eachother.
My question is, is this the best way to interact between two node.js connections, would it be fast enough? Or is there a design patten for this specific task that I'm missing?
thanks
Creating a new table per game is generally considered a Terrible Idea.
If you don't need persistence -- ie. in the case your Node.js server croaks, a game may be lost -- you can simply store the games in memory, in an object, let's say games, which might contain an object that has an array of players, each of which might contain x and y coordinates, etc.
var games = {
123019240: {
players: {
123: {x: 1, y: 1, name: 'Joe'},
456: {x: 2, y: 2, name: 'Jimbob'}
}
}
};
If you do need persistence, though, you really should probably look into some other databases than SQL -- for instance Redis might be a good choice for the task.
In any case, SQL feels like the wrong tool, and creating new tables on demand even more so. (If you are using SQL, though, consider a table layout with game_id, player_id, x and y and be sure to have an index on game_id :) )
The approach you need to take is the following:
Each client sends it's coordinate to the server at specific intervals (using emit). The server checks this position for validity and stores it the db. It then uses a broadcast message (http://socket.io/#how-to-use - Broadcasting messages) to send this position to all the clients.
Each client in turn will update the displayed position of the character/player that moved.
You cannot create a direct connection between two players because they are using a browser. Each connection must pass through a single node.js server.
You can view some tutorials here:
http://www.nodejs-news.com/nodejs-tech/Nodejs-Socketio-Building-HTML5-game/
(They use the Impact engine but the principles are the same)
In my experience, if you have users interacting with each other in a clustered server environment, its best to have them interacting on the same server.
Example:
5 game servers, people create games together in a lobby. A game contains a max number of people. With this scenario, it is much much much easier to keep the game on one server, and make all users connect to that one game server. This prevents needed convo between servers, and keeps game state consistent and fast!
Eve Online is a great example of this. Each 'region' is it's own server, and when you travel far enough through the universe, you are transparently moved to another game server. That way if you're fighting somebody, chances are they're on the same server. Then the game server is free to periodically write data to the DB. This is the best way, as the user never has to wait for the DB. They communicate directly with the game server, game server communicates with DB every once in a while. At most, your user would lose only a few seconds of data (and so would everyone else on that game server).