/*============================================================================* *H *H FILE *H konvertiere_RKI_Datei.c *H *H MODIFICATION HISTORY *H *H Date Name Modification *H --------------------------------------------------------------------------- *H 23.11.2021 JMH Initiale Version *H 01.12.2021 JMH Konvertierung der Original-RKI-Datei (ohne cut!) *H 01.12.2021 JMH Binärdatei schreiben anstelle der beiden Textdateien *H *============================================================================*/ /*----------------------------------------------------------------------------* * Include Files *----------------------------------------------------------------------------*/ #include #include #include #include /*----------------------------------------------------------------------------* * Private #define's *----------------------------------------------------------------------------*/ #define ANZAHL_ZEICHEN_PRO_ZEILE 255 #define ANZAHL_FELDER 14 /*----------------------------------------------------------------------------* * Private functions *----------------------------------------------------------------------------*/ FILE *open_FILE (const char *filename); FILE *create_BIN_FILE (const char *filename); char *get_line_from_FILE (FILE *file, char *string); void write_to_FILE (void *buffer, size_t size, size_t number, FILE *file); void fseek_FILE (FILE *file, long int offset, int origin); void close_FILE (FILE *file); /*============================================================================* *F *F FUNCTION *F open_FILE *F *F PURPOSE *F Open ASCII file *F *============================================================================*/ FILE *open_FILE (const char *filename) { FILE *file; file = fopen (filename, "r"); if (file == NULL) { mexErrMsgTxt ("Fehler bei fopen (filename, \"r\")!"); } return file; } /* END OF FUNCTION open_FILE */ /*============================================================================* *F *F FUNCTION *F create_BIN_FILE *F *F PURPOSE *F Create binary file *F *============================================================================*/ FILE *create_BIN_FILE (const char *filename) { FILE *file; file = fopen (filename, "wb"); if (file == NULL) { mexErrMsgTxt ("Fehler bei fopen (filename, \"wb\")!"); } return file; } /* END OF FUNCTION create_BIN_FILE */ /*============================================================================* *F *F FUNCTION *F get_line_from_FILE *F *F PURPOSE *F Read string until end of line from ASCII file *F *============================================================================*/ char *get_line_from_FILE (FILE *file, char *string) { return fgets (string, ANZAHL_ZEICHEN_PRO_ZEILE, file); } /* END OF FUNCTION get_line_from_FILE */ /*============================================================================* *F *F FUNCTION *F write_to_FILE *F *F PURPOSE *F fwrite (buffer, size, number, file) with error handler *F *============================================================================*/ void write_to_FILE (void *buffer, size_t size, size_t number, FILE *file) { if (fwrite (buffer, size, number, file) < number) { mexErrMsgTxt ("Fehler bei fwrite (buffer, size, number, file)!"); } } /* END OF FUNCTION write_to_FILE */ /*============================================================================* *F *F FUNCTION *F fseek_FILE *F *F PURPOSE *F fseek (file, offset, origin) with error handler *F *============================================================================*/ void fseek_FILE (FILE *file, long int offset, int origin) { if (fseek (file, offset, origin) != 0) { mexErrMsgTxt ("Fehler bei fseek (file, offset, origin)!"); } } /* END OF FUNCTION fseek_FILE */ /*============================================================================* *F *F FUNCTION *F close_FILE *F *F PURPOSE *F fclose (file) with error handler *F *============================================================================*/ void close_FILE (FILE *file) { if (fclose (file) == EOF) { mexErrMsgTxt ("Fehler bei fclose (file)!"); } } /* END OF FUNCTION close_FILE */ /*============================================================================* *F *F FUNCTION *F mexFunction *F *F PURPOSE *F Konverter der RKI-Datei in MEX-Datei, um RAM zu schonen *F *============================================================================*/ void mexFunction (int nlhs, mxArray *plhs [], int nrhs, const mxArray *prhs []) { int Dateiname_RKI_n; char Dateiname_RKI [ANZAHL_ZEICHEN_PRO_ZEILE]; int Dateiname_BIN_n; char Dateiname_BIN [ANZAHL_ZEICHEN_PRO_ZEILE]; double *Status; FILE *Datei_RKI; FILE *Datei_BIN; char Zeile [ANZAHL_ZEICHEN_PRO_ZEILE]; char *Textfeld; int AnzahlZeilen; int Datum_gefunden; int Zahl; int Tag; int Monat; int Jahr; int AnzahlFall; int AnzahlTodesfall; int Meldejahr; int Meldemonat; int Meldetag; int NeuerFall; int NeuerTodesfall; int Referenzjahr; int Referenzmonat; int Referenztag; int NeuGenesen; int AnzahlGenesen; int IstErkrankungsbeginn; int Alter_min; int32_t Header [5]; int16_t Puffer [ANZAHL_FELDER]; /******************************************************************************/ if (nrhs < 2) { mexErrMsgTxt ("Anzahl der Input-Argumente zu klein!"); } /******************************************************************************/ Dateiname_RKI_n = mxGetN (prhs [0]); mxGetString (prhs [0], Dateiname_RKI, (Dateiname_RKI_n + 1)); /******************************************************************************/ Dateiname_BIN_n = mxGetN (prhs [1]); mxGetString (prhs [1], Dateiname_BIN, (Dateiname_BIN_n + 1)); /******************************************************************************/ /******************************************************************************/ plhs [0] = mxCreateDoubleMatrix (1, 1, mxREAL); Status = mxGetPr (plhs [0]); *Status = 1.0; /******************************************************************************/ Datei_RKI = open_FILE (Dateiname_RKI); Datei_BIN = create_BIN_FILE (Dateiname_BIN); /******************************************************************************/ /* * Platzhalter für Größe der Matrix sowie Aktualisierungs-Datum der * RKI-Corona-Datei in BIN-Datei speichern */ Header [0] = (int32_t) 0; Header [1] = (int32_t) 0; Header [2] = (int32_t) 0; Header [3] = (int32_t) 0; Header [4] = (int32_t) 0; write_to_FILE (Header, sizeof (int32_t), 5, Datei_BIN); /* * Relevante Daten der RKI-Datei parsen */ get_line_from_FILE (Datei_RKI, Zeile); AnzahlZeilen = 0; Datum_gefunden = 0; while (get_line_from_FILE (Datei_RKI, Zeile) != NULL) { Textfeld = strtok (Zeile, ","); if (Textfeld == NULL) { mexErrMsgTxt ("Leeres Textfeld!"); } Textfeld = strtok (NULL, ","); if (Textfeld == NULL) { mexErrMsgTxt ("Leeres Textfeld!"); } Textfeld = strtok (NULL, ","); if (Textfeld == NULL) { mexErrMsgTxt ("Leeres Textfeld!"); } Textfeld = strtok (NULL, ","); if (Textfeld == NULL) { mexErrMsgTxt ("Leeres Textfeld!"); } /* * Altersgruppe: Altersgruppe des Falles aus den 6 Gruppe 0-4, 5-14, 15-34, * 35-59, 60-79, 80+ sowie unbekannt */ Textfeld = strtok (NULL, ","); if (Textfeld == NULL) { mexErrMsgTxt ("Leeres Textfeld!"); } Textfeld += 1; if ((*Textfeld < '0') || (*Textfeld > '9')) { Alter_min = 99; } else { sscanf (Textfeld, "%d", &Alter_min); } Textfeld = strtok (NULL, ","); if (Textfeld == NULL) { mexErrMsgTxt ("Leeres Textfeld!"); } /* * AnzahlFall: Anzahl der Fälle in der entsprechenden Gruppe */ Textfeld = strtok (NULL, ","); if (Textfeld == NULL) { mexErrMsgTxt ("Leeres Textfeld!"); } sscanf (Textfeld, "%d", &AnzahlFall); /* * AnzahlTodesfall: Anzahl der Todesfälle in der entsprechenden Gruppe */ Textfeld = strtok (NULL, ","); if (Textfeld == NULL) { mexErrMsgTxt ("Leeres Textfeld!"); } sscanf (Textfeld, "%d", &AnzahlTodesfall); /* * Meldedatum: Datum, wann der Fall dem Gesundheitsamt bekannt geworden ist */ Textfeld = strtok (NULL, "/"); if (Textfeld == NULL) { mexErrMsgTxt ("Leeres Textfeld!"); } sscanf (Textfeld, "%d", &Meldejahr); Textfeld = strtok (NULL, "/"); if (Textfeld == NULL) { mexErrMsgTxt ("Leeres Textfeld!"); } sscanf (Textfeld, "%d", &Meldemonat); Textfeld = strtok (NULL, " "); if (Textfeld == NULL) { mexErrMsgTxt ("Leeres Textfeld!"); } sscanf (Textfeld, "%d", &Meldetag); Textfeld = strtok (NULL, "\""); if (Textfeld == NULL) { mexErrMsgTxt ("Leeres Textfeld!"); } /* * Datenstand: Datum, wann der Datensatz zuletzt aktualisiert worden ist */ Textfeld = strtok (NULL, "."); if (Textfeld == NULL) { mexErrMsgTxt ("Leeres Textfeld!"); } if (Datum_gefunden != 0) { sscanf (Textfeld, "%d", &Zahl); if (Zahl != Tag) { mexErrMsgTxt ("Inkonsistenter Tag beim Datenstand!"); } } else { sscanf (Textfeld, "%d", &Tag); } Textfeld = strtok (NULL, "."); if (Textfeld == NULL) { mexErrMsgTxt ("Leeres Textfeld!"); } if (Datum_gefunden != 0) { sscanf (Textfeld, "%d", &Zahl); if (Zahl != Monat) { mexErrMsgTxt ("Inkonsistenter Monat beim Datenstand!"); } } else { sscanf (Textfeld, "%d", &Monat); } Textfeld = strtok (NULL, ","); if (Textfeld == NULL) { mexErrMsgTxt ("Leeres Textfeld!"); } if (Datum_gefunden != 0) { sscanf (Textfeld, "%d", &Zahl); if (Zahl != Jahr) { mexErrMsgTxt ("Inkonsistentes Jahr beim Datenstand!"); } } else { sscanf (Textfeld, "%d", &Jahr); Datum_gefunden = 1; } Textfeld = strtok (NULL, ","); if (Textfeld == NULL) { mexErrMsgTxt ("Leeres Textfeld!"); } /* * NeuerFall: * 0: Fall ist in der Publikation für den aktuellen Tag und in der für * den Vortag enthalten * 1: Fall ist nur in der aktuellen Publikation enthalten * -1: Fall ist nur in der Publikation des Vortags enthalten * Damit ergibt sich: * Anzahl Fälle der aktuellen Publikation als Summe(AnzahlFall), * wenn NeuerFall in (0,1); * Delta zum Vortag als Summe(AnzahlFall), wenn NeuerFall in (-1,1) */ Textfeld = strtok (NULL, ","); if (Textfeld == NULL) { mexErrMsgTxt ("Leeres Textfeld!"); } sscanf (Textfeld, "%d", &NeuerFall); /* * NeuerTodesfall: * 0: Fall ist in der Publikation für den aktuellen Tag und in der für * den Vortag jeweils ein Todesfall * 1: Fall ist in der aktuellen Publikation ein Todesfall, nicht jedoch * in der Publikation des Vortages * -1: Fall ist in der aktuellen Publikation kein Todesfall, jedoch war * er in der Publikation des Vortags ein Todesfall * -9: Fall ist weder in der aktuellen Publikation noch in der des * Vortages ein Todesfall * Damit ergibt sich: * Anzahl Todesfälle der aktuellen Publikation als * Summe(AnzahlTodesfall), wenn NeuerTodesfall in (0,1); * Delta zum Vortag als Summe(AnzahlTodesfall), wenn NeuerTodesfall in * (-1,1) */ Textfeld = strtok (NULL, ","); if (Textfeld == NULL) { mexErrMsgTxt ("Leeres Textfeld!"); } sscanf (Textfeld, "%d", &NeuerTodesfall); /* * Referenzdatum: * Erkrankungsdatum bzw. wenn das nicht bekannt ist, das Meldedatum */ Textfeld = strtok (NULL, "/"); if (Textfeld == NULL) { mexErrMsgTxt ("Leeres Textfeld!"); } sscanf (Textfeld, "%d", &Referenzjahr); Textfeld = strtok (NULL, "/"); if (Textfeld == NULL) { mexErrMsgTxt ("Leeres Textfeld!"); } sscanf (Textfeld, "%d", &Referenzmonat); Textfeld = strtok (NULL, " "); if (Textfeld == NULL) { mexErrMsgTxt ("Leeres Textfeld!"); } sscanf (Textfeld, "%d", &Referenztag); Textfeld = strtok (NULL, ","); if (Textfeld == NULL) { mexErrMsgTxt ("Leeres Textfeld!"); } /* * NeuGenesen: * 0: Fall ist in der Publikation für den aktuellen Tag und in der für * den Vortag jeweils Genesen * 1: Fall ist in der aktuellen Publikation Genesen, nicht jedoch in der * Publikation des Vortages * -1: Fall ist in der aktuellen Publikation nicht Genesen, jedoch war * er in der Publikation des Vortags Genesen * -9: Fall ist weder in der aktuellen Publikation noch in der des * Vortages Genesen * Damit ergibt sich: * Anzahl Genesen der aktuellen Publikation als Summe(AnzahlGenesen), * wenn NeuGenesen in (0,1); * Delta zum Vortag als Summe(AnzahlGenesen) wenn NeuGenesen in (-1,1) */ Textfeld = strtok (NULL, ","); if (Textfeld == NULL) { mexErrMsgTxt ("Leeres Textfeld!"); } sscanf (Textfeld, "%d", &NeuGenesen); /* * AnzahlGenesen: Anzahl der Genesenen in der entsprechenden Gruppe */ Textfeld = strtok (NULL, ","); if (Textfeld == NULL) { mexErrMsgTxt ("Leeres Textfeld!"); } sscanf (Textfeld, "%d", &AnzahlGenesen); /* * IstErkrankungsbeginn: 1, wenn das Refdatum der Erkrankungsbeginn ist, * 0 sonst */ Textfeld = strtok (NULL, ","); if (Textfeld == NULL) { mexErrMsgTxt ("Leeres Textfeld!"); } sscanf (Textfeld, "%d", &IstErkrankungsbeginn); /* * Relevante Daten der RKI-Datei in BIN-Datei speichern */ Puffer [0] = (int16_t) AnzahlFall; Puffer [1] = (int16_t) AnzahlTodesfall; Puffer [2] = (int16_t) Meldejahr; Puffer [3] = (int16_t) Meldemonat; Puffer [4] = (int16_t) Meldetag; Puffer [5] = (int16_t) NeuerFall; Puffer [6] = (int16_t) NeuerTodesfall; Puffer [7] = (int16_t) Referenzjahr; Puffer [8] = (int16_t) Referenzmonat; Puffer [9] = (int16_t) Referenztag; Puffer [10] = (int16_t) NeuGenesen; Puffer [11] = (int16_t) AnzahlGenesen; Puffer [12] = (int16_t) IstErkrankungsbeginn; Puffer [13] = (int16_t) Alter_min; write_to_FILE (Puffer, sizeof (int16_t), ANZAHL_FELDER, Datei_BIN); AnzahlZeilen += 1; } /* * Größe der Matrix sowie Aktualisierungs-Datum der RKI-Corona-Datei am * Anfang der BIN-Datei speichern */ Header [0] = (int32_t) ANZAHL_FELDER; Header [1] = (int32_t) AnzahlZeilen; Header [2] = (int32_t) Tag; Header [3] = (int32_t) Monat; Header [4] = (int32_t) Jahr; fseek_FILE (Datei_BIN, 0, SEEK_SET); write_to_FILE (Header, sizeof (int32_t), 5, Datei_BIN); /******************************************************************************/ close_FILE (Datei_BIN); close_FILE (Datei_RKI); *Status = 0.0; } /* END OF FUNCTION mexFunction */ /* END OF FILE sortiere_RKI_Datensaetze_ein.c */