Page 1 of 2

Load bug report state into this table save slot #1

Posted: 28 June 2020, 14:09
by Lunalol
Hi.
In production control panel, you have this option :
Bug report ID ______ Studio table ID ______ ⇨ Load bug report state into this table save slot #1
You can load a bug report state in a dev game slot.
But how players are handled ?
If I create a table in dev mode, I will be all players (player0, player1, player2...), not same players than in real table.
So it doesn't work for me.
Some advice ?
Thanks

Re: Load bug report state into this table save slot #1

Posted: 28 June 2020, 16:33
by Inaofr

Re: Load bug report state into this table save slot #1

Posted: 29 June 2020, 13:47
by Lymon Flowers
To complement the documentation: if you have a LoadDebug function defined in your main game class, you can just execute it by typing LoadDebug() in the chat text box. Here is the function I use, which is more generic IMHO than the function prrovided in the doc:

Code: Select all

    function LoadDebug()
    {
        $my_player_id = 2317319;
        $tomodify = [ 'player' => [ 'player_id' ],
                      'global' => [ 'global_value' ],
                      'stats' => [ 'stats_player_id' ],
                      'movement' => [ 'player_moving' ],
                      'car' => [ 'car_owner' ],
                      'power' => [ 'power_owner' ],
                      'card' => [ 'card_location_arg' ]
        ];
        $players_id = [];
      
        foreach ( self::getObjectListFromDB ( "SELECT * from player" ) as $player )
            $players_id [ ] = $player [ 'player_id' ];
      
        for ( $i = 0 ; $i < sizeof($players_id); $i++ )
            foreach ( $tomodify as $table => $fields )
                foreach ( $fields as $field )
                    self::DbQuery ( sprintf ( "UPDATE `%s` SET `%s`=%d WHERE `%s`=%d",
                                              $table, $field, $my_player_id + $i, $field, $players_id [ $i ] ) );
    }
You just need to modify $my_player_id and use your "main" player ID in the studio (as the others will be incremented if you use the "express start" feature. The $tomodify variable is a real example for my game, just put any table you want to modify and for each table, row names.

After loading the DB into slot 1, open TWO browser tabs on the game, then load slot 1, which will corrupt a tab. On the other tab, just send LoadDebug() into the chat and that's it! You can reload other tab safely.

Re: Load bug report state into this table save slot #1

Posted: 29 June 2020, 16:04
by Lunalol
Thanks for help.
And really sorry to don't have read carefully docs !

Re: Load bug report state into this table save slot #1

Posted: 29 June 2020, 18:15
by Draasill
Nice method, bdrieu, thanks !

Re: Load bug report state into this table save slot #1

Posted: 08 July 2020, 02:57
by quietmint
@BGA, this "load bug report" feature is very useful but it's incredibly difficult to use. Two small changes on your part would make it much better for us:

1) Let me load bug reports from any project. For example, we have "santorini" in prod, but in studio I have my own copy of the same game called "santoriniqq". So I cannot load any bug reports. There is no reason to have this limitation -- if the databases for the two projects are identical, the bug report could be loaded.

2) Give me a callback method that gets invokes after clicking "Load 1" button in the studio, after the database has been updated. Similar to upgradeTableDb(), I want to run some SQL to fix the game immediately after loading the save state data. The framework should notify our game.php with some hook like this:

Code: Select all

public function loadSaveStateDb($saveNbr) {
  // run SQL UPDATEs here to fix player IDs, etc.
}

Re: Load bug report state into this table save slot #1

Posted: 08 July 2020, 10:15
by Een
This was actually meant as a last resort, for the most complex cases when the bug cannot be reproduced from the description.

I agree it could be more streamlined. Noted, but I don't know when we'll be able to get down to improving this.

Re: Load bug report state into this table save slot #1

Posted: 12 July 2020, 06:25
by quietmint
I spent a lot of time today making this load bug report work better for Santorini. In the future I hope something like this gets added to BGA framework so it's automatically available in all projects. The "load bug report" button should move out of control panel into the game page, and it should be an easy one-click operation like I've done here :)

But in the meantime, other developers can do something similar to the below. I made it so you can type loadBug(12345) in the chat and it will do all the necessary steps of loading the bug report into your current table. You can review all the game code at https://github.com/AntonioSoler/bga-santorini but here's what I added specifically about load bug report:

---

Add loadBug() and loadBugSQL() to game.php:

