/****************************************************************************
** Leistungsorientierte Krankenanstaltenfinanzierung (LKF)                 **
** Scoring-C-Sourcen V2026.1                                               **
** (C) 2026 BMASGPK                                                        **
*****************************************************************************
** npplaus5.c - Erweiterte Plausibilitätsüberprüfungen                     **
**                                                                         **
**		 Alex.Holzer@chello.at                                             **
**       Bernhard.Pesec@dothealth.at                                       **
***************************************************************************/

#include "lkfint5.h"
#include <ctype.h>

#define TRACE_INFO(pAufenthalt,nAbtFC,sLine) (lkf_addTraceAufenthaltLine ((pAufenthalt)->pScoringContext, pAufenthalt, (int)(nAbtFC), sLine, LKF_FAC_MBDS, LKF_TRACE_INFO))
#define TRACE_DETAIL(pAufenthalt,nAbtFC,sLine) (lkf_addTraceAufenthaltLine ((pAufenthalt)->pScoringContext, pAufenthalt, (int)(nAbtFC), sLine, LKF_FAC_MBDS, LKF_TRACE_DETAIL))

#define NP_IU_DIAG_FILENAME    "NPDIAG.dat"
#define NP_INTMEL_FILENAME     "NPMEL.dat"
#define NP_INTBEGRMEL_FILENAME "NPIBMEL.dat"
#define NP_INVASMEL_FILENAME   "NPIVMEL.dat"

#define NEONINTBEH			1
#define NEONINTUEB			2
#define PAEDINTBEH			4
#define PAEDINTUEB			8
#define FNP_BESOND		   16
#define FNP_7299		   32

#define INTBEGRMEL_SHIFT	8
#define INVASMEL			(16<<8)

#define ABTTYPE_UEBERWACHUNG 1
#define ABTTYPE_BEHANDLUNG   2

#define NPPLAUSMODUS_MITMEL 1
/*#define NPPLAUS_DEFAULT_DEBUG 1*/

#define MAX_OPMEL 10000

#define VERKETT_ADD 1

/*#define DEBUG_NPPLAUS(auf,krit,res) ;*/
#define DEBUG_NPPLAUS(auf,type,krit,res) debug_npplaus(auf,type,krit,res,pNPC);

#define NPPLAUS_WARN_ALLOC_INITIAL		 10
#define NPPLAUS_WARN_ALLOC_EXTEND		 20

#define NPPLAUS_PROTOKOLL_ALLOC_INITIAL	100
#define NPPLAUS_PROTOKOLL_ALLOC_EXTEND  100

#define NPPLAUS_ABTSTAT_ALLOC_INITIAL     5
#define NPPLAUS_ABTSTAT_ALLOC_EXTEND	  5

#define NPPLAUS_MAX_NI					 14
#define NPPLAUS_MAX_NU					 12
#define NPPLAUS_MAX_PI					  6
#define NPPLAUS_MAX_PU					  6
#define NPPLAUS_MAX_S1					  1
#define NPPLAUS_MAX_S2					  1

typedef char NPPLAUS_HINT[20]; 

typedef struct 
{
	const char *ReasonCode;
	const char *ReasonText;
	int         ReasonNr;
} NPPLAUS_REASON;


typedef struct NPPLAUS_ANALYSIS
{
	unsigned int nAlloc;
	unsigned int nCount;
	const NPPLAUS_REASON **ppReason;
	NPPLAUS_HINT *pHint;
    LKF_CONTEXT *pContext;
} NPPLAUS_ANALYSIS;


typedef struct
{
	LKF_AUFENTHALT   *pAufenthalt;
	unsigned int      nAbtIndex;
	unsigned int      nWarningCode;
	char			  sInfo[120];
	NPPLAUS_ANALYSIS *pWarningAnalysis;
} NPPLAUS_WARN_STRUC;

typedef struct
{
	LKF_AUFENTHALT *pAufenthalt;
	unsigned int    nAbtIndex;
	unsigned int    nKritType;
	unsigned int    nKritNr;
	unsigned int    nOK;
} NPPLAUS_PROTOKOLL;

#define NPPLAUS_TF_COUNT      8
#define NPPLAUS_KRIT_COUNT   40

typedef struct
{
	char sAbtFC[8];
	char sEinstufung[2];
	int  nZugang;
	int  nTreffer;
	int  nNichtTreffer;
	int  nBDGesamt;
	int  nBDTreffer;
	int  nBDNichtTreffer;

	unsigned int pTFCounter[NPPLAUS_TF_COUNT];
	unsigned int pKritCount[NPPLAUS_KRIT_COUNT];
} NPPLAUS_ABTSTAT;

struct NPPLAUS_CONTEXT
{
	const NPPLAUS_STRUC **ppDiag;
	char ABTIDENT[32];
	int   *mels;
	unsigned int *meldats;
	unsigned int max_diag;
	LKF_AUFENTHALT *pAufenthalt;
	LKF_CONTEXT *pContext;
	STAMM2001 *pStamm;
	unsigned int abtindex;
	unsigned int lGebDat;
	unsigned int lIntAufDat;
	unsigned int lIntEntDat;
	unsigned int lAufDat;
	unsigned int lEntDat;
	unsigned int lAbtBd;
	unsigned int lAlterTage;
	unsigned int lNeonatologieLimit;
	unsigned int lAbtBehandlungEntdat;
	unsigned int lBehandlungsAbtIndex;
	int abt_type;
	int is_neonat;
	FILE *pTraceFile;

	NPPLAUS_WARN_STRUC *pWarnings;
	unsigned int nWarningAlloc;
	unsigned int nWarningCount;

	NPPLAUS_PROTOKOLL *pProtokoll;
	unsigned int nProtokollAlloc;
	unsigned int nProtokollCount;

	unsigned int c_ni[NPPLAUS_MAX_NI];
	unsigned int c_nu[NPPLAUS_MAX_NU];
	unsigned int c_pi[NPPLAUS_MAX_PI];
	unsigned int c_pu[NPPLAUS_MAX_PU];
	unsigned int c_s1[NPPLAUS_MAX_S1];
	unsigned int c_s2[NPPLAUS_MAX_S2];

	unsigned int bEnableProtokoll;

	char sIntAufDat[12];
	char sIntEntDat[12];

	/* Statistiken für abtsum-File */
	unsigned int nAbtStatCount;
	unsigned int nAbtStatAlloc;
	NPPLAUS_ABTSTAT *pAbtStat;

	NPPLAUS_ABTSTAT *pCurrentAbtStat;

	/* MELs ohne Datum */
	int *pMelOhneDat;

	int nTraceAufenthalt;
	char sTracePrefix[8];
} ;


/* Einleseroutinen fuer die NPPlaus-Stammdaten **********************************************/

/********************************************************************************************
** lkf_find_npplaus: Sucht zu einer Diagnose die zugehörige NPPlaus-Definition             **
********************************************************************************************/

static int find_npplaus (const void *e, const void *a)
{
	return strncmp ((const char *) e, ((const NPPLAUS_STRUC *)a)->DIAG, LKF_AUFENTHALT_DIAG_LEN); 
}

const NPPLAUS_STRUC *lkf_find_npplaus (STAMM2001 *pStamm, const char *diag)
{
	if (pStamm->pNPPlaus) {
		const NPPLAUS_STRUC *pS;
		pS = (const NPPLAUS_STRUC *) bsearch (diag, pStamm->pNPPlaus, pStamm->npplaus_gesamt, sizeof (NPPLAUS_STRUC), find_npplaus);
	
		if (!pS) {
			int len;
			char zdiag[8];

			len = GetLength (diag, LKF_AUFENTHALT_DIAG_LEN);

			if (len == 6) {
				memcpy (zdiag, diag, 5);
				zdiag[5] = ' ';
				zdiag[6] = 0;
				pS = (const NPPLAUS_STRUC *) bsearch (zdiag, pStamm->pNPPlaus, pStamm->npplaus_gesamt, sizeof (NPPLAUS_STRUC), find_npplaus);
			}
		}

		return pS;
	
	}
	else return 0;
}

/********************************************************************************************
** lkf_read_npplaus: Liest die Intensiv-Diagnosen für den NP-Plaus-Check ein.              **
****** V7.2 ********************************************************************************/


#define NPPLAUS_SETFLAG(id,val) if (buf[id]=='J') flag |= val

static int sort_npplaus (const void *d1, const void *d2)
{
	return strcmp (((const NPPLAUS_STRUC *)d1)->DIAG, ((const NPPLAUS_STRUC *)d2)->DIAG);
}

#define MAX_BUF_LEN 1024

int lkf_read_npplaus_intdiag (int modelljahr, STAMM2001 *pStamm /* V11.1 */, unsigned int *pCount, char *errbuf)
{
	int ret = 0;
	STAMM_FILE *fp;
	char buf[MAX_BUF_LEN];
	NPPLAUS_STRUC *pPlaus;
    LKF_CONTEXT *pContext;
	unsigned int count;

    pContext = pStamm->pScoringContext;
	fp = lkf_stamm_open (pStamm, NP_IU_DIAG_FILENAME, 0);
    
	if (fp->fp || fp->fileContent) {
		unsigned int nAlloc = 1000;
		pPlaus = (NPPLAUS_STRUC *) lkf_alloc_stamm_array (pContext, sizeof (NPPLAUS_STRUC), nAlloc, "alloc: npplaus_intdiag");
        if (!pPlaus) return LKF_OUTOFMEMORY_ERROR;
		count = 0;

		while (!ret && lkf_stamm_line (buf, MAX_BUF_LEN - 1, fp)) 
		{
            int flag, offset;
			if (count == nAlloc) {
				nAlloc *= 2;
				pPlaus = (NPPLAUS_STRUC *) lkf_realloc_stamm_array (pContext, sizeof (NPPLAUS_STRUC), nAlloc, (char *) pPlaus, count, "realloc: npplaus_intdiag");
                if (!pPlaus) {
                    return LKF_OUTOFMEMORY_ERROR;
                }
			}
			
			simLTrim (pPlaus[count].DIAG, buf, 6);
			pPlaus[count].DIAG[LKF_AUFENTHALT_DIAG_LEN] = 0;
			CopyTrimNull (pPlaus[count].KOMBKZ, buf + 7, NPPLAUS_KOMBKZ_LEN);
			flag = 0;
			offset = NPPLAUS_KOMBKZ_LEN + 6 + 2;				
			
			NPPLAUS_SETFLAG(offset, 1);
			NPPLAUS_SETFLAG(offset+1, 1<<1);
			NPPLAUS_SETFLAG(offset+2, 1<<2);
			NPPLAUS_SETFLAG(offset+3, 1<<3);
			NPPLAUS_SETFLAG(offset+4, 1<<4);
			NPPLAUS_SETFLAG(offset+5, 1<<5);
			NPPLAUS_SETFLAG(offset+6, 1<<6);
			NPPLAUS_SETFLAG(offset+7, 1<<7);
			NPPLAUS_SETFLAG(offset+8, 1<<8);
			NPPLAUS_SETFLAG(offset+9, 1<<9);
			NPPLAUS_SETFLAG(offset+10, 1<<10);
			NPPLAUS_SETFLAG(offset+11, 1<<11);
			NPPLAUS_SETFLAG(offset+12, 1<<12);
			NPPLAUS_SETFLAG(offset+13, 1<<13);

			pPlaus[count].FlagsNeonIntBeh = flag;

			flag = 0;
			offset += 15;
			NPPLAUS_SETFLAG(offset, 1);
			NPPLAUS_SETFLAG(offset+1, 1<<1);
			NPPLAUS_SETFLAG(offset+2, 1<<2);
			NPPLAUS_SETFLAG(offset+3, 1<<3);
			NPPLAUS_SETFLAG(offset+4, 1<<4);
			NPPLAUS_SETFLAG(offset+5, 1<<5);
			NPPLAUS_SETFLAG(offset+6, 1<<6);
			NPPLAUS_SETFLAG(offset+7, 1<<7);
			NPPLAUS_SETFLAG(offset+8, 1<<8);
			NPPLAUS_SETFLAG(offset+9, 1<<9);
			NPPLAUS_SETFLAG(offset+10, 1<<10);
			NPPLAUS_SETFLAG(offset+11, 1<<11);

			pPlaus[count].FlagsNeonIntUeb = flag;

			flag = 0;
			offset += 13;
			NPPLAUS_SETFLAG(offset, 1);
			NPPLAUS_SETFLAG(offset+1, 1<<1);
			NPPLAUS_SETFLAG(offset+2, 1<<2);
			NPPLAUS_SETFLAG(offset+3, 1<<3);
			NPPLAUS_SETFLAG(offset+4, 1<<4);
			NPPLAUS_SETFLAG(offset+5, 1<<5);
			
			pPlaus[count].FlagsPaedIntBeh = flag;

			flag = 0;
			offset += 7;
			NPPLAUS_SETFLAG(offset, 1);
			NPPLAUS_SETFLAG(offset+1, 1<<1);
			NPPLAUS_SETFLAG(offset+2, 1<<2);
			NPPLAUS_SETFLAG(offset+3, 1<<3);
			NPPLAUS_SETFLAG(offset+4, 1<<4);
			NPPLAUS_SETFLAG(offset+5, 1<<5);
			pPlaus[count].FlagsPaedIntUeb = flag;
			++count;
		}
		lkf_stamm_close (fp);
		if (ret) LKF_FREE (pContext, "lkf_read_npplaus_intdiag", pPlaus);
		else {
			qsort (pPlaus, count, sizeof(NPPLAUS_STRUC), sort_npplaus);
			
			pStamm->pNPPlaus = pPlaus;
			*pCount = count;
		}

	}
	else {
		pStamm->nNPDisabled = 1;
		sprintf (errbuf, "Stammdaten-Datei '%s' konnte nicht geoeffnet werden: %s", NP_IU_DIAG_FILENAME, fp->error);
        lkf_stamm_close(fp);
		ret = 1;
	}


	if (ret) {
		pStamm->pNPPlaus = 0;
		*pCount = 0;
		return ret;
	}
	return 0;
}

static const char *SpecTexts[] = {/* FNP_7299 */   "7299 codiert (Abrechnung erzwungen, Krankengeschichte vorzulegen)",
								  /* FNP_besond */ "besondere Umstände: Entlassungsart Transfer- oder Sterbefall"};

static const char *PaedIntUebTexts[] = {/* PU_Krit01 */ "Überwachung und Therapie zur Abwendung einer lebensbedrohlichen Verschlechterung",
										/* PU_Krit02 */ "3 Tage Überwachung nach Beendigung einer maschinellen Beatmung",
										/* PU_Krit03 */ "Überwachung (mind. 48 Std.) nach Schockbehandlung",
										/* PU_Krit04 */ "Postop-Überwachung",
										/* PU_Krit05 */ "Patienten mit zentral liegendem Gefäßkatheter",
										/* PU_Krit06 */ "sonstige Intensivüberwachungsmaßnahmen"};

static const char *PaedIntBehTexts[] = {/* PI_Krit01 */ "Überwachung von Vitalparametern und Therapie bei akuter Lebensbedrohung",
										/* PI_Krit02 */ "Beatmung oder Atemhilfe (und 24 Std. darüber hinaus)",
										/* PI_Krit03 */ "Schockbehandlung bis zur Stabilisierung",
										/* PI_Krit04 */ "kontinuierliche, invasive Druckmessung (7281)",
										/* PI_Krit05 */ "Totale parenterale Ernährung oder Zentraler Venenkatheter (in der akuten Phase)",
										/* PI_Krit06 */ "Sonstige Intensivbehandlungsmaßnahmen (z.B. Peritonealdialyse, Haemofiltration, Kardioversion, externe Schrittmachertherapie)"};

static const char *NeonIntBehTexts[] = {/* NI_Krit01 */ "FG <30 postmenstr.Wochen und/oder < 1.500 g KG", 
										/* NI_Krit02 */ "FG/NG mit Apnoen (>15 Sek.) und/oder Bradykardien (<80%), die zur Beatmung mit dem Beutel zwingen oder häufig (>5mal in 8 Std.) einer externen Stimulation bedürfen", 
										/* NI_Krit03 */ "Beatmung oder CPAP-Atemhilfe, auch bis 24 Std. danach", 
										/* NI_Krit04 */ "akut bedrohliche. Herzfehler/Herzrhythmusstörung", 
										/* NI_Krit05 */ "Schock und/oder schwere Gerinnungsstörung", 
										/* NI_Krit06 */ "Hydrops fetalis", 
										/* NI_Krit07 */ "Lebensbedrohliche Infektionen (Sepsis, Meningitis, NEC) bis 3 Tage nach der Stabilisierung", 
										/* NI_Krit08 */ "Lebensbedrohliche Stoffwechselstörungen (z.B. schwere Hypoglykämie) bis zur Stabilisierung", 
										/* NI_Krit09 */ "Schwere Erkrankungen des ZNS (Postasphyxiesyndrom, frische Hirnblutung, Krampfstatus)", 
										/* NI_Krit10 */ "Zustand nach größeren Operationen (Dauer abhängig vom Pflegebedarf, mind. 2 Tage)", 
										/* NI_Krit11 */ "Einleitung einer totalen parenteralen Ernährung (meist über ZVK) in der akuten Krankheitsphase", 
										/* NI_Krit12 */ "Behandlung mit sehr differenten Medikamenten (z.B. Katecholamine, Prostaglandin E1)", 
										/* NI_Krit13 */ "FG/NG mit Pleuradrainage, arteriellem Zugang, Austauschtransfusion, Peritonealdialyse, externem Schrittmacher, offene Ventrikeldrainage, etc.", 
										/* NI_Krit14 */ "FG/NG am Tage eines zeitaufwendigen externen Transportes mit Arzt"};

static const char *NeonIntUebTexts[] = {/* NU_Krit01 */ "FG 30-32 postmenstr.Wochen und/oder 1.500 - 1.800 g KG",
										/* NU_Krit02 */ "Apnoen und/oder Bradykardien (externe Stimulation selten oder nicht erforderlich)",
										/* NU_Krit03 */ "Respiratorische Störungen ohne Atemhilfe (z.B. Pneumothorax, hoher oder stark wechselnder Sauerstoffbedarf)",
										/* NU_Krit04 */ "Symptomatischer Herzfehler und/oder Herzrhythmusstörung",
										/* NU_Krit05 */ "Schwere Infektion (Pneumonie, Enteritis, Sepsisverdacht) bis zur Stabilisierung",
										/* NU_Krit06 */ "Fetopathia diabetica und andere überwachungsbedürftige Stoffwechselstörungen",
										/* NU_Krit07 */ "Krampfanfälle (während der medikamentösen Einstellung)",
										/* NU_Krit08 */ "Drogenentzugssyndrom",
										/* NU_Krit09 */ "Zustand nach größeren (3.-5. Tag, vorher Intensivtherapie) oder kleineren (1.-2. Tag) Operationen",
										/* NU_Krit10 */ "Zentraler Venenkatheter und/oder totale parenterale Ernährung",
										/* NU_Krit11 */ "",
										/* NU_Krit12 */ "Auffällige FG und NG mit unklarer Diagnose in den ersten 24 h nach der Aufnahme (praktisch alle FG und NG)"};

static int debug_npplaus (const char *auf, unsigned int krittype, unsigned int kritnr, int res, NPPLAUS_CONTEXT *pNPC)
{
	NPPLAUS_PROTOKOLL *pProt;
	if (!pNPC->bEnableProtokoll) return -1;

	if (!res) return -2; /* nur getroffene Faelle dokumentieren */

	if (krittype == FNP_7299)
		return -3; /* FNP_7299-Treffer werden nicht protokolliert */

	if (pNPC->nProtokollCount == pNPC->nProtokollAlloc) {
		NPPLAUS_PROTOKOLL *pOld = pNPC->pProtokoll;
		pNPC->nProtokollAlloc += NPPLAUS_PROTOKOLL_ALLOC_EXTEND;
		pNPC->pProtokoll = (NPPLAUS_PROTOKOLL *) LKF_CALLOC (pNPC->pContext, "debug_npplaus", pNPC->nProtokollAlloc, sizeof (NPPLAUS_PROTOKOLL));
        if (!pNPC->pProtokoll) {
            if (pOld) LKF_FREE(pNPC->pContext, "debug_npplaus", pOld);
            return LKF_OUTOFMEMORY_ERROR;
        }
		if (pOld) {
			if (pNPC->nProtokollCount) memcpy (pNPC->pProtokoll, pOld, sizeof(NPPLAUS_PROTOKOLL) * pNPC->nProtokollCount);
			LKF_FREE (pNPC->pContext, "debug_npplaus", pOld);
		}
	}

	pProt = pNPC->pProtokoll + pNPC->nProtokollCount++;

	pProt->nKritType = krittype;
	pProt->nKritNr = kritnr;
	pProt->nOK = 1;
	pProt->pAufenthalt = pNPC->pAufenthalt;
	pProt->nAbtIndex = pNPC->abtindex;
    return 0;
}

static const char *lkf_npplaus_trace_getdaterangebuffer (NPPLAUS_CONTEXT *pNPC, unsigned int nStartDate, unsigned int nBeforeDate, char *sBuf)
{
	char sStartDate[12];
	char sEndDate[12];
	if (nStartDate) 
		lkf_int2dat (nStartDate, sStartDate);
	else
		strcpy (sStartDate, "?");

	if (nBeforeDate)
		lkf_int2dat (nBeforeDate-1, sEndDate);
	else
		strcpy (sEndDate, "?");

	sprintf (sBuf, "range: %s - %s", sStartDate, sEndDate);
	return sBuf;
}

static void lkf_npplaus_tracedetail_criteria (NPPLAUS_CONTEXT *pNPC, const char *sLine)
{ /* Kriteriums-spezifische Trace-Information */

	char sTraceLine[1024];
	sprintf (sTraceLine, "%5.5s: %s", pNPC->sTracePrefix, sLine);

	TRACE_DETAIL (pNPC->pAufenthalt, pNPC->abtindex, sTraceLine);
}


int lkf_read_npplaus_intmel (int modelljahr, STAMM2001 *pStamm, char *errbuf)
{
	int mel, flag;
	STAMM_FILE *fp;
	char buf[MAX_BUF_LEN];


    for (mel = 0; mel < (int)pStamm->mel_list_gesamt; mel++) pStamm->mel_array[mel].flags = 0;

	fp = lkf_stamm_open (pStamm, NP_INTMEL_FILENAME, 0);

    if (fp->fp || fp->fileContent) {
		while (lkf_stamm_line (buf, MAX_BUF_LEN - 1, fp)) {
            mel = FindMelIndexStamm (pStamm, buf);
            if (mel < 0) continue;
			flag = 0;
			NPPLAUS_SETFLAG(5,NEONINTBEH);
			NPPLAUS_SETFLAG(6,NEONINTUEB);
			NPPLAUS_SETFLAG(7,PAEDINTBEH);
			NPPLAUS_SETFLAG(8,PAEDINTUEB);
			pStamm->mel_array[mel].flags = (unsigned int) flag;
			
		}
			
		lkf_stamm_close (fp);
		return 0;
	}

    pStamm->nNPDisabled = 1;
    sprintf (errbuf, "Stammdaten-Datei '%s' konnte nicht geoeffnet werden: %s", NP_INTMEL_FILENAME, fp->error);
    lkf_stamm_close(fp);
    return 1;
}

int lkf_read_npplaus_intbegrmel (int modelljahr, STAMM2001 *pStamm, char *errbuf)
{
	int mel_von, mel_bis, mel, flag;
	STAMM_FILE *fp;
	char buf[MAX_BUF_LEN];

	fp = lkf_stamm_open (pStamm, NP_INTBEGRMEL_FILENAME, 0);

	if (fp->fp || fp->fileContent) {
		while (lkf_stamm_line (buf, MAX_BUF_LEN - 1, fp)) {
            mel_von = FindMelIndexStamm (pStamm, buf);
            mel_bis = FindMelIndexStamm (pStamm, buf + 5);
            if (mel_von < 0 || mel_bis < 0)
                continue;
            
			flag = 0;
			NPPLAUS_SETFLAG(10,NEONINTBEH);
			NPPLAUS_SETFLAG(12,NEONINTUEB);
			NPPLAUS_SETFLAG(11,PAEDINTBEH);
			NPPLAUS_SETFLAG(13,PAEDINTUEB);

			for (mel = mel_von; mel <= mel_bis; mel++) {
				if (pStamm->mel_array[mel].isValid)
					pStamm->mel_array[mel].flags |= (unsigned int) (flag << INTBEGRMEL_SHIFT);
			
			}			
		}
			
		lkf_stamm_close (fp);
		return 0;
	}
	
    pStamm->nNPDisabled = 1;
    sprintf (errbuf, "Stammdaten-Datei '%s' konnte nicht geoeffnet werden: %s", NP_INTBEGRMEL_FILENAME, fp->error);
    lkf_stamm_close(fp);
    return 1;
}


int lkf_read_npplaus_invasmel (int modelljahr, STAMM2001 *pStamm, char *errbuf)
{
	int mel;
	STAMM_FILE *fp;
	char buf[MAX_BUF_LEN];

	fp = lkf_stamm_open (pStamm, NP_INVASMEL_FILENAME, 0);

	if (fp->fp || fp->fileContent) {
		while (lkf_stamm_line (buf, MAX_BUF_LEN - 1, fp)) {
            mel = FindMelIndexStamm (pStamm, buf);
            if (mel < 0) continue;
			if (pStamm->mel_array[mel].isValid) pStamm->mel_array[mel].flags |= INVASMEL;
		}
			
		lkf_stamm_close (fp);
		return 0;
	}
	
    pStamm->nNPDisabled = 1;
    sprintf (errbuf, "Stammdaten-Datei '%s' konnte nicht geoeffnet werden: %s", NP_INVASMEL_FILENAME, fp->error);
    lkf_stamm_close(fp);
    return 1;
}



/* Plausibilitätsüberprüfungen *******************************************************************************/

typedef int (*NPPLAUS_CHECK_FUNCTION_TYPE)(NPPLAUS_CONTEXT *);



/************************************************************************************************************
** Tracing-Hilfsroutinen                                                                                   **
************************************************************************************************************/


static const char *trace_gettypestring (unsigned int type)
{ 
	switch (type)
	{
	default:
		return "???";
	case 0:
		return "ALL";
	case NEONINTBEH:
		return "NB";
	case NEONINTUEB:
		return "NU";
	case PAEDINTBEH:
		return "PB";
	case PAEDINTUEB:
		return "PU";
	case (NEONINTBEH << INTBEGRMEL_SHIFT):
		return "BEGR-NI";
	case (NEONINTUEB << INTBEGRMEL_SHIFT):
		return "BEGR-NU";
	case (PAEDINTBEH << INTBEGRMEL_SHIFT):
		return "BEGR-PI";
	case (PAEDINTUEB << INTBEGRMEL_SHIFT):
		return "BEGR-PU";
	case INVASMEL:
		return "INVAS";
	}
}

static const char *trace_gettypeflagstring (unsigned int type, int flag, char *sBuf)
{
	const char *sTypeString = trace_gettypestring (type);
	
	char sFlagBuf[20];
	const char *sNrString = 0;

	switch (flag)
	{
		case 1:
			sNrString = "1";break;
		case 2:
			sNrString = "2";break;
		case 4:
			sNrString = "3";break;
		case 8:
			sNrString = "4";break;
		case 16:
			sNrString = "5";break;
		case 32:
			sNrString = "6";break;
		case 64:
			sNrString = "7";break;
		case 128:
			sNrString = "8";break;
		case 256:
			sNrString = "9";break;
		case 512:
			sNrString = "10";break;
		case 1024:
			sNrString = "11";break;
		case 2048:
			sNrString = "12";break;
		case 4096:
			sNrString = "13";break;
		case 8192:
			sNrString = "14";break;
		case 16384:
			sNrString = "15";break;
		default:
			sprintf (sFlagBuf, "~%d", flag);
			sNrString = sFlagBuf;
	
	}

	sprintf (sBuf, "%s#%s", sTypeString, sNrString);
	return sBuf;
}


/************************************************************************************************************
** Hilfsroutinen, die Teile der Kriterien überprüfen                                                       **
************************************************************************************************************/

static int flagcheckeddiag (NPPLAUS_CONTEXT *pNPC, unsigned int type, int flag, unsigned int thisdiag)
{ /* Überprüft für eine Diagnose, ob das entsprechende Flag gesetzt ist */
	
	if (pNPC->ppDiag[thisdiag]) {	
		switch (type) {
		
			case NEONINTUEB:
				if (pNPC->ppDiag[thisdiag]->FlagsNeonIntUeb & flag) return 1;
				break;
			case NEONINTBEH:
				if (pNPC->ppDiag[thisdiag]->FlagsNeonIntBeh & flag) return 1;
				break;
			case PAEDINTUEB:
				if (pNPC->ppDiag[thisdiag]->FlagsPaedIntUeb & flag) return 1;
				break;
			case PAEDINTBEH:
				if (pNPC->ppDiag[thisdiag]->FlagsPaedIntBeh & flag) return 1;
				break;
			case 0:
				return 1;
			default:
				break;	
		}
	}
	return 0;
}


static int flagchecked (NPPLAUS_CONTEXT *pNPC, unsigned int type, int flag, unsigned int startdiag)
{ /* Überprüft, ob bei einer best. Diagnose zu einem Typ das entsprechende Flag gesetzt ist,
	 beginnend mit startdiag; es wird der Index bzw. -1 zurückgeliefert */
	unsigned int i;

	for (i = startdiag; i < pNPC->max_diag; i++) {
		if (flagcheckeddiag (pNPC, type, flag, i))
		{
			if (LKF_IS_TRACE_DETAIL (pNPC->nTraceAufenthalt))
			{
				char sTraceLine[512];
				char sTypeFlagBuf[24];
				sprintf (sTraceLine, "suche nach np-diag (%s) (start=%d): index=%d gefunden (DIAG=%6.6s, KombKz=%s)", 
							trace_gettypeflagstring(type, flag, sTypeFlagBuf), startdiag, i, pNPC->ppDiag[i]->DIAG, pNPC->ppDiag[i]->KOMBKZ);
				lkf_npplaus_tracedetail_criteria (pNPC, sTraceLine);
			}
			return (int) i;
		}
	}

	if (LKF_IS_TRACE_DETAIL (pNPC->nTraceAufenthalt))
	{
		char sTraceLine[512];
		char sTypeFlagBuf[24];
		sprintf (sTraceLine, "suche nach np-diag (%s) (start=%d): nicht gefunden", 
					trace_gettypeflagstring(type, flag, sTypeFlagBuf), startdiag);
		lkf_npplaus_tracedetail_criteria (pNPC, sTraceLine);
	}

	return -1;
}

static int check_matchingmeldat (NPPLAUS_CONTEXT *pNPC, unsigned int melindex, MEL_ARRAY_STRUC *pMel, unsigned int min_date, unsigned int before_date)
{ /* Überprüft, ob die Leistung waehrend des angeg. Zeitraums erbracht wurde */

	unsigned int lMelDat = (unsigned int) lkf_dat2int (pNPC->pAufenthalt->mel[melindex].MELDAT);

	if (lMelDat == 0)
	{
		return 0;
	}
	if (min_date == 0 && before_date == 0) return 1;
	else if ((!min_date || lMelDat >= min_date) && (!before_date || lMelDat < before_date)) return 1;
	else return 0;
}

static int check_matchingmel (NPPLAUS_CONTEXT *pNPC, unsigned int type, int start, unsigned int min_date, unsigned int before_date)
{
	unsigned int i;
	int mel;
	MEL_ARRAY_STRUC *pMel;

	for (i = (unsigned int) start; i < pNPC->pAufenthalt->mel_anz; i++) {
	
		mel = pNPC->mels[i];
		if (mel >= 0) { /* V21.2: ignore invalid MELs (Crash) */
			pMel = pNPC->pContext->pStamm2001->mel_array + mel;
			if (pMel->flags & type) {
				if (check_matchingmeldat (pNPC, i, pMel, min_date, before_date)) 
				{
					if (LKF_IS_TRACE_DETAIL (pNPC->nTraceAufenthalt))
					{
						char sTraceLine[512];
						char sTraceDateBuf[48];
						sprintf (sTraceLine, "suche nach np-mel (typ=%s/start=%d/%s): index=%d (mel=%4.4s) gefunden", 
									trace_gettypestring(type), start, lkf_npplaus_trace_getdaterangebuffer (pNPC, min_date, before_date, sTraceDateBuf),
									i, pNPC->pAufenthalt->mel[i].MEL);
						lkf_npplaus_tracedetail_criteria (pNPC, sTraceLine);
					}
					return (int) i;
				}
			}
		}
	}

	if (LKF_IS_TRACE_DETAIL (pNPC->nTraceAufenthalt))
	{
		char sTraceLine[512];
		char sTraceDateBuf[48];
		sprintf (sTraceLine, "suche nach np-mel (typ=%s/start=%d/%s): nicht gefunden", 
					trace_gettypestring(type), start, lkf_npplaus_trace_getdaterangebuffer (pNPC, min_date, before_date, sTraceDateBuf));
		lkf_npplaus_tracedetail_criteria (pNPC, sTraceLine);
	}
	return -1;
}

