It is currently 11 Sep 2025, 23:15
   
Text Size

SQLite Data Engine

Post MTG Forge Related Programming Questions Here

Moderators: timmermac, Blacksmith, KrazyTheFox, Agetian, friarsol, CCGHQ Admins

SQLite Data Engine

Postby Krizzen » 20 Jul 2011, 07:43

I'd like to propose a possible storage engine for the massive number of cards this project has to face on a daily basis:

http://www.zentus.com/sqlitejdbc/

Its pretty simple to get up and going. It runs native SQLite engines.

Maybe I'm partial to SQL, but I think it'd be cool to "select * from cards where power > 3 and toughness > 3 and text like '%flying%'"
Krizzen
 
Posts: 7
Joined: 20 Jul 2011, 03:04
Has thanked: 0 time
Been thanked: 0 time

Re: SQLite Data Engine

Postby Snacko » 20 Jul 2011, 10:22

H2 database http://www.h2database.com/html/main.html is a bit more feature rich than sqlite if you don't need compatibility with sqlite dbs.
Snacko
DEVELOPER
 
Posts: 826
Joined: 29 May 2008, 19:35
Has thanked: 4 times
Been thanked: 74 times

Re: SQLite Data Engine

Postby Krizzen » 21 Jul 2011, 02:58

Oh wow, H2 seems very nice! Few projects boast a small footprint and great performance.

As far as implementing such a beast, I've sifted through the code to try to discover how the cards are loaded, stored in memory, then sorted, searched etc. seemingly to no avail. So...

If a database engine into Forge is feasible, I might can be of assistance. So, if it is possible, any pointers to where I can start looking in the code where I can plug an engine in?
Krizzen
 
Posts: 7
Joined: 20 Jul 2011, 03:04
Has thanked: 0 time
Been thanked: 0 time

Re: SQLite Data Engine

Postby zerker2000 » 21 Jul 2011, 04:33

Cards are stored as forge.Card objects, in heap. To 'plug an engine in', one would remove all/most variables (except uniqueNumber) from that class, and point the getter/setter methods to the database.
O forest, hold thy wand'ring son
Though fears assail the door.
O foliage, cloak thy ravaged one
In vestments cut for war.


--Eladamri, the Seed of Freyalise
zerker2000
Programmer
 
Posts: 569
Joined: 09 May 2009, 21:40
Location: South Pasadena, CA
Has thanked: 0 time
Been thanked: 0 time

Re: SQLite Data Engine

Postby zerker2000 » 21 Jul 2011, 04:44

Cards are stored as Card objects, in heap. To 'plug an engine in', one would remove all/most variables (except uniqueNumber) from that class, and point the getter/setter methods to the database.

EDIT:They're loaded in CardFactory.getAllCards, executed at startup. They're grouped/sorted/searched mostly with CardList, which is a wrapper for ArrayList<Card>;
O forest, hold thy wand'ring son
Though fears assail the door.
O foliage, cloak thy ravaged one
In vestments cut for war.


--Eladamri, the Seed of Freyalise
zerker2000
Programmer
 
Posts: 569
Joined: 09 May 2009, 21:40
Location: South Pasadena, CA
Has thanked: 0 time
Been thanked: 0 time

Re: SQLite Data Engine

Postby Krizzen » 21 Jul 2011, 04:53

For some reason I didn't bother to look at CardFactory! Thanks very much!
Krizzen
 
Posts: 7
Joined: 20 Jul 2011, 03:04
Has thanked: 0 time
Been thanked: 0 time

Re: SQLite Data Engine

Postby Rob Cashwalker » 21 Jul 2011, 14:03

There's a lot more to a Card object than just text and numbers, which is where the database could come in handy. The Card object contains ability objects which provide functionality, those abilities are generated during runtime during loading. Those objects couldn't be stored in a database.

Use of a database would streamline display of the deck editor and its filtering features. However it would still need to be populated somewhat dynamically, since the card.txt file can be modified at anytime, and we don't want to maintain a single file with all cards.
The Force will be with you, Always.
User avatar
Rob Cashwalker
Programmer
 
Posts: 2167
Joined: 09 Sep 2008, 15:09
Location: New York
Has thanked: 5 times
Been thanked: 40 times

Re: SQLite Data Engine

Postby zerker2000 » 21 Jul 2011, 14:44

As long as AF abilities include descriptions, would it be feasible to make a "HardcodedAbility", and refactor the cardFactories to use ability text rather than card name? That way, we could load the entire cardsfolder as text for deck editing, but only generate Card objects when we need them (and then store them in a table to avoid redundancy, but it would probably decrease footprint tremendously either way).
O forest, hold thy wand'ring son
Though fears assail the door.
O foliage, cloak thy ravaged one
In vestments cut for war.


--Eladamri, the Seed of Freyalise
zerker2000
Programmer
 
Posts: 569
Joined: 09 May 2009, 21:40
Location: South Pasadena, CA
Has thanked: 0 time
Been thanked: 0 time