Code: Select all

  /*
   * loadBug: in studio, type loadBug(20762) into the table chat to load a bug report from production
   * client side JavaScript will fetch each URL below in sequence, then refresh the page
   */
  public function loadBug($reportId)
  {
    $db = explode('_', self::getUniqueValueFromDB("SELECT SUBSTRING_INDEX(DATABASE(), '_', -2)"));
    $game = $db[0];
    $tableId = $db[1];
    self::notifyAllPlayers('loadBug', "Trying to load <a href='https://boardgamearena.com/bug?id=$reportId' target='_blank'>bug report $reportId</a>", [
      'urls' => [
        // Emulates "load bug report" in control panel
        "https://studio.boardgamearena.com/admin/studio/getSavedGameStateFromProduction.html?game=$game&report_id=$reportId&table_id=$tableId",
        
        // Emulates "load 1" at this table
        "https://studio.boardgamearena.com/table/table/loadSaveState.html?table=$tableId&state=1",
        
        // Calls the function below to update SQL
        "https://studio.boardgamearena.com/1/$game/$game/loadBugSQL.html?table=$tableId&report_id=$reportId",
        
        // Emulates "clear PHP cache" in control panel
        // Needed at the end because BGA is caching player info
        "https://studio.boardgamearena.com/admin/studio/clearGameserverPhpCache.html?game=$game",
      ]
    ]);
  }

  /*
   * loadBugSQL: in studio, this is one of the URLs triggered by loadBug() above
   */
  public function loadBugSQL($reportId)
  {
    $studioPlayer = self::getCurrentPlayerId();
    $players = $this->playerManager->getPlayers();

    // Change for your game
    // We are setting the current state to match the start of a player's turn if it's already game over
    $sql = [
      "UPDATE global SET global_value=" . ST_MOVE . " WHERE global_id=1 AND global_value=" . ST_BGA_GAME_END
    ];
    foreach ($players as $player) {
      $pId = $player->getId();
      // All game can keep this SQL
      $sql[] = "UPDATE player SET player_id=$studioPlayer WHERE player_id=$pId";
      $sql[] = "UPDATE global SET global_value=$studioPlayer WHERE global_value=$pId";
      $sql[] = "UPDATE stats SET stats_player_id=$studioPlayer WHERE stats_player_id=$pId";

      // Change the below SQL to update the specific tables for your game
      $sql[] = "UPDATE card SET card_location_arg=$studioPlayer WHERE card_location_arg=$pId";
      $sql[] = "UPDATE piece SET player_id=$studioPlayer WHERE player_id=$pId";
      $sql[] = "UPDATE log SET player_id=$studioPlayer WHERE player_id=$pId";
      $sql[] = "UPDATE log SET action_arg=REPLACE(action_arg, $pId, $studioPlayer)";

      // This could be improved, it assumes you had sequential studio accounts before loading
      // e.g., quietmint0, quietmint1, quietmint2, etc. are at the table
      $studioPlayer++;
    }
    $msg = "<b>Loaded <a href='https://boardgamearena.com/bug?id=$reportId' target='_blank'>bug report $reportId</a></b><hr><ul><li>" . implode(';</li><li>', $sql) . ';</li></ul>';
    self::warn($msg);
    self::notifyAllPlayers('message', $msg, []);

    foreach ($sql as $q) {
      self::DbQuery($q);
    }
    self::reloadPlayersBasicInfos();
  }
Add loadBugSQL() to actions.php

Code: Select all

  public function loadBugSQL()
  {
    self::setAjaxMode();
    $reportId = (int) self::getArg('report_id', AT_int, true);
    $this->game->loadBugSQL($reportId);
    self::ajaxResponse();
  }
Add loadBug notification handler to game.js.

Code: Select all

  notif_loadBug: function (n) {
    function fetchNextUrl() {
      var url = n.args.urls.shift();
      console.log('Fetching URL', url);
      dojo.xhrGet({
        url: url,
        load: function (success) {
          // This could be improved, I don't check the response for errors
          console.log('Success for URL', url, success);
          if (n.args.urls.length > 0) {
            fetchNextUrl();
          } else {
            console.log('Done, reloading page');
            window.location.reload();
          }
        }
      });
    }

    console.log('Notif: load bug', n.args);
    fetchNextUrl();
  },

Re: Load bug report state into this table save slot #1

Posted: 13 July 2020, 00:51
by Brainchild
quietmint wrote: 12 July 2020, 06:25 I made it so you can type loadBug(12345) in the chat and it will do all the necessary steps of loading the bug report into your current table.
Good stuff! I hope I never need to use this, but if I do I expect it will be quite a time-saver.

Re: Load bug report state into this table save slot #1

Posted: 13 July 2020, 01:13
by RicardoRix
awesomeness