Last active
December 16, 2015 16:19
-
-
Save vincent4vx/5462513 to your computer and use it in GitHub Desktop.
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 | |
define('BASE', __DIR__.DIRECTORY_SEPARATOR); | |
/** | |
* @property-read Input $input | |
* @property-read Loader $loader | |
* @property-read Router $router | |
*/ | |
class Core implements ArrayAccess{ | |
/** | |
* @var Core | |
*/ | |
private static $_instance = null; | |
private $vars=array(); | |
private function __construct() { | |
self::$_instance = $this; | |
$autoload = array('Input', 'Router'); | |
$this->loader = new Loader($autoload); | |
} | |
public function __get($name){ | |
return isset($this[$name]) ? $this[$name] : null; | |
} | |
public function __isset($name) { | |
return isset($this[$name]); | |
} | |
public function __set($name, $value){ | |
$this[$name] = $value; | |
} | |
public function offsetSet($offset, $value) { | |
$this->vars[$offset] = $value; | |
} | |
public function offsetGet($offset) { | |
return isset($this->vars[$offset]) ? $this->vars[$offset] : null; | |
} | |
public function offsetExists($offset) { | |
return isset($this->vars[$offset]); | |
} | |
public function offsetUnset($offset) { | |
unset($this->vars[$offset]); | |
} | |
public function execute(){ | |
$function = $this->router->selectRoute(); | |
$exec_param = array(); | |
$reflec = new ReflectionFunction($function); | |
foreach($reflec->getParameters() as $param){ | |
$value = $this->input->{$param->getName()}; | |
if($value===false){ | |
if($param->isDefaultValueAvailable()) | |
$value = $param->getDefaultValue(); | |
else | |
$value = null; | |
} | |
$exec_param[] = $value; | |
} | |
$reflec->invokeArgs($exec_param); | |
} | |
/** | |
* @return Core | |
*/ | |
public static function instance(){ | |
if(self::$_instance===null) | |
new self; | |
return self::$_instance; | |
} | |
} | |
abstract class Component{ | |
/** | |
* @var Core | |
*/ | |
private $_instance; | |
public function __construct() { | |
$this->_instance = Core::instance(); | |
} | |
public function __get($name) { | |
return $this->_instance->$name; | |
} | |
public function __set($name, $value) { | |
$this->_instance->$name = $value; | |
} | |
} | |
class Loader extends Component{ | |
public function __construct(array $autoload) { | |
parent::__construct(); | |
foreach($autoload as $class) | |
$this->load($class); | |
} | |
public function get($class_name){ | |
if($this->{strtolower($class_name)}===null) | |
$this->load($class_name); | |
return $this->{strtolower($class_name)}; | |
} | |
public function load($name){ | |
if(!class_exists($name)){ | |
throw new Exception(<<<MSG | |
La classe "$name" n'existe pas, ou n'est pas encore incluse ! | |
MSG | |
); | |
} | |
if($this->{strtolower($name)}!==null){ | |
throw new Exception(<<<MSG | |
La class "$name" est déjà chargée ! | |
MSG | |
); | |
} | |
$this->{strtolower($name)} = new $name; | |
} | |
} | |
class Router{ | |
private $action = ''; | |
private $_routes = array(); | |
public function __construct() { | |
if(!($this->action=Core::instance()->input->action)) | |
$this->action = 'layout'; | |
} | |
public function register($name, callable $function){ | |
$this->_routes[$name] = $function; | |
} | |
public function selectRoute(){ | |
foreach($this->_routes as $name=>$function){ | |
if((~$name & $this->action)===str_repeat(chr(0), strlen($this->action))){ | |
return $function; | |
} | |
} | |
throw new Exception('Erreur 404'); | |
} | |
} | |
class Cache{ | |
const EXT = '.cache'; | |
public function get($name){ | |
$file = self::processName($name); | |
if(!file_exists($file)) | |
return false; | |
$data = unserialize(file_get_contents($file)); | |
if($data['destruct_time'] < time()){ | |
unlink($file); | |
return false; | |
} | |
return $data['content']; | |
} | |
public function set($name, $value, $time = 60){ | |
$file = self::processName($name); | |
if(!is_dir(dirname($file))) | |
mkdir(dirname ($file), 0777, true); | |
$data = array( | |
'content' => $value, | |
'destruct_time' => time() + $time | |
); | |
return file_put_contents($file, serialize($data)); | |
} | |
private static function processName($name){ | |
return BASE.'cache'.DIRECTORY_SEPARATOR.str_replace('.', DIRECTORY_SEPARATOR, $name).self::EXT; | |
} | |
} | |
class Input{ | |
public function __get($name){ | |
foreach($_GET + $_POST as $k => $v){ | |
if(($k & $name)==$name) | |
return urldecode(trim($v)); | |
} | |
return false; | |
} | |
} | |
class HtmlPage{ | |
private $code = ''; | |
public function addContent($content){ | |
$this->code.=$content; | |
return $this; | |
} | |
public function __toString() { | |
return $this->code; | |
} | |
} | |
class HtmlTag{ | |
private $content = ''; | |
private $name = ''; | |
private $attributes = array(); | |
public function __construct($name, array $attributes = array()){ | |
$this->name = $name; | |
$this->attributes = $attributes; | |
} | |
public function addContent($content){ | |
$this->content.=$content; | |
return $this; | |
} | |
public function __toString() { | |
$open = '<'.$this->name.' '; | |
foreach($this->attributes as $name=>$value){ | |
if(is_numeric($name)) | |
$open.=$value.' '; | |
else | |
$open.=$name.'="'.addslashes($value).'" '; | |
} | |
$open.='>'; | |
$close = '</'.$this->name.'>'; | |
return $open.$this->content.$close; | |
} | |
} | |
class Invader{ | |
private static $pattern = [ | |
[0, 0, 1, 0, 1, 0, 0], | |
[0, 1, 1, 1, 1, 1, 0], | |
[0, 1, 0, 1, 0, 1, 0], | |
[0, 1, 0, 1, 0, 1, 0], | |
[1, 1, 1, 1, 1, 1, 1], | |
[1, 0, 1, 0, 1, 0, 1] | |
]; | |
private $color; | |
private $eyes = array(); | |
public function __construct() { | |
$rand = new Rand(12); | |
$this->color = $rand->nextInt(0, 0xFFFFFF); | |
$this->eyes = array_fill(0, 6, array_fill(0, 7, 0)); | |
$this->eyes[$rand->nextInt(2, 3)][2] = 1; | |
$this->eyes[$rand->nextInt(2, 3)][4] = 1; | |
} | |
/** | |
* @return Mapper | |
*/ | |
public function getMap($size_x, $size_y){ | |
$rand = new Rand(12); | |
$map = new Mapper($size_x, $size_y); | |
$pos_x = $rand->nextInt(0, $size_x - count(self::$pattern[0])); | |
$pos_y = $rand->nextInt(0, $size_y - count(self::$pattern)); | |
$map->fill(self::$pattern, $this->color, $pos_x, $pos_y); | |
$map->fill($this->eyes, 0, $pos_x, $pos_y); | |
return $map; | |
} | |
} | |
class Mapper{ | |
private $map; | |
private $X; | |
private $Y; | |
public function __construct($x, $y){ | |
$this->map = array_fill(0, $y, array_fill(0, $x, null)); | |
$this->X = $x; | |
$this->Y = $y; | |
} | |
public function fill(array $pattern, $color, $x_pos, $y_pos){ | |
foreach($pattern as $y => $row){ | |
foreach($row as $x => $fill){ | |
if($fill) | |
$this->map[($y_pos + $y) % $this->Y][($x_pos + $x) % $this->X] = $this->intToHexColor($color); | |
} | |
} | |
} | |
private function intToHexColor($i){ | |
$hex = dechex($i); | |
while(strlen($hex) < 6){ | |
$hex = '0'.$hex; | |
} | |
return '#'.$hex; | |
} | |
public function toJSON(){ | |
return json_encode($this->map); | |
} | |
} | |
class Rand{ | |
private $current = 0; | |
private $values = array(); | |
public function __construct($advence = 623){ | |
$this->values[] = microtime(true); | |
for($i = 1; $i < $advence; $i++){ | |
$v = 1812433253 * ($this->values[$i - 1] ^ (($this->values[$i - 1]) >> 30 )) + 1; | |
$v = decbin($v); | |
while(strlen($v) < 32){ | |
$v = '0'.$v; | |
} | |
$this->values[] = bindec(substr($v, strlen($v) - 32)); | |
} | |
} | |
private function generate(){ | |
foreach($this->values as $i => $value){ | |
$y = ($value & 0x80000000) + ($this->values[($i + 1) % count($this->values)] & 0x7fffffff); | |
$this->values[$i] = $this->values[($i + 397) % count($this->values)] ^ ($y >> 1); | |
if(($y % 2)!==0){ | |
$this->values[$i] = $this->values[$i] ^ 2567483615; | |
} | |
} | |
} | |
public function getNext(){ | |
if($this->current === 0) | |
$this->generate(); | |
$value = $this->values[$this->current]; | |
$value ^= ($value >> 11); | |
$value ^= (($value << 7) & 2636928640); | |
$value ^= (($value << 15) & 4022730752); | |
$value ^= ($value >> 18); | |
$this->current = ($this->current + 1) % count($this->values); | |
return $value; | |
} | |
public function nextInt($min = 0, $max = null){ | |
if(!$max) | |
$max = self::max_value(); | |
$value = $this->getNext() % ($max + 1); | |
while($value < $min){ | |
$value = ($value + $min) % ($max + 1); | |
} | |
return $value; | |
} | |
public static function max_value(){ | |
return pow(2, 32) - 1; | |
} | |
} | |
$core = Core::instance(); | |
set_exception_handler(function(Exception $e){ | |
echo '<pre>', $e, '</pre>'; | |
exit; | |
}); | |
$core->router->register( | |
'layout', | |
function($size_x = 40, $size_y = 30, $speed = 1500) use($core){ | |
$size_x = abs((int)$size_x); | |
$size_y = abs((int)$size_y); | |
$speed = abs((int)$speed); | |
if(!($data=$core->loader->get('Cache')->get('layout'))){ | |
$data = new HtmlPage(); | |
$head = new HtmlTag('head'); | |
$x = (100 / $size_x) - 1; | |
$y = (100 / $size_y) - 1; | |
$head->addContent((new HtmlTag('style'))->addContent(<<<TXT | |
div{ | |
margin: 1px; | |
width: $x%; | |
height: $y%; | |
padding: 3px; | |
display: inline-block; | |
} | |
TXT | |
)); | |
$head->addContent((new HtmlTag('script', array('type'=>'text/javascript')))->addContent(<<<SCRIPT | |
var X = $size_x; | |
var Y = $size_y; | |
window.setTimeout(loadInvader, 1000); | |
function loadInvader(){ | |
xhr = new XMLHttpRequest(); | |
xhr.open("GET", "index.php?action=invader&size_x=" + X + "&size_y=" + Y, false); | |
xhr.send(null); | |
fillPage(JSON.parse(xhr.responseText)); | |
window.setTimeout(loadInvader, $speed); | |
} | |
function fillPage(map){ | |
for(var y in map){ | |
for(var x in map[y]){ | |
var id = "block_" + x + "_" + y; | |
document.getElementById(id).style.background = map[y][x]; | |
} | |
} | |
} | |
SCRIPT | |
)); | |
$data->addContent($head); | |
$body = new HtmlTag('body'); | |
for($y = 0; $y < $size_y; $y++){ | |
for($x = 0; $x < $size_x; $x++){ | |
$id = 'block_'.$x.'_'.$y; | |
$body->addContent((new HtmlTag('div', array('id'=>$id)))->addContent(' ')); | |
} | |
$body->addContent('<br/>'); | |
} | |
$data = (string)$data->addContent($body); | |
$core->cache->set('layout.'.$size_x.'x'.$size_y.'@'.$speed, $data, 3600); | |
} | |
echo $data; | |
} | |
); | |
$core->router->register('invader', function($size_x = 40, $size_y = 30){ | |
$invader = new Invader; | |
echo $invader->getMap(abs((int)$size_x), abs((int)$size_y))->toJSON(); | |
}); | |
$core->execute(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment