Spring naar hoofdtekst

Random StarTrek episode selector

Geplaatst op door ,
Laatste aanpassing op .

Inleiding

Heb je dat ook wel eens? De volledige collectie van alle StarTrek televisieseries staat in je kast of op je harde schijf, en je hebt geen idee welke aflevering je vandaag wil bekijken. Dit PHP-script neemt je die keuze uit handen en selecteert een willekeurige aflevering uit een willekeurig seizoen van een willekeurige serie.

Dit was mijn eerste project waarin ik zelf een XML-schema schreef en daarna het bijbehorende XML-bestand vulde met behulp van MemoryAlpha. De uitvoer van het script ziet er als volgt uit:

Today's random StarTrek episode:  
TOS 2x04 Who Mourns for Adonais?

Klik om het complete pakket, het XML-bestand of het XML-schema te downloaden.

Update

Na twaalf jaar radiostilte is er een nieuwe serie aan de StarTrek canon toegevoegd: Discovery. De tot nu toe bekendegemaakte afleveringen van het eerste seizoen heb ik aan dit script en bijbehorende bestanden toegevoegd.

Script

<?php

error_reporting(E_ALL);
ini_set('display_errors', '1');
date_default_timezone_set(@date_default_timezone_get());

$x = new DOMDocument();
$o = array();
$p = dirname(__FILE__);

if(@$x->load($p.'/data.xml') && @$x->schemaValidate($p.'/schema.xsd')) {
    foreach ($x->getElementsByTagName('Series') as $series) {
        $sr = new Series(
            $series->getAttribute('code'),
            $series->getAttribute('name')
        );

        foreach ($series->getElementsByTagName('Season') as $season) {
            $se = new Season(
                (int)$season->getAttribute('number')
            );

            foreach ($season->getElementsByTagName('Episode') as $episode) {
                $ep = new Episode(
                    (int)$episode->getAttribute('number'),
                    (string)$episode->getAttribute('name'),
                    (int)strtotime($episode->getAttribute('airdate'))
                );
                $se->episodes[] = $ep;
            }
            $sr->seasons[] = $se;
        }
        $o[] = $sr;
    }
    $randSeries = $o[array_rand($o)];
    $randSeason = $randSeries->seasons[array_rand($randSeries->seasons)];
    $randEpisode = $randSeason->episodes[array_rand($randSeason->episodes)];

    $outputFormat =
        "<pre>Today's random StarTrek episode:<br />".
        "<a href=\"http://en.memory-alpha.org/wiki/%1\$s\">%1\$s</a> ".
        "<a href=\"http://en.memory-alpha.org/wiki/%1\$s_Season_%2\$d\">%2\$dx%3\$02d</a> ".
        "<a href=\"http://en.memory-alpha.org/wiki/%5\$s_(episode)\">%4\$s</a>".
        "</pre>"; 

    if(isset($argv) && $argc > 0) {
        $outputFormat =
            "Today's random StarTrek episode:\n".
            "%1\$s %2\$dx%3\$02d %4\$s\n";
    }
    printf($outputFormat,
        $randSeries->code,
        $randSeason->number,
        $randEpisode->number,
        $randEpisode->name,
        str_replace(' ', '_', $randEpisode->name)
    );
}

class Series
{
    public $code;
    public $name;
    public $seasons;

    public function __construct($code, $name) {
        $this->code = $code;
        $this->name = $name;
    }
}
class Season
{
    public $number;
    public $episodes;

    public function __construct($number) {
        $this->number = $number;
    }
}
class Episode
{
    public $number;
    public $name;
    public $airdate;

    public function __construct($number, $name, $airdate) {
        $this->number = $number;
        $this->name = $name;
        $this->airdate = $airdate;
    }
}

XML-data

Hieronder een verkorte weergave van het volledige XML-bestand.

