prompt: You will be provided with a partial code base and an issue statement explaining a problem to resolve.
  <issue>
  Spider argos is broken
  During the global build at 2021-08-25-14-42-15, spider **argos** failed with **0 features** and **0 errors**.
  
  Here's [the log](https://data.alltheplaces.xyz/runs/2021-08-25-14-42-15/logs/argos.txt) and [the output](https://data.alltheplaces.xyz/runs/2021-08-25-14-42-15/output/argos.geojson) ([on a map](https://data.alltheplaces.xyz/map.html?show=https://data.alltheplaces.xyz/runs/2021-08-25-14-42-15/output/argos.geojson))
  Spider argos is broken
  During the global build at 2021-05-26-14-42-23, spider **argos** failed with **0 features** and **0 errors**.
  
  Here's [the log](https://data.alltheplaces.xyz/runs/2021-05-26-14-42-23/logs/argos.log) and [the output](https://data.alltheplaces.xyz/runs/2021-05-26-14-42-23/output/argos.geojson) ([on a map](https://data.alltheplaces.xyz/map.html?show=https://data.alltheplaces.xyz/runs/2021-05-26-14-42-23/output/argos.geojson))
  
  </issue>
  <code>
  [start of locations/spiders/argos.py]
  1 import scrapy
  2 import re
  3 import json
  4 from locations.items import GeojsonPointItem
  5 
  6 
  7 class ArgosSpider(scrapy.Spider):
  8 
  9     name = "argos"
  10     item_attributes = {"brand": "Argos"}
  11     allowed_domains = ["www.argos.co.uk"]
  12     download_delay = 0.5
  13     start_urls = ("http://www.argos.co.uk/stores/",)
  14 
  15     def parse_stores(self, response):
  16         data = re.findall(r"window.INITIAL_STATE =[^<]+", response.text)
  17         json_data = json.loads(data[0].replace("window.INITIAL_STATE =", ""))
  18         properties = {
  19             "addr_full": json_data["store"]["store"]["address"],
  20             "phone": json_data["store"]["store"]["tel"],
  21             "city": json_data["store"]["store"]["town"],
  22             "state": "",
  23             "postcode": json_data["store"]["store"]["postcode"],
  24             "ref": json_data["store"]["store"]["id"],
  25             "website": response.url,
  26             "lat": float(json_data["store"]["store"]["lat"]),
  27             "lon": float(json_data["store"]["store"]["lng"]),
  28         }
  29 
  30         open_hours = ""
  31         for item in json_data["store"]["store"]["storeTimes"]:
  32             open_hours = open_hours + item["date"][:2] + " " + item["time"] + " ;"
  33         if open_hours:
  34             properties["opening_hours"] = open_hours
  35 
  36         yield GeojsonPointItem(**properties)
  37 
  38     def parse(self, response):
  39         urls = response.xpath('//div/div[@class="azsl-panel"]/ul/li/a/@href').extract()
  40         for path in urls:
  41             yield scrapy.Request(response.urljoin(path), callback=self.parse_stores)
  42
  [end of locations/spiders/argos.py]
  </code>
  
  I need you to solve this issue by generating a single patch file that I can apply directly to this repository using git apply. Please respond with a single patch file in the following format.
  <patch>
  diff --git a/file.py b/file.py
  --- a/file.py
  +++ b/file.py
  @@ -1,27 +1,35 @@
   def euclidean(a, b):
  -    while b:
  -        a, b = b, a % b
  -    return a
  +    if b == 0:
  +        return a
  +    return euclidean(b, a % b)
   
   
   def bresenham(x0, y0, x1, y1):
       points = []
       dx = abs(x1 - x0)
       dy = abs(y1 - y0)
  -    sx = 1 if x0 < x1 else -1
  -    sy = 1 if y0 < y1 else -1
  -    err = dx - dy
  +    x, y = x0, y0
  +    sx = -1 if x0 > x1 else 1
  +    sy = -1 if y0 > y1 else 1
   
  -    while True:
  -        points.append((x0, y0))
  -        if x0 == x1 and y0 == y1:
  -            break
  -        e2 = 2 * err
  -        if e2 > -dy:
  -            err -= dy
  -            x0 += sx
  -        if e2 < dx:
  -            err += dx
  -            y0 += sy
  +    if dx > dy:
  +        err = dx / 2.0
  +        while x != x1:
  +            points.append((x, y))
  +            err -= dy
  +            if err < 0:
  +                y += sy
  +                err += dx
  +            x += sx
  +    else:
  +        err = dy / 2.0
  +        while y != y1:
  +            points.append((x, y))
  +            err -= dx
  +            if err < 0:
  +                x += sx
  +                err += dy
  +            y += sy
  +
  +    points.append((x, y))
       return points
  
  </patch>
