Created
August 19, 2017 11:51
-
-
Save pmeulen/69c48b702407cf1a915b4e048670669a to your computer and use it in GitHub Desktop.
Making random opaque strings much more easy to compare by giving them a backgroud color that is derived from the value of the sring
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/** Making opaque values like GUIDs or session identifiers easier to compare and distinguish | |
* | |
* By giving each opaque value a background color that is derived from the value itself, it | |
* becomes much easier to eyeball whether two values are likely to be the same. This really helps | |
* when reading logs or other diagnostic output that contain opaque identifiers like GUIDs or other | |
* opaque identifiers. | |
* | |
* Testing: | |
* - Start PHP buildin webserver: php -S 127.0.0.1:8080 | |
* - browse to http://127.0.0.1:8080/HTMLColorFingerprint.php | |
*/ | |
/** Derive a HTML color from a string value | |
* | |
* The same string value will always generate the same color. The returned color is suitable for use | |
* as a background color for text on a light (white) background with dark (black) text. | |
* | |
* @param string $value The value to fingerprint | |
* @return string HTML hexadecimal RGB color format: #RRGGBB | |
*/ | |
function HTMLColorFingerprint($value) | |
{ | |
// We want to generate a color that is suitable to use as a background color on a light (white) | |
// background for black text, so we want a to pick color with both a minimum and maximum brightness | |
// so there is enough contrast between the back text and the background color, and the coloring is | |
// still visible. | |
// Pick a random color in the Hue, Saturation and Lightness (HSL) color space | |
// with a Lightness value between minL and maxL | |
$minL = 50.0 / 100.0; // 0 .. 1 | |
$maxL = 80.0 / 100.0; // 0 .. 1 | |
// Since the md5 mixes the bits of $value into the fingerprint that it returns, we arbitrarily cut | |
// three 4 digit hex numbers (0..65535) from the md5 fingerprint and scale them to appropriate values | |
// for H, S and L | |
$hexFingerprint=md5($value); // 32 character hex string | |
$h = (1.0 / 65535.0) * intval(substr($hexFingerprint, 0, 4), 16); // 0 .. 1 | |
$s = (1.0 / 65535.0) * intval(substr($hexFingerprint, 4, 4), 16); // 0 .. 1 | |
$l = $minL + $maxL * (1.0-$minL) * (1.0 / 65535.0) * intval(substr($hexFingerprint, 8, 4), 16); // $minLightness .. 100 (%) | |
// Convert from HSL to Red, Green and Blue (RGB) color space | |
// Source: https://stackoverflow.com/questions/20423641/php-function-to-convert-hsl-to-rgb-or-hex | |
$r=$l; $g=$l; $b=$l; | |
$v = ($l <= 0.5) ? ($l * (1.0 + $s)) : ($l + $s - $l * $s); | |
if ($v > 0){ | |
$m = $l + $l - $v; | |
$sv = ($v - $m ) / $v; | |
$h *= 6.0; | |
$sextant = floor($h); | |
$fract = $h - $sextant; | |
$vsf = $v * $sv * $fract; | |
$mid1 = $m + $vsf; | |
$mid2 = $v - $vsf; | |
switch ($sextant) { | |
case 0: | |
$r = $v; $g = $mid1; $b = $m; | |
break; | |
case 1: | |
$r = $mid2; $g = $v; $b = $m; | |
break; | |
case 2: | |
$r = $m; $g = $v; $b = $mid1; | |
break; | |
case 3: | |
$r = $m; $g = $mid2; $b = $v; | |
break; | |
case 4: | |
$r = $mid1; $g = $m; $b = $v; | |
break; | |
case 5: | |
$r = $v; $g = $m; $b = $mid2; | |
break; | |
} | |
} | |
// Convert from RGB values (0 .. 1) to hex (00 .. FF) | |
$color='#' .str_pad(dechex($r*256),2,'0',STR_PAD_LEFT) | |
.str_pad(dechex($g*256),2,'0',STR_PAD_LEFT) | |
.str_pad(dechex($b*256),2,'0',STR_PAD_LEFT); | |
return $color; | |
} | |
/** Generate a HTML test page with random text with random hex nonces injected that | |
* are can be colored with HTMLColorFingerprint() | |
*/ | |
echo "<!doctype HTML><html><body><h1>Can you spot which values are the same?</h1>"; | |
$plain = ($_REQUEST['plain'] == 1) ? 1 : 0; | |
$seed = intval($_REQUEST['seed']); | |
echo "Colors "; | |
echo $plain ? "<a href='?plain=0&seed=$seed'>on</a> <b>off</b></a>" : "<b>on</b> <a href='?plain=1&seed=$seed'>off</a>"; | |
echo "<br />Seed"; | |
for ($i=0;$i<20;$i++) { | |
if ($i==$seed) | |
echo " <b>$seed</b>"; | |
else | |
echo $seeds[]=" <a href='?plain=$plain&seed=$i'>$i</a>"; | |
} | |
mt_srand($seed); // Seed RNG so we always get the same output | |
$wordList=array('lorem', 'ipsum', 'dolor', 'sit', 'amet', 'consectetuer', 'adipiscing', 'elit', 'aenean', | |
'commodo', 'ligula', 'eget', 'massa', 'cum', 'sociis', 'natoque', 'penatibus', 'et', 'magnis', 'dis', | |
'parturient', 'montes', 'nascetur', 'ridiculus', 'mus', 'donec', 'quam', 'felis', 'ultricies', 'nec'); | |
// Generate $nrNonces nonces to be inserted at random locations in the text | |
$nrNonces=10; | |
$nonces=array(); | |
for ($i=0;$i<$nrNonces;$i++) { | |
$value=''; | |
for ($j = 0; $j < 10; $j++) { | |
$value .= str_pad(dechex(mt_rand(0, 255)), 2, '0', STR_PAD_LEFT); | |
} | |
$nonces[]=$value; | |
} | |
// Generate random paragraphs, sentences, phrases and words based on $wordList above and inject nonces | |
// from $nonces | |
$nrParagraphs=5; // Number of paragraphs to generate | |
$paragraphs=array(); | |
for ($paragraph=0;$paragraph<$nrParagraphs;$paragraph++) { | |
$nrSentences = mt_rand(3, 7); // Number of sentences per paragraph | |
$sentences = array(); | |
for ($sentence = 0; $sentence < $nrSentences; $sentence++) { | |
$nrPhrases = mt_rand(1, 5); // Number of phrases per sentence | |
$phrases = array(); | |
for ($phrase = 0; $phrase < $nrPhrases; $phrase++) { | |
$nrWords = mt_rand(1, 10); // Number of words per phrase | |
$words = array(); | |
$randWords = $wordList; | |
for ($word = 0; $word < $nrWords; $word++) { | |
$randWord = mt_rand(0, sizeof($randWords) - 1); // Choose random word | |
$words[] = $randWords[$randWord]; | |
array_splice($randWords, $randWord,1); // Remove chosen word so we don't choose the same word twice in a phrase | |
} | |
if (mt_rand(0, 5)==0) { | |
// Insert a random nonce in the phrase | |
$value=$nonces[mt_rand(0, sizeof($nonces)-1)]; // Pick random nonce | |
$color=($_REQUEST['plain'] == 1) ? '#CCCCCC' : HTMLColorFingerprint($value); | |
$nonceHTML = "<code style='background-color: $color'>$value</code>"; | |
array_splice($words, mt_rand(0,sizeof($words)), 0, $nonceHTML); | |
} | |
$phrases[] = join(' ', $words); | |
} | |
$sentences[] = ucfirst(join(', ', $phrases)); | |
} | |
echo '<p>'.join('. ', $sentences).'.</p>'; | |
} | |
echo "</body></html>"; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment