/* compute change in go rating following EGF (cieply) */
/* compile using  cc -Wall gorating.c -o gorating -lm  */
#include <stdio.h>
#include <stdlib.h>
#include <math.h>

double
get_a(int rating) {
	double r = rating;

	if (r < 100.0)
		return 200.0;
	if (r < 2700.0)
		return 205.0 - r/20;
	return 70.0;
}

double
get_con(int rating) {
	double r = rating;

	if (r < 100.0)
		return 116.0;
	if (r < 200.0)
		return 116.0 - (r-100.0) * 0.06;
	if (r < 1300.0)
		return 110.0 - (r-200.0) * 0.05;
	if (r < 2000.0)
		return 55.0 - (r-1300.0) * 0.04;
	if (r < 2400.0)
		return 27.0 - (r-2000.0) * 0.03;
	if (r < 2600.0)
		return 15.0 - (r-2400.0) * 0.02;
	if (r < 2700.0)
		return 11.0 - (r-2600.0) * 0.01;
	return 10.0;
}

/* expectation to win, when the other player has a strength
   that is diff higher */
double
expectancy(int diff, double a) {
	return 1.0 / (1.0 + exp(diff / a));
}

double
expectrr(int r1, int r2) {
	if (r1 <= r2)
		return expectancy(r2-r1, get_a(r1));
	else
		return 1-expectancy(r1-r2, get_a(r2));
}

int
min(int a, int b) {
	if (a < b) return a;
	return b;
}

int
main(int argc, char **argv){
	int oldr, ropp;
	double d, dtot, e;

	if (argc < 2) {
		fprintf(stderr, "call: %s oldr +r1 +r2 -r3 -r4 ...\n",
			argv[0]);
		fprintf(stderr,
			"where r1, r2 are ratings of beaten opponents\n");
		fprintf(stderr,
			"and r3, r4 are ratings of opponents that won\n");
		exit(1);
	}

	oldr = atoi(argv[1]);
	printf("Old rating: %d\n", oldr);

	argc -= 2;
	argv += 2;
	dtot = 0.0;
	while (argc) {
		if (argv[0][0] == '+') {
			ropp = atoi(argv[0]+1);
			e = expectrr(oldr, ropp);
			d = get_con (oldr) * (1-e);
			dtot += d;
			printf(" won against %d - prob %2.0f%% - gains %.1f\n",
			       ropp, 100*e, d);
		} else if (argv[0][0] == '-') {
			ropp = atoi(argv[0]+1);
			e = expectrr(oldr, ropp);
			d = get_con (oldr) * e;
			dtot -= d;
			printf("lost against %d - prob %2.0f%% - loses %.1f\n",
			       ropp, 100*(1-e), d);
		} else {
			fprintf(stderr, "bad option\n");
			exit(1);
		}
		argc--;
		argv++;
	}
	printf("New rating: %.1f\n", oldr+dtot);
	return 0;
}