<?xml version="1.0" encoding="UTF-8"?>
<StarTrek xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="schema.xsd" xmlns="">

    <Series code="TOS" name="The Original Series">
        <Season number="1">
            <Episode number="1" airdate="1988-10-04" name="The Cage"/>
            <Episode number="1" airdate="1966-09-22" name="Where No Man Has Gone Before"/>
            <Episode number="2" airdate="1966-11-10" name="The Corbomite Maneuver"/>
            <!-- ... -->
        </Season>
        <!-- ... -->
    </Series>

    <Series code="TAS" name="The Animated Series">
        <Season number="1">
            <Episode number="1" airdate="1973-09-08" name="Beyond the Farthest Star"/>
            <!-- ... -->
        </Season>
        <Season number="2">
            <!-- ... -->
        </Season>
    </Series>

    <Series code="TNG" name="The Next Generation">
        <Season number="1">
            <Episode number="1" airdate="1987-09-28" name="Encounter at Farpoint, Part I"/>
            <!-- ... -->
        </Season>
        <!-- ... -->
    </Series>

    <Series code="DS9" name="Deep Space 9">
        <Season number="1">
            <Episode number="1" airdate="1993-01-03" name="Emissary"/>
            <!-- ... -->
        </Season>
        <!-- ... -->
    </Series>

    <Series code="VOY" name="Voyager">
        <Season number="1">
            <Episode number="1" airdate="1995-01-16" name="Caretaker"/>
            <!-- ... -->
        </Season>
        <!-- ... -->
    </Series>

    <Series code="ENT" name="Enterprise">
        <Season number="1">
            <Episode number="1" airdate="2001-09-26" name="Broken Bow"/>
            <!-- ... -->
        </Season>
        <!-- ... -->
    </Series>

    <Series code="DIS" name="Discovery">
        <Season number="1">
            <Episode number="1" airdate="2017-09-24" name="The Vulcan Hello" />
            <!-- ... -->
        </Season>
        <!-- ... -->
    </Series>

</StarTrek>

XSD-schema

En tot slot, het XML-schema om de data te valideren:

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">

  <xs:element name="StarTrek" type="TypeStarTrek">
    <xs:unique name="uniqueSeries">
      <xs:selector xpath="./Series" />
      <xs:field xpath="@code" />
    </xs:unique>
  </xs:element>

  <xs:complexType name="TypeStarTrek">
    <xs:sequence>
      <xs:element maxOccurs="7" minOccurs="7" name="Series"
        type="TypeSeries">
        <xs:unique name="uniqueSeasonNUmber">
          <xs:selector xpath="./Season" />
          <xs:field xpath="@number" />
        </xs:unique>
      </xs:element>
    </xs:sequence>
  </xs:complexType>

  <xs:complexType name="TypeSeries">
    <xs:sequence>
      <xs:element maxOccurs="7" minOccurs="1" name="Season"
        type="TypeSeason">
        <xs:unique name="uniqueEpisodeNumber">
          <xs:selector xpath="./Episode" />
          <xs:field xpath="@number" />
        </xs:unique>
      </xs:element>
    </xs:sequence>

    <xs:attribute name="code" type="SeriesCode" use="required" />
    <xs:attribute name="name" type="StringNonEmpty" use="required" />
  </xs:complexType>

  <xs:complexType name="TypeSeason">
    <xs:sequence>
      <xs:element maxOccurs="30" minOccurs="0" name="Episode"
        type="TypeEpisode">
      </xs:element>
    </xs:sequence>
    <xs:attribute name="number" type="SeasonNumber" use="required" />
  </xs:complexType>

  <xs:complexType name="TypeEpisode">
    <xs:attribute name="number" type="EpisodeNumber" use="required" />
    <xs:attribute name="airdate" type="DateEmpty" use="required" />
    <xs:attribute name="name" type="StringNonEmpty" use="required" />
  </xs:complexType>

  <xs:simpleType name="StringNonEmpty">
    <xs:restriction base="xs:string">
      <xs:minLength value="1" />
    </xs:restriction>
  </xs:simpleType>

  <xs:simpleType name="DateEmpty">
    <xs:union memberTypes="Empty xs:date" />
  </xs:simpleType>

  <xs:simpleType name="EpisodeNumber">
    <xs:restriction base="xs:integer">
      <xs:minInclusive value="0" />
      <xs:maxInclusive value="30" />
    </xs:restriction>
  </xs:simpleType>

  <xs:simpleType name="SeasonNumber">
    <xs:restriction base="xs:integer">
      <xs:minInclusive value="1" />
      <xs:maxInclusive value="7" />
    </xs:restriction>
  </xs:simpleType>

  <xs:simpleType name="SeriesCode">
    <xs:restriction base="xs:string">
      <xs:enumeration value="TOS" />
      <xs:enumeration value="TAS" />
      <xs:enumeration value="TNG" />
      <xs:enumeration value="DS9" />
      <xs:enumeration value="VOY" />
      <xs:enumeration value="ENT" />
      <xs:enumeration value="DIS" />
    </xs:restriction>
  </xs:simpleType>

  <xs:simpleType name="Empty">
    <xs:restriction base="xs:string">
      <xs:enumeration value="" />
    </xs:restriction>
  </xs:simpleType>

</xs:schema>

Inhoudsopgave

Klik op één van de onderstaande categorieën om de lijst met artikelen te filteren.