/* Week (actually just interval) top generator for MAX's BBS version 1.54 */
/* Generates at top-10 list of uploaders */
/* Anyone may use this for anything they want if they want to */

#include <proto/dos.h>          /* C= */
#include <proto/exec.h>
#include <exec/memory.h>
#include <exec/lists.h>
#include <exec/nodes.h>
#include <stdio.h>              /* SAS printf */
#include <stdlib.h>             /* atoi */
#include <string.h>             /*     strengbehandling */

struct maxfileentry {
  ULONG dato;                   /* Dato for fil anskaffelse - dage siden 01/01/78 */
  ULONG pad1;
  ULONG siz;                    /* Filstørrelse */
  ULONG dlcount;                /* Antal gange downloadet */
  UBYTE flags;
  UBYTE area;                   /* Area filen hører til i */
  UBYTE name[41];               /* Filnavn */
  UBYTE desc[60];               /* Fil desc. */
  char  uploader[41];           /* Navn på uploader */
  UBYTE unknown[42];            /* ?? evt. en sysop-kommentar, jeg er ikke sikker */
};

struct maxfilelist {
  UBYTE max[62];                /* MAX's text */
  ULONG filetotal;              /* Antal filer på BBS */
  ULONG filesarea[100];         /* Antal filer for hver sektion */
};

struct usernodetype {
  struct Node n;
  ULONG bytes;
  ULONG files;
};

BOOL hentfil(char *filnavnet, APTR *ptrptr, ULONG *sizptr)
{
struct FileInfoBlock *fib;
BPTR filhandle;

  if (filhandle=Open(filnavnet,MODE_OLDFILE))
  {
    if (fib=AllocDosObjectTags(DOS_FIB,TAG_END))
    {
      if (ExamineFH(filhandle,fib))
      {
        if (*ptrptr=AllocVec(fib->fib_Size,MEMF_ANY))
        {
          if (fib->fib_Size==Read(filhandle,*ptrptr,fib->fib_Size))
          {
            *sizptr=fib->fib_Size;
            FreeDosObject(DOS_FIB,fib);
            Close(filhandle);
            return(TRUE);
          } else printf("Coulden't read file %s\n",filnavnet);
          FreeVec(*ptrptr);
        } else printf("No memory\n");
      FreeDosObject(DOS_FIB,fib);
      } else printf("AmigaDos won't cooperate!\n");
    } else printf("REALLY no memory\n");
    Close(filhandle);
  } else printf("Coulden't open file %s\n",filnavnet);
  return(FALSE);
}

