Add Kwik Trip
This commit is contained in:
parent
4c4b37e74e
commit
d75b833911
|
@ -6,6 +6,7 @@ import amtrakLayer from './amtrak/layer.js';
|
|||
import arenasLayer from './nhl-arenas/layer.js';
|
||||
import menardsLayer from './menards/layer.js';
|
||||
import culversLayer from './culvers/layer.js';
|
||||
import kwikTripLayer from './kwik-trip/layer.js';
|
||||
|
||||
const layerCategories = [
|
||||
{
|
||||
|
@ -66,6 +67,10 @@ const layerCategories = [
|
|||
name: "Culver's",
|
||||
layer: culversLayer,
|
||||
},
|
||||
{
|
||||
name: "Kwik Trip/Kwik Star",
|
||||
layer: kwikTripLayer,
|
||||
}
|
||||
]
|
||||
}
|
||||
];
|
||||
|
|
23
layers/kwik-trip/README.md
Normal file
23
layers/kwik-trip/README.md
Normal file
|
@ -0,0 +1,23 @@
|
|||
See also https://chandlerswift.com/2022/04/16/the-holy-trinity.html
|
||||
|
||||
```python
|
||||
# Kwik Trip
|
||||
# Export to CSV from https://www.kwiktrip.com/Maps-Downloads/Store-List
|
||||
print("Searching for Kwik Trip locations")
|
||||
kwiktrip_count = 0
|
||||
with open('stores.csv') as f:
|
||||
reader = csv.DictReader(f)
|
||||
for row in reader:
|
||||
kwiktrip_count += 1
|
||||
stores.append({
|
||||
'chain': "Kwik Trip",
|
||||
'lat': float(row['Latitude']),
|
||||
'long': float(row['Longitude']),
|
||||
'address': row['Address'].title(),
|
||||
'city': row['City'].title(),
|
||||
'state': row['State'],
|
||||
'zip': row['Zip'],
|
||||
'website': f"https://www.kwiktrip.com/locator/store?id={row['Store Number']}",
|
||||
})
|
||||
print(f"{kwiktrip_count} locations found")
|
||||
```
|
48
layers/kwik-trip/get_data.py
Executable file
48
layers/kwik-trip/get_data.py
Executable file
|
@ -0,0 +1,48 @@
|
|||
#!/usr/bin/env python3
|
||||
|
||||
import requests
|
||||
import json
|
||||
from bs4 import BeautifulSoup
|
||||
|
||||
print("Searching for Kwik Trip locations")
|
||||
response = requests.get('https://www.kwiktrip.com/Maps-Downloads/Store-List')
|
||||
|
||||
# HACK HACK HACK
|
||||
soup = BeautifulSoup(response.text, 'html.parser')
|
||||
table = soup.find('table') # there's only one, currently; no identifying ID or anything
|
||||
headers = [th.get_text() for th in table.find('thead').find_all('th')]
|
||||
|
||||
# turn it into a reasonable dict
|
||||
raw_stores = []
|
||||
for row in table.find('tbody').find_all('tr'):
|
||||
store = {}
|
||||
for (header, cell) in zip(headers, row.find_all('td')):
|
||||
store[header] = cell.get_text()
|
||||
raw_stores.append(store)
|
||||
print(f"""{len(raw_stores)} locations found""")
|
||||
|
||||
# turn _that_ into GeoJSON Features
|
||||
stores = []
|
||||
for store in raw_stores:
|
||||
stores.append({
|
||||
"type": "Feature",
|
||||
"geometry": {
|
||||
"type": "Point",
|
||||
"coordinates": [float(store['Longitude']), float(store['Latitude'])], # yes, [lon, lat] since it's [x, y]
|
||||
},
|
||||
"properties": {
|
||||
'address': store['Address'].title(),
|
||||
'city': store['City'].title(),
|
||||
'state': store['State'],
|
||||
'zip': store['Zip'],
|
||||
'website': f"https://www.kwiktrip.com/locator/store?id={store['Store Number']}",
|
||||
},
|
||||
})
|
||||
|
||||
geojson = {
|
||||
"type": "FeatureCollection",
|
||||
"features": stores,
|
||||
}
|
||||
|
||||
with open("kwik-trip-data.geojson", "w") as f:
|
||||
f.write(json.dumps(geojson))
|
24
layers/kwik-trip/layer.js
Normal file
24
layers/kwik-trip/layer.js
Normal file
|
@ -0,0 +1,24 @@
|
|||
import VectorLayer from 'ol/layer/Vector';
|
||||
import {Vector as VectorSource} from 'ol/source.js';
|
||||
import GeoJSON from 'ol/format/GeoJSON.js';
|
||||
|
||||
import {Style} from 'ol/style.js';
|
||||
import Icon from 'ol/style/Icon.js';
|
||||
|
||||
import kwikTripURL from '/data/kwik-trip-data.geojson?url'; // TODO: remove `?url`?
|
||||
import pinURL from '/layers/kwik-trip/pin.svg?url'; // TODO: remove `?url`?
|
||||
|
||||
const vectorLayer = new VectorLayer({
|
||||
source: new VectorSource({
|
||||
url: kwikTripURL,
|
||||
format: new GeoJSON,
|
||||
}),
|
||||
style: new Style({
|
||||
image: new Icon({
|
||||
anchor: [0.5, 1],
|
||||
src: pinURL,
|
||||
}),
|
||||
}),
|
||||
});
|
||||
|
||||
export default vectorLayer;
|
111
layers/kwik-trip/pin.svg
Normal file
111
layers/kwik-trip/pin.svg
Normal file
|
@ -0,0 +1,111 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
viewBox="0 0 384 512"
|
||||
width="40px"
|
||||
height="30px"
|
||||
version="1.1"
|
||||
id="svg873"
|
||||
sodipodi:docname="kwiktrip-location-pin-solid.svg"
|
||||
inkscape:version="1.1.2 (0a00cf5339, 2022-02-04, custom)"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<defs
|
||||
id="defs877">
|
||||
<inkscape:path-effect
|
||||
effect="bspline"
|
||||
id="path-effect6210"
|
||||
is_visible="true"
|
||||
lpeversion="1"
|
||||
weight="33.333333"
|
||||
steps="2"
|
||||
helper_size="0"
|
||||
apply_no_weight="true"
|
||||
apply_with_weight="true"
|
||||
only_selected="false" />
|
||||
<inkscape:path-effect
|
||||
effect="bspline"
|
||||
id="path-effect6206"
|
||||
is_visible="true"
|
||||
lpeversion="1"
|
||||
weight="33.333333"
|
||||
steps="2"
|
||||
helper_size="0"
|
||||
apply_no_weight="true"
|
||||
apply_with_weight="true"
|
||||
only_selected="false" />
|
||||
<inkscape:path-effect
|
||||
effect="bspline"
|
||||
id="path-effect5933"
|
||||
is_visible="true"
|
||||
lpeversion="1"
|
||||
weight="33.333333"
|
||||
steps="2"
|
||||
helper_size="0"
|
||||
apply_no_weight="true"
|
||||
apply_with_weight="true"
|
||||
only_selected="false" />
|
||||
<inkscape:path-effect
|
||||
effect="bspline"
|
||||
id="path-effect5817"
|
||||
is_visible="true"
|
||||
lpeversion="1"
|
||||
weight="33.333333"
|
||||
steps="2"
|
||||
helper_size="0"
|
||||
apply_no_weight="true"
|
||||
apply_with_weight="true"
|
||||
only_selected="false" />
|
||||
<mask
|
||||
maskUnits="userSpaceOnUse"
|
||||
id="mask5454">
|
||||
<path
|
||||
d="m 384,192 c 0,87.4 -117,243 -168.3,307.2 -12.3,15.3 -35.1,15.3 -47.4,0 C 116.1,435 -1.4e-6,279.4 -1.4e-6,192 -1.4e-6,85.96 85.959999,0 192,0 245.96029,0 294.73775,22.2758 329.62577,58.13661 363.27205,92.72104 384,139.94065 384,192 Z"
|
||||
id="path5456"
|
||||
sodipodi:nodetypes="sccssss"
|
||||
style="fill:#ffffff;fill-opacity:1" />
|
||||
</mask>
|
||||
</defs>
|
||||
<sodipodi:namedview
|
||||
id="namedview875"
|
||||
pagecolor="#505050"
|
||||
bordercolor="#eeeeee"
|
||||
borderopacity="1"
|
||||
inkscape:pageshadow="0"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pagecheckerboard="0"
|
||||
showgrid="false"
|
||||
inkscape:zoom="1.1255704"
|
||||
inkscape:cx="-124.38138"
|
||||
inkscape:cy="258.09136"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1080"
|
||||
inkscape:window-x="1920"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="svg873" />
|
||||
<!--! Font Awesome Pro 6.0.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2022 Fonticons, Inc. -->
|
||||
<path
|
||||
d="m 384,192 c 0,87.4 -117,243 -168.3,307.2 -12.3,15.3 -35.1,15.3 -47.4,0 C 116.1,435 0,279.4 0,192 0,85.96 85.96,0 192,0 245.96029,0 294.73775,22.275796 329.62577,58.136607 363.27205,92.721042 384,139.94065 384,192 Z"
|
||||
id="path871"
|
||||
sodipodi:nodetypes="sccssss"
|
||||
style="fill:#c8102e;fill-opacity:1" />
|
||||
<g
|
||||
id="g838"
|
||||
transform="matrix(0.73027096,0,0,0.73027096,52.207956,54.279026)">
|
||||
<path
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:0.270601"
|
||||
d="m 131.77301,84.822086 c 0,0 -48.244176,-0.655215 -48.244176,-0.655215 0,0 -59.822086,175.480979 -59.822086,175.480979 m 0,0 c 0,0 49.349694,0.85276 49.349694,0.85276 0,0 16.217178,-52.27484 16.217178,-52.27484 0,0 31.87975,-28.89325 31.87975,-28.89325 0,0 6.63681,1.05766 6.63681,1.05766 0,0 12.96074,78.88712 12.96074,78.88712 0,0 49.16196,-0.42454 49.16196,-0.42454 0,0 -18.9276,-117.53006 -18.9276,-117.53006 0,0 60.87362,-55.928835 60.87362,-55.928835 0,0 -61.62945,-0.866258 -61.62945,-0.866258 0,0 -58.26258,65.289573 -58.26258,65.289573 0,0 -3.38527,-2.31779 -3.38527,-2.31779 0,0 23.19141,-62.677304 23.19141,-62.677304"
|
||||
id="path6204"
|
||||
inkscape:path-effect="#path-effect6206"
|
||||
inkscape:original-d="M 131.77301,84.822086 83.528834,84.166871 23.706748,259.64785 m 0,0 49.349694,0.85276 16.217178,-52.27484 31.87975,-28.89325 6.63681,1.05766 12.96074,78.88712 49.16196,-0.42454 -18.9276,-117.53006 60.87362,-55.928835 -61.62945,-0.866258 -58.26258,65.289573 -3.38527,-2.31779 23.19141,-62.677304" />
|
||||
<path
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:0"
|
||||
d="m 260.7411,174.81902 c 0,0 -55.8049,-0.24111 -55.8049,-0.24111 0,0 9.69141,-29.53006 9.69141,-29.53006 0,0 148.77974,2.72506 148.77974,2.72506 0,0 -10.45608,28.08411 -10.45608,28.08411 0,0 -49.78553,-0.0642 -49.78553,-0.0642 0,0 -39.56674,142.51108 -39.56674,142.51108 0,0 -42.44376,-0.31234 -42.44376,-0.31234 0,0 39.58586,-143.17254 39.58586,-143.17254 z"
|
||||
id="path6208"
|
||||
inkscape:path-effect="#path-effect6210"
|
||||
inkscape:original-d="m 260.7411,174.81902 -55.8049,-0.24111 9.69141,-29.53006 148.77974,2.72506 -10.45608,28.08411 -49.78553,-0.0642 -39.56674,142.51108 -42.44376,-0.31234 z"
|
||||
sodipodi:nodetypes="ccccccccc" />
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 5.1 KiB |
Loading…
Reference in a new issue