golden_diff: diff --git a/locations/spiders/argos.py b/locations/spiders/argos.py
  --- a/locations/spiders/argos.py
  +++ b/locations/spiders/argos.py
  @@ -1,41 +1,58 @@
  -import scrapy
   import re
   import json
  -from locations.items import GeojsonPointItem
   
  +from locations.items import GeojsonPointItem
  +from locations.hours import OpeningHours
  +from scrapy.spiders import SitemapSpider
   
  -class ArgosSpider(scrapy.Spider):
   
  +class ArgosSpider(SitemapSpider):
       name = "argos"
  -    item_attributes = {"brand": "Argos"}
  +    item_attributes = {"brand": "Argos", "brand_wikidata": "Q4789707"}
       allowed_domains = ["www.argos.co.uk"]
       download_delay = 0.5
  -    start_urls = ("http://www.argos.co.uk/stores/",)
  +    sitemap_urls = [
  +        "https://www.argos.co.uk/stores_sitemap.xml",
  +    ]
  +    sitemap_rules = [
  +        (
  +            r"https://www.argos.co.uk/stores/([\d]+)-([\w-]+)",
  +            "parse",
  +        ),
  +    ]
  +    custom_settings = {
  +        "USER_AGENT": "Mozilla/5.0 (X11; Linux x86_64; rv:99.0) Gecko/20100101 Firefox/99.0"
  +    }
   
  -    def parse_stores(self, response):
  +    def parse(self, response):
           data = re.findall(r"window.INITIAL_STATE =[^<]+", response.text)
           json_data = json.loads(data[0].replace("window.INITIAL_STATE =", ""))
           properties = {
  -            "addr_full": json_data["store"]["store"]["address"],
  +            "street_address": json_data["store"]["store"]["address"],
               "phone": json_data["store"]["store"]["tel"],
               "city": json_data["store"]["store"]["town"],
  -            "state": "",
  +            "name": json_data["store"]["store"]["name"],
               "postcode": json_data["store"]["store"]["postcode"],
               "ref": json_data["store"]["store"]["id"],
               "website": response.url,
               "lat": float(json_data["store"]["store"]["lat"]),
               "lon": float(json_data["store"]["store"]["lng"]),
  +            "extras": {
  +                "store_type": json_data["store"]["store"]["type"],
  +            },
           }
   
  -        open_hours = ""
  +        oh = OpeningHours()
           for item in json_data["store"]["store"]["storeTimes"]:
  -            open_hours = open_hours + item["date"][:2] + " " + item["time"] + " ;"
  -        if open_hours:
  -            properties["opening_hours"] = open_hours
  +            open_time, close_time = item["time"].split(" - ")
  +            if (
  +                open_time
  +                and not open_time.isspace()
  +                and close_time
  +                and not close_time.isspace()
  +            ):
  +                oh.add_range(item["date"][:2], open_time, close_time)
   
  -        yield GeojsonPointItem(**properties)
  +        properties["opening_hours"] = oh.as_opening_hours()
   
  -    def parse(self, response):
  -        urls = response.xpath('//div/div[@class="azsl-panel"]/ul/li/a/@href').extract()
  -        for path in urls:
  -            yield scrapy.Request(response.urljoin(path), callback=self.parse_stores)
  +        yield GeojsonPointItem(**properties)
  
verification_info: {"golden_diff": "diff --git a/locations/spiders/argos.py b/locations/spiders/argos.py\n--- a/locations/spiders/argos.py\n+++ b/locations/spiders/argos.py\n@@ -1,41 +1,58 @@\n-import scrapy\n import re\n import json\n-from locations.items import GeojsonPointItem\n \n+from locations.items import GeojsonPointItem\n+from locations.hours import OpeningHours\n+from scrapy.spiders import SitemapSpider\n \n-class ArgosSpider(scrapy.Spider):\n \n+class ArgosSpider(SitemapSpider):\n     name = \"argos\"\n-    item_attributes = {\"brand\": \"Argos\"}\n+    item_attributes = {\"brand\": \"Argos\", \"brand_wikidata\": \"Q4789707\"}\n     allowed_domains = [\"www.argos.co.uk\"]\n     download_delay = 0.5\n-    start_urls = (\"http://www.argos.co.uk/stores/\",)\n+    sitemap_urls = [\n+        \"https://www.argos.co.uk/stores_sitemap.xml\",\n+    ]\n+    sitemap_rules = [\n+        (\n+            r\"https://www.argos.co.uk/stores/([\\d]+)-([\\w-]+)\",\n+            \"parse\",\n+        ),\n+    ]\n+    custom_settings = {\n+        \"USER_AGENT\": \"Mozilla/5.0 (X11; Linux x86_64; rv:99.0) Gecko/20100101 Firefox/99.0\"\n+    }\n \n-    def parse_stores(self, response):\n+    def parse(self, response):\n         data = re.findall(r\"window.INITIAL_STATE =[^<]+\", response.text)\n         json_data = json.loads(data[0].replace(\"window.INITIAL_STATE =\", \"\"))\n         properties = {\n-            \"addr_full\": json_data[\"store\"][\"store\"][\"address\"],\n+            \"street_address\": json_data[\"store\"][\"store\"][\"address\"],\n             \"phone\": json_data[\"store\"][\"store\"][\"tel\"],\n             \"city\": json_data[\"store\"][\"store\"][\"town\"],\n-            \"state\": \"\",\n+            \"name\": json_data[\"store\"][\"store\"][\"name\"],\n             \"postcode\": json_data[\"store\"][\"store\"][\"postcode\"],\n             \"ref\": json_data[\"store\"][\"store\"][\"id\"],\n             \"website\": response.url,\n             \"lat\": float(json_data[\"store\"][\"store\"][\"lat\"]),\n             \"lon\": float(json_data[\"store\"][\"store\"][\"lng\"]),\n+            \"extras\": {\n+                \"store_type\": json_data[\"store\"][\"store\"][\"type\"],\n+            },\n         }\n \n-        open_hours = \"\"\n+        oh = OpeningHours()\n         for item in json_data[\"store\"][\"store\"][\"storeTimes\"]:\n-            open_hours = open_hours + item[\"date\"][:2] + \" \" + item[\"time\"] + \" ;\"\n-        if open_hours:\n-            properties[\"opening_hours\"] = open_hours\n+            open_time, close_time = item[\"time\"].split(\" - \")\n+            if (\n+                open_time\n+                and not open_time.isspace()\n+                and close_time\n+                and not close_time.isspace()\n+            ):\n+                oh.add_range(item[\"date\"][:2], open_time, close_time)\n \n-        yield GeojsonPointItem(**properties)\n+        properties[\"opening_hours\"] = oh.as_opening_hours()\n \n-    def parse(self, response):\n-        urls = response.xpath('//div/div[@class=\"azsl-panel\"]/ul/li/a/@href').extract()\n-        for path in urls:\n-            yield scrapy.Request(response.urljoin(path), callback=self.parse_stores)\n+        yield GeojsonPointItem(**properties)\n", "issue": "Spider argos is broken\nDuring the global build at 2021-08-25-14-42-15, spider **argos** failed with **0 features** and **0 errors**.\n\nHere's [the log](https://data.alltheplaces.xyz/runs/2021-08-25-14-42-15/logs/argos.txt) and [the output](https://data.alltheplaces.xyz/runs/2021-08-25-14-42-15/output/argos.geojson) ([on a map](https://data.alltheplaces.xyz/map.html?show=https://data.alltheplaces.xyz/runs/2021-08-25-14-42-15/output/argos.geojson))\nSpider argos is broken\nDuring the global build at 2021-05-26-14-42-23, spider **argos** failed with **0 features** and **0 errors**.\n\nHere's [the log](https://data.alltheplaces.xyz/runs/2021-05-26-14-42-23/logs/argos.log) and [the output](https://data.alltheplaces.xyz/runs/2021-05-26-14-42-23/output/argos.geojson) ([on a map](https://data.alltheplaces.xyz/map.html?show=https://data.alltheplaces.xyz/runs/2021-05-26-14-42-23/output/argos.geojson))\n", "before_files": [{"content": "import scrapy\nimport re\nimport json\nfrom locations.items import GeojsonPointItem\n\n\nclass ArgosSpider(scrapy.Spider):\n\n    name = \"argos\"\n    item_attributes = {\"brand\": \"Argos\"}\n    allowed_domains = [\"www.argos.co.uk\"]\n    download_delay = 0.5\n    start_urls = (\"http://www.argos.co.uk/stores/\",)\n\n    def parse_stores(self, response):\n        data = re.findall(r\"window.INITIAL_STATE =[^<]+\", response.text)\n        json_data = json.loads(data[0].replace(\"window.INITIAL_STATE =\", \"\"))\n        properties = {\n            \"addr_full\": json_data[\"store\"][\"store\"][\"address\"],\n            \"phone\": json_data[\"store\"][\"store\"][\"tel\"],\n            \"city\": json_data[\"store\"][\"store\"][\"town\"],\n            \"state\": \"\",\n            \"postcode\": json_data[\"store\"][\"store\"][\"postcode\"],\n            \"ref\": json_data[\"store\"][\"store\"][\"id\"],\n            \"website\": response.url,\n            \"lat\": float(json_data[\"store\"][\"store\"][\"lat\"]),\n            \"lon\": float(json_data[\"store\"][\"store\"][\"lng\"]),\n        }\n\n        open_hours = \"\"\n        for item in json_data[\"store\"][\"store\"][\"storeTimes\"]:\n            open_hours = open_hours + item[\"date\"][:2] + \" \" + item[\"time\"] + \" ;\"\n        if open_hours:\n            properties[\"opening_hours\"] = open_hours\n\n        yield GeojsonPointItem(**properties)\n\n    def parse(self, response):\n        urls = response.xpath('//div/div[@class=\"azsl-panel\"]/ul/li/a/@href').extract()\n        for path in urls:\n            yield scrapy.Request(response.urljoin(path), callback=self.parse_stores)\n", "path": "locations/spiders/argos.py"}]}