static int check_matchingmelfromlist (NPPLAUS_CONTEXT *pNPC, const int *melarray, unsigned int min_date, unsigned int before_date)
{
	unsigned int i, j;
	int mel;
	MEL_ARRAY_STRUC *pMel;

	for (i = 0; i < pNPC->pAufenthalt->mel_anz; i++) {
		mel = pNPC->mels[i];
		if (mel>=0) {
			for (j = 0; melarray[j] && melarray[j] != mel; j++) ;
			if (melarray[j]) {
				pMel = pNPC->pContext->pStamm2001->mel_array + mel;
				if (check_matchingmeldat (pNPC, i, pMel, min_date, before_date)) return (int) i;
			}
		}
	}
	return -1;
}

static int has_kombkz (NPPLAUS_CONTEXT *pNPC, unsigned int index, const char *kombkz)
{
	return !strcmp(pNPC->ppDiag[index]->KOMBKZ, kombkz);
}

static int has_kombkz_array (NPPLAUS_CONTEXT *pNPC, unsigned int index, const char **kombkzarray)
{
	unsigned int i;
	for (i = 0; kombkzarray[i]; i++) {
		if (has_kombkz (pNPC, index, kombkzarray[i])) return 1;
	}
	return 0;
}

static int find_diag_kombkz (NPPLAUS_CONTEXT *pNPC, const char *kombkz, unsigned int exclude, unsigned int type, int flag)
{
	unsigned int i;
	for (i = 0; i < pNPC->max_diag; i++) {
		if (i != exclude && pNPC->ppDiag[i] != 0) {
			if (has_kombkz (pNPC, i, kombkz)) {

				int bFound = 0;
				if (type) {
					if (flagcheckeddiag (pNPC, type, flag, i)) bFound = 1;
				}
				else bFound = 1;

				if (bFound)
				{
					if (LKF_IS_TRACE_DETAIL (pNPC->nTraceAufenthalt))
					{
						char sTraceLine[512];
						char sTypeFlagBuf[24];
						sprintf (sTraceLine, "suche nach np-diag (%s) mit kombkz=%s (exclude=%d): index=%d gefunden (DIAG=%6.6s, KombKz=%s)", 
									trace_gettypeflagstring(type, flag, sTypeFlagBuf), kombkz, exclude, i, pNPC->ppDiag[i]->DIAG, pNPC->ppDiag[i]->KOMBKZ);
						lkf_npplaus_tracedetail_criteria (pNPC, sTraceLine);
					}
					return (int) i;
				}
			}
		}
	}
	if (LKF_IS_TRACE_DETAIL (pNPC->nTraceAufenthalt))
	{
		char sTypeFlagBuf[24];
		char sTraceLine[512];
		sprintf (sTraceLine, "suche nach np-diag (%s) mit kombkz=%s (exclude=%d): nicht gefunden", 
					trace_gettypeflagstring(type, flag, sTypeFlagBuf), kombkz, exclude);
		lkf_npplaus_tracedetail_criteria (pNPC, sTraceLine);
	}
	return -1;
}

static const char *join_strings (const char **psStringArray, char *sBuf)
{
	while (*psStringArray)
	{
		strcpy (sBuf, *psStringArray);
		sBuf += strlen (*(psStringArray++));
	}
	*sBuf = 0;
	return sBuf;
}

static int find_diag_kombkz_array (NPPLAUS_CONTEXT *pNPC, const char **kombkzs, unsigned int exclude, int start, unsigned int type, int flag)
{
	unsigned int i, j;
	for (i = (unsigned int) start; i < pNPC->max_diag; i++) {
		if (i != exclude && pNPC->ppDiag[i]) {
			for (j = 0; kombkzs[j]; j++) {
				if (has_kombkz (pNPC, i, kombkzs[j])) {
					int bFound = 0;
					if (type) {
						if (flagcheckeddiag (pNPC, type, flag, i)) bFound = 1;
					}
					else bFound = 1;

					if (bFound)
					{
						if (LKF_IS_TRACE_DETAIL (pNPC->nTraceAufenthalt))
						{
							char sTraceLine[512];
							char sKombKZBuf[128];
							char sTypeFlagBuf[24];
							sprintf (sTraceLine, "suche nach np-diag (%s) mit kombkz in [%s] (exclude=%d): index=%d gefunden (DIAG=%6.6s, KombKz=%s)", 
										trace_gettypeflagstring(type, flag, sTypeFlagBuf), join_strings (kombkzs, sKombKZBuf), exclude, i, pNPC->ppDiag[i]->DIAG, pNPC->ppDiag[i]->KOMBKZ);
							lkf_npplaus_tracedetail_criteria (pNPC, sTraceLine);
						}
						return (int) i;
					}
				}
			}
		}
	}
	if (LKF_IS_TRACE_DETAIL (pNPC->nTraceAufenthalt))
	{
		char sTraceLine[512];
		char sKombKZBuf[128];
		char sTypeFlagBuf[24];
		sprintf (sTraceLine, "suche nach np-diag (%s) mit kombkzs in [%s] (exclude=%d): nicht gefunden", 
					trace_gettypeflagstring(type, flag, sTypeFlagBuf), join_strings (kombkzs, sKombKZBuf), exclude);
		lkf_npplaus_tracedetail_criteria (pNPC, sTraceLine);
	}
	return -1;
}

static int check_diag_invers_kombkz (NPPLAUS_CONTEXT *pNPC, unsigned int index, const char *kombkz, const char *invkombkz, int invers, int type, int flag)
{ /* Überprüft, ob die akt. Diagnose das kombkz hat und eine zweite Diagnose mit invkombkz kodiert ist */
	if (has_kombkz (pNPC, index, kombkz)) {
		if (find_diag_kombkz (pNPC, invkombkz, index, 0, 0 /* V10.0 type, flag */)>=0) return 1;
	}
	return 0;
}

static int check_diag_invers_kombkz_array (NPPLAUS_CONTEXT *pNPC, unsigned int index, const char **kombkzarray, const char **invkombkzarray, int invers, int type, int flag)
{
	if (has_kombkz_array (pNPC, index, kombkzarray)) {
		if (find_diag_kombkz_array (pNPC, invkombkzarray, index, 0, 0, 0) >= 0) return 1;
	}
	return 0;
}

static int npplaus_stdalterlst_check (NPPLAUS_CONTEXT *pNPC, unsigned int type, int flag)
{
	int found_mel, found_diag;

	found_diag = flagchecked (pNPC, type, flag, 0);
	if (found_diag == -1) return 0;

#ifdef NPPLAUSMODUS_MITMEL
	found_mel = check_matchingmel (pNPC, type, 0, pNPC->lIntAufDat, pNPC->lIntEntDat + VERKETT_ADD);
	if (found_mel == -1) return 0;
#endif

	return 1;
}


static int npplaus_stdalterlst_check_mel (NPPLAUS_CONTEXT *pNPC, unsigned int type, int flag)
{
	int found;

	found = flagchecked (pNPC, type, flag, 0);
	if (found == -1) return 0;

	found = check_matchingmel (pNPC, type, 0, pNPC->lIntAufDat, pNPC->lIntEntDat + VERKETT_ADD);
	if (found == -1) return 0;

	return 1;
}


static int npplaus_stdalterlst_check_mellist (NPPLAUS_CONTEXT *pNPC, unsigned int type, int flag, const int *melarray, unsigned int min_date, unsigned int max_date)
{
	int found;

	found = flagchecked (pNPC, type, flag, 0);
	if (found == -1) return 0;

	found = check_matchingmelfromlist (pNPC, melarray, min_date, max_date);
	if (found == -1) return 0;

	return 1;
}

static int check_opmel_begr (NPPLAUS_CONTEXT *pNPC, unsigned int type, int max_mel, unsigned int min_date, unsigned int before_date)
{
	int found_mel = -1;

	while (1) {
		found_mel = check_matchingmel (pNPC, type << INTBEGRMEL_SHIFT, found_mel + 1, min_date, before_date);
		if (found_mel == -1) return -1;
	
		if (!max_mel || pNPC->mels[found_mel] <= max_mel) return found_mel;
	}
}


static int check_opmel_invas (NPPLAUS_CONTEXT *pNPC, int max_mel, unsigned int min_date, unsigned int before_date)
{
	int found_mel = -1;

	while (1) {
		found_mel = check_matchingmel (pNPC, INVASMEL, found_mel+1, min_date, before_date);
		if (found_mel == -1) return -1;
	
		if (!max_mel || pNPC->mels[found_mel] <= max_mel) return found_mel;
	}
}


/************************************************************************************************************
** Kriterien für Neonatologische Intensivueberwachung                                                      **
************************************************************************************************************/

static int npplaus_neonintueb1 (NPPLAUS_CONTEXT *pNPC)
{
	return npplaus_stdalterlst_check (pNPC, NEONINTUEB, 1<<0);
}

static int npplaus_neonintueb2 (NPPLAUS_CONTEXT *pNPC)
{
	return npplaus_stdalterlst_check (pNPC, NEONINTUEB, 1<<1);
}

static int npplaus_neonintueb3 (NPPLAUS_CONTEXT *pNPC)
{
	static const char *kombkzarray[] = {"Rsp", "RspInt", 0};
	int nextcheckdiag = -1;
	int found;

#ifdef NPPLAUSMODUS_MITMEL
	found = check_matchingmel (pNPC, NEONINTUEB, 0, pNPC->lIntAufDat, pNPC->lIntEntDat + VERKETT_ADD);
	if (found == -1) return 0;
#endif

	do {
		found = flagchecked (pNPC, NEONINTUEB, 1<<2, (unsigned int) (nextcheckdiag + 1));
		nextcheckdiag = found;

		if (found >= 0) {
			if (!has_kombkz_array (pNPC, (unsigned int) found, kombkzarray)) return 1;
			if (has_kombkz (pNPC, (unsigned int) found, "Rsp"))
			{
				if (find_diag_kombkz (pNPC, "RspInt", (unsigned int) found, 0, 0)) return 1;
			}
		}
	} while (nextcheckdiag != -1);
	return 0;
}

static int npplaus_neonintueb4 (NPPLAUS_CONTEXT *pNPC)
{
	return npplaus_stdalterlst_check (pNPC, NEONINTUEB, 1<<3);
}

static int npplaus_neonintueb5 (NPPLAUS_CONTEXT *pNPC)
{
	return npplaus_stdalterlst_check (pNPC, NEONINTUEB, 1<<4);
}

static int npplaus_neonintueb6 (NPPLAUS_CONTEXT *pNPC)
{
	return npplaus_stdalterlst_check (pNPC, NEONINTUEB, 1<<5);
}

static int npplaus_neonintueb7 (NPPLAUS_CONTEXT *pNPC)
{
	return npplaus_stdalterlst_check (pNPC, NEONINTUEB, 1<<6);
}

static int npplaus_neonintueb8 (NPPLAUS_CONTEXT *pNPC)
{
	return npplaus_stdalterlst_check (pNPC, NEONINTUEB, 1<<7);
}


#define MAX_OPMEL 10000

static int npplaus_neonintueb9 (NPPLAUS_CONTEXT *pNPC)
{
	int found_mel, found_diag;
	
	unsigned int i;
	int mel;
	MEL_ARRAY_STRUC *pMel;

	found_mel = check_opmel_invas (pNPC, MAX_OPMEL, 0, pNPC->lIntEntDat + VERKETT_ADD);
	if (found_mel < 0) return 0;

	found_mel = check_opmel_invas (pNPC, MAX_OPMEL, 0, pNPC->lIntEntDat);
	if (found_mel >= 0) 
	{
        if (pNPC->lEntDat - pNPC->lAufDat <= 2) return 1;
	}

	/* Leistung auf Behandlungsstation, Verlegung innerhalb eines Tages */

	if (pNPC->lEntDat - pNPC->lAufDat > 3) return 0;

	if (pNPC->abtindex-1 == pNPC->lBehandlungsAbtIndex)
	{

		found_diag = flagchecked (pNPC, NEONINTUEB, 1<<8, 0);
		if (found_diag < 0) return 0;

		if (check_matchingmel (pNPC, NEONINTUEB, 0, pNPC->lIntAufDat, pNPC->lIntEntDat + VERKETT_ADD) < 0) return 0;

		for (i = 0; i < pNPC->pAufenthalt->mel_anz; i++) {
		
			mel = pNPC->mels[i];
			if (mel>=0) {
				pMel = pNPC->pContext->pStamm2001->mel_array + mel;
				if ((pMel->flags & (NEONINTUEB<<INTBEGRMEL_SHIFT)) && (pMel->flags & INVASMEL)) {
					if (check_matchingmeldat (pNPC, i, pMel, (unsigned int) pNPC->pAufenthalt->lAufDat, pNPC->lAbtBehandlungEntdat + 1)) return 1;
				}
			}
		}
		return 0;
	}
	
	return 0;

}

static int npplaus_neonintueb10 (NPPLAUS_CONTEXT *pNPC)
{
	return npplaus_stdalterlst_check_mellist (pNPC, NEONINTUEB, 1<<9, pNPC->pStamm->ppMelIndexLists[MEL_NPPLAUS_PB5], pNPC->lIntAufDat, pNPC->lIntEntDat + VERKETT_ADD);
}

static int npplaus_neonintueb11 (NPPLAUS_CONTEXT *pNPC)
{
	return 0; /* entfaellt */
}

static int npplaus_neonintueb12 (NPPLAUS_CONTEXT *pNPC)
{
	if (pNPC->lAufDat + 1 == pNPC->lEntDat && pNPC->lAufDat == pNPC->pAufenthalt->lAufDat && check_matchingmel (pNPC, NEONINTUEB, 0, pNPC->lIntAufDat, pNPC->lIntEntDat + VERKETT_ADD)>-1) return 1;
	else return 0;
}

static NPPLAUS_CHECK_FUNCTION_TYPE funcArrayNeonIntUeb[] = 
	{npplaus_neonintueb1, npplaus_neonintueb2, npplaus_neonintueb3, npplaus_neonintueb4,
	 npplaus_neonintueb5, npplaus_neonintueb6, npplaus_neonintueb7, npplaus_neonintueb8,
	 npplaus_neonintueb9, npplaus_neonintueb10, npplaus_neonintueb11, npplaus_neonintueb12,
	 0};


/************************************************************************************************************
** Kriterien für Neonatologische Intensivbehandlung                                                      **
************************************************************************************************************/

static int npplaus_neonintbeh1 (NPPLAUS_CONTEXT *pNPC)
{
	return npplaus_stdalterlst_check (pNPC, NEONINTBEH, 1<<0);
}

static int npplaus_neonintbeh2 (NPPLAUS_CONTEXT *pNPC)
{
	return npplaus_stdalterlst_check (pNPC, NEONINTBEH, 1<<1);
}

static int npplaus_neonintbeh3 (NPPLAUS_CONTEXT *pNPC)
{
	int found;

	found = check_matchingmelfromlist (pNPC, pNPC->pStamm->ppMelIndexLists[MEL_NPPLAUS_IB3], pNPC->lIntAufDat, pNPC->lIntEntDat + VERKETT_ADD);
	if (found < 0) return 0;

	found = flagchecked (pNPC, NEONINTBEH, 1<<2, 0);
	if (found >= 0) return 1; /* Variante 1 */

	found = check_matchingmel (pNPC, NEONINTBEH << INTBEGRMEL_SHIFT, 0, pNPC->lIntAufDat, pNPC->lIntEntDat + VERKETT_ADD);
	if (found >= 0) return 1; /* Variante 2 */
	
	return 0;
	
	
}

