September 11

Best Freelance PHP Developers For Hire

There are many different technologies available fo [...]

There are many different technologies available for web development. However, PHP easily takes the lead when it comes to developing and designing a website from scratch. The open-source programming language is effective for creating dynamic and engaging web pages for delivering inclusive interactive to all the users.

May 09

Top differences between Laravel and Yii framework

The two PHP based frameworks- Laravel and Yii are [...]

Best Web & Mobile App Development Company

February 11

PHP Loop Thru Multidimensional Arrays

PHP Loop Thru Multidimensional Arrays
foreach ($array as $i => $values) {
    print "$i {\n";
    foreach ($values as $key => $value) {
        print "    $key => $value\n";
    }
    print "}\n";
}
August 21

Soccer simulation for a game

Soccer simulation for a game

I would propose that you have an array of minutes with actions at first.

$minutes = array(1, 3, 4, 7, 11, 13, ..., 90, 92);

For each of these minutes, you could then simulate an attack.

The attacking team is determined by dice before: $attacking = mt_rand(1, 2);

So the part which is most important to me is the attack function.

Please edit my approach or use it as a sample. Can you help me to improve this? The function should be complex so that the results are as realistic as possible. But you need to find something between high predictability and too random results. I only want to improve this function.

My approach:

<?php
function Chance_Percent($chance, $universe = 100) {
    $chance = abs(intval($chance));
    $universe = abs(intval($universe));
    if (mt_rand(1, $universe) <= $chance) {
        return true;
    }
    return false;
}
function simulate_attack($teamname_att, $teamname_def, $strength_att, $strength_def) {
    global $minute, $goals, $_POST, $matchReport, $fouls, $yellowCards, $redCards, $offsides, $schuesse, $taktiken;
    // input values: attacker's name, defender's name, attacker's strength array, defender's strength array
    // players' strength values vary from 0.1 to 9.9
    // ADJUSTMENT START
    switch ($taktiken[$teamname_att][0]) {
        case 1: $strength_att['defenders'] *= 1.1; $strength_att['forwards'] *= 0.9; break;
        case 3: $strength_att['defenders'] *= 0.9; $strength_att['forwards'] *= 1.1; break;
    }
    switch ($taktiken[$teamname_def][0]) {
        case 1: $strength_def['defenders'] *= 1.1; $strength_def['forwards'] *= 0.9; break;
        case 3: $strength_def['defenders'] *= 0.9; $strength_def['forwards'] *= 1.1; break;
    }
    // ADJUSTMENT END
    $matchReport .= '<p>'.$minute.'\': '.comment($teamname_att, 'attack');
    $offense_strength = $strength_att['forwards']/$strength_def['defenders'];
    $defense_strength = $strength_def['defenders']/$strength_att['forwards'];
    if (Chance_Percent(50*$offense_strength*($taktiken[$teamname_att][2]/2)*($taktiken[$teamname_att][3]/2))) {
        // attacking team passes 1st third of opponent's field side
        $matchReport .= ' '.comment($teamname_def, 'attack_advance');
        if (Chance_Percent(25*($taktiken[$teamname_def][4]/2))) {
            // the defending team fouls the attacking team
            $fouls[$teamname_def]++;
            $matchReport .= ' '.comment($teamname_def, 'attack_advance_foul');
            if (Chance_Percent(43)) {
                // yellow card for the defending team
                // chance is correct for my purpose
                $yellowCards[$teamname_def]++;
                $matchReport .= ' '.comment($teamname_def, 'attack_advance_foul_yellow');
            }
            elseif (Chance_Percent(3)) {
                // red card for the defending team
                // chance is correct for my purpose (only 1.43% because it's an alternative way)
                $redCards[$teamname_def]++;
                $matchReport .= ' '.comment($teamname_def, 'attack_advance_foul_red');
            }
            // indirect free kick
            // only 58.23% because it's an alternative way
            $matchReport .= ' '.comment($teamname_def, 'attack_advance_foul_iFreeKick');
            if (Chance_Percent(25)) {
                // shot at the goal
                $schuesse[$teamname_att]++;
                $matchReport .= ' '.comment($teamname_def, 'attack_advance_foul_iFreeKick_shot');
                if (Chance_Percent(25)) {
                    // attacking team scores (6.25% chance)
                    $goals[$teamname_att]++;
                    $matchReport .= ' '.comment($teamname_def, 'attack_advance_foul_iFreeKick_shot_score');
                }
                else {
                    // defending goalkeeper saves
                    // only 18.75% because it's an alternative way
                    $matchReport .= ' '.comment($teamname_def, 'attack_advance_foul_iFreeKick_shot_save');
                }
            }
            else {
                // defending team cleares the ball
                // only 75% because it's an alternative way
                $matchReport .= ' '.comment($teamname_def, 'attack_advance_foul_iFreeKick_clear');
            }
        }
        elseif (Chance_Percent(17)) {
            // attacking team is caught offside
            // only 4.25% because it's an alternative way
            $offsides[$teamname_att]++;
            $matchReport .= ' '.comment($teamname_def, 'attack_advance_offside');
        }
        else {
            if (Chance_Percent(25*($taktiken[$teamname_def][5]/2))) {
                // the defending team fouls the attacking team
                $fouls[$teamname_def]++;
                $matchReport .= ' '.comment($teamname_def, 'attack_advance_foul');
                if (Chance_Percent(43)) {
                    // yellow card for the defending team
                    // chance is correct for my purpose
                    $yellowCards[$teamname_def]++;
                    $matchReport .= ' '.comment($teamname_def, 'attack_advance_foul_yellow');
                }
                elseif (Chance_Percent(3)) {
                    // red card for the defending team
                    // chance is correct for my purpose (only 1.43% because it's an alternative way)
                    $redCards[$teamname_def]++;
                    $matchReport .= ' '.comment($teamname_def, 'attack_advance_foul_red');
                }
                if (Chance_Percent(19)) {
                    // penalty for the attacking team
                    $schuesse[$teamname_att]++;
                    $matchReport .= ' '.comment($teamname_def, 'attack_advance_foul_penalty');
                    if (Chance_Percent(77)) {
                        // attacking team scores (77% chance according to Wikipedia)
                        $goals[$teamname_att]++;
                        $matchReport .= ' '.comment($teamname_def, 'attack_advance_foul_penalty_score');
                    }
                    elseif (Chance_Percent(50)) {
                        // shot misses the goal
                        // only 11.5% because it's an alternative way
                        $matchReport .= ' '.comment($teamname_def, 'attack_advance_foul_penalty_miss');
                    }
                    else {
                        // defending goalkeeper saves
                        // only 11.5% because it's an alternative way
                        $matchReport .= ' '.comment($teamname_def, 'attack_advance_foul_penalty_save');
                    }
                }
                elseif (Chance_Percent(28)) {
                    // direct free kick
                    // only 22.68% because it's an alternative way
                    $matchReport .= ' '.comment($teamname_def, 'attack_advance_foul_dFreeKick');
                    if (Chance_Percent(33)) {
                        // shot at the goal
                        $schuesse[$teamname_att]++;
                        $matchReport .= ' '.comment($teamname_def, 'attack_advance_foul_dFreeKick_shot');
                        if (Chance_Percent(33)) {
                            // attacking team scores (10.89% chance)
                            $goals[$teamname_att]++;
                            $matchReport .= ' '.comment($teamname_def, 'attack_advance_foul_dFreeKick_shot_score');
                        }
                        else {
                            // defending goalkeeper saves
                            $matchReport .= ' '.comment($teamname_def, 'attack_advance_foul_dFreeKick_shot_save');
                        }
                    }
                    else {
                        // defending team cleares the ball
                        // only 77% because it's an alternative way
                        $matchReport .= ' '.comment($teamname_def, 'attack_advance_foul_dFreeKick_clear');
                    }
                }
                else {
                    // indirect free kick
                    // only 58.23% because it's an alternative way
                    $matchReport .= ' '.comment($teamname_def, 'attack_advance_foul_iFreeKick');
                    if (Chance_Percent(25)) {
                        // shot at the goal
                        $schuesse[$teamname_att]++;
                        $matchReport .= ' '.comment($teamname_def, 'attack_advance_foul_iFreeKick_shot');
                        if (Chance_Percent(25)) {
                            // attacking team scores (6.25% chance)
                            $goals[$teamname_att]++;
                            $matchReport .= ' '.comment($teamname_def, 'attack_advance_foul_iFreeKick_shot_score');
                        }
                        else {
                            // defending goalkeeper saves
                            // only 18.75% because it's an alternative way
                            $matchReport .= ' '.comment($teamname_def, 'attack_advance_foul_iFreeKick_shot_save');
                        }
                    }
                    else {
                        // defending team cleares the ball
                        // only 75% because it's an alternative way
                        $matchReport .= ' '.comment($teamname_def, 'attack_advance_foul_iFreeKick_clear');
                    }
                }
            }
            else {
                // attack passes the 2nd third of the opponent's field side - good chance
                $matchReport .= ' '.comment($teamname_def, 'attack_advance_advance');
                if (Chance_Percent(62*($taktiken[$teamname_att][6]/2)*($taktiken[$teamname_att][7]/2)/($taktiken[$teamname_att][8]/2)*($taktiken[$teamname_att][9]/2)/($taktiken[$teamname_def][10]/2))) {
                    // shot at the goal
                    $schuesse[$teamname_att]++;
                    $matchReport .= ' '.comment($teamname_def, 'attack_advance_advance_shot');
                    if (Chance_Percent(30*$strength_def['goalkeeper']/7/($taktiken[$teamname_att][11]/2))) {
                        // the attacking team scores
                        // only 8.78% because it's an alternative way
                        // if goalkeeper has strenth 7 then chance is 8.78% otherwise lower/higher
                        $goals[$teamname_att]++;
                        $matchReport .= ' '.comment($teamname_def, 'attack_advance_advance_shot_score');
                    }
                    else {
                        if (Chance_Percent(50)) {
                            // the defending defenders block the shot
                            $matchReport .= ' '.comment($teamname_def, 'attack_advance_advance_shot_block');
                        }
                        else {
                            // the defending goalkeeper saves
                            $matchReport .= ' '.comment($teamname_def, 'attack_advance_advance_shot_save');
                        }
                    }
                }
            }
        }
    }
    // attacking team doesn't pass 1st third of opponent's field side
    elseif (Chance_Percent(15*$defense_strength*($taktiken[$teamname_att][12]/2)*($taktiken[$teamname_att][13]/2))) {
        // quick counter attack - playing on the break
        // only 7.5% because it's an alternative way
        // if defense has strength 7 then chance is 7.5% otherwise lower/higher
        $strength_att['defenders'] = $strength_att['defenders']*0.8; // weaken the current attacking team's defense
        $matchReport .= ' '.comment($teamname_def, 'attack_quickCounterAttack');
        $matchReport .= ' ['.$goals[$_POST['team1']].':'.$goals[$_POST['team2']].']</p>'; // close comment line
        return simulate_attack($teamname_def, $teamname_att, $strength_def, $strength_att); // new attack - this one is finished
    }
    else {
        // ball goes into touch - out of the field
        $matchReport .= ' '.comment($teamname_def, 'attack_throwIn');
        if (Chance_Percent(33)) {
            // if a new chance is created
            if (Chance_Percent(50)) {
                // throw-in for the attacking team
                $matchReport .= ' '.comment($teamname_def, 'attack_throwIn_att');
                $matchReport .= ' ['.$goals[$_POST['team1']].':'.$goals[$_POST['team2']].']</p>'; // close comment line
                return simulate_attack($teamname_att, $teamname_def, $strength_att, $strength_def); // new attack - this one is finished
            }
            else {
                // throw-in for the defending team
                $matchReport .= ' '.comment($teamname_def, 'attack_throwIn_def');
                $matchReport .= ' ['.$goals[$_POST['team1']].':'.$goals[$_POST['team2']].']</p>'; // close comment line
                return simulate_attack($teamname_def, $teamname_att, $strength_def, $strength_att); // new attack - this one is finished
            }
        }
    }
    $matchReport .= ' ['.$goals[$_POST['team1']].':'.$goals[$_POST['team2']].']</p>'; // close comment line
    return TRUE; // finish the attack
}
?>

