diff --git a/configs/config.json.optimizer.example b/configs/config.json.optimizer.example
index b5dab91231..f322ad81a6 100644
--- a/configs/config.json.optimizer.example
+++ b/configs/config.json.optimizer.example
@@ -19,35 +19,31 @@
"groups": {
"gym": ["Dragonite", "Snorlax", "Lapras", "Arcanine"]
},
- "keep": [
+ "rules": [
{
"mode": "by_family",
"top": 1,
- "sort": [{"iv": 0.9}],
- "evolve": true,
- "upgrade": false
+ "sort": ["iv"],
+ "evolve": {"iv": 0.9}
},
{
"mode": "by_family",
"top": 1,
- "sort": [{"ncp": 0.9}],
- "evolve": true,
- "upgrade": false
+ "sort": ["ncp"],
+ "evolve": {"ncp": 0.9}
},
{
"mode": "by_family",
"top": 1,
- "sort": ["cp"],
- "evolve": false,
- "upgrade": false
+ "sort": ["cp"]
},
{
"mode": "by_family",
"names": ["gym"],
"top": 3,
- "sort": [{"iv": 0.9}, {"ncp": 0.9}],
- "evolve": true,
- "upgrade": true
+ "sort": ["iv", "ncp"],
+ "evolve": {"iv": 0.9, "ncp": 0.9},
+ "upgrade": {"iv": 0.9, "ncp": 0.9}
}
]
}
diff --git a/docs/pokemon_optimizer.md b/docs/pokemon_optimizer.md
index c7183d1958..66f9c93f34 100644
--- a/docs/pokemon_optimizer.md
+++ b/docs/pokemon_optimizer.md
@@ -17,14 +17,16 @@
- [upgrade](#upgrade)
- [upgrade_level](#upgrade_level)
- [groups](#groups)
- - [keep](#keep)
- - [mode](#keep-mode)
- - [names](#keep-names)
- - [top](#keep-top)
- - [sort](#keep-sort)
- - [evolve](#keep-evolve)
- - [Examples of configuration](#examples-of-configuration)
+ - [rules](#rules)
+ - [mode](#rule-mode)
+ - [names](#rule-names)
+ - [top](#rule-top)
+ - [sort](#rule-sort)
+ - [keep](#rule-keep)
+ - [evolve](#rule-evolve)
+ - [upgrade](#rule-upgrade)
- [Eevee case](#eevee-case)
+- [FAQ](#faq)
# About
The Pokemon Optimizer manage transfer, evolution and upgrade of your Pokemon.
@@ -60,35 +62,31 @@ There is only one pass at each action.
"groups": {
"gym": ["Dragonite", "Snorlax", "Lapras", "Arcanine"]
},
- "keep": [
+ "rules": [
{
"mode": "by_family",
"top": 1,
- "sort": [{"iv": 0.9}],
- "evolve": true,
- "upgrade": false
+ "sort": ["iv"],
+ "evolve": {"iv": 0.9}
},
{
"mode": "by_family",
"top": 1,
- "sort": [{"ncp": 0.9}],
- "evolve": true,
- "upgrade": false
+ "sort": ["ncp"],
+ "evolve": {"ncp": 0.9}
},
{
"mode": "by_family",
"top": 1,
- "sort": ["cp"],
- "evolve": false,
- "upgrade": false
+ "sort": ["cp"]
},
{
"mode": "by_family",
- "names": ["gym"],
"top": 3,
- "sort": [{"iv": 0.9}, {"ncp": 0.9}],
- "evolve": true,
- "upgrade": true
+ "names": ["gym"],
+ "sort": ["iv", "ncp"],
+ "evolve": {"iv": 0.9, "ncp": 0.9},
+ "upgrade": {"iv": 0.9, "ncp": 0.9}
}
]
}
@@ -115,6 +113,7 @@ Enable or disable the task.
| `min_slots_left` | `[0-N]` | `5` |
The Pokemon Optimizer will be triggered when you have that number (or less) empty slots in your Pokemon Bag.
+
If this number is higher than your total bag capacity, the Pokemon Optimizer will run each time there is a Pokemon to either transfer, evolve or upgrade.
[[back to top](#pokemon-optimizer)]
@@ -125,7 +124,7 @@ The Pokemon Optimizer will be triggered when you have that number (or less) empt
The `transfer` parameter activate or deactivate the transfer of Pokemon.
-At `true`, you allow the Pokemon Optimizer to transfer every Pokemon that are not good enough to be kept according to your own criteria.
+At `true`, you allow the Pokemon Optimizer to transfer every Pokemon that are not good enough to be kept according to your criteria.
At `false`, and regardless of other parameters, no Pokemon is ever going to be transfered.
Note that, whatever is the value you choose to give to that parameter, you will still see logs explaining which Pokemon are transfered.
@@ -161,10 +160,9 @@ This is the maximum time to wait after transferring a Pokemon.
The `evolve` parameter activate or deactivate the evolution of Pokemon.
-At `true`, you allow the Pokemon Optimizer to evolve every Pokemon that are the best according to your own criteria.
+At `true`, you allow the Pokemon Optimizer to evolve every Pokemon that is meeting the evolution criteria.
You also allow it to evolve lower quality Pokemon when [`evolve_for_xp`](#evolve_for_xp) parameter is `true`.
At `false`, and regardless of other parameters, no Pokemon is ever going to be evolved.
-
`evolve` parameter can be deactivated separately for each rule (see [`evolve`](#keep-evolve)).
Note that, whatever is the value you choose to give to that parameter, you will still see logs explaining which Pokemon are evolved.
The purpose of this is to show you what choices are made by the Pokemon Optimizer.
@@ -189,7 +187,7 @@ This is the duration of the evolution animation and time to wait after performin
|-----------------|-----------------|---------|
| `evolve_for_xp` | `true`, `false` | `true` |
-Let you choose if you want the Pokemon Otimizer to use your candies to evolve low quality Pokemon.
+Let you choose if you want the Pokemon Optimizer to use your candies to evolve low quality Pokemon.
Better quality Pokemon have priority for evolution and the Pokemon Optimizer will never evolve for xp if a better Pokemon is waiting for candies to evolve.
These low quality Pokemon will only be used if you have plenty of candies left after evolving your best Pokemon.
@@ -223,7 +221,7 @@ At `true`, no evolution will be performed unless we have an available lucky egg
|------------------------------|-----------------|---------|
| `evolve_count_for_lucky_egg` | `[0-N]` | `80` |
-If you allow the Pokemon Optimizer to use a lucky egg, this parameter let you define the minimum number of Pokemons that must evolve when using a lucky egg.
+If you allow the Pokemon Optimizer to use a lucky egg, this parameter let you define the minimum number of Pokemon that must evolve when using a lucky egg.
If a lucky egg is available, the Pokemon Optimizer is going to wait that number is reached to perform evolution.
If you do not have any available lucky egg, the Pokemon Optimizer will ignore this parameter and evolution will be performed without lucky egg.
@@ -249,11 +247,10 @@ Define whether you allow the Pokemon Optimizer to use a lucky egg before evolvin
The `upgrade` parameter activate or deactivate the upgrade (power-up) of Pokemon.
-At `true`, you allow the Pokemon Optimizer to upgrade every Pokemon that are the best according to your own criteria.
+At `true`, you allow the Pokemon Optimizer to upgrade every Pokemon that is meeting the upgrade criteria.
If `evolve` is also activated, evolution has priority over upgrade.
Which means that the Pokemon Optimizer is going to wait that a Pokemon is fully evolved before upgrading it.
At `false`, and regardless of other parameters, no Pokemon is ever going to be upgraded.
-
`upgrade` parameter can be deactivated separately for each rule (see [`upgrade`](#keep-upgrade)).
Note that, whatever is the value you choose to give to that parameter, you will still see logs explaining which Pokemon are upgraded.
The purpose of this is to show you what choices are made by the Pokemon Optimizer.
@@ -295,7 +292,7 @@ The higher the level is, the more costly in candies and stardust it becomes to u
| `groups` | (see below) | `{}` |
You can define `groups` of Pokemon to help you restrict rules to a specific set of Pokemon.
-
You can then use these `groups` names in the [`names`](#keep-names) parameter of your rule to refer to list of Pokemon
+
You can then use these `groups` names in the [`names`](#rule-names) parameter of your rule to refer to list of Pokemon
`groups` are list of Pokemon names:
```
@@ -308,15 +305,15 @@ You can define `groups` of Pokemon to help you restrict rules to a specific set
```
A same Pokemon name can appear in different `groups`. And `groups` may reference each others.
-
Just like [`names`](#keep-names), you can also negate a group by preceding its name by a `!` or `-`.
+
Just like [`names`](#rule-names), you can also negate a group by preceding its name by a `!` or `-`.
Including `groups` and negating others allow you to create group unions and/or intersections.
[[back to top](#pokemon-optimizer)]
-### keep
+### rules
| Parameter | Possible values | Default |
|-----------|-----------------|-------------|
-| `keep` | (see below) | (see below) |
+| `rules` | (see below) | (see below) |
This parameter is a list that contains as many element as you want.
Each element of that list define a rule that select what Pokemon are the best.
@@ -326,17 +323,38 @@ The conjunction of all rules define the list of all Pokemon to keep.
Every Pokemon not selected is candidate for transfer.
```
-[
- {"mode": "by_family", "top": 1, "sort": [{"iv": 0.9}], "evolve": True, "upgrade": False},
- {"mode": "by_family", "top": 1, "sort": [{"ncp": 0.9}], "evolve": True, "upgrade": False},
- {"mode": "by_family", "top": 1, "sort": ["cp"], "evolve": False, "upgrade": False},
- {"mode": "by_family", "top": 3, "names": ["gym"], "sort": [{"iv": 0.9}, {"ncp": 0.9}], "evolve": True, "upgrade": True}
+"rules": [
+ {
+ "mode": "by_family",
+ "top": 1,
+ "sort": ["iv"],
+ "evolve": {"iv": 0.9}
+ },
+ {
+ "mode": "by_family",
+ "top": 1,
+ "sort": ["ncp"],
+ "evolve": {"ncp": 0.9}
+ },
+ {
+ "mode": "by_family",
+ "top": 1,
+ "sort": ["cp"]
+ },
+ {
+ "mode": "by_family",
+ "top": 3,
+ "names": ["gym"],
+ "sort": ["iv", "ncp"],
+ "evolve": {"iv": 0.9, "ncp": 0.9},
+ "upgrade": {"iv": 0.9, "ncp": 0.9}
+ }
]
```
[[back to top](#pokemon-optimizer)]
-#### keep mode
+#### rule mode
| Parameter | Possible values | Default |
|-----------|--------------------------------------------|---------------|
| `mode` | `"by_pokemon"`, `"by_family"`, `"overall"` | `"by_family"` |
@@ -356,7 +374,7 @@ A family is the group of a Pokemon with all its evolutions.
[[back to top](#pokemon-optimizer)]
-#### keep names
+#### rule names
| Parameter | Possible values | Default |
|-----------|-----------------|--------------------------|
| `names` | list of strings | `[]` = All Pokemon names |
@@ -366,13 +384,13 @@ The `names` allow you to restrict a rule to a selected set of Pokemon.
You can negate a name by preceding it by a `!` or `-`. In that case, the rule apply to all except the negated names.
You can combine Pokemon names and group names together in the same list.
-By default, rules apply to all Pokemons.
+By default, rules apply to all Pokemon.
- In `by_family` mode, if a Pokemon name is present in the `names` list, it refer to all Pokemon in that Pokemon family.
- In `overall` mode, the `names` list behave as a filter on the whole Pokemon bag.
[[back to top](#pokemon-optimizer)]
-#### keep top
+#### rule top
| Parameter | Possible values | Default |
|-----------|-----------------------|---------|
| `top` | `0`, `]0-1[`, `[1-N]` | `0` |
@@ -394,13 +412,14 @@ This value define how many Pokemon, at the top of your selection, you wish to ke
[[back to top](#pokemon-optimizer)]
-#### keep sort
+#### rule sort
| Parameter | Possible values | Default |
|-----------|-----------------|---------|
| `sort` | (see below) | `[]` |
Define according to which criteria you want to sort your Pokemon.
-
Available criteria are:
+
+###### Available criteria
| Criteria | Description |
|----------------------|------------------------------------------------------------------------------|
@@ -423,125 +442,161 @@ Define according to which criteria you want to sort your Pokemon.
| `hp_max` | max health points |
You can put multiple criteria in the list by separating them by a comma: `"sort": ["iv", "cp"]`
-
If multiple criteria are present, Pokemon will be ranked according to the first, then if equals the second, etc...
+
If multiple criteria are present, Pokemon will be ranked according to the first criteria, then, if equals, to the second criteria, etc.
-In addition to define sorting criteria, the `sort` list may contain minimum requirements for evolution and upgrade:
-- `"top": 1, "sort": ["iv"], "evolve": True` will rank Pokemon by `iv`.
-
It will keep and evolve the best of them.
-- `"top": 1, "sort": [{"iv": 0.9}], "evolve": True` will rank Pokemon by `iv`.
-
It will keep the best of them and evolve it only if its `iv` is greater than `0.9`.
-- `"top": 3, "sort": [{"iv": 0.9}, {"cp": 1200}], "evolve": True` will rank Pokemon by `iv` and then `cp`.
-
It will keep the top 3 of them and evolve them only if their `iv` is greater than `0.9` and their `cp` greater than `1200`.
+#### rule keep
+| Parameter | Possible values | Default |
+|-----------|-----------------|---------|
+| `keep` | (see below) | `true` |
+
+Define minimum requirements to keep the Pokemon. Only Pokemon meeting these minimum requirements will be sorted.
+By default, if `keep` is not provided or is empty, all Pokemon will be sorted.
+
+The parameter can be a boolean value (`true` or `false`) or a list a criteria.
+The available criteria are the same as for the [`sort`](#available-criteria) parameter.
+
+The minimum requirement values can be a single value or a range.
+
They can also be a negative value if you wish to keep Pokemon below a certain criteria:
+
+- `"keep": false` will not rank any Pokemon. That is like deactivating the rule.
+- `"keep": true` will rank all Pokemon.
+- `"keep": {"iv": 0.9}` will only rank Pokemon with `iv` greater than `0.9`.
+- `"keep": {"iv": 0.9, "cp": 1200}` will only rank Pokemon with `iv` greater than `0.9` and `cp` greater than `1200`.
+- `"keep": {"iv": 0.9}` will only rank Pokemon with `iv` greater than `0.9`.
+- `"keep": {"cp": -20}` will only rank Pokemon with `cp` lower than `20`.
+- `"keep": {"cp": [10, 20]}` will only rank Pokemon with `cp` between `10` and `20`.
+- `"keep": {"iv": [[0.3, 0.5], [0.9, 1.0]]}` will only rank Pokemon with `iv` between `0.3` and `0.5` or between `0.9` and `1.0`.
[[back to top](#pokemon-optimizer)]
-#### keep evolve
+#### rule evolve
| Parameter | Possible values | Default |
|-----------|-----------------|---------|
-| `evolve` | `true`, `false` | `true` |
+| `evolve` | (see below) | `true` |
-The parameter allow you to selectively control what Pokemon to evolve.
+Define minimum requirements to evolve the Pokemon. Only Pokemon meeting these minimum requirements will be evolved.
+By default, if `evolve` is not provided or is empty, no Pokemon will be evolved.
-At `true`, all Pokemon selected and meeting the minimum evolution criteria (see [`sort`](#keep-sort)) will be evolved.
-
At `false`, Pokemon selected will not be eligible for evolution, unless they are also selected by another rule that allow them to evolve.
+The parameter can be a boolean value (`true` or `false`) or a list a criteria.
+The available criteria are the same as for the [`sort`](#available-criteria) parameter.
+
+The minimum requirement values can be a single value or a range.
+
They can also be a negative value if you wish to evolve Pokemon below a certain criteria:
+
+- `"evolve": false` will not try to evolve any of the Pokemon selected.
+- `"evolve": true` will try to evolve all Pokemon selected.
+- `"evolve": {"iv": 0.9}` will only evolve Pokemon with `iv` greater than `0.9`.
+- `"evolve": {"iv": 0.9, "cp": 1200}` will only evolve Pokemon with `iv` greater than `0.9` and `cp` greater than `1200`.
+- `"evolve": {"iv": 0.9}` will only evolve Pokemon with `iv` greater than `0.9`.
+- `"evolve": {"cp": -20}` will only evolve Pokemon with `cp` lower than `20`.
+- `"evolve": {"cp": [10, 20]}` will only evolve Pokemon with `cp` between `10` and `20`.
+- `"evolve": {"iv": [[0.3, 0.5], [0.9, 1.0]]}` will only evolve Pokemon with `iv` between `0.3` and `0.5` or between `0.9` and `1.0`.
[[back to top](#pokemon-optimizer)]
-#### keep upgrade
+#### rule upgrade
| Parameter | Possible values | Default |
|-----------|-----------------|---------|
-| `upgrade` | `true`, `false` | `false` |
+| `upgrade` | (see below) | `false` |
+
+Define minimum requirements to upgrade the Pokemon. Only Pokemon meeting these minimum requirements will be upgraded.
+By default, if `upgrade` is not provided or is empty, no Pokemon will be upgraded.
+
+The parameter can be a boolean value (`true` or `false`) or a list a criteria.
+The available criteria are the same as for the [`sort`](#available-criteria) parameter.
+
+The minimum requirement values can be a single value or a range.
+
They can also be a negative value if you wish to evolve Pokemon below a certain criteria:
+
+- `"upgrade": false` will not try to upgrade any of the Pokemon selected.
+- `"upgrade": true` will try to upgrade all Pokemon selected.
+- `"upgrade": {"iv": 0.9}` will only upgrade Pokemon with `iv` greater than `0.9`.
+- `"upgrade": {"iv": 0.9, "cp": 1200}` will only upgrade Pokemon with `iv` greater than `0.9` and `cp` greater than `1200`.
+- `"upgrade": {"iv": 0.9}` will only upgrade Pokemon with `iv` greater than `0.9`.
+- `"upgrade": {"cp": -20}` will only upgrade Pokemon with `cp` lower than `20`.
+- `"upgrade": {"cp": [10, 20]}` will only upgrade Pokemon with `cp` between `10` and `20`.
+- `"upgrade": {"iv": [[0.3, 0.5], [0.9, 1.0]]}` will only upgrade Pokemon with `iv` between `0.3` and `0.5` or between `0.9` and `1.0`.
+
+[[back to top](#pokemon-optimizer)]
+
+# Eevee case
+
+For Eevee Pokemon family, and any other family with multiple paths of evolution, the Pokemon Optimizer behaves as if the chances of getting a specific evolution were random and equal.
+
In practice, here are the effects you might notice regarding Eevee family:
+- If you are missing one version of evolution, every Eevee is a possible candidate to become the best Eevee you have for that specific evolution.
+
So as long as an evolution version is missing, the Pokemon Optimizer will tentatively try to keep and evolve all Eevees.
-The parameter allow you to selectively control what Pokemon to upgrade.
+- Once you have all version of evolution, things are not yet simple. Every Pokemon better than the worst evolution you have is a candidate to replace it.
+
The Pokemon Optimizer will tentatively try to keep and evolve all Eevees that may replace the worst evolution you have.
-At `true`, all Pokemon selected and meeting the minimum upgrade criteria (see [`sort`](#keep-sort)) will be upgraded.
-
At `false`, Pokemon selected will not be eligible for upgrade, unless they are also selected by another rule that allow them to upgrade.
+- If you deactivate the global `evolve` parameter, the Pokemon Optimizer will not apply above rules since it considers you are manually controlling the evolution of your Eevees.
[[back to top](#pokemon-optimizer)]
-## Examples of configuration
-> Keep the 2 best `iv` of every single Pokemon, and evolve them if they are over 0.9 `iv`.
+# FAQ
+#### How do I keep the 2 best `iv` of every single Pokemon, and evolve them if they are over `0.9` `iv` ?
+
+```
+{
+ "mode": "by_pokemon",
+ "top": 2,
+ "sort": ["iv"],
+ "evolve": {"iv": 0.9}
+},
+```
+
+#### How do I keep the 2 best `iv` of every single Pokemon, and evolve them if they are over `0.9` `ncp` ?
```
{
"mode": "by_pokemon",
"top": 2,
- "sort": [{"iv": 0.9}],
- "evolve": true
+ "sort": ["iv"],
+ "evolve": {"ncp": 0.9}
},
```
-> Keep my 10 best `cp` Dragonite and Snorlax to fight gyms.
+#### How do I keep my 10 best `cp` Dragonite and Snorlax to fight gyms ?
```
{
"mode": "by_pokemon",
"names": ["Dragonite", "Snorlax"]
"top": 10,
- "sort": ["cp"],
- "evolve": false
+ "sort": ["cp"]
},
```
-> Keep my Gyarados with the best moveset for attack.
+#### How do I keep the Gyarados with the best moveset for attack ?
```
{
"mode": "by_pokemon",
"names": ["Gyarados"]
"top": 1,
- "sort": ["dps_attack"],
- "evolve": false
+ "sort": ["dps_attack"]
},
```
-> I don't want you to use my candies for my loved Pokemon, But for others, it is ok.
+#### How do I keep the Gyarados with the best fast attack ?
```
-"groups": {
- "my loves ones" : ["Dragonite", "Snorlax", "Caterpie"]
+{
+ "mode": "by_pokemon",
+ "names": ["Gyarados"]
+ "top": 1,
+ "sort": ["dps1"]
},
-"keep": [
- {
- "mode": "by_family",
- "names": ["my loves ones"]
- "top": 1,
- "sort": ["iv"],
- "evolve": false
- },
- {
- "mode": "by_family",
- "names": ["!my loves ones"]
- "top": 1,
- "sort": ["iv"],
- "evolve": true
- }
- // + Exclude `my loves ones` from any other rule
-]
```
-> Do not touch my Dragonites !
+#### How do I keep all my Poliwag with `cp` less that `20` ?
```
{
"mode": "by_pokemon",
- "names": ["Dragonite"]
+ "names": ["Poliwag"]
+ "keep": {"cp": -20}
},
-// + Exclude Dragonite from any other rule
```
[[back to top](#pokemon-optimizer)]
-
-# Eevee case
-
-For Eevee Pokemon family, and any other family with multiple paths of evolution, the Pokemon Optimizer behaves as if the chances of getting a specific evolution were random and equal.
-
In practice, here are the effects you might notice regarding Eevee family:
-- If you are missing one version of evolution, every Eevee is a possible candidate to the become the best Eevee you have for that specific evolution.
-
So as long as an evolution version is missing, the Pokemon Optimizer will tentatively try to keep and evolve all Eevees.
-
-- Once you have all version of evolution, things are not yet simple. Every every better than the worst evolution you have is a candidate to replace it.
-
The Pokemon Optimizer will tentatively try to keep and evolve all Eevees that may replace the worst evolution you have.
-
-- If you deactivate the global `evolve` parameter, the Pokemon Optimizer will not apply above rules since it considers you are manually controlling the evolution of your Eevees.
-
-[[back to top](#pokemon-optimizer)]
diff --git a/pokemongo_bot/cell_workers/pokemon_optimizer.py b/pokemongo_bot/cell_workers/pokemon_optimizer.py
index cceca4418f..d4829f63d4 100644
--- a/pokemongo_bot/cell_workers/pokemon_optimizer.py
+++ b/pokemongo_bot/cell_workers/pokemon_optimizer.py
@@ -9,6 +9,7 @@
from pokemongo_bot.base_task import BaseTask
from pokemongo_bot.human_behaviour import sleep, action_delay
from pokemongo_bot.item_list import Item
+from pokemongo_bot.tree_config_builder import ConfigException
from pokemongo_bot.worker_result import WorkerResult
SUCCESS = 1
@@ -35,6 +36,9 @@ def initialize(self):
with open(pokemon_upgrade_cost_file, "r") as fd:
self.pokemon_upgrade_cost = json.load(fd)
+ if self.config.get("keep", None) is not None:
+ raise ConfigException("Pokemon Optimizer configuration has changed. See docs/pokemon_optimized.md or configs/config.json.optimizer.example")
+
self.config_min_slots_left = self.config.get("min_slots_left", 5)
self.config_transfer = self.config.get("transfer", False)
self.config_transfer_wait_min = self.config.get("transfer_wait_min", 3)
@@ -48,10 +52,10 @@ def initialize(self):
self.config_upgrade = self.config.get("upgrade", False)
self.config_upgrade_level = self.config.get("upgrade_level", 60)
self.config_groups = self.config.get("groups", {"gym": ["Dragonite", "Snorlax", "Lapras", "Arcanine"]})
- self.config_keep = self.config.get("keep", [{"mode": "by_family", "top": 1, "sort": [{"iv": 0.9}], "evolve": True, "upgrade": False},
- {"mode": "by_family", "top": 1, "sort": [{"ncp": 0.9}], "evolve": True, "upgrade": False},
- {"mode": "by_family", "top": 1, "sort": ["cp"], "evolve": False, "upgrade": False},
- {"mode": "by_family", "top": 3, "names": ["gym"], "sort": [{"iv": 0.9}, {"ncp": 0.9}], "evolve": True, "upgrade": True}])
+ self.config_rules = self.config.get("rules", [{"mode": "by_family", "top": 1, "sort": ["iv"], "evolve": {"iv": 0.9}},
+ {"mode": "by_family", "top": 1, "sort": ["ncp"], "evolve": {"ncp": 0.9}},
+ {"mode": "by_family", "top": 1, "sort": ["cp"]},
+ {"mode": "by_family", "top": 3, "names": ["gym"], "sort": ["iv", "ncp"], "evolve": {"iv": 0.9, "ncp": 0.9}, "upgrade": {"iv": 0.9, "ncp": 0.9}}])
if (not self.config_may_use_lucky_egg) and self.config_evolve_only_with_lucky_egg:
self.config_evolve = False
@@ -72,11 +76,11 @@ def work(self):
self.open_inventory()
+ keep_all = []
try_evolve_all = []
try_upgrade_all = []
- keep_all = []
- for rule in self.config_keep:
+ for rule in self.config_rules:
mode = rule.get("mode", "by_family")
names = rule.get("names", [])
whitelist_names, blacklist_names = self.get_colorlist_names(names)
@@ -91,10 +95,10 @@ def work(self):
if whitelist_names and (name not in whitelist_names):
continue
- try_evolve, try_upgrade, keep = self.get_best_pokemon_for_rule(pokemon_list, rule)
+ keep, try_evolve, try_upgrade = self.get_best_pokemon_for_rule(pokemon_list, rule)
+ keep_all += keep
try_evolve_all += try_evolve
try_upgrade_all += try_upgrade
- keep_all += keep
elif mode == "by_family":
for family_id, pokemon_list in self.group_by_family_id(inventory.pokemons().all()):
matching_names = self.get_family_names(family_id)
@@ -106,13 +110,13 @@ def work(self):
continue
if family_id == 133: # "Eevee"
- try_evolve, try_upgrade, keep = self.get_multi_best_pokemon_for_rule(pokemon_list, rule, 3)
+ keep, try_evolve, try_upgrade = self.get_multi_best_pokemon_for_rule(pokemon_list, rule, 3)
else:
- try_evolve, try_upgrade, keep = self.get_best_pokemon_for_rule(pokemon_list, rule)
+ keep, try_evolve, try_upgrade = self.get_best_pokemon_for_rule(pokemon_list, rule)
+ keep_all += keep
try_evolve_all += try_evolve
try_upgrade_all += try_upgrade
- keep_all += keep
elif mode == "overall":
pokemon_list = []
@@ -127,14 +131,14 @@ def work(self):
pokemon_list.append(pokemon)
- try_evolve, try_upgrade, keep = self.get_best_pokemon_for_rule(pokemon_list, rule)
+ keep, try_evolve, try_upgrade = self.get_best_pokemon_for_rule(pokemon_list, rule)
+ keep_all += keep
try_evolve_all += try_evolve
try_upgrade_all += try_upgrade
- keep_all += keep
+ keep_all = self.unique_pokemon_list(keep_all)
try_evolve_all = self.unique_pokemon_list(try_evolve_all)
try_upgrade_all = self.unique_pokemon_list(try_upgrade_all)
- keep_all = self.unique_pokemon_list(keep_all)
transfer_all = []
evolve_all = []
@@ -142,11 +146,11 @@ def work(self):
xp_all = []
for family_id, pokemon_list in self.group_by_family_id(inventory.pokemons().all()):
+ keep = [p for p in keep_all if self.get_family_id(p) == family_id]
try_evolve = [p for p in try_evolve_all if self.get_family_id(p) == family_id]
try_upgrade = [p for p in try_upgrade_all if self.get_family_id(p) == family_id]
- keep = [p for p in keep_all if self.get_family_id(p) == family_id]
- transfer, evolve, upgrade, xp = self.get_evolution_plan(family_id, pokemon_list, try_evolve, try_upgrade, keep)
+ transfer, evolve, upgrade, xp = self.get_evolution_plan(family_id, pokemon_list, keep, try_evolve, try_upgrade)
transfer_all += transfer
evolve_all += evolve
@@ -218,8 +222,7 @@ def get_closest_name(self, name):
return closest_name
else:
- self.logger.error("Unknown Pokemon name [%s]", name)
- return ""
+ raise ConfigException("Unknown Pokemon name [%s]" % name)
def group_by_pokemon_id(self, pokemon_list):
sorted_list = sorted(pokemon_list, key=self.get_pokemon_id)
@@ -236,7 +239,7 @@ def get_family_id(self, pokemon):
return pokemon.first_evolution_id
def get_best_pokemon_for_rule(self, pokemon_list, rule):
- sorted_pokemon = self.sort_pokemon_list(pokemon_list, rule)
+ sorted_pokemon = self.sort_pokemon_list_to_keep(pokemon_list, rule)
if len(sorted_pokemon) == 0:
return ([], [], [])
@@ -258,88 +261,120 @@ def get_best_pokemon_for_rule(self, pokemon_list, rule):
return self.get_better_pokemon_for_rule(sorted_pokemon, rule, worst)
def get_multi_best_pokemon_for_rule(self, family_list, rule, nb_branch):
- sorted_family = self.sort_pokemon_list(family_list, rule)
+ sorted_family = self.sort_pokemon_list_to_keep(family_list, rule)
# Handle each group of senior independently
senior_pokemon_list = [p for p in sorted_family if not p.has_next_evolution()]
other_family_list = [p for p in sorted_family if p.has_next_evolution()]
senior_pids = set(p.pokemon_id for p in senior_pokemon_list)
+ keep_all = []
try_evolve_all = []
try_upgrade_all = []
- keep_all = []
if not self.config_evolve:
# Player handle evolution manually = Fall-back to per Pokemon behavior
for _, pokemon_list in self.group_by_pokemon_id(sorted_family):
- try_evolve, try_upgrade, keep = self.get_best_pokemon_for_rule(pokemon_list, rule)
+ keep, try_evolve, try_upgrade = self.get_best_pokemon_for_rule(pokemon_list, rule)
+ keep_all += keep
try_evolve_all += try_evolve
try_upgrade_all += try_upgrade
- keep_all += keep
else:
for _, pokemon_list in self.group_by_pokemon_id(senior_pokemon_list):
- try_evolve, try_upgrade, keep = self.get_best_pokemon_for_rule(pokemon_list, rule)
+ keep, try_evolve, try_upgrade = self.get_best_pokemon_for_rule(pokemon_list, rule)
+ keep_all += keep
try_evolve_all += try_evolve
try_upgrade_all += try_upgrade
- keep_all += keep
if len(other_family_list) > 0:
if len(senior_pids) < nb_branch:
# We did not get every combination yet = All other Pokemon are potentially good to keep
worst = other_family_list[-1]
else:
- best = try_evolve_all + try_upgrade_all + keep_all
- worst = self.sort_pokemon_list(best, rule)[-1]
+ best = keep_all + try_evolve_all + try_upgrade_all
+ worst = self.sort_pokemon_list_to_keep(best, rule)[-1]
- try_evolve, try_upgrade, keep = self.get_better_pokemon_for_rule(other_family_list, rule, worst, 12)
+ keep, try_evolve, try_upgrade = self.get_better_pokemon_for_rule(other_family_list, rule, worst, 12)
+ keep_all += keep
try_evolve_all += try_evolve
try_upgrade_all += try_upgrade
- keep_all += keep
- return try_evolve_all, try_upgrade_all, keep_all
+ return keep_all, try_evolve_all, try_upgrade_all
def get_better_pokemon_for_rule(self, pokemon_list, rule, worst, limit=1000):
min_score = self.get_score(worst, rule)[0]
scored_list = [(p, self.get_score(p, rule)) for p in pokemon_list]
- best = [x for x in scored_list if x[1][0] >= min_score][:limit]
- try_evolve = [x[0] for x in best if x[1][1] is True]
- try_upgrade = [x[0] for x in best if x[1][1] is False and x[1][2] is True]
- keep = [x[0] for x in best]
+ scored_keep = [x for x in scored_list if (x[1][0] >= min_score) and (x[1][1] is True)][:limit]
+ keep = [x[0] for x in scored_keep]
+ try_evolve = [x[0] for x in scored_keep if x[1][2] is True]
+ try_upgrade = [x[0] for x in scored_keep if (x[1][2] is False) and (x[1][3] is True)]
- return try_evolve, try_upgrade, keep
+ return keep, try_evolve, try_upgrade
- def sort_pokemon_list(self, pokemon_list, rule):
- return sorted(pokemon_list, key=lambda p: self.get_score(p, rule)[0], reverse=True)
+ def sort_pokemon_list_to_keep(self, pokemon_list, rule):
+ scored_list = [(p, self.get_score(p, rule)) for p in pokemon_list]
+ scored_keep = [x for x in scored_list if x[1][1] is True]
+ scored_keep.sort(key=lambda x: x[1][0], reverse=True)
+
+ return [p for p, x in scored_keep]
def get_score(self, pokemon, rule):
score = []
- may_try_evolve = (getattr(pokemon, "has_next_evolution", False) and
- pokemon.has_next_evolution() and
- rule.get("evolve", True))
- may_try_upgrade = rule.get("upgrade", False)
for a in rule.get("sort", []):
- if (type(a) is str) or (type(a) is unicode):
- value = getattr(pokemon, a, 0)
- score.append(value)
- elif type(a) is dict:
- value = getattr(pokemon, a.keys()[0], 0)
- score.append(value)
- may_try_evolve &= (value >= a.values()[0])
- may_try_upgrade &= (value >= a.values()[0])
- elif type(a) is list:
- value = getattr(pokemon, a[0], 0)
- score.append(value)
- may_try_evolve &= (value >= a[1])
- may_try_upgrade &= (value >= a[1])
-
- return tuple(score), may_try_evolve, may_try_upgrade
+ value = getattr(pokemon, a, 0)
+ score.append(value)
+
+ rule_keep = rule.get("keep", True)
+ rule_evolve = rule.get("evolve", True)
+ rule_upgrade = rule.get("upgrade", False)
+
+ keep = rule_keep not in [False, {}]
+ keep &= self.satisfy_requirements(pokemon, rule_keep)
+
+ may_try_evolve = (hasattr(pokemon, "has_next_evolution") and pokemon.has_next_evolution())
+ may_try_evolve &= rule_evolve not in [False, {}]
+ may_try_evolve &= self.satisfy_requirements(pokemon, rule_evolve)
+
+ may_try_upgrade = rule_upgrade not in [False, {}]
+ may_try_upgrade &= self.satisfy_requirements(pokemon, rule_upgrade)
+
+ return tuple(score), keep, may_try_evolve, may_try_upgrade
+
+ def satisfy_requirements(self, pokemon, req):
+ if type(req) is bool:
+ return req
+
+ satisfy = True
+
+ for a, v in req.items():
+ value = getattr(pokemon, a, 0)
+
+ if (type(v) is str) or (type(v) is unicode):
+ v = float(v)
+
+ if type(v) is list:
+ if type(v[0]) is list:
+ satisfy_range = False
+
+ for r in v:
+ satisfy_range |= (value >= r[0]) and (value <= r[1])
+
+ satisfy &= satisfy_range
+ else:
+ satisfy &= (value >= v[0]) and (value <= v[1])
+ elif v < 0:
+ satisfy &= (value <= abs(v))
+ else:
+ satisfy &= (value >= v)
+
+ return satisfy
def unique_pokemon_list(self, pokemon_list):
seen = set()
return [p for p in pokemon_list if not (p.unique_id in seen or seen.add(p.unique_id))]
- def get_evolution_plan(self, family_id, family_list, try_evolve, try_upgrade, keep):
+ def get_evolution_plan(self, family_id, family_list, keep, try_evolve, try_upgrade):
candies = inventory.candies().get(family_id).quantity
# All the rest is crap, for now