I'd prefer Method 2. It's flexible and can be implemented fairly easy.
The idea is to split the complex condition into a tree of simple ones. Each node of the tree is a comparison function and the leaves are either references to the user data or threshold values.
So your "Need min 100 gold" are going to look like
greater
+-gold
+-999
or in JSON
"greater":{"attribute":"gold", "value":999}
but, using keys as function references have it's downsides: for example, you can't make an array of conditions. Therefore it would be better to make a condition object, like this:
{
"type": "greater",
"arguments": {
"attr":"gold"
"value":999
}
}
using structures like this, you can build complex conditions just by introducing functions "every" and "some", which will return true when every or some conditions are true accordingly (and that is where we need an array of conditions).
So your initial condition may be rewritten as
const enough_gold = {
"type": "greater",
"args": {"attr": "gold","value": 999}
}
const lvl_ten_plus = {
"type": "greater",
"args": {"attr": "level","value": 9}
}
const have_item = {
"type": "have",
"args": {"attr": "item","value": "item_name"}
}
const compl_event = {
"type": "have",
"args": {"attr": "event","value": "event_name"}
}
const new_event = {
"type": "all",
"args": [
enough_gold,
lvl_ten_plus,
have_item,
compl_event
]
}
the data for testing this condition may look like
{
"gold": 8350,
"level": 11,
"item": ["item1", "item3"],
"event": ["some_event", "another_event"]
}
I switched to js to make it more readable and to show how you can nest conditions. I also introduced "have" function - this will iterate an array-attribute and return true if it includes provided value.
You can store those condition sets in file or database. In the latter case, it would be better to store each condition as a separate record and reference from complex ones to the simple ones. This will allow you to reuse some conditions and make balancing and patching easier.
I have no experience with MongoDB, but from what I read it will be perfect for this job.
Oh, and once you've extracted condition tree, you will know exactly which player attributes you'll need for the test, so you won't have to extract everything. Just in case.
Not that long ago I wrote a small condition-solver lib just for fun and maybe cases like this. It allows for creating nested conditions and testing them against some data set. Solver class is about 50 lines long (indents, comments and debug method included) and pretty simple, so I guess, there would be no problems porting it to ruby or PHP or any other language as long as there are hash tables and function pointers. The idea is simple as well: it will recursively call specified function for the specified arguments. And it's realy simple to use, here's an example
// Creating a solver with some initial data
const sol = new Solver({
money: 30,
fame: 25
})
// Creating some conditions
// have more than 50 money
const rich = cnd(
'gt',
arg(
'money',
50
)
)
// have more than 15 fame
const good = cnd(
'gt',
arg(
'fame',
15
)
)
// have at least something
const well = cnd(
'any',
[
rich,
good
]
)
// let's try it
sol.is(rich) // false: "money" is not > 50 (30)
sol.is(good) // true: "fame" is > 15 (25)
sol.is(well) // true: he's not rich, but he's good at least
Here's the source code link if it's relevant.
As for status bonuses, try looking at this answer it shows how you can implement them with MongoDB (and likes), and this one uses more traditional RMDBS approach.