#include <stdio.h>
#include <strings.h>
#include <stdlib.h>

#define BOOL int
#define TRUE 1
#define FALSE 0

struct SYSTEM {
    char sName[5];
    char sAuthor[40];
    char sURL[80];
    char sSite[80];
    char* pRank;
} g_systems[32];

struct TEAM {
    char sName[17];
    int nSumRanks;
    int nTop30;
    int nTop10;
    int nTop5;
    int nTop1;
    int nRanks[32];   // for median
    double dMedian;
    double dRating;
} *g_teams[1024];

void main() {
    FILE *pfIn, *pfOut;
    char sLine[4096], sDate[4096];
    int nSystems = 0, nTeams = 0, nSystemsFound = 0;
    int iSystem, iTeam;
    char *pLine, *pSrc, *pDest, *pTeam, ch;
    BOOL bInTag, bRepeat;
    struct TEAM *team;
    int nLine = 0;

    pfIn = fopen("systems.txt","r");
    while(fgets(sLine,sizeof sLine,pfIn)) {
        if(strlen(sLine) >= 6) {
            sLine[strlen(sLine)-1] = 0;
            switch(nLine++) {
                case 0:
                    strncpy(g_systems[nSystems].sName,sLine,4);
                    g_systems[nSystems].sName[4] = 0;
                    strcpy(g_systems[nSystems].sAuthor,sLine+4);
                    g_systems[nSystems].pRank = NULL;
                    g_systems[nSystems].sSite[0] = 0;
                    g_systems[nSystems].sURL[0] = 0;
                    nSystems++;
                    break;
                case 1:
                    strcpy(g_systems[nSystems-1].sSite,sLine);
                    break;
                case 2:
                    strcpy(g_systems[nSystems-1].sURL,sLine);
                    break;
            }
        } else nLine = 0;
    }
    fclose(pfIn);
    
    pfIn = fopen("compare.htm","r");
    sDate[0] = 0;
    while(fgets(sLine,sizeof sLine,pfIn)) {
        if(!strncmp(sLine,"<h3>",4)) {
            char* sEnd = strstr(sLine," (");
            if(sEnd) {
                int nLen = sEnd - sLine - 4;
                strncpy(sDate,sLine+4,nLen);
                sDate[nLen] = 0;
                break;
            }
        }
    }
    while(fgets(sLine,sizeof sLine,pfIn)) {
        if(!strncmp(sLine,"<font color=\"#0080FF\">",22)) {
            for(iSystem=0; iSystem<nSystems; iSystem++) {
                pLine = strstr(sLine+22,g_systems[iSystem].sName);
                if(pLine) {
                    nSystemsFound++;
                    g_systems[iSystem].pRank = pLine - 22;
                }
            }
            pTeam = strstr(sLine+22,"Rank, Team") - 22;
            break;
        }
    }
    printf("%d of %d systems found on Kenneth Massey's page for %s\n",
     nSystemsFound,nSystems,sDate);
    while(fgets(sLine,sizeof sLine,pfIn)) {
        if(!strncmp(sLine,"----------",10)) break;
        if(!strncmp(sLine,"<font color=\"#0080FF\">",22)) continue;
        if(!strcmp(sLine,"\n")) continue;
        pSrc = sLine;  // remove <...> from line
        pDest = sLine;
        bInTag = FALSE;
        while(ch = *pSrc++) {
            if(bInTag) {
                if(ch == '>') bInTag = FALSE;
            } else {
                if(ch == '<') bInTag = TRUE;
                else *pDest++ = ch;
            }
        }
        *pDest = 0;
        g_teams[nTeams] = (struct TEAM*) malloc(sizeof(struct TEAM));
        strncpy(g_teams[nTeams]->sName,pTeam,16);
        g_teams[nTeams]->sName[16] = 0;
        g_teams[nTeams]->nSumRanks = 0;
        g_teams[nTeams]->nTop30 = 0;
        g_teams[nTeams]->nTop10 = 0;
        g_teams[nTeams]->nTop5 = 0;
        g_teams[nTeams]->nTop1 = 0;
        int mSystems = 0, jSystem;
        for(iSystem=0; iSystem<nSystems; iSystem++) {
            if(g_systems[iSystem].pRank) {
                int nRank = atoi(g_systems[iSystem].pRank);
                if(nRank > 30 && nTeams < 15) printf(
                 "Suspicious ranking: %s ranks %s as #%d\n",
                  g_systems[iSystem].sAuthor,g_teams[nTeams]->sName,nRank);
                if(nRank <= 30) g_teams[nTeams]->nTop30++;
                if(nRank <= 10) g_teams[nTeams]->nTop10++;
                if(nRank <= 5) g_teams[nTeams]->nTop5++;
                if(nRank <= 1) g_teams[nTeams]->nTop1++;
                g_teams[nTeams]->nSumRanks += nRank;
                // insert rank in list with insertion sort
                jSystem = mSystems-1;
                while(jSystem >= 0 &&
                 g_teams[nTeams]->nRanks[jSystem] > nRank) {
                  g_teams[nTeams]->nRanks[jSystem+1] = 
                   g_teams[nTeams]->nRanks[jSystem];
                  jSystem--;
                }
                g_teams[nTeams]->nRanks[jSystem+1] = nRank;
                mSystems++;
            }
        }
        nTeams++;
    }
    fclose(pfIn);

    pfOut = fopen("index.shtml","w");

    pfIn = fopen("start.htm","r");
    while(fgets(sLine,sizeof sLine,pfIn)) {
        if(!strcmp(sLine,"DATE\n")) fprintf(pfOut,"%s (%d systems)\n",
         sDate,nSystemsFound);
        else if(!strcmp(sLine,"LIST\n")) {
            for(iSystem=0;iSystem<nSystems;iSystem++) {
                fprintf(pfOut," <li><font face=\"Arial\" size=\"4\"><a href=\""
                 "%s\">%s</a> - %s",
                 g_systems[iSystem].sURL,g_systems[iSystem].sAuthor,
                 g_systems[iSystem].sSite);
               if(!g_systems[iSystem].pRank)
                fputs(" <font color=\"red\">Data missing</font>",pfOut);
               fputs("</font></li>\n",pfOut);
            }
        } else fputs(sLine,pfOut);
    }
    fclose(pfIn);

    for(iTeam=0; iTeam<nTeams; iTeam++) {  // calculate ratings
        g_teams[iTeam]->dMedian =
         (g_teams[iTeam]->nRanks[nSystemsFound/2] + 
          g_teams[iTeam]->nRanks[(nSystemsFound-1)/2]) / 2.0;
        g_teams[iTeam]->dRating =
         101.0 - (g_teams[iTeam]->nSumRanks/(double)nSystemsFound +
          g_teams[iTeam]->dMedian)/2.0;
    }

    do {  // sort the teams
        bRepeat = FALSE;
        for(iTeam=1; iTeam<nTeams; iTeam++) {
            if(g_teams[iTeam-1]->dRating < g_teams[iTeam]->dRating) {
                if(iTeam <= 30) 
                 printf("Switch %2d %s%7.3f and %s%7.3f\n",iTeam,
                 g_teams[iTeam-1]->sName,g_teams[iTeam-1]->dRating,
                 g_teams[iTeam  ]->sName,g_teams[iTeam  ]->dRating);
                team = g_teams[iTeam-1];
                g_teams[iTeam-1] = g_teams[iTeam];
                g_teams[iTeam] = team;
                bRepeat = TRUE;
            }
        }
    } while(bRepeat);
    
    for(iTeam=0; iTeam<nTeams; iTeam++) {  // output the teams
        double dAverage = g_teams[iTeam]->nSumRanks/(double)nSystemsFound;
        fprintf(pfOut,"%4d %s%7.3f%9.3f%7.1f%6d%6d%5d%5d\n",
         iTeam+1,g_teams[iTeam]->sName,
         g_teams[iTeam]->dRating,dAverage,
         g_teams[iTeam]->dMedian,g_teams[iTeam]->nTop30,
         g_teams[iTeam]->nTop10,g_teams[iTeam]->nTop5,g_teams[iTeam]->nTop1);
    }

    pfIn = fopen("end.htm","r");
    while(fgets(sLine,sizeof sLine,pfIn)) {
        if(!strcmp(sLine,"LIST\n")) {
            for(iSystem=0;iSystem<nSystems;iSystem++) {
                fprintf(pfOut,"<p><font face=\"Arial\" size=\"4\">%s",
                 g_systems[iSystem].sSite);
               if(!g_systems[iSystem].pRank)
                fputs(" <font color=\"red\">Data missing</font>",pfOut);
               fprintf(pfOut,"<br>\n%s</font></p>\n",g_systems[iSystem].sURL);
            }
        } else fputs(sLine,pfOut);
    }
    fclose(pfIn);

    fclose(pfOut);
}