Tactical settings which should have an influence on the randomness:

  • adjustment (1=defensive, 2=neutral, 3=offensive): the higher the value is the weaker is the defense and the stronger is the offense
  • speed of play (1=slow, 2=medium, 3=fast): the higher the value is the better are the opportunities but the higher is the risk of getting a quick counter attack
  • distance of passes (1=short, 2=medium, 3=long): the higher the value is the less but better opportunities you get and the more often you are offside
  • creation of changes (1=safe, 2=medium, 3=risky): the higher the value is the better are your opportunities but the higher is the risk of getting a quick counter attack
  • pressure in defense (1=low, 2=medium, 3=high): the higher the value is the more quick counter attacks you will have
  • aggressivity (1=low, 2=medium, 3=high): the higher the value is the more attacks you will stop by fouls

Integration of the tactical settings:

All the tactical settings have a value which can be "1", "2" or "3". "2" is always neutral/medium. So I divide the values by 2. I get a ratio which is 0.5 or 1 or 1.5. I thought that I could then easily multiply the chances by this in order to integrate tactical influence. But one problem has evolved: If I multiply a chance by 2 or more tactical values, it can be higher than 100% (60 x 1.5 x 1.5 for example). So I can't integrate the tactics this way. What else can I do?


Thank you very much!