Re: SQLite Data Engine

Postby Braids » 23 Jul 2011, 17:33

zerker2000 wrote:Cards are stored as forge.Card objects, in heap. To 'plug an engine in', one would remove all/most variables (except uniqueNumber) from that class, and point the getter/setter methods to the database.
i don't think that is the right approach. we still need Card instances in memory so that they can be differentiated from one another. for example, one card {permanent} has counters on it, and the other does not.

the main features of a relational database are {1} to provide and edit information that is shared among multiple clients, and {2} to provide a powerful query language to as few as one client. i do not think it wise to try to replace Card instances with rows in a table. we have to make them instances at some point in order to manipulate them in the java programming language. pulling them in and out of a database row would add unnecessary complexity and would hamper performance.

i can't think of a good reason why we would be interested in feature {1}. i don't think we want to centralize all oracle card information to a cloud of relational database systems for access by multiple clients. it's easier just to release new batches of card txt files with forge upgrade.

reason {2} would be interesting. we would have the only mtg relational database i know of.

Code: Select all
select name from all_cards
where text like "%enters the battlefield%" and (color = "W" or color = "B");
but how many of our users know how to write sql queries like this? this sounds like it would be more suited as a (very handy) separate web-based service, rather than part of forge itself.

Rob Cashwalker wrote:There's a lot more to a Card object than just text and numbers, which is where the database could come in handy. The Card object contains ability objects which provide functionality, those abilities are generated during runtime during loading. Those objects couldn't be stored in a database.
yes. i agree.

Rob Cashwalker wrote:Use of a database would streamline display of the deck editor and its filtering features. However it would still need to be populated somewhat dynamically, since the card.txt file can be modified at anytime, and we don't want to maintain a single file with all cards.
i don't see much of a point in keeping both a database and a set of txt files around.

the deck editor's filters could be streamlined by moving from CardLists to Generators. if you want proof, try looking up a card by a substring in its name using the Filter menu in the deck editor. it is Blightning fast. beware, it may leave your deck editor in an unresettable state. i would have converted more CardList uses to Generator in there, but the code was very entwined with the CardList implementation in its fields, etc.

i do understand that a deck editor needs to slurp a generator into a CardList at some point in order to be able to do sorting. but if we can apply as many filters as possible before doing that, it would really speed things up.

Edit: as marked.
Last edited by Braids on 23 Jul 2011, 17:38, edited 1 time in total.
"That is the dumbest thing I've ever seen." --Rob Cashwalker, regarding Innistrad double-sided cards. One of the first times he and I have ever agreed on something. ;)
User avatar
Braids
Programmer
 
Posts: 556
Joined: 22 Jun 2011, 00:39
Location: Unknown. Hobby: Driving myself and others to constructive madness.
Has thanked: 1 time
Been thanked: 1 time

Re: SQLite Data Engine

Postby Braids » 23 Jul 2011, 17:37

zerker2000 wrote:As long as AF abilities include descriptions, would it be feasible to make a "HardcodedAbility", and refactor the cardFactories to use ability text rather than card name? That way, we could load the entire cardsfolder as text for deck editing, but only generate Card objects when we need them (and then store them in a table to avoid redundancy, but it would probably decrease footprint tremendously either way).
i tried to do something like this when i implemented the lazy CardFactory.

the main problem is that CardFactory has some insane magick Sleight of Mind inside it. it actually keeps two databases of card instances. one set (forge.CardFactory.allCards) has all of the abilitiies attached, and are owned by the HumanPlayer. the other set (forge.CardFactory.map) has no abilities and no owner, but its contents serve as templates for the first set. not understanding these nuances is probably what caused my lazy CardFactory effort to fail.

Edit: as marked.
"That is the dumbest thing I've ever seen." --Rob Cashwalker, regarding Innistrad double-sided cards. One of the first times he and I have ever agreed on something. ;)
User avatar
Braids
Programmer
 
Posts: 556
Joined: 22 Jun 2011, 00:39
Location: Unknown. Hobby: Driving myself and others to constructive madness.
Has thanked: 1 time
Been thanked: 1 time

Re: SQLite Data Engine

Postby zerker2000 » 23 Jul 2011, 21:12

Well yes, and if we wanted to axe the loading of every card at runtime, we'd have to get rid of both, and move readCards to the deck editor.
O forest, hold thy wand'ring son
Though fears assail the door.
O foliage, cloak thy ravaged one
In vestments cut for war.


--Eladamri, the Seed of Freyalise
zerker2000
Programmer
 
Posts: 569
Joined: 09 May 2009, 21:40
Location: South Pasadena, CA
Has thanked: 0 time
Been thanked: 0 time

Re: SQLite Data Engine

Postby Braids » 23 Jul 2011, 21:20

zerker2000 wrote:Well yes, and if we wanted to axe the loading of every card at runtime, we'd have to get rid of both, and move readCards to the deck editor.
deferring the loading of all cards until they were actually needed is in reality not that helpful. just about everything except playing constructed matches with specific or random (but not randomly generated) decks requires all cards to be loaded into memory. so for standard Forge usage, there is little point.

however, for writing unit tests, it would make test execution much faster. i intend to write a separate CardFactory that lazily loads cards for this very purpose.

edit: minor rewording.
"That is the dumbest thing I've ever seen." --Rob Cashwalker, regarding Innistrad double-sided cards. One of the first times he and I have ever agreed on something. ;)
User avatar
Braids
Programmer
 
Posts: 556
Joined: 22 Jun 2011, 00:39
Location: Unknown. Hobby: Driving myself and others to constructive madness.
Has thanked: 1 time
Been thanked: 1 time

Re: SQLite Data Engine

Postby zerker2000 » 23 Jul 2011, 21:51

Right, except we don't actually need "fleshed out" cards anywhere except play, do we? Also, looking through the code, I don't see any abilities/owner being added to allCards cards. Is that actually the case?
As for unit tests, moving readCards anywhere outside the CardFactory constructor should work, at least if we make a static AllZone.ReadCard(why isn't that class named CardReader, by the way?), and remember to call it if we do need to.
O forest, hold thy wand'ring son
Though fears assail the door.
O foliage, cloak thy ravaged one
In vestments cut for war.


--Eladamri, the Seed of Freyalise
zerker2000
Programmer
 
Posts: 569
Joined: 09 May 2009, 21:40
Location: South Pasadena, CA
Has thanked: 0 time
Been thanked: 0 time

Re: SQLite Data Engine

Postby Braids » 23 Jul 2011, 22:31

zerker2000 wrote:Right, except we don't actually need "fleshed out" cards anywhere except play, do we?
`
you're almost right about "fleshed out" cards only being needed in games. not in play which is an old synonym for on the battlefield. at other times, we just need their oracle/printed attributes. i now see that differentiating between these two uses of the term {card} is very important. this could explain why CardFactory contains two lists. nice find! :)

zerker2000 wrote:Also, looking through the code, I don't see any abilities/owner being added to allCards cards. Is that actually the case?
`
src/forge/CardFactory.java, lines 104-107:
Code: Select all
            while (it.hasNext()) {
                c = getCard(it.next().toString(), AllZone.getHumanPlayer());
                allCards.add(c);
            }
the javadoc for getCard clearly states that it sets the card's owner. you'll have to take it on faith that it also adds abilities. :)

zerker2000 wrote:As for unit tests, moving readCards anywhere outside the CardFactory constructor should work, at least if we make a static AllZone.ReadCard(why isn't that class named CardReader, by the way?), and remember to call it if we do need to.
`
i don't want to move readCards. i prefer to write a separate LazyCardFactory class. the last time i tried to edit CardFactory to make it lazy, i broke Forge in unexpected and quizzical ways.

yes, ReadCard should be named CardReader, but i didn't feel like refactoring it when i was last modifying it.

the depth of your analysis begs the question. are you volunteering for any of this?

edit: formatting changes.
"That is the dumbest thing I've ever seen." --Rob Cashwalker, regarding Innistrad double-sided cards. One of the first times he and I have ever agreed on something. ;)
User avatar
Braids
Programmer
 
Posts: 556
Joined: 22 Jun 2011, 00:39
Location: Unknown. Hobby: Driving myself and others to constructive madness.
Has thanked: 1 time
Been thanked: 1 time

Re: SQLite Data Engine

Postby zerker2000 » 23 Jul 2011, 23:26

Ah, they were being passed through getCard. Do we actually need to do that? The way I see it, the only thing needed outside the game(and that may exclude libraries) is oracle text(and other characteristics), and that should be parseable in ReadCard using Description tags. Even if we don't want to create a separate UnparsedCard class, I'm fairly certain that could be added to Card as a boolean, and checked in e.g. DefaultPlayerZone.add.
By "fleshed out" cards I meant Card Objects, in the MTG Rulebook sense, but yes, the existence of hand/grave abilities does require slightly earlier parsing.
And finally, I'm not quite sure if I am volunteering for anything, but I may indeed have a decent amount of free time within the next month.
O forest, hold thy wand'ring son
Though fears assail the door.
O foliage, cloak thy ravaged one
In vestments cut for war.


--Eladamri, the Seed of Freyalise
zerker2000
Programmer
 
Posts: 569
Joined: 09 May 2009, 21:40
Location: South Pasadena, CA
Has thanked: 0 time
Been thanked: 0 time

Next

Return to Developer's Corner

Who is online

Users browsing this forum: No registered users and 35 guests

Main Menu

User Menu

Our Partners


Who is online

In total there are 35 users online :: 0 registered, 0 hidden and 35 guests (based on users active over the past 10 minutes)
Most users ever online was 7967 on 09 Sep 2025, 23:08

Users browsing this forum: No registered users and 35 guests

Login Form