/*
 *	lav.c - Amiga load average
 *
 *	Written by:
 *	William J. Rucklidge
 *	wjr@unicus.UUCP		(soon to be wjr@unicus.com)
 *
 *	You may take this program and skywrite it and sell tickets for all
 *	I care. (i.e this program is placed in the public domain).
 *	However, if you have any improvements, suggestions or comments, mail
 *	a note to me.
 */

#include	<intuition/intuition.h>
#include	<exec/exec.h>
#include	<exec/execbase.h>

#define	TIME15	900	/* Number of samples in 15 minutes */
#define	TIME5	300	/* Number of samples in 5 minutes */
#define	TIME1	60	/* Number of samples in 1 minute */
#define	TPS	50	/* Ticks per sample, for Delay() */
#define	CLOSEWIDTH	30	/* Width of the close gadget in pixels */

struct NewWindow windef = {
	289, 0, 300, 10,
	-1, -1,
	CLOSEWINDOW,
	WINDOWCLOSE | WINDOWDEPTH | WINDOWDRAG,
	NULL, NULL,
	(UBYTE *) "Load",
	NULL, NULL, 0, 0, 0, 0,
	WBENCHSCREEN
};

struct IntuiText wintext = {
	0, 1, JAM2,
	0, 0,
	NULL, NULL, NULL
	};

extern void *OpenLibrary(), *OpenWindow(), *FindTask();

struct IntuitionBase *IntuitionBase;

void
convertTime(sum, count, position)
long sum;
int count;
register char *position;
{
    register long temp;

    temp = (sum * 100L + 50L) / count;
    *(position + 4) = '0' + (int)(temp % 10);
    temp /= 10;
    *(position + 3) = '0' + (int)(temp % 10);
    temp /= 10;
    *(position + 1) = '0' + (int)(temp % 10);
    temp /= 10;
    if (temp != 0) {
	*position = '0' + (int)(temp % 10);
	}
    else {
	*position = ' ';
	}
    }

#define	FORMAT	"Load: ##.## ##.## ##.##"

main()
{
    register int length;	/* Length of the current run queue */
    register struct Node *mynode; /* Node to walk through the queue */
    register int i;	/* General counter */
    int last[TIME15];	/* Length of the run queue in the last TIME seconds */
    long sum15 = 0;	/* Sum of the last 15 minutes */
    long sum5 = 0;	/* Sum of the last 5 minutes */
    long sum1 = 0;	/* Sum of the last minute */
    int pos = 0;	/* Current position in last for new value */
    int pos15 = 0;	/* Current position in last for sum15 */
    int pos5 = TIME15-TIME5;	/* Current position in last for sum5 */
    int pos1 = TIME15-TIME1;	/* Current position in last for sum1 */
    char uptimestr[26];
    struct ExecBase *ExecBase;
    struct Window *win;

    SetTaskPri(FindTask(0L), 5L);

    (void) strcpy(uptimestr, FORMAT);

    if (!(ExecBase = (struct ExecBase *)OpenLibrary("exec.library", 0L))) {
	printf("Couldn't open exec... the sky is falling!\n");
	exit(999);
	}

    if (!(IntuitionBase =
	    (struct IntuitionBase *)OpenLibrary("intuition.library", 0L))) {
	printf("Couldn't open intuition - must be dumb\n");
	CloseLibrary(ExecBase);
	exit(998);
	}

    if (!(win = OpenWindow(&windef))) {
	printf("Couldn't open window\n");
	CloseLibrary(IntuitionBase);
	CloseLibrary(ExecBase);
	exit(997);
	}

    wintext.IText = (UBYTE *)uptimestr;

    for (i = 0; i < TIME15 ; i++) {
	last[i] = 0;
	}

    for (;;) {
	Delay((long)TPS);
	if (GetMsg(win -> UserPort)) {
	    break;
	    }

	length = 0;
	Disable();
	for (mynode = (ExecBase -> TaskReady).lh_Head;
		mynode = mynode -> ln_Succ; ) {
	    length++;
	    }
	Enable();

	sum15 += (length - last[pos15]);
	sum5 += (length - last[pos5]);
	sum1 += (length - last[pos1]);
	last[pos] = length;
	if (++pos15 == TIME15) {
	    pos15 = 0;
	    }
	if (++pos5 == TIME15) {
	    pos5 = 0;
	    }
	if (++pos1 == TIME15) {
	    pos1 = 0;
	    }
	if (++pos == TIME15) {
	    pos = 0;
	    }

	convertTime(sum1, TIME1, uptimestr + 6);
	convertTime(sum5, TIME5, uptimestr + 12);
	convertTime(sum15, TIME15, uptimestr + 18);
	PrintIText(win -> RPort, &wintext, (long)CLOSEWIDTH, 1L);
	}

    CloseWindow(win);
    CloseLibrary(IntuitionBase);
    CloseLibrary(ExecBase);
    }


