F Lucas

Ranch Hand
+ Follow
since Jul 04, 2017
Merit badge: grant badges
For More
Cows and Likes
Cows
Total received
In last 30 days
0
Forums and Threads

Recent posts by F Lucas

A section from 3.8 Python grammar specification...


...I might be screwed.
Should I try to make separate rules for each of the tokens in the comments instead?
If Python concatenated all of these into a single rule I feel like it is for optimization, but PLY says it is better to make separate rules instead of various alternatives because each of these will be basically a conditional and slow down everything.

Comments like:


Look more doable to code.
1 year ago

I think you kinda shot yourself in the foot by choosing a LALR parser generator (PLY) to generate a parser for a PEG grammar



Oh.. I really should've researched parsers harder before going into this..
I thought I couldn't use the symbols in PLY because of some limitation of it being in Python, never would've imagined its not even the same type of grammar...

Every del_stmt is also a simple_stmt, which necessarily means that it is followed by a semicolon or newline. The positive lookahead just appears to be some sort of performance hack. You can probably get away with omitting the lookahead completely



Makes sense. I had a feeling that was the case but was too scared to modify something I didn't understand completely, but I guess I already am modifying parts of it.

I will study some more about parsers first before I get to the point where I have to refactor most of my code.

Thank you for the help.




1 year ago
Hello.
I've been working on a Python-like language with PLY to parse mods for my game, while reducing security risks by restricting or removing functionality from Python such as imports and multithreading.
To do that I am reading the official Python grammar specification, and I've stumbled into this...
==============
# ( e )
#   Match e (allows also to use other operators in the group like '(e)*')
# [ e ] or e?
#   Optionally match e.
# e*
#   Match zero or more occurrences of e.
# e+
#   Match one or more occurrences of e.
# s.e+
#   Match one or more occurrences of e, separated by s. The generated parse tree
#   does not include the separator. This is otherwise identical to (e (s e)*).
# &e
#   Succeed if e can be parsed, without consuming any input.
# !e
#   Fail if e can be parsed, without consuming any input.
# ~
#   Commit to the current alternative, even if it fails to parse.
#
======= Rules continue.... =====

I managed to implement most of the rules containing these symbols in ply, sometimes making extra tokens to match these special rules.
But I am completely stumped in '&'.
For '!', my approach was to define a token with a different name of what the token needs if the offending lookahead is found.
Something like:


If the negative lookahead ( the token ASSIGN here) is found, the token is reduced to star_expressions_assign, and will not match the
star_expressions Token requisite in assignment.

The problem is when I cannot change the name of the Token at all.
I have to check for a lookahead, and not consume it.

I've tried to find a way to check for the next Token. I could not find it, but even if I did,
how would I return the Token without modifying it when it does not match?

So in short, I want to do something like


To somehow "ruminate"(swallow something, then let it back into the mouth, to send it to the second stomach.. like cows.) Tokens.
I need to check if a Token exists, but not consume it and send it back to the stack for it to be reduced into something else.

Sorry for the poor wording. I could not find a better way to word it.
Any help is appreciated.
1 year ago
It's basically going to be a card game battle royale (The original game mode)
but moddable.
I played some Slay the Spire and thought that the combat system was really creative, and wanted to make a multiplayer game out of it.

..If I finish it that is. I sure hope I manage to do it.
Wow.

That post just made me realize how shallow was my planning for this.

The problem with natural keys is that they might take up more space in your database if the values take up more than a few bytes.



The space usage on the name will probably be irrelevant because my project will not be that big, but I will definitely keep it in mind.

I hope you're using Django's authentication mechanism, and you're not building your own.



I am. I've made the mistake of trying to cipher passwords on my own before...

Why have a 0 status at all? Just remove the entry when a player isn't queued up.

Also, if your database supports it, use enums instead of integers for columns like this. It's much nicer to read something like 'queued' and 'ready', instead of 1 and 2.



Good point. I am going to remove 0.

And my DB does not support enums, but django does and shows the field value by the enum name set in the code.

Don't store an amount of time, you can't reliably update it.



Completely true. I don't know what I was thinking about how to update a few dozens of players worth of time every second..

I hope it only holds all variables related to the specific player.



It does.

For larger text formats like JSON, use CLOB instead of VARCHAR. Or consider serializing your game state to a binary format, and saving it as a BLOB.


Ok. This one might be substantial in size enough to be worth to serialize, since I have no idea what the contents may be.

It's probably highly unlikely that two identical rulesets will get added to the table, and even if they do, is it that big a deal?



This is the only part I am unsure of.
Since my site is just a personal project, I cannot expect many concurrent players.
If somebody makes a mod, identical to another, and makes lobbies (Something close to a queue) with another name, I will be splitting the potential player pool that was
supposed to go into the same match, into two lobbies.
This might make custom modes impossible.

Also I want to properly credit modders, and I'd not like people arguing about copy and pasting mods.
Might be an unnecessary precaution, but I think this will do more good than harm.

And I guess that is all for now.

Thanks for all the help Stephan.

I wish you a great day, you surely made mine better
Hello.

