home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
High Voltage Shareware
/
high1.zip
/
high1
/
DIR23
/
TOUCH2.ZIP
/
GRPH.C
< prev
next >
Wrap
C/C++ Source or Header
|
1993-08-14
|
11KB
|
501 lines
/*
* grph.c - graph support
*/
/*
* Copyright 1993 Victor A. Abell, Lafayette, Indiana 47906. All rights
* reserved.
*
* Written by Victor A. Abell.
*
* Permission is granted to anyone to use this software for any purpose on
* any computer system, and to alter it and redistribute it freely, subject
* to the following restrictions:
*
* 1. Victor A. Abell is not responsible for any consequences of the use of
* this software.
*
* 2. The origin of this software must not be misrepresented, either by
* explicit claim or by omission. Credit to Victor A. Abell must
* appear in documentation and sources.
*
* 3. Altered versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
*
* 4. This notice may not be removed or altered.
*/
#ifndef lint
static char copyright[] =
"@(#) Copyright 1993 Victor A. Abell.\nAll rights reserved.\n";
#endif
#include "touch2.h"
#include <ctype.h>
#include <math.h>
#define FIELDLN 16 /* dump line field length */
#define GPFX 31 /* graph prefix column count */
char Date[FIELDLN]; /* dump line date */
char Dow[FIELDLN]; /* dump line day of week */
double Gmaxl; /* graph maximum line */
double Gminl; /* graph minimum line */
short Lpp = LPP; /* lines per page */
double Rval; /* dump line reading value */
char Time[FIELDLN]; /* dump line time value */
char *MeasName[] = { "Regular", "Check Solution (C)", "Check Strip (!)",
"Meter Error (*)" };
/*
* DrawGraph() - draw a graph of meter memory values
*/
void
DrawGraph(ty)
int ty; /* type: 0 = screen, 1 = file */
{
#if defined(UNIX)
int i;
#else
short i;
#endif
short err, gmn, gmx, j, k, lpp, mmol, n[4], pc, row;
char ch, *cp1, *cp2, gttl[2][82], hdr[5][72], ln[82], pr[80];
double fn, dj, dk, iv, max[4], min[4], mn, mx, sumx[4], sumxx[4];
short prow, px, pxh, py, pyh;
char pca[PRTRCTLLN+1], pcb[PRTRCTLLN+1];
int pcal, pcbl;
struct videoconfig vc;
#if defined(UNIX)
int g, gt, pcol;
#else
short g, gt, pcol;
#endif
/*
* If graphing to screen, enter VRES16COLOR video mode.
*/
if ( !ty) {
vc = Vc;
if (_setvideomode(_VRES16COLOR) == 0) {
(void) WarnMsg(10, 30,
"The graph function requires VRES16COLOR.",
12, 30,
"This display does not support that mode.", 0);
return;
}
_setbkcolor(Colors[BkClrx].v);
_settextcolor(TxtClrx);
_setcolor(TxtClrx);
_getvideoconfig(&Vc);
Vmode = 1;
}
/*
* Miscellaneous setup.
*/
for (j = 0; j < 4; j++) {
max[j] = 0.0;
min[j] = 9999.0;
n[j] = 0;
sumx[j] = sumxx[j] = 0.0;
}
px = Vc.numxpixels / ((Vc.numtextcols > 80 ? 80 : Vc.numtextcols) - 2);
py = Vc.numypixels / Vc.numtextrows;
pxh = px/2;
pyh = py/2;
/*
* Accumulate statistics values.
*/
for (err = mmol = 0, i = DumpHs; i < DumpLc; i++) {
if ((j = ParseDumpLn(i, 1)) == 0) {
err = 1;
if ((char)WarnMsg(10, 34, "Bad dump line:", 12,
(short)(((Vc.numtextcols - strlen(DumpLp[i]))/2)+1),
DumpLp[i], 1)
== ESC) {
graph_exit:
if ( ! ty) {
_setvideomode(vc.mode);
_setbkcolor(BkClrx & 7);
_settextcolor(TxtClrx);
Vc = vc;
Vmode = 0;
}
return;
}
continue;
}
if (j == 2)
mmol = 1;
if (j > 3)
continue;
sumx[Rtype] += Rval;
sumxx[Rtype] += Rval * Rval;
n[Rtype]++;
if (max[Rtype] < Rval)
max[Rtype] = Rval;
if (min[Rtype] > Rval)
min[Rtype] = Rval;
}
if (err)
goto graph_exit;
/*
* Form statistics lines.
*/
(void) sprintf(&hdr[0][0], " %-18s %7s %6s %8s %6s %6s",
"", "Number", "Mean", "Std Dev", "Min", "Max");
for (j = 0; j < 4; j++) {
if ( ! n[j]) {
hdr[j+1][0] = '\0';
continue;
}
fn = (float)n[j];
(void) sprintf(&hdr[j+1][0],
" %-18s %7d %6.1f %8.2f %6.1f %6.1f",
MeasName[j], n[j], sumx[j]/fn,
sqrt(sumxx[j]/fn - (sumx[j]/fn * sumx[j]/fn)),
min[j], max[j]);
}
/*
* Establish graph parameters.
*/
if ( ! Lineval) {
if (mmol) {
Gmaxl = DEFMMMAX;
Gminl = DEFMMMIN;
} else {
Gmaxl = DEFMGMAX;
Gminl = DEFMGMIN;
}
}
mn = (Gminl < min[0]) ? Gminl : min[0];
mx = (Gmaxl > max[0]) ? Gmaxl : max[0];
dk = (double)(((Vc.numtextcols > 80) ? 80 : Vc.numtextcols) - GPFX - 2);
if ((iv = (mx - mn) / dk) < 0.1)
iv = 0.1;
gmn = (int)((Gminl - mn) / iv) + GPFX;
gmx = (int)((Gmaxl - mn) / iv) + GPFX;
(void) sprintf(>tl[0][0], "%.3f %s per column", iv,
mmol ? "mmol/l" : "mg/dl");
for (j = strlen(>tl[0][0]); j < GPFX; j++)
gttl[0][j] = ' ';
for (j = 0; j < GPFX; j++)
gttl[1][j] = ' ';
cp1 = >tl[0][GPFX-4];
cp2 = >tl[1][GPFX];
for (dj = mn; dj < mx; ) {
(void) sprintf(cp1, "%5.1f", dj);
cp1 += 5;
*cp2++ = '+';
*cp2 = '\0';
dj += iv;
for (k = 0; k < 5 && dj <= mx; k++) {
if (k < 1) {
*cp1++ = ' ';
*cp1 = '\0';
}
*cp2++ = '-';
*cp2 = '\0';
dj += iv;
}
}
/*
* If drawing graph to file, create printer control strings.
*/
if (ty) {
if (AftGraph)
pcal = CvtPrtrStr(AftGraph, pca, sizeof(pca));
if (BefGraph) {
if ((pcbl = CvtPrtrStr(BefGraph, pcb, sizeof(pcb))) > 0)
(void) fwrite((void *)pcb, (size_t)pcbl, 1, Graphfs);
}
lpp = Lpp;
pc = 0;
}
/*
* Refill screen.
*/
for (j = pcol = 0;;) {
if ( ! ty) {
pcol = 0;
_clearscreen(_GCLEARSCREEN);
(void) sprintf(pr,
"(%d of %d) Press ESC or X to exit; Page Up/Down; Arrow Up/Down.",
(j < 9) ? 1 : j - 9 + 1, DumpLc - DumpHs);
PromptMsg(pr);
}
for (row = 1, k = j;
row < Vc.numtextrows && k < DumpLc+9-DumpHs;
k++, row++)
{
if ( ! ty)
_settextposition(row, 1);
switch (k) {
case 0:
if ( ! ty)
_outtext(Gttl);
break;
case 1:
case 2:
case 3:
case 4:
case 5:
if ( ! ty)
_outtext(&hdr[k-1][0]);
break;
case 6:
break;
case 7:
case 8:
if ( ! ty)
_outtext(>tl[k-7][0]);
break;
default:
(void) ParseDumpLn(k-9+DumpHs, 1);
if (Rtype == RDREG)
g = (int)((Rval - mn) / iv) + GPFX;
if (Rtype == RDHIGH) {
(void) sprintf(ln,
"%-3.3s %-8.8s %-8.8s HIGH",
Dow, Date, Time);
} else {
switch (Rtype) {
case RDSOL:
ch = 'C'; break;
case RDSTRIP:
ch = '!'; break;
case RDMTRERR:
ch = '*'; break;
default:
ch = ' ';
}
(void) sprintf(ln,
"%-3.3s %-8.8s %-8.8s %c %5.1f",
Dow, Date, Time, ch, Rval);
}
if (ty) {
if (lpp >= Lpp) {
pc++;
if (PcDisp) {
(void) fprintf(Graphfs,
"%s\nPage %2d: %s\n",
pc > 1 ? "\f" : "",
pc, Gttl);
} else {
(void) fprintf(Graphfs,
"%s\n %s\n",
pc > 1 ? "\f" : "",
Gttl);
}
(void) fprintf(Graphfs,
"\n%s\n%s\n%s\n%s\n%s\n\n%s\n%s\n",
&hdr[0][0],
&hdr[1][0],
&hdr[2][0],
&hdr[3][0],
&hdr[4][0],
>tl[0][0],
>tl[1][0]);
lpp = HDRLPP;
}
if (Rtype != RDREG) {
gt = gmx;
g = GPFX-2;
} else
gt = (g > gmx) ? g : gmx;
ln[gt+1] = '\0';
for (gt; gt >= GPFX-2; gt--) {
if (gt == gmn || gt == gmx) {
ln[gt] = (gt <= g) ? IntCh[0]
: LineCh[0];
} else if (gt >= GPFX && gt <= g)
ln[gt] = BarCh[0];
else
ln[gt] = ' ';
}
(void) fprintf(Graphfs, "%s\n", ln);
lpp++;
} else {
_outtext(ln);
if (gmn) {
_settextposition(row, gmn + 1);
_outtext(LineCh);
}
if (gmx) {
_settextposition(row, gmx + 1);
_outtext(LineCh);
}
if (Rtype != RDREG)
break;
if (pcol) {
_moveto((pcol * px) + pxh,
((prow-1) * py) + pyh);
_lineto((g * px) + pxh,
((row-1) * py) + pyh);
}
pcol = g;
prow = row;
}
}
}
/*
* See if done graphing to file.
*/
if (ty) {
if (k >= DumpLc+9-DumpHs) {
if (pcal > 0) {
(void) fwrite((void *)pca,
(size_t)pcal, 1, Graphfs);
}
(void) fclose(Graphfs);
Graphfs = NULL;
return;
}
j = k;
continue;
}
/*
* Wait for keyboard input.
*/
for (k = 1; k;) {
switch ((char)WaitAnyKey()) {
case ESC:
case 'x':
case 'X':
goto graph_exit;
case PGDN:
if ((j+Vc.numtextrows-1) < (DumpLc+9-DumpHs)) {
j = j + Vc.numtextrows - 1;
k = 0;
} else
putch(BELL);
break;
case PGUP:
if (j < (Vc.numtextrows - 1))
j = 0;
else
j = j - (Vc.numtextrows - 1);
k = 0;
break;
case UARW:
if (j) {
j--;
k = 0;
} else
putch(BELL);
break;
case DARW:
if (j < (DumpLc+9-DumpHs-1)) {
j++;
k = 0;
} else
putch(BELL);
break;
default:
putch(BELL);
}
}
}
}
/*
* ParseDumpLn() - parse dump line
*/
int
ParseDumpLn(i, s)
#if defined(UNIX)
int i; /* line index */
int s; /* seconds flag */
#else
short i; /* line index */
short s; /* seconds flag */
#endif
{
char *cp, r[FIELDLN];
short rv;
if ( i < DumpHs || i > DumpLc)
return(0);
/*
* Parse day of week, date, time and reading.
*/
if ((cp = ParseField(DumpLp[i], Dow, sizeof(Dow))) == NULL)
return(0);
if ((cp = ParseField(cp, Date, sizeof(Date))) == NULL)
return(0);
if ((cp = ParseField(cp, Time, sizeof(Time))) == NULL)
return(0);
if ((cp = ParseField(cp, r, sizeof(r))) == NULL)
return(0);
/*
* Convert last two characters of day of week to lower case.
*/
if (Dow[1] && isascii(Dow[1]) && isupper(Dow[1]))
Dow[1] = tolower(Dow[1]);
if (Dow[2] && isascii(Dow[2]) && isupper(Dow[2]))
Dow[2] = tolower(Dow[2]);
/*
* Shorten the time by eliminating the :00 seconds.
*/
if (s) {
if (strncmp(&Time[5], ":00", 3) == 0) {
for (cp = &Time[5];; cp++) {
if ((*cp = *(cp+3)) == '\0')
break;
}
}
}
/*
* Get reading type and convert the value.
*/
cp = r;
rv = 1;
switch (*cp) {
case ' ':
case 'M':
if (strcmpi(cp, " HIGH ") == 0) {
Rtype = RDHIGH;
return(4);
}
Rtype = RDREG;
break;
case '!':
Rtype = RDSTRIP;
break;
case 'C':
case 'K': /* SVENS || DEUTS */
Rtype = RDSOL;
break;
default:
return(0);
}
/*
* Parse value.
*/
cp++;
if (*cp == 'M') {
rv = 2;
cp++;
} else
rv = 1;
if ( ! Atof(cp, &Rval, NULL, cp)) {
if (*cp == '?') {
Rtype = RDMTRERR;
return(3);
}
Rval = 0.0;
return(0);
}
return(rv);
}