static int npplaus_neonintbeh4 (NPPLAUS_CONTEXT *pNPC)
{
	int found_diag = -1, found_begrmel;

#ifdef NPPLAUSMODUS_MITMEL
	if (check_matchingmel (pNPC, NEONINTBEH, 0, pNPC->lIntAufDat, pNPC->lIntEntDat + VERKETT_ADD) < 0) return 0;
#endif

	found_begrmel = check_matchingmel (pNPC, NEONINTBEH << INTBEGRMEL_SHIFT, 0, (unsigned int) pNPC->pAufenthalt->lAufDat, pNPC->lIntEntDat+1);

	while (1) {
		found_diag = flagchecked (pNPC, NEONINTBEH, 1<<3, (unsigned int) (found_diag + 1));
		if (found_diag < 0) return 0;

		if (found_begrmel >= 0) return 1; /* Kriterium 4b */

		if (has_kombkz (pNPC, (unsigned int) found_diag, "KL")) {
			if (find_diag_kombkz (pNPC, "KLInt", (unsigned int) found_diag, 0, 0 /* NEONINTBEH, 1<<3 */) >= 0) return 1; /* Kriterium 4a_1 */
		}
		else {
			if (!has_kombkz (pNPC, (unsigned int) found_diag, "KLInt")) return 1; /* Kriterium 4a_2 */
		}
	}
	return 0;
}

static int npplaus_neonintbeh5 (NPPLAUS_CONTEXT *pNPC)
{
	return npplaus_stdalterlst_check (pNPC, NEONINTBEH, 1<<4);
}

static int npplaus_neonintbeh6 (NPPLAUS_CONTEXT *pNPC)
{
	return npplaus_stdalterlst_check (pNPC, NEONINTBEH, 1<<5);
}

static int npplaus_neonintbeh7 (NPPLAUS_CONTEXT *pNPC)
{
	static const char *kombkzarray[] = {"GI", "ExsInt", "Rsp", "RspInt", 0};
	const char *invkombkz;

	int found_diag, found_diag2;

#ifdef NPPLAUSMODUS_MITMEL
	if (check_matchingmel (pNPC, NEONINTBEH, 0, pNPC->lIntAufDat, pNPC->lIntEntDat + VERKETT_ADD) < 0) return 0;
#endif
	
	found_diag = -1;

	while (1) {
		found_diag = flagchecked (pNPC, NEONINTBEH, 1<<6, (unsigned int) (found_diag + 1));
		if (found_diag < 0) return 0;
	
		if (!has_kombkz_array (pNPC, (unsigned int) found_diag, kombkzarray)) return 1;
	
		invkombkz = 0;
		if (has_kombkz (pNPC, (unsigned int) found_diag, "GI")) invkombkz = "ExsInt";
		else if (has_kombkz (pNPC, (unsigned int) found_diag, "Rsp")) invkombkz = "RspInt";

		if (invkombkz) {
			found_diag2 = -1;
			do {
				found_diag2 = flagchecked (pNPC, 0, 0, (unsigned int) (found_diag2 + 1));
				if (found_diag2 >= 0 && has_kombkz (pNPC, (unsigned int) found_diag2, invkombkz)) return 1;
			} while (found_diag2 >= 0);
		}
	}
}

static int npplaus_neonintbeh8 (NPPLAUS_CONTEXT *pNPC)
{
	static const char *kombkzarray[] = {"SW", "GerInt", "KLInt", "LeInt", "RspInt", "ZNSInt", 0};
	static const char *invkombkzarray[] = {"GerInt", "KLInt", "LeInt", "RspInt", "ZNSInt", 0};
	int found_diag, found_diag2;

#ifdef NPPLAUSMODUS_MITMEL
	if (check_matchingmel (pNPC, NEONINTBEH, 0, pNPC->lIntAufDat, pNPC->lIntEntDat + VERKETT_ADD) < 0) return 0;
#endif

	found_diag = -1;

	while (1) {
		found_diag = flagchecked (pNPC, NEONINTBEH, 1<<7, (unsigned int) (found_diag + 1));
		if (found_diag < 0) return 0;
	
		if (!has_kombkz_array (pNPC, (unsigned int) found_diag, kombkzarray)) return 1;
	
		if (has_kombkz (pNPC, (unsigned int) found_diag, "SW")) {
			found_diag2 = -1;
			do {
				found_diag2 = flagchecked (pNPC, 0, 0, (unsigned int) (found_diag2 + 1));
				if (found_diag2 >= 0 && has_kombkz_array (pNPC, (unsigned int) found_diag2, invkombkzarray)) return 1;
			} while (found_diag2 >= 0);
		}
	}
		
	return 0;
}

static int npplaus_neonintbeh9 (NPPLAUS_CONTEXT *pNPC)
{
	return npplaus_stdalterlst_check (pNPC, NEONINTBEH, 1<<8);
}

static int npplaus_neonintbeh10 (NPPLAUS_CONTEXT *pNPC)
{
	if (flagchecked (pNPC, NEONINTBEH, 1<<9, 0) < 0) return 0;
	if (check_opmel_begr (pNPC, NEONINTBEH, MAX_OPMEL, (unsigned int) pNPC->pAufenthalt->lAufDat, pNPC->lIntEntDat-1)<0) return 0;

#ifdef NPPLAUSMODUS_MITMEL	
	if (check_matchingmel (pNPC, NEONINTBEH, 0, pNPC->lIntAufDat, pNPC->lIntEntDat+ VERKETT_ADD)<0) return 0;
#endif

	return 1;
}

static int npplaus_neonintbeh11 (NPPLAUS_CONTEXT *pNPC)
{
    return npplaus_stdalterlst_check_mellist (pNPC, NEONINTBEH, 1<<10, pNPC->pStamm->ppMelIndexLists[MEL_NPPLAUS_IB11], pNPC->lIntAufDat, pNPC->lIntEntDat + VERKETT_ADD);
}

static int npplaus_neonintbeh12 (NPPLAUS_CONTEXT *pNPC)
{
	return npplaus_stdalterlst_check_mel (pNPC, NEONINTBEH, 1<<11);
}

static int npplaus_neonintbeh13 (NPPLAUS_CONTEXT *pNPC)
{
	return npplaus_stdalterlst_check_mellist (pNPC, NEONINTBEH, 1<<12, pNPC->pStamm->ppMelIndexLists[MEL_NPPLAUS_IB13], 0, pNPC->lIntEntDat + VERKETT_ADD);
}

static int npplaus_neonintbeh14 (NPPLAUS_CONTEXT *pNPC)
{

	unsigned int i;

	if (pNPC->lEntDat - pNPC->lAufDat < 2 && pNPC->lEntDat < (unsigned int) pNPC->pAufenthalt->lAufDat + 2)
	{
        for (i = 0; i < pNPC->pAufenthalt->mel_anz; i++) {
            if (IsConstMEL (pNPC->pContext, CONSTMEL_ZZ020_7250, pNPC->mels[i])) {
                if ((int)pNPC->meldats[i] == pNPC->pAufenthalt->lAufDat) return 1;
            }
        }
	}
	return 0;
}

static NPPLAUS_CHECK_FUNCTION_TYPE funcArrayNeonIntBeh[] =
	{npplaus_neonintbeh1, npplaus_neonintbeh2, npplaus_neonintbeh3, npplaus_neonintbeh4,
	 npplaus_neonintbeh5, npplaus_neonintbeh6, npplaus_neonintbeh7, npplaus_neonintbeh8,
	 npplaus_neonintbeh9, npplaus_neonintbeh10, npplaus_neonintbeh11, npplaus_neonintbeh12,
	 npplaus_neonintbeh13, npplaus_neonintbeh14, 0};

/************************************************************************************************************
** Kriterien für Paediatrische Intensivueberwachung                                                      **
************************************************************************************************************/

static int npplaus_paedintueb1 (NPPLAUS_CONTEXT *pNPC)
{

	static const char *kombkzarray[] = {"Rsp", "RspInt", "Verbr", "VerbrInt", "ZNS", "ZNSInt", 0};

	int found = -1, melfound;
	unsigned int i;

#ifdef NPPLAUSMODUS_MITMEL
	melfound = check_matchingmel (pNPC, PAEDINTUEB, 0, pNPC->lIntAufDat, pNPC->lIntEntDat + VERKETT_ADD);
#else
	melfound = 0;
#endif

	if (melfound >= 0) {

		do {

			found = flagchecked (pNPC, PAEDINTUEB, 1,(unsigned int) (found + 1));
			if (found >= 0) {
				if (!has_kombkz_array (pNPC, (unsigned int) found, kombkzarray)) return 1; /* Variante 1a_1 */
				if (check_diag_invers_kombkz (pNPC, (unsigned int) found, "Rsp", "RspInt", 0, PAEDINTUEB, 1)) return 1; /* Variante 1a_2 */
				if (check_diag_invers_kombkz (pNPC, (unsigned int) found ,"Verbr", "VerbrInt", 0, PAEDINTUEB, 1)) return 1; /* Variante 1a_3 */
				if (check_diag_invers_kombkz (pNPC, (unsigned int) found, "ZNS", "ZNSInt", 0, PAEDINTUEB, 1)) return 1; /* Variante 1a_4 */
			}
			
		} while (found >= 0);
	}

	/* Ueberpruefe Variante 1b */
	for (i = 0; i < pNPC->max_diag && pNPC->ppDiag[i] == 0; i++) ;
	if (i < pNPC->max_diag) {
#ifdef NPPLAUSMODUS_MITMEL
		found = check_opmel_begr (pNPC, PAEDINTUEB, MAX_OPMEL, (unsigned int) pNPC->pAufenthalt->lAufDat, pNPC->lIntEntDat + 1);
		if (found < 0) return 0;
#endif

#ifndef NPPLAUSMODUS_MITMEL /* wenn definiert, wird das schon am Beginn gecheckt */
		found = check_matchingmel (pNPC, PAEDINTUEB, 0, pNPC->lIntAufDat, pNPC->lIntEntDat + VERKETT_ADD);
		if (found < 0) return 0;
#endif

		found = check_opmel_invas (pNPC, MAX_OPMEL, 0, pNPC->lIntEntDat + VERKETT_ADD);
		if (found >= 0) return 1;
	}


	return 0;
}

static int npplaus_paedintueb2 (NPPLAUS_CONTEXT *pNPC)
{
	unsigned int i, j;
	int flagdiag, mel;
	MEL_ARRAY_STRUC *pMel;
	const int *melarray = pNPC->pStamm->ppMelIndexLists[MEL_NPPLAUS_IB3];

	if (pNPC->lAbtBd > 3) return 0;

	flagdiag = flagchecked (pNPC, PAEDINTUEB, 1<<1, 0);
	if (flagdiag == -1) return 0;


	for (i = 0; i < pNPC->pAufenthalt->mel_anz; i++) {
		mel = pNPC->mels[i];
		if (mel >= 0) {
			for (j = 0; melarray[j] && melarray[j] != mel; j++) ;
			if (melarray[j]) {
				pMel = pNPC->pContext->pStamm2001->mel_array + mel;
				if (check_matchingmeldat (pNPC, i, pMel, (unsigned int) pNPC->pAufenthalt->lAufDat, pNPC->lAufDat)) return 1; 
			}
		}
	}
	return 0;
}

static int npplaus_paedintueb3 (NPPLAUS_CONTEXT *pNPC)
{
	return npplaus_stdalterlst_check (pNPC, PAEDINTUEB, 1<<2);
}

static int npplaus_paedintueb4 (NPPLAUS_CONTEXT *pNPC)
{
	int found = check_matchingmel (pNPC, PAEDINTUEB, 0, pNPC->lIntAufDat, pNPC->lIntEntDat + VERKETT_ADD);
	if (found < 0) return 0;

	if (check_opmel_invas(pNPC, MAX_OPMEL, (unsigned int) pNPC->pAufenthalt->lAufDat, pNPC->lIntEntDat + 1) >= 0) return 1; /* Kriterium 4a */
	if (flagchecked (pNPC, PAEDINTUEB, 1<<3, 0) < 0) return 0;
	if (check_opmel_begr (pNPC, PAEDINTUEB, MAX_OPMEL, (unsigned int) pNPC->pAufenthalt->lAufDat, pNPC->lIntEntDat + 1) >= 0) return 1; /* Kriterium 4b */
	return 0;
}

static int npplaus_paedintueb5 (NPPLAUS_CONTEXT *pNPC)
{
	return npplaus_stdalterlst_check_mellist (pNPC, PAEDINTUEB, 1<<4, pNPC->pStamm->ppMelIndexLists[MEL_NPPLAUS_PU5], 0, pNPC->lIntEntDat + VERKETT_ADD);
}

static int npplaus_paedintueb6 (NPPLAUS_CONTEXT *pNPC)
{
	return npplaus_stdalterlst_check_mel (pNPC, PAEDINTUEB, 1<<5);
}


static NPPLAUS_CHECK_FUNCTION_TYPE funcArrayPaedIntUeb[] =
	{npplaus_paedintueb1, npplaus_paedintueb2, npplaus_paedintueb3, npplaus_paedintueb4,
	 npplaus_paedintueb5, npplaus_paedintueb6, 0};


/************************************************************************************************************
** Kriterien für Paediatrische Intensivbehandlung                                                      **
************************************************************************************************************/

static int npplaus_paedintbeh1 (NPPLAUS_CONTEXT *pNPC)
{
	int found_diag = -1;
	static const char *kombkzarray[] = {"GI", "ExsInt", "KL", "KLInt", "Rsp", "RspInt", "SW", "Verbr", "VerbrInt", "Verg", "ZNSInt", 0};
	static const char *kombkzarrayV6[] = {"Verg", 0};
	static const char *kombkzarrayV6i[] = {"KLInt", "LeInt", "RspInt", "ZNSInt", 0};
	static const char *kombkzarrayV7[] = {"SW", 0};
	static const char *kombkzarrayV7i[] = {"GerInt", "KLInt", "LeInt", "RspInt", "ZNSInt", 0};

#ifdef NPPLAUSMODUS_MITMEL
	if (check_matchingmel (pNPC, PAEDINTBEH, 0, pNPC->lIntAufDat, pNPC->lIntEntDat + VERKETT_ADD) < 0) return 0;
#endif

	while (1) {

		found_diag = flagchecked (pNPC, PAEDINTBEH, 1<<0, (unsigned int) (found_diag + 1));
		if (found_diag == -1) return 0;

		if (!has_kombkz_array (pNPC, (unsigned int) found_diag, kombkzarray)) return 1;               /* Variante 1 */
		if (check_diag_invers_kombkz (pNPC, (unsigned int) found_diag, "GI", "ExsInt", 0, PAEDINTBEH, 1<<0)) return 1;  /* Variante 2 */
		if (check_diag_invers_kombkz (pNPC, (unsigned int) found_diag, "KL", "KLInt", 0, PAEDINTBEH, 1<<0)) return 1;   /* Variante 3 */
		if (check_diag_invers_kombkz (pNPC, (unsigned int) found_diag, "Rsp", "RspInt", 0, PAEDINTBEH, 1<<0)) return 1; /* Variante 4 */
		if (check_diag_invers_kombkz (pNPC, (unsigned int) found_diag, "Verbr", "VerbrInt", 0, PAEDINTBEH, 1<<0)) return 1; /* Variante 5 */
		if (check_diag_invers_kombkz_array (pNPC, (unsigned int) found_diag, kombkzarrayV6, kombkzarrayV6i, 0, PAEDINTBEH, 1<<0)) return 1; /* Variante 6 */
		if (check_diag_invers_kombkz_array (pNPC, (unsigned int) found_diag, kombkzarrayV7, kombkzarrayV7i, 0, PAEDINTBEH, 1<<0)) return 1; /* Variante 7 */
	}
}

