Last active
August 15, 2019 01:55
-
-
Save BEcraft/f3e5ea7a58d0376dab3f53ac49f9c7de to your computer and use it in GitHub Desktop.
Un simple concepto de logros en PHP
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 declare(strict_types = 1); | |
namespace Logros; | |
use ReflectionFunction, Exception, OutOfRangeException, ArrayObject; | |
############################################################### | |
# > Ejemplo simple de un sistema de logros por BEcraft. # | |
############################################################### | |
# > Clase principal para los logros: | |
abstract class Logro | |
{ | |
protected $evento, $ejecutor, $descripcion, $configuracion; | |
public function __construct(array $datos = [], callable $ejecutor, string $descripcion) | |
{ | |
$this->validarEjecutor($ejecutor); | |
$this->ejecutor = $ejecutor; | |
$this->descripcion = $descripcion; | |
$this->configuracion = new Configuracion($datos); | |
} | |
public function validarEjecutor(callable $ejecutor): void | |
{ | |
$parametros = (new ReflectionFunction($ejecutor))->getParameters(); | |
if (count($parametros) < 2) | |
{ | |
throw new OutOfRangeException("El número de parametros dado en el ejecutor ha de ser mayor a 1."); | |
} | |
$secuencia = ["Logros\Evento", "Logros\Configuracion"]; //Clases | |
foreach ($secuencia as $i => $tipo) | |
{ | |
$parametro = (string) $parametros[$i]->getType(); | |
if ( ! (class_exists($parametro, false)) || ! (is_a($parametro, $tipo, true))) | |
{ | |
throw new Exception("No se ha podido encontrar una relacion de \"{$tipo2}\" con la clase {$tipo}."); | |
} | |
$secuencia[$i] = $parametro; | |
} | |
$this->evento = $secuencia[0]; | |
} | |
public function procesarEvento(Evento $evento): void | |
{ | |
if ($this->Completado() || get_class($evento) !== $this->evento) | |
{ | |
return; | |
} | |
if (($respuesta = ($this->ejecutor)($evento, $this->configuracion)) === 0) | |
{ | |
return; | |
} | |
$this->configuracion->Progreso($respuesta); | |
} | |
public function Completado(): bool | |
{ | |
return ($this->configuracion->Progreso() >= 100); | |
} | |
public function GuardarLogro(int $banderas = 0): string | |
{ | |
return json_encode($this->configuracion, ($banderas | JSON_PRETTY_PRINT)); | |
} | |
public function Descripcion(): string | |
{ | |
return $this->descripcion; | |
} | |
} | |
# > Logro #1: | |
class SaludarLogro extends Logro | |
{ | |
public function __construct(array $datos = []) | |
{ | |
parent::__construct($datos, function (HablarEvento $evento, Configuracion $configuracion) { | |
if (strtolower($evento->Mensaje()) !== "hola") | |
{ | |
return 0; | |
} | |
return 100; | |
}, "Escribe \"Hola\""); | |
} | |
} | |
# > Logro #2: | |
class ContarHastaCinco extends Logro | |
{ | |
public function __construct(array $datos = []) | |
{ | |
parent::__construct($datos, function (HablarEvento $evento, Configuracion $configuracion) { | |
$numero = (int) $evento->Mensaje(); | |
$conteo = (int) $configuracion->offsetGet("conteo"); | |
if (++$conteo === $numero) | |
{ | |
$configuracion->offsetSet("conteo", $numero); return (($numero / 5) * 100); | |
} | |
return 0; | |
}, "¡Debes contar hasta 5!"); | |
} | |
} | |
# > Almacenamiento para los datos del logro, puede ser un arreglo cualquiera. | |
class Configuracion extends ArrayObject | |
{ | |
public function __construct(array $datos) | |
{ | |
parent::__construct($datos, ArrayObject::ARRAY_AS_PROPS); | |
} | |
public function Progreso(?float $progreso = null): float | |
{ | |
if ($progreso === null) | |
{ | |
return (float) ($this->offsetGet("progreso") ?? 0); | |
} | |
$this->offsetSet("progreso", $progreso); return 0; | |
} | |
} | |
# > Inicio de simulación de eventos: | |
class HablarEvento extends Evento | |
{ | |
private $mensaje; | |
public function __construct(Usuario $usuario, string $mensaje) | |
{ | |
parent::__construct($usuario); | |
$this->mensaje = $mensaje; | |
} | |
public function Mensaje(): string | |
{ | |
return $this->mensaje; | |
} | |
} | |
abstract class Evento | |
{ | |
protected $usuario; | |
public function __construct(Usuario $usuario) | |
{ | |
$this->usuario = $usuario; | |
} | |
public function Usuario(): Usuario | |
{ | |
return $this->usuario; | |
} | |
} | |
# > Fin de simulación de eventos. | |
class Usuario | |
{ | |
protected $nombre; | |
public function __construct(string $nombre) | |
{ | |
$this->nombre = $nombre; | |
} | |
public function Nombre(): string | |
{ | |
return $this->nombre; | |
} | |
} | |
$logros = [new SaludarLogro(), new ContarHastaCinco()]; # > Puedes crear una clase de trabaje con los logros. | |
$usuario = new Usuario("Edita"); | |
$guardado = []; | |
echo "Logros disponibles: " . PHP_EOL; | |
foreach ($logros as $logro) | |
{ | |
echo get_class($logro) . " -> " . $logro->Descripcion() . PHP_EOL; | |
} | |
# > Método solo de prueba. | |
function procesar() | |
{ | |
global $logros, $usuario, $guardado; | |
while(count($logros) > 0) | |
{ | |
$evento = new HablarEvento($usuario, trim(fgets(STDIN))); | |
# > Ejemplo de como se guardan los logros: | |
if ($evento->Mensaje() === "guardar") | |
{ | |
# > Al guardar el logro: | |
foreach ($logros as $logro) | |
{ | |
$guardado[get_class($logro)] = $logro->GuardarLogro(); | |
} | |
$logros = []; | |
echo "Logros guardados: " . implode(", ", array_map(function ($i) use ($guardado) { | |
return key($guardado) . " -> " . $i; next($guardado); | |
}, $guardado)) . PHP_EOL; | |
# > Al cargar el logro: | |
foreach ($guardado as $i => $datos) | |
{ | |
$logros[] = new $i(json_decode($datos, true)); | |
} | |
$guardado = []; | |
return procesar(); | |
} | |
# > Procesar el evento: | |
foreach ($logros as $i => $logro) | |
{ | |
$logro->procesarEvento($evento); | |
if ($logro->Completado()) | |
{ | |
echo("[¡] Se ha completado el logro " . get_class($logro) . PHP_EOL); unset($logros[$i]); | |
} | |
} | |
} | |
} | |
procesar(); | |
if ($logros === []) | |
{ | |
echo "¡Felicidades " . $usuario->Nombre() . ", has completado todos los logros!" . PHP_EOL; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment