prompt: You will be provided with a partial code base and an issue statement explaining a problem to resolve.
  <issue>
  Spider tijuanaflats is broken
  During the global build at 2021-05-26-14-42-23, spider **tijuanaflats** failed with **0 features** and **0 errors**.
  
  Here's [the log](https://data.alltheplaces.xyz/runs/2021-05-26-14-42-23/logs/tijuanaflats.log) and [the output](https://data.alltheplaces.xyz/runs/2021-05-26-14-42-23/output/tijuanaflats.geojson) ([on a map](https://data.alltheplaces.xyz/map.html?show=https://data.alltheplaces.xyz/runs/2021-05-26-14-42-23/output/tijuanaflats.geojson))
  
  </issue>
  <code>
  [start of locations/spiders/tijuanaflats.py]
  1 # -*- coding: utf-8 -*-
  2 import scrapy
  3 import re
  4 
  5 from locations.items import GeojsonPointItem
  6 
  7 
  8 class TijuanaFlatsSpider(scrapy.Spider):
  9     name = "tijuanaflats"
  10     item_attributes = { 'brand': "Tijuana Flats" }
  11     allowed_domains = ['tijuanaflats.com']
  12     start_urls = (
  13         'https://tijuanaflats.com/wpsl_stores-sitemap.xml',
  14     )
  15 
  16     def parse(self, response):
  17         response.selector.remove_namespaces()
  18         city_urls = response.xpath('//url/loc/text()').extract()
  19         for path in city_urls:
  20             yield scrapy.Request(
  21                 path.strip(),
  22                 callback=self.parse_store,
  23             )
  24 
  25     def parse_store(self, response):
  26 
  27         if response.xpath('//table[@class="wpsl-opening-hours"]/tr').extract():
  28             storeHours = str(response.xpath('//table[@class="wpsl-opening-hours"]/tr').extract())
  29             storeHours = storeHours.replace('[','').replace(']','').replace("'",'').replace(',',' - ')
  30         else:
  31             storeHours = response.xpath('//table[@class="wpsl-opening-hours"]/tr').extract()
  32 
  33 
  34         properties = {
  35             'name': response.xpath('//h1[@class="entry-title"]/text()').extract_first(),
  36             'website': response.request.url,
  37             'ref': response.xpath('//h1[@class="entry-title"]/text()').extract_first(),
  38             'addr_full': response.xpath('//div[@class="wpsl-location-address"]/span[1]/text()').extract_first() + " " + response.xpath('//div[@class="wpsl-location-address"]/span[2]/text()').extract_first(),
  39             'city': response.xpath('//div[@class="wpsl-location-address"]/span[3]/text()').extract_first().rstrip(', '),
  40             'state': response.xpath('//div[@class="wpsl-location-address"]/span[4]/text()').extract_first().strip(),
  41             'postcode': response.xpath('//div[@class="wpsl-location-address"]/span[5]/text()').extract_first().strip(),
  42             'opening_hours': storeHours,
  43             'lat': float(response.xpath('//script/text()').extract()[-3].split('"lat":"')[1].split('"')[0]),
  44             'lon': float(response.xpath('//script/text()').extract()[-3].split('"lng":"')[1].split('"')[0]),
  45         }
  46 
  47         yield GeojsonPointItem(**properties)
  [end of locations/spiders/tijuanaflats.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/tijuanaflats.py b/locations/spiders/tijuanaflats.py
  --- a/locations/spiders/tijuanaflats.py
  +++ b/locations/spiders/tijuanaflats.py
  @@ -1,47 +1,45 @@
   # -*- coding: utf-8 -*-
  +import json
  +
   import scrapy
  -import re
   
   from locations.items import GeojsonPointItem
   
   
   class TijuanaFlatsSpider(scrapy.Spider):
       name = "tijuanaflats"
  -    item_attributes = { 'brand': "Tijuana Flats" }
  -    allowed_domains = ['tijuanaflats.com']
  -    start_urls = (
  -        'https://tijuanaflats.com/wpsl_stores-sitemap.xml',
  -    )
  +    item_attributes = {"brand": "Tijuana Flats", "brand_wikidata": "Q7801833"}
  +    allowed_domains = ["tijuanaflats.com"]
  +    start_urls = ("https://www.tijuanaflats.com/locations",)
   
       def parse(self, response):
  -        response.selector.remove_namespaces()
  -        city_urls = response.xpath('//url/loc/text()').extract()
  -        for path in city_urls:
  -            yield scrapy.Request(
  -                path.strip(),
  -                callback=self.parse_store,
  +        data = json.loads(
  +            response.xpath(
  +                '//tjs-view-locations/attribute::*[name()=":locations"]'
  +            ).extract_first()
  +        )
  +        for row in data:
  +            for ent in row["yoast_json_ld"][0]["@graph"]:
  +                if ent["@type"] == "WebPage" and row["slug"] in ent["url"]:
  +                    name = ent["name"]
  +
  +            # extract text from html snippet
  +            hours_of_operation = scrapy.Selector(text=row["acf"]["hours_of_operation"])
  +            opening_hours = "; ".join(
  +                a.strip() for a in hours_of_operation.xpath("//text()").extract()
               )
   
  -    def parse_store(self, response):
  -
  -        if response.xpath('//table[@class="wpsl-opening-hours"]/tr').extract():
  -            storeHours = str(response.xpath('//table[@class="wpsl-opening-hours"]/tr').extract())
  -            storeHours = storeHours.replace('[','').replace(']','').replace("'",'').replace(',',' - ')
  -        else:
  -            storeHours = response.xpath('//table[@class="wpsl-opening-hours"]/tr').extract()
  -
  -
  -        properties = {
  -            'name': response.xpath('//h1[@class="entry-title"]/text()').extract_first(),
  -            'website': response.request.url,
  -            'ref': response.xpath('//h1[@class="entry-title"]/text()').extract_first(),
  -            'addr_full': response.xpath('//div[@class="wpsl-location-address"]/span[1]/text()').extract_first() + " " + response.xpath('//div[@class="wpsl-location-address"]/span[2]/text()').extract_first(),
  -            'city': response.xpath('//div[@class="wpsl-location-address"]/span[3]/text()').extract_first().rstrip(', '),
  -            'state': response.xpath('//div[@class="wpsl-location-address"]/span[4]/text()').extract_first().strip(),
  -            'postcode': response.xpath('//div[@class="wpsl-location-address"]/span[5]/text()').extract_first().strip(),
  -            'opening_hours': storeHours,
  -            'lat': float(response.xpath('//script/text()').extract()[-3].split('"lat":"')[1].split('"')[0]),
  -            'lon': float(response.xpath('//script/text()').extract()[-3].split('"lng":"')[1].split('"')[0]),
  -        }
  -
  -        yield GeojsonPointItem(**properties)
  \ No newline at end of file
  +            properties = {
  +                "ref": row["slug"],
  +                "name": name,
  +                "lat": row["acf"]["physical_location"]["lat"],
  +                "lon": row["acf"]["physical_location"]["lng"],
  +                "addr_full": row["acf"]["address_1"],
  +                "city": row["acf"]["city"],
  +                "state": row["acf"]["state"],
  +                "postcode": row["acf"]["zip"],
  +                "phone": row["acf"]["contact_phone"],
  +                "website": f'https://www.tijuanaflats.com/locations/{row["slug"]}',
  +                "opening_hours": opening_hours,
  +            }
  +            yield GeojsonPointItem(**properties)
  
verification_info: {"golden_diff": "diff --git a/locations/spiders/tijuanaflats.py b/locations/spiders/tijuanaflats.py\n--- a/locations/spiders/tijuanaflats.py\n+++ b/locations/spiders/tijuanaflats.py\n@@ -1,47 +1,45 @@\n # -*- coding: utf-8 -*-\n+import json\n+\n import scrapy\n-import re\n \n from locations.items import GeojsonPointItem\n \n \n class TijuanaFlatsSpider(scrapy.Spider):\n     name = \"tijuanaflats\"\n-    item_attributes = { 'brand': \"Tijuana Flats\" }\n-    allowed_domains = ['tijuanaflats.com']\n-    start_urls = (\n-        'https://tijuanaflats.com/wpsl_stores-sitemap.xml',\n-    )\n+    item_attributes = {\"brand\": \"Tijuana Flats\", \"brand_wikidata\": \"Q7801833\"}\n+    allowed_domains = [\"tijuanaflats.com\"]\n+    start_urls = (\"https://www.tijuanaflats.com/locations\",)\n \n     def parse(self, response):\n-        response.selector.remove_namespaces()\n-        city_urls = response.xpath('//url/loc/text()').extract()\n-        for path in city_urls:\n-            yield scrapy.Request(\n-                path.strip(),\n-                callback=self.parse_store,\n+        data = json.loads(\n+            response.xpath(\n+                '//tjs-view-locations/attribute::*[name()=\":locations\"]'\n+            ).extract_first()\n+        )\n+        for row in data:\n+            for ent in row[\"yoast_json_ld\"][0][\"@graph\"]:\n+                if ent[\"@type\"] == \"WebPage\" and row[\"slug\"] in ent[\"url\"]:\n+                    name = ent[\"name\"]\n+\n+            # extract text from html snippet\n+            hours_of_operation = scrapy.Selector(text=row[\"acf\"][\"hours_of_operation\"])\n+            opening_hours = \"; \".join(\n+                a.strip() for a in hours_of_operation.xpath(\"//text()\").extract()\n             )\n \n-    def parse_store(self, response):\n-\n-        if response.xpath('//table[@class=\"wpsl-opening-hours\"]/tr').extract():\n-            storeHours = str(response.xpath('//table[@class=\"wpsl-opening-hours\"]/tr').extract())\n-            storeHours = storeHours.replace('[','').replace(']','').replace(\"'\",'').replace(',',' - ')\n-        else:\n-            storeHours = response.xpath('//table[@class=\"wpsl-opening-hours\"]/tr').extract()\n-\n-\n-        properties = {\n-            'name': response.xpath('//h1[@class=\"entry-title\"]/text()').extract_first(),\n-            'website': response.request.url,\n-            'ref': response.xpath('//h1[@class=\"entry-title\"]/text()').extract_first(),\n-            'addr_full': response.xpath('//div[@class=\"wpsl-location-address\"]/span[1]/text()').extract_first() + \" \" + response.xpath('//div[@class=\"wpsl-location-address\"]/span[2]/text()').extract_first(),\n-            'city': response.xpath('//div[@class=\"wpsl-location-address\"]/span[3]/text()').extract_first().rstrip(', '),\n-            'state': response.xpath('//div[@class=\"wpsl-location-address\"]/span[4]/text()').extract_first().strip(),\n-            'postcode': response.xpath('//div[@class=\"wpsl-location-address\"]/span[5]/text()').extract_first().strip(),\n-            'opening_hours': storeHours,\n-            'lat': float(response.xpath('//script/text()').extract()[-3].split('\"lat\":\"')[1].split('\"')[0]),\n-            'lon': float(response.xpath('//script/text()').extract()[-3].split('\"lng\":\"')[1].split('\"')[0]),\n-        }\n-\n-        yield GeojsonPointItem(**properties)\n\\ No newline at end of file\n+            properties = {\n+                \"ref\": row[\"slug\"],\n+                \"name\": name,\n+                \"lat\": row[\"acf\"][\"physical_location\"][\"lat\"],\n+                \"lon\": row[\"acf\"][\"physical_location\"][\"lng\"],\n+                \"addr_full\": row[\"acf\"][\"address_1\"],\n+                \"city\": row[\"acf\"][\"city\"],\n+                \"state\": row[\"acf\"][\"state\"],\n+                \"postcode\": row[\"acf\"][\"zip\"],\n+                \"phone\": row[\"acf\"][\"contact_phone\"],\n+                \"website\": f'https://www.tijuanaflats.com/locations/{row[\"slug\"]}',\n+                \"opening_hours\": opening_hours,\n+            }\n+            yield GeojsonPointItem(**properties)\n", "issue": "Spider tijuanaflats is broken\nDuring the global build at 2021-05-26-14-42-23, spider **tijuanaflats** failed with **0 features** and **0 errors**.\n\nHere's [the log](https://data.alltheplaces.xyz/runs/2021-05-26-14-42-23/logs/tijuanaflats.log) and [the output](https://data.alltheplaces.xyz/runs/2021-05-26-14-42-23/output/tijuanaflats.geojson) ([on a map](https://data.alltheplaces.xyz/map.html?show=https://data.alltheplaces.xyz/runs/2021-05-26-14-42-23/output/tijuanaflats.geojson))\n", "before_files": [{"content": "# -*- coding: utf-8 -*-\nimport scrapy\nimport re\n\nfrom locations.items import GeojsonPointItem\n\n\nclass TijuanaFlatsSpider(scrapy.Spider):\n    name = \"tijuanaflats\"\n    item_attributes = { 'brand': \"Tijuana Flats\" }\n    allowed_domains = ['tijuanaflats.com']\n    start_urls = (\n        'https://tijuanaflats.com/wpsl_stores-sitemap.xml',\n    )\n\n    def parse(self, response):\n        response.selector.remove_namespaces()\n        city_urls = response.xpath('//url/loc/text()').extract()\n        for path in city_urls:\n            yield scrapy.Request(\n                path.strip(),\n                callback=self.parse_store,\n            )\n\n    def parse_store(self, response):\n\n        if response.xpath('//table[@class=\"wpsl-opening-hours\"]/tr').extract():\n            storeHours = str(response.xpath('//table[@class=\"wpsl-opening-hours\"]/tr').extract())\n            storeHours = storeHours.replace('[','').replace(']','').replace(\"'\",'').replace(',',' - ')\n        else:\n            storeHours = response.xpath('//table[@class=\"wpsl-opening-hours\"]/tr').extract()\n\n\n        properties = {\n            'name': response.xpath('//h1[@class=\"entry-title\"]/text()').extract_first(),\n            'website': response.request.url,\n            'ref': response.xpath('//h1[@class=\"entry-title\"]/text()').extract_first(),\n            'addr_full': response.xpath('//div[@class=\"wpsl-location-address\"]/span[1]/text()').extract_first() + \" \" + response.xpath('//div[@class=\"wpsl-location-address\"]/span[2]/text()').extract_first(),\n            'city': response.xpath('//div[@class=\"wpsl-location-address\"]/span[3]/text()').extract_first().rstrip(', '),\n            'state': response.xpath('//div[@class=\"wpsl-location-address\"]/span[4]/text()').extract_first().strip(),\n            'postcode': response.xpath('//div[@class=\"wpsl-location-address\"]/span[5]/text()').extract_first().strip(),\n            'opening_hours': storeHours,\n            'lat': float(response.xpath('//script/text()').extract()[-3].split('\"lat\":\"')[1].split('\"')[0]),\n            'lon': float(response.xpath('//script/text()').extract()[-3].split('\"lng\":\"')[1].split('\"')[0]),\n        }\n\n        yield GeojsonPointItem(**properties)", "path": "locations/spiders/tijuanaflats.py"}]}