static int npplaus_paedintbeh2 (NPPLAUS_CONTEXT *pNPC)
{
	int mel_found;

/*	if (pNPC->lAbtBd < 1) return 0; V10.0 */
	
	mel_found = check_matchingmelfromlist (pNPC, pNPC->pStamm->ppMelIndexLists[MEL_NPPLAUS_IB3], pNPC->lIntAufDat, pNPC->lIntEntDat + VERKETT_ADD);

	if (mel_found >= 0) {

		if (flagchecked (pNPC, PAEDINTBEH, 1<<1, 0)>=0) return 1;
		if (check_opmel_begr (pNPC, PAEDINTBEH, MAX_OPMEL, (unsigned int) pNPC->pAufenthalt->lAufDat, pNPC->lIntEntDat+1) >=0) return 1;
	}
	return 0;
}

static int npplaus_paedintbeh3 (NPPLAUS_CONTEXT *pNPC)
{
	return npplaus_stdalterlst_check (pNPC, PAEDINTBEH, 1<<2);
}

static int npplaus_paedintbeh4 (NPPLAUS_CONTEXT *pNPC)
{
	int found_diag, found_mel;
		
	if (check_matchingmelfromlist (pNPC, pNPC->pStamm->ppMelIndexLists[MEL_NPPLAUS_PB4], pNPC->lIntAufDat, pNPC->lIntEntDat + VERKETT_ADD) == -1) return 0;

	found_diag = flagchecked (pNPC, PAEDINTBEH, 1<<3, 0);

	if (found_diag >= 0) return 1; /* Krit 4_1*/

	found_mel = check_opmel_begr (pNPC, PAEDINTBEH, MAX_OPMEL, (unsigned int) pNPC->pAufenthalt->lAufDat, pNPC->lIntEntDat + 1);
	if (found_mel >= 0) return 1; /* Krit 4_2 */
	return 0;
}

static int npplaus_paedintbeh5 (NPPLAUS_CONTEXT *pNPC)
{
	int mel_found;
	
	mel_found = check_matchingmelfromlist (pNPC, pNPC->pStamm->ppMelIndexLists[MEL_NPPLAUS_PB5], pNPC->lIntAufDat, pNPC->lIntEntDat + VERKETT_ADD);

	if (mel_found >= 0) {

		if (flagchecked (pNPC, PAEDINTBEH, 1<<4, 0)>=0) return 1;
		if (check_opmel_begr (pNPC, PAEDINTBEH, MAX_OPMEL, 0, pNPC->lIntEntDat + 1) >=0) return 1;
	}
	return 0;
}

static int npplaus_paedintbeh6 (NPPLAUS_CONTEXT *pNPC)
{
	int found_mel, found_diag;
	static const char *kombkzarray[] = {"GerInt", "KLInt", "LeInt", "RspInt", "ZNSInt", 0};
	found_diag = -1;

	while (1) {

		found_diag = flagchecked (pNPC, PAEDINTBEH, 1<<5, (unsigned int) (found_diag + 1));
		if (found_diag == -1) return 0;

		found_mel = check_matchingmel (pNPC, PAEDINTBEH, 0, pNPC->lIntAufDat, pNPC->lIntEntDat + VERKETT_ADD);

		if (found_mel >= 0) {
			if (has_kombkz (pNPC, (unsigned int) found_diag, "SW")) {
				/* Krit 6_1 */
				if (find_diag_kombkz_array (pNPC, kombkzarray, (unsigned int) found_diag, 0, 0, 0) >= 0) return 1;
			}
			else return 1; /* Krit 6_2 */

			/* Krit 6_3 */
			if (check_opmel_begr (pNPC, PAEDINTBEH, MAX_OPMEL, (unsigned int) pNPC->pAufenthalt->lAufDat, pNPC->lIntEntDat+1) >= 0) return 1;
		}

	}
	return 0;	
}

static NPPLAUS_CHECK_FUNCTION_TYPE funcArrayPaedIntBeh[] =
	{npplaus_paedintbeh1, npplaus_paedintbeh2, npplaus_paedintbeh3, npplaus_paedintbeh4,
	 npplaus_paedintbeh5, npplaus_paedintbeh6, 0};


/************************************************************************************************************
** Besondere Kriterien                                                                                     **
************************************************************************************************************/


static int npplaus_fnp_besond (NPPLAUS_CONTEXT *pNPC)
{
	char cEntart = pNPC->pAufenthalt->ENTART;

	if (pNPC->abtindex + 1 < pNPC->pAufenthalt->abt_anz) return 0; /* nur auf Entlassungsabteilung */

	if (cEntart == 'T' || cEntart == 'S') return 1;
	return 0;
}

static int npplaus_fnp_7299 (NPPLAUS_CONTEXT *pNPC)
{
	return 0;
}

static NPPLAUS_CHECK_FUNCTION_TYPE funcArrayBesond[] = {npplaus_fnp_besond, 0};
static NPPLAUS_CHECK_FUNCTION_TYPE funcArray7299[] = {npplaus_fnp_7299, 0};

/************************************************************************************************************
** function lkf_npplaus_check_area: Überprüft einen Bereich des NP-Plaus                                   **
************************************************************************************************************/

static int lkf_npplaus_check_area (NPPLAUS_CONTEXT *pNPC, const NPPLAUS_CHECK_FUNCTION_TYPE *pFuncArray, unsigned int *counter, unsigned int krittype, unsigned nKritOffset)
{
	unsigned int flagIndex;
	int ret;
	int nTraceDebug;
	char sTraceLine[1024];
	int match;
	const char *sKritPrefix;

	flagIndex = 0;
	match = 0;

	nTraceDebug = LKF_IS_TRACE_DETAIL (pNPC->nTraceAufenthalt);

	switch (krittype)
	{
		case NEONINTUEB:
			if (nTraceDebug) sprintf (sTraceLine, "NPPLAUS-NU-Check (neonat. Ueberwachung)");
			sKritPrefix = "NU";
			break;
		case NEONINTBEH:
			if (nTraceDebug) sprintf (sTraceLine, "NPPLAUS-NB-Check (neonat. Behandlung)");
			sKritPrefix = "NB";
			break;
		case PAEDINTUEB:
			if (nTraceDebug) sprintf (sTraceLine, "NPPLAUS-PU-Check (paediatrische Ueberwachung)");
			sKritPrefix = "PU";
			break;
		case PAEDINTBEH:
			if (nTraceDebug) sprintf (sTraceLine, "NPPLAUS-PB-Check (paediatrische Behandlung)");
			sKritPrefix = "PB";
			break;
		case FNP_BESOND:
			if (nTraceDebug) sprintf (sTraceLine, "NPPLAUS-NB-Check (besondere Kriterien)");
			sKritPrefix = "FB";
			break;
		case FNP_7299:
			if (nTraceDebug) sprintf (sTraceLine, "NPPLAUS-FN-Check (MEL-7299-Check)");
			sKritPrefix = "FN";
			break;
		default:
			if (nTraceDebug) sprintf (sTraceLine, "NPPLAUS - unbekannter Check ???");
			sKritPrefix = "??";
			break;
	}
	if (nTraceDebug)
		TRACE_DETAIL (pNPC->pAufenthalt, pNPC->abtindex, sTraceLine);

	while (pFuncArray[flagIndex] != 0) {
	
		sprintf (pNPC->sTracePrefix, "%s%02d", sKritPrefix, flagIndex+1);

		ret = pFuncArray[flagIndex](pNPC); 
	
		if ((krittype != NEONINTBEH && krittype != NEONINTUEB) || pNPC->is_neonat) {
			if (ret) counter[flagIndex]++;
		}

		if (ret)
		{
			pNPC->pCurrentAbtStat->pKritCount[flagIndex + nKritOffset]++;
		
			if (nTraceDebug)
			{
				sprintf (sTraceLine, "    Kriterium %s%d getroffen", sKritPrefix, flagIndex+1);
				TRACE_DETAIL (pNPC->pAufenthalt, pNPC->abtindex, sTraceLine);
			}
		}
		flagIndex++;
		DEBUG_NPPLAUS (pNPC->ABTIDENT, krittype, flagIndex, ret);
		
		if (ret) match = ret; /* alle Kriterien checken */
	}

	if (!match && nTraceDebug)
	{
		sprintf (sTraceLine, "    keine %s-Treffer", sKritPrefix);
		TRACE_DETAIL (pNPC->pAufenthalt, pNPC->abtindex, sTraceLine);
	}

	return match; /* nicht getroffen */
}


/****************************************************************************************************************************************
** lkf_npplaus_check_abt: Überprüft die NP-Plaus-Kriterien für eine Abteilung                                                          **
****************************************************************************************************************************************/

static int lkf_npplaus_check_abt (NPPLAUS_CONTEXT *pNPC)
{
	int ret = 0;
	

    if (lkf_npplaus_check_area (pNPC, funcArrayNeonIntBeh, pNPC->c_ni, NEONINTBEH,  0))
    {
        if (pNPC->is_neonat || pNPC->pContext->modelljahr < 2006) ret |= NEONINTBEH; /* Treffer gilt nur, wenn neonatus, sonst nur fuer Statistik */
    }
    if (lkf_npplaus_check_area (pNPC, funcArrayNeonIntUeb, pNPC->c_nu, NEONINTUEB, 14))
    {
        if (pNPC->is_neonat || pNPC->pContext->modelljahr < 2006) ret |= NEONINTUEB;
    }

	if (lkf_npplaus_check_area (pNPC, funcArrayPaedIntBeh, pNPC->c_pi, PAEDINTBEH, 26)) ret |= PAEDINTBEH;
	if (lkf_npplaus_check_area (pNPC, funcArrayPaedIntUeb, pNPC->c_pu, PAEDINTUEB, 32)) ret |= PAEDINTUEB;
	
	if (lkf_npplaus_check_area (pNPC, funcArrayBesond,    pNPC->c_s1,  FNP_BESOND, 38))   ret |= FNP_BESOND;
	if (lkf_npplaus_check_area (pNPC, funcArray7299,      pNPC->c_s2,  FNP_7299, 39)) ret |= FNP_7299;

	return ret;
}

/*******************************************************************************************
** Function npplaus_get_warn_info: Ermittelt die Grob-Ursache für eine NPPlaus-Warning    **
*******************************************************************************************/

static NPPLAUS_REASON 
	Reason_IntDg =		 {"TFDG1", "Kein Krit. getr., aber Intensiv-DG vorhanden!", 0},
	Reason_NoIntDg =	 {"TFDG2", "Kein Krit. getr., KEINE Intensiv-DG vorhanden!", 1},
	Reason_KombIntDg =	 {"TFDG3", "Kein Krit. getr., nur Intensiv-DG mit Komb-KZ vorhanden!", 2},
	Reason_IntMel =		 {"TFML1", "Kein Krit. getr., aber Intensiv-MEL mit plausiblem Datum vorhanden!", 3},
	Reason_NoIntMel =	 {"TFML2", "Kein Krit. getr., KEINE Intensiv-Leistung vorhanden!", 4},
	Reason_IntMelNoDat = {"TFML3", "Kein Krit. getr., Intensiv-MEL ohne plausibles Datum vorhanden!", 5},
	Reason_IntBegrMel =	 {"TFIM1", "Kein Krit. getr., aber IntBegrMel vorhanden!", 6},
    Reason_NoIntBegrMel ={"TFIM2", "Kein Krit. getr., KEINE IntBegrMel vorhanden", 7};

static NPPLAUS_REASON *ppReasons[] =
	{&Reason_IntDg, &Reason_NoIntDg, &Reason_KombIntDg, &Reason_IntMel, &Reason_NoIntMel,
        &Reason_IntMelNoDat, &Reason_IntBegrMel, &Reason_NoIntBegrMel};

static NPPLAUS_ANALYSIS *lkf_npplaus_alloc_analysis (LKF_CONTEXT *pContext, unsigned int nCount)
{
	NPPLAUS_ANALYSIS *pNew = (NPPLAUS_ANALYSIS *) LKF_MALLOC (pContext, "lkf_npplaus_alloc_analysis", sizeof (NPPLAUS_ANALYSIS));
    if (!pNew) return 0;
    
	pNew->nAlloc = nCount;
	pNew->nCount = 0;
    pNew->pContext = pContext;
	
	if (nCount > 0)
	{
		pNew->ppReason = (const NPPLAUS_REASON **) LKF_CALLOC (pContext, "lkf_npplaus_alloc_analysis.reason", nCount, sizeof (const NPPLAUS_REASON *));
        if (!pNew->ppReason) {
            LKF_FREE(pContext, "lkf_npplaus_alloc_analysis", pNew);
            return 0;
        }
		pNew->pHint = (NPPLAUS_HINT *) LKF_CALLOC (pContext, "lkf_npplaus_alloc_analysis.hint", sizeof (NPPLAUS_HINT), nCount);
        if (!pNew->pHint) {
            LKF_FREE(pContext, "lkf_npplaus_alloc_analysis.reason", pNew->ppReason);
            LKF_FREE(pContext, "lkf_npplaus_alloc_analysis", pNew);
            return 0;
        }
	}
	else
	{
		pNew->ppReason = 0;
		pNew->pHint = 0;
	}
	return pNew;
}

static int lkf_npplaus_analysis_add (NPPLAUS_CONTEXT *pNPC, NPPLAUS_WARN_STRUC *pWarn, const NPPLAUS_REASON *pReason, const char *sHint)
{ /* V10.1 */
	unsigned int i;
	NPPLAUS_ANALYSIS *pAnalysis;
    LKF_CONTEXT *pContext;
    pContext = pNPC->pContext;
    if (!pWarn->pWarningAnalysis) {
        pAnalysis = pWarn->pWarningAnalysis = lkf_npplaus_alloc_analysis (pContext, 5);
        return LKF_OUTOFMEMORY_ERROR;
    }
	else {
		pAnalysis = pWarn->pWarningAnalysis;
		for (i = 0; i < pAnalysis->nCount; i++)
		{
			if (pAnalysis->ppReason[i] == pReason && !strncmp (pAnalysis->pHint[i], sHint, sizeof (NPPLAUS_HINT)-1))
				return 0;
		}

		if (pAnalysis->nAlloc == pAnalysis->nCount)
		{
            const NPPLAUS_REASON **ppOldReason = pAnalysis->ppReason;
            NPPLAUS_HINT *pOldHints = pAnalysis->pHint;

			ppOldReason = pAnalysis->ppReason;
			pOldHints = pAnalysis->pHint;
			
			pAnalysis->nAlloc += 5;
			pAnalysis->ppReason = LKF_CALLOC (pContext, "lkf_npplaus_analysis_add.reason", pAnalysis->nAlloc, sizeof (const NPPLAUS_REASON *));
            if (!pAnalysis->ppReason) {
                LKF_FREE(pContext, "lkf_npplaus_analysis_add.reason", ppOldReason);
                LKF_FREE(pContext, "lkf_npplaus_analysis_add.hint", pOldHints);
                return LKF_OUTOFMEMORY_ERROR;
            }
			pAnalysis->pHint = LKF_CALLOC (pContext, "lkf_npplaus_analysis_add.hint", pAnalysis->nAlloc, sizeof (NPPLAUS_HINT));
            if (!pAnalysis->pHint) {
                LKF_FREE(pContext, "lkf_npplaus_analysis_add.reason", ppOldReason);
                LKF_FREE(pContext, "lkf_npplaus_analysis_add.hint", pOldHints);
                return LKF_OUTOFMEMORY_ERROR;
            }
			memcpy ((void *) pAnalysis->ppReason, ppOldReason, sizeof (const NPPLAUS_REASON *) * pAnalysis->nCount);
			memcpy (pAnalysis->pHint, pOldHints, sizeof (NPPLAUS_HINT) * pAnalysis->nCount);
			LKF_FREE (pContext, "lkf_npplaus_analysis_add.reason", (void *) ppOldReason);
			LKF_FREE (pContext, "lkf_npplaus_analysis_add.hint", pOldHints);
		}
		else
			pAnalysis = pWarn->pWarningAnalysis;
	}
	pAnalysis->ppReason[pAnalysis->nCount] = pReason;
	strncpy (pAnalysis->pHint[pAnalysis->nCount], sHint, sizeof (NPPLAUS_HINT));
	pAnalysis->pHint[pAnalysis->nCount++][sizeof(NPPLAUS_HINT)-1] = 0;

	pNPC->pCurrentAbtStat->pTFCounter[pReason->ReasonNr]++;
    return 0;
}