Update (2014): A few years later, I have now released the full code base of the game as open-source on GitHub. You'll find the specific implementation of this simulation in this file, if anyone is interested.

February 12

Regular Expressions Cheat Sheet

Regular Expressions Cheat Sheet from DaveChild. A [...]

Regular Expressions Cheat Sheet

A quick reference guide for regular expressions (regex), including symbols, ranges, grouping, assertions and some sample patterns to get you started.

September 06

GitHub - Amsoft-Systems/ZipIt: Zip files up on the fly using PHP

ZipIt - Zip files up on the fly using PHP
Skip to content

README.md

Zip-It! File Zipper – Matt Pass Version 1.1.0

Introduction Zip-It! quite simply, is a component that automatically zips up files & folders you’d like, into a zip file.

Upon making a request to add files and folders to a zip, it first of all quickly and intelligently verifies that these files and folders exist. Once done with the verification, it will then create (or overwrite) a zip file and add all of these files, folders (and sub-folders and files recursively within them), into the zip. Upon completion, it can then provide a download link to the user, which when clicked on starts a header based download, so they may begin downloading the zip.

Zip-It! is the perfect solution for packing files on the fly and providing a download option to the user if you wish.

Setup Installation of Zip-It! couldn’t be simpler;

  1. Copy zip-it.php, zip-it-download-zip.php and zip-it.css to your website.
  2. Create a new folder, called zips and change the write permissions on this folder to allow the public to write to it (most commonly referred to as changing the CHMOD permissions to allow public write access).
  3. Set a HTML form to send form fields to zip-it.php via a POST form sending method, ensuring that the field name begins with _zipIt and the value of that field contains the filename or folder that you wish to include in the zip. Please ensure you end folders with a trailing to indicate it’s a folder and not a file.

