├── .gitignore ├── README.md ├── examples ├── lowersax.php ├── simple.php └── snippet.php └── src ├── Incidence.php └── LowerSax.php /.gitignore: -------------------------------------------------------------------------------- 1 | examples/data.json 2 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # PHP-Inzidenz-Ampel 2 | 3 | Eine Inzidenz-Ampel mit Werten des RKI. Beschrieben im Artikel [Corona-Ampel](https://ct.de/yw1c) in c’t 9/2021 ab Seite 160. 4 | 5 | ## Beispiel ausprobieren 6 | 7 | Laden Sie die Inhalte des Repos herunter und navigieren Sie in den Ordner. Starten Sie dann einen lokalen Entwicklungsserver mit: 8 | 9 | ``` 10 | php -S localhost:8000 11 | ``` 12 | 13 | Im Browser unter der Adresse http://localhost:8000/examples/simple.php finden Sie eine simple Tabelle. Unter http://localhost:8000/examples/snippet.php sehen Sie eine Inzidenz-Ampel. 14 | Im Ordner `examples` finden Sie die Dateien. Passen Sie die Regions-ID wie im Artikel beschrieben an. 15 | 16 | ## Verwenden auf der eigenen Website 17 | 18 | Sie brauchen die Datei `src/Incidence.php`, die Sie in Ihrem Dokument per `include()` einbinden. Verwenden Sie zum Beispiel die Datei `examples/snippet.php` als Schnipsel in Ihrer Seite, um eine Ampel darzustellen. -------------------------------------------------------------------------------- /examples/lowersax.php: -------------------------------------------------------------------------------- 1 | "; 14 | print_r($data); 15 | echo ""; 16 | -------------------------------------------------------------------------------- /examples/simple.php: -------------------------------------------------------------------------------- 1 | getDaily(0); 12 | 13 | echo " 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 |
" . $today['GEN'] . "
7-Tage-Inzidenz" . round($today['cases7_per_100k'], 2) . "
Fälle insgesamt" . $today['cases'] . "
Fälle letzte 7 Tage" . $today['cases7_lk'] . "
Tote" . $today['deaths'] . "
" . $today['BL'] . "
7-Tage-Inzidenz" . round($today['cases7_bl_per_100k'], 2) . "
Fälle letzte 7 Tage" . $today['cases7_bl'] . "
"; 24 | -------------------------------------------------------------------------------- /examples/snippet.php: -------------------------------------------------------------------------------- 1 | getDaily(0); 19 | 20 | echo "
"; 21 | 22 | echo "

Inzidenz-Ampel für " . $today['GEN'] . "