The explanation about second normal form was a real eye opener. I can't find a way to thank you enough for it  

So, about the attributes..

As you said is_guest is redundant. It just means it is a temporary account that will be deleted on session end, and does not have an email.
So I can remove it.

is_online really is not supposed to be in the database, but I am making a page with django and I am not sure if I can
check if there is an ongoing session with a specific user. I will remove it if I can though.

Below is my current idea of the database structure, and the explanation for each of the fields.
It is going to be a wall of text, sorry.


Tables

Table Accounts

name: varchar (PK), Its the username of the account. Maybe I should be using a separate ID for the PK, but since I could enforce unique usernames this way, I figured I'd just make this the PK.

email: varchar, The email. Nullable, and if Null, this account is a "guest" account and gets restricted access to the site.

password: varchar (cyphered before added to DB), The password.

elo: smallint: This is a number that goes up and down depending on the player's win/lose ratio, that represents this player's skill.
I have no way of using this for now, but I will later implement a queue which only matches players with close enough elo.

Because name is the PK, at no point I will get two records when querying by name.
None of the other fields can determine another field.
So this field is in third normal form.

Table Queue_sessions
Since I am making a multiplayer game, I need a way for players to wait in a queue until there are enough players to fill a match lobby with.
This is where currently queued players get recorded.

name(FK): The player that is in queue. Unique, not nullable.

queue_status: tinyint, This is either 0(Not in queue),1(In queue waiting for match),or 2(In queue but not available for matching.)
Reasons for the status may vary, like the user being prompted for confirmation to join a match. It is in queue, but not eligible for receiving another alert for a match.

queue_time: time, The amount of time this player has been in the queue. Players with the bigger queue_time are prioritized to find a match quicker.

Because name is not nullable and always unique, I can also query this table by name and never get 2 different records.
I cannot determine any other fields using anything other than name, so this table must be in third normal form.

Table Game_sessions

My game is a moddable, multiplayer, turn-based game.
Which means anybody can make modified versions of my game by changing the game logic,
There are multiple players interacting with each other in a match,
And I do not need to care about latency.

Because it is moddable, I cannot make a table for each game type, and ensure I only have the fields that I need.

So this is what I've came up with for now..

name(FK): The name of the player in game. Unique, not nullable.

game_info: a varchar that will hold a JSON, not too big in size, that holds all the variables needed for the game.
The field name will likely change. Not nullable.

match(FK): The ID of the match. It refers to the table Matches. Not nullable.

name is unique and not nullable, game_info and match is not unique.
This table is in third normal form.

(And some more fields might be added.)

Table Matches

id(PK): Just an auto-increment int.

ruleset_id(FK): The id of the used Ruleset(Object used to modify the game). Refers to the table Rulesets. Not nullable.

ongoing_time: Time this match has been going for. I might have to terminate matches that go on for too long and delete records related to it. Nullable, because it is null for finished matches.

result: A JSON that holds information about a finished match. Contents vary depending on the Ruleset, so again, I cannot make definite fields to hold the values. Nullable, because it is null for ongoing matches.

I have a PK, no other value is unique, none of the values define anything other than the PK. This table is in third normal form.

Table Rulesets

id(PK): Just an auto-increment int.

content: JSON to be read by the backend code. unique.

No two rulesets will have the same id, or the same content. Always only one record when I query for either of the fields.
This table is in third normal form.


Is this correct?

Thanks.
Hello, sorry for the late reply. I had some school matters to resolve and did not have time to check back.
I've read both replies, but I want to make sure if I got their meanings right.

Junilu's reply:
I've thought of that at first, but then for some reason I thought it would be weird to have multiple tables that might contain the same user.
For example, if there is user Foo, which is currently online and in a game, I would have table Accounts, and 2 more tables Game_sessions and Online_Sessions that would have a foreign key to
the user's ID?
Makes sense to me, but these concepts still feel alien to me, and I'd like to know if this kind of approach is normal.

Stephan's reply:
Now I'm confused again.. I've been confused for a time about what "functionally dependent" means and after doing some research I thought it meant something like
"If A determines B, B is functionally dependent to A".
As in, no record with a different A can have the same B for it to be functionally dependent.
Is that not the case? If it is not it makes things much simpler..
And, the argument about online_status was a complete blind spot for me. I will consider a way to not use it.

So, what I probably should be doing is:

Table Account
name(PK),email(Nullable),password,elo

Table Online_sessions (If I do not find a way to not use this)
name(FK)

Table Game_sessions
name(FK),(Not yet defined fields I will use in the actual game)

Table Queue_sessions
name(FK),queue_time

Like, instead of using flags, I can just use the fact that the record exists in a specific table to get the information needed?

Big thanks to both of you.
Hello.  
I have a table "Accounts" which holds records about accounts for a site I have been working on.  
I've recently come across the idea of normalization, and I've been stuck at the process of Second Normalization.  
My table contains fields that are not functionally dependent to the PK, cannot be Superkeys themselves, and cannot be Foreign keys.  
In this situation, how do you decide on where to move these fields?  
Below is the current version of the table in SQL:

