/***************************************************************************
 *                                                                         *
 *   BBSPSTAT.C                                                            *
 *                                                                         *
 *   Copyright (c) 1992-1997 Galacticomm, Inc.    All Rights Reserved.     *
 *                                                                         *
 *   This is the offline utility that generates the .BIN files for the     *
 *   default statistical graph screens.                                    *
 *                                                                         *
 *                                             - Chris Robert 03/01/92     *
 *                                                                         *
 ***************************************************************************/

#ifdef GCWINNT
#include <windows.h>
#endif // GCWINNT
#include "gcomm.h"
#include "majorbbs.h"
#include "oprlow.h"
#include "statscns.h"
#include "excphand.h"

#define FILREV "$Revision: 9 $"

#ifdef GCWINNT
#define KEY_USECONSOLE "UseConsoleWindow"
#define INIVIDEO() AllocConsole(); initvid();
#else
#define INIVIDEO() initvid();
#endif // GCWINNT

DFAFILE *svbb;                     /* system variable data block pointer   */

static CHAR dosscn[GVIDSCNSIZ];    /* saved DOS screen image               */
extern CHAR scntbl[][GVIDSCNSIZ];/* array of screens (c/o MAKESCNS)*/

USHORT dtrack;                     /* date of last zeroing of stats        */

struct sysvbl sv;                  /* system variable structure #1         */
struct sysvb2 sv2;                 /* system variable structure #2         */
struct sysvb3 sv3;                 /* system variable structure #3         */

static CHAR *months[]={
     "","January's","February's","March's","April's","May's","June's","July's",
     "August's","September's","October's","November's","December's"
};

static VOID lstats(VOID),drwgr1(VOID),drwgr2(VOID),drwgr3(VOID),drwgr4(VOID),
            drwgr5(VOID),drwgr6(VOID),labely(INT,INT,LONG,INT,INT),
            drawbar(INT,INT,INT,LONG,LONG,INT),sgraph(CHAR *filnam),
            sstats(VOID),dtitle(INT,INT,INT,CHAR *),zeromac(VOID),
            wipout(INT botx,INT boty,INT hgt,INT wid);


