ftp.nice.ch/pub/next/science/education/CurveGrader.NIHS.bs.tar.gz#/CurveGrader/Source/CurveView.m

This is CurveView.m in view mode; [Download] [Up]

/*
 *	A plotting view. 
 *	Rob Ferrante
 */
#import "CurveView.h"
#import "GradeSlider.h"
#include "CV.h"
#import <appkit/Matrix.h>
#import <appkit/Cell.h>
#import <objc/List.h>
#import <dpsclient/wraps.h>
#import <strings.h>

@implementation CurveView

float  scoreFromPos(int x)
{
	return 100.0 - x/5.0;
}

- initFrame: (NXRect *)r
{
	int i;	
	self = [super initFrame:r];
	count = 0;
	percentMode = NO;
	topOfView = 399;
	for (i=0;i<20;i++) scoreBin[i]=0;
	posA = 100; posB=200; posC=300; posD=400;
	return self;
}

- setPercentMode:sender
{
	percentMode = ([[sender selectedCell] tag] == 1);
	[self updateFields];
	return self;
}

- loadStudents:sender
{
	int num, i, maxBin=0;
	[scoreMatrix getNumRows:&num numCols:&i]; // used i for cols, don't need
	count = 0;
	for (i=0;i<20;i++) scoreBin[i]=0;
	for (i=0;i<num;i++) {
		scores[i] = [[scoreMatrix cellAt:i :0] floatValue];
		if (strlen([[nameMatrix cellAt:i :0] stringValue]) >0){
			count++;
			if (scores[i]>=100.0) scores[i]=99.9;
			scoreBin[(int)(scores[i]/5.0)]++;
		}
	}
	for (i=0;i<20;i++)
		if (maxBin < scoreBin[i]) maxBin = scoreBin[i];
	[self setDrawSize:500 :(topOfView=maxBin*1.25)];
	[self display];
	[self updateFields];
	return self;
}

- loadGrades:sender
{
	int i;
	float cutA,cutB,cutC,cutD;
	
	cutA = scoreFromPos(posA);
	cutB = scoreFromPos(posB);
	cutC = scoreFromPos(posC);
	cutD = scoreFromPos(posD);
	for (i=0;i<count;i++) {
		if (scores[i] >= cutA) [[gradeMatrix cellAt:i :0] setStringValue:"A"];
		else if (scores[i] >= cutB) [[gradeMatrix cellAt:i :0] setStringValue:"B"];
		else if (scores[i] >= cutC) [[gradeMatrix cellAt:i :0] setStringValue:"C"];
		else if (scores[i] >= cutD) [[gradeMatrix cellAt:i :0] setStringValue:"D"];
		else [[gradeMatrix cellAt:i :0] setStringValue:"F"];
	}
	return self;
}

- drawSelf:(NXRect *)list:(int)count
{
	int i=19, k=0;
	NXRect  bar;
	NXEraseRect(&bounds);
	PSsetgray(NX_DKGRAY);
	while(i>=0) {
		NXSetRect(&bar,k,0,25,scoreBin[i--]);
		NXRectFill(&bar);
		k +=25;
	}
	PSlines(posA, posB, posC, posD, topOfView);
	return self;
}

- moveA:sender
{
	posA = [sender posA];
	[self display];
	[fieldA setFloatValue:[self percentBetween:scoreFromPos(posA) :100.01]];
	[fieldB setFloatValue:[self percentBetween:scoreFromPos(posB) :scoreFromPos(posA)]];
    return self;
}

- moveB:sender
{
	posB = [sender posB];
	[self display];
	[fieldB setFloatValue:[self percentBetween:scoreFromPos(posB) :scoreFromPos(posA)]];
	[fieldC setFloatValue:[self percentBetween:scoreFromPos(posC) :scoreFromPos(posB)]];
    return self;
}

- moveC:sender
{
	posC = [sender posC];
	[self display];
	[fieldC setFloatValue:[self percentBetween:scoreFromPos(posC) :scoreFromPos(posB)]];
	[fieldD setFloatValue:[self percentBetween:scoreFromPos(posD) :scoreFromPos(posC)]];
    return self;
}

- moveD:sender
{
	posD = [sender posD];
	[self display];
	[fieldD setFloatValue:[self percentBetween:scoreFromPos(posD) :scoreFromPos(posC)]];
	[fieldF setFloatValue:[self percentBetween:0.0 :scoreFromPos(posD)]];
    return self;
}

- updateFields
{
	[fieldA setFloatValue:[self percentBetween:scoreFromPos(posA) :100.01]];
	[fieldB setFloatValue:[self percentBetween:scoreFromPos(posB) :scoreFromPos(posA)]];
	[fieldC setFloatValue:[self percentBetween:scoreFromPos(posC) :scoreFromPos(posB)]];
	[fieldD setFloatValue:[self percentBetween:scoreFromPos(posD) :scoreFromPos(posC)]];
	[fieldF setFloatValue:[self percentBetween:0.0 :scoreFromPos(posD)]];
	return self;
}

-(float)percentBetween:(float)low :(float)high
{
	int i,k=0;
	
	for (i=0; i<count;i++) {
		if (scores[i]>=low && scores[i]<high) k++;
	}
	if (percentMode == YES) return (k/(float)count)*100.0;
	else return k;
}



@end

These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.