// (C) Copyright 1992 Jim Patterson

#import <appkit/appkit.h>
#import <objc/objc.h>
#import "PerformanceEvaluator.h"
#import "GameView.h"

@implementation PerformanceEvaluator
+ new
{
	int i;
	self = [super new];
	for (i=0; i<128; i++)
		keyInfo[i] = (keyStatType *) malloc(sizeof(keyStatType));
	[self reset];
	return self;
} 

- setKeyColumn:anObject { keyColumn = anObject; return self; }
- setRelColumn:anObject {relColumn = anObject; return self; }
- setAbsColumn:anObject {absColumn = anObject; return self;}
- setSuggText:anObject { suggText = anObject; return self; }
- setPerformanceEvaluatorWindow:anObject {performanceEvaluatorWindow = anObject; return self; }
- tellGameCompleted:(BOOL) wasCompleted {gameCompleted = (int) wasCompleted; return self; }
- logOccurrence: (char) aChar		// tell evaluator that one more aChar is in game
{
	keyInfo[(int) aChar]->numInGame++;
	return self;
}

- logKeyMiss: (char) aChar	// tell evaluator that one more aChar was missed
{
	keyInfo[(int) aChar]->numMissed++;
	return self;
}

- reset	// erase all existing statistics
{
	int i;

	missedCount = 0;
	for (i=0; i<128; i++)	{
		keyInfo[i]->key = (char) i;
		keyInfo[i]->numMissed = 0;
		keyInfo[i]->numInGame = 0;
		keyInfo[i]->relFreq = 0.0;
		keyInfo[i]->absFreq = 0.0;
		*(keyInfo[i]->relFreqBuff) = '\0';
		*(keyInfo[i]->absFreqBuff) = '\0';
		}
	for (i=0; i<6; i++)
		largest[i] = keyInfo[i];
	missedCount = 0;
	gameCompleted = NO;
	[performanceEvaluatorWindow setDocEdited:YES];
	return self;	
}



- flush
{
	int i,j;
	char ch[2];

	ch[1] = '\0';
	for (i=0; i<6; i++)
		if (largest[i]->numMissed>0)
			 {
			ch[0] = largest[i]->key; 
			[[keyColumn cellAt:i:0] setStringValue:ch];
			[[relColumn cellAt:i:0] setStringValue:largest[i]->relFreqBuff];
			[[absColumn cellAt:i:0] setStringValue:largest[i]->absFreqBuff];
			}
		else {
			[[keyColumn cellAt:i:0] setStringValue:""];
			[[relColumn cellAt:i:0] setStringValue:""];
			[[absColumn cellAt:i:0] setStringValue:""];
			}
	return self;
}
			

- summarize
{
	int i,totalMistakes;

	// compute total number of mistakes	
	totalMistakes = 0;
	for (i=33; i<128; i++) totalMistakes += keyInfo[i]->numMissed;
	for (i=33; i<128; i++)
		if (keyInfo[i]->numMissed >0) {
			keyInfo[i]->relFreq = ((float) keyInfo[i]->numMissed) / ((float) totalMistakes);
			keyInfo[i]->absFreq = ((float) keyInfo[i]->numMissed)/ ((float) keyInfo[i]->numInGame);
			if (keyInfo[i]->numMissed>=keyInfo[i]->numInGame)
				sprintf(keyInfo[i]->relFreqBuff,"%4.1f%%",0.0);
			else sprintf(keyInfo[i]->relFreqBuff,"%4.1f%%",(1-keyInfo[i]->absFreq) * 100.0);	
			sprintf(keyInfo[i]->absFreqBuff,"%d of %d",keyInfo[i]->numMissed, keyInfo[i]->numInGame);
			}
	if ((gameCompleted) && (totalMistakes < 5))	
		[suggText setStringValue:
			"You did very well!  You should move on to the next lesson or play this lesson again, but faster."];
	else if (gameCompleted)
		[suggText setStringValue:
			"You were fast but not accurate.  Customize a lesson to practice your weak keys."];
	else [suggText setStringValue:
			"\nYou did not finish.  You should play again at a slower speed."];
	return self;
}

- debugDump
{
	int i,dummy;
	printf("======== SUMMARY ========\n");
	for (i=33; i<128; i++) {
		if (keyInfo[i]->numMissed >0)
			printf("%c::    missed: %d of %d    relFreq:|%s|(%4.1f)    absFreq:|%s|(%4.1f)\n",  
				keyInfo[i]->key,
				keyInfo[i]->numMissed,
				keyInfo[i]->numInGame,
				keyInfo[i]->relFreqBuff,keyInfo[i]->relFreq,
				keyInfo[i]->absFreqBuff,keyInfo[i]->absFreq);
		}
	printf("===========================\n");
				
	return self;
}
	

- sortKeyInfo	// partial (6 largest only) selection sort of keyInfo[] by absFreq
{
	int i,j,max;
	keyStatType *temp,*copy[128];

	for (i=0; i<128; i++) 
		copy[i] = keyInfo[i];	
	for (i=0; i<6; i++) {
		max = i;
		for (j=i+1; j<128; j++)
			if (copy[j]->absFreq > copy[max]->absFreq)
				 max = j;
		largest[i] = copy[max];
		temp = copy[max]; copy[max] = copy[i]; copy[i] = temp;
		}
	return self;
}
				
- free
{
	int i;
	for (i=0; i<128; i++)
		free(keyInfo[i]);
	[super free];
	return self;
} 
			 
- readInfo:(NXTypedStream *) tstream
{
	int i;

	for (i=0; i<6; i++) {
		NXReadTypes(tstream,"{ciiff}",
			&(largest[i]->key),
			&(largest[i]->numMissed),&(largest[i]->numInGame),
			&(largest[i]->relFreq),&(largest[i]->absFreq));
		NXReadArray(tstream, "c", 20,largest[i]->relFreqBuff);
		NXReadArray(tstream, "c", 20, largest[i]->absFreqBuff);
		}
	NXReadTypes(tstream,"ii",&missedCount,&gameCompleted);
	[performanceEvaluatorWindow setDocEdited:NO];
	[self flush];
	return self;
}

- writeInfo:(NXTypedStream *) tstream
{
	int i;
	
	for (i=0; i<6; i++) {
		NXWriteTypes(tstream,"{ciiff}",
			&(largest[i]->key),
			&(largest[i]->numMissed),&(largest[i]->numInGame),
			&(largest[i]->relFreq),&(largest[i]->absFreq));
		NXWriteArray(tstream, "c", 20, largest[i]->relFreqBuff);
		NXWriteArray(tstream, "c", 20, largest[i]->absFreqBuff);
		}
	NXWriteTypes(tstream,"ii",&missedCount,&gameCompleted);
	[performanceEvaluatorWindow setDocEdited:NO];
	return self;
}
	

@end