int main(int argc, char *argv[])
{
BYTE *filemem,*usermem,*rammemem; /* File.data og user.data pointere */
ULONG filesiz,usersiz,rammesiz; /* File.data og user.data filstørrelser */

ULONG totalfiles; /* Antal filer eksisterende i file.data */

BPTR filhandle; /* Handle til outputfil i ram: */

int i;

ULONG j;

ULONG x,y;

struct DateTime datostart,datoslut;

struct maxfileentry *filptr;

struct List userlist;

struct Node *usernode,*bestuser,*traverseringsptr;

char *KarlEinar="$VER: MaxWeektop v1.0\n";

  /* Undgå BROK fra compileren om at versionstrengen er overflødig */
  strlen(KarlEinar);
  /* Check rigtigt antal argumenter */
  if(argc!=11)
  {
    printf("Usage: %s file.data user.data startdate enddate xpos ypos infile outfile loaccess hiaccess\n",argv[0]);
    printf("Xpos/ypos is top left corner of the list\nInfile is the filename of a prefabricated frame\n");
    return(20);
  }
  /* Konverter position */
  x=atoi(argv[5]);
  y=atoi(argv[6]);
  /* Initialiser DateTime strukturer */
  datostart.dat_Format=datoslut.dat_Format=FORMAT_DOS;
  datostart.dat_Flags=datoslut.dat_Flags=0;
  datostart.dat_StrTime=datoslut.dat_StrTime=NULL;
  datostart.dat_StrDate=argv[3];
  datoslut.dat_StrDate=argv[4];
  /* Konverter datoerne til datetime format */
  if(!StrToDate(&datostart))
  {
    printf("Bad startdate, use dd-mmm-yy\n");
    return(20);
  }
  if(!StrToDate(&datoslut))
  {
    printf("Bad enddate, use dd-mmm-yy\n");
    return(20);
  }
  /* Inititaliser liste */
  NewList(&userlist);
  /* Hent lige de filer vi skal bruge */
  if (hentfil(argv[1],(APTR)&filemem,&filesiz))
  {
    if (hentfil(argv[2],(APTR)&usermem,&usersiz))
    {
      /* Find brugere på bbs'et frem */
      for(i=0;i<(usersiz-66)/308;i++)
      {
        j=*(ULONG *)(usermem+i*308+248+66); /* Brugerens access level */
        if(j>=atoi(argv[9]) && j<atoi(argv[10]))
        {
          if(usernode=AllocVec(sizeof(struct usernodetype),MEMF_ANY))
          {
            ((struct usernodetype *)usernode)->bytes=0;
            ((struct usernodetype *)usernode)->files=0;
            usernode->ln_Name=usermem+i*308+66;
            AddTail(&userlist,usernode);
          }
        }
      }
      if (filhandle=Open(argv[8],MODE_NEWFILE))
      {
        /* Klister rammefilen på først */
        if(hentfil(argv[7],(APTR)&rammemem,&rammesiz))
        {
          Write(filhandle,rammemem,rammesiz);
          FreeVec(rammemem);
        }
        /* Find ud af antal filer i maxs filebase */
        totalfiles=(filesiz-466)/202;
        /* Check alle filer for uploader */
        filptr=(struct maxfileentry *)(filemem+sizeof(struct maxfilelist));
        for(i=0;i<totalfiles;i++)
        {
          if(filptr->dato>=datostart.dat_Stamp.ds_Days && filptr->dato<datoslut.dat_Stamp.ds_Days)
          {
            if(usernode=FindName(&userlist,filptr->uploader))
            {
              /* Brugeren fandtes i vores liste, læg filen til hans "score" */
              ((struct usernodetype *)usernode)->bytes+=filptr->siz;
              ((struct usernodetype *)usernode)->files++;
            }
          }
          filptr++;
        }
        /* Find den bedste 10 gange i træk */
        for(i=0;i<10;i++)
        {
          /* Placer markør rigtigt */
          FPrintf(filhandle,"\x1b""[%ld;%ldH",y+i,x);
          /* Find første user = bedste indtil videre */
          traverseringsptr=bestuser=userlist.lh_Head;
          /* Hvis der ikke er flere brugere tilbage, så loop ikke mere, ellers slår det klik */
          if(bestuser->ln_Succ==NULL) break;
          /* Check efter bedre usere */
          while(traverseringsptr->ln_Succ!=NULL)
          {
            if(((struct usernodetype *)traverseringsptr)->bytes>((struct usernodetype *)bestuser)->bytes)
            {
              bestuser=traverseringsptr;
            }
            traverseringsptr=traverseringsptr->ln_Succ;
          }
          /* Udskriv den bedste user vi fandt */
          FPrintf(filhandle,"%-40s",bestuser->ln_Name);
          j=((struct usernodetype *)bestuser)->bytes;
          /* En masse kode, bare for at sætte "," for hver tusind */
          if(j>=1000000)
          {
            FPrintf(filhandle,"%3ld,%03ld,%03ld",j/1000000,j/1000%1000,j%1000);
          }
          else
          {
            if(j>=1000)
            {
              FPrintf(filhandle,"    %3ld,%03ld",j/1000,j%1000);
            }
            else
            {
              FPrintf(filhandle,"        %3ld",j);
            }
          }
          /* Udskriv også hvor mange filer det var i */
          FPrintf(filhandle," %8ld",((struct usernodetype *)bestuser)->files);
          /* Fjern den bedste user vi fandt, han er ligemeget nu.. */
          Remove(bestuser);
          FreeVec(bestuser);
        }
        /* Luk ram:weektop filen */
        Close(filhandle);
        /* Slet listen af usere og deres upload "score" */
        while(userlist.lh_Head->ln_Succ != NULL)
        {
          FreeVec(RemHead(&userlist));
        }
      FreeVec(usermem);
      } else printf("Couldn't open output file. Now beam me up, Scotty.\n");
    }
  FreeVec(filemem);
  }
  return(0);
}