"; 23 | echo "
(Fälle pro 100.000 Einwohner in 7 Tagen)
"; 24 | 25 | drawStoplight($today, $threshold); 26 | 27 | echo ""; 28 | echo drawLine($today); 29 | echo drawLine($incidence->getDaily(1)); 30 | echo drawLine($incidence->getDaily(2)); 31 | echo "
"; 32 | echo "
Quelle: RKI
"; 33 | echo "
"; 34 | 35 | function drawLine($data) 36 | { 37 | if ($data) { 38 | 39 | $inc = round($data['cases7_per_100k'], 2); 40 | if ($inc < 100) { 41 | $co = "value_ok"; 42 | } else { 43 | $co = "value_stop"; 44 | } 45 | 46 | echo " 47 | " . germanDay($data['ts']) . ", " . date("d.m.Y", $data['ts']) . " 48 | " . round($data['cases7_per_100k'], 2) . " 49 | "; 50 | } 51 | } 52 | 53 | function drawStoplight($data, $threshold) 54 | { 55 | if ($data['cases7_per_100k'] > $threshold) { 56 | $color = "stoplight_stop"; 57 | $text = "Geschlossen"; 58 | } else { 59 | $color = "stoplight_ok"; 60 | $text = "Geöffnet"; 61 | } 62 | echo "
"; 63 | echo $text; 64 | echo "
"; 65 | } 66 | 67 | function germanDay($ts) 68 | { 69 | $d = [ 70 | 1 => "Montag", 71 | 2 => "Dienstag", 72 | 3 => "Mittwoch", 73 | 4 => "Donnerstag", 74 | 5 => "Freitag", 75 | 6 => "Samstag", 76 | 7 => "Sonntag" 77 | ]; 78 | return $d[date("N", $ts)]; 79 | } 80 | 81 | ?> 82 | 145 | -------------------------------------------------------------------------------- /src/Incidence.php: -------------------------------------------------------------------------------- 1 | cache_file = $cache_file; 33 | $this->region_id = $ri; 34 | } 35 | 36 | public function getDaily($offset = 0) 37 | { 38 | $d = new DateTime("today -" . $offset . " day"); 39 | $dt = $d->format('Ymd'); 40 | 41 | $c = $this->getCache($dt); 42 | if (is_array($c)) { 43 | $c['cached'] = true; 44 | return $c; 45 | } 46 | $c = $this->fetchData($dt); 47 | if (is_array($c)) { 48 | $c['cached'] = false; 49 | return $c; 50 | } 51 | } 52 | 53 | private function getCache(string $dt) 54 | { 55 | $f = @file_get_contents($this->cache_file); 56 | 57 | if ($f == false) { 58 | return; 59 | } 60 | 61 | $data = json_decode($f, true); 62 | if (isset($data[$dt])) { 63 | return $data[$dt]; 64 | } else { 65 | return; 66 | } 67 | } 68 | 69 | private function fetchData(string $dt) 70 | { 71 | $fieldstr = implode(",", $this->fields); 72 | 73 | $c = curl_init(); 74 | curl_setopt( 75 | $c, 76 | CURLOPT_URL, 77 | 'https://services7.arcgis.com/mOBPykOjAyBO2ZKk/arcgis/rest/services/RKI_Landkreisdaten/FeatureServer/0/query?where=OBJECTID=' 78 | . $this->region_id . '&outFields=' . $fieldstr . '&returnGeometry=false&outSR=&f=json' 79 | ); 80 | 81 | curl_setopt($c, CURLOPT_RETURNTRANSFER, 1); 82 | 83 | $result = curl_exec($c); 84 | if (curl_errno($c)) { 85 | throw new Exception("could not contact arcgis server"); 86 | } 87 | curl_close($c); 88 | 89 | $json = json_decode($result, true); 90 | 91 | if (!isset($json['features'][0]['attributes'])) { 92 | return; 93 | } 94 | 95 | $data = $json['features'][0]['attributes']; 96 | $date = DateTime::createFromFormat("d.m.Y, H:i", str_replace(" Uhr", "", $data['last_update'])); 97 | $data['ts'] = $date->format("U"); 98 | $set = $this->setCache($data); 99 | if ($set == $dt) { 100 | return $data; 101 | } else { 102 | return; 103 | } 104 | } 105 | 106 | private function setCache($data) 107 | { 108 | $f = @file_get_contents($this->cache_file); 109 | if ($f == false) { 110 | $old = []; 111 | } else { 112 | $old = json_decode($f, true); 113 | } 114 | $date = DateTime::createFromFormat("d.m.Y, H:i", str_replace(" Uhr", "", $data['last_update'])); 115 | $key = $date->format("Ymd"); 116 | $old[$key] = $data; 117 | file_put_contents($this->cache_file, json_encode($old)); 118 | return $key; 119 | } 120 | } 121 | -------------------------------------------------------------------------------- /src/LowerSax.php: -------------------------------------------------------------------------------- 1 | format("U"); 6 | 7 | $f = @file_get_contents('./nds.json'); 8 | if ($f === false) { 9 | getFresh($t, $city); 10 | } 11 | $cached = json_decode($f, true); 12 | 13 | if (isset($cached[$t])) { 14 | $cc = $cached[$t]; 15 | $cc['cached'] = 1; 16 | return $cc; 17 | } 18 | 19 | return getFresh($t, $city); 20 | } 21 | 22 | function getFresh($ts, $city) 23 | { 24 | $csv = @file_get_contents('https://www.apps.nlga.niedersachsen.de/corona/download.php?csv_tag_region-file'); 25 | 26 | $lines = explode("\n", $csv); 27 | 28 | $array = array(); 29 | foreach ($lines as $line) { 30 | 31 | $d = str_getcsv($line, ";"); 32 | if (isset($d[3]) and $d[3] == $city) { 33 | $date = DateTime::createFromFormat("d.m.Y, h:i", $d[0] . ", 00:00"); 34 | $ts = $date->format('U'); 35 | 36 | $d['cases7_per_100k'] = $d[6]; 37 | $d['ts'] = $ts; 38 | $array[$ts] = $d; 39 | } 40 | } 41 | 42 | if (isset($array[$ts])) { 43 | file_put_contents("./nds.json", json_encode($array)); 44 | } 45 | return $array[$ts]; 46 | } 47 | --------------------------------------------------------------------------------