1<?php 2// scorechart.php -- HotCRP chart generator 3// Copyright (c) 2006-2018 Eddie Kohler; see LICENSE. 4 5// Generates a PNG image of a bar chat. 6// Arguments are passed in as v; s is graph style. 7// Don't forget to change the width and height calculations in 8// ReviewField::unparse_graph if you change the width and height here. 9 10if (!isset($_GET["v"])) { 11 header("HTTP/1.0 400 Bad Request"); 12 exit; 13} 14 15// fail if no GD support so the browser displays alt text 16if (!function_exists("imagecreate")) { 17 require_once("src/init.php"); 18 Dbl::q("insert into Settings set name='__gd_required', value=1 on duplicate key update value=1"); 19 header("HTTP/1.0 503 Service Unavailable"); 20 exit; 21} 22 23// parse values 24$s = (isset($_GET["s"]) ? $_GET["s"] : 0); 25if ($s != 0 && $s != 1 && $s != 2) 26 $s = 2; 27$valMax = 1; 28$values = array(); 29$maxY = $sum = 0; 30foreach (explode(",", $_GET["v"]) as $value) { 31 $value = (ctype_digit($value) && $value > 0 ? intval($value) : 0); 32 $values[$valMax++] = $value; 33 $maxY = max($value, $maxY); 34 $sum += $value; 35} 36if (isset($_GET["h"]) && is_numeric($_GET["h"])) 37 $valLight = intval($_GET["h"]); 38else 39 $valLight = 0; 40if ($valLight < 1 || $valLight >= $valMax) 41 $valLight = 0; 42$levelChar = (isset($_GET["c"]) && ord($_GET["c"]) >= 65 43 ? ord($_GET["c"]) : 0); 44 45 46// set shape constants 47if ($s == 0) { 48 list($blockHeight, $blockWidth, $blockSkip, $blockPad, $textWidth) 49 = array(8, 8, 2, 4, 12); 50} else if ($s == 1) { 51 list($blockHeight, $blockWidth, $blockSkip, $blockPad, $textWidth) 52 = array(3, 3, 2, 2, 0); 53} 54 55if ($s == 0 || $s == 1) { 56 $maxY = max($maxY, 3); 57 $picWidth = ($blockWidth + $blockPad) * ($valMax - 1) 58 + $blockPad 59 + 2 * $textWidth; 60 $picHeight = $blockHeight * $maxY + $blockSkip * ($maxY + 1); 61 $pic = @imagecreate($picWidth + 1, $picHeight + 1); 62} else if ($s == 2) { 63 $picWidth = 64; 64 $picHeight = 8; 65 $pic = @imagecreate($picWidth, $picHeight); 66} 67 68$cWhite = imagecolorallocate($pic, 255, 255, 255); 69$cBlack = imagecolorallocate($pic, 0, 0, 0); 70$cgray = imagecolorallocate($pic, 190, 190, 255); 71 72if ($s == 0) { 73 imagefilledrectangle($pic, 0, 0, $picWidth + 1, $picHeight + 1, $cBlack); 74 imagefilledrectangle($pic, 1, 1, $picWidth - 1, $picHeight - 1, $cWhite); 75} else if ($s == 1) { 76 imagecolortransparent($pic, $cWhite); 77 imagefilledrectangle($pic, 0, $picHeight, $picWidth + 1, $picHeight + 1, $cgray); 78 imagefilledrectangle($pic, 0, $picHeight - $blockHeight - $blockPad, 0, $picHeight + 1, $cgray); 79 imagefilledrectangle($pic, $picWidth, $picHeight - $blockHeight - $blockPad, $picWidth + 1, $picHeight + 1, $cgray); 80} 81 82$cv_black = array(0, 0, 0); 83$cv_bad = array(200, 128, 128); 84$cv_good = array(0, 232, 0); 85function quality_color($c1, $c2, $f) { 86 return array($c2[0] * $f + $c1[0] * (1 - $f), 87 $c2[1] * $f + $c1[1] * (1 - $f), 88 $c2[2] * $f + $c1[2] * (1 - $f)); 89} 90 91$pos = 0; 92 93for ($value = 1; $value < $valMax; $value++) { 94 $vpos = ($levelChar ? $valMax - $value : $value); 95 $height = $values[$vpos]; 96 $frac = ($vpos - 1) / ($valMax - 1); 97 $cv_cur = quality_color($cv_bad, $cv_good, $frac); 98 $cFill = imagecolorallocate($pic, $cv_cur[0], $cv_cur[1], $cv_cur[2]); 99 100 if ($s == 0 || $s == 1) { 101 $curX = $blockWidth * ($value - 1) 102 + $blockPad * $value + $textWidth; 103 $curY = $picHeight - ($blockHeight + $blockSkip) * $height + $blockHeight; 104 105 for ($h = 1; $h <= $height; $h++) { 106 if ($h == $height && $vpos == $valLight) { 107 $cv_cur = quality_color($cv_black, $cv_cur, 0.5); 108 $cFill = imagecolorallocate($pic, $cv_cur[0], $cv_cur[1], $cv_cur[2]); 109 } 110 imagefilledrectangle($pic, $curX, $curY - $blockHeight, 111 $curX + $blockWidth, $curY, $cFill); 112 $curY += ($blockHeight + $blockSkip); 113 } 114 } else { 115 if ($height > 0) 116 imagefilledrectangle($pic, ($picWidth + 1) * $pos / $sum, 0, 117 ($picWidth + 1) * ($pos + $height) / $sum - 2, $picHeight, 118 $cFill); 119 $pos += $height; 120 } 121} 122 123if ($s == 0) { 124 imagestringup($pic, 2, 0, 30, "Bad", $cBlack); 125 imagestringup($pic, 2, $picWidth-$textWidth, 30, "Good", $cBlack); 126 } else if ($s == 1) { 127 $lx = $textWidth + $blockPad; 128 $rx = $picWidth - $blockWidth - $textWidth - $blockPad; 129 $y = $picHeight - $blockHeight - $blockSkip - 3; 130 if (isset($_GET["c"]) && ord($_GET["c"]) >= 65) { 131 if ($values[1] == 0) 132 imagestring($pic, 1, $rx, $y, $_GET["c"], $cgray); 133 if ($values[$valMax - 1] == 0) 134 imagestring($pic, 1, $lx, $y, chr(ord($_GET["c"]) - $valMax + 2), $cgray); 135 } else { 136 if ($values[1] == 0) 137 imagestring($pic, 1, $lx, $y, 1, $cgray); 138 if ($values[$valMax - 1] == 0) 139 imagestring($pic, 1, $rx, $y, $valMax - 1, $cgray); 140 } 141} 142 143session_cache_limiter(""); 144header("Cache-Control: max-age=31557600, public"); 145header("Expires: " . gmdate("D, d M Y H:i:s", time() + 31557600) . " GMT"); 146header("Content-Type: image/png"); 147imagepng($pic); 148exit(); 149