CloudObjects / Directory / werewolves.lukasrosenstock.net / GameController
Sign in

GameController

a phpmae:Class in werewolves.lukasrosenstock.net
Public PHP Methods
  • showPage($gameId)

    No documentation available.

  • transmitVote($gameId)

    No documentation available.

  • dealCards($auth, $gameId, $deck)

    No documentation available.

  • resetVoting($auth, $gameId)

    No documentation available.

  • observe($gameId)

    No documentation available.

Source Code
<?php

use Exception;
use Psr\Container\ContainerInterface;
use Psr\Http\Message\RequestInterface;
use Webmozart\Assert\Assert;

/**
 * Implementation for coid://werewolves.lukasrosenstock.net/GameController
 */
class GameController {

    const BASE_ID = 'appkTRVIjuKAKcquF';

    private $airtable;
    private $authkey;
    private $playerUiTemplate;
    private $request;
    private $pusherProvider;

    public function __construct(ContainerInterface $container,
            RequestInterface $request, PusherProvider $pusherProvider) {
        $this->airtableApi = $container->get('airtable');
        $this->authkey = $container->get('authkey');
        $this->playerUiTemplate = $container->get('playerUi');
        $this->request = $request;
        $this->pusherProvider = $pusherProvider;
    }

    public function showPage($gameId) {
        try {
            $gameData = json_decode($this->airtableApi->get(self::BASE_ID.'/'.$gameId)->getBody(), true);

            $request = $this->request->getParsedBody();

            $pageVars = [
                'page' => isset($request['action']) ? $request['action'] : 'home',
                'gameId' => $gameId
            ];
            switch ($request['action']) {
                case "register":
                    // Register for a game
                    if (!isset($request['player_name']) || strlen(trim($request['player_name'])) < 2) {
                        $pageVars['error'] = "Invalid name.";
                        $pageVars['page'] = 'home';
                    } else {
                        try {
                            // Add player to Airtable
                            $record = json_decode($this->airtableApi->post(
                                self::BASE_ID.'/'.$gameId, [
                                'json' => [
                                    'fields' => [
                                        'Player Name' => $request['player_name']
                                    ]                            
                                ]
                            ])->getBody(), true);

                            $pageVars['player_id'] = $record['id'];
                            $pageVars['player_auth'] = hash_hmac('sha1', $record['id'], $this->authKey);
                            $pageVars['player_name'] = $request['player_name'];
                        } catch (Exception $e) {
                            $pageVars['error'] = "Registration failed: " . $e->getMessage();
                            $pageVars['page'] = 'home';
                        }
                    }
                    break;
                case "reveal":
                    // Reveal own identity
                    if (isset($request['player_id']) && isset($request['player_auth'])
                            && $request['player_auth'] == hash_hmac('sha1', $request['player_id'], $this->authKey)) {
                        
                        $pageVars['player_data'] = [];
                        $pageVars['player_id'] = $request['player_id'];
                        $pageVars['player_auth'] = $request['player_auth'];
                        foreach ($gameData['records'] as $r) {
                            $pageVars['player_data'][$r['id']] = $r['fields']['Player Name'];

                            if ($r['id'] == $request['player_id'])
                                $pageVars['player_name'] = $r['fields']['Player Name'];
                            
                            if ($r['id'] == $request['player_id'] && isset($r['fields']['Character'])) {
                                $pageVars['role'] = $r['fields']['Character'];
                                $pageVars['faction'] = $r['fields']['Faction'];
                            }
                        }
                        
                        if (!isset($pageVars['role'])) {
                            $pageVars['error'] = "Role has not been assigned!";
                            $pageVars['page'] = 'register';
                        }
                    } else {
                        $pageVars['error'] = "Invalid session!";
                        $pageVars['page'] = 'register';
                    }
            }
        } catch (Exception $e) {
            $pageVars = [ 'page' => 'invalid_game' ];
        }

        return $this->playerUiTemplate->render($pageVars);
    }

    public function transmitVote($gameId) {
        try {
            $request = $this->request->getParsedBody();

            Assert::keyExists($request, 'player_id');
            Assert::keyExists($request, 'player_auth');
            Assert::keyExists($request, 'target_id');
            Assert::eq($request['player_auth'], hash_hmac('sha1', $request['player_id'], $this->authKey),
                "Authorization failure.");
            
            $gameData = json_decode($this->airtableApi->get(self::BASE_ID.'/'.$gameId)->getBody(), true);

            foreach ($gameData['records'] as $r)
                if ($r['id'] == $request['target_id']) {
                    $this->pusherProvider->triggerEvent('VoteCast', $request['player_id'].'|'.$request['target_id'], $gameId);

                    return [
                        'success' => true
                    ];
            }

            return [
                'success' => false
            ];
        } catch (Exception $e) {
            return [
                'success' => false,
                'error' => $e->getMessage()
            ];
        }
    }

    public function dealCards($auth, $gameId, $deck) {
        if ($auth != $this->authkey)
            return "You are not authorized to deal cards.";

        $cards = explode(',', $deck);
        $gameData = json_decode($this->airtableApi->get(self::BASE_ID.'/'.$gameId)->getBody(), true);
        $playerCount = count($gameData['records']);

        if ($playerCount < count($cards))
            return "Deck has too many cards.";

        while (count($cards) < $playerCount)
            $cards[] = 'Villager';

        shuffle($cards);

        $i = 0;
        foreach ($gameData['records'] as $r) {
            $this->airtableApi->patch(
                self::BASE_ID.'/'.$gameId.'/'.$r['id'], [
                'json' => [
                    'fields' => [
                        'Character' => $cards[$i]
                    ]                            
                ]
            ]);
            $i++;
        }

        return "Cards dealt.";
    }

    public function resetVoting($auth, $gameId) {
        if ($auth != $this->authkey)
            return "You are not authorized to reset voting.";

        return $this->pusherProvider->triggerEvent('VoteReset', '', $gameId);
    }

    public function observe($gameId) {
        try {
            $gameData = json_decode($this->airtableApi->get(self::BASE_ID.'/'.$gameId)->getBody(), true);

            $request = $this->request->getParsedBody();

            $pageVars = [
                'page' => 'reveal',
                'gameId' => $gameId
            ];
            
            $pageVars['player_data'] = [];
            $pageVars['player_id'] = 'NARRATOR';
            $pageVars['player_auth'] = 'NARRATOR';
            foreach ($gameData['records'] as $r)
                $pageVars['player_data'][$r['id']] = $r['fields']['Player Name'];
        } catch (Exception $e) {
            $pageVars = [ 'page' => 'invalid_game' ];
        }

        return $this->playerUiTemplate->render($pageVars);
    }

}
Meta
URI / COID
coid://werewolves.lukasrosenstock.net/GameController content_copy
Revision
22-361d5ab32eb02064c3e8c6ead72737ff content_copy
Last updated
2020-10-28 23:11 (UTC)
Created at
2020-10-28 23:11 (UTC)
Usage permission
co:Public
Objects in this namespace