name: varchar (PK)
is_guest : tinyint
is_online: tinyint
email: varchar
password: varchar (cyphered before added to DB)
queue_status: tinyint
is_ingame: tinyint
elo: smallint
queue_time: time  

queue_time and queue_status seems easy enough to move to another table. Since they are unique to players currently in a queue, they can be moved to another field.
name, email, password is obvious enough to keep in the same field.  
But what about all the tinyints(Which were supposed to be Booleans)?

I need these informations about the player, but none of the tinyint fields fulfil the constraints of Second normalization, where all the fields need to be functionally dependent to the PK.

So, where do I move these fields? Do I even move them? What kind of problems could I get for not correctly normalizing this table?

Any help is greatly appreciated.


 
Hello. I've been asking a lot of questions about a program I am making in this forum, and I think it is complete.
But since I am who made the code, it probably has a lot of blind points in the design, code, and many more.

How do I look for errors that are not quite obvious like compile or runtime exceptions?
I'd like to know some principles, because my code got huge and separated in many files and is now very difficult to review.

Thanks.
5 years ago
Learned a lot from that one. Going to fix those problems.  
Thanks for the reply.
5 years ago
Alright.  
1. I made the field static, so it can be accessed by the other thread.  
Originally.  
Many sections of my code is becoming unnessesary after changes.  
Probably this is one of them too.  

2. The field I return is a reference to an object.
I was going to say it is immutable, but I did not explicitly make it so.  
It just does not needing to be mutable, because I create an instance, and then just get the data from an external resource.  
Its definitely not primitive, I can say that for sure.
Setter and Login needs Getter.
Browser needs Setter, Login, Getter, and print.

3.I meant to say 'Make the constructor of Class2 recieve an instance of Class1, and store the reference.'
By 'Initiate' I meant 'Set parameters AFTER instantiation, at a convinient timing'.
Which was nessesary, but probably will not be after I clean up the design.  
I thought the method name was accurate because when initiated, it would be considered dormant since it cannot do anything, and then you initialize it by giving the right classes.

4.initiate() is only called on the main method, once per object. The rest is handled by methods inside the FXBasedBrowser.
It does not have circular dependency, but its still quite messy indeed.  

6. I did not multithread it. When I launch the application, JavaFX creates another thread for it to run.
I do not know how to run it in one thread.

Basically, I created 5 interfaces.
Getter gets data from external sources
Setter stores data on external sources
Login is basically a getter, except having a reference to an instance of this object with a valid password gives you access to the methods. Used specifically for logging in.
Browser is the user interface.
The reason, is because I first had to make the core logic work by storing and reading from txt files, and creating a console based browser, where you type commands.
Then when I made MySQL versions of Getter,Setter, and Login, and made the FX version of Browser... Thats where things got messed up.
I'm just making the code work for now. And when it finally works, I will clean up the unnessesary parts.
But maybe that is a bad way to work with a project.
No need to say sorry. These kind of comments makes me realize things I would never do. And if I'm wrong, why should I not be criticized for it?
5 years ago
I kind of knew the jargon was going to be terribly mixed up.  
But about the code. I'm shocked about the amount of errors you found in that tiny snippet, and now I imagine how many is in my whole code...
I think I will check my code again.
Thanks for the reply.

5 years ago
Hello. I have been working on a project of mine, and it also needed to do the same thing you wanted to do.  
This approach is a bit, crude. But it works.  
Probably not the best, but I will post it anyways.  
Hope it helps  
I will reference "the class that holds the field you want to share" as Class1.
The other one, Class2.

1. Make the field you want to share static.
2. Add a Getter to Class1 that gets the field.
3. Add a parameter to Class2, that stores references to Class1.
4. Initiate Class2 inside the code in Class1, pass itself as the parameter(use 'this').
5. Begin running Class2 in another thread
6. Now it has access to Class1, which has a Getter for the field you want to share.

This worked for me when I was using JavaFX. It looks something like:

5 years ago
IT WORKED.
Many, MANY thanks to Knute, for being here from the beginning, and John for the detailed answer and solution.

I will list every change relevant to the solution in case another person gets stuck.
1. Corrected parameters on TableColumns. It is supposed to be <The Data Object Class, the returned variable Class>

2. Naming conventions for PropertyValueFactory is hard to understand, but it is:
exampleProperty <- this is your field
and you need:
getExample()
setExample()
and exampleProperty().

3. Application, while having a name that may look like it is your entire code, is NOT. Application should be a bare boned class just to have launch() include things that your CONTROLLER wants to do before entering passive state (That you have to click or do something in the GUI to activate methods and sections of the code.)
So I created a new class FXBLauncher, just to launch the FXBasedBrowser.
Due to my code needing the reference to every class present inside launch, I used FXMLLoader.setController() to dynamically set the controller.

The reason for this is that I can set the controller to an existing instance of my class, that already Initialized(It takes 4 classes as parameter, and had to be initialized prior to launch.)

Again, MANY thanks to both John and Knute.
I will be marking this thread as solved, and adding a +1 to every single reply.
5 years ago