static void lkf_npplaus_free_analysis (NPPLAUS_ANALYSIS *pNPPlausAnalysis)
{
    LKF_CONTEXT *pContext = pNPPlausAnalysis->pContext;
	if (pNPPlausAnalysis->ppReason)
	{
		LKF_FREE (pContext, "lkf_npplaus_free_analysis.reason", (void *) pNPPlausAnalysis->ppReason);
		LKF_FREE (pContext, "lkf_npplaus_free_analysis.hint", pNPPlausAnalysis->pHint);
	}
	LKF_FREE (pContext, "lkf_npplaus_free_analysis", pNPPlausAnalysis);
}

static void npplaus_get_warn_reason (NPPLAUS_CONTEXT *pNPC, NPPLAUS_WARN_STRUC *pWarning)
{
	unsigned int lMelDat, i;
	int bHasDiag, bHasKombDiag, nIntMel, nIntBegrMel;
	MEL_ARRAY_STRUC *pMel;

	bHasDiag = 0;
	bHasKombDiag = 0;
	nIntMel = 0;
	nIntBegrMel = 0;

	for (i = 0; i < pNPC->max_diag; i++)
	{
		if (pNPC->ppDiag[i])
		{
			if (pNPC->ppDiag[i]->KOMBKZ[0])
				bHasKombDiag = 1;
			else
				bHasDiag = 1;
		}
	}

	if (bHasDiag)
		lkf_npplaus_analysis_add (pNPC, pWarning, &Reason_IntDg, "");
	else if (bHasKombDiag)
		lkf_npplaus_analysis_add (pNPC, pWarning, &Reason_KombIntDg, "");
	else
		lkf_npplaus_analysis_add (pNPC, pWarning, &Reason_NoIntDg, "");

	for (i = 0; i < pNPC->pAufenthalt->mel_anz; i++)
	{
		if (pNPC->mels[i] >= 0)
		{
			pMel = pNPC->pContext->pStamm2001->mel_array + pNPC->mels[i];
			lMelDat = (unsigned int) lkf_dat2int (pNPC->pAufenthalt->mel[i].MELDAT);

			if (nIntMel < 2 && (pMel->flags & 255))
			{
				if (nIntMel < 2)
				{
					if (lMelDat >= pNPC->lIntAufDat && lMelDat <= pNPC->lIntEntDat)
						nIntMel = 2;
				}
				else
					nIntMel = 1;
			}
			if (pMel->flags & (255<<8))
				nIntBegrMel = 1;
		}
	}

	switch (nIntMel)
	{
		case 2:
			lkf_npplaus_analysis_add (pNPC, pWarning, &Reason_IntMel, "");
			break;
		case 1:
			lkf_npplaus_analysis_add (pNPC, pWarning, &Reason_IntMelNoDat, "");
			break;
		default:
			lkf_npplaus_analysis_add (pNPC, pWarning, &Reason_NoIntMel, "");
			break;
	}

	if (nIntBegrMel)
		lkf_npplaus_analysis_add (pNPC, pWarning, &Reason_IntBegrMel, "");
	else	
		lkf_npplaus_analysis_add (pNPC, pWarning, &Reason_NoIntBegrMel, "");
}

static void npplaus_get_warn_info (NPPLAUS_CONTEXT *pNPC, NPPLAUS_WARN_STRUC *pWarning)
{
	char sIntAufDatBuf[12], sIntEntDatBuf[12];

	sprintf  (pWarning->sInfo, "%s      ; AddWochen: %2d; Alter: T:%5d W:%4d; AbtBD: %3d; AbtTyp: %s; Verkettung: %s - %s",
		pNPC->is_neonat ? "NEO ": "PAED", 
		(pNPC->lNeonatologieLimit-28)/7, 
		pNPC->lAlterTage, pNPC->lAlterTage / 7,
		pNPC->lAbtBd,
		pNPC->abt_type == 1 ? "UEB" : "BEH",
		FormatDate8 (pNPC->sIntAufDat, sIntAufDatBuf),
		FormatDate8 (pNPC->sIntEntDat, sIntEntDatBuf));

	npplaus_get_warn_reason (pNPC, pWarning);
}

/*******************************************************************************************
** Funktion lkf_NPPlaus_Check: Führt die Plausibilitäts-Überprüfung durch.                **
**                             (Aufruf von lkf_plaus)                                     **
*******************************************************************************************/

static unsigned int diag_neonatologie_limit_2024 (const char *diag)
{ /* V2024.0 */
    if (memcmp (diag, "301.", 4)) {
        return 0;
    }
    
    if (diag[4] == '2') {
        if (diag[5] < '1' || diag[5] > '9') {
            return 0;
        }
        return (('9' - diag[5]) + 15) * 7;
    }
    if (diag[4] == '3') {
        if (diag[5] < '0' || diag[5] > '9') {
            return 0;
        }
        return (('9' - diag[5]) + 5) * 7;
    }
    return 0;
}

static unsigned int diag_neonatologie_limit_2014 (const char *diag)
{
	if (!memcmp (diag, "P07.2", 5) || !memcmp (diag, "P07.0", 5)) return 21 * 7;
	else if (!memcmp (diag, "P07.1", 5) || !memcmp (diag, "P07.3", 5)) {
		switch (diag[5]) {
			case '0': return 16 * 7;
			case '1': return 14 * 7;
			case '2': return 11 * 7;
			 default: return  0;
		}
	}
	return 0;
}

_SCORING_EXPORT unsigned int lkf_test_get_neonatologie_limit (const char *diag, unsigned int modelljahr) {
    if (modelljahr < 2024) {
        return diag_neonatologie_limit_2014(diag);
    }
    return diag_neonatologie_limit_2024(diag);
}


int lkf_setNeonatologie (LKF_AUFENTHALT *pAufenthalt, unsigned int nAbtIndex) {
    LKF_AUFENTHALT_ABT *pAbt = pAufenthalt->abt + nAbtIndex;
    pAbt->ISNEONAT = (((long)pAbt->lAbtDat - pAufenthalt->lGebDat) > 28) ? 'N' : 'J';
    return pAbt->ISNEONAT == 'J';
}


static unsigned int diag_neonatologie_limit (const char *diag)
{
	if (!memcmp (diag, "P07.2", 5)) return 21 * 7;
	else if (!memcmp (diag, "P07.3", 5)) {
		switch (diag[5]) {
			case '0': return 16 * 7;
			case '1': return 14 * 7;
			case '2': return 11 * 7;
			 default: return  0;
		}
	}
	return 0;
}

static int npplaus_warn (NPPLAUS_CONTEXT *pNPC, unsigned int warncode, unsigned int abt)
{

	if (warncode != NPPLAUS_7299 && warncode != NPPLAUS_MELOHNEDAT)
	{
		NPPLAUS_WARN_STRUC *pWarn;
		if (pNPC->nWarningAlloc == pNPC->nWarningCount) {
			NPPLAUS_WARN_STRUC *pOld = pNPC->pWarnings;
			pNPC->nWarningAlloc += NPPLAUS_WARN_ALLOC_EXTEND;
			pNPC->pWarnings = (NPPLAUS_WARN_STRUC *) LKF_CALLOC(pNPC->pContext, "npplaus_warn", pNPC->nWarningAlloc, sizeof(NPPLAUS_WARN_STRUC));
            if (!pNPC->pWarnings) {
                if (pOld) LKF_FREE(pNPC->pContext, "npplaus_warn", pOld);
                return LKF_OUTOFMEMORY_ERROR;
            }
			if (pOld) {
				if (pNPC->nWarningCount) memcpy (pNPC->pWarnings, pOld, sizeof(NPPLAUS_WARN_STRUC) * pNPC->nWarningCount);
				LKF_FREE (pNPC->pContext, "npplaus_warn", pOld);
			}
		}

		pWarn = pNPC->pWarnings + pNPC->nWarningCount++;

		pWarn->nAbtIndex = abt;
		pWarn->nWarningCode = warncode;
		pWarn->pAufenthalt = pNPC->pAufenthalt;
		pWarn->sInfo[0] = 0;
		pWarn->pWarningAnalysis = 0;
		npplaus_get_warn_info (pNPC, pWarn);
	}

	Satzart_ReportMBDSError (pNPC->pAufenthalt, lkf_getPlausNPWarningErrorDef ((int) warncode), abt);
    return 0;
}

int lkf_NPPlaus_Init (LKF_CONTEXT *pContext)
{
	if (pContext->flags & LKFCONTEXT_NPPLAUS) {
	
#ifdef NPPLAUS_DEFAULT_DEBUG
		if (pContext->sNPPlausTraceFilename[0] == 0) strcpy (pContext->sNPPlausTraceFilename, "c:\\npplaus.csv");
#endif

		if (pContext->sNPPlausTraceFilename[0] != 0) {
			FILE *fp = fopen (pContext->sNPPlausTraceFilename, "w");
			if (fp) fprintf (fp, "KANR     ; AUFZAHL    ; ABTFC    ; ABTPOS ; CODE ; KOMMENTAR\n");
			if (pContext->npplaus_tracefile) fclose (pContext->npplaus_tracefile);
			pContext->npplaus_tracefile = fp;
		}	

		if (pContext->pNPPlausContext) {
			lkf_free_npplaus_context (pContext->pNPPlausContext);
			pContext->pNPPlausContext = 0;
		}
	}
	return 0;
}

static char *lkf_npplaus_getAufIdent (LKF_AUFENTHALT *pAufenthalt, int abtindex, char *buf)
{
    if (SAFEIS2017ORLATER(pAufenthalt)) {
        if (abtindex < 0)
            sprintf (buf, "%4.4s     ; %12.12s ;          ;        ;", pAufenthalt->KANR, pAufenthalt->PATID);
        else
            sprintf (buf, "%4.4s     ; %12.12s ; %8.8s ; %3.3s    ;", pAufenthalt->KANR, pAufenthalt->PATID, pAufenthalt->abt[abtindex].ABTFC, pAufenthalt->abt[abtindex].ABTPOS);
    }
    else {
        if (abtindex < 0)
            sprintf (buf, "%4.4s     ; %10.10s ;          ;        ;", pAufenthalt->KANR, pAufenthalt->PATID);
        else
            sprintf (buf, "%4.4s     ; %10.10s ; %8.8s ; %2.2s     ;", pAufenthalt->KANR, pAufenthalt->PATID, pAufenthalt->abt[abtindex].ABTFC, pAufenthalt->abt[abtindex].ABTPOS);
    }
	return buf;
}

_SCORING_EXPORT unsigned int lkf_npplaus_getProtokollHeadline (LKF_CONTEXT *pContext, char *buf, unsigned int maxlen)
{
	unsigned int len;
	char *pHeadline = "KANR     ; AUFZAHL    ; ABTFC    ; ABTPOS ; CODE ; KOMMENTAR";
	len = (unsigned int) strlen (pHeadline);
	strncpy (buf, pHeadline, maxlen);
	return len;
}

_SCORING_EXPORT unsigned int lkf_npplaus_getProtokollLineCount (LKF_CONTEXT *pContext)
{
	if (pContext->pNPPlausContext)
		 return pContext->pNPPlausContext->nProtokollCount;
	else return 0;
}

_SCORING_EXPORT unsigned int lkf_npplaus_getWarningLineCount (LKF_CONTEXT *pContext)
{
	if (pContext->pNPPlausContext) 
		 return pContext->pNPPlausContext->nWarningCount;
	else return 0;
}

_SCORING_EXPORT unsigned int lkf_npplaus_getWarningInfo (LKF_CONTEXT *pContext, unsigned int i, char *buf, unsigned int maxlen)
{ /* Ausführliche Information zur aufgetretenen NP-Plaus-Warning */
	if (pContext->pNPPlausContext && i < pContext->pNPPlausContext->nWarningCount) 
	{
		NPPLAUS_WARN_STRUC *pWarn = pContext->pNPPlausContext->pWarnings + i;
		unsigned int len;
		char lbuf[512];
		char aufident[64];

		sprintf (lbuf, "%s;    ;%s", lkf_npplaus_getAufIdent (pWarn->pAufenthalt, (int) pWarn->nAbtIndex, aufident), pWarn->sInfo);

		len = (unsigned int) strlen (lbuf);
		strncpy (buf, lbuf, maxlen);
		return len;
	}
	else return 0;
}

_SCORING_EXPORT unsigned int lkf_npplaus_getInfoLine (LKF_CONTEXT *pContext, unsigned int i, char *buf, unsigned int maxlen)
{
	if (pContext->pNPPlausContext && i < pContext->pNPPlausContext->nWarningCount) 
	{
		NPPLAUS_WARN_STRUC *pWarn = pContext->pNPPlausContext->pWarnings + i;
		unsigned int len;
		char lbuf[512];
		char aufident[64];

		if (pWarn->sInfo[0])
			sprintf (lbuf, "%s INFO ; %s", lkf_npplaus_getAufIdent (pWarn->pAufenthalt, (int) pWarn->nAbtIndex, aufident), pWarn->sInfo);
		else
			lbuf[0] = 0;
		len = (unsigned int) strlen (lbuf);
		strncpy (buf, lbuf, maxlen);
		return len;
	}
	else return 0;
}

_SCORING_EXPORT unsigned int lkf_npplaus_getReasonCount (LKF_CONTEXT *pContext, unsigned int i)
{
	if (pContext->pNPPlausContext && i < pContext->pNPPlausContext->nWarningCount) 
	{
		NPPLAUS_WARN_STRUC *pWarn = pContext->pNPPlausContext->pWarnings + i;
		if (pWarn->pWarningAnalysis)
			return pWarn->pWarningAnalysis->nCount;
		else
			return 0;
	}
	return 0;
}

_SCORING_EXPORT unsigned int lkf_npplaus_getReasonLine (LKF_CONTEXT *pContext, unsigned int i, unsigned int j, char *buf, unsigned int maxlen)
{
	if (pContext->pNPPlausContext && i < pContext->pNPPlausContext->nWarningCount) 
	{
		NPPLAUS_WARN_STRUC *pWarn = pContext->pNPPlausContext->pWarnings + i;
		unsigned int len;
		char lbuf[512];
		char aufident[64];

		if (!pWarn->pWarningAnalysis || pWarn->pWarningAnalysis->nCount < j)
		{
			if (maxlen > 0) *buf = 0;
			return 0;
		}

		sprintf (lbuf, "%s %5.5s; %s", lkf_npplaus_getAufIdent (pWarn->pAufenthalt, (int) pWarn->nAbtIndex, aufident), pWarn->pWarningAnalysis->ppReason[j]->ReasonCode, pWarn->pWarningAnalysis->ppReason[j]->ReasonText);

		len = (unsigned int) strlen (lbuf);
		strncpy (buf, lbuf, maxlen);
		return len;
	}
	else return 0;
}

_SCORING_EXPORT unsigned int lkf_npplaus_getWarningLine (LKF_CONTEXT *pContext, unsigned int i, char *buf, unsigned int maxlen)
{
	if (pContext->pNPPlausContext && i < pContext->pNPPlausContext->nWarningCount) 
	{
		NPPLAUS_WARN_STRUC *pWarn = pContext->pNPPlausContext->pWarnings + i;
		unsigned int len;
		char lbuf[512];
		char aufident[64];

        const LKF_SATZART_ERRORDEF *pErrorDef = lkf_getPlausNPWarningErrorDef ((int) pWarn->nWarningCode);
        int nAbtIndex;
        if (pWarn->nWarningCode == NPPLAUS_MELOHNEDAT)
            nAbtIndex = -1;
        else
            nAbtIndex = (int) pWarn->nAbtIndex;
        
        
        if (pErrorDef)
        {
            char code[6];
            char errorTextBuf[256];
            lkf_getErrorIdent (pContext, pErrorDef, 6, code);
            sprintf (lbuf, "%s %4.4s ; %s", lkf_npplaus_getAufIdent (pWarn->pAufenthalt, nAbtIndex, aufident), code, lkf_context_formatted_text (pContext, pErrorDef->sText, errorTextBuf));
        }
        else
            sprintf (lbuf, "%s %4.4d ; %s", lkf_npplaus_getAufIdent (pWarn->pAufenthalt, nAbtIndex, aufident), pWarn->nWarningCode, lkf_plaus_WarningCode2Text (pContext, (int) pWarn->nWarningCode));
		len = (unsigned int) strlen (lbuf);
		strncpy (buf, lbuf, maxlen);
		return len;
	}
	else return 0;
}

