255)
		$grn = 255;
	if ($grn > 190)
		$fg = 'blue';
	else
		$fg = 'white';
	$bg = sprintf("#00%02x00", $grn);
 }
 else # ($erl > 0.5)
 {
	$red = (-0.3 - log10(1.0 - $erl)) * 255;
	if ($red < 0)
		$red = 0;
	if ($red > 255)
		$red = 255;
	$fg = 'white';
	$bg = sprintf("#%02x0000", $red);
 }
 return array($fg, $bg);
}
#
function pctcolour($pct)
{
 if ($pct == 100)
 {
	$fg = 'white';
	$bg = 'black';
 }
 if ($pct < 100)
 {
	$grn = (2.0 - log10($pct)) * 255;
	if ($grn < 0)
		$grn = 0;
	if ($grn > 255)
		$grn = 255;
	if ($grn > 190)
		$fg = 'blue';
	else
		$fg = 'white';
	$bg = sprintf("#00%02x00", $grn);
 }
 if ($pct > 100)
 {
	$red = (log10(pow($pct,4.0)) - 8.0) / 3.0 * 255;
	if ($red < 0)
		$red = 0;
	if ($red > 255)
		$red = 255;
	$fg = 'white';
	$bg = sprintf("#%02x0000", $red);
 }
 return array($fg, $bg);
}
#
function mthcolour($luck)
{
 if ($luck == 1.0)
 {
	$fg = 'white';
	$bg = 'black';
 }
 else if ($luck > 1.0)
 {
	// 1.0 .. 1.1 (> 1.1 = max)
	$grn = ($luck - 1.0) * 2550.0;
	if ($grn > 255)
		$grn = 255;
	if ($grn < 0)
		$grn = 0;
	if ($grn > 190)
		$fg = 'blue';
	else
		$fg = 'white';
	$bg = sprintf("#00%02x00", $grn);
 }
 else
 {
	// 0.9 .. 1.0 (< 0.9 = max)
	$red = (1.0 - $luck) * 2550.0;
	if ($red > 255)
		$red = 255;
	if ($red < 0)
		$red = 0;
	$fg = 'white';
	$bg = sprintf("#%02x0000", $red);
 }
 return array($fg, $bg);
}
#
function statstable($poolfee, $ans, $data)
{
	if ($ans['STATUS'] != 'ok' or !isset($ans['s_rows']) or $ans['s_rows'] < 1)
		return '';
	$pg = '
Block Statistics
';
	$pg .= "\n";
	$pg .= "";
	$pg .= "| Description | ";
	$pg .= "Time | ";
	$pg .= "MeanTx% | ";
	$pg .= "Diff% | ";
	$pg .= "Mean% | ";
	$pg .= "CDF[Erl] | ";
	$pg .= "Luck% | ";
	$tt = "";
	$tt .= '?';
	$tt .= "";
	$tt .= "Pool PPS%: MeanTx% * Luck% minus the pool fee";
	$pg .= "${tt}PPS% | ";
	$pg .= "
\n";
	$since = $data['info']['lastblock'];
	$count = $ans['s_rows'];
	for ($i = 0; $i < $count; $i++)
	{
		if (($i % 2) == 0)
			$row = 'even';
		else
			$row = 'odd';
		$desc = $ans['s_desc:'.$i];
		$age = daysago($since - $ans['s_prevcreatedate:'.$i]);
		$diff = number_format(100 * $ans['s_diffratio:'.$i], 2);
		$mean = number_format(100 * $ans['s_diffmean:'.$i], 2);
		$cdferl = $ans['s_cdferl:'.$i];
		list($fg, $bg) = erlcolour($cdferl);
		$cdferldsp = "".number_format($cdferl, 4).'';
		$bg = " bgcolor=$bg";
		$luck = number_format(100 * $ans['s_luck:'.$i], 2);
		$txm = number_format(100 * $ans['s_txmean:'.$i], 1);
		$o = number_format((100 - $poolfee) * $ans['s_txmean:'.$i] / $ans['s_diffmean:'.$i], 2);
		$pg .= "";
		$pg .= "| $desc Blocks | ";
		$pg .= "$age | ";
		$pg .= "$txm% | ";
		$pg .= "$diff% | ";
		$pg .= "$mean% | ";
		$pg .= "$cdferldsp | ";
		$pg .= "$luck% | ";
		$pg .= "$o% | ";
		$pg .= "
\n";
	}
	$pg .= "
\n";
	return $pg;
}
#
function monthtable($poolfee, $ans, $limit)
{
	if ($ans['STATUS'] != 'ok' or !isset($ans['rows']) or $ans['rows'] < 1)
		return '';
	$nowmon = intval(gmdate('n', $ans['STAMP']));
	$nowyyyy = intval(gmdate('Y', $ans['STAMP']));
	$pg = 'Monthly Statistics
';
	$pg .= "\n";
	$pg .= "";
	$pg .= "| UTC Month | ";
	$pg .= "Pool Avg | ";
	$pg .= "Blocks | ";
	$pg .= "Expected | ";
	$pg .= "Mean Diff% | ";
	$pg .= "MeanTx% | ";
	$pg .= "Luck% | ";
	$pg .= "PPS% | ";
	$pg .= "
\n";
	$pg .= '';
	$count = $ans['rows'];
	$rout = $bcount = $bcd = $bmon = $byyyy = $bdiffacc = $bdiffratio = $btxn = 0;
	$skipped = false;
	for ($i = 0; $i < $count; $i++)
	{
		$conf = $ans['confirmed:'.$i];
		// Skip leading orphans
		if (!$skipped && ($conf == 'O' || $conf == 'R'))
			continue;
		$skipped = true;
		// If anything is missing, skip this table
		$diffratio = $ans['diffratio:'.$i];
		if ($diffratio == '?')
			break;
		$cd = $ans['firstcreatedate:'.$i];
		$mon = intval(gmdate('n', $cd));
		$yyyy = intval(gmdate('Y', $cd));
		// all orphans after a block must be included with that block
		if (($conf != 'O' && $conf != 'R')
		&&  ($mon != $bmon || $yyyy != $byyyy))
		{
			if ($bcount != 0)
			{
				if (($rout % 2) == 0)
					$row = 'even';
				else
					$row = 'odd';
				if ($bmon == $nowmon && $byyyy == $nowyyyy)
					$dots = '…';
				else
					$dots = '';
				$elap = $bcd - $cd;
				$phr = ($bdiffacc / $elap) * pow(2, 32);
				$phrdsp = siprefmt($phr);
				$name = gmdate('Y M', $bcd);
				$exc = number_format($bdiffratio, 2);
				if ($bdiffratio > $bcount)
					$bcol = 'darkred';
				else
					$bcol = 'darkgreen';
				$md = number_format(100 * $bdiffratio / $bcount, 2);
				$mr = number_format(100 * $btxn / $bcount, 2);
				$ml = $bcount / $bdiffratio;
				$mldsp = number_format(100 * $ml, 2);
				$oa = (100 - $poolfee) * ($bcount / $bdiffratio) * ($btxn / $bcount);
				$odsp = number_format($oa, 2);
				list($fg, $bg) = mthcolour($ml);
				$pg .= "";
				$pg .= "| $name$dots | ";
				$pg .= "${phrdsp}Hs | ";
				$pg .= "$bcount | ";
				$pg .= "$exc | ";
				$pg .= "$md% | ";
				$pg .= "$mr% | ";
				$pg .= "$mldsp% | ";
				$pg .= "$odsp% | ";
				$pg .= "
\n";
				$rout++;
			}
			if ($rout > $limit)
				break;
			$bcd = $cd;
			$bmon = $mon;
			$byyyy = $yyyy;
			$bcount = $bdiffacc = $bdiffratio = $btxn = 0;
		}
		$bdiffratio += floatval($ans['diffratio:'.$i]);
		$bdiffacc += floatval($ans['diffacc:'.$i]);
		if ($conf != 'O' and $conf != 'R')
		{
			$height = $ans['height:'.$i];
			$reward = floatval($ans['reward:'.$i]);
			$re = 5000000000.0 * pow(0.5, floor($height / 210000.0));
			$btxn += $reward / $re;
			$bcount++;
		}
	}
	$pg .= '
';
	return $pg;
}
#
function doblocks($data, $user)
{
 $blink = '= 0; $i--)
	{
		$conf = $ans['confirmed:'.$i];
		$diffratio = $ans['diffratio:'.$i];
		if ($diffratio > 0)
		{
			$colpct += 100.0 * $diffratio;
			$ans['colpct:'.$i] = $colpct;
			if ($conf != 'O' and $conf != 'R')
				$colpct = 0;
		}
	}
	for ($i = 0; $i < $count; $i++)
	{
		if (($i % 2) == 0)
			$row = 'even';
		else
			$row = 'odd';
		$hi = $ans['height:'.$i];
		$hifld = "$blink$hi>$hi";
		$ex = '';
		$conf = $ans['confirmed:'.$i];
		$stat = $ans['status:'.$i];
		$inf = $ans['info:'.$i];
		$tt = '';
		if ($conf == 'O' or $conf == 'R')
		{
			$ex = 's';
			$orph = true;
			$seq = '';
			$nn = $cnt;
			if ($conf == 'R')
			{
				addTips();
				$in = explode(':', $inf, 2);
				if (trim($in[0]) != '')
					$stat = trim($in[0]);
				if (count($in) < 2 or trim($in[1]) == '')
				{
					$tip = 'Share diff was VERY close
';
					$tip .= 'so we tested it,
';
					$tip .= "but it wasn't worthy
";
				}
				else
					$tip = str_replace('+', '
', trim($in[1]));
				$tt = "";
				$tt .= '?';
				$tt .= "";
				$tt .= "$tip";
			}
		}
		else
		{
			$seq = $ans['seq:'.$i];
			$nn = ++$cnt;
		}
		if ($conf == '1')
		{
			if (isset($data['info']['lastheight']))
			{
				$confn = 1 + $data['info']['lastheight'] - $hi;
				$stat = '+'.$confn.' Confirms';
			}
			else
				$stat = 'Conf';
		}
		$stara = '';
		if ($conf == 'O' or $conf == 'R')
			$stara = '*';
		if (isset($ans['statsconf:'.$i]))
		{
			if ($ans['statsconf:'.$i] == 'Y')
				$approx = '';
			else
				$approx = '~';
		}
		else
			$approx = '';
		$diffacc = $ans['diffacc:'.$i];
		$acc = number_format($diffacc, 0);
		$netdiff = $ans['netdiff:'.$i];
		$diffratio = $ans['diffratio:'.$i];
		$cdf = $ans['cdf:'.$i];
		$luck = $ans['luck:'.$i];
		$hist = $ans['luckhistory:'.$i];
		if ($diffratio > 0)
		{
			$pct = 100.0 * $diffratio;
			$colpct = $ans['colpct:'.$i];
			if ($conf != 'O' and $conf != 'R')
			{
				list($fg, $bg) = pctcolour($colpct);
				$bpct = "$approx".number_format($pct, 3).'%';
				$bg = " bgcolor=$bg";
				$histdsp = "$approx".number_format(100.0 * $hist, 2).'%';
			}
			else
			{
				$bpct = "$approx".number_format($pct, 3).'%';
				$bg = '';
				$histdsp = ' ';
			}
			$blktot += $diffacc;
			if ($conf != 'O' and $conf != 'R')
				$nettot += $netdiff;
			$cdfdsp = number_format($cdf, 3);
		}
		else
		{
			$bg = '';
			$bpct = '?';
			$cdfdsp = '?';
			$histdsp = '?';
		}
		if ($wantcsv === false)
		{
		 $pg .= "";
		 $pg .= "| $seq | ";
		 $pg .= "$hifld | ";
		 if ($user !== null)
		 {
			list($abr, $nam) = dspname($ans['workername:'.$i]);
			$pg .= "$nam | ";
		 }
		 $pg .= "".btcfmt($ans['reward:'.$i]).' | ';
		 $pg .= "".utcd($ans['firstcreatedate:'.$i], false, false).' | ';
		 $pg .= "$tt$stat | ";
		 $pg .= "$stara$approx$acc | ";
		 $pg .= "$bpct | ";
		 $pg .= "$cdfdsp | ";
		 $pg .= "$histdsp | ";
		 $pg .= "$nn | ";
		 $pg .= "
\n";
		}
		else
		{
		 $csv .= "$seq,";
		 $csv .= "$hi,";
		 $csv .= "\"$stat\",";
		 $csv .= $ans['firstcreatedate:'.$i].',';
		 $csv .= "$diffacc,";
		 $csv .= "$netdiff,";
		 $csv .= $ans['blockhash:'.$i]."\n";
		}
	}
	$pg .= '';
 }
 if ($wantcsv === true)
 {
	echo $csv;
	exit(0);
 }
 if ($orph === true)
 {
	$pg .= '| 
 |