+
+ 'promotedProduct' => $product,
+ 'buttons' => $buttons,
+ ];
+}
+
+function buildDeveloperCurrentGamer()
+{
+ return [
+ 'gamer' => [
+ 'uuid' => '00702342-0000-1111-2222-c3e1500cafe2',
+ 'username' => 'stouyapi',
+ ],
+ ];
+}
+
+/**
+ * For /api/v1/developers/xxx/products/?only=yyy
+ */
+function buildDeveloperProductOnly($product, $developer)
+{
+ return [
+ 'developerName' => $developer->name,
+ 'currency' => $product->currency,
+ 'products' => [
+ buildProduct($product),
+ ],
+ ];
+}
+
+/**
+ * For /api/v1/developers/xxx/products/
+ */
+function buildDeveloperProducts($products, $developer)
+{
+ $jsonProducts = [];
+ foreach ($products as $product) {
+ $jsonProducts[] = buildProduct($product);
+ }
+ return [
+ 'developerName' => $developer->name,
+ 'currency' => $products[0]->currency ?? 'EUR',
+ 'products' => $jsonProducts,
+ ];
+}
+
+function buildPurchases($game)
+{
+ $purchasesData = [
+ 'purchases' => [],
+ ];
+ $promotedProduct = getPromotedProduct($game);
+ if ($promotedProduct) {
+ $purchasesData['purchases'][] = [
+ 'purchaseDate' => time() * 1000,
+ 'generateDate' => time() * 1000,
+ 'identifier' => $promotedProduct->identifier,
+ 'gamer' => '00702342-0000-1111-2222-c3e1500cafe2',//gamer uuid
+ 'uuid' => '00702342-0000-1111-2222-c3e1500beef3',//transaction ID
+ 'priceInCents' => $promotedProduct->originalPrice * 100,
+ 'localPrice' => $promotedProduct->localPrice,
+ 'currency' => $promotedProduct->currency,
+ ];
+ }
+
+ $encryptedOnce = dummyEncrypt($purchasesData);
+ $encryptedTwice = dummyEncrypt($encryptedOnce);
+ return $encryptedTwice;
+}
+
+function buildSearch($games)
+{
+ $games = sortByTitle($games);
+ $results = [];
+ foreach ($games as $game) {
+ $results[] = [
+ 'title' => $game->title,
+ 'url' => 'ouya://launcher/details?app=' . $game->packageName,
+ 'contentRating' => $game->contentRating,
+ ];
+ }
+ return [
+ 'count' => count($results),
+ 'results' => $results,
+ ];
+}
+
+function dummyEncrypt($data)
+{
+ return [
+ 'key' => base64_encode('0123456789abcdef') . "\n",
+ 'iv' => 't3jir1LHpICunvhlM76edQ==' . "\n",//random bytes
+ 'blob' => base64_encode(
+ json_encode($data, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES)
+ ) . "\n",
+ ];
+}
+
+function addChunkedDiscoverRows(&$data, $games, $title)
+{
+ $chunks = array_chunk($games, 4);
+ $first = true;
+ foreach ($chunks as $chunk) {
+ addDiscoverRow(
+ $data, $first ? $title : '',
+ $chunk
+ );
+ $first = false;
+ }
+}
+
+function addDiscoverRow(&$data, $title, $games)
+{
+ $row = [
+ 'title' => $title,
+ 'showPrice' => true,
+ 'ranked' => false,
+ 'tiles' => [],
+ ];
+ foreach ($games as $game) {
+ if (is_string($game)) {
+ //category link
+ $tilePos = count($data['tiles']);
+ $data['tiles'][$tilePos] = buildDiscoverCategoryTile($game);
+
+ } else {
+ //game
+ if (isset($game->links->original)) {
+ //do not link unlocked games.
+ // people an access them via the original games
+ continue;
+ }
+ $tilePos = findTile($data['tiles'], $game->packageName);
+ if ($tilePos === null) {
+ $tilePos = count($data['tiles']);
+ $data['tiles'][$tilePos] = buildDiscoverGameTile($game);
+ }
+ }
+ $row['tiles'][] = $tilePos;
+ }
+ $data['rows'][] = $row;
+}
+
+function findTile($tiles, $packageName)
+{
+ foreach ($tiles as $pos => $tile) {
+ if ($tile['package'] == $packageName) {
+ return $pos;
+ }
+ }
+ return null;
+}
+
+function buildDiscoverCategoryTile($title)
+{
+ return [
+ 'url' => 'ouya://launcher/discover/' . categoryPath($title),
+ 'image' => '',
+ 'title' => $title,
+ 'type' => 'discover'
+ ];
+}
+
+function buildDiscoverGameTile($game)
+{
+ $latestRelease = $game->latestRelease;
+ return [
+ 'gamerNumbers' => $game->players,
+ 'genres' => $game->genres,
+ 'url' => 'ouya://launcher/details?app=' . $game->packageName,
+ 'latestVersion' => [
+ 'apk' => [
+ 'md5sum' => $latestRelease->md5sum,
+ ],
+ 'versionNumber' => $latestRelease->name,
+ 'uuid' => $latestRelease->uuid,
+ ],
+ 'inAppPurchases' => $game->inAppPurchases,