_SCORING_EXPORT unsigned int lkf_npplaus_getProtokollLine (LKF_CONTEXT *pContext, unsigned int i, char *buf, unsigned int maxlen)
{
	if (pContext->pNPPlausContext && i < pContext->pNPPlausContext->nProtokollCount) 
	{
		unsigned int len;
		char lbuf[512];
		char typetext[10];
		const char *beschreibung;
		char aufident[64];
		NPPLAUS_PROTOKOLL *pProt = pContext->pNPPlausContext->pProtokoll + i;
		
		switch (pProt->nKritType) {
		
			case NEONINTBEH:
					sprintf (typetext, "NB%02d", pProt->nKritNr);
					beschreibung = NeonIntBehTexts[pProt->nKritNr - 1];
					break;
			case NEONINTUEB:
					sprintf (typetext, "NU%02d", pProt->nKritNr);
					beschreibung = NeonIntUebTexts[pProt->nKritNr - 1];
					break;
			case PAEDINTBEH:
					sprintf (typetext, "PB%02d", pProt->nKritNr);
					beschreibung = PaedIntBehTexts[pProt->nKritNr - 1];
					break;
			case PAEDINTUEB:
					sprintf (typetext, "PU%02d", pProt->nKritNr);
					beschreibung = PaedIntUebTexts[pProt->nKritNr - 1];
					break;
			case FNP_BESOND:
					strcpy (typetext, "SK01");
					beschreibung = SpecTexts[1];
					break;
			case FNP_7299:
					strcpy (typetext, "SK02");
					beschreibung = SpecTexts[0];
					break;
			default:
					strcpy (typetext, "undef.");
					beschreibung = ""; /* V18.0 */
					break;
		}

		sprintf (lbuf, "%s %4.4s ; %s", lkf_npplaus_getAufIdent (pProt->pAufenthalt, (int) pProt->nAbtIndex, aufident), typetext, beschreibung);

		len = (unsigned int) strlen (lbuf);
		strncpy (buf, lbuf, maxlen);
		return len;
	}
	else return 0;
}


int lkf_NPPlaus_End (LKF_CONTEXT *pContext)
{
	if (pContext->flags & LKFCONTEXT_NPPLAUS) {

		if (pContext->npplaus_tracefile) {
			fclose (pContext->npplaus_tracefile);
			pContext->npplaus_tracefile = 0;
		}
	}
	return 0;
}


static NPPLAUS_ABTSTAT *GetAbtStatStructure (NPPLAUS_CONTEXT *pNPContext, const char *sAbtFC, const char *sEinstufung)
{ /* V10.0 */
	int nCmp, nMin, nMax, nMedian;
	NPPLAUS_ABTSTAT *pAbtStat;
    LKF_CONTEXT *pContext;
    
    pContext = pNPContext->pContext;
	nMin = -1;
	nMax = (int) pNPContext->nAbtStatCount;
	while (nMin + 1 < nMax)
	{
		nMedian = (nMin + nMax)>>1;
		nCmp = memcmp (pNPContext->pAbtStat[nMedian].sAbtFC, sAbtFC, 8);
		if (nCmp == 0) return pNPContext->pAbtStat + nMedian;
		else if (nCmp > 0) nMax = nMedian;
		else nMin = nMedian;
	}

	if (pNPContext->nAbtStatAlloc == pNPContext->nAbtStatCount)
	{
		NPPLAUS_ABTSTAT *pOld = pNPContext->pAbtStat;
		pNPContext->nAbtStatAlloc += NPPLAUS_ABTSTAT_ALLOC_EXTEND;
		pNPContext->pAbtStat = (NPPLAUS_ABTSTAT *) LKF_CALLOC (pContext, "GetAbtStatStructure", pNPContext->nAbtStatAlloc, sizeof (NPPLAUS_ABTSTAT));
        if (!pNPContext->pAbtStat) return 0;
		if (nMax > 0)
			memcpy (pNPContext->pAbtStat, pOld, sizeof (NPPLAUS_ABTSTAT) * (unsigned int) nMax);
		if (nMax < (int) pNPContext->nAbtStatCount)
			memcpy (pNPContext->pAbtStat + nMax + 1, pOld + nMax, sizeof (NPPLAUS_ABTSTAT) * (pNPContext->nAbtStatCount - (unsigned int) nMax));
		LKF_FREE (pContext, "GetAbtStatStructure", pOld);
	}
	else if (nMax < (int) pNPContext->nAbtStatCount)
		memmove (pNPContext->pAbtStat + nMax + 1, pNPContext->pAbtStat + nMax, sizeof (NPPLAUS_ABTSTAT) * (pNPContext->nAbtStatCount - (unsigned int) nMax));
	
	pAbtStat = pNPContext->pAbtStat + nMax;
	memset (pAbtStat, 0, sizeof (NPPLAUS_ABTSTAT));
	memcpy (pAbtStat->sAbtFC, sAbtFC, 8);
	memcpy (pAbtStat->sEinstufung, sEinstufung, 2);
	pNPContext->nAbtStatCount++;
	return pAbtStat;
}

extern const LKF_SATZART_ERRORDEF LKFErrorNPPlausMELOhneDatum;

int lkf_NPPlaus_Check (LKF_CONTEXT *pContext, LKF_AUFENTHALT *pAufenthalt)
{
	const NPPLAUS_STRUC **ppDiags;
	unsigned int i, j, neonatologie_limit, act;
	int ret, *abt_type, abt_count;
	char tmp_spez_list[20];
	int abtok; /* V10.0 */
	NPPLAUS_ABTSTAT *pAbtStat; /* V10.0 */
	const SPEZ_LIST_STRING *pSpezListString;

	NPPLAUS_CONTEXT *pNPC;
	char sTraceLine[1024];
    
	if (!pContext->pNPPlausContext) {
		pContext->pNPPlausContext = lkf_alloc_npplaus_context (pContext);
	}
	pNPC = pContext->pNPPlausContext;

	/* Überprüfung, ob Neon / Paed / Ueb / Beh */
	abt_count = 0;

	abt_type = LKF_CALLOC (pContext, "lkf_NPPlaus_Check", pAufenthalt->abt_anz, sizeof (int));
    if (!abt_type) {
        return LKF_OUTOFMEMORY_ERROR;
    }
	for (i = 0; i < pAufenthalt->abt_anz; i++) {
	
		abt_type[i] = 0;
		sprintf (tmp_spez_list, ".....%4.4s%8.8s", pAufenthalt->KANR, pAufenthalt->abt[i].ABTFC);
		pSpezListString = SpezInArray (pContext, tmp_spez_list);
	
		if (pSpezListString && !ABTFC_Spez_Check (pAufenthalt, (int) i, pSpezListString, 0)) pSpezListString = 0;

		if (pSpezListString && (*pSpezListString)[0]=='I' && (*pSpezListString)[27]=='K') {
		
			switch ((*pSpezListString)[28]) { 
				case '0': abt_type[i] = ABTTYPE_UEBERWACHUNG; break;
				case '1': abt_type[i] = ABTTYPE_BEHANDLUNG; break;
				default:  break;
			}
		}	
		if (abt_type[i] > 0) abt_count++;

		if (LKF_IS_TRACE_DETAIL (pContext->nTraceAufenthalt))
		{
			if (abt_type[i])
			{
				sprintf (sTraceLine, "NPPLAUS; Spez; Suchstring = '%s', gefunden = '%.*s' -> %s",
						 tmp_spez_list, (int) sizeof (SPEZ_LIST_STRING), (const char *) pSpezListString, 
						 (abt_type[i] == ABTTYPE_UEBERWACHUNG) ? "UEBERWACHUNG" : "BEHANDLUNG");

			}
			else if (pSpezListString)
			{
				sprintf (sTraceLine, "NPPLAUS; Spez; Suchstring = '%s', gefunden = '%.*s' -> keine NP-Abteilung",
						tmp_spez_list, (int) sizeof (SPEZ_LIST_STRING), (const char *) pSpezListString);
			}
			else
				sprintf (sTraceLine, "NPPLAUS: Spez; Suchstring = '%s', nicht gefunden", tmp_spez_list);
			TRACE_DETAIL (pAufenthalt, i, sTraceLine);
		}
	}

    if (!abt_count) {
        LKF_FREE (pContext, "lkf_NPPlaus_Check", abt_type);
        return 0; /* keine NP-Intensivabteilung, daher kein NP-Plaus-Check */
    }
    
    neonatologie_limit = 4 * 7;

    ppDiags = (const NPPLAUS_STRUC **) LKF_CALLOC (pContext, "lkf_NPPlaus_Check.diag", pAufenthalt->diag_anz, sizeof (NPPLAUS_STRUC *));
    if (!ppDiags) return LKF_OUTOFMEMORY_ERROR;
    
	for (i = 0; i < pAufenthalt->diag_anz; i++) {
		ppDiags[i] = lkf_find_npplaus (pContext->pStamm2001, pAufenthalt->diag[i].DIAG);

        if (pContext->modelljahr >= 2024) {
            act = diag_neonatologie_limit_2024 (pAufenthalt->diag[i].DIAG);
        }
        else if (pContext->modelljahr >= 2014) {
            act = diag_neonatologie_limit_2014 (pAufenthalt->diag[i].DIAG);
        }
        else {
            act = diag_neonatologie_limit (pAufenthalt->diag[i].DIAG);
        }
		if (act > neonatologie_limit) neonatologie_limit = act;
	}

	/*	neonatologie_limit += 6; V10.0: entfällt, V11.0: wieder dazu */

	if (LKF_IS_TRACE_DETAIL (pContext->nTraceAufenthalt))
	{
		for (i = 0; i < pAufenthalt->diag_anz; i++)
		{
			if (ppDiags[i])
			{
				if (i)
				{
					sprintf (sTraceLine, "ZD#%03d ist NP-Diagnose: %6.6s", i-1, ppDiags[i]->DIAG);
				}
				else
				{
					sprintf (sTraceLine, "HD     ist NP-Diagnose: %6.6s", ppDiags[i]->DIAG);
				}
				TRACE_DETAIL(pAufenthalt, -1, sTraceLine);
			}
		}
	}

	ret = 0;

    /* Erzeugen des NPPlaus-Context */
	pNPC->pAufenthalt = pAufenthalt;
	pNPC->pContext = pContext;
	pNPC->pStamm = pContext->pStamm2001;
	pNPC->ppDiag = ppDiags;
    pNPC->max_diag = pAufenthalt->diag_anz;
	pNPC->lNeonatologieLimit = neonatologie_limit;
	pNPC->lGebDat = (unsigned int) lkf_dat2int (pAufenthalt->GEBDAT);
	pNPC->lAbtBehandlungEntdat = 0;
	pNPC->lBehandlungsAbtIndex = 999999;
	pNPC->lIntAufDat = 0;

	pNPC->nTraceAufenthalt = pContext->nTraceAufenthalt; /* V11.0 */

	pNPC->pTraceFile = pContext->npplaus_tracefile;

	if (pAufenthalt->mel_anz) {
		pNPC->mels = LKF_CALLOC (pContext, "lkf_NPPlaus_Check.mel", pAufenthalt->mel_anz, sizeof (int));
        if (!pNPC->mels) return LKF_OUTOFMEMORY_ERROR;
        pNPC->meldats = LKF_CALLOC (pContext, "lkf_NPPlaus_Check.meldats", pAufenthalt->mel_anz, sizeof (unsigned int));
        if (!pNPC->meldats) return LKF_OUTOFMEMORY_ERROR;
		pNPC->pMelOhneDat = LKF_CALLOC (pContext, "lkf_NPPlaus_Check.melOhneDat", pAufenthalt->mel_anz, sizeof (int));
        if (!pNPC->pMelOhneDat) return LKF_OUTOFMEMORY_ERROR;
        
        for (i = 0; i < pAufenthalt->mel_anz; i++)
        {
            pNPC->mels[i] = FindMelIndexStamm (pNPC->pStamm, pAufenthalt->mel[i].MEL);
            pNPC->meldats[i] = (unsigned int) lkf_dat2int (pAufenthalt->mel[i].MELDAT);
        }
	}
	else pNPC->mels = 0;
 
	pNPC->lIntAufDat = 0;

	/* Überprüfe für jede Abteilung, welche Kriterien erfuellt sind */
	for (i = 0; i < pAufenthalt->abt_anz; i++) {
		if (abt_type[i]) {

			/* Verkettung ermitteln (Ermittlung von Beginn und Ende des Intensiv-Aufenthalts) */
			if (pNPC->lIntAufDat == 0) {
				pNPC->lIntAufDat = (unsigned int) lkf_dat2int (pAufenthalt->abt[i].ABTDAT);
				memcpy (pNPC->sIntAufDat, pAufenthalt->abt[i].ABTDAT, 8);
				for (j = i; j < pAufenthalt->abt_anz && abt_type[j]; j++) ;

				if (j < pAufenthalt->abt_anz)
				{
					pNPC->lIntEntDat = (unsigned int) lkf_dat2int (pAufenthalt->abt[j].ABTDAT);
					memcpy (pNPC->sIntEntDat, pAufenthalt->abt[j].ABTDAT, 8);
				}
				else
				{
					pNPC->lIntEntDat = (unsigned int) lkf_dat2int (pAufenthalt->ENTDAT);			
					memcpy (pNPC->sIntEntDat, pAufenthalt->ENTDAT, 8);
				}
			}

			pNPC->abt_type = abt_type[i];
			pNPC->abtindex = i;
			pNPC->lAufDat = (unsigned int) lkf_dat2int (pAufenthalt->abt[i].ABTDAT);
/*			if (!npplaus_context.lIntAufDat) {
				npplaus_context.lIntAufDat = npplaus_context.lAufDat;
				
				for (j = i + 1; j < pAufenthalt->abt_anz && abt_type[j]; j++) ;
				npplaus_context.lIntEntDat = lkf_dat2int ((j < pAufenthalt->abt_anz) ? pAufenthalt->abt[j].ABTDAT : pAufenthalt->ENTDAT);

			}
*/			pNPC->lEntDat = (unsigned int) (lkf_dat2int ((i + 1 < pAufenthalt->abt_anz) ? pAufenthalt->abt[i+1].ABTDAT : pAufenthalt->ENTDAT));
			pNPC->lAbtBd = pNPC->lEntDat - pNPC->lAufDat;
            
            if (pNPC->pContext->isBM && pNPC->pContext->modelljahr >= 2015) {
                pNPC->is_neonat = pAufenthalt->abt[i].ISNEONAT == 'J';
                pNPC->lAlterTage = pNPC->is_neonat ? 7 : 35;
            }
            else {
                pNPC->lAlterTage = pNPC->lAufDat - pNPC->lGebDat;
                pNPC->is_neonat = (pNPC->lAlterTage <= pNPC->lNeonatologieLimit) ? 1 : 0;
            }
            
			if (abt_type[i] == ABTTYPE_BEHANDLUNG) 
			{
				pNPC->lAbtBehandlungEntdat = pNPC->lEntDat;
				pNPC->lBehandlungsAbtIndex = i;
			}

            if (pNPC->pContext->modelljahr >= 2017) {
                sprintf (pNPC->ABTIDENT, "%4.4s;%12.12s;%8.8s;%02d", pAufenthalt->KANR, pAufenthalt->PATID, pAufenthalt->abt[i].ABTFC, i + 1);
                            }
            else {
                sprintf (pNPC->ABTIDENT, "%4.4s;%10.10s;%8.8s;%02d", pAufenthalt->KANR, pAufenthalt->PATID, pAufenthalt->abt[i].ABTFC, i + 1);
            }
            
			
			if (pAufenthalt->ENTART != 'V' && (pNPC->lEntDat > pNPC->lAufDat || ((strchr ("ST", pAufenthalt->ENTART)||pAufenthalt->ENTART == LKF_ENTART_REVERS) && i+1 == pAufenthalt->abt_anz)))
			{ /* V9.4: ENTART ungleich V; lEntDat / lAufDat statt lIntEntDat / lIntAufDat */
			  /* V9.4: keine WM0W mehr in diesen Fällen */
			
				
				pAbtStat = GetAbtStatStructure (pNPC, pAufenthalt->abt[i].ABTFC, (abt_type[i] == ABTTYPE_UEBERWACHUNG) ? "K0" : "K1");
				pNPC->pCurrentAbtStat = pAbtStat;
				
				ret = lkf_npplaus_check_abt (pNPC);
				abtok = 0; /* V10.0 */
				 
				if (ret == 0) npplaus_warn (pNPC, NPPLAUS_WARNING, i);
				else if (!(ret & FNP_BESOND)) {

					if (pNPC->is_neonat)
					{ /* (pContext->modelljahr >= 2006 && pNPC->is_neonat) */
						if (abt_type[i] == ABTTYPE_BEHANDLUNG) {
							if (!(ret & (NEONINTBEH | PAEDINTBEH))) {
							/*	if (ret & FNP_7299) npplaus_warn (&npplaus_context, NPPLAUS_7299, i);
								else */
								npplaus_warn (pNPC, NPPLAUS_NUR_UEB, i);
							}
							else abtok = 1;
						}
						else abtok = 1;
					}
					else if (pNPC->pAufenthalt->Alter <= 170) 
					{
						if (abt_type[i] == ABTTYPE_UEBERWACHUNG) {
							if (!(ret & (PAEDINTUEB | PAEDINTBEH))) {
								/* if (ret & FNP_7299) npplaus_warn (&npplaus_context, NPPLAUS_7299, i); 
								else */
								npplaus_warn (pNPC, NPPLAUS_NUR_NEON, i);
							}
							else abtok = 1;
						}
						else { /* Behandlung */
							if (!(ret & PAEDINTBEH)) {
								/* if (ret & FNP_7299) npplaus_warn (&npplaus_context, NPPLAUS_7299, i);
								else */
								if (ret & PAEDINTUEB) npplaus_warn (pNPC, NPPLAUS_NUR_UEB, i);
								else npplaus_warn (pNPC, NPPLAUS_NUR_NEON, i);
							
							}
							else abtok = 1;
						}
					}
					else {  /* Ur-alt */
						/* if (ret & FNP_7299) npplaus_warn (&npplaus_context, NPPLAUS_7299, i); 
						else */
						npplaus_warn (pNPC, NPPLAUS_WARNING, i);
					}
				}
				else
					abtok = 1;
				if (ret & FNP_7299) 
				{
					npplaus_warn (pNPC, NPPLAUS_7299, i);
					/* abtok = 0; */
				}

				pAbtStat->nZugang++;
				pAbtStat->nBDGesamt += pNPC->lAbtBd;
				if (abtok)
				{
					pAbtStat->nTreffer++;
					pAbtStat->nBDTreffer += pNPC->lAbtBd;
				}
				else
				{
					pAbtStat->nNichtTreffer++;
					pAbtStat->nBDNichtTreffer += pNPC->lAbtBd;
				}
			}
			else ret = 0;

		}
		else pNPC->lIntAufDat = 0;
	}

	if (pNPC->mels) 
	{
		if (pContext->modelljahr >= 2006)
		{ /* V10.0 */
			for (i = 0; i < pAufenthalt->mel_anz; i++)
			{
				if (pNPC->pMelOhneDat[i])
				{
	/*				Satzart_ReportMBDSError (pAufenthalt, &LKFErrorNPPlausMELOhneDatum, i); */
					npplaus_warn (pNPC, NPPLAUS_MELOHNEDAT, i);
				}
			}
		}
		LKF_FREE (pContext, "lkf_NPPlaus_Check", (void *) pNPC->mels);
		LKF_FREE (pContext, "lkf_NPPlaus_Check", (void *) pNPC->meldats);
		LKF_FREE (pContext, "lkf_NPPlaus_Check", (void *) pNPC->pMelOhneDat); /* V10.0 */
	}

	LKF_FREE (pContext, "lkf_NPPlaus_Check", (void*)ppDiags);
	LKF_FREE (pContext, "lkf_NPPlaus_Check", abt_type);

	return ret;
}

