#ifdef SMURF
 #define Assert assert
#else
 #include <stdio.h>
 #include <math.h>
 #include <assert.h>
 #define Assert(b,s) assert(b)
#endif

void TrialInit(void);
void TrialStat(int oldCC, int CCounter, int accessDelay);
void TrialAllDone(void);

#if TEST_MAIN
int main()
{
	static int oldCC, CCounter, attemptSpace, accessDelay;
	TrialInit();

	while(1)
	{
		static char buf[1024], garbage[255];
		oldCC = CCounter;

		if(!fgets(buf, sizeof(buf), stdin))
			break;

		if(sscanf(buf, "%s %s %d %d", garbage, garbage, &CCounter, &attemptSpace) != 4 || attemptSpace < 0)
			continue;

		if(CCounter == 0 && oldCC == 0 )
			/* nothing */;
		else if(oldCC == 0 )
			accessDelay = 0;
		else
			accessDelay += attemptSpace;
		TrialStat(oldCC, CCounter, accessDelay);
	}

	TrialAllDone();
	return 0;
}
#endif

#define DECADES 6
#define START2 100
#define LIM2 60
#define START4 220
#define LIM4 120
#define START8 456
#define STEPSIZE 188
#define SAMPLESIZE 20
#define UPPER_LIMIT (STEPSIZE*DECADES)

typedef LimArray[UPPER_LIMIT +1];
static LimArray limit, trys, wins, lost;
static int immediateWins, allwins, maxCC;

int IntPow10(int n)
{
	int result = 1;
	while(n--)
		result *= 10;
	return result;
}

void TrialInit(void)
{
	int i,j;
	limit [0] = 100;
	trys [0] = 0;
	wins [0] = 0;

	printf("UPPER_LIMIT = %d\n", UPPER_LIMIT);
	for(i=0; i < DECADES; i++)
	{
	    for(j = 1; j <= STEPSIZE; j++)
		{
			const k = i * STEPSIZE + j;
			trys [k] = 0;
			wins [k] = 0;
			lost [k] = 0;
			if(j <= LIM2)
				limit [k] = (START2 + 2 * j) * IntPow10(i);
			else if(j <= LIM4)
				limit [k] = (START4 + 4 * (j - LIM2)) * IntPow10(i);
			else
				limit [k] = (START8 + 8 * (j - LIM4)) * IntPow10(i);
			/*printf("%d %d\n", k, limit[k]);*/
		}
	}
}


void TrialStat(int oldCC, int CCounter, int accessDelay)
{
	if(CCounter == 0 && oldCC == 0 )
		immediateWins ++;
	else if(oldCC == 0 )
	{
		Assert(CCounter == 1, "oldCC == 0 but CCounter != 1");
		Assert(accessDelay == 0, "oldCC=0 but accessDelay != 0");
	}
	else
	{
		int bin;
		if(CCounter > maxCC )
			maxCC = CCounter;

		Assert(oldCC > 0, "compiler bug");
		if(accessDelay < limit[1])
		{
#if SMURF
			cerr << "accessDelay < 100: " << accessDelay << "\n";
#endif
			Assert(accessDelay >= limit [1], "access delay impossibly small");
		}

		if(accessDelay >= limit [UPPER_LIMIT] )
			bin = UPPER_LIMIT;
		else
		{
			int decade = 0;
			bin = 0;
			while(!(bin + STEPSIZE >= UPPER_LIMIT
					|| accessDelay <= limit [bin + STEPSIZE]))
			{
				bin += STEPSIZE;
				decade += 1;
			}

			Assert(accessDelay > limit [bin] &&
				accessDelay <= limit [bin + STEPSIZE],
				"improper decade selection");
			if(accessDelay <= limit [bin + LIM2] )
				bin += (int)ceil ( (accessDelay - START2 * IntPow10(decade)) /
					(2 * IntPow10(decade)));
			else if(accessDelay <= limit [bin + LIM4] )
				bin += (int)ceil(LIM2 + (accessDelay - START4*IntPow10(decade)) /
					(4 * IntPow10(decade)));
			else
				bin += (int)ceil (LIM4 + (accessDelay - START8*IntPow10(decade)) /
					(8 * IntPow10(decade)));

			/*
			** Try to correct off-by-1 bin errors
			*/
			if(bin > 0 && accessDelay <= limit[bin-1])
				bin--;
			else if(bin < UPPER_LIMIT && accessDelay > limit[bin])
				bin++;

			Assert(bin <= UPPER_LIMIT, "bin too high");
			Assert(bin > 0 && accessDelay > limit [bin - 1],
				"accessDelay > limit [bin - 1]");
			Assert(accessDelay <= limit [bin], "accessDelay <= limit [bin]");
		}

		if(CCounter == 0 )
		{
			trys [bin] += 1;
			wins [bin] += 1;
			allwins += 1;
		}
		else
			trys [bin] += 1;
	}
}


void TrialAllDone(void)
{
	int k;

	printf("%d out of %d packets had no collisions.  Largest CCounter was: %d\n",
		immediateWins, immediateWins + allwins, maxCC);
	puts("Of those that did, here are prob[left], prob[try now], and prob[succeed]");
	for(k = 1; k <= UPPER_LIMIT; k++)
	{
		if(trys [k] > 0 || wins [k] > 0 || lost[k] > 0)
			printf("%d %d %d %d\n",  limit [k], trys [k], wins [k], lost [k]);
	}
	fflush(stdout);
}

