kuddeldaddeldu
Erfahrenes Mitglied
Hi,
ich hatte zwar wenig Zeit und bin nicht fertig, aber angesichts der Uhrzeit stelle ich schon mal die bisherige Lösung rein. Bei Aufgabe B fehlen noch die Erweiterungen.
Basisklassen, die von allen Turtles genutzt, bzw. erweitert werden:
Plotter.php (abstrakte Klasse)
SVGPlotter.php (konkrete SVG-Implementierung der Klasse Plotter
Factory.php (liefert eine Instanz des konkret benötigten Plotters)
Turtle.php (abstrakte Klasse)
Aufgabe A:
TurtleA.php (konkrete Implementierung von Turtle)
Parameter ist der Pfad auf die Turtle-Datei.
Erweiterung:
TurleA_ext.php (konkrete Implementierung von Turtle)
Aufgabe B:
TurtleB.php (konkrete Implementierung von Turtle)
Vielleicht liefer ich die Erweiterungen noch nach.
LG
ich hatte zwar wenig Zeit und bin nicht fertig, aber angesichts der Uhrzeit stelle ich schon mal die bisherige Lösung rein. Bei Aufgabe B fehlen noch die Erweiterungen.
Basisklassen, die von allen Turtles genutzt, bzw. erweitert werden:
Plotter.php (abstrakte Klasse)
PHP:
<?php
abstract class Plotter {
protected $name;
protected $width;
protected $height;
protected $buffer;
public function __construct($name, $width, $height) {
$this->name = $name;
$this->height = $height;
$this->width = $width;
}
abstract public function draw_line($x1, $y1, $x2, $y2);
abstract public function draw_polyline($line);
}
?>
SVGPlotter.php (konkrete SVG-Implementierung der Klasse Plotter
PHP:
<?php
require_once 'Plotter.php';
class SVGPlotter extends Plotter {
private $doc_tpl = '<?xml version="1.0" ?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="{width}" height="{height}" stroke="black" fill="none">
{content}
</svg>';
private $line_tpl = '<line x1="%d" y1="%d" x2="%d" y2="%d" />';
private $polyline_tpl = '<polyline points="%s" />';
private $svg = '';
public function __construct($name, $width, $height) {
parent::__construct($name, $width, $height);
$this->svg = str_replace(array('{width}', '{height}'), array($width, $height), $this->doc_tpl);
$this->buffer = '';
}
public function __destruct() {
$this->svg = str_replace('{content}', $this->buffer, $this->svg);
file_put_contents($this->name . '.svg', $this->svg);
}
public function draw_line($x1, $y1, $x2, $y2) {
$this->buffer .= sprintf($this->line_tpl, $x1, $this->height - $y1, $x2, $this->height - $y2) . "\n";
}
public function draw_polyline($coordinates) {
$points = array();
foreach($coordinates as $point) {
$points[] = sprintf('%F %F', $point[0], $this->height - $point[1]);
}
$this->buffer .= sprintf($this->polyline_tpl, implode(',', $points));
}
}
?>
Factory.php (liefert eine Instanz des konkret benötigten Plotters)
PHP:
<?php
class Factory {
public static function getPlotter($type, $target, $width, $height) {
switch($type) {
case 'svg':
$classname = 'SVGPlotter';
break;
}
require_once($classname . '.php');
return new $classname($target, $width, $height);
}
}
?>
Turtle.php (abstrakte Klasse)
PHP:
<?php
abstract class Turtle {
protected $phi = 0;
protected $angle;
protected $x;
protected $y;
protected $stepwidth;
protected $actions;
protected $name;
protected $width;
protected $height;
abstract public function parseInput($input);
abstract public function run();
public function __construct($inputFile) {
$this->parseInput(file_get_contents($inputFile));
$this->setName(basename($inputFile, '.turtle'));
}
protected function getName() {
return $this->name;
}
protected function getX() {
return $this->x;
}
protected function getY() {
return $this->y;
}
protected function getPhi() {
return $this->phi;
}
protected function getAngle() {
return $this->angle;
}
protected function getStepwidth() {
return $this->stepwidth;
}
protected function getActions() {
return $this->actions;
}
protected function getWidth() {
return $this->width;
}
protected function getHeight() {
return $this->height;
}
protected function setName($name) {
$this->name = $name;
}
protected function setX($x) {
$this->x = $x;
}
protected function setY($y) {
$this->y = $y;
}
protected function setPhi($phi) {
$this->phi = $phi;
}
protected function setAngle($angle) {
$this->angle = $angle * M_PI / 180.0;
}
protected function setStepwidth($stepwidth) {
$this->stepwidth = $stepwidth;
}
protected function setActions($actions) {
$this->actions = $actions;
}
protected function setWidth($width) {
$this->width = $width;
}
protected function setHeight($height) {
$this->height = $height;
}
protected function incrementPhi() {
$this->setPhi($this->getPhi() + $this->getAngle());
}
protected function decrementPhi() {
$this->setPhi($this->getPhi() - $this->getAngle());
}
}
?>
Aufgabe A:
TurtleA.php (konkrete Implementierung von Turtle)
PHP:
<?php
require_once 'Turtle.php';
require_once 'Factory.php';
class TurtleA extends Turtle {
public function parseInput($input) {
$params = sscanf($input, "%d %d\n%d %d\n%d\n%d\n%s");
$this->setWidth($params[0]);
$this->setHeight($params[1]);
$this->setX($params[2]);
$this->setY($params[3]);
$this->setStepwidth($params[4]);
$this->setAngle($params[5]);
$this->setPhi(0);
$this->setActions(str_split($params[6]));
}
public function run() {
$plotter = Factory::getPlotter('svg', $this->getName(), $this->getWidth(), $this->getHeight());
foreach($this->getActions() as $action) {
switch($action) {
case 'F':
$plotter->draw_line($this->getX(), $this->getY(), $this->getX() + $this->getStepwidth()*cos($this->getPhi()), $this->getY() + $this->getStepwidth()*sin($this->getPhi()));
$this->setX($this->getX() + $this->getStepwidth()*cos($this->getPhi()));
$this->setY($this->getY() + $this->getStepwidth()*sin($this->getPhi()));
break;
case '+':
$this->incrementPhi();
break;
case '-':
$this->decrementPhi();
break;
}
}
}
}
$turtle = new TurtleA($argv[1]);
$turtle->run();
?>
Parameter ist der Pfad auf die Turtle-Datei.
Erweiterung:
TurleA_ext.php (konkrete Implementierung von Turtle)
PHP:
<?php
require_once 'Turtle.php';
require_once 'Factory.php';
class TurtleA extends Turtle {
private $stack;
private $pos;
private function getPos() {
return $this->pos;
}
private function setPos($pos) {
$this->pos = $pos;
}
private function incrementPos() {
$this->pos++;
}
private function setStack($stack) {
$this->stack = $stack;
}
private function getAction($pos) {
return $this->actions[$pos];
}
private function pushStack() {
$this->stack[] = array($this->getX(), $this->getY(), $this->getPhi());
}
private function popStack() {
$state = array_pop($this->stack);
$this->setX($state[0]);
$this->setY($state[1]);
$this->setPhi($state[2]);
}
public function __construct($inputFile) {
parent::__construct($inputFile);
$this->setStack(array());
$this->setPos(0);
}
public function parseInput($input) {
$params = sscanf($input, "%d %d\n%d %d\n%d\n%d\n%s");
$this->setWidth($params[0]);
$this->setHeight($params[1]);
$this->setX($params[2]);
$this->setY($params[3]);
$this->setStepwidth($params[4]);
$this->setAngle($params[5]);
$this->setPhi(0);
$this->setActions(str_split($params[6]));
}
public function run() {
$plotter = Factory::getPlotter('svg', $this->getName(), $this->getWidth(), $this->getHeight());
while($this->getPos() < count($this->actions)) {
switch($this->getAction($this->getPos())) {
case '[':
$this->pushStack();
break;
case ']':
$this->popStack();
break;
case 'F':
$plotter->draw_line($this->getX(), $this->getY(), $this->getX() + $this->getStepwidth()*cos($this->getPhi()), $this->getY() + $this->getStepwidth()*sin($this->getPhi()));
$this->setX($this->getX() + $this->getStepwidth()*cos($this->getPhi()));
$this->setY($this->getY() + $this->getStepwidth()*sin($this->getPhi()));
break;
case '+':
$this->incrementPhi();
break;
case '-':
$this->decrementPhi();
break;
}
$this->incrementPos();
}
}
}
$turtle = new TurtleA($argv[1]);
$turtle->run();
?>
Aufgabe B:
TurtleB.php (konkrete Implementierung von Turtle)
PHP:
<?php
require_once 'Turtle.php';
require_once 'Factory.php';
class TurtleB extends Turtle {
private $stack;
private $pos;
private $polyline;
private $plotter;
private $substitutions;
private function setSubstitutions($substitutions) {
$this->substitutions = $substitutions;
}
private function getPos() {
return $this->pos;
}
private function setPos($pos) {
$this->pos = $pos;
}
private function setStack($stack) {
$this->stack = $stack;
}
private function getPolyline() {
return $this->polyline;
}
private function getPolylineSize() {
return count($this->getPolyline());
}
private function resetPolyline() {
$this->polyline = array();
}
private function pushPolyline($x, $y) {
$this->polyline[] = array($x, $y);
}
private function incrementPos() {
$this->pos++;
}
private function getAction($pos) {
return $this->actions[$pos];
}
private function pushStack() {
$this->stack[] = array($this->getX(), $this->getY(), $this->getPhi());
}
private function popStack() {
$state = array_pop($this->stack);
$this->setX($state[0]);
$this->setY($state[1]);
$this->setPhi($state[2]);
}
public function __construct($inputFile) {
parent::__construct($inputFile);
$this->setStack(array());
$this->resetPolyline();
$this->pushPolyline($this->getX(), $this->getY());
$this->setPos(0);
}
public function parseInput($input) {
$params = sscanf($input, "%d %d\n%f %f\n%f\n%f\n%s\n%d\n%s");
$this->setWidth($params[0]);
$this->setHeight($params[1]);
$this->setX($params[2]);
$this->setY($params[3]);
$this->setStepwidth($params[4]);
$this->setAngle($params[5]);
$iterations = $params[7];
$substitution = $params[8];
$actions = $params[6];
for($i = 0; $i < $iterations; $i++) {
$actions = str_replace('F', $substitution, $actions);
}
$this->setPhi(0);
$this->setActions(str_split($actions));
}
public function run() {
$this->plotter = Factory::getPlotter('png', $this->getName(), $this->getWidth(), $this->getHeight());
while($this->getPos() < count($this->actions)) {
switch($this->getAction($this->getPos())) {
case '[':
$this->pushStack();
break;
case ']':
if($this->getPolyline()) {
$this->plotter->draw_polyline($this->getPolyline());
}
$this->popStack();
$this->resetPolyline();
$this->pushPolyline($this->getX(), $this->getY());
break;
case 'F':
$this->setX($this->getX() + $this->getStepwidth()*cos($this->getPhi()));
$this->setY($this->getY() + $this->getStepwidth()*sin($this->getPhi()));
$this->pushPolyline($this->getX(), $this->getY());
if($this->getPolylineSize() > 50) {
$this->plotter->draw_polyline($this->getPolyline());
$this->resetPolyline();
$this->pushPolyline($this->getX(), $this->getY());
}
break;
case '+':
$this->incrementPhi();
break;
case '-':
$this->decrementPhi();
break;
}
$this->incrementPos();
}
if($this->getPolylineSize() > 0) {
$this->plotter->draw_polyline($this->getPolyline());
}
}
}
$turtle = new TurtleB($argv[1]);
$turtle->run();
?>
Vielleicht liefer ich die Erweiterungen noch nach.
LG
Zuletzt bearbeitet: