We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Trying to Incubate Eggs Always
Same issue for me
 #4875 

> I was listening to events via websocket. I realized that it always try to incubate eggs. While I'm listening events these logs appear every 5-10 secs.
> 
> Attempting to apply incubator EggIncubatorProto7823468502291754353 to egg 14174621514891967477
> Incubator in use.

But restarting bot is not a solution for me. 


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

{"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@@ -176,14 +176,10 @@\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_breakable_incubators:\n-            self.ready_breakable_incubators = temp_ready_breakable_incubators\n-        if temp_ready_infinite_incubators:\n-            self.ready_infinite_incubators = temp_ready_infinite_incubators\n-        if temp_eggs:\n-            self.eggs = temp_eggs\n+        self.used_incubators = temp_used_incubators\n+        self.ready_breakable_incubators = temp_ready_breakable_incubators\n+        self.ready_infinite_incubators = temp_ready_infinite_incubators\n+        self.eggs = temp_eggs\n         return matched_pokemon\n \n     def _hatch_eggs(self):\n", "issue": "Trying to Incubate Eggs Always\nSame issue for me\n #4875 \n\n> I was listening to events via websocket. I realized that it always try to incubate eggs. While I'm listening events these logs appear every 5-10 secs.\n> \n> Attempting to apply incubator EggIncubatorProto7823468502291754353 to egg 14174621514891967477\n> Incubator in use.\n\nBut restarting bot is not a solution for me. \n\n", "before_files": [{"content": "from datetime import datetime, timedelta\n\nfrom pokemongo_bot import inventory\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_breakable_incubators = []\n        self.ready_infinite_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.infinite_longer_eggs_first = self.config.get(\"infinite_longer_eggs_first\", False)\n        self.breakable_longer_eggs_first = self.config.get(\"breakable_longer_eggs_first\", True)\n        self.min_interval = self.config.get('min_interval', 120)\n\n        self.breakable_incubator = self.config.get(\"breakable\", [2,5,10])\n        self.infinite_incubator = self.config.get(\"infinite\", [2,5,10])\n\n    def work(self):\n        try:\n            self._check_inventory()\n        except:\n            return\n\n        should_print = self._should_print()\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                should_print = False\n            else:\n                self.bot.metrics.next_hatching_km(km_left)\n\n        if should_print:\n            self._print_eggs()\n            self._compute_next_update()\n\n        IncubateEggs.last_km_walked = self.km_walked\n\n        # if there is a ready infinite incubator\n        if self.ready_infinite_incubators:\n            # get available eggs\n            eggs = self._filter_sort_eggs(self.infinite_incubator,\n                    self.infinite_longer_eggs_first)\n            self._apply_incubators(eggs, self.ready_infinite_incubators)\n\n        if self.ready_breakable_incubators:\n            # get available eggs\n            eggs = self._filter_sort_eggs(self.breakable_incubator,\n                    self.breakable_longer_eggs_first)\n            self._apply_incubators(eggs, self.ready_breakable_incubators)\n\n\n    def _filter_sort_eggs(self, allowed, sorting):\n        eligible_eggs = filter(lambda egg: int(egg[\"km\"]) in allowed, self.eggs)\n        eligible_eggs.sort(key=lambda egg: egg[\"km\"], reverse=sorting)\n\n        return eligible_eggs\n\n\n    def _apply_incubators(self, available_eggs, available_incubators):\n\n        for incubator in available_incubators:\n            for egg in available_eggs:\n                if egg[\"used\"] or egg[\"km\"] == -1:\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        if lookup_ids:\n            inventory.refresh_inventory()\n        matched_pokemon = []\n        temp_eggs = []\n        temp_used_incubators = []\n        temp_ready_breakable_incubators = []\n        temp_ready_infinite_incubators = []\n        inv = inventory.jsonify_inventory()\n        for inv_data in inv:\n            inv_data = inv_data.get(\"inventory_item_data\", {})\n            if \"egg_incubators\" in inv_data:\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', 0)\n                        km_walked = incubator.get('target_km_walked', 0)\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                        if incubator.get('uses_remaining') is not None:\n                            temp_ready_breakable_incubators.append({\n                                \"id\": incubator.get('id', -1)\n                            })\n                        else:\n                            temp_ready_infinite_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_breakable_incubators:\n            self.ready_breakable_incubators = temp_ready_breakable_incubators\n        if temp_ready_infinite_incubators:\n            self.ready_infinite_incubators = temp_ready_infinite_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        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                    #remove as egg and add as pokemon\n                    inventory.pokemons().remove(pokemon['id'])\n                    inventory.pokemons().add(inventory.Pokemon(pokemon))\n                else:\n                    pokemon['name'] = \"error\"\n        except:\n            pokemon_data = [{\"name\":\"error\", \"cp\":\"error\", \"iv\":\"error\"}]\n        if not pokemon_ids or not pokemon_data 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            # hatching egg gets exp too!\n            inventory.player().exp += xp[i]\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)\n", "path": "pokemongo_bot/cell_workers/incubate_eggs.py"}], "after_files": [{"content": "from datetime import datetime, timedelta\n\nfrom pokemongo_bot import inventory\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_breakable_incubators = []\n        self.ready_infinite_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.infinite_longer_eggs_first = self.config.get(\"infinite_longer_eggs_first\", False)\n        self.breakable_longer_eggs_first = self.config.get(\"breakable_longer_eggs_first\", True)\n        self.min_interval = self.config.get('min_interval', 120)\n\n        self.breakable_incubator = self.config.get(\"breakable\", [2,5,10])\n        self.infinite_incubator = self.config.get(\"infinite\", [2,5,10])\n\n    def work(self):\n        try:\n            self._check_inventory()\n        except:\n            return\n\n        should_print = self._should_print()\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                should_print = False\n            else:\n                self.bot.metrics.next_hatching_km(km_left)\n\n        if should_print:\n            self._print_eggs()\n            self._compute_next_update()\n\n        IncubateEggs.last_km_walked = self.km_walked\n\n        # if there is a ready infinite incubator\n        if self.ready_infinite_incubators:\n            # get available eggs\n            eggs = self._filter_sort_eggs(self.infinite_incubator,\n                    self.infinite_longer_eggs_first)\n            self._apply_incubators(eggs, self.ready_infinite_incubators)\n\n        if self.ready_breakable_incubators:\n            # get available eggs\n            eggs = self._filter_sort_eggs(self.breakable_incubator,\n                    self.breakable_longer_eggs_first)\n            self._apply_incubators(eggs, self.ready_breakable_incubators)\n\n\n    def _filter_sort_eggs(self, allowed, sorting):\n        eligible_eggs = filter(lambda egg: int(egg[\"km\"]) in allowed, self.eggs)\n        eligible_eggs.sort(key=lambda egg: egg[\"km\"], reverse=sorting)\n\n        return eligible_eggs\n\n\n    def _apply_incubators(self, available_eggs, available_incubators):\n\n        for incubator in available_incubators:\n            for egg in available_eggs:\n                if egg[\"used\"] or egg[\"km\"] == -1:\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        if lookup_ids:\n            inventory.refresh_inventory()\n        matched_pokemon = []\n        temp_eggs = []\n        temp_used_incubators = []\n        temp_ready_breakable_incubators = []\n        temp_ready_infinite_incubators = []\n        inv = inventory.jsonify_inventory()\n        for inv_data in inv:\n            inv_data = inv_data.get(\"inventory_item_data\", {})\n            if \"egg_incubators\" in inv_data:\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', 0)\n                        km_walked = incubator.get('target_km_walked', 0)\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                        if incubator.get('uses_remaining') is not None:\n                            temp_ready_breakable_incubators.append({\n                                \"id\": incubator.get('id', -1)\n                            })\n                        else:\n                            temp_ready_infinite_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        self.used_incubators = temp_used_incubators\n        self.ready_breakable_incubators = temp_ready_breakable_incubators\n        self.ready_infinite_incubators = temp_ready_infinite_incubators\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        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                    #remove as egg and add as pokemon\n                    inventory.pokemons().remove(pokemon['id'])\n                    inventory.pokemons().add(inventory.Pokemon(pokemon))\n                else:\n                    pokemon['name'] = \"error\"\n        except:\n            pokemon_data = [{\"name\":\"error\", \"cp\":\"error\", \"iv\":\"error\"}]\n        if not pokemon_ids or not pokemon_data 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            # hatching egg gets exp too!\n            inventory.player().exp += xp[i]\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)\n", "path": "pokemongo_bot/cell_workers/incubate_eggs.py"}]}