mirror of
https://github.com/tomasriveral/ReSSPublica.git
synced 2026-08-11 18:28:38 +02:00
feeds: add places of worship per Religion in Bern
This commit is contained in:
Binary file not shown.
|
After Width: | Height: | Size: 296 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 299 KiB |
@@ -16,6 +16,11 @@ on:
|
||||
required: false
|
||||
default: "false"
|
||||
type: boolean
|
||||
forceGenerationBernPlacesOfWorship:
|
||||
description: "force feed generation of places of worship per religion in Bern"
|
||||
required: false
|
||||
default: "false"
|
||||
type: boolean
|
||||
|
||||
jobs:
|
||||
build:
|
||||
@@ -92,6 +97,31 @@ jobs:
|
||||
fi
|
||||
git commit -m "feeds: asian hornets sighting in Bern update $(date -u +%Y-%m-%d)"
|
||||
|
||||
- name: Generate feeds for places of worship per religion in Bern
|
||||
run: |
|
||||
if [ "${{ github.event_name }}" = "workflow_dispatch" ] && [ "${{ inputs.verbose }}" = "true" ]; then
|
||||
echo "Running in VERBOSE mode"
|
||||
if [ "${{ github.event_name }}" = "workflow_dispatch" ] && [ "${{ inputs.forceGenerationBernPlacesOfWorship }}" = "true" ]; then
|
||||
resspublica --force_gen_bernReligionMap --verbose
|
||||
else
|
||||
resspublica --gen_bernReligionMap --verbose
|
||||
fi
|
||||
else
|
||||
if [ "${{ github.event_name }}" = "workflow_dispatch" ] && [ "${{ inputs.forceGenerationBernPlacesOfWorship }}" = "true" ]; then
|
||||
resspublica --force_gen_bernReligionMap
|
||||
else
|
||||
resspublica --gen_bernReligionMap
|
||||
fi
|
||||
fi
|
||||
git add feed/ .cache/ assets/
|
||||
|
||||
if git diff --cached --quiet; then
|
||||
echo "No changes to commit"
|
||||
exit 0
|
||||
fi
|
||||
git commit -m "feeds: places of worship per Religion in Bern update $(date -u +%Y-%m-%d)"
|
||||
|
||||
|
||||
- name: Push changes
|
||||
run: |
|
||||
git push origin main
|
||||
|
||||
@@ -25,7 +25,9 @@ AI (ChatGPT 5.5 and Deepl) was used in this project for :
|
||||
* crafting the SPARQL requests (a language I had never heard of before this project)
|
||||
* minor debugging when alternative methods did not solve the problems.
|
||||
* German, Italian and Romansh translations.
|
||||
* counselling the right python libraries to use
|
||||
* help with Python libraries
|
||||
|
||||
All code was reviewed by a human.
|
||||
|
||||
## Contributing
|
||||
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
<?xml version='1.0' encoding='UTF-8'?>
|
||||
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="de">
|
||||
<id>https://raw.githubusercontent.com/tomasriveral/ReSSPublica/refs/heads/main/feed/atom/de/gotteshauserNachReligionImKantonBern</id>
|
||||
<title>Gotteshäuser nach Religion im Kanton Bern</title>
|
||||
<updated>2026-06-17T21:51:13.499795+02:00</updated>
|
||||
<author>
|
||||
<name>ReSSPublica</name>
|
||||
</author>
|
||||
<link href="https://raw.githubusercontent.com/tomasriveral/ReSSPublica/refs/heads/main/feed/atom/de/gotteshauserNachReligionImKantonBern.atom" rel="self"/>
|
||||
<generator uri="https://lkiesow.github.io/python-feedgen" version="1.0.0">python-feedgen</generator>
|
||||
<subtitle>RSS-Feed der Gotteshäuser nach Religion im Kanton Bern</subtitle>
|
||||
</feed>
|
||||
@@ -0,0 +1,12 @@
|
||||
<?xml version='1.0' encoding='UTF-8'?>
|
||||
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="fr">
|
||||
<id>https://raw.githubusercontent.com/tomasriveral/ReSSPublica/refs/heads/main/feed/atom/fr/lieuDeCulteParReligionDansLeCantonDeBerne</id>
|
||||
<title>Lieu de culte par religion dans le canton de Berne</title>
|
||||
<updated>2026-06-17T21:51:13.497469+02:00</updated>
|
||||
<author>
|
||||
<name>ReSSPublica</name>
|
||||
</author>
|
||||
<link href="https://raw.githubusercontent.com/tomasriveral/ReSSPublica/refs/heads/main/feed/atom/fr/lieuDeCulteParReligionDansLeCantonDeBerne.atom" rel="self"/>
|
||||
<generator uri="https://lkiesow.github.io/python-feedgen" version="1.0.0">python-feedgen</generator>
|
||||
<subtitle>Flux RSS des Lieu de culte par religion dans le canton de Berne</subtitle>
|
||||
</feed>
|
||||
@@ -0,0 +1,13 @@
|
||||
<?xml version='1.0' encoding='UTF-8'?>
|
||||
<rss xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/" version="2.0">
|
||||
<channel>
|
||||
<title>Gotteshäuser nach Religion im Kanton Bern</title>
|
||||
<link>https://raw.githubusercontent.com/tomasriveral/ReSSPublica/refs/heads/main/feed/atom/de/gotteshauserNachReligionImKantonBern.atom</link>
|
||||
<description>RSS-Feed der Gotteshäuser nach Religion im Kanton Bern</description>
|
||||
<atom:link href="https://raw.githubusercontent.com/tomasriveral/ReSSPublica/refs/heads/main/feed/atom/de/gotteshauserNachReligionImKantonBern.atom" rel="self"/>
|
||||
<docs>https://github.com/tomasriveral/ReSSPublica</docs>
|
||||
<generator>python-feedgen</generator>
|
||||
<language>de</language>
|
||||
<lastBuildDate>Wed, 17 Jun 2026 21:51:13 +0200</lastBuildDate>
|
||||
</channel>
|
||||
</rss>
|
||||
@@ -0,0 +1,13 @@
|
||||
<?xml version='1.0' encoding='UTF-8'?>
|
||||
<rss xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/" version="2.0">
|
||||
<channel>
|
||||
<title>Lieu de culte par religion dans le canton de Berne</title>
|
||||
<link>https://raw.githubusercontent.com/tomasriveral/ReSSPublica/refs/heads/main/feed/atom/fr/lieuDeCulteParReligionDansLeCantonDeBerne.atom</link>
|
||||
<description>Flux RSS des Lieu de culte par religion dans le canton de Berne</description>
|
||||
<atom:link href="https://raw.githubusercontent.com/tomasriveral/ReSSPublica/refs/heads/main/feed/atom/fr/lieuDeCulteParReligionDansLeCantonDeBerne.atom" rel="self"/>
|
||||
<docs>https://github.com/tomasriveral/ReSSPublica</docs>
|
||||
<generator>python-feedgen</generator>
|
||||
<language>fr</language>
|
||||
<lastBuildDate>Wed, 17 Jun 2026 21:51:13 +0200</lastBuildDate>
|
||||
</channel>
|
||||
</rss>
|
||||
@@ -31,6 +31,7 @@
|
||||
matplotlib
|
||||
pycurl
|
||||
beautifulsoup4
|
||||
seaborn
|
||||
];
|
||||
|
||||
# you will need to point to your local git clone
|
||||
@@ -59,6 +60,7 @@
|
||||
matplotlib
|
||||
beautifulsoup4
|
||||
pycurl
|
||||
seaborn
|
||||
];
|
||||
};
|
||||
};
|
||||
|
||||
+2
-1
@@ -18,7 +18,8 @@ dependencies = [
|
||||
"pyarrow", #dep for parquet
|
||||
"matplotlib",
|
||||
"beautifulsoup4",
|
||||
"pycurl"
|
||||
"pycurl",
|
||||
"seaborn"
|
||||
]
|
||||
|
||||
[project.scripts]
|
||||
|
||||
@@ -135,7 +135,7 @@ def generateBernAsianHornetFeed(ASSETS, CACHE):
|
||||
else:
|
||||
weeklyEntry["url"] = f"https://opendata.swiss/{lang}/dataset/asiatische-hornisse"
|
||||
weeklyEntry["title"] = translatedBernAsianHornetSightings[lang] + f" {start.isoformat()}-{end.isoformat()}"
|
||||
weeklyEntry["text"] = f"<img src=\"https://raw.githubusercontent.com/tomasriveral/ReSSPublica/refs/heads/main/.cache/bernAsianHornets-{lang}-{start.isoformat()}-{end.isoformat()}.png\" alt=\"{translatedBernAsianHornetSightings[lang]} {start.isoformat()}-{end.isoformat()}\">" # yes there is an error in filename. the s in asian is capitalized. I don't really want to regenerate all the images...
|
||||
weeklyEntry["text"] = f"<img src=\"https://raw.githubusercontent.com/tomasriveral/ReSSPublica/refs/heads/main/.cache/bernAsianHornets-{lang}-{start.isoformat()}-{end.isoformat()}.png\" alt=\"{translatedBernAsianHornetSightings[lang]} {start.isoformat()}-{end.isoformat()}\">"
|
||||
feeds[lang].append(copy.deepcopy(weeklyEntry))
|
||||
|
||||
generateFeed(
|
||||
|
||||
@@ -0,0 +1,272 @@
|
||||
import pandas as pd
|
||||
import copy
|
||||
import geopandas as gpd
|
||||
from shapely import wkb
|
||||
import matplotlib.pyplot as plt
|
||||
import datetime
|
||||
from datetime import date, time
|
||||
from bs4 import BeautifulSoup
|
||||
from tinydb import TinyDB, Query
|
||||
from time import sleep
|
||||
from zoneinfo import ZoneInfo
|
||||
from pathlib import Path
|
||||
from seaborn import color_palette
|
||||
|
||||
|
||||
import logging
|
||||
logger = logging.getLogger("resspublica")
|
||||
|
||||
from .translations import *
|
||||
from .utils import *
|
||||
|
||||
# We don't have a date fields in this dataset.
|
||||
# What we do i create a snapshot (an image) each trimester to see the evolution
|
||||
|
||||
def generateBernReligionMap(ASSETS, CACHE):
|
||||
|
||||
arbitraryStartDate = date.fromisoformat("2026-01-01") # start date for weekly image generation. The data source starts at 2021-05-22, but as there is no date information, we must start at today
|
||||
|
||||
logger.info("Generating Religion map in Bern feed...")
|
||||
logger.info("Preparing data...")
|
||||
#ASIAN_HORNETS_DB_PATH = CACHE / "bernAsianHornet.json"
|
||||
#global db
|
||||
#global q
|
||||
#db = TinyDB(ASIAN_HORNETS_DB_PATH)
|
||||
#q = Query()
|
||||
|
||||
|
||||
# 1. Load data
|
||||
url = "https://geofiles.be.ch/geoportal/pub/download/RELIGION/religion_relstaet.parquet"
|
||||
dataframe = pd.read_parquet(url)
|
||||
|
||||
# 2. Convert WKB geometry safely
|
||||
def safe_load(x):
|
||||
try:
|
||||
return wkb.loads(x)
|
||||
except Exception:
|
||||
return None
|
||||
|
||||
dataframe["geometry"] = dataframe["geometry"].apply(safe_load)
|
||||
dataframe = dataframe.dropna(subset=["geometry"])
|
||||
|
||||
religionGeoDataFrame = gpd.GeoDataFrame(dataframe, geometry="geometry", crs="EPSG:2056")
|
||||
|
||||
# We create a trimesterly image
|
||||
# We just need to check if we haven't already created it
|
||||
|
||||
# Each row is of the form Pandas(Index=127, objectid=23, uuid='D7CF8B83-4CD0-4F9E-9126-603BCCC0A42D', e_koord=2585316, n_koord=1221326, adresse='Rue de la Source 27', plz_ort='2502 Biel/Bienne', name_staet='Christkatholische Kirchgemeinde Biel', bez_staet='Christkatholische Kirchgemeinde Biel', symbol=8, reltra_id=1, reltrat_reltra_de='christlich', reltrat_reltra_fr='Christianisme', nkenn_id=6.0, nkennt_nkenn_de='christkatholisch', nkennt_nkenn_fr='catholique chrétien', kontakt_id=1, kontaktt_kontakt_de='offiziell', kontaktt_kontakt_fr='officiel', url='https://christkatholisch.ch/biel', adresse_k='Sekretariat und Pfarramt, General-Dufourstrasse 105', plz_ort_k='2502 Biel/Bienne', telefon='032 341 21 16', email='sekretariat.biel@christkatholisch.ch', jur_id=1, jurt_jur_de='öffentlich-rechtlich anerkannte Körperschaft', jurt_jur_fr='Collectivité reconnue de droit public', geometry=<POINT (2585316 1221326)>, bbox={'min_x': 2585316.0, 'min_y': 1221326.0, 'max_x': 2585316.0, 'max_y': 1221326.0})
|
||||
|
||||
# Note : some religion don't have subdivision in this dataset (ex: Judaisme) and as such don't have nkennt_* keys for them we set nkenn_id to 0
|
||||
|
||||
# Generate a dictionary that contains all (available) religions :
|
||||
logger.info("Gathering information on the religions...")
|
||||
df = religionGeoDataFrame.copy()
|
||||
|
||||
# ensure nkenn_id exists even when NaN
|
||||
df['nkenn_id_filled'] = df['nkenn_id'].fillna(0).astype(int)
|
||||
|
||||
# build composite key "reltra-nkenn"
|
||||
df['key'] = df['reltra_id'].astype(int).astype(str) + "-" + df['nkenn_id_filled'].astype(str)
|
||||
|
||||
# keep only relevant columns
|
||||
cols = [
|
||||
'key',
|
||||
'reltra_id',
|
||||
'nkenn_id',
|
||||
'nkennt_nkenn_fr',
|
||||
'nkennt_nkenn_de',
|
||||
'reltrat_reltra_fr',
|
||||
'reltrat_reltra_de'
|
||||
]
|
||||
|
||||
df = df[cols].drop_duplicates(subset=['key'])
|
||||
|
||||
# sort by reltra_id so that religion groups are contiguous
|
||||
df = df.sort_values(by=["reltra_id", "nkenn_id"], na_position="last")
|
||||
# build dictionary
|
||||
religions = (
|
||||
df.set_index('key')
|
||||
.apply(lambda row: {
|
||||
k: v for k, v in {
|
||||
"nkenn_id": row["nkenn_id"],
|
||||
"nkennt_nkenn_fr": row["nkennt_nkenn_fr"],
|
||||
"nkennt_nkenn_de": row["nkennt_nkenn_de"],
|
||||
"reltra_id": row["reltra_id"],
|
||||
"reltrat_reltra_fr": row["reltrat_reltra_fr"],
|
||||
"reltrat_reltra_de": row["reltrat_reltra_de"],
|
||||
}.items()
|
||||
if pd.notna(v)
|
||||
}, axis=1)
|
||||
.to_dict()
|
||||
)
|
||||
logger.debug(religions)
|
||||
|
||||
# generate color palette (1 color by religion with similar religion similar color)
|
||||
palette = color_palette("husl", len(religions.keys()))
|
||||
color_map = {
|
||||
key: palette[i]
|
||||
for i, key in enumerate(religions.keys())
|
||||
}
|
||||
|
||||
# as the canton borders do not change (frequently), we just download once the data
|
||||
gdbPathToCantonBoundariesDirectory = ASSETS / "swissBOUNDARIES3D_1_5_LV95_LN02.gdb"
|
||||
|
||||
cantonsBoundariesData = gpd.read_file(
|
||||
gdbPathToCantonBoundariesDirectory,
|
||||
layer="TLM_KANTONSGEBIET"
|
||||
)
|
||||
|
||||
bernCantonBoundaries = cantonsBoundariesData[
|
||||
cantonsBoundariesData["KANTONSNUMMER"] == 2
|
||||
].to_crs(religionGeoDataFrame.crs)
|
||||
|
||||
religionGeoDataFrame = religionGeoDataFrame[religionGeoDataFrame.geometry.notnull()].copy()
|
||||
|
||||
municipialitiesBoundaries = gpd.read_file(
|
||||
gdbPathToCantonBoundariesDirectory,
|
||||
layer="TLM_HOHEITSGEBIET"
|
||||
)
|
||||
|
||||
bernCityBoundaries = municipialitiesBoundaries[
|
||||
municipialitiesBoundaries["NAME"] == "Bern"
|
||||
].to_crs(religionGeoDataFrame.crs)
|
||||
|
||||
bernCityPolygon = bernCityBoundaries.geometry.iloc[0]
|
||||
|
||||
# subset of the scatter points of religion within the boundaries of the city of Bern
|
||||
religionGeoDataFrameSubsetInBernCity = religionGeoDataFrame[religionGeoDataFrame.within(bernCityPolygon)].copy()
|
||||
|
||||
for start, end in trimesterRangesFrom(arbitraryStartDate):
|
||||
if Path( CACHE / f"bernReligionMap-fr-{start.isoformat()}-{end.isoformat()}.png").exists(): # we only check french, but if one language exists the other ones should also exist
|
||||
logger.debug(f"Trimester {start.isoformat()}-{end.isoformat()} was already cached. Skipping...")
|
||||
continue
|
||||
logger.debug(f"Handling trimester {start.isoformat()}-{end.isoformat()}...")
|
||||
|
||||
for lang in ["fr", "de"]:
|
||||
fig, (pltAxBernCanton, pltAxBernCity) = plt.subplots(
|
||||
2, 1,
|
||||
figsize=(12, 16),
|
||||
gridspec_kw={"height_ratios": [1.2, 1]}
|
||||
)
|
||||
bernCantonBoundaries.plot(
|
||||
ax=pltAxBernCanton,
|
||||
facecolor="none",
|
||||
edgecolor="black",
|
||||
linewidth=2
|
||||
)
|
||||
|
||||
for religion_key in religions.keys():
|
||||
logger.info(f"Handling religion {religion_key}")
|
||||
reltra_id_str, nkenn_id_str = religion_key.split("-")
|
||||
|
||||
reltra_id = int(reltra_id_str)
|
||||
nkenn_id = int(nkenn_id_str)
|
||||
|
||||
subset = religionGeoDataFrame[religionGeoDataFrame["reltra_id"] == reltra_id]
|
||||
|
||||
if nkenn_id == 0:
|
||||
subset.plot(
|
||||
ax=pltAxBernCanton,
|
||||
color=color_map[religion_key],
|
||||
markersize=5,
|
||||
alpha=0.6,
|
||||
label=religions[religion_key][f"reltrat_reltra_{lang}"]
|
||||
)
|
||||
else:
|
||||
subset = subset[subset["nkenn_id"] == nkenn_id]
|
||||
|
||||
subset.plot(
|
||||
ax=pltAxBernCanton,
|
||||
color=color_map[religion_key],
|
||||
markersize=5,
|
||||
alpha=0.6,
|
||||
label=religions[religion_key][f"nkennt_nkenn_{lang}"]
|
||||
+ f" ({religions[religion_key][f'reltrat_reltra_{lang}'].strip(" ")})"
|
||||
) # for some reason the reltrat_reltra_fr for bouddisme has a final " " so we need to strip it
|
||||
handles, labels = pltAxBernCanton.get_legend_handles_labels()
|
||||
|
||||
fig.legend(
|
||||
handles,
|
||||
labels,
|
||||
loc="upper right",
|
||||
ncol=1,
|
||||
fontsize=10,
|
||||
title=translatedPlacesOfWorshipInBern[lang]
|
||||
)
|
||||
fig.subplots_adjust(right=0.8)
|
||||
|
||||
pltAxBernCanton.set_title("")
|
||||
pltAxBernCanton.set_axis_off()
|
||||
|
||||
bernCantonBoundaries.plot(
|
||||
ax=pltAxBernCity,
|
||||
facecolor="none",
|
||||
edgecolor="black",
|
||||
linewidth=2
|
||||
)
|
||||
|
||||
bernCityBoundaries.boundary.plot(ax=pltAxBernCity, color="black", linewidth=1)
|
||||
|
||||
|
||||
|
||||
for religion_key in religions.keys():
|
||||
reltra_id_str, nkenn_id_str = religion_key.split("-")
|
||||
|
||||
reltra_id = int(reltra_id_str)
|
||||
nkenn_id = int(nkenn_id_str)
|
||||
|
||||
subset = religionGeoDataFrameSubsetInBernCity[religionGeoDataFrameSubsetInBernCity["reltra_id"] == reltra_id]
|
||||
|
||||
if nkenn_id != 0:
|
||||
subset = subset[subset["nkenn_id"] == nkenn_id]
|
||||
|
||||
subset.plot(
|
||||
ax=pltAxBernCity,
|
||||
color=color_map[religion_key],
|
||||
markersize=5,
|
||||
alpha=0.7
|
||||
)
|
||||
xmin, ymin, xmax, ymax = bernCityBoundaries.total_bounds
|
||||
|
||||
pltAxBernCity.set_xlim(xmin, xmax)
|
||||
pltAxBernCity.set_ylim(ymin, ymax)
|
||||
pltAxBernCity.set_title(translatedCityOfBern[lang])
|
||||
pltAxBernCity.set_axis_off()
|
||||
|
||||
plt.tight_layout()
|
||||
plt.savefig(CACHE / f"bernReligionMap-{lang}-{start.isoformat()}-{end.isoformat()}.png", dpi=120, bbox_inches="tight")
|
||||
logger.debug(f"Generated bernReligionMap-{lang}-{start.isoformat()}-{end.isoformat()}.png")
|
||||
plt.close()
|
||||
feeds = {
|
||||
"fr": [],
|
||||
"de": []
|
||||
}
|
||||
for start, end in trimesterRangesFrom(arbitraryStartDate):
|
||||
trimestrialEntry = {}
|
||||
trimestrialEntry["id"] = datetime.combine(start, time(12, 0)).timestamp() # we use timestamp as ids
|
||||
trimestrialEntry["creationDate"] = start.isoformat()
|
||||
trimestrialEntry["date"] = start.isoformat() # there is no point have them different. On other feeds it's used for update date
|
||||
trimestrialEntry["source"] = "opendata.swiss"
|
||||
|
||||
for lang in ["fr", "de"]:
|
||||
trimestrialEntry["url"] = f"https://opendata.swiss/{lang}/dataset/religionslandkarte"
|
||||
trimestrialEntry["title"] = f"{translatedPlacesOfWorshipInBern[lang]}-{start.isoformat()}"
|
||||
trimestrialEntry["text"] = f"<img src=\"https://raw.githubusercontent.com/tomasriveral/ReSSPublica/refs/heads/main/.cache/bernReligionMap-{lang}-{start.isoformat()}-{end.isoformat()}.png\" alt=\"{translatedPlacesOfWorshipInBern[lang]} {start.isoformat()}\">"
|
||||
generateFeed(
|
||||
translatedPlacesOfWorshipInBern["fr"],
|
||||
f"Flux RSS des {translatedPlacesOfWorshipInBern["fr"]}",
|
||||
translatedPlacesOfWorshipInBernCamelCase["fr"],
|
||||
"fr",
|
||||
["rss", "atom"],
|
||||
datetime.now().replace(tzinfo=ZoneInfo("Europe/Zurich")),
|
||||
feeds["fr"]
|
||||
)
|
||||
generateFeed(
|
||||
translatedPlacesOfWorshipInBern["de"],
|
||||
f"RSS-Feed der {translatedPlacesOfWorshipInBern["de"]}",
|
||||
translatedPlacesOfWorshipInBernCamelCase["de"],
|
||||
"de",
|
||||
["rss", "atom"],
|
||||
datetime.now().replace(tzinfo=ZoneInfo("Europe/Zurich")),
|
||||
feeds["de"]
|
||||
)
|
||||
@@ -9,6 +9,7 @@ from .utils import *
|
||||
from .federalInitiativesFeeds import *
|
||||
from .translations import *
|
||||
from .bernAsianHornet import *
|
||||
from .bernReligionMap import *
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser()
|
||||
@@ -16,6 +17,8 @@ def main():
|
||||
parser.add_argument("--gen_federalInitiatives", action="store_true", help="Generate federal popular initiatives feed")
|
||||
parser.add_argument("--gen_bernAsianHornets", action="store_true", help="Generate Asian hornets sightings in Bern feed (only Mondays)")
|
||||
parser.add_argument("--force_gen_bernAsianHornets", action="store_true", help="Generate Asian hornets sightings in Bern feed even when not Monday")
|
||||
parser.add_argument("--gen_bernReligionMap", action="store_true", help="Generate map of religions in Bern (only start of trimesters)")
|
||||
parser.add_argument("--force_gen_bernReligionMap", action="store_true", help="Generate map of religions in Bern even when not start of trimester")
|
||||
|
||||
|
||||
args = parser.parse_args()
|
||||
@@ -35,4 +38,6 @@ def main():
|
||||
generateFederalFeed(CACHE)
|
||||
if (date.today().weekday() == 0 and args.gen_bernAsianHornets) or args.force_gen_bernAsianHornets:
|
||||
generateBernAsianHornetFeed(ASSETS, CACHE)
|
||||
if ( args.gen_bernReligionMap and date.today().day == 1 and date.today().month in [1, 5, 9]) or args.force_gen_bernReligionMap:
|
||||
generateBernReligionMap(ASSETS, CACHE)
|
||||
logging.info("Done")
|
||||
|
||||
@@ -76,3 +76,15 @@ translatedBernAsianHornetSightings = {
|
||||
"it": ("Avvistamenti di calabroni asiatici a Berna"),
|
||||
"rm": ("Observaziuns da vespras asiaticas a Berna"),
|
||||
}
|
||||
translatedPlacesOfWorshipInBern = {
|
||||
"de": "Gotteshäuser nach Religion im Kanton Bern",
|
||||
"fr": "Lieu de culte par religion dans le canton de Berne"
|
||||
}
|
||||
translatedPlacesOfWorshipInBernCamelCase = {
|
||||
"de": "gotteshauserNachReligionImKantonBern",
|
||||
"fr": "lieuDeCulteParReligionDansLeCantonDeBerne"
|
||||
}
|
||||
translatedCityOfBern = {
|
||||
"de": "Stadt Bern",
|
||||
"fr": "Ville de Bern"
|
||||
}
|
||||
|
||||
@@ -117,3 +117,35 @@ def weeklyRangesFrom(start_date: date):
|
||||
start += timedelta(days=7)
|
||||
|
||||
return weeks
|
||||
|
||||
|
||||
def trimester_start(d: date) -> date:
|
||||
if d.month <= 4:
|
||||
return date(d.year, 1, 1)
|
||||
elif d.month <= 8:
|
||||
return date(d.year, 5, 1)
|
||||
else:
|
||||
return date(d.year, 9, 1)
|
||||
def next_trimester_start(d: date) -> date:
|
||||
if d.month <= 4:
|
||||
return date(d.year, 5, 1)
|
||||
elif d.month <= 8:
|
||||
return date(d.year, 9, 1)
|
||||
else:
|
||||
return date(d.year + 1, 1, 1)
|
||||
def trimesterRangesFrom(start_date: date):
|
||||
today = date.today()
|
||||
|
||||
current_trimester_start = trimester_start(today)
|
||||
start = trimester_start(start_date)
|
||||
|
||||
trimesters = []
|
||||
|
||||
while start < current_trimester_start:
|
||||
next_start = next_trimester_start(start)
|
||||
end = next_start - timedelta(days=1)
|
||||
|
||||
trimesters.append((start, end))
|
||||
start = next_start
|
||||
|
||||
return trimesters
|
||||
|
||||
Reference in New Issue
Block a user