Example:

That’s it! When you click the button, your specified files will be packed up into a zip and a download link provided. Clicking this will then prompt a download in your web browser. Note: Should you run into any problems, please check to ensure you have the php_zip extension enabled.

Making it your own Obviously this is enough to get things operating but you will likely want to modify Zip-It! to suit your needs. Some things you may want to consider include;

• Changing the style/design to fit seamlessly with your website • Altering the flow of Zip-It! to fit in with the flow of actions on your website • Changing $zipFileName so the zip’s filename is still unique but not just a number • Turning on the $overwriteZip parameter so users can overwrite zips they produce • Adding an email option, so users can email the zip as an attachment

Hopefully you can see the benefits of zipping files up quickly and easily using Zip-It!

Happy zipping!

You can't perform that action at this time.
You signed in with another tab or window. Reload to refresh your session. You signed out in another tab or window. Reload to refresh your session.
September 03

Better Markdown Parser in PHP

Fast and extensible Markdown parser in PHP. It sup [...]

Markdown Parser in PHP

One File  //  Super Fast  //  Extensible  //  GitHub Flavored


DemoGitHub



$Parsedown = new Parsedown();
echo $Parsedown->text('Hello _Parsedown_!');
We also make a Markdown editor called Caret
August 28

GitHub - puppyCMS

