/*
 * Copyright (c) 1995 Sun Microsystems, Inc.
 * All rights reserved.
 * 
 * Permission is hereby granted, without written agreement and without
 * license or royalty fees, to use, copy, modify, and distribute this
 * software and its documentation for any purpose, provided that the
 * above copyright notice and the following two paragraphs appear in
 * all copies of this software.
 * 
 * IN NO EVENT SHALL SUN MICROSYSTEMS, INC. BE LIABLE TO ANY PARTY FOR
 * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING
 * OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF SUN
 * MICROSYSTEMS, INC. HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 * 
 * SUN MICROSYSTEMS, INC. SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
 * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT.  THE SOFTWARE PROVIDED
 * HEREUNDER IS ON AN "AS IS" BASIS, AND SUN MICROSYSTEMS, INC. HAS NO
 * OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR
 * MODIFICATIONS.
 */

#include <stdio.h>
#include <tcl.h>
#include <tk.h>
#include "doomarena.h"

#define K 10.0
#define N 100000.0

static double
CalcFactor(double r1, double r2)
{
  double diff, diff2, factor;

  diff = r1 - r2;
  diff2 = diff * diff;

  if (diff >= 0.0) {
    factor = K * (N / (diff2 + N));
  }
  else {
    factor = (K/2) * (2 - (N / (diff2 + N)));
  }

  return factor;
}

int
DoomStatsCmd(ClientData clientData, Tcl_Interp *interp,
	     int argc, char **argv)
{
  char buf[64];
  char **players, **infostr;
  char *val;
  int numPlayers, infolen;
  int i, j, k, max, frags, deaths;
  double rankings[4];
  double rankingsIncr[4];
  int info[4][4];

  if (argc != 4) {
    printf(interp->result,
	   "wrong # args: should be \"%s players info rankings\"",
	   argv[0]);
    return TCL_ERROR;
  }

  if (Tcl_SplitList(interp, argv[1], &numPlayers, &players) != TCL_OK)
    return TCL_ERROR;

  /* Read info */
  max = 0;
  for (i=0; i<numPlayers; i++) {
    sprintf(buf, "%d", i);
    val = Tcl_GetVar2(interp, argv[2], buf, NULL);
    if (!val) {
      sprintf(interp->result, "bad info array: \"%s\" not found",
	      buf);
      free(players);
      return TCL_ERROR;
    }

    if (Tcl_SplitList(interp, val, &infolen, &infostr) != TCL_OK) {
      free(players);
      return TCL_ERROR;
    }

    if (infolen != numPlayers) {
      sprintf(interp->result, "wrong number of info elements: \"%s\"",
	      players[i]);
      free(players);
      return TCL_ERROR;
    }

    for (j=0; j<infolen; j++) {
      if (Tcl_GetInt(interp, infostr[j], &info[i][j]) != TCL_OK)
	return TCL_ERROR;
      if (max < info[i][j]) {
	max = info[i][j];
      }
    }
  }

  /* Read rankings */
  for (i=0; i<numPlayers; i++) {
    val = Tcl_GetVar2(interp, argv[3], players[i], NULL);
    if (!val) {
      rankings[i] = 1000;
    }
    else {
      if (Tcl_GetDouble(interp, val, &rankings[i]) != TCL_OK) {
	free(players);
	return TCL_ERROR;
      }
    }
  }

  for (i=0; i<max; i++) {
    memset(&rankingsIncr, 0, 4 * sizeof(double));

    for (j=0; j<numPlayers; j++) {
      for (k=0; k<numPlayers; k++) {
	frags = info[j][k];
	deaths = info[k][j];
	if (i < frags) {
	  rankingsIncr[j] += CalcFactor(rankings[j], rankings[k]);
	}
	if (i < deaths) {
	  rankingsIncr[j] -= CalcFactor(rankings[k], rankings[j]);
	}
      }
    }

    for (j=0; j<numPlayers; j++) {
      rankings[j] += rankingsIncr[j];
    }
  }

  for (i=0; i<numPlayers; i++) {
    sprintf(buf, "%f", rankings[i]);
    Tcl_SetVar2(interp, argv[3], players[i], buf, NULL);
  }

  free(players);
  return TCL_OK;
}
