Hey all,
Ever tried to write a text spinner? Code that will turn {Text 1|Text 2} into
Usage:
Output:
My code isn't overly quick though. I'd be interested to see how others have tackled the problem.
Cheers,
Leon
Ever tried to write a text spinner? Code that will turn {Text 1|Text 2} into
- Text 1
- Text 2
Code:
<?
//Save below as spinner.php
function create_checked_spin($text,$int=10) {
//Check for OK implementation of spinner and then spin for text
if(strstr($text,"{") && strstr($text,"|") || strstr($text,"}") && strstr($text,"|")) {
$check = check_spin($text);
if($check['result'] == false) {
if($check['seps']) {
$return['error'] = "<div class='notice' style='margin-top:2px;margin-bottom:2px;width:50%'>Error with Spinner. You have " . $check['seps'] . " seperator(s), but " . $check['divs'] . " curly bracket(s)</div>";
} else {
$return['error'] = "<div class='notice' style='margin-top:2px;margin-bottom:2px;width:50%'>Error with Spinner. You have " . $check['right'] . " right bracket(s), but " . $check['left'] . " left bracket(s)</div>";
}
} else {
$return['spin'] = do_spin($text,$int);
}
}
return $return;
}
function check_spin($text) {
//Make sure no funny business
preg_match_all("/}/",$text,$right);
preg_match_all("/{/",$text,$left);
preg_match_all("/\|/",$text,$divider);
$divs= count($right[0]) + count($left[0]);
$seps = count($divider[0]);
if($seps*2 != $divs) {
//return array("seps"=>$seps,"divs"=>$divs,"result"=>false);
}
if(count($right[0]) != count($left[0])) {
return array("right"=>count($right[0]),"left"=>count($left[0]),"result"=>false);
}
return array("result"=>true);
}
function do_spin($text,$int=1) {
$return = array();
//Mark paras
$text = ereg_replace("\n","@@@PARA",$text);
$text = ereg_replace("@@@PARA[\n\r\s]+@@@PARA","##PARA##",$text);
$text = ereg_replace("@@@PARA","",$text);
//Whitespace is bad
$text = ereg_replace("[\r\t\n]","",$text);
//Secret guru technique
$text = "{" . $text . "|}";
while((count($return) < $int) && $counter < 1000) {
$marked_text = get_levels($text);
$choices = create_choices_array($marked_text);
$final_text = trim(process_choices_array($choices));
if($final_text) {
$return[$final_text] = ereg_replace("##PARA##","\n\n",$final_text);
}
$counter++;
}
return array_values($return);
}
function process_choices_array($choices) {
$base = choose($choices[1]);
while(strstr($base,"@@@CHOICE")) {
preg_match("/@@@CHOICE([0-9]+)@@@/",$base,$matches);
$base = str_replace($matches[0],choose($choices[$matches[1]]),$base);
}
return $base;
}
function choose($array) {
return $array['Choices'][array_rand($array['Choices'])];
}
function create_choices_array($marked_text) {
$final_text = $marked_text['text'][count($marked_text['text'])];
//Run through array in reverse order
for($i=count($marked_text['text']);$i>0;$i--) {
$regex = "/STARTMARKER".$i."@@@(.*?)@@@".$i."ENDMARKER/";
preg_match($regex,$final_text,$matches);
preg_match("@(.*)\|(.*)@",$matches[1],$choices);
$choices = explode("|",$matches[1]);
$output[$i] = array("Raw_Text"=>$matches[0],
"Text"=>$matches[1],
"Choices"=>$choices,
);
$final_text = str_replace($matches[0],"@@@CHOICE$i@@@",$final_text);
}
return $output;
}
function get_levels($text) {
$counter =0;
while(strstr($text,"{") || strstr($text,"}")) {
$_counter++;
//echo $text . "\n";
//Run throgh text
for($i=0;$i<strlen($text);$i++) {
$letter = $text{$i};
if($letter == "{") {
$left_count++;
}
if($letter == "}") {
$right_count++;
}
if($left_count >0) {
$sentence .= $letter;
}
if($left_count == $right_count && ($left_count >0)) {
$counter++;
$return['level'][$counter] = $sentence;
$_sentence = substr($sentence, 1); //Remove {
$_sentence = substr($_sentence, 0, -1); //Remove {
$text = str_replace($sentence,"STARTMARKER".$counter."@@@$_sentence@@@".$counter."ENDMARKER",$text);
$return['text'][$counter] = $text;
$left_count = 0;
$right_count = 0;
$sentence = "";
break;
}
}
}
return $return;
}
?>
Code:
require_once("spinner.php");
$text = "{{Great|Awesome|Fantastic|Brilliant} {link|site|website} - {highly|thoroughly|totally} recommended|Terrible site, don't visit it}";
$desc = create_checked_spin($text,30); //Create 30 different spins
print_r($desc);
Code:
Array
(
[spin] => Array
(
[0] => Great link - totally recommended
[1] => Terrible site, don't visit it
[2] => Brilliant website - thoroughly recommended
[3] => Great link - thoroughly recommended
[4] => Brilliant site - highly recommended
[5] => Brilliant website - totally recommended
[6] => Awesome website - totally recommended
[7] => Great website - totally recommended
[8] => Brilliant site - totally recommended
[9] => Great site - totally recommended
[10] => Awesome site - totally recommended
[11] => Fantastic link - totally recommended
[12] => Great website - highly recommended
[13] => Awesome site - highly recommended
[14] => Fantastic site - totally recommended
[15] => Awesome website - highly recommended
[16] => Fantastic site - highly recommended
[17] => Fantastic link - highly recommended
[18] => Great link - highly recommended
[19] => Brilliant site - thoroughly recommended
[20] => Fantastic website - highly recommended
[21] => Brilliant link - totally recommended
[22] => Fantastic link - thoroughly recommended
[23] => Awesome site - thoroughly recommended
[24] => Great site - thoroughly recommended
[25] => Brilliant link - thoroughly recommended
[26] => Brilliant link - highly recommended
[27] => Fantastic website - totally recommended
[28] => Awesome link - totally recommended
[29] => Awesome link - highly recommended
)
)
Cheers,
Leon