#ifdef GCWINNT
INT WINAPI
WinMain(
HINSTANCE hInstance,               // handle of current instance
HINSTANCE hPrevInstance,           // handle of previous instance
LPSTR pCmdLine,                    // pointer to command line
INT nCmdShow)                      // show state of window
{
#else
INT
main(                              /* main program loop                    */
INT argc,
CHAR *argv[])
{
#endif // GCWINNT
#ifdef GCWINNT
     HKEY hKey;
     DWORD keyType;
     DWORD keySize;
     DWORD keyVal=1;               /* always do screens unless otherwise   */
#endif    // GCWINNT
TRY
#ifdef GCWINNT
     (VOID)hInstance;
     (VOID)hPrevInstance;
     (VOID)nCmdShow;
     (VOID)pCmdLine;
     if (RegOpenKeyEx(HKEY_LOCAL_MACHINE,REG_KEY_BASE,0,KEY_ALL_ACCESS,&hKey)
            == ERROR_SUCCESS) {
          keySize=sizeof(keyVal);
          if (RegQueryValueEx(hKey,KEY_USECONSOLE,NULL,&keyType,(BYTE *)&keyVal,
               &keySize) == ERROR_SUCCESS) {
               if ((keySize != sizeof(keyVal)) || (keyType != REG_DWORD)) {
                    keyVal=1;
               }
          }
          else {
               keyVal=1;
          }
          RegCloseKey(hKey);
     }
#else
     (VOID)argc;
     (VOID)argv;
#endif // GCWINNT
#ifdef GCWINNT
     if (keyVal != 0) {
#endif    // GCWINNT
          INIVIDEO();
          cursiz(GVIDNOCURS);
          scn2mem(dosscn,0,GVIDSCNSIZ);
          monorcol();
          cvtscn(scntbl[0]);
          explode(scntbl[0],23,9,55,13);
          setwin(scntbl[0],0,0,79,24,0);
#ifdef GCWINNT
     }
#endif GCWINNT
     lstats();
#ifdef GCWINNT
     if (keyVal != 0) {
#endif    // GCWINNT
          color=1;                 /* always generate screens in color     */
          drwgr1();
          drwgr2();
          drwgr3();
          drwgr4();
          drwgr5();
          drwgr6();
#ifdef GCWINNT
     }
#endif // GCWINNT
     sstats();
#ifdef GCWINNT
     if (keyVal != 0) {
#endif    // GCWINNT
          setatr(0x07);
          printf(" ");
          locate(0,24);
          mem2scn(dosscn,0,GVIDSCNSIZ);
          cursiz(1);
#ifdef GCWINNT
          FreeConsole();
     }
#else
     clsvid();
#endif // GCWINNT
     return(0);
EXCEPT
#ifdef GCWINNT
     return(1);
#endif // GCWINNT
}

static VOID
lstats(VOID)                       /* load statistics info from disk       */
{
     svbb=dfaOpen("wgsvbl2.dat",sizeof(struct sysvb3),NULL);
     dfaGetEQ(&sv,"key",0);
     dfaGetEQ(&sv2,"ky2",0);
     dfaGetEQ(&sv3,"ky3",0);
     if (sv2.lstzer == 0) {
          sv2.lstzer=today();
          dtrack=1;
     }
     else {
          dtrack=cofdat(today())-cofdat(sv2.lstzer);
          dtrack=(dtrack == 0 ? 1 : dtrack);
     }
}

static VOID
drwgr1(VOID)                       /* draw the first graph (lines-in-use)  */
{
     INT i;
     LONG biggest=0L;

     iniscn("wgssta1.bin",scntbl[0]);
     dtitle(21,1,70,spr("%s Average Lines-in-Use",months[ddmon(sv2.lstzer)]));
     for (i=0 ; i < 48 ; i++) {
          biggest=max(biggest,(LONG)(sv2.nliniu[i]));
     }
     biggest=(biggest+dtrack/2)/dtrack;
     wipout(22,15,13,48);
     labely(17,3,biggest,25,4);
     for (i=0 ; i < 48 ; i++) {
          drawbar(22+i,15,1,biggest,(LONG)((sv2.nliniu[i])+dtrack/2)/dtrack,25);
     }
     sgraph("wgssta1.bin");
}

static VOID
drwgr2(VOID)                       /* draw the 2nd graph (calls/baud rate) */
{
     INT i;
     LONG biggest=0L;

     iniscn("wgssta2.bin",scntbl[0]);
     dtitle(22,3,71,spr("%s Calls by Baud Rate",months[ddmon(sv2.lstzer)]));
     for (i=0 ; i < 8 ; i++) {
          biggest=max(biggest,sv.calls[i]);
     }
     wipout(24,13,9,45);
     labely(17,5,biggest,17,5);
     for (i=0 ; i < 8 ; i++) {
          drawbar(24+(i*6),13,3,biggest,sv.calls[i],17);
     }
     sgraph("wgssta2.bin");
}

static VOID
drwgr3(VOID)                       /* draw the 3rd graph (time used)       */
{
     INT i,j;
     LONG biggest=0L,totals[24];

     iniscn("wgssta3.bin",scntbl[0]);
     dtitle(22,1,70,spr("%s Average Minutes Used",months[ddmon(sv2.lstzer)]));
     setmem(totals,sizeof(LONG)*24,0);
     for (i=0 ; i < 24 ; i++) {
          for (j=0 ; j < NUMGRPS-1 ; j++) {
               totals[i]+=sv3.secghr[j][i];
          }
          totals[i]=((totals[i]+30L)/60L+dtrack/2)/dtrack;
     }
     for (i=0 ; i < 24 ; i++) {
          biggest=max(biggest,totals[i]);
     }
     wipout(23,15,13,46);
     labely(17,3,biggest,25,5);
     for (i=0 ; i < 24 ; i++) {
          drawbar(23+(i*2),15,1,biggest,totals[i],25);
     }
     sgraph("wgssta3.bin");
}

static VOID
drwgr4(VOID)                       /* draw the 4th graph (time used/g#)    */
{
     INT i,j;
     LONG biggest=0L,totals[NUMGRPS-1],temp;

     iniscn("wgssta4.bin",scntbl[0]);
     dtitle(24,1,70,spr("%s Average Hours Used",months[ddmon(sv2.lstzer)]));
     setmem(totals,sizeof(LONG)*(NUMGRPS-1),0);
     for (i=0 ; i < NUMGRPS-1 ; i++) {
          for (j=0 ; j < 24 ; j++) {
               totals[i]+=sv3.secghr[i][j];
          }
          totals[i]=(temp=((totals[i]+1800L)/3600L+dtrack/2)/dtrack) > 9999L
                    ? 9999L : temp;
     }
     for (i=0 ; i < NUMGRPS-1 ; i++) {
          biggest=max(biggest,totals[i]);
     }
     wipout(23,15,13,47);
     labely(18,3,biggest,25,4);
     for (i=0 ; i < NUMGRPS-1 ; i++) {
          drawbar(24+(i*3),15,1,biggest,totals[i],25);
     }
     sgraph("wgssta4.bin");
}

static VOID
drwgr5(VOID)                       /* draw the 5th graph (creds used)      */
{
     INT i,j;
     LONG biggest=0L,totals[24];

     iniscn("wgssta5.bin",scntbl[0]);
     dtitle(22,1,70,spr("%s Average Credits Used",months[ddmon(sv2.lstzer)]));
     setmem(totals,sizeof(LONG)*24,0);
     for (i=0 ; i < 24 ; i++) {
          for (j=0 ; j < NUMGRPS-1 ; j++) {
               totals[i]+=sv3.crdghr[j][i];
          }
          totals[i]=((totals[i]+500L)/1000L+dtrack/2)/dtrack;
     }
     for (i=0 ; i < 24 ; i++) {
          biggest=max(biggest,totals[i]);
     }
     wipout(23,15,13,46);
     labely(17,3,biggest,25,5);
     for (i=0 ; i < 24 ; i++) {
          drawbar(23+(i*2),15,1,biggest,totals[i],25);
     }
     sgraph("wgssta5.bin");
}

static VOID
drwgr6(VOID)                       /* draw the 6th graph (creds used/g#)   */
{
     INT i,j;
     LONG biggest=0L,totals[NUMGRPS-1],temp;

     iniscn("wgssta6.bin",scntbl[0]);
     dtitle(24,1,70,spr("%s Average Credits Used",months[ddmon(sv2.lstzer)]));
     setmem(totals,sizeof(LONG)*(NUMGRPS-1),0);
     for (i=0 ; i < NUMGRPS-1 ; i++) {
          for (j=0 ; j < 24 ; j++) {
               totals[i]+=sv3.crdghr[i][j];
          }
          totals[i]=(temp=((totals[i]+500L)/1000L+dtrack/2)/dtrack) > 9999L
               ? 9999L : temp;
     }
     for (i=0 ; i < NUMGRPS-1 ; i++) {
          biggest=max(biggest,totals[i]);
     }
     wipout(23,15,13,47);
     labely(18,3,biggest,25,4);
     for (i=0 ; i < NUMGRPS-1 ; i++) {
          drawbar(24+(i*3),15,1,biggest,totals[i],25);
     }
     sgraph("wgssta6.bin");
}

static VOID
dtitle(upx,upy,dwx,title)          /* display the title (centered)         */
INT upx,upy;                            /* upper left x and y coordinates  */
INT dwx;                                /* right-most x coordinate         */
CHAR *title;                            /* title to be displayed           */
{
     INT i;

     setatr(0x1D);
     locate(upx,upy);
     for (i=0 ; i < (dwx-upx) ; i++) {
          printf(" ");
     }
     locate(upx+(dwx-upx)/2-strlen(title)/2,upy);
     printf("%s",title);
}

static VOID
labely(upx,upy,scale,num,len)       /* label the y axis                    */
INT upx,upy;                            /* upper x and y coordinates       */
LONG scale;                             /* largest number (for scale)      */
INT num;                                /* number of half-labels           */
INT len;                                /* length of each label (rt. just) */
{
     INT i;
     LONG tckamt;

     setatr(0x1A);
     scale=(tckamt=(scale < num ? 1 : (scale+num/2)/num))*2L;
     for (i=(num/2)-1 ; i >= 0 ; i--) {
          printfat(upx,upy+i,"%s",spr("%*ld",len,scale));
          scale+=(tckamt*2);
     }
}

static VOID
wipout(botx,boty,hgt,wid)               /* wipe out the graph area         */
INT botx,boty;                          /*   bottom-left x and y coords    */
INT hgt,wid;                            /*   heigth and width of graph     */
{
     INT x,y;

     setatr(0x1A);
     for (y=boty ; y > boty-hgt ; y--) {
          for (x=botx ; x < botx+wid ; x++) {
               locate(x,y);
               printf(y == boty ? "Ä" : " ");
          }
     }
}

static VOID
drawbar(botx,boty,width,scale,size,num) /* draw a bar on the bar graph     */
INT botx,boty;                          /*   bottom left x and y coords    */
INT width;                              /*   width of the bar              */
LONG scale;                             /*   # to scale with (biggest)     */
LONG size;                              /*   size of this bar              */
INT num;                                /*   number of labels              */
{
     INT i,j,chr;
     LONG tckamt;

     setatr(0x1E);
     tckamt=(scale < num ? 1 : (scale+num/2)/num);
     for (i=0 ; i <= num ; i+=2) {
          if (i == 0) {
               locate(botx,boty);
               if (size >= tckamt) {
                    chr='ß';
                    setatr(0x1E);
               }
               else {
                    chr='Ä';
                    setatr(0x1A);
               }
          }
          else {
               locate(botx,boty-i/2);
               setatr(0x1E);
               chr=(size >= tckamt*(i+1) ? 'Û' : size >= tckamt*i ? 'Ü' : ' ');
          }
          for (j=0 ; j < width ; j++) {
               printf("%c",chr);
          }
     }
}

static VOID
sgraph(filnam)                     /* save the current graph in memory     */
CHAR *filnam;                           /* file name to save as            */
{
     FILE *fp;

     if ((fp=fopen(filnam,FOPWB)) == NULL) {
          catastro("CAN'T OPEN \"%s\" FOR UPDATING!",filnam);
     }
     fwrite(scntbl[0],GVIDSCNSIZ,1,fp);
     fclose(fp);
}

static VOID
sstats(VOID)                       /* save all the stats again             */
{
     INT i,j;

     if (ddmon(today()) != ddmon(sv2.lstzer)) {
          zeromac();
          for (i=0 ; i < 8 ; i++) {
               sv.calls[i]=0L;
          }
          for (i=0 ; i < NUMGRPS-1 ; i++) {
               for (j=0 ; j < 24 ; j++) {
                    sv3.secghr[i][j]=0L;
                    sv3.crdghr[i][j]=0L;
               }
          }
          for (i=0 ; i < 48 ; i++) {
               sv2.nliniu[i]=0;
          }
          sv2.lstzer=today();
     }
     dfaSetBlk(svbb);
     dfaGetEQ(NULL,"key",0);
     dfaUpdateV(&sv,sizeof(struct sysvbl));
     dfaGetEQ(NULL,"ky2",0);
     dfaUpdateV(&sv2,sizeof(struct sysvb2));
     dfaGetEQ(NULL,"ky3",0);
     dfaUpdateV(&sv3,sizeof(struct sysvb3));
     dfaClose(svbb);
}

static VOID
zeromac(VOID)                      /* zero module and class statistics     */
{
     DFAFILE *bbptr;
     struct mdstats tmpmd;
     struct acclass tmpcl;

     bbptr=dfaOpen("wgsstat2.dat",sizeof(struct mdstats),NULL);
     if (dfaQueryLO(0)) {
          do {
               dfaAbsRec(&tmpmd,0);
               tmpmd.creds=0L;
               tmpmd.seconds=0L;
               dfaUpdate(&tmpmd);
          } while (dfaQueryNX());
     }
     dfaClose(bbptr);
     bbptr=dfaOpen("wgsclas2.dat",sizeof(struct acclass),NULL);
     if (dfaQueryLO(0)) {
          do {
               dfaAbsRec(&tmpcl,0);
               tmpcl.seconds=0L;
               dfaUpdate(&tmpcl);
          } while (dfaQueryNX());
     }
     dfaClose(bbptr);
}