puppyCMS - Tiny, simple, flat file CMS in PHP that [...]
Skip to content
Tiny, simple, flat file CMS in PHP that is SEO friendly and responsive. There's no database for this easy content management system and templates are gorgeous, using bootstrap and bootswatch themes. Build micro sites, simple blogs by using Markdown and the included file manager.

README.md

puppyCMS

pupyCMS is a very simple, flat file CMS that is SEO friendly and responsive - built in PHP (minimum requirements are PHP 5). It takes a few seconds to configure (just one config file). It works on all major browsers including mobile versions.

The biggest difference between puppyCMS and other flat file, responsive content management platforms is that its very small, takes seconds to start, uses markdown for easy editing and uses strapdown.js to produce HTML and templates. jQuery is used if additional functionality is required.

You can create smart looking micro sites with ease, but if you want to extend them into full sites, then a bit of messing with HTML, maybe some PHP and you can have fully-fledged websites too - very SEO friendly.

See the homepage here: http://puppycms.com/

Features

  • Flat file
  • Tiny code
  • Takes a few seconds to install and configure
  • Fully responsive
  • Smart template system (using bootstrap)
  • Works in all browsers
  • Uses Markdown to edit pages
  • Much easier than 95% of flat file CMS

If you want to make simple static content sites in very quick time, then puppyCMS is the CMS for you. It is perfect for creating hobby sites, or micro sites, and with the 11 templates included, you can produce very smart, content-rich sites in no time.

puppyCMS uses strapdown.js to convert it's easy markdown language into HTML, with themes also provided by strapdown.js/bootswatch.

puppyCMS also uses the excellent Responsive Slides slider for additional functionality if required.

August 27

Really Simple Traffic Logger Script

Born out of boredom, unrealized necessity and the fruit of another script, this really simple PHP counter logs page views and tracks visitors from the time they enter your site to  the time they leave it. Weighing in at slight 9.9 KiB, or 5.6 KiB when all comments are removed, it represents excellent value for a free php website traffic counter and logger.

August 27

PHP Spinner Updated - Spin articles for SEO

A Collection Of Thoughts

Location: Home

PHP Spinner Updated - Spin articles for SEO

Quite a while ago I wrote a post on spinning text using PHP to create lots of fresh content from one single block of marked up text. I actually had use for a nested version of this spinning code the other day so set about creating a more efficient version of my previous nested spin code and packed it up in a class wrapper so it would choose whether to use the nested spinner or the flat version dynamically.

Without further ado here is the new PHP Spinner code.

class Spinner
{
	# Detects whether to use the nested or flat version of the spinner (costs some speed)
	public static function detect($text $seedPageName = true $openingConstruct = '{{' $closingConstruct = '}}' $separator = '|')
	{
		if(preg_match('~'$openingConstruct'(?:(?!'$closingConstruct').)*'$openingConstruct'~s' $text))
		{
			return self::nested($text $seedPageName $openingConstruct $closingConstruct $separator);
		}
		else
		{
			return self::flat($text $seedPageName false $openingConstruct $closingConstruct $separator);
		}
	}
 