static const char *copystring (char *sBuf, unsigned int lBufLen, const char *sSource)
{
	strncpy (sBuf, sSource, lBufLen);
	if (lBufLen <= strlen (sSource))
		sBuf[lBufLen-1] = 0;
	return sBuf;
}

_SCORING_EXPORT const char *lkf_npplaus_sum_headline (LKF_CONTEXT *pContext, char *sBuf, unsigned int lBufLen)
{ /* V10.0 */
	if (pContext->pNPPlausContext)
	{
		return copystring (sBuf, lBufLen, "KANR     ; ABTFC    ; STUFE    ;   ZUGANG ;  TREFFER ; NOTREFFER ;  QUOTE% ; BELAGSD. ; BD-TREFF ; BD-NGETR ");
	}
	else
	{
		return 0;
	}
}

_SCORING_EXPORT unsigned int lkf_npplaus_sum_abtcount (LKF_CONTEXT *pContext)
{ /* V10.0 */
	if (pContext->pNPPlausContext)
		return pContext->pNPPlausContext->nAbtStatCount;
	else
		return 0;
}

_SCORING_EXPORT const char *lkf_npplaus_sum_abtline (LKF_CONTEXT *pContext, unsigned int lLineIndex, char *sBuf, unsigned int lBufLen)
{
	if (pContext->pNPPlausContext && lLineIndex < pContext->pNPPlausContext->nAbtStatCount)
	{
		char sLocalBuf[256];
		int nQuote;

		NPPLAUS_ABTSTAT *pAbtStat = pContext->pNPPlausContext->pAbtStat + lLineIndex;
		
		if (pAbtStat->nZugang)
			nQuote = (pAbtStat->nTreffer * 1000 + pAbtStat->nZugang/2) / pAbtStat->nZugang;
		else
			nQuote = 0;

		sprintf (sLocalBuf, "%4.4s     ; %8.8s ; %2.2s       ; %8d ; %8d ;  %8d ;   %3d,%1d ; %8d ; %8d ; %8d",
				 pContext->KANR, pAbtStat->sAbtFC, pAbtStat->sEinstufung,
				 pAbtStat->nZugang, pAbtStat->nTreffer, pAbtStat->nNichtTreffer, nQuote / 10, nQuote % 10,
				 pAbtStat->nBDGesamt, pAbtStat->nBDTreffer, pAbtStat->nBDNichtTreffer);
		return copystring (sBuf, lBufLen, sLocalBuf);
	}
	else
		return 0;
}

NPPLAUS_CONTEXT *lkf_alloc_npplaus_context (LKF_CONTEXT *pContext)
{
	NPPLAUS_CONTEXT *pNPC = (NPPLAUS_CONTEXT *) LKF_MALLOC (pContext, "lkf_alloc_npplaus_context", sizeof (NPPLAUS_CONTEXT));
    if (!pNPC) return 0;
	memset (pNPC, 0, sizeof (NPPLAUS_CONTEXT));

	pNPC->nWarningAlloc = NPPLAUS_WARN_ALLOC_INITIAL;
	pNPC->nProtokollAlloc = NPPLAUS_PROTOKOLL_ALLOC_INITIAL;

	pNPC->pProtokoll = (NPPLAUS_PROTOKOLL *) LKF_CALLOC (pContext, "lkf_alloc_npplaus_context", pNPC->nProtokollAlloc, sizeof (NPPLAUS_PROTOKOLL));
    if (!pNPC->pProtokoll) {
        LKF_FREE(pContext, "lkf_alloc_npplaus_context", pNPC);
        return 0;
    }
	pNPC->pWarnings = (NPPLAUS_WARN_STRUC *) LKF_CALLOC (pContext, "lkf_alloc_npplaus_context", pNPC->nWarningAlloc, sizeof (NPPLAUS_WARN_STRUC));
    if (!pNPC->pWarnings) {
        LKF_FREE(pContext, "lkf_alloc_npplaus_context", pNPC->pProtokoll);
        LKF_FREE(pContext, "lkf_alloc_npplaus_context", pNPC);
        return 0;
    }

	pNPC->bEnableProtokoll = 1;

	/* V10.0 */
	pNPC->nAbtStatAlloc = NPPLAUS_ABTSTAT_ALLOC_INITIAL;
	pNPC->pAbtStat = (NPPLAUS_ABTSTAT *) LKF_CALLOC (pContext, "lkf_alloc_npplaus_context.abtstat", pNPC->nAbtStatAlloc, sizeof (NPPLAUS_ABTSTAT));

	return pNPC;

}

void lkf_free_npplaus_context (NPPLAUS_CONTEXT *pNPC)
{
	unsigned int i;
    LKF_CONTEXT *pContext;
    
    pContext = pNPC->pContext;
    
	LKF_FREE (pContext, "lkf_free_npplaus_context", pNPC->pProtokoll);

	for (i = 0; i < pNPC->nWarningCount; i++)
	{ /* V10.1 */
		if (pNPC->pWarnings[i].pWarningAnalysis)
			lkf_npplaus_free_analysis (pNPC->pWarnings[i].pWarningAnalysis);
	}

	LKF_FREE (pContext, "lkf_free_npplaus_context", pNPC->pWarnings);
	LKF_FREE (pContext, "lkf_free_npplaus_context", pNPC->pAbtStat);
	LKF_FREE (pContext, "lkf_free_npplaus_context", pNPC);
}

int lkf_reset_npplaus_context_package (NPPLAUS_CONTEXT *pNPC) {
    
    unsigned int i;
    LKF_CONTEXT *pContext;
    
    pContext = pNPC->pContext;
    
    LKF_FREE (pContext, "lkf_reset_npplaus_context_package", pNPC->pProtokoll);
    
    for (i = 0; i < pNPC->nWarningCount; i++)
    {
        if (pNPC->pWarnings[i].pWarningAnalysis)
            lkf_npplaus_free_analysis (pNPC->pWarnings[i].pWarningAnalysis);
    }
    
    LKF_FREE (pContext, "lkf_reset_npplaus_context_package", pNPC->pWarnings);
    
    pNPC->nWarningAlloc = NPPLAUS_WARN_ALLOC_INITIAL;
    pNPC->nProtokollAlloc = NPPLAUS_PROTOKOLL_ALLOC_INITIAL;
    pNPC->nWarningCount = 0;
    pNPC->nProtokollCount = 0;
    
    pNPC->pProtokoll = (NPPLAUS_PROTOKOLL *) LKF_CALLOC (pContext, "lkf_reset_npplaus_context_package.prot", pNPC->nProtokollAlloc, sizeof (NPPLAUS_PROTOKOLL));
    if (!pNPC->pProtokoll) {
        pNPC->pWarnings = 0;
        return LKF_OUTOFMEMORY_ERROR;
    }
    
    pNPC->pWarnings = (NPPLAUS_WARN_STRUC *) LKF_CALLOC (pContext, "lkf_reset_npplaus_context_package.warn", pNPC->nWarningAlloc, sizeof (NPPLAUS_WARN_STRUC));
    if (!pNPC->pWarnings) return LKF_OUTOFMEMORY_ERROR;
    return 0;
}

/*********************************************************************
** Funktion lkf_set_npplaus_tracefilename: Setzt den Ausgabepfad    **
**  (für Trace-Informationen, wenn eingeschaltet.                   **
*********************************************************************/

_SCORING_EXPORT void lkf_set_npplaus_tracefilename (LKF_CONTEXT *pContext, const char *outputpath)
{
	char buf[512];
	unsigned int i, count;
	FILE *fp;

	fp = fopen (outputpath, "w");

	lkf_npplaus_getProtokollHeadline (pContext, buf, 512);
	fprintf (fp, "%s\n", buf);
			
	count = lkf_npplaus_getWarningLineCount (pContext);
	for (i = 0; i < count; i++) {
		lkf_npplaus_getWarningLine (pContext, i, buf, 512);
		fprintf (fp, "%s\n", buf);
	}

	count = lkf_npplaus_getProtokollLineCount (pContext);
	for (i = 0; i < count; i++) {
		lkf_npplaus_getProtokollLine (pContext, i, buf, 512);
		fprintf (fp, "%s\n", buf);
	}
	fclose (fp);
}

_SCORING_EXPORT unsigned int lkf_npplaus_tfsum_headline (LKF_CONTEXT *pContext, char *sBuf, unsigned int lBufLen)
{ /* V10.1 */
	int i;
	char sHeadline[1024];
	unsigned int nPos;
	strcpy (sHeadline, "KANR     ; ABTFC    ; STUFE    ;   ZUGANG ;  NOTREFFER ");
	nPos = (unsigned int) strlen (sHeadline);

	for (i = 0; i < NPPLAUS_TF_COUNT; i++)
	{
		nPos += (unsigned int) sprintf (sHeadline + nPos, ";%6.6s ", ppReasons[i]->ReasonCode);
	}

	strncpy (sBuf, sHeadline, lBufLen);
	sBuf[lBufLen-1] = 0;
	return (unsigned int) strlen (sHeadline);

}

_SCORING_EXPORT unsigned int lkf_npplaus_critsum_headline (LKF_CONTEXT *pContext, char *sBuf, unsigned int lBufLen)
{ /* V10.1 */
	char sHeadline[1024];

	strcpy (sHeadline, "KANR     ; ABTFC    ; STUFE    ;   ZUGANG ;  NB01 ;  NB02 ;  NB03 ;  NB04 ;  NB05 ;  NB06 ;  NB07 ;  NB08 ;  NB09 ;  NB10 ;  NB11 ;  NB12 ;  NB13 ;  NB14 ;  NU01 ;  NU02 ;  NU03 ;  NU04 ;  NU05 ;  NU06 ;  NU07 ;  NU08 ;  NU09 ;  NU10 ;  NU12 ;  PB01 ;  PB02 ;  PB03 ;  PB04 ;  PB05  ; PB06 ;  PU01 ;  PU02 ;  PU03 ;  PU04 ;  PU05  ; PU06 ;  SK01");

	strncpy (sBuf, sHeadline, lBufLen);
	sBuf[lBufLen-1] = 0;
	return (unsigned int) strlen (sHeadline);

}

_SCORING_EXPORT unsigned int lkf_npplaus_tfsum (LKF_CONTEXT *pContext, unsigned int i, char *sBuf, unsigned int lBufLen)
{
	char sInternalBuf[1024];
	unsigned int nBufLen;
	unsigned int j;

	if (pContext->pNPPlausContext && pContext->pNPPlausContext->nAbtStatCount > i)
	{
		NPPLAUS_ABTSTAT *pAbtStat = pContext->pNPPlausContext->pAbtStat + i;
		nBufLen = (unsigned int) sprintf (sInternalBuf, "%-6.6s   ; %8.8s ; %2.2s       ; %8d ;   %8d ", pContext->KANR, pAbtStat->sAbtFC, pAbtStat->sEinstufung, pAbtStat->nZugang, pAbtStat->nNichtTreffer);

		for (j = 0; j < NPPLAUS_TF_COUNT ;j++)
		{
			nBufLen += (unsigned int) sprintf (sInternalBuf + nBufLen, ";%6d ", pAbtStat->pTFCounter[j]);
		}
	}		
	else
		sInternalBuf[0] = 0;


	strncpy (sBuf, sInternalBuf, lBufLen);
	sBuf[lBufLen-1] = 0;
	return (unsigned int) strlen (sInternalBuf);
}

_SCORING_EXPORT unsigned int lkf_npplaus_critsum (LKF_CONTEXT *pContext, unsigned int i, char *sBuf, unsigned int lBufLen)
{ /* V10.1 */
	char sInternalBuf[1024];
	unsigned int nBufLen;
	unsigned int j;
	if (pContext->pNPPlausContext && pContext->pNPPlausContext->nAbtStatCount > i)
	{
		NPPLAUS_ABTSTAT *pAbtStat = pContext->pNPPlausContext->pAbtStat + i;
		nBufLen = (unsigned int) sprintf (sInternalBuf, "%-6.6s   ; %8.8s ; %2.2s       ; %8d ", pContext->KANR, pAbtStat->sAbtFC, pAbtStat->sEinstufung, pAbtStat->nZugang);

		for (j = 0; j < NPPLAUS_KRIT_COUNT ; j++)
		{
			if (j == 24 || j == 39)
				continue; /* kein Kriterium NU11, ignoriere SK02 */

			nBufLen += (unsigned int) sprintf (sInternalBuf + nBufLen, ";%6d ", pAbtStat->pKritCount[j]);
		}

	}
	else
		sInternalBuf[0] = 0;

	strncpy (sBuf, sInternalBuf, lBufLen);
	sBuf[lBufLen-1] = 0;
	return (unsigned int) strlen (sInternalBuf);
}
