www/api/v1/games/*/
www/api/v1/search-data/
www/discover/
+www/game/
*
* @author Christian Weiske <cweiske@cweiske.de>
*/
+require_once __DIR__ . '/functions.php';
+
$wwwDir = __DIR__ . '/../www/';
$discoverDir = __DIR__ . '/../www/api/v1/discover-data/';
$wwwDiscoverDir = $wwwDir . 'discover/';
+$gameDetailsDir = __DIR__ . '/../www/api/v1/details-data/';
+$wwwGameDir = $wwwDir . 'game/';
if (!is_dir($wwwDiscoverDir)) {
mkdir($wwwDiscoverDir, 0755);
}
+if (!is_dir($wwwGameDir)) {
+ mkdir($wwwGameDir, 0755);
+}
+
+foreach (glob($gameDetailsDir . '*.json') as $gameDataFile) {
+ $htmlFile = basename($gameDataFile, '.json') . '.htm';
+ file_put_contents(
+ $wwwGameDir . $htmlFile,
+ renderGameFile($gameDataFile)
+ );
+}
foreach (glob($discoverDir . '*.json') as $discoverFile) {
$htmlFile = basename($discoverFile, '.json') . '.htm';
$sections[] = $section;
}
+ $navLinks = [];
+ if ($title == 'DISCOVER') {
+ $navLinks['../'] = 'back';
+ } else {
+ $navLinks['./'] = 'discover';
+ }
+
$discoverTemplate = __DIR__ . '/../data/templates/discover.tpl.php';
ob_start();
include $discoverTemplate;
return $html;
}
+
+function renderGameFile($gameDataFile)
+{
+ $json = json_decode(file_get_contents($gameDataFile));
+ $appsDir = dirname($gameDataFile, 2) . '/apps/';
+ $downloadJson = json_decode(
+ file_get_contents(
+ $appsDir . $json->version->uuid . '-download.json'
+ )
+ );
+ $apkDownloadUrl = $downloadJson->app->downloadLink;
+
+ $navLinks = [];
+ foreach ($json->genres as $genreTitle) {
+ $url = '../discover/' . categoryPath($genreTitle) . '.htm';
+ $navLinks[$url] = $genreTitle;
+ }
+
+ $gameTemplate = __DIR__ . '/../data/templates/game.tpl.php';
+ ob_start();
+ include $gameTemplate;
+ $html = ob_get_contents();
+ ob_end_clean();
+
+ return $html;
+}
?>
rm www/api/v1/discover-data/*
rm www/api/v1/games/*/*
rm www/api/v1/search-data/*
+rm www/discover/*
+rm www/game/*
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>OUYA: <?= htmlspecialchars($title); ?></title>
+ <meta name="generator" content="stouyapi"/>
<link rel="stylesheet" type="text/css" href="../ouya-discover.css"/>
</head>
<body class="discover">
<header>
<h1><?= htmlspecialchars($title); ?></h1>
+ <img class="ouyalogo" src="../ouya-logo.grey.svg" alt="OUYA logo" width="20%"/>
</header>
<?php foreach ($sections as $section): ?>
</section>
<?php endforeach; ?>
+
+ <nav>
+ <?php foreach ($navLinks as $url => $title): ?>
+ <a rel="up" href="<?= htmlspecialchars($url) ?>"><?= htmlspecialchars($title) ?></a>
+ <?php endforeach ?>
+ </nav>
</body>
</html>
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title><?= htmlspecialchars($json->title); ?> - OUYA game</title>
+ <meta name="generator" content="stouyapi"/>
+ <link rel="stylesheet" type="text/css" href="../ouya-game.css"/>
+ </head>
+ <body class="game">
+ <header>
+ <img class="ouyalogo" src="../ouya-logo.grey.svg" alt="OUYA logo" width="20%"/>
+ </header>
+ <section class="text">
+ <h1><?= htmlspecialchars($json->title); ?></h1>
+ <dl class="meta">
+ <dt>Rating</dt>
+ <dd class="rating">
+ <span class="average average-<?= round($json->rating->average) ?>"><?= $json->rating->average ?></span>
+ <span class="count">(<?= $json->rating->count ?>)</span>
+ </dd>
+
+ <dt>Developer</dt>
+ <dd class="company">
+ <?= htmlspecialchars($json->developer->name) ?>
+ </dd>
+
+ <dt>Suggested age</dt>
+ <dd class="contentRating">
+ <?= htmlspecialchars($json->suggestedAge) ?>
+ </dd>
+
+ <dt>Number of players</dt>
+ <dd class="players">
+ <?= htmlspecialchars(implode(', ', $json->gamerNumbers)) ?>
+ </dd>
+
+ <dt>Download size</dt>
+ <dd class="size">
+ <?= number_format($json->apk->fileSize / 1024 / 1024, 2) ?> MiB
+ </dd>
+ </dl>
+
+ <p class="description">
+ <?= nl2br(htmlspecialchars($json->description)) ?>
+ </p>
+ </section>
+
+ <section class="media">
+ <h2>Screenshots</h2>
+ <div class="content">
+ <?php foreach ($json->mediaTiles as $tile): ?>
+ <?php if ($tile->type == 'image'): ?>
+ <img src="<?= htmlspecialchars($tile->urls->thumbnail) ?>" alt="Screenshot of <?= htmlspecialchars($json->title); ?>"/>
+ <?php elseif ($tile->type == 'video'): ?>
+ <video controls="">
+ <source src="<?= htmlspecialchars($tile->url) ?>"/>
+ </video>
+ <?php endif ?>
+ <?php endforeach ?>
+ </div>
+ </section>
+
+ <section class="buttons">
+ <div>
+ <a href="<?= $apkDownloadUrl ?>">Download .apk</a>
+ <p>
+ Version <?= $json->version->number ?>, published
+ <?= gmdate('Y-m-d', $json->version->publishedAt) ?>
+ </p>
+ </div>
+ </section>
+
+ <nav>
+ <?php foreach ($navLinks as $url => $title): ?>
+ <a rel="up" href="<?= htmlspecialchars($url) ?>"><?= htmlspecialchars($title) ?></a>
+ <?php endforeach ?>
+ </nav>
+ </body>
+</html>
width: 100%;
padding-left: 3ex;
}
+.ouyalogo {
+ height: 3rem;
+ width: auto;
+ position: fixed;
+ top: 2ex;
+ right: 6vw;
+}
h2 {
text-shadow: 2px 2px #555;
padding-left: 2ex;
font-size: 80%;
}
+
+
+nav {
+ text-align: center;
+ margin-top: 6ex;
+ margin-bottom: 2ex;
+}
+nav a {
+ color: white;
+ margin-left: 1ex;
+ margin-right: 1ex;
+}
+
+
+/* rating stars */
.average {
visibility: hidden;
font-size: 0;
--- /dev/null
+body {
+ background-color: #333;
+ color: #CCC;
+ font-family: sans;
+ margin: 0;
+ padding: 0;
+ padding-top: 10ex;
+ padding-left: 5ex;
+
+ display: grid;
+ grid-template-columns: 45vw 45vw;
+ grid-gap: 1.5vw;
+}
+
+header {
+ position: fixed;
+ top: 0;
+ left: 0;
+ display: block;
+ width: 100%;
+ padding-left: 3ex;
+}
+.ouyalogo {
+ height: 3rem;
+ width: auto;
+ position: fixed;
+ top: 2ex;
+ right: 6vw;
+}
+
+section.media {
+ grid-column: 1;
+ grid-row: 1;
+}
+section.text {
+ grid-column: 2;
+ grid-row: 1;
+}
+
+section.buttons {
+ grid-column: 1 / 3;
+ grid-row: 2;
+}
+nav {
+ grid-column: 1 / 3;
+ grid-row: 3;
+}
+
+.media img, .media video {
+ max-width: 100%;
+ flex-basis: 100%;
+ flex-shrink: 0;
+}
+
+
+.media h2 {
+ display: none;
+}
+.media .content {
+ overflow-x: auto;
+ display: flex;
+ flex-direction: row;
+ scroll-snap-type: x mandatory;
+}
+.media .content img, .media .content video {
+ scroll-snap-align: start;
+}
+
+
+.text h1 {
+ font-weight: normal;
+ margin-top: 0;
+}
+.text dt {
+ display: none;
+}
+.text dd {
+ display: inline;
+ margin: 0;
+ font-weight: bold;
+}
+.text dd ~ dd:before {
+ content: "|";
+ font-weight: normal;
+}
+
+.description {
+ overflow-y: auto;
+ max-height: 50vh;
+}
+
+
+.buttons a {
+ font-size: 1.5rem;
+ color: #CCC;
+}
+
+nav {
+ text-align: center;
+}
+nav a {
+ color: white;
+ margin-left: 1ex;
+ margin-right: 1ex;
+}
+
+
+/* rating stars */
+.average {
+ visibility: hidden;
+ font-size: 0;
+}
+.average:before {
+ visibility: visible;
+ font-size: 1rem;
+ color: orange;
+}
+.average:after {
+ visibility: visible;
+ font-size: 1rem;
+}
+.average-0:after {
+ content: "★★★★★";
+}
+.average-1:before {
+ content: "★";
+}
+.average-1:after {
+ content: "★★★★";
+}
+.average-2:before {
+ content: "★★";
+}
+.average-2:after {
+ content: "★★★";
+}
+.average-3:before {
+ content: "★★★";
+}
+.average-3:after {
+ content: "★★";
+}
+.average-4:before {
+ content: "★★★★";
+}
+.average-4:after {
+ content: "★";
+}
+.average-5:before {
+ content: "★★★★★";
+}
--- /dev/null
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ sodipodi:docname="ouya-logo.svg"
+ inkscape:version="1.0rc1 (09960d6f05, 2020-04-09)"
+ id="svg4058"
+ height="200"
+ width="600"
+ version="1.1">
+ <sodipodi:namedview
+ inkscape:pagecheckerboard="true"
+ inkscape:document-rotation="0"
+ inkscape:current-layer="svg4058"
+ inkscape:window-maximized="1"
+ inkscape:window-y="33"
+ inkscape:window-x="0"
+ inkscape:cy="111.05604"
+ inkscape:cx="317.07029"
+ inkscape:zoom="2.8284271"
+ showgrid="false"
+ id="namedview13"
+ inkscape:window-height="984"
+ inkscape:window-width="1920"
+ inkscape:pageshadow="2"
+ inkscape:pageopacity="0"
+ guidetolerance="10"
+ gridtolerance="10"
+ objecttolerance="10"
+ borderopacity="1"
+ bordercolor="#666666"
+ pagecolor="#ffffff">
+ <inkscape:grid
+ id="grid14"
+ type="xygrid" />
+ </sodipodi:namedview>
+ <defs
+ id="defs4060" />
+ <metadata
+ id="metadata4063">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title></dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <g
+ id="layer1"
+ transform="matrix(0.70921753,0,0,0.70921753,16.312988,-575.43195)">
+ <g
+ id="g4050"
+ transform="translate(-32.826774,1321.6644)">
+ <path
+ inkscape:connector-curvature="0"
+ style="color:#CCCCCC;fill:none;stroke:#CCCCCC;stroke-width:11.98948383;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="path2999"
+ transform="matrix(1.0008772,0,0,1.0008772,21.2686,-884.25862)"
+ d="m 227.85715,514.50507 a 81.428575,81.428575 0 1 1 -162.85715,0 81.428575,81.428575 0 1 1 162.85715,0 z" />
+ <path
+ inkscape:connector-curvature="0"
+ style="color:#CCCCCC;fill:none;stroke:#CCCCCC;stroke-width:12.00000095;stroke-linecap:round;stroke-miterlimit:4;stroke-opacity:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="path2999-6"
+ d="m 423.60916,-446.45023 0.49999,87 c 0.22695,39.48771 -32.01164,71.64801 -71.5,71.64801 -39.48836,0 -71.49999,-32.01164 -71.5,-71.5 l 0,-87.14801" />
+ <path
+ inkscape:connector-curvature="0"
+ style="color:#CCCCCC;fill:none;stroke:#CCCCCC;stroke-width:12.00000095;stroke-linecap:round;stroke-miterlimit:4;stroke-opacity:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="path2999-6-5"
+ d="m 603.45555,-446.45023 0.5,37.05346 c 0.53281,39.48477 -32.01164,71.648 -71.5,71.648 -39.48836,0 -71.5,-32.01163 -71.5,-71.5 l 0,-37.20146" />
+ <path
+ inkscape:connector-curvature="0"
+ style="fill:#ff0000;stroke:#CCCCCC;stroke-width:12;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ id="path3998"
+ d="m 532.45878,-292.98077 0,-41.55194" />
+ <path
+ inkscape:connector-curvature="0"
+ style="color:#CCCCCC;fill:none;stroke:#CCCCCC;stroke-width:12.00000095;stroke-linecap:round;stroke-miterlimit:4;stroke-opacity:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="path2999-6-43"
+ d="m 636.82793,-292.45023 -0.5,-81.9747 c -0.24085,-39.48763 32.01164,-71.648 71.5,-71.648 39.48836,0 71.5,32.01163 71.5,71.49999 l 0,82.12271" />
+ <path
+ inkscape:connector-curvature="0"
+ style="fill:#ff0000;stroke:#CCCCCC;stroke-width:12;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ id="path3998-9"
+ d="m 637.16323,-345.75021 140.57043,0" />
+ </g>
+ </g>
+</svg>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ sodipodi:docname="ouya-logo.svg"
+ inkscape:version="1.0rc1 (09960d6f05, 2020-04-09)"
+ id="svg4058"
+ height="200"
+ width="600"
+ version="1.1">
+ <sodipodi:namedview
+ inkscape:pagecheckerboard="true"
+ inkscape:document-rotation="0"
+ inkscape:current-layer="svg4058"
+ inkscape:window-maximized="1"
+ inkscape:window-y="33"
+ inkscape:window-x="0"
+ inkscape:cy="111.05604"
+ inkscape:cx="317.07029"
+ inkscape:zoom="2.8284271"
+ showgrid="false"
+ id="namedview13"
+ inkscape:window-height="984"
+ inkscape:window-width="1920"
+ inkscape:pageshadow="2"
+ inkscape:pageopacity="0"
+ guidetolerance="10"
+ gridtolerance="10"
+ objecttolerance="10"
+ borderopacity="1"
+ bordercolor="#666666"
+ pagecolor="#ffffff">
+ <inkscape:grid
+ id="grid14"
+ type="xygrid" />
+ </sodipodi:namedview>
+ <defs
+ id="defs4060" />
+ <metadata
+ id="metadata4063">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title></dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <g
+ id="layer1"
+ transform="matrix(0.70921753,0,0,0.70921753,16.312988,-575.43195)">
+ <g
+ id="g4050"
+ transform="translate(-32.826774,1321.6644)">
+ <path
+ inkscape:connector-curvature="0"
+ style="color:#000000;fill:none;stroke:#000000;stroke-width:11.98948383;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="path2999"
+ transform="matrix(1.0008772,0,0,1.0008772,21.2686,-884.25862)"
+ d="m 227.85715,514.50507 a 81.428575,81.428575 0 1 1 -162.85715,0 81.428575,81.428575 0 1 1 162.85715,0 z" />
+ <path
+ inkscape:connector-curvature="0"
+ style="color:#000000;fill:none;stroke:#000000;stroke-width:12.00000095;stroke-linecap:round;stroke-miterlimit:4;stroke-opacity:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="path2999-6"
+ d="m 423.60916,-446.45023 0.49999,87 c 0.22695,39.48771 -32.01164,71.64801 -71.5,71.64801 -39.48836,0 -71.49999,-32.01164 -71.5,-71.5 l 0,-87.14801" />
+ <path
+ inkscape:connector-curvature="0"
+ style="color:#000000;fill:none;stroke:#000000;stroke-width:12.00000095;stroke-linecap:round;stroke-miterlimit:4;stroke-opacity:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="path2999-6-5"
+ d="m 603.45555,-446.45023 0.5,37.05346 c 0.53281,39.48477 -32.01164,71.648 -71.5,71.648 -39.48836,0 -71.5,-32.01163 -71.5,-71.5 l 0,-37.20146" />
+ <path
+ inkscape:connector-curvature="0"
+ style="fill:#ff0000;stroke:#000000;stroke-width:12;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ id="path3998"
+ d="m 532.45878,-292.98077 0,-41.55194" />
+ <path
+ inkscape:connector-curvature="0"
+ style="color:#000000;fill:none;stroke:#000000;stroke-width:12.00000095;stroke-linecap:round;stroke-miterlimit:4;stroke-opacity:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="path2999-6-43"
+ d="m 636.82793,-292.45023 -0.5,-81.9747 c -0.24085,-39.48763 32.01164,-71.648 71.5,-71.648 39.48836,0 71.5,32.01163 71.5,71.49999 l 0,82.12271" />
+ <path
+ inkscape:connector-curvature="0"
+ style="fill:#ff0000;stroke:#000000;stroke-width:12;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ id="path3998-9"
+ d="m 637.16323,-345.75021 140.57043,0" />
+ </g>
+ </g>
+</svg>