Open hallister opened 11 years ago
It's my understanding that with using SQLAlchemy as an ORM, we don't need to worry about IDs (and in fact we shouldn't ever need to know a specific ID), since it returns to us our own defined objects, which can be passed around in Python, and have normal Pythonic attributes and methods available for use. Let me know if I'm misunderstanding it.
Let me mull this over for a bit and I'll let you know how I'm feeling about it tomorrow.
@andschwa I spoke with you earlier but now I see what you are asking, I'll try to explain. For anyone else reading this, I use key/id interchangeably since they are the same thing. An "id" is a unique identifier we use in programming, a key (specifically a primary key) is a unique id for an entry in a database.
We have a number of ways we could actually implement this:
However, what we won't do is pass around the ORM objects we are creating via SQLAlchemy. The reason for this is fairly straight forward: the client doesn't get to have access to the database. Only the backend can.
Remember, the backend is responsible for validating two types of constraints:
If we pass around ORM objects, that means the client has DIRECT access to the database. That's unacceptable.
That said, if people are interested in implementation, I'll give you all 2 options:
import event
def callback(conn, message, ident):
print ("Got message: " + message + " from " + ident)
action = event.Action('localhost', 4000, callback)
action.move(character_id='2', location_id='3')
More OOPish:
import unit
character = unit.Character()
character.move(3)
# callback is handled internally as Character extends the object that handles callbacks.
Most would probably prefer the OOP version, however, it complicates the initial game setup (by complicate I mean I'm going to have to spend a lot more time thinking about it :tongue:).
--NOTE--
Client and AI team should decide their preferred style.
The server team implements, but never uses this code.
The first option is exactly what I thought we were going to implement and that is what the client team has been expecting. That the ID system will work something like this:
ObjectType gets a Key:
Characters->corresponding character's name
Military->ID #. Specific unit #
(Ex: In game there are 5 Imperial militia (ID=4). To send a call about unit 3 we use callback(conn, move, 4.3))
Mission->Key (ie: "Scavenge for resources" has a unique key=G)
This is just an example and not the actually ID list.
The second option does look like a contender as well, but as @hall5714 said, it requires more thinking....
Hey, coming in as a Python programmer, the second version (OOP style) is really the easiest way to implement this in Python. I'm working out an architecture on my whiteboard right now.
@andschwa Awesome! @harr6176 liked the oop style too. And I think it will actually be less "work" the backend has to do. We are going to talk a little about this in a client team meeting today. Hopefully we will have a consensus at that point.
The API was discussed today during the Client Team meeting and it looks like we are leaning toward more functional. So the first option is Client Teams vote.
How is the first one functional programming?
@andschwa I think what she was trying to say is that she prefers the more function based method calls (procedural approach) rather than the methods on class instances (oop approach).
Regardless, what you said earlier about the second version being "easier to implement" isn't true.
For example, the implementation I have now is using the first example. I don't have to implement action.move at all, I simply implement a method override on the action class, so that when any function is called it's value is sent back to the server. I then use an ActionHandler() class which says that a restriction on "move" is that only stacks can do it. So I select the stack_id that's sent along with the move request from the database, and if that stack doesn't exist (or isn't specified) I send back an error.
Compare that to having a Stack class, which both Character and Military extend. The stack class itself will need the exact same internal methods (like _move, _combat, etc) to send back to the server. That is actually really neat, and really workable, but ONLY if those classes can also be represented as sprites for the Client team (which they can't).
Bottom line: OOP ALWAYS requires more code than a functional equivalent, and thus (by definition) its implementation can never be simpler.
I would disagree. If by "more function based method calls" we mean a procedural approach, then no, OOP will be simpler as it helps to enforce DRY, which procedural absolutely violates.
Also, why can't the client team take a class and do a lookup on it to retrieve the sprite? This would be implemented simpler in interface.display(object). The display method of the interface will grab the information it needs from the object (that is, what it is, what it has), and find its corresponding sprite. Really this would be wrapped a couple times, say to display the map, and then subsections of the map calling similar methods on what they contain (planets, environs, etc.).
Where is the client team's graphics code? I'd like to see what they've already implemented so I can know the best way to go about integrating with it.
We're not writing a state based game using a functional or procedural programming paradigm. Object-oriented is by far the most appropriate design for a turn-based strategy game. If anyone disagrees, please let me know why a game of objects maps better to a non OO design. I think Dr. J would laugh at us if we turned in a procedural or functional program in Python for a game.
@andschwa By "more function based method calls" I mean exactly as displayed in my first example. That also happens to be the way I implemented this in code. Which means an Action class which has method overrides for various actions that can occur on the board. This is still very much OOP, and that should be clear to even a novice programmer from my examples. One certainly "looks" more OOPish than the other, but that isn't the case (again, the examples make that very clear).
So no one is advocating any one particular programming paradigm.
I want to be clear on this, so as not to confuse anyone. If the second example is chosen, it will be nothing more than an abstract of the first example. The implementation needs to stay the same, but instead of having one event.Action
class we will have action.Character
and action.Unit
and action.Planet
which will all subclass from a slightly different implementation of event.Action()
.
As for looking at the client team's code, to be blunt, why? You are currently working on the ORM implementation. The ORM is used by the backend server when an action is called. I'm currently working on the backend. Your implementation of the ORM should have NO bearing on what the client team's graphics code looks like at all.
Could you please clarify what you mean by "functional"? Because as I understand it, functional programming means more mathematical evaluation and no state or mutable variables, and so I don't understand what you're trying to display with your example. (Also, your example looks like something straight out of a web app, which would be directly dealing with the database and so have a notion of object IDs etc., but I thought we wanted to abstract that out.) I wish to communicate effectively and contribute to this project, so I appreciate your input.
[Edit: trying to sound constructive here, not mean]
The fact that we still, as far as I know, don't have a definite relationship between the client and server and AI and server finalized yet, is scary. We were still talking about the issue at the last client meeting Saturday. That is something that should have been done a month ago, two months ago. We need that exact relationship between everything finalized, before we can finish the API. I don't have the answers, but I think I should say something and try to get us focused on the main goal, the game. This is my suggestion.
I favor making the server do all the rule checking and telling the client yes or no. Whatever. Let's get a design document or something published on it, so we are programming this thing with focus.
@cawaltrip Maybe I am wrong, but I think the AI team would like a way to get the state. They want a way to get information. State in -> Decision out. From my discussion with Jordan.
@mein1156 et al. Honestly, AI just needs data. The calls we're making to perform the actions will (should) be the same as the calls that the Client will be making to perform those same actions. The only real difference is we don't need to be able to see the beautiful handiwork that they are working on since it'll just be data for us.
As for what we need to make an "intelligent" decision. That would be everything. To make a good decision, the AI will have to know the current state of the game (whose turn, loyalty of every planet, game turn, # of units around, etc). I'm sure that data will be given to the client as well, so in the end we just need what everyone else does
@leit7193 Do you mean that you want to get the entire state of the game whenever you ask for it, or will you hold the at least what you know to have been the state of the machine and then wait to get updates to that information like I'm guess the client will do?
@mein1156 I don't know how we're planning on giving out the data that everyone needs currently. Basically, the AI is going to need everything that the human can see in order to be able to make its decision. Whether that comes in the form of a series of calls or one enormous call isn't a big deal. Parsing the data shouldn't be the server's job, but we do have to have the data.
@andschwa Instead of me trying to clarify what I mean, I think the best way to go forward is for you to explain exactly what problem you have with the first example. I'm not sure at this point why this is even an argument.
@mein1156 @leit7193 I have a complete implementation of a framework which allows for calling the API. Move works and responds. However after 4 days of this being open, no one has contributed to it. The data will be in the form of a simple dictionary that states the changes of a particular action.
Again, I was hoping to get more feedback on the API before I started implementing but I am just going to go for it tomorrow. As I begin implementing, I'll return "dummy data" for now and we'll just add an API as we go.
Now for specific things:
"The fact that we still, as far as I know, don't have a definite relationship between the client and server and AI and server finalized yet, is scary"
We do. I have entirely implemented the network communication protocol for this. Now we only need to know what the API is.
"That is something that should have been done a month ago, two months ago."
Doing implementation 2 months ago would have broken the entire cycle Dr. J wanted us to do, so I disagree.
"Let's get a design document or something published on it, so we are programming this thing with focus."
To an extent that's what this is. We drastically need people to contribute to it however.
"Whether that comes in the form of a series of calls or one enormous call isn't a big deal. Parsing the data shouldn't be the server's job, but we do have to have the data."
It will be via the API that this issue is about, so a series of calls. The Server will be exposing a single API which both the client and AI will need to use.
I'll have more code tomorrow to give this some direction.
@hall5714 Justin, you have shared no code to date to the server-team's repo save some empty init files. If you have code, it is not in a place any of us have been able to find it, and therefore have not been able to use it or even have an idea about what you're doing.
My problem with the first example is that it will be more difficult to implement as this project moves along, as it doesn't abstract out the database data.
All: I pushed code earlier this weekend representing a basic framework model for how this game can be put together. Please pull, branch, review and make changes as you see fit and necessary, and push back. We have a start, let's get rolling.
@hall5714 It will be via the API that this issue is about, so a series of calls. The Server will be exposing a single API which both the client and AI will need to use.
Perfect! I can't wait to use it! Thanks!
@hall5714 Sorry, I didn't mean implementation, I meant design. I think I misunderstood you, did you want suggestions on modifying the API you designed or suggestions on expanding the API you wrote or both? I thought you meant the former.
@andschwa No, I haven't pushed my code because I wasn't ready to. That said, I'm not sure what your interest in my code is given that your responsibility is the ORM, and as far as I know, you haven't implemented any of that yet. I'm working on the Server which depends on the ORM. The ORM does not depend on anything else, so you can work on that regardless of how I implement the Server.
Your "problem" is non-sense. How in the world did you determine I'm not abstracting the database out?
To be clear: The network communication layer is already done. When a client wants to commit an action it will call an Action.move() as stated in the first example. When it does that a message is stringifyed, byte-encoded, sent over the network to the server, which parses the request. Up to that point is implemented. The next phase will be taking the parsed input, modifying the database and updating the client (and it's opponent) with the new state.
For the record, the code you pushed was nothing but a bunch of pseudo-methods for classes that don't exist. You haven't worked closely with either the client team or on the network communication, but you are writing pseudo classes for both. What we REALLY need from you Andy is the actual ORM for the database. That is what you are supposed to be working on, is it not?
@mein1156 Actually the suggestions I could REALLY use is on the API itself. The top post on here has a few API calls that we could use, but there are (obviously) many missing. I was hoping to design the API first before implementing one of the methods, but as it turns out that may not be particularly useful. I'll have some code up for you guys to review tomorrow.
@hall5714 Ok, that's good to know we have the relationship defined, I won't be scared anymore about that. I'll try and think of some stuff to add to the API today. Related questions, how do you imagine dealing with issues that the client has to do in response to something happening, for example, when does the defender get to choose to try and flee? Does the server ask first, or the client just ask? How do you imagine this happening?
Sorry if I sounded like a jerk yesterday all. I've been battling a flu since Sunday so I'm a bit cranky :tongue:. I won't be in class since I don't feel like sharing this with anyone, but I will still have the code up today.
It’s all right, I’ve come down with a cold and just slept through half the day today.
It really will be great to see the code that currently makes up the project, so I’m not just programming blind. I started a SQLAlchemy skeleton using Robert’s RFC the other day, but it’s not very useful without knowing what I have to integrate with, since there’s many different ways to set it up, and the best way will depend on what it has to work with. It’s frustrating being asked to program a piece of a backend that’s apparently mostly written, when I can’t see what abstraction layers we already have, and how the client and server are to communicate. Since the repository has been empty, it’s hard to know what to do. When do you think you can get your code up?
On Nov 5, 2013, at 8:51 AM, Justin Hall notifications@github.com wrote:
Sorry if I sounded like a jerk yesterday all. I've been battling a flu since Sunday so I'm a bit cranky . I won't be in class since I don't feel like sharing this with anyone, but I will still have the code up today.
— Reply to this email directly or view it on GitHub.
https://github.com/hall5714/Freedom-Galaxy/
Checkout the event_queue branch.
@andschwa You shouldn't be integrating at all. The ORM is the core of the server, so we implement that and my event_queue and server will both operate off of that. The first thing that needs to be done is the database. If you have questions let me know.
@hall5714 The event_queue code looks cool enough, if I understood it correctly, it has incoming and outgoing queues for the server, to handle actions sent to it by the clients.
We should all be integrating, that's what collaborative coding is. My first question still is: where's the ER diagram? At this point I'm just going off the data files and developing it from there.
@hall5714 In terms of combat and missions, here is one of my suggestions based off of my interpretations of the rules. Tell me if this is what you were looking for. I have more.
I'll ignore the difference between the two types of calls here.
As far as the client or AI initialing combat, they have three choices: Environ, PDB, or Character Combat. The PDB combat is a reaction to a movement into the orbit box or in the star system game, moving off the planet or using a starship to move from environ to environ on the planet. So, that combat will have to be a reaction to the phasing player's action. I'll assume that is already taken care of.
combat(location_id) | For Environ (aka military unit combat) Combat combat(location_id, defending_group_id) | For PDB attack combat(attacking_group_id, defending_group_id, location_id, type, intention) | For Character Combat
Environ combat occurs between all military units in the same environ (plus leaders)[10.1](so we don't need to specify the units?).
However, in the case of searching for example, one out of multiple groups can be targeted for attack and one stack of characters is chosen to attack, so I put an attacking_group_id and an defending_group_id field in there. Character Combat requires two choices, "firefight" or "hand-to-hand" and "capture" or "kill" (type is a reserved work though).
Fleeing might be: flee() This might require no arguments since only one combat can occur at a time in the game. However, this call can only occur at a specific time during the combat round so the player needs to somehow be a where of that opportunity.
Continuing with searching API:
search(group_id, location_id) where group_id is a stack of the non-phasing player's search "squad".
If the search is successful, the searching player has a one-time opportunity to attack the found group. Not sure how that is planning on being incorporated into the API.
Here is a preliminary that we worked on that is focused on movement, missions and combat and isn't exhaustive.
move(stack_id, destination_id)
assign(stack_id, mission)
complete_mission(environ_id) -- this would be per action event we think
search(stack_id)
combat(attacker_id, defender_id, option_list)
activate_characters(* characters)
deactivate_characters(* characters)
combine_stack(stack_id, stack_id)
break_stack(unit_id) -- remove an individual unit from a stack
I have successfully implemented a prototype of the underlying network communication, it's time to develop the grammar rules for our language. We need as much input as possible from all teams on this, as this is our form of communication between parts. If you have a suggestion or a suggested change, speak up!
Keys
Methods