	# The flat version does not allow nested spin blocks, but is much faster (~2x)
	public static function flat($text $seedPageName = true $calculate = false $openingConstruct = '{{' $closingConstruct = '}}' $separator = '|')
	{
		# Choose whether to return the string or the number of permutations
		$return = 'text';
		if($calculate)
		{
			$permutations	= 1;
			$return			= 'permutations';
		}
 
		# If we have nothing to spin just exit (don't use a regexp)
		if(strpos($text $openingConstruct) === false)
		{
			return $$return;
		}
 
		if(preg_match_all('!'$openingConstruct'(.*?)'$closingConstruct'!s' $text $matches))
		{
			# Optional, always show a particular combination on the page
			self::checkSeed($seedPageName);
 
			$find		= array();
			$replace	= array();
 
			foreach($matches as $key => $match)
			{
				$choices = explode($separator $matches1$key);
 
				if($calculate)
				{
					$permutations *= count($choices);
				}
				else
				{
					$find		= $match;
					$replace	= $choicesmt_rand( count($choices) - 1);
				}
			}
 
			if($calculate)
			{
				# Ensure multiple instances of the same spinning combinations will spin differently
				$text = self::str_replace_first($find $replace $text);
			}
		}
 
		return $$return;
	}
 
	# The nested version allows nested spin blocks, but is slower
	public static function nested($text $seedPageName = true $openingConstruct = '{{' $closingConstruct = '}}' $separator = '|')
	{
		# If we have nothing to spin just exit (don't use a regexp)
		if(strpos($text $openingConstruct) === false)
		{
			return $text;
		}
 
		# Find the first whole match
		if(preg_match('!'$openingConstruct'(.+?)'$closingConstruct'!s' $text $matches))
		{
			# Optional, always show a particular combination on the page
			self::checkSeed($seedPageName);
 
			# Only take the last block
			if(($pos = mb_strrpos($matches1 $openingConstruct)) !== false)
			{
				$matches1 = mb_substr($matches1 $pos + mb_strlen($openingConstruct));
			}
 
			# And spin it
			$parts	= explode($separator $matches1);
			$text	= self::str_replace_first($openingConstruct$matches1$closingConstruct $partsmt_rand( count($parts) - 1) $text);
 
			# We need to continue until there is nothing left to spin
			return self::nested($text $seedPageName $openingConstruct $closingConstruct $separator);
		}
		else
		{
			# If we have nothing to spin just exit
			return $text;
		}
	}
 
	# Similar to str_replace, but only replaces the first instance of the needle
	private static function str_replace_first($find $replace $string)
	{
		# Ensure we are dealing with arrays
		if(is_array($find))
		{
			$find = array($find);
		}
 
		if(is_array($replace))
		{
			$replace = array($replace);
		}
 
		foreach($find as $key => $value)
		{
			if(empty($value))
			{
				if(($pos = mb_strpos($string $value)) !== false)
				{
					# If we have no replacement make it empty
					if(isset($replace$key))
					{
						$replace$key = '';
					}
 
					$string = mb_substr($string  $pos)$replace$keymb_substr($string $pos + mb_strlen($value));
				}
			}
		}
 
		return $string;
	}
 
	private static function checkSeed($seedPageName)
	{
		# Don't do the check if we are using random seeds
		if($seedPageName)
		{
			if($seedPageName === true)
			{
				mt_srand(crc32($_SERVER'REQUEST_URI'));
			}
			elseif($seedPageName == 'every second')
			{
				mt_srand(crc32($_SERVER'REQUEST_URI'date('Y-m-d-H-i-s')));
			}
			elseif($seedPageName == 'every minute')
			{
				mt_srand(crc32($_SERVER'REQUEST_URI'date('Y-m-d-H-i')));
			}
			elseif($seedPageName == 'hourly' OR $seedPageName == 'every hour')
			{
				mt_srand(crc32($_SERVER'REQUEST_URI'date('Y-m-d-H')));
			}
			elseif($seedPageName == 'daily' OR $seedPageName == 'every day')
			{
				mt_srand(crc32($_SERVER'REQUEST_URI'date('Y-m-d')));
			}
			elseif($seedPageName == 'weekly' OR $seedPageName == 'every week')
			{
				mt_srand(crc32($_SERVER'REQUEST_URI'date('Y-W')));
			}
			elseif($seedPageName == 'monthly' OR $seedPageName == 'every month')
			{
				mt_srand(crc32($_SERVER'REQUEST_URI'date('Y-m')));
			}
			elseif($seedPageName == 'annually' OR $seedPageName == 'every year')
			{
				mt_srand(crc32($_SERVER'REQUEST_URI'date('Y')));
			}
			elseif(preg_match('!every ([0-9.]+) seconds!' $seedPageName $matches))
			{
				mt_srand(crc32($_SERVER'REQUEST_URI'floor(time() / $matches1)));
			}
			elseif(preg_match('!every ([0-9.]+) minutes!' $seedPageName $matches))
			{
				mt_srand(crc32($_SERVER'REQUEST_URI'floor(time() / ($matches1 * 60))));
			}
			elseif(preg_match('!every ([0-9.]+) hours!' $seedPageName $matches))
			{
				mt_srand(crc32($_SERVER'REQUEST_URI'floor(time() / ($matches1 * 3600))));
			}
			elseif(preg_match('!every ([0-9.]+) days!' $seedPageName $matches))
			{
				mt_srand(crc32($_SERVER'REQUEST_URI'floor(time() / ($matches1 * 86400))));
			}
			elseif(preg_match('!every ([0-9.]+) weeks!' $seedPageName $matches))
			{
				mt_srand(crc32($_SERVER'REQUEST_URI'floor(time() / ($matches1 * 604800))));
			}
			elseif(preg_match('!every ([0-9.]+) months!' $seedPageName $matches))
			{
				mt_srand(crc32($_SERVER'REQUEST_URI'floor(time() / ($matches1 * 2620800))));
			}
			elseif(preg_match('!every ([0-9.]+) years!' $seedPageName $matches))
			{
				mt_srand(crc32($_SERVER'REQUEST_URI'floor(time() / ($matches1 * 31449600))));
			}
			else
			{
				throw new Exception($seedPageName ' Was not a valid spin time option!');
			}
		}
	}
}

And an example:

$string = '{{The|A}} {{quick|speedy|fast}} {{brown|black|red}} {{fox|wolf}} {{jumped|bounded|hopped|skipped}} over the {{lazy|tired}} {{dog|hound}}';
 
echo '

';   for($i = 1; $i <= 5; $i++) { echo Spinner::detect($string false)'
'
; // or Spinner::flat($string, false).'
';
}   echo '

'
;

Which produces:

The speedy black wolf bounded over the lazy hound
A speedy brown fox skipped over the tired hound
The quick red wolf bounded over the lazy hound
The fast brown fox hopped over the tired dog
The speedy brown fox jumped over the tired dog

and it will work happily as a nested PHP spinner too:

$string = '{{A {{simple|basic}} example|An uncomplicated scenario|The {{simplest|trivial|fundamental|rudimentary}} case|My {{test|invest{{igative|igation}}}} case}} to illustrate the {{function|problem}}';
 
echo '

';   for($i = 1; $i <= 5; $i++) { echo Spinner::detect($string false)'
'
; // or Spinner::nested($string, false).'
';
}   echo '

'
;

Which produces:

A basic example to illustrate the function
My test case to illustrate the problem
The rudimentary case to illustrate the function
An uncomplicated scenario to illustrate the problem
The fundamental case to illustrate the problem

Improvement

The spinner now allows seed page options to be strings such as 'daily', 'every 2.5 hours' or 'every 3 weeks' rather than just true / false so the spun text will automatically update every set period of time. See the checkSeed (bottom) function for allowed values.

Have fun spinning articles! Any comments, suggestions or improvements are welcome.

all content ©2009-2016 Paul Norman