diff --git a/R/aktualisiere_karten.R b/R/aktualisiere_karten.R
new file mode 100644
index 0000000000000000000000000000000000000000..28626b76e347cde275a6d73884451345badcdb84
--- /dev/null
+++ b/R/aktualisiere_karten.R
@@ -0,0 +1,49 @@
+#' aktualisiere_karten.R
+
+
+aktualisiere_karten <- function(wl_url = stimmbezirke_url) {
+  # Lies Ortsteil-Daten ein und vergleiche
+  neue_orts_df <- lies_gebiet(wl_url) %>% 
+    aggregiere_stadtteile() %>% 
+    mutate(quorum = ifelse(wahlberechtigt == 0,
+                           0,
+                           ja / wahlberechtigt * 100)) %>% 
+    mutate(status = ifelse(meldungen_anz == 0,
+                           "KEINE DATEN",
+                           paste0(ifelse(meldungen_anz < meldungen_max,
+                                          "TREND ",""),
+                                   ifelse(ja < nein,
+                                          "NEIN",
+                                          ifelse(quorum < 30,
+                                                 "JA",
+                                                 "JA QUORUM")))
+    ))
+  alte_orts_df <- hole_letztes_df("daten/ortsteile")
+  # Datenstand identisch? Dann brich ab. 
+  if(vergleiche_stand(alte_orts_df,neue_orts_df)) {
+    return(FALSE) 
+  } else {
+    # Zeitstempel holen
+    archiviere(neue_orts_df,"daten/ortsteile")
+    ts <- neue_orts_df %>% pull(zeitstempel) %>% last()
+    # Datentabelle übertragen
+    dw_data_to_chart(neue_orts_df,choropleth_id)
+    dw_data_to_chart(neue_orts_df,symbol_id)
+    dw_data_to_chart(neue_orts_df,tabelle_id)
+    # Anmerkungen aktualisieren
+    wahlberechtigt <- neue_orts_df %>% pull(wahlberechtigt) %>% sum()
+    # Prozentsatz ausgezählte Stimmen: abgerundet auf ganze Prozent
+    ausgezählt <- floor(wahlberechtigt / ffm_waehler *100)
+    annotate_str <- generiere_auszählungsbalken(ausgezählt,
+                                                anz = neue_orts_df %>% pull(meldungen_anz) %>% sum(),
+                                                max = neue_orts_df %>% pull(meldungen_max) %>% sum(),
+                                                ts = ts)
+    dw_edit_chart(symbol_id,annotate=annotate_str)
+    dw_edit_chart(choropleth_id,annotate=annotate_str)
+    dw_edit_chart(tabelle_id,annotate=annotate_str)
+    dw_publish_chart(symbol_id)
+    dw_publish_chart(choropleth_id)
+    dw_publish_chart(tabelle_id)
+    return(TRUE)
+  }
+}
\ No newline at end of file
diff --git a/R/generiere_testdaten.R b/R/generiere_testdaten.R
new file mode 100644
index 0000000000000000000000000000000000000000..3eed9587e7a82d8e51b2252b2ce46d563e810348
--- /dev/null
+++ b/R/generiere_testdaten.R
@@ -0,0 +1,140 @@
+#' generiere_testdaten.R
+#' 
+#' Macht aus den Templates für Ortsteil- und Wahllokal-Ergebnisse
+#' jeweils eine Serie von fiktiven Livedaten, um das Befüllen der
+#' Grafiken testen zu können. 
+#' 
+
+require(tidyr)
+require(dplyr)
+require(readr)
+
+# Alles weg, was noch im Speicher rumliegt
+rm(list=ls())
+
+source("R/lies_aktuellen_stand.R")
+
+#---- Funktion zum Testdaten-Löschen ----
+lösche_testdaten <- function(){
+  q <- tolower(readline(prompt = "Testdaten löschen - sicher? "))
+  if (!(q %in% c("j","y","ja"))) { return() }
+  # Datenarchiv weg
+  if (file.exists("daten/fom_df.rds")){
+    file.remove("daten/fom_df.rds")
+  }
+  # Testdaten
+  testdaten_files <- list.files("testdaten", full.names=TRUE) 
+  for (f in testdaten_files) {
+    # Grausam, I know. 
+    if (str_detect(f,"ortsteile[0-9]+\\.csv") |
+        str_detect(f,"wahllokale[0-9]+\\.csv")) {
+      file.remove(f)
+    }
+  }
+}
+
+# Vorlagen laden
+vorlage_wahllokale_df <- read_delim("testdaten/Open-Data-06412000-Buergerentscheid-zur-Abwahl-des-Oberbuergermeisters-der-Stadt-Frankfurt-am-Main_-Herrn-Peter-Feldmann-Stimmbezirk.csv", 
+                                   delim = ";", escape_double = FALSE, 
+                                   locale = locale(date_names = "de", 
+                                                   decimal_mark = ",", 
+                                                   grouping_mark = "."), 
+                                   trim_ws = TRUE)
+
+wahllokale_max <- sum(vorlage_wahllokale_df$`max-schnellmeldungen`)
+
+# Konstanten für die Simulation - werden jeweils um bis zu +/-25% variiert
+c_wahlberechtigt = 510000 / wahllokale_max # Gleich große Wahlbezirke
+c_wahlbeteiligung = 0.3 # Wahlbeteiligung um 30%, wird im Lauf der "Wahl" erhöht (kleinere WL sind schneller ausgezählt)
+c_wahlschein = 0.25 # 25% Briefwähler
+c_nv = 0.05 # 0,5% wählen "spontan" und sind nicht verzeichnet (nv) im Wählerverzeichnis
+c_ungültig = 0.01 # 1% Ungültige
+c_nein = 0.15 # unter den gültigen: 85% Ja-Stimmen (Varianz also von ca 81-89%)
+
+variiere <- function(x = 1) {
+  # Variiert den übergebenen Wert zufällig um -25% bis +25%:
+  # Zufallswerte zwischen 0,75 und 1,25 erstellen und multiplizieren
+  #
+  # Die Length-Funktion ist wichtig - sonst erstellt runif() nur einen 
+  # Zufallswert, mit dem alle Werte von x multipliziert werden. 
+  return(floor(x * (runif(length(x),0.75,1.25))))
+}
+
+
+
+i = 1
+# Schleife für die Wahllokale: Solange noch nicht alle "ausgezählt" sind...
+while(sum(vorlage_wahllokale_df$`anz-schnellmeldungen`) < wahllokale_max) {
+  # ...splitte das df in die gemeldeten (meldungen_anz == 1) und nicht gemeldeten Zeilen
+  tmp_gemeldet_df <- vorlage_wahllokale_df %>% filter(`anz-schnellmeldungen` == 1)
+  # Die Variable rand wird als Anteil von 20 Meldungen an debn noch offenen Wahllokale berechnet
+  rand <- 20 / (nrow(vorlage_wahllokale_df) - nrow(tmp_gemeldet_df)) 
+  tmp_sample_df <- vorlage_wahllokale_df %>% 
+    filter(`anz-schnellmeldungen` == 0) %>% 
+    # Bei den noch nicht ausgefüllten "Meldungen" mit einer Wahrscheinlichkeit
+    # von rand in die Gruppe sortieren, die neu "gemeldet" wird
+    mutate(sample = (runif(nrow(.)) < rand))
+  tmp_offen_df <- tmp_sample_df %>% 
+    filter(sample == 0) %>%
+    # sample-Variable wieder raus
+    select(-sample)
+  tmp_neu_df <- tmp_sample_df %>% 
+    filter(sample == 1) %>% 
+  select(-sample) %>% 
+    # Alle als gemeldet markieren
+    mutate(`anz-schnellmeldungen` = 1) %>%
+    # Und jetzt der Reihe nach (weil die Werte z.T. aufeinander aufbauen)
+    # Wahlberechtigte
+    mutate(A = floor(c_wahlberechtigt * runif(nrow(.),0.75,1.25))) %>% 
+    # Wahlschein
+    mutate(A2 = floor(A * c_wahlschein * runif(nrow(.),0.75,1.25))) %>% 
+    # Nicht verzeichnet
+    mutate(A3 = floor(A * c_nv * runif(nrow(.),0.75,1.25))) %>% 
+    # Regulär Wahlberechtigte (ohne Wahlschein oder nv)
+    mutate(A1 = A - A2 - A3) %>% 
+    # Abgegebene Stimmen
+    mutate(B = floor(A * c_wahlbeteiligung * runif(nrow(.),0.75,1.25))) %>% 
+    # davon mit Wahlschein
+    mutate(B1 = floor(B * c_wahlschein * runif(nrow(.),0.75,1.25))) %>% 
+    # davon ungültig
+    mutate(C = floor(B * c_ungültig * runif(nrow(.),0.75,1.25))) %>% 
+    # gültig
+    mutate(D = B - C) %>% 
+    # davon ja
+    mutate(D2 = floor(D * c_nein *runif(nrow(.),0.75,1.25))) %>% 
+    mutate(D1 = D - D2)
+  # Kurze Statusmeldung
+  cat("Neu gemeldet:",nrow(tmp_neu_df),"noch offen:",nrow(tmp_offen_df))
+  # Phew. Aktualisierte Testdatei zusammenführen und anlegen. 
+  vorlage_wahllokale_df <- tmp_gemeldet_df %>% 
+    bind_rows(tmp_neu_df) %>% 
+    bind_rows(tmp_offen_df) %>%
+    # wieder in die Reihenfolge nach Wahllokal-Nummer
+    arrange(`gebiet-nr`)
+  
+  write_csv2(vorlage_wahllokale_df,
+             paste0("testdaten/wahllokale",
+                    sprintf("%02i",i),
+                    ".csv"),
+             escape = "backslash")
+  # Generiere die passende Ortsteil-Meldung
+  # Geht aus irgeneindem Grund nicht, aber wir brauchens ja auch nicht. 
+  # ortsteile_df <- zuordnung_wahllokale_df %>% 
+  #   select(`gebiet-name` = name,ortsteilnr) %>% 
+  #   left_join(vorlage_wahllokale_df,by="gebiet-name") %>% 
+  #   # Zuordnung der Wahllokale
+  #   group_by(ortsteilnr) %>% 
+  #   # Das crasht - WTF???
+  #   summarize(across(7:18, ~ sum(.,na.rm = T))) %>%
+  #   left_join(stadtteile_df %>% select(ortsteilnr = nr,name),by="ortsteilnr") %>% 
+  #   rename(`gebiet-nr` = ortsteilnr) %>% 
+  #   mutate(`gebiet-name` = name) %>% 
+  #   select(-ortsteilnr) 
+    
+  i <- i+1
+  # Wahlbeteiligung schrittweise ein wenig anheben - um zu simulieren, 
+  # dass "kleinere" Wahllokale zuerst ausgezählt werden
+  c_wahlbeteiligung <- c_wahlbeteiligung + 0.002
+}
+
+
diff --git a/R/lies_aktuellen_stand.R b/R/lies_aktuellen_stand.R
new file mode 100644
index 0000000000000000000000000000000000000000..70b7bca9985413a10982c16b486276077c7c0b19
--- /dev/null
+++ b/R/lies_aktuellen_stand.R
@@ -0,0 +1,152 @@
+library(readr)
+library(lubridate)
+library(tidyr)
+library(stringr)
+library(dplyr)
+
+# lies_aktuellen_stand.R
+#
+# Enthält die Funktion zum Lesen der aktuellen Daten. 
+
+#---- Vorbereitung ----
+# Statische Daten einlesen
+# (das später durch ein schnelleres .rda ersetzen)
+
+# Enthält drei Datensätze: 
+# - opendata_wahllokale_df mit der Liste aller Stimmwahlbezirke nach Wahllokal
+# - statteile_df: Stadtteil mit Namen und laufender Nummer, Geokoordinaten, Ergebnissen 2018
+# - zuordnung_stimmbezirke: Stimmbezirk-Nummer (als int und String) -> Stadtteilnr.
+ 
+load ("index/index.rda")
+
+# Konfiguration auslesen und in Variablen schreiben
+config_df <- read_csv("index/config.csv")
+for (i in c(1:nrow(config_df))) {
+  # Erzeuge neue Variablen mit den Namen und Werten aus der CSV
+  assign(config_df$name[i],
+         # Kann man den Wert auch als Zahl lesen?
+         # Fieses Regex sucht nach reiner Zahl oder Kommawerten.
+         # Keine Exponentialschreibweise!
+         ifelse(grepl("^[0-9]*\\.*[0-9]+$",config_df$value[i]),
+                # Ist eine Zahl - wandle um
+                as.numeric(config_df$value[i]),
+                # Keine Zahl - behalte den String
+                config_df$value[i]))
+}
+
+
+#---- Daten ins Archiv schreiben oder daraus lesen
+archiviere <- function(df,a_directory = "daten/stimmbezirke") {
+  if (!dir.exists(a_directory)) {
+    dir.create(a_directory)
+  }
+  write_csv(df,
+            paste0(a_directory,"/",
+                   # Zeitstempel isolieren und alle Doppelpunkte
+                   # durch Bindestriche ersetzen
+                   str_replace_all(df %>% pull(zeitstempel) %>% last(),
+                               "\\:","_"),
+                   ".csv"))
+}
+
+hole_letztes_df <- function(a_directory = "daten/stimmbezirke") {
+  if (!dir.exists(a_directory)) return(tibble())
+  neuester_file <- list.files(a_directory, full.names=TRUE) %>% 
+    file.info() %>% 
+    # Legt eine Spalte namens path an
+    tibble::rownames_to_column(var = "path") %>% 
+    arrange(desc(ctime)) %>% 
+    head(1) %>% 
+    # Pfad wieder rausziehen
+    pull(path)
+  if (length(neuester_file)==0) {
+    # Falls keine Daten archiviert, gibt leeres df zurück
+    return(tibble())
+  } else {
+    return(read_csv(neuester_file))
+  }
+}
+
+
+#---- Lese-Funktionen ----
+lies_gebiet <- function(stand_url = stimmbezirke_url) {
+  ts <- now()
+  # Versuch Daten zu lesen - und gib ggf. Warnung oder Fehler zurück
+  check = tryCatch(
+    { stand_df <- read_delim(stand_url, 
+                         delim = ";", escape_double = FALSE, 
+                         locale = locale(date_names = "de", 
+                                         decimal_mark = ",", 
+                                         grouping_mark = "."), 
+                         trim_ws = TRUE) %>% 
+      # Spalten umbenennen, Zeitstempel-Spalte einfügen
+                    mutate(zeitstempel=ts) %>% 
+                    select(zeitstempel,
+                           nr = `gebiet-nr`,
+                           name = `gebiet-name`,
+                           meldungen_anz = `anz-schnellmeldungen`,
+                           meldungen_max = `max-schnellmeldungen`,
+                           # Ergebniszellen
+                           wahlberechtigt = A,
+                           # Mehr zum Wahlschein hier: https://www.bundeswahlleiter.de/service/glossar/w/wahlscheinvermerk.html
+                           waehler_regulaer = A1,
+                           waehler_wahlschein = A2,
+                           waehler_nv = A3,
+                           stimmen = B,
+                           stimmen_wahlschein = B1, 
+                           ungueltig = C,
+                           gueltig = D,
+                           ja = D1,
+                           nein = D2)
+      },
+    warning = function(w) {teams_warning(w,title="Feldmann: Datenakquise")},
+    error = function(e) {teams_warning(e,title="Feldmann: Datenakquise")})
+  # Spalten umbenennen, 
+  return(stand_df)
+}
+
+
+# Sind die beiden df abgesehen vom Zeitstempel identisch?
+# Funktion vergleicht die numerischen Werte - Spalte für Spalte.
+vergleiche_stand <- function(alt_df, neu_df) {
+  neu_sum_df <- alt_df %>% summarize_if(is.numeric,sum,na.rm=T)
+  alt_sum_df <- neu_df %>% summarize_if(is.numeric,sum,na.rm=T)
+  # Unterschiedliche Spaltenzahlen? Dann können sie keine von Finns Männern sein.
+  if (length(neu_sum_df) != length(alt_sum_df)) return(FALSE)
+  # Differenzen? Dann können sie keine von Finns Männern sein. 
+  return(sum(abs(neu_sum_df - alt_sum_df))==0)
+}
+
+#' Liest Stimmbezirke, gibt nach Ortsteil aggregierte Daten zurück
+#' (hier: kein Sicherheitscheck)
+aggregiere_stadtteile <- function(stimmbezirke_df) {
+  ortsteile_df <- stimmbezirke_df %>% 
+    left_join(zuordnung_stimmbezirke_df,by=c("nr","name")) %>% 
+    group_by(ortsteilnr) %>% 
+    summarize(zeitstempel = last(zeitstempel),
+              across(meldungen_anz:nein, ~ sum(.,na.rm = T))) %>%
+    rename(nr = ortsteilnr) %>% 
+    # Stadtteilnamen, 2018er Ergebnisse, Geokoordinaten dazuholen
+    left_join(stadtteile_df, by="nr") %>% 
+    # Nach Ortsteil sortieren
+    arrange(nr) %>% 
+    # Wichtige Daten für bessere Lesbarkeit nach vorn
+    relocate(zeitstempel,nr,name,lon,lat)
+    
+  # Sicherheitscheck: Warnen, wenn nicht alle Ortsteile zugeordnet
+  if (nrow(ortsteile_df) != nrow(stadtteile_df)) teams_warnung("Nicht alle Ortsteile zugeordnet")
+  if (nrow(zuordnung_stimmbezirke_df) != length(unique(stimmbezirke_df$nr))) teams_warnung("Nicht alle Stimmbezirke zugeordnet")
+  return(ortsteile_df)
+}
+
+lies_stadtteil_direkt <- function(stand_url = ortsteile_url) {
+  neu_df <- lies_gebiet(stand_url)  %>%
+    # nr bei Ortsteil-Daten leer/ignorieren
+    select(!nr) %>% 
+    # Stadtteilnr., Geodaten und Feldmann-2018-Daten reinholen:
+    left_join(stadtteile_df, by=c("name")) %>% 
+    mutate(trend = (meldungen_anz < meldungen_max),
+           quorum_erreicht = (ja >= (wahlberechtigt * 0.3)))
+  return(neu_df)
+}
+
diff --git a/R/messaging.R b/R/messaging.R
new file mode 100644
index 0000000000000000000000000000000000000000..b2b93b0e1470153dc8f474648344f2546ad7dfc2
--- /dev/null
+++ b/R/messaging.R
@@ -0,0 +1,41 @@
+library(readr)
+library(lubridate)
+library(tidyr)
+library(stringr)
+library(dplyr)
+library(teamr)
+
+#' messaging.R
+#' 
+#' Kommunikation mit Teams
+#' 
+#' Webhook wird als URL im Environment gespeichert. Wenn nicht dort, dann 
+
+# Webhook schon im Environment? 
+if (Sys.getenv("WEBHOOK_REFERENDUM") == "") {
+  t_txt <- read_file("../key/webhook_referendum.key")
+  Sys.setenv(WEBHOOK_REFERENDUM = t_txt)
+}
+
+teams_meldung <- function(...,title="Feldmann-Update") {
+  cc <- teamr::connector_card$new(hookurl = t_txt)
+  cc$title(paste0(title," - ",lubridate::with_tz(lubridate::now(),
+                                                 "Europe/Berlin")))
+  alert_str <- paste0(...)
+  cc$text(alert_str)
+  cc$print()
+  cc$send()
+} 
+
+teams_error <- function(...) {
+  alert_str <- paste0(...)
+  teams_meldung(title="Feldmann: FEHLER: ", ...)
+  stop(alert_str)
+} 
+
+teams_warning <- function(...) {
+  alert_str <- paste0(...)
+  teams_meldung("Feldmann: WARNUNG: ",...)
+  warning(alert_str)
+} 
+
diff --git a/R/update_all.R b/R/update_all.R
new file mode 100644
index 0000000000000000000000000000000000000000..e0dd5d6d73505c1a8d37304dcf8eb2236688b0f4
--- /dev/null
+++ b/R/update_all.R
@@ -0,0 +1,203 @@
+library(pacman)
+
+# Laden und ggf. installieren
+p_load(this.path)
+p_load(readr)
+p_load(lubridate)
+p_load(tidyr)
+p_load(stringr)
+p_load(dplyr)
+p_load(DatawRappr)
+
+rm(list=ls())
+
+# Aktuelles Verzeichnis als workdir
+setwd(this.path::this.dir())
+# Aus dem R-Verzeichnis eine Ebene rauf
+setwd("..")
+
+
+source("R/messaging.R")
+source("R/lies_aktuellen_stand.R")
+source("R/aktualisiere_karten.R")
+source("R/generiere_balken.R")  
+
+
+#----aktualisiere_fom() ----
+# fom ist das "Feldmann-o-meter", die zentrale Grafik mit dem Stand der Auszählung.
+
+aktualisiere_fom <- function(wl_url = stimmbezirke_url) {
+  
+  # Einlesen: Feldmann-o-meter-Daten so far. 
+  # Wenn die Daten noch nicht existieren, generiere ein leeres df. 
+  if(file.exists("daten/fom_df.rds")) {
+    fom_df <- readRDS("daten/fom_df.rds")
+  } else {
+    # Leeres df mit einer Zeile
+    fom_df <- tibble(zeitstempel = as_datetime(startdatum),
+                           meldungen_anz = 0,
+                           meldungen_max = 575,
+                           # Ergebniszellen
+                           wahlberechtigt = 0,
+                           # Mehr zum Wahlschein hier: https://www.bundeswahlleiter.de/service/glossar/w/wahlscheinvermerk.html
+                           waehler_regulaer = 0,
+                           waehler_wahlschein = 0,
+                           waehler_nv = 0,
+                           stimmen = 0,
+                           stimmen_wahlschein = 0, 
+                           ungueltig = 0,
+                           gueltig = 0,
+                           ja = 0,
+                           nein = 0)
+    # SAVE kann man sich schenken; df ist schneller neu erzeugt
+    # save(feldmann_df,"daten/feldmann_df.rda")
+  }
+  # Daten zur Sicherheit sortieren, dann die letzte  Zeile rausziehen
+  letzte_fom_df <- fom_df %>% 
+    arrange(zeitstempel) %>% 
+    tail(1)
+  # Neue Daten holen (mit Fehlerbehandlung)
+  stimmbezirke_df <- lies_gebiet(wl_url) 
+  neue_fom_df <- stimmbezirke_df %>% 
+    # Namen raus
+    select(-name,-nr) %>% 
+    # Daten aufsummieren
+    summarize(zeitstempel = last(zeitstempel),
+      across(2:ncol(.), ~ sum(.,na.rm=T)))
+  # Alte und neue Daten identisch? Dann brich ab. 
+  if (vergleiche_stand(letzte_fom_df,neue_fom_df)) {
+    return(FALSE)
+  } else {
+    # Archiviere die Rohdaten 
+    archiviere(stimmbezirke_df,"daten/stimmbezirke/")
+    # Ergänze das fom_df um die neuen Daten und sichere es
+    fom_df <- fom_df %>% bind_rows(neue_fom_df)
+    saveRDS(fom_df,"daten/fom_df.rds")
+    # Bilde das Dataframe
+    # Sende die Daten an Datawrapper und aktualisiere
+    fom_dw_df <- fom_df %>% 
+      mutate(ausgezählt = meldungen_anz / meldungen_max *100) %>% 
+      mutate(prozent30 = NA) %>% 
+      mutate(quorum = ja / wahlberechtigt * 100) %>% 
+      select(ausgezählt, wahlberechtigt, ungueltig, ja, nein, quorum, prozent30) %>% 
+      # Noch den Endpunkt der 30-Prozent-Linie
+      bind_rows(tibble(ausgezählt = 100, prozent30 = ffm_waehler * 0.3))
+    dw_data_to_chart(fom_dw_df,fom_id)
+    # Parameter setzen
+    alles_ausgezählt <- (neue_fom_df$meldungen_max == neue_fom_df$meldungen_anz)
+    if (neue_fom_df$meldungen_anz == 0) {
+      quorum = 0
+      feldmann_str <- "Es liegen noch keine Auszählungsdaten des Bürgerentscheids vor."
+    } else {
+      quorum <- (neue_fom_df$ja / neue_fom_df$wahlberechtigt * 100)
+      if (quorum >= 30) {
+        if (alles_ausgezählt ) {
+          feldmann_str <- "Peter Feldmann ist als OB abgewählt."
+        } else {
+          feldmann_str <- "Nach dem derzeitigen Auszählungsstand wäre Peter Feldmann als OB abgewählt."
+        }
+      } else {
+        if (alles_ausgezählt ) {
+          feldmann_str <- "Peter Feldmann bleibt OB von Frankfurt."
+        } else {
+          feldmann_str <- "Nach dem derzeitigen Auszählungsstand bliebe Peter Feldmann OB von Frankfurt."
+        }
+      }
+    }
+    
+    # Breite des Balkens: Wenn das Quorum erreicht ist, hat er die volle Breite,
+    # wenn nicht, einen Anteil von 30%, um die Entfernung von der Markierung zu zeigen
+    
+    # Jetzt die Beschreibungstexte mit den Fake-Balkengrafiken generieren
+    beschreibung_str <- paste0(
+      "Die Abwahl ist beschlossen, wenn mindestens 30 Prozent aller Wahlberechtigten mit &quot;Ja&quot; stimmen.<br/><br>",
+      "<b style='font-weight:700;font-size:120%;'>",
+      # Erste dynamisch angepasste Textstelle: Bleibt Feldmann?
+      feldmann_str,
+      "</b><br/><br>",
+      generiere_balken(wb = neue_fom_df$wahlberechtigt,
+                       ja = neue_fom_df$ja,
+                       nein = neue_fom_df$nein,
+                       auszählung_beendet = alles_ausgezählt))
+    annotate_str <- generiere_auszählungsbalken(
+      ausgezählt = floor(neue_fom_df$wahlberechtigt / ffm_waehler * 100),
+      anz = neue_fom_df$meldungen_anz,
+      max = neue_fom_df$meldungen_max,
+      ts = neue_fom_df$zeitstempel)
+    briefwahl_anz <- stimmbezirke_df %>% filter(str_detect(nr,"^9")) %>% 
+      pull(meldungen_anz) %>% sum()
+    briefwahl_max <- stimmbezirke_df %>% filter(str_detect(nr,"^9")) %>% 
+      nrow()
+    annotate_str <- paste0("<strong>Derzeit sind ",
+                           briefwahl_anz,
+                           " von ",
+                           briefwahl_max, 
+                           " Briefwahl-Stimmbezirken ausgezählt.</strong><br/><br/>",
+                           annotate_str)
+    dw_edit_chart(fom_id,intro = beschreibung_str,annotate = annotate_str)
+    dw_publish_chart(fom_id)
+    return(TRUE)
+  }
+}
+
+
+#---- MAIN ----
+# Ruft aktualisiere_fom() auf
+# (die dann wieder aktualisiere_karten() aufruft)
+check = tryCatch(
+  { 
+    neue_daten <- aktualisiere_fom(stimmbezirke_url)
+  },
+  warning = function(w) {teams_warning(w,title="Feldmann: fom")},
+  error = function(e) {teams_warning(e,title="Feldmann: fom")})
+# Neue Daten? Dann aktualisiere die Karten
+if (neue_daten) {
+  check = tryCatch(
+    { 
+      neue_daten <- aktualisiere_karten(stimmbezirke_url)
+    },
+    warning = function(w) {teams_warning(w,title="Feldmann: Karten")},
+    error = function(e) {teams_warning(e,title="Feldmann: Karten")})
+  if (neue_daten) {
+    # Alles OK, letzte Daten nochmal holen und ausgeben
+    fom_df <- readRDS("daten/fom_df.rds") %>% 
+      arrange(zeitstempel) %>% 
+      tail(1)
+    if(fom_df$meldungen_anz > 0) {
+      stimmbezirke_df <- lies_gebiet(stimmbezirke_url)
+      briefwahl_anz <- stimmbezirke_df %>% filter(str_detect(nr,"^9")) %>% 
+        pull(meldungen_anz) %>% sum()
+      briefwahl_max <- stimmbezirke_df %>% filter(str_detect(nr,"^9")) %>% 
+        nrow()
+      fom_update_str <- paste0(
+        "<strong>Update OK</strong><br/><br/>",
+        fom_df$meldungen_anz,
+        " von ",
+        fom_df$meldungen_max," Stimmbezirke ausgezählt.<br> ",
+                              "Derzeit sind ",
+                               briefwahl_anz,
+                               " von ",
+                               briefwahl_max, 
+                               " Briefwahl-Stimmbezirken ausgezählt.<br/>",
+        "<ul><li><strong>Quorum zur Abwahl ist derzeit",
+        ifelse(fom_df$ja / fom_df$wahlberechtigt < 0.3, " nicht ", " "),
+        "erreicht</strong></li>",
+        "<li><strong>Anteil der Ja-Stimmen an den Wahlberechtigten: ",
+        format(fom_df$ja / fom_df$wahlberechtigt * 100,decimal.mark=",",big.mark=".",nsmall=1, digits=3),"%",
+        "</li><li>Ja-Stimmen: ",
+        format(fom_df$ja,decimal.mark=",",big.mark="."),
+        "</li><li>Nein-Stimmen: ",
+        format(fom_df$nein,decimal.mark=",",big.mark="."),
+        "</li><li>Verhältnis Ja:Nein: ",
+        format(fom_df$ja / (fom_df$ja + fom_df$nein) * 100,decimal.mark=",",big.mark=".",nsmall=1, digits=3),"% : ",
+        format(fom_df$nein / (fom_df$ja + fom_df$nein) *100,decimal.mark=",",big.mark=".",nsmall=1, digits=3),"%</li></ul>"
+        
+      )
+      teams_meldung(fom_update_str,title="Feldmann-Referendum")
+
+    }
+  } else {
+    teams_warning("Neue Stimmbezirk-Daten, aber keine neuen Ortsdaten?")
+  }
+} 
+# Auch hier TRUE zurückbekommen;; alles OK?
\ No newline at end of file
diff --git a/README.md b/README.md
index 4640ee6d11697585bb58c7f8fda7800fd439cfe6..b56eda9e4e778d815d162f3c68c3a50b71e370c7 100644
--- a/README.md
+++ b/README.md
@@ -1,2 +1,55 @@
-# obwahlen
-Code, um die Ergebnisse hessischer Bürgermeisterwahlen abzubilden
+# obwahlen PRE
+
+**DIES IST IM AUGENBLICK NUR EINE NOCH NICHT ANGEPASSTE KOPIE DES REFERENDUMS-CODES** - bitte nicht nutzen und wundern! Anpassung spätestens zur [1. Runde der OB-Wahl in Frankfurt am 5. März 2023](https://frankfurt.de/aktuelle-meldung/meldungen/direktwahl-oberbuergermeisterin-oberbuergermeister-frankfurt/). 
+
+R-Code, um den Auszählungsstand hessischer Bürgermeisterwahlen in Echtzeit abzurufen und mit Datawrapper darzustellen
+
+## Ordnerstruktur
+
+- **R** enthält den Code
+- **index** enthält Index-, Konfigurations-, und Template-Dateien
+- **daten** wird vom Code beschrieben und enthält den aktuellen Datenstand.
+
+## Daten aufarbeiten
+
+### Ziele
+
+Folgende Grafiken wären denkbar: 
+* Balkengrafik Ergebnis nach derzeitigem Auszählungsstand mit "Fortschrittsbalken"
+* Choropleth Stadtteil-Sieger
+* Choropleth Ergebnis nach Kandidat
+* Choropleth Wahlbeteiligung
+* Choropleth Briefwahl
+* Tabelle nach Stadtteil 
+* Tabelle nach Kandidaten (Erste drei? fünf?)
+
+### Konfiguration
+
+- Konfigurationsdatei ```index/config.csv``` mit Link, Starttermin, Datawrapper-Zielen; Anzahl der eingegangenen Briefwahlstimmen
+- ```index/index.rda``` mit Tabellen Zuordnung Stimmbezirk->Wahllokal und Stadtteilen
+
+### Aufarbeitung
+
+- Daten nach Stimmbezirk abfragen
+- Zuordnung Stimmen zu Kandidaten, Umrechnung Prozente gültige Stimmen
+Aggregation auf Stadtteilebene
+- Zuordnung Stimmbezirk->Stadtteil
+- Prozentanteile je Kandidat, Wahlbeteiligung
+Aggregation auf Stadtebene
+- Prozentanteile je Kandidat, Gewinner
+- Fortschrittsbalken ausgezählte Wahllokale
+- Fortschrittsbalken ausgezählte Stimmen (mit akt. Briefwahlstimmendaten)
+
+
+## Struktur des Codes
+
+### Hauptroutinen
+
+- **update_all.R** ist das Skript für den CRON-Job. Es pollt nach Daten, ruft die Abruf-, Aggregations- und Auswertungsfunktionen auf und gibt Meldungen aus. 
+- **lies_aktuellen_stand.R** enthält Funktionen, die die Daten lesen, aggregieren und archivieren
+- **aktualisiere_karten.R** enthält die Funktionen zur Datenausgabe
+- **messaging.R** enthält Funktionen, die Teams-Updates und -Fehlermeldungen generieren
+
+### Hilfsfunktionen
+
+- **generiere_testdaten.R** ist ein Skript, das zufällige, aber plausible CSV-Daten auf Stimmbezirks-Ebene zum Testen generiert
diff --git a/index/config.csv b/index/config.csv
new file mode 100644
index 0000000000000000000000000000000000000000..04090781806af46ccd34af31eaf562a4a8cb9201
--- /dev/null
+++ b/index/config.csv
@@ -0,0 +1,8 @@
+name,value,comment
+stimmbezirke_url,https://votemanager-ffm.ekom21cdn.de/2022-11-06/06412000/praesentation/Open-Data-06412000-Buergerentscheid-zur-Abwahl-des-Oberbuergermeisters-der-Stadt-Frankfurt-am-Main_-Herrn-Peter-Feldmann-Stimmbezirk.csv?ts=1667662273015,URL Daten-CSV Stimmbezirke
+ffm_waehler,508182,Wahlamt
+fom_id,bIm87,Datawrapper-ID Feldmann-o-meter
+choropleth_id,UwKOO,Datawrapper-ID Stadtteile Choropleth-Karte
+symbol_id,RWqrf,Datawrapper-ID Stadtteile Symbole (absolute Stimmen)
+tabelle_id,hLqMi,Datawrapper-ID Tabelle Stadtteile
+startdatum,2022-11-06 18:00:00 CET,Beginn der Auszählung
diff --git a/index/stadtteile.csv b/index/stadtteile.csv
new file mode 100644
index 0000000000000000000000000000000000000000..66dba9e3eb2e8c5a481e3be95da03d9da6e1352d
--- /dev/null
+++ b/index/stadtteile.csv
@@ -0,0 +1,45 @@
+nr,name,lon,lat,wahlberechtigt_2018,waehler_2018,gueltig_2018,feldmann_2018
+1,Altstadt,8.682385346400634,50.11059669873516,2772,1035,1030,427
+2,Innenstadt,8.682664888207869,50.113790989177375,4343,1074,1066,435
+4,Westend-Süd,8.6594393465439925,50.11682467903111,13376,5835,5814,1814
+5,Westend-Nord,8.666488952498467,50.128769620533795,6887,2761,2751,1064
+6,Nordend-West,8.684596043386934,50.13022858244322,22988,10779,10743,4368
+7,Nordend-Ost,8.69761974358955,50.127318654892264,17390,7852,7817,3578
+8,Ostend,8.719218276147204,50.11554639352114,20946,8411,8358,3873
+9,Bornheim,8.712407551447747,50.13090801018288,22232,9682,9633,4954
+10,Gutleut- und Bahnhofsviertel,8.652137942960298,50.099479845695974,6802,2113,2103,831
+11,Gallus,8.636377745265355,50.10300477630784,23958,6529,6488,2926
+12,Bockenheim,8.632922516089874,50.12128753657858,27090,10377,10332,4546
+13,Sachsenhausen-Nord,8.684579993638577,50.10051804775371,23441,9940,9897,4128
+14,Sachsenhausen-Süd und Flughafen,8.629663957345496,50.0607635296547,20710,8739,8700,3702
+16,Oberrad,8.727138168461476,50.09922899999497,9206,3109,3093,1491
+17,Niederrad,8.636199605275262,50.081631798202295,16799,5412,5366,2712
+18,Schwanheim,8.572652070944704,50.081760019105545,13936,5261,5217,2524
+19,Griesheim,8.600109548586545,50.09781734654457,14910,3670,3632,1921
+20,Rödelheim,8.603076601631098,50.127692431637506,12446,4518,4487,2108
+21,Hausen,8.626134516198546,50.13524298077671,4518,1814,1796,889
+22,Praunheim,8.61444644716483,50.14547905112678,11093,4365,4337,2109
+24,Heddernheim,8.64020132453368,50.158128239125205,11867,4579,4546,2385
+25,Niederursel,8.616911198776547,50.16683966510584,10458,3843,3818,1797
+26,Ginnheim,8.648134546192246,50.14388748058928,11185,4310,4285,2101
+27,Dornbusch,8.670541998003081,50.14434313041997,13527,6140,6102,2671
+28,Eschersheim,8.659950213724542,50.16002839395001,11166,5005,4982,2159
+29,Eckenheim,8.683795236784233,50.148564823086005,9638,3457,3425,1764
+30,Preungesheim,8.697198159142667,50.15544843144313,10222,3983,3965,2025
+31,Bonames,8.665887880254154,50.18258113675648,4467,1566,1549,862
+32,Berkersheim,8.702941786636124,50.17015956481773,2607,1137,1129,515
+33,Riederwald,8.73274589886058,50.12667040584185,3209,1070,1063,669
+34,Seckbach,8.726644066440096,50.147246840458955,7419,2926,2909,1381
+35,Fechenheim,8.762275115113775,50.12551773891441,10381,2571,2551,1475
+36,Höchst,8.539657322936813,50.098523172532,9859,2527,2506,1251
+37,Nied,8.57676379509509,50.103479453362766,12659,3730,3708,1975
+38,Sindlingen,8.51273746688725,50.07800492013246,5763,1768,1748,1011
+39,Zeilsheim,8.495768400332896,50.097784690964886,8012,2328,2299,1199
+40,Unterliederbach,8.525490184772172,50.10992510336304,10485,3201,3176,1533
+41,Sossenheim,8.574019745075416,50.12010605434964,10126,2684,2652,1270
+42,Nieder-Erlenbach,8.709219115856458,50.20871646737095,3544,1808,1796,665
+43,Kalbach-Riedberg,8.639008245521376,50.1846309062546,12409,5359,5333,2349
+44,Harheim,8.689844680792895,50.18583895746724,3548,1846,1836,601
+45,Nieder-Eschbach,8.668094243977997,50.20106152063871,8041,2979,2950,1204
+46,Bergen-Enkheim,8.766772308170399,50.15913246211432,13431,5774,5742,2583
+47,Frankfurter Berg,8.673427563622,50.169778678198924,5409,2049,2030,978
diff --git a/index/zuordnung_wahllokale.csv b/index/zuordnung_wahllokale.csv
new file mode 100644
index 0000000000000000000000000000000000000000..c673346f90a2723d028487a82298881b49dd4ceb
--- /dev/null
+++ b/index/zuordnung_wahllokale.csv
@@ -0,0 +1,576 @@
+"nr","name","ortsteilnr"
+"01001","010-01",1
+"01002","010-02",1
+"04001","040-01",2
+"07001","070-01",2
+"08001","080-01",2
+"09001","090-01",10
+"10001","100-01",4
+"10002","100-02",4
+"11001","110-01",4
+"11002","110-02",4
+"12001","120-01",6
+"12002","120-02",6
+"12003","120-03",6
+"12004","120-04",6
+"13001","130-01",7
+"13002","130-02",7
+"13003","130-03",7
+"14001","140-01",8
+"14002","140-02",8
+"14003","140-03",8
+"14004","140-04",8
+"14005","140-05",8
+"15101","151-01",10
+"15102","151-02",10
+"15103","151-03",10
+"15104","151-04",10
+"15301","153-01",11
+"15302","153-02",11
+"15401","154-01",11
+"15402","154-02",11
+"16101","161-01",11
+"16102","161-02",11
+"16103","161-03",11
+"16104","161-04",11
+"16201","162-01",11
+"16202","162-02",11
+"16203","162-03",11
+"16204","162-04",11
+"16205","162-05",11
+"16301","163-01",12
+"16302","163-02",12
+"16303","163-03",12
+"16401","164-01",11
+"16501","165-01",11
+"16502","165-02",11
+"16503","165-03",11
+"16504","165-04",11
+"17001","170-01",4
+"17002","170-02",4
+"17003","170-03",4
+"18001","180-01",4
+"18002","180-02",4
+"18003","180-03",4
+"19101","191-01",5
+"19102","191-02",5
+"19103","191-03",5
+"19201","192-01",5
+"19202","192-02",5
+"20101","201-01",6
+"20102","201-02",6
+"20201","202-01",6
+"20202","202-02",6
+"20301","203-01",6
+"20302","203-02",6
+"20303","203-03",6
+"20304","203-04",6
+"21101","211-01",6
+"21102","211-02",6
+"21103","211-03",6
+"21201","212-01",6
+"21202","212-02",6
+"21203","212-03",6
+"21301","213-01",6
+"22101","221-01",7
+"22102","221-02",7
+"22103","221-03",7
+"22201","222-01",7
+"22202","222-02",7
+"22203","222-03",7
+"22204","222-04",7
+"23001","230-01",7
+"23002","230-02",7
+"23003","230-03",7
+"24001","240-01",9
+"24002","240-02",9
+"25101","251-01",8
+"25102","251-02",8
+"25103","251-03",8
+"25104","251-04",8
+"25201","252-01",8
+"25202","252-02",8
+"25203","252-03",8
+"25204","252-04",8
+"25205","252-05",8
+"26101","261-01",8
+"26102","261-02",8
+"26103","261-03",8
+"26201","262-01",33
+"26202","262-02",33
+"27101","271-01",9
+"27102","271-02",9
+"27201","272-01",9
+"27202","272-02",9
+"27203","272-03",9
+"27204","272-04",9
+"27205","272-05",9
+"28101","281-01",9
+"28102","281-02",9
+"28103","281-03",9
+"28201","282-01",9
+"28202","282-02",9
+"28203","282-03",9
+"29001","290-01",9
+"29002","290-02",9
+"30001","300-01",13
+"30002","300-02",13
+"32101","321-01",13
+"32102","321-02",13
+"32103","321-03",13
+"32201","322-01",13
+"32202","322-02",13
+"32203","322-03",13
+"32204","322-04",13
+"32205","322-05",13
+"32301","323-01",14
+"32302","323-02",14
+"32303","323-03",14
+"32304","323-04",14
+"32305","323-05",14
+"32306","323-06",14
+"32401","324-01",13
+"32402","324-02",13
+"32403","324-03",13
+"32404","324-04",13
+"32601","326-01",14
+"32602","326-02",14
+"32603","326-03",14
+"33101","331-01",13
+"33102","331-02",13
+"33103","331-03",13
+"33201","332-01",14
+"33202","332-02",14
+"33203","332-03",14
+"33204","332-04",14
+"33205","332-05",14
+"33206","332-06",14
+"34101","341-01",12
+"34102","341-02",12
+"34103","341-03",12
+"34201","342-01",12
+"34202","342-02",12
+"34301","343-01",12
+"34401","344-01",12
+"35001","350-01",12
+"35002","350-02",12
+"35003","350-03",12
+"35004","350-04",12
+"36101","361-01",12
+"36102","361-02",12
+"36103","361-03",12
+"36201","362-01",12
+"36202","362-02",12
+"36203","362-03",12
+"36204","362-04",12
+"37101","371-01",17
+"37102","371-02",17
+"37103","371-03",17
+"37104","371-04",17
+"37105","371-05",17
+"37106","371-06",17
+"37201","372-01",17
+"37202","372-02",17
+"37203","372-03",17
+"37204","372-04",17
+"37205","372-05",17
+"37206","372-06",17
+"38001","380-01",16
+"38002","380-02",16
+"38003","380-03",16
+"38004","380-04",16
+"38005","380-05",16
+"38006","380-06",16
+"39001","390-01",34
+"39002","390-02",34
+"39003","390-03",34
+"39004","390-04",34
+"39005","390-05",34
+"39006","390-06",34
+"39007","390-07",34
+"40101","401-01",20
+"40102","401-02",20
+"40103","401-03",20
+"40104","401-04",20
+"40105","401-05",20
+"40201","402-01",20
+"40202","402-02",20
+"40203","402-03",20
+"40204","402-04",20
+"41001","410-01",21
+"41002","410-02",21
+"41003","410-03",21
+"42201","422-01",22
+"42202","422-02",22
+"42203","422-03",22
+"42301","423-01",22
+"42302","423-02",22
+"42401","424-01",22
+"42501","425-01",22
+"42601","426-01",22
+"42602","426-02",22
+"43101","431-01",24
+"43102","431-02",24
+"43103","431-03",24
+"43104","431-04",24
+"43105","431-05",24
+"43201","432-01",24
+"43202","432-02",24
+"43203","432-03",24
+"43204","432-04",24
+"44101","441-01",26
+"44102","441-02",26
+"44103","441-03",26
+"44104","441-04",26
+"44105","441-05",26
+"44106","441-06",26
+"44107","441-07",26
+"44108","441-08",26
+"44201","442-01",27
+"44202","442-02",27
+"44203","442-03",27
+"44204","442-04",27
+"45101","451-01",28
+"45102","451-02",28
+"45103","451-03",28
+"45104","451-04",28
+"45201","452-01",28
+"45202","452-02",28
+"45203","452-03",28
+"45204","452-04",28
+"46101","461-01",29
+"46102","461-02",29
+"46103","461-03",29
+"46104","461-04",29
+"46105","461-05",29
+"46106","461-06",29
+"46107","461-07",29
+"46201","462-01",27
+"46202","462-02",27
+"46203","462-03",27
+"46204","462-04",27
+"46205","462-05",27
+"46206","462-06",27
+"46301","463-01",27
+"46302","463-02",27
+"47001","470-01",30
+"47002","470-02",30
+"47003","470-03",30
+"47004","470-04",30
+"47005","470-05",30
+"47006","470-06",30
+"47007","470-07",30
+"48101","481-01",25
+"48102","481-02",25
+"48103","481-03",25
+"48201","482-01",25
+"48202","482-02",25
+"48203","482-03",25
+"48301","483-01",25
+"49101","491-01",31
+"49102","491-02",31
+"49103","491-03",31
+"49201","492-01",47
+"49202","492-02",47
+"49203","492-03",47
+"49204","492-04",47
+"50001","500-01",32
+"50002","500-02",32
+"51001","510-01",35
+"51002","510-02",35
+"51003","510-03",35
+"51004","510-04",35
+"52001","520-01",35
+"52002","520-02",35
+"52003","520-03",35
+"53101","531-01",18
+"53102","531-02",18
+"53103","531-03",18
+"53104","531-04",18
+"53105","531-05",18
+"53201","532-01",18
+"53202","532-02",18
+"53203","532-03",18
+"53204","532-04",18
+"53205","532-05",18
+"53206","532-06",18
+"54101","541-01",19
+"54102","541-02",19
+"54201","542-01",19
+"54202","542-02",19
+"54203","542-03",19
+"55101","551-01",19
+"55102","551-02",19
+"55201","552-01",19
+"55202","552-02",19
+"55203","552-03",19
+"56101","561-01",37
+"56102","561-02",37
+"56103","561-03",37
+"56104","561-04",37
+"56105","561-05",37
+"56201","562-01",37
+"56202","562-02",37
+"56203","562-03",37
+"56204","562-04",37
+"57001","570-01",36
+"57002","570-02",36
+"57003","570-03",36
+"58001","580-01",36
+"58002","580-02",36
+"59101","591-01",36
+"59102","591-02",36
+"60101","601-01",38
+"60102","601-02",38
+"60201","602-01",38
+"60202","602-02",38
+"60401","604-01",39
+"61101","611-01",39
+"61102","611-02",39
+"61201","612-01",39
+"61202","612-02",39
+"62101","621-01",40
+"62102","621-02",40
+"62103","621-03",40
+"62104","621-04",40
+"62201","622-01",40
+"62202","622-02",40
+"62203","622-03",40
+"63101","631-01",41
+"63102","631-02",41
+"63103","631-03",41
+"63104","631-04",41
+"63201","632-01",41
+"63202","632-02",41
+"63203","632-03",41
+"64001","640-01",42
+"64002","640-02",42
+"64003","640-03",42
+"65001","650-01",43
+"65002","650-02",43
+"65003","650-03",43
+"65101","651-01",43
+"65102","651-02",43
+"65103","651-03",43
+"65104","651-04",43
+"65105","651-05",43
+"65106","651-06",43
+"65107","651-07",43
+"66001","660-01",44
+"66002","660-02",44
+"66003","660-03",44
+"67001","670-01",45
+"67002","670-02",45
+"67003","670-03",45
+"67004","670-04",45
+"67005","670-05",45
+"67006","670-06",45
+"68001","680-01",46
+"68002","680-02",46
+"68003","680-03",46
+"68004","680-04",46
+"68005","680-05",46
+"68006","680-06",46
+"68007","680-07",46
+"68008","680-08",46
+"68009","680-09",46
+"68010","680-10",46
+90101,"901-01",1
+90201,"902-01",2
+90202,"902-02",2
+90401,"904-01",4
+90402,"904-02",4
+90403,"904-03",4
+90404,"904-04",4
+90405,"904-05",4
+90501,"905-01",5
+90502,"905-02",5
+90503,"905-03",5
+90601,"906-01",6
+90602,"906-02",6
+90603,"906-03",6
+90604,"906-04",6
+90605,"906-05",6
+90606,"906-06",6
+90607,"906-07",6
+90608,"906-08",6
+90609,"906-09",6
+90701,"907-01",7
+90702,"907-02",7
+90703,"907-03",7
+90704,"907-04",7
+90705,"907-05",7
+90706,"907-06",7
+90707,"907-07",7
+90801,"908-01",8
+90802,"908-02",8
+90803,"908-03",8
+90804,"908-04",8
+90805,"908-05",8
+90806,"908-06",8
+90807,"908-07",8
+90808,"908-08",8
+90809,"908-09",8
+90901,"909-01",9
+90902,"909-02",9
+90903,"909-03",9
+90904,"909-04",9
+90905,"909-05",9
+90906,"909-06",9
+90907,"909-07",9
+90908,"909-08",9
+90909,"909-09",9
+91001,"910-01",10
+91002,"910-02",10
+91003,"910-03",10
+91101,"911-01",11
+91102,"911-02",11
+91103,"911-03",11
+91104,"911-04",11
+91105,"911-05",11
+91106,"911-06",11
+91107,"911-07",11
+91108,"911-08",11
+91201,"912-01",12
+91202,"912-02",12
+91203,"912-03",12
+91204,"912-04",12
+91205,"912-05",12
+91206,"912-06",12
+91207,"912-07",12
+91208,"912-08",12
+91209,"912-09",12
+91210,"912-10",12
+91211,"912-11",12
+91301,"913-01",13
+91302,"913-02",13
+91303,"913-03",13
+91304,"913-04",13
+91305,"913-05",13
+91306,"913-06",13
+91307,"913-07",13
+91308,"913-08",13
+91309,"913-09",13
+91310,"913-10",13
+91401,"914-01",14
+91402,"914-02",14
+91403,"914-03",14
+91404,"914-04",14
+91405,"914-05",14
+91406,"914-06",14
+91407,"914-07",14
+91408,"914-08",14
+91409,"914-09",14
+91601,"916-01",16
+91602,"916-02",16
+91603,"916-03",16
+91701,"917-01",17
+91702,"917-02",17
+91703,"917-03",17
+91704,"917-04",17
+91705,"917-05",17
+91706,"917-06",17
+91801,"918-01",18
+91802,"918-02",18
+91803,"918-03",18
+91804,"918-04",18
+91805,"918-05",18
+91806,"918-06",18
+91901,"919-01",19
+91902,"919-02",19
+91903,"919-03",19
+91904,"919-04",19
+91905,"919-05",19
+92001,"920-01",20
+92002,"920-02",20
+92003,"920-03",20
+92004,"920-04",20
+92005,"920-05",20
+92101,"921-01",21
+92102,"921-02",21
+92201,"922-01",22
+92202,"922-02",22
+92203,"922-03",22
+92204,"922-04",22
+92205,"922-05",22
+92401,"924-01",24
+92402,"924-02",24
+92403,"924-03",24
+92404,"924-04",24
+92405,"924-05",24
+92501,"925-01",25
+92502,"925-02",25
+92503,"925-03",25
+92504,"925-04",25
+92601,"926-01",26
+92602,"926-02",26
+92603,"926-03",26
+92604,"926-04",26
+92701,"927-01",27
+92702,"927-02",27
+92703,"927-03",27
+92704,"927-04",27
+92705,"927-05",27
+92706,"927-06",27
+92801,"928-01",28
+92802,"928-02",28
+92803,"928-03",28
+92804,"928-04",28
+92901,"929-01",29
+92902,"929-02",29
+92903,"929-03",29
+92904,"929-04",29
+93001,"930-01",30
+93002,"930-02",30
+93003,"930-03",30
+93004,"930-04",30
+93101,"931-01",31
+93102,"931-02",31
+93201,"932-01",32
+93301,"933-01",33
+93401,"934-01",34
+93402,"934-02",34
+93403,"934-03",34
+93501,"935-01",35
+93502,"935-02",35
+93503,"935-03",35
+93504,"935-04",35
+93601,"936-01",36
+93602,"936-02",36
+93603,"936-03",36
+93701,"937-01",37
+93702,"937-02",37
+93703,"937-03",37
+93704,"937-04",37
+93801,"938-01",38
+93802,"938-02",38
+93901,"939-01",39
+93902,"939-02",39
+93903,"939-03",39
+94001,"940-01",40
+94002,"940-02",40
+94003,"940-03",40
+94004,"940-04",40
+94101,"941-01",41
+94102,"941-02",41
+94103,"941-03",41
+94104,"941-04",41
+94201,"942-01",42
+94202,"942-02",42
+94301,"943-01",43
+94302,"943-02",43
+94303,"943-03",43
+94304,"943-04",43
+94305,"943-05",43
+94401,"944-01",44
+94402,"944-02",44
+94501,"945-01",45
+94502,"945-02",45
+94503,"945-03",45
+94601,"946-01",46
+94602,"946-02",46
+94603,"946-03",46
+94604,"946-04",46
+94605,"946-05",46
+94701,"947-01",47
+94702,"947-02",47
diff --git a/obwahlen.Rproj b/obwahlen.Rproj
new file mode 100644
index 0000000000000000000000000000000000000000..8e3c2ebc99e2e337f7d69948b93529a437590b27
--- /dev/null
+++ b/obwahlen.Rproj
@@ -0,0 +1,13 @@
+Version: 1.0
+
+RestoreWorkspace: Default
+SaveWorkspace: Default
+AlwaysSaveHistory: Default
+
+EnableCodeIndexing: Yes
+UseSpacesForTab: Yes
+NumSpacesForTab: 2
+Encoding: UTF-8
+
+RnwWeave: Sweave
+LaTeX: pdfLaTeX