We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
[Feature Request] Differentiate Between Unlimited and "Purchased" Incubator use.
Blue incubators are difficult to get so I use it only for 10km eggs. Is there any configuration to prevent bot from using Blue Incubator?


--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `pokemongo_bot/cell_workers/incubate_eggs.py`
Content:
```
1 from datetime import datetime, timedelta
2 
3 from pokemongo_bot.human_behaviour import sleep
4 from pokemongo_bot.base_task import BaseTask
5 
6 
7 class IncubateEggs(BaseTask):
8     SUPPORTED_TASK_API_VERSION = 1
9 
10     last_km_walked = 0
11 
12     def initialize(self):
13         self.next_update = None
14         self.ready_incubators = []
15         self.used_incubators = []
16         self.eggs = []
17         self.km_walked = 0
18         self.hatching_animation_delay = 4.20
19         self.max_iv = 45.0
20 
21         self._process_config()
22 
23     def _process_config(self):
24         self.longer_eggs_first = self.config.get("longer_eggs_first", True)
25         self.min_interval = self.config.get('min_interval', 120)
26 
27     def work(self):
28         try:
29             self._check_inventory()
30         except:
31             return
32 
33         if self.used_incubators and IncubateEggs.last_km_walked != self.km_walked:
34             self.used_incubators.sort(key=lambda x: x.get("km"))
35             km_left = self.used_incubators[0]['km']-self.km_walked
36             if km_left <= 0:
37                 self._hatch_eggs()
38             else:
39                 self.bot.metrics.next_hatching_km(km_left)
40 
41         if self._should_print():
42             self._print_eggs()
43             self._compute_next_update()
44 
45         IncubateEggs.last_km_walked = self.km_walked
46 
47         sorting = self.longer_eggs_first
48         self.eggs.sort(key=lambda x: x.get("km"), reverse=sorting)
49 
50         if self.ready_incubators:
51             self._apply_incubators()
52 
53     def _apply_incubators(self):
54         for incubator in self.ready_incubators:
55             if incubator.get('used', False):
56                 continue
57             for egg in self.eggs:
58                 if egg["used"] or egg["km"] == -1:
59                     continue
60                 self.emit_event(
61                     'incubate_try',
62                     level='debug',
63                     formatted="Attempting to apply incubator {incubator_id} to egg {egg_id}",
64                     data={
65                         'incubator_id': incubator['id'],
66                         'egg_id': egg['id']
67                     }
68                 )
69                 ret = self.bot.api.use_item_egg_incubator(
70                     item_id=incubator["id"],
71                     pokemon_id=egg["id"]
72                 )
73                 if ret:
74                     code = ret.get("responses", {}).get("USE_ITEM_EGG_INCUBATOR", {}).get("result", 0)
75                     if code == 1:
76                         self.emit_event(
77                             'incubate',
78                             formatted='Incubating a {distance_in_km} egg.',
79                             data={
80                                 'distance_in_km': str(egg['km'])
81                             }
82                         )
83                         egg["used"] = True
84                         incubator["used"] = True
85                         break
86                     elif code == 5 or code == 7:
87                         self.emit_event(
88                             'incubator_already_used',
89                             level='debug',
90                             formatted='Incubator in use.',
91                         )
92                         incubator["used"] = True
93                         break
94                     elif code == 6:
95                         self.emit_event(
96                             'egg_already_incubating',
97                             level='debug',
98                             formatted='Egg already incubating',
99                         )
100                         egg["used"] = True
101 
102     def _check_inventory(self, lookup_ids=[]):
103         inv = {}
104         response_dict = self.bot.api.get_inventory()
105         matched_pokemon = []
106         temp_eggs = []
107         temp_used_incubators = []
108         temp_ready_incubators = []
109         inv = reduce(
110             dict.__getitem__,
111             ["responses", "GET_INVENTORY", "inventory_delta", "inventory_items"],
112             response_dict
113         )
114         for inv_data in inv:
115             inv_data = inv_data.get("inventory_item_data", {})
116             if "egg_incubators" in inv_data:
117                 temp_used_incubators = []
118                 temp_ready_incubators = []
119                 incubators = inv_data.get("egg_incubators", {}).get("egg_incubator",[])
120                 if isinstance(incubators, basestring):  # checking for old response
121                     incubators = [incubators]
122                 for incubator in incubators:
123                     if 'pokemon_id' in incubator:
124                         start_km = incubator.get('start_km_walked', 9001)
125                         km_walked = incubator.get('target_km_walked', 9001)
126                         temp_used_incubators.append({
127                             "id": incubator.get('id', -1),
128                             "km": km_walked,
129                             "km_needed": (km_walked - start_km)
130                         })
131                     else:
132                         temp_ready_incubators.append({
133                             "id": incubator.get('id', -1)
134                         })
135                 continue
136             if "pokemon_data" in inv_data:
137                 pokemon = inv_data.get("pokemon_data", {})
138                 if pokemon.get("is_egg", False) and "egg_incubator_id" not in pokemon:
139                     temp_eggs.append({
140                         "id": pokemon.get("id", -1),
141                         "km": pokemon.get("egg_km_walked_target", -1),
142                         "used": False
143                     })
144                 elif 'is_egg' not in pokemon and pokemon['id'] in lookup_ids:
145                     pokemon.update({
146                         "iv": [
147                             pokemon.get('individual_attack', 0),
148                             pokemon.get('individual_defense', 0),
149                             pokemon.get('individual_stamina', 0)
150                         ]})
151                     matched_pokemon.append(pokemon)
152                 continue
153             if "player_stats" in inv_data:
154                 self.km_walked = inv_data.get("player_stats", {}).get("km_walked", 0)
155         if temp_used_incubators:
156             self.used_incubators = temp_used_incubators
157         if temp_ready_incubators:
158             self.ready_incubators = temp_ready_incubators
159         if temp_eggs:
160             self.eggs = temp_eggs
161         return matched_pokemon
162 
163     def _hatch_eggs(self):
164         response_dict = self.bot.api.get_hatched_eggs()
165         log_color = 'green'
166         try:
167             result = reduce(dict.__getitem__, ["responses", "GET_HATCHED_EGGS"], response_dict)
168         except KeyError:
169             return
170         pokemon_ids = []
171         if 'pokemon_id' in result:
172             pokemon_ids = [id for id in result['pokemon_id']]
173         stardust = result.get('stardust_awarded', "error")
174         candy = result.get('candy_awarded', "error")
175         xp = result.get('experience_awarded', "error")
176         sleep(self.hatching_animation_delay)
177         self.bot.latest_inventory = None
178         try:
179             pokemon_data = self._check_inventory(pokemon_ids)
180             for pokemon in pokemon_data:
181                 # pokemon ids seem to be offset by one
182                 if pokemon['pokemon_id']!=-1:
183                     pokemon['name'] = self.bot.pokemon_list[(pokemon.get('pokemon_id')-1)]['Name']
184                 else:
185                     pokemon['name'] = "error"
186         except:
187             pokemon_data = [{"name":"error","cp":"error","iv":"error"}]
188         if not pokemon_ids or pokemon_data[0]['name'] == "error":
189             self.emit_event(
190                 'egg_hatched',
191                 data={
192                     'pokemon': 'error',
193                     'cp': 'error',
194                     'iv': 'error',
195                     'exp': 'error',
196                     'stardust': 'error',
197                     'candy': 'error',
198                 }
199             )
200             return
201         for i in range(len(pokemon_data)):
202             msg = "Egg hatched with a {pokemon} (CP {cp} - IV {iv}), {exp} exp, {stardust} stardust and {candy} candies."
203             self.bot.metrics.hatched_eggs(1)
204             self.emit_event(
205                 'egg_hatched',
206                 formatted=msg,
207                 data={
208                     'pokemon': pokemon_data[i]['name'],
209                     'cp': pokemon_data[i]['cp'],
210                     'iv': "{} {}".format(
211                         "/".join(map(str, pokemon_data[i]['iv'])),
212                         round(sum(pokemon_data[i]['iv'])/self.max_iv, 2)
213                     ),
214                     'exp': xp[i],
215                     'stardust': stardust[i],
216                     'candy': candy[i],
217                 }
218             )
219 
220     def _print_eggs(self):
221         if not self.used_incubators:
222             return
223 
224         self.used_incubators.sort(key=lambda x: x.get("km"))
225         
226         eggs = ['{:.2f}/{} km'.format(e['km_needed']-e['km']+self.km_walked, e['km_needed']) for e in self.used_incubators]
227 
228         self.emit_event(
229                     'next_egg_incubates',
230                     formatted='Eggs incubating: [{eggs}] (Eggs left: {eggs_left}, Incubating: {eggs_inc})',
231                     data={
232                         'eggs_left': len(self.eggs),
233                         'eggs_inc': len(self.used_incubators),
234                         'eggs': ', '.join(eggs)
235                     }
236                 )
237         
238     def _should_print(self):
239         """
240         Returns a value indicating whether the eggs should be displayed.
241         :return: True if the stats should be displayed; otherwise, False.
242         :rtype: bool
243         """
244         return self.next_update is None or datetime.now() >= self.next_update
245 
246     def _compute_next_update(self):
247         """
248         Computes the next update datetime based on the minimum update interval.
249         :return: Nothing.
250         :rtype: None
251         """
252         self.next_update = datetime.now() + timedelta(seconds=self.min_interval)
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/pokemongo_bot/cell_workers/incubate_eggs.py b/pokemongo_bot/cell_workers/incubate_eggs.py
--- a/pokemongo_bot/cell_workers/incubate_eggs.py
+++ b/pokemongo_bot/cell_workers/incubate_eggs.py
@@ -23,7 +23,10 @@
     def _process_config(self):
         self.longer_eggs_first = self.config.get("longer_eggs_first", True)
         self.min_interval = self.config.get('min_interval', 120)
-
+        
+        self.breakable_incubator = self.config.get("breakable", [])
+        self.infinite_incubator = self.config.get("infinite", [])
+    
     def work(self):
         try:
             self._check_inventory()
@@ -57,6 +60,17 @@
             for egg in self.eggs:
                 if egg["used"] or egg["km"] == -1:
                     continue
+                
+                if self.breakable_incubator:
+                    if incubator.get('uses_remaining') is not None: # test if the incubator is of type breakable
+                        if egg["km"] not in self.breakable_incubator:
+                            continue
+                    
+                if self.infinite_incubator:
+                    if incubator.get('uses_remaining') is None: # test if the incubator is of type infinite
+                        if egg["km"] not in self.infinite_incubator:
+                            continue
+                
                 self.emit_event(
                     'incubate_try',
                     level='debug',
@@ -119,7 +133,7 @@
                 incubators = inv_data.get("egg_incubators", {}).get("egg_incubator",[])
                 if isinstance(incubators, basestring):  # checking for old response
                     incubators = [incubators]
-                for incubator in incubators:
+                for incubator in incubators:                                           
                     if 'pokemon_id' in incubator:
                         start_km = incubator.get('start_km_walked', 9001)
                         km_walked = incubator.get('target_km_walked', 9001)

{"golden_diff": "diff --git a/pokemongo_bot/cell_workers/incubate_eggs.py b/pokemongo_bot/cell_workers/incubate_eggs.py\n--- a/pokemongo_bot/cell_workers/incubate_eggs.py\n+++ b/pokemongo_bot/cell_workers/incubate_eggs.py\n@@ -23,7 +23,10 @@\n     def _process_config(self):\n         self.longer_eggs_first = self.config.get(\"longer_eggs_first\", True)\n         self.min_interval = self.config.get('min_interval', 120)\n-\n+        \n+        self.breakable_incubator = self.config.get(\"breakable\", [])\n+        self.infinite_incubator = self.config.get(\"infinite\", [])\n+    \n     def work(self):\n         try:\n             self._check_inventory()\n@@ -57,6 +60,17 @@\n             for egg in self.eggs:\n                 if egg[\"used\"] or egg[\"km\"] == -1:\n                     continue\n+                \n+                if self.breakable_incubator:\n+                    if incubator.get('uses_remaining') is not None: # test if the incubator is of type breakable\n+                        if egg[\"km\"] not in self.breakable_incubator:\n+                            continue\n+                    \n+                if self.infinite_incubator:\n+                    if incubator.get('uses_remaining') is None: # test if the incubator is of type infinite\n+                        if egg[\"km\"] not in self.infinite_incubator:\n+                            continue\n+                \n                 self.emit_event(\n                     'incubate_try',\n                     level='debug',\n@@ -119,7 +133,7 @@\n                 incubators = inv_data.get(\"egg_incubators\", {}).get(\"egg_incubator\",[])\n                 if isinstance(incubators, basestring):  # checking for old response\n                     incubators = [incubators]\n-                for incubator in incubators:\n+                for incubator in incubators:                                           \n                     if 'pokemon_id' in incubator:\n                         start_km = incubator.get('start_km_walked', 9001)\n                         km_walked = incubator.get('target_km_walked', 9001)\n", "issue": "[Feature Request] Differentiate Between Unlimited and \"Purchased\" Incubator use.\nBlue incubators are difficult to get so I use it only for 10km eggs. Is there any configuration to prevent bot from using Blue Incubator?\n\n", "before_files": [{"content": "from datetime import datetime, timedelta\n\nfrom pokemongo_bot.human_behaviour import sleep\nfrom pokemongo_bot.base_task import BaseTask\n\n\nclass IncubateEggs(BaseTask):\n    SUPPORTED_TASK_API_VERSION = 1\n\n    last_km_walked = 0\n\n    def initialize(self):\n        self.next_update = None\n        self.ready_incubators = []\n        self.used_incubators = []\n        self.eggs = []\n        self.km_walked = 0\n        self.hatching_animation_delay = 4.20\n        self.max_iv = 45.0\n\n        self._process_config()\n\n    def _process_config(self):\n        self.longer_eggs_first = self.config.get(\"longer_eggs_first\", True)\n        self.min_interval = self.config.get('min_interval', 120)\n\n    def work(self):\n        try:\n            self._check_inventory()\n        except:\n            return\n\n        if self.used_incubators and IncubateEggs.last_km_walked != self.km_walked:\n            self.used_incubators.sort(key=lambda x: x.get(\"km\"))\n            km_left = self.used_incubators[0]['km']-self.km_walked\n            if km_left <= 0:\n                self._hatch_eggs()\n            else:\n                self.bot.metrics.next_hatching_km(km_left)\n\n        if self._should_print():\n            self._print_eggs()\n            self._compute_next_update()\n\n        IncubateEggs.last_km_walked = self.km_walked\n\n        sorting = self.longer_eggs_first\n        self.eggs.sort(key=lambda x: x.get(\"km\"), reverse=sorting)\n\n        if self.ready_incubators:\n            self._apply_incubators()\n\n    def _apply_incubators(self):\n        for incubator in self.ready_incubators:\n            if incubator.get('used', False):\n                continue\n            for egg in self.eggs:\n                if egg[\"used\"] or egg[\"km\"] == -1:\n                    continue\n                self.emit_event(\n                    'incubate_try',\n                    level='debug',\n                    formatted=\"Attempting to apply incubator {incubator_id} to egg {egg_id}\",\n                    data={\n                        'incubator_id': incubator['id'],\n                        'egg_id': egg['id']\n                    }\n                )\n                ret = self.bot.api.use_item_egg_incubator(\n                    item_id=incubator[\"id\"],\n                    pokemon_id=egg[\"id\"]\n                )\n                if ret:\n                    code = ret.get(\"responses\", {}).get(\"USE_ITEM_EGG_INCUBATOR\", {}).get(\"result\", 0)\n                    if code == 1:\n                        self.emit_event(\n                            'incubate',\n                            formatted='Incubating a {distance_in_km} egg.',\n                            data={\n                                'distance_in_km': str(egg['km'])\n                            }\n                        )\n                        egg[\"used\"] = True\n                        incubator[\"used\"] = True\n                        break\n                    elif code == 5 or code == 7:\n                        self.emit_event(\n                            'incubator_already_used',\n                            level='debug',\n                            formatted='Incubator in use.',\n                        )\n                        incubator[\"used\"] = True\n                        break\n                    elif code == 6:\n                        self.emit_event(\n                            'egg_already_incubating',\n                            level='debug',\n                            formatted='Egg already incubating',\n                        )\n                        egg[\"used\"] = True\n\n    def _check_inventory(self, lookup_ids=[]):\n        inv = {}\n        response_dict = self.bot.api.get_inventory()\n        matched_pokemon = []\n        temp_eggs = []\n        temp_used_incubators = []\n        temp_ready_incubators = []\n        inv = reduce(\n            dict.__getitem__,\n            [\"responses\", \"GET_INVENTORY\", \"inventory_delta\", \"inventory_items\"],\n            response_dict\n        )\n        for inv_data in inv:\n            inv_data = inv_data.get(\"inventory_item_data\", {})\n            if \"egg_incubators\" in inv_data:\n                temp_used_incubators = []\n                temp_ready_incubators = []\n                incubators = inv_data.get(\"egg_incubators\", {}).get(\"egg_incubator\",[])\n                if isinstance(incubators, basestring):  # checking for old response\n                    incubators = [incubators]\n                for incubator in incubators:\n                    if 'pokemon_id' in incubator:\n                        start_km = incubator.get('start_km_walked', 9001)\n                        km_walked = incubator.get('target_km_walked', 9001)\n                        temp_used_incubators.append({\n                            \"id\": incubator.get('id', -1),\n                            \"km\": km_walked,\n                            \"km_needed\": (km_walked - start_km)\n                        })\n                    else:\n                        temp_ready_incubators.append({\n                            \"id\": incubator.get('id', -1)\n                        })\n                continue\n            if \"pokemon_data\" in inv_data:\n                pokemon = inv_data.get(\"pokemon_data\", {})\n                if pokemon.get(\"is_egg\", False) and \"egg_incubator_id\" not in pokemon:\n                    temp_eggs.append({\n                        \"id\": pokemon.get(\"id\", -1),\n                        \"km\": pokemon.get(\"egg_km_walked_target\", -1),\n                        \"used\": False\n                    })\n                elif 'is_egg' not in pokemon and pokemon['id'] in lookup_ids:\n                    pokemon.update({\n                        \"iv\": [\n                            pokemon.get('individual_attack', 0),\n                            pokemon.get('individual_defense', 0),\n                            pokemon.get('individual_stamina', 0)\n                        ]})\n                    matched_pokemon.append(pokemon)\n                continue\n            if \"player_stats\" in inv_data:\n                self.km_walked = inv_data.get(\"player_stats\", {}).get(\"km_walked\", 0)\n        if temp_used_incubators:\n            self.used_incubators = temp_used_incubators\n        if temp_ready_incubators:\n            self.ready_incubators = temp_ready_incubators\n        if temp_eggs:\n            self.eggs = temp_eggs\n        return matched_pokemon\n\n    def _hatch_eggs(self):\n        response_dict = self.bot.api.get_hatched_eggs()\n        log_color = 'green'\n        try:\n            result = reduce(dict.__getitem__, [\"responses\", \"GET_HATCHED_EGGS\"], response_dict)\n        except KeyError:\n            return\n        pokemon_ids = []\n        if 'pokemon_id' in result:\n            pokemon_ids = [id for id in result['pokemon_id']]\n        stardust = result.get('stardust_awarded', \"error\")\n        candy = result.get('candy_awarded', \"error\")\n        xp = result.get('experience_awarded', \"error\")\n        sleep(self.hatching_animation_delay)\n        self.bot.latest_inventory = None\n        try:\n            pokemon_data = self._check_inventory(pokemon_ids)\n            for pokemon in pokemon_data:\n                # pokemon ids seem to be offset by one\n                if pokemon['pokemon_id']!=-1:\n                    pokemon['name'] = self.bot.pokemon_list[(pokemon.get('pokemon_id')-1)]['Name']\n                else:\n                    pokemon['name'] = \"error\"\n        except:\n            pokemon_data = [{\"name\":\"error\",\"cp\":\"error\",\"iv\":\"error\"}]\n        if not pokemon_ids or pokemon_data[0]['name'] == \"error\":\n            self.emit_event(\n                'egg_hatched',\n                data={\n                    'pokemon': 'error',\n                    'cp': 'error',\n                    'iv': 'error',\n                    'exp': 'error',\n                    'stardust': 'error',\n                    'candy': 'error',\n                }\n            )\n            return\n        for i in range(len(pokemon_data)):\n            msg = \"Egg hatched with a {pokemon} (CP {cp} - IV {iv}), {exp} exp, {stardust} stardust and {candy} candies.\"\n            self.bot.metrics.hatched_eggs(1)\n            self.emit_event(\n                'egg_hatched',\n                formatted=msg,\n                data={\n                    'pokemon': pokemon_data[i]['name'],\n                    'cp': pokemon_data[i]['cp'],\n                    'iv': \"{} {}\".format(\n                        \"/\".join(map(str, pokemon_data[i]['iv'])),\n                        round(sum(pokemon_data[i]['iv'])/self.max_iv, 2)\n                    ),\n                    'exp': xp[i],\n                    'stardust': stardust[i],\n                    'candy': candy[i],\n                }\n            )\n\n    def _print_eggs(self):\n        if not self.used_incubators:\n            return\n\n        self.used_incubators.sort(key=lambda x: x.get(\"km\"))\n        \n        eggs = ['{:.2f}/{} km'.format(e['km_needed']-e['km']+self.km_walked, e['km_needed']) for e in self.used_incubators]\n\n        self.emit_event(\n                    'next_egg_incubates',\n                    formatted='Eggs incubating: [{eggs}] (Eggs left: {eggs_left}, Incubating: {eggs_inc})',\n                    data={\n                        'eggs_left': len(self.eggs),\n                        'eggs_inc': len(self.used_incubators),\n                        'eggs': ', '.join(eggs)\n                    }\n                )\n        \n    def _should_print(self):\n        \"\"\"\n        Returns a value indicating whether the eggs should be displayed.\n        :return: True if the stats should be displayed; otherwise, False.\n        :rtype: bool\n        \"\"\"\n        return self.next_update is None or datetime.now() >= self.next_update\n\n    def _compute_next_update(self):\n        \"\"\"\n        Computes the next update datetime based on the minimum update interval.\n        :return: Nothing.\n        :rtype: None\n        \"\"\"\n        self.next_update = datetime.now() + timedelta(seconds=self.min_interval)", "path": "pokemongo_bot/cell_workers/incubate_eggs.py"}], "after_files": [{"content": "from datetime import datetime, timedelta\n\nfrom pokemongo_bot.human_behaviour import sleep\nfrom pokemongo_bot.base_task import BaseTask\n\n\nclass IncubateEggs(BaseTask):\n    SUPPORTED_TASK_API_VERSION = 1\n\n    last_km_walked = 0\n\n    def initialize(self):\n        self.next_update = None\n        self.ready_incubators = []\n        self.used_incubators = []\n        self.eggs = []\n        self.km_walked = 0\n        self.hatching_animation_delay = 4.20\n        self.max_iv = 45.0\n\n        self._process_config()\n\n    def _process_config(self):\n        self.longer_eggs_first = self.config.get(\"longer_eggs_first\", True)\n        self.min_interval = self.config.get('min_interval', 120)\n        \n        self.breakable_incubator = self.config.get(\"breakable\", [])\n        self.infinite_incubator = self.config.get(\"infinite\", [])\n    \n    def work(self):\n        try:\n            self._check_inventory()\n        except:\n            return\n\n        if self.used_incubators and IncubateEggs.last_km_walked != self.km_walked:\n            self.used_incubators.sort(key=lambda x: x.get(\"km\"))\n            km_left = self.used_incubators[0]['km']-self.km_walked\n            if km_left <= 0:\n                self._hatch_eggs()\n            else:\n                self.bot.metrics.next_hatching_km(km_left)\n\n        if self._should_print():\n            self._print_eggs()\n            self._compute_next_update()\n\n        IncubateEggs.last_km_walked = self.km_walked\n\n        sorting = self.longer_eggs_first\n        self.eggs.sort(key=lambda x: x.get(\"km\"), reverse=sorting)\n\n        if self.ready_incubators:\n            self._apply_incubators()\n\n    def _apply_incubators(self):\n        for incubator in self.ready_incubators:\n            if incubator.get('used', False):\n                continue\n            for egg in self.eggs:\n                if egg[\"used\"] or egg[\"km\"] == -1:\n                    continue\n                \n                if self.breakable_incubator:\n                    if incubator.get('uses_remaining') is not None: # test if the incubator is of type breakable\n                        if egg[\"km\"] not in self.breakable_incubator:\n                            continue\n                    \n                if self.infinite_incubator:\n                    if incubator.get('uses_remaining') is None: # test if the incubator is of type infinite\n                        if egg[\"km\"] not in self.infinite_incubator:\n                            continue\n                \n                self.emit_event(\n                    'incubate_try',\n                    level='debug',\n                    formatted=\"Attempting to apply incubator {incubator_id} to egg {egg_id}\",\n                    data={\n                        'incubator_id': incubator['id'],\n                        'egg_id': egg['id']\n                    }\n                )\n                ret = self.bot.api.use_item_egg_incubator(\n                    item_id=incubator[\"id\"],\n                    pokemon_id=egg[\"id\"]\n                )\n                if ret:\n                    code = ret.get(\"responses\", {}).get(\"USE_ITEM_EGG_INCUBATOR\", {}).get(\"result\", 0)\n                    if code == 1:\n                        self.emit_event(\n                            'incubate',\n                            formatted='Incubating a {distance_in_km} egg.',\n                            data={\n                                'distance_in_km': str(egg['km'])\n                            }\n                        )\n                        egg[\"used\"] = True\n                        incubator[\"used\"] = True\n                        break\n                    elif code == 5 or code == 7:\n                        self.emit_event(\n                            'incubator_already_used',\n                            level='debug',\n                            formatted='Incubator in use.',\n                        )\n                        incubator[\"used\"] = True\n                        break\n                    elif code == 6:\n                        self.emit_event(\n                            'egg_already_incubating',\n                            level='debug',\n                            formatted='Egg already incubating',\n                        )\n                        egg[\"used\"] = True\n\n    def _check_inventory(self, lookup_ids=[]):\n        inv = {}\n        response_dict = self.bot.api.get_inventory()\n        matched_pokemon = []\n        temp_eggs = []\n        temp_used_incubators = []\n        temp_ready_incubators = []\n        inv = reduce(\n            dict.__getitem__,\n            [\"responses\", \"GET_INVENTORY\", \"inventory_delta\", \"inventory_items\"],\n            response_dict\n        )\n        for inv_data in inv:\n            inv_data = inv_data.get(\"inventory_item_data\", {})\n            if \"egg_incubators\" in inv_data:\n                temp_used_incubators = []\n                temp_ready_incubators = []\n                incubators = inv_data.get(\"egg_incubators\", {}).get(\"egg_incubator\",[])\n                if isinstance(incubators, basestring):  # checking for old response\n                    incubators = [incubators]\n                for incubator in incubators:                                           \n                    if 'pokemon_id' in incubator:\n                        start_km = incubator.get('start_km_walked', 9001)\n                        km_walked = incubator.get('target_km_walked', 9001)\n                        temp_used_incubators.append({\n                            \"id\": incubator.get('id', -1),\n                            \"km\": km_walked,\n                            \"km_needed\": (km_walked - start_km)\n                        })\n                    else:\n                        temp_ready_incubators.append({\n                            \"id\": incubator.get('id', -1)\n                        })\n                continue\n            if \"pokemon_data\" in inv_data:\n                pokemon = inv_data.get(\"pokemon_data\", {})\n                if pokemon.get(\"is_egg\", False) and \"egg_incubator_id\" not in pokemon:\n                    temp_eggs.append({\n                        \"id\": pokemon.get(\"id\", -1),\n                        \"km\": pokemon.get(\"egg_km_walked_target\", -1),\n                        \"used\": False\n                    })\n                elif 'is_egg' not in pokemon and pokemon['id'] in lookup_ids:\n                    pokemon.update({\n                        \"iv\": [\n                            pokemon.get('individual_attack', 0),\n                            pokemon.get('individual_defense', 0),\n                            pokemon.get('individual_stamina', 0)\n                        ]})\n                    matched_pokemon.append(pokemon)\n                continue\n            if \"player_stats\" in inv_data:\n                self.km_walked = inv_data.get(\"player_stats\", {}).get(\"km_walked\", 0)\n        if temp_used_incubators:\n            self.used_incubators = temp_used_incubators\n        if temp_ready_incubators:\n            self.ready_incubators = temp_ready_incubators\n        if temp_eggs:\n            self.eggs = temp_eggs\n        return matched_pokemon\n\n    def _hatch_eggs(self):\n        response_dict = self.bot.api.get_hatched_eggs()\n        log_color = 'green'\n        try:\n            result = reduce(dict.__getitem__, [\"responses\", \"GET_HATCHED_EGGS\"], response_dict)\n        except KeyError:\n            return\n        pokemon_ids = []\n        if 'pokemon_id' in result:\n            pokemon_ids = [id for id in result['pokemon_id']]\n        stardust = result.get('stardust_awarded', \"error\")\n        candy = result.get('candy_awarded', \"error\")\n        xp = result.get('experience_awarded', \"error\")\n        sleep(self.hatching_animation_delay)\n        self.bot.latest_inventory = None\n        try:\n            pokemon_data = self._check_inventory(pokemon_ids)\n            for pokemon in pokemon_data:\n                # pokemon ids seem to be offset by one\n                if pokemon['pokemon_id']!=-1:\n                    pokemon['name'] = self.bot.pokemon_list[(pokemon.get('pokemon_id')-1)]['Name']\n                else:\n                    pokemon['name'] = \"error\"\n        except:\n            pokemon_data = [{\"name\":\"error\",\"cp\":\"error\",\"iv\":\"error\"}]\n        if not pokemon_ids or pokemon_data[0]['name'] == \"error\":\n            self.emit_event(\n                'egg_hatched',\n                data={\n                    'pokemon': 'error',\n                    'cp': 'error',\n                    'iv': 'error',\n                    'exp': 'error',\n                    'stardust': 'error',\n                    'candy': 'error',\n                }\n            )\n            return\n        for i in range(len(pokemon_data)):\n            msg = \"Egg hatched with a {pokemon} (CP {cp} - IV {iv}), {exp} exp, {stardust} stardust and {candy} candies.\"\n            self.bot.metrics.hatched_eggs(1)\n            self.emit_event(\n                'egg_hatched',\n                formatted=msg,\n                data={\n                    'pokemon': pokemon_data[i]['name'],\n                    'cp': pokemon_data[i]['cp'],\n                    'iv': \"{} {}\".format(\n                        \"/\".join(map(str, pokemon_data[i]['iv'])),\n                        round(sum(pokemon_data[i]['iv'])/self.max_iv, 2)\n                    ),\n                    'exp': xp[i],\n                    'stardust': stardust[i],\n                    'candy': candy[i],\n                }\n            )\n\n    def _print_eggs(self):\n        if not self.used_incubators:\n            return\n\n        self.used_incubators.sort(key=lambda x: x.get(\"km\"))\n        \n        eggs = ['{:.2f}/{} km'.format(e['km_needed']-e['km']+self.km_walked, e['km_needed']) for e in self.used_incubators]\n\n        self.emit_event(\n                    'next_egg_incubates',\n                    formatted='Eggs incubating: [{eggs}] (Eggs left: {eggs_left}, Incubating: {eggs_inc})',\n                    data={\n                        'eggs_left': len(self.eggs),\n                        'eggs_inc': len(self.used_incubators),\n                        'eggs': ', '.join(eggs)\n                    }\n                )\n        \n    def _should_print(self):\n        \"\"\"\n        Returns a value indicating whether the eggs should be displayed.\n        :return: True if the stats should be displayed; otherwise, False.\n        :rtype: bool\n        \"\"\"\n        return self.next_update is None or datetime.now() >= self.next_update\n\n    def _compute_next_update(self):\n        \"\"\"\n        Computes the next update datetime based on the minimum update interval.\n        :return: Nothing.\n        :rtype: None\n        \"\"\"\n        self.next_update = datetime.now() + timedelta(seconds=self.min_interval)", "path": "pokemongo_bot/cell_workers/incubate_eggs.py"}]}