[QUIZ#17] yaslaw (PHP)

Yaslaw

alter Rempler
Moderator
Hatte leider nur grad kurz Zeit (2 Stunden) für die Aufgabe 1.

Als Fragen-Antwort-Quelle dient mir dei Datei von Matthias Reitinger.

Dazu habe ich diese einfache Klasse erstellt
Aufgabe1.php
PHP:
<?php
class Aufgabe1{
    const C_DATA_FILE = 'fragen.csv.txt';
    
    /**
     * Construkter
     * @param $length Länge des Losungswortes 
     */
    public function __construct($length = false){
        //Liste einlesen
        foreach(file(self::C_DATA_FILE) as $id => $entry){
            list($this->words[$id], $this->questions[$id]) = explode(';', $entry);
        }
        //Losungswort aussuchen
        //Wenn die Länge mitgegeben wurde, die Wörter aus der Liste nach Wortlänge filtern
        if ($length !== false && is_numeric($length)) {
            $words = array_filter($this->words, create_function('$word', "return strlen(\$word) == {$length};"));
        } else {
            $words =$this->words;
        }
        //Ein beliebiges Wort aus der gefilterten Liste aussuchen
        $this->myWord = $words[array_rand($words)];
        //Die Horizontalen Wörter/Antworten auslesen
        $this->createAnswers();
        //Ausgabe vorbereiten
        $this->prepareOutput();
    }
    
    /**
     * Pro Buchstabe ein Wort definieren
     */
    protected function createAnswers(){
        //Pro Buchstabe des Losungswortes ein Wort aussuchen
        foreach(str_split($this->myWord) as $this->letter){
            //Filtern nach dem Buchstaben
            $selWords = array_filter($this->words, array($this,'filterByLetter'));
            //Ein zufälliges Wort aussuchen
            $id = array_rand($selWords);
            $word = $selWords[$id];
         
            //Nur die Losungsbuchstaben ausfiltern und davon zufällig einen aussuchen
            $pos = array_rand(array_filter(str_split($word), array($this,'filterByLetter')));

            //Antworten speichern
            $this->answers[] = compact('id', 'word', 'pos');
            
            //Wort aus der Liste entfernen, damit es nicht nochmal gewählt wird  
            unset($this->words[$id]);
            
            //'Geometrie' bestimmen
            $this->maxPos = max($this->maxPos, $pos);
            $this->length = max($this->length, strlen($word));
        }
                
    }
    
    /**
     * Aufbereiten der formatierten Ausgabe
     */
    protected function prepareOutput(){
        foreach($this->answers as $key => $entry){
            $row['nr'] = $key + 1;
            //Fragen speichern
            $this->selectedQuestions[] = array('nr' => $row['nr'], 'question' => $this->questions[$entry['id']]);
            
            //Links und Rechts die nicht verwedneten Felder ermitteln (colspan)
            $row['leftLen'] = $this->maxPos - $entry['pos']+1;
            $row['rightLen'] = $this->length - ($leftLen + strlen($entry['word']));
            
            //Die Quiz-Zeile erstellen
            $this->quizs[] = self::getFormatedWord($entry['word'], $entry['pos'], $row, false);
            //Die Lösungszeile erstellen 
            $this->losungen[] = self::getFormatedWord($entry['word'], $entry['pos'], $row, true); 
        }        
    }
    
    /**
     * formatiert das Wort als Tabellenfelder
     * @param String $word
     * @param Number $pos
     * @param Number $row
     * @param Boolean $asAnswer
     * @return String
     */
    protected static function getFormatedWord($word, $pos, $row, $asAnswer){
        //Array mit allen Buchstaben erstellen. Wenn nicht die Antwort mitgegeben wird, dann leerzeichen
        $letters = ($asAnswer) ? str_split($word) : array_fill(0, strlen($word), '&nbsp;');
        //Jeder Buchstabe als Tabellenfeld formatieren
        array_walk($letters, array(self, 'formatLetter'), $pos);
        //Die Zeilenausgabe um die formatierten Fleder ergänzen            
        $row['word'] = implode($letters); 
        return $row;
        
    }
     
    /**
     * Callback-Function um die Buchstaben als Tabellenfeld zu formatieren
     * @param String $item
     * @param Number $letterPos
     * @param Number_type $pos
     */
    protected static function formatLetter(&$item, $letterPos, $pos){
        $tag = ($letterPos == $pos) ? 'th' : 'td';
        $item = "<{$tag} class='word'>{$item}</{$tag}>";
    }
    
    /**
     * Callback-Function für array_filter
     * @param String $word
     * @return Boolean
     */
    protected function filterByLetter($word){
        return stripos($word, $this->letter) !== false;
    }    
}
?>

Dazu ein kleines Template, dass die Ausgabe formatiert
templateAufgabe1.php
PHP:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN">
<html>
    <head>
        <!-- Style definitionen -->
        <style type="text/css">
            table, tr { border:1px solid #000;}
            th {
                width:25px; 
                background-color:#FFFFCC;}
            td {width:25px;}
            .word {
                border:1px solid #000;
                align:center;
                valign:middle;}
        </style>
    </head>
    
    <body>
        <h2>Rätsel</h2>
        <table>
            <?php foreach($obj->quizs as $row){ ?>
                <tr>
                    <td><?=$row['nr']; ?>:</td>
                    <td colspan="<?=$row['leftLen']; ?>">&nbsp;</td>
                        <?=$row['word'];?>
                    <td colspan="<?=$row['rightLen']; ?>">&nbsp;</td>
                </tr>
            <?php } //END $obj->quizs ?>
        </table>
        <hr />
        <p>
            <?php foreach($obj->selectedQuestions as $row){ ?>
                <?=$row['nr'];?>: <?=$row['question'];?><br />
            <?php } //END $obj->selectedQuestions ?>
        </p>
        <h2>Lösung</h2>
        <?=$obj->myWord;?>
        <hr />
        <table>
            <?php foreach($obj->losungen as $row){?>
                <tr>
                    <td><?=$row['nr']; ?>:</td>
                    <td colspan="<?=$row['leftLen']; ?>">&nbsp;</td>
                        <?=$row['word'];?>
                    <td colspan="<?=$row['rightLen']; ?>">&nbsp;</td>
                </tr>
            <?php } //END $obj->losungen ?>
        </table>

    </body>
</html>

Und natürlich noch das index.php, das als Einstieg verwendet wird
index.php
PHP:
<?php
/**
 * Funktion exceptionErrorHandler
 * Fehlerbehandlung sauber definieren. Alle Errors als Exception ausgeben
 * @link exceptionErrorHandler.php: http://wiki.yaslaw.info/wikka/PhpErrorsAsExceptions
 */
include_once('functions/exceptionErrorHandler.php');
/**
 * Funktion filterInputDefaults
 * erweitert filter_input_array um 'default'
 * @link filterInputDefaults.php: http://wiki.yaslaw.info/wikka/PhpFilterInputDefaults
 */
include_once('functions/filterInputDefaults.php');

/**
 * GET - Definionen
 * Es ist nur ein Parameter zugellassen.
 * @param   len: Länge des Losungswortes 
 * @example quiz17/index.php?len=5
 */
$definition = array('len' =>  array(
                                'filter' => FILTER_VALIDATE_INT,
                                'options' => array('min_range' => 3, 'max_range' => 50),
                                'default' => false));
$get = filterInputDefaults(INPUT_GET, $definition);

//Klasse für die Aufgabe 1 einbinden
include_once('Aufgabe1.php');

//Mein Aufgabe1-Objekt anlegen
$obj = new Aufgabe1($get['len']);

//Ausgabe
include_once('templateAufgabe1.php');
?>

Die 2 Funktionen die ich am Anfang einbinde findet ihr hier
exceptionErrorHandler.php
filterInputDefaults.php
 
Zuletzt bearbeitet:
Zurück