This is a documentation for Board Game Arena: play board games online !

Practical debugging: Розніца паміж версіямі

З пляцоўкі Board Game Arena
Перайсці да навігацыі Перайсці да пошуку
 
(Не паказана 39 прамежкавых версій 11 удзельнікаў)
Радок 1: Радок 1:
{{Studio_Framework_Navigation}}


This page gives you practical tips to debug your game during the development. Don't hesitate to share with us your difficulties in order we can improve this section.
This page gives you practical tips to debug your game during development. Don't hesitate to share your difficulties with us so that we can improve this section.


== Tools ==
== Tools ==


To work on BGA Studio, we recommend you to use [www.google.com/chrome Google Chrome] as it's the current fastest browser for BGA platform, and it's available in all OS.
To work on BGA Studio, we recommend that you use [http://www.google.com/chrome Google Chrome] as it's currently the fastest browser for the BGA platform, and it's available for all OSes.


Another reason to use Chrome is that it embed all tools you need to work on BGA Studio. You can see them by pressing "F12" or from the menu ("Tools > Development tools").
Another reason to use Chrome is that it embeds all the tools you need to work on BGA Studio. You can see them by pressing "F12" or from the menu ("Tools > Development tools").


A good practice is to use a second browser to develop the game, in order to check that your game is working fine on this browser too.
A good practice is to use a second browser to develop the game, in order to verify that your game is working fine on this browser too.


To debug with Firefox browser, we advise you to use these 2 extensions:
To debug with Firefox browser, we advise you to use these 2 extensions:
* [https://addons.mozilla.org/firefox/addon/firebug/ Firebug]
* [https://addons.mozilla.org/firefox/addon/firebug/ Firebug]
* [https://addons.mozilla.org/firefox/addon/web-developer/ Web developper]
* [https://addons.mozilla.org/firefox/addon/web-developer/ Web developer]


To debug with Internet Explorer, we advise you to use one of the most recent version (ex: IE9). Last versions of Internet Explorer have way better development tools than the previous ones...
To debug with other browsers (IE, Edge, Opera), we advise you to use one of the most recent versions. Latest versions of the browser will likely have better development tools than the previous ones...


== General tip for debugging ==
== General tip for debugging ==
Радок 24: Радок 25:
== Debugging my game when it cannot start ==
== Debugging my game when it cannot start ==


If your game don't start because of an error, you are probably in one of these situations:
If your game won't start because of an error, you are probably in one of these situations:
* There is a SQL error in your dbmodel.sql file.
* There is a SQL error in your dbmodel.sql file.
* You have a syntax error in your PHP file.
* You have a syntax error in your PHP file.
* Your PHP "setup" - or any method used during the game initial states - generates an exception.
* Your PHP "setup" - or any method used during the game initial states - generates an exception.


If the error is not explicitly displayed when you click on "Express start", you should check the "Gameserver error log" in the [[Studio_back-office|Studio backoffice]].
If the error is not explicitly displayed when you click on "Express start", you should check the "Gameserver error log" as per [[Studio logs]].
More cases of why game can't start are described on the [[Troubleshooting]] page.


== Debugging my PHP game logic (or my view) ==
== Debugging my PHP game logic (or my view) ==
Радок 35: Радок 37:
Most of the time, debugging PHP is quite easy. Here's what I do when I want to develop/debug some game logic that is triggered by some game action:
Most of the time, debugging PHP is quite easy. Here's what I do when I want to develop/debug some game logic that is triggered by some game action:


* At first, I make sure that I can reproduce the needed game situation in one click. To do this, I use the "[[Tools_and_tips_of_BGA_Studio#Save_.26_restore_state|save & restore]]" function.
* At first, I make sure that I can reproduce the needed game situation with one click. To do this, I use the "[[Tools_and_tips_of_BGA_Studio#Save_.26_restore_state|save & restore]]" function.
* Another possibility for this is to place a '''die('ok');''' PHP statement right after the PHP I am developing/debugging. This way, I make sure that every request will fail and then nothing will be commited to the database, anyway.
* Another possibility for this is to place a '''die('ok');''' PHP statement right after the PHP I am developing/debugging. This way, I make sure that every request will fail and then nothing will be committed to the database.
* Then, I use '''var_dump''' function to dump PHP variables and check what's wrong, until it works.
* Then, I use the '''var_dump''' function to dump PHP variables and check what's wrong, until it works.


Example:
Example:
Радок 50: Радок 52:


</pre>
</pre>
=== Add traces to your code ===
You can use the following functions in your game to add server side logging:
'''self::dump( 'name_of_variable', $variable );'''  // dump variable, like var_dump but in the log debug level logging, goes to [[Studio_logs|BGA request&SQL logs]]
'''self::debug( $message );'''  // debug level logging, goes to [[Studio_logs|BGA request&SQL logs]]
'''self::trace( $message );'''  // info level logging, goes to [[Studio_logs|BGA request&SQL logs]]
'''self::warn( $message );'''  // warning level logging, goes to [[Studio_logs#BGA_unexpected_exceptions_logs|BGA unexpected exceptions log]]
'''self::error( $message );'''  // error level logging, goes to [[Studio_logs#BGA_unexpected_exceptions_logs|BGA unexpected exceptions log]]
Check [[Studio logs]] for more details on how to access your logs.
This can be useful when you need to follow the flow of your code and not just stop it to see how it goes at some point.
Only the error log level will appear in production. This level should be used only for critical problems.
Other levels will show only in the development environment and can be used as you see fit.
Note: tracing likely won't work in constructor and game setup, use other methods (such as dumping on stdout)


== Debugging my HTML/CSS layout ==
== Debugging my HTML/CSS layout ==


Situation examples:
Example situations
* why my game element doesn't show up in the interface?
* why my CSS property hasn't been applied to this element?
* why this game element is displayed at this position?


A first useful tip when an element does not show up in the interface is to give it a red background:
* Why doesn't my game element show up in the interface?
* Why hasn't my CSS property been applied to this element?
* Why is this game element displayed at this position?
 
A useful tip when an element does not show up in the interface is to give it a red background:
<pre>
<pre>
#my_element {
#my_element {
Радок 66: Радок 92:
</pre>
</pre>


This way, you know if the element is not visible because of some of its CSS property or because of anything else.
This way, you know if the element is not visible because of some CSS property or because of something else.


Another tip: sometimes, you change a CSS property with no visible effect on your interface. In that case, add a "display:none" property. If your element does not disappear, the bug probably comes from your CSS selector and not from your CSS property.
Another tip: sometimes, changing a CSS property has no visible effect on your interface. In that case, add a "display:none" property. If your element does not disappear, the bug probably comes from your CSS selector and not from your CSS property.


Using Chrome "Elements" tab (thre first one), you can:
Using Chrome "Elements" tab (the first one), you can:
* See the CURRENT HTML of your page. Remember that the classical "show page source" is inefficient with BGA as you are modifying the page source with your Javascript code.
* See the CURRENT HTML of your page. Remember that the classical "show page source" is inefficient with BGA as you are modifying the page source with your Javascript code.
* Using the "magnifying glass", you can click on any part of your game interface and check it's HTML code and associated CSS styles.
* Using the "magnifying glass", you can click on any part of your game interface and check its HTML code and associated CSS styles.
* You can even modify directly some CSS property and see if how it looks immediately on the game interface.
* You can even modify directly some CSS properties and see how it looks immediately in the game interface.


== Debugging my Javascript game interface logic ==
When changing css you have to force reload (Ctrl+R). But it also reloads all images which is long, if you want it faster you can define this function in js file, and call it from Browser js console
<pre>
function reloadCss() {
var links = document.getElementsByTagName("link");
for (var cl in links) {
var link = links[cl];
if (link.rel === "stylesheet")
link.href += "?";
}
}
</pre>
=== Debugging Toolips CSS/Layout ===


Compare to PHP debugging, Javascript debugging can sometimes be painful.
To inspect tooltip you need to pin it so it does not disappear.
Best way to do that is to inspect element which you have tooltip for, and in dev tools (or similar) force state to hover, i.e. select ":hov" icon and select :hover checkbox.


Here's are some tips to make your life easier while developing and debugging Javascript:
If this does not work: open the console (dev tools) large enough window, hover to make the tooltip appear and alt + tab to focus the console that will cover the tooltip. That way the onmouseout will never be triggered.


=== Do complex things on PHP side ===
=== Debugging my Javascript game interface logic ===


PHP side is more reliable and simpler to debug than Javascript. Then, when you need to perform a complex operation, check first it you can't write it on server side first.
Compared to PHP debugging, Javascript debugging can sometimes be painful.


The most frequent case is the following: you want to compute possible moves in a game situation. Doing it in Javascript is a nightmare. Then, do it on PHP, and transfer the result to your client interface using the "args" game state property.
Here are some tips to make your life easier while developing and debugging Javascript:


Note: check Reversi example for this.
=== Do complex things on the PHP side ===
 
The most frequent case is the following: you want to compute possible moves in a game situation. Doing it in Javascript is a nightmare. Do it in PHP, and transfer the results to your client interface using the "args" game state property.
 
Note: See the Reversi tutorial for an example.


=== Add traces in your code ===
=== Add traces in your code ===
Радок 103: Радок 145:
It will popup what you wish and pause the execution until you click ok.
It will popup what you wish and pause the execution until you click ok.


This won't be useful for complex structures, only native types will get plainly displayed. But this is sometimes useful just with messages to make sure which way the execution goes.
This won't be useful for complex structures; only native types will be plainly displayed. But this is sometimes useful just with messages to make sure which way the execution goes.
 
=== Use Browser Debugger (e.g. Chrome) ===


== Some frequent errors ==
Modern browsers also allow you to put breakpoints in your js code.
 
This will stop code execution on that line and will launch the JavaScript debugger.
 
In Chrome, to add a breakpoint: add a line to your .js file
 
<pre>debugger; </pre>
 
Refresh the page F5, and make sure you have the Developer tools window open, press F12.
When the break-point is hit you can then step through your code and visualise variables, etc.
 
== Online format checkers ==
Copy and paste code for a quick code sanity check like the right number of brackets.
 
PHP: [https://phpcodechecker.com/ https://phpcodechecker.com/]


=== when launching the game "Fatal error during creation of database ebd_quoridor_389 Not logged." ===
JS:  [http://esprima.org/demo/validate.html http://esprima.org/demo/validate.html]


Check that you didn't use $g_user or getCurrentPlayerId() in setupNewGame() function or in an "args" function of your state.
== Some frequent errors ==


As these functions are not consequences of a user action, there is no current player defined.
See [[Troubleshooting]].


As a general rule, you should use getActivePlayerId() and not getCurrentPlayerId(). See the [http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine presentation on the game state machine] for more information.
== Get the database matching a bug report ==


=== when refreshing the web page, the interface remains on "Application loading..." ===
For a way to automate the below steps, see this post: https://boardgamearena.com/forum/viewtopic.php?f=12&t=16454#p63167


In this case, you probably have a syntax error in your Javascript code, and the interface refuses to load.
---


To find this error, check if there is an error message in the Javascript console (F12).
When a player creates a bug report in production, a snapshot of the game database is taken. You can get access to this snapshot from the studio by following the steps below:
* Create a table in the studio with the same game and number of players as the table for which the report has been written. Launch this table.
* Open another tab on the studio and go to "Manage game" page for your project (you have to be admin for this project)
* In the "Errors in production" section, fill up the fields "Bug report ID" (this is the ID of the bug report in production) and "Studio table ID" (this is the ID of the table you created above) then click the "⇨ Load bug report state into this table save slot #1" button.
* If the snapshot is correctly retrieved, you see a "Done!" message.
* Go back to the tab with your studio table and click "Load 1".
* The page refreshes automatically and is broken. This is normal, as the player ids from the snapshot are the player ids of the production, not those of the studio. We'll need to update them.
** '''Important note:''' if you see a "Done!" message but clicking "Load 1" doesn't bring any change, it's that the snapshot is unfortunately not available (most likely because the bug report was declared too long after the game ended and the database had already been garbage collected to reclaim space).
* Click on the "Go to game database" button
* For each table using player_ids, you'll need to update the player_ids from the production to use the player_ids from the studio. You can see the player_ids from the table page before entering the game by hovering over the player names.
* Tables to update:
** player
** global (value with ID 2 is the active player)
** stats
** tables specific to your schema that use player_ids
* If your changes to player_ids are not taken into account, it may be a cache problem: use the "Clear PHP cache" button on your "Manage game" page.
* Then you should be able to play with the same state of the game as when the report was created in production.
* If the game has ended, you can place it again in the game state you want to debug by setting the value with ID 1 in the global table to the appropriate state value, and the value with ID 2 to the player you want active).
*
* Below is an example php function you may want to make. You can call this function from the chat window: LoadDebug()
* change instances of 2308257, and 2308258 to you own BGA Studio logins YourLogin0 and YourLogin1
* change $id0 and $id1 to the player_ids from the table you want to debug, and have recently imported.
* Before you load Slot1, open a second tab with the table, because after loading the slot, that tab will be unusable. In the second tab you can call LoadDebug() in the chat window


If there is really nothing on the log, it's probably that the system was unable to load your Javascript because of an syntax error that affect the structure of the Javascript file, typically a missing "}" or a missing "," after a method definition.
<pre>
public function LoadDebug()
{
// These are the id's from the BGAtable I need to debug.
$id0 = '85268563';
$id1 = '85278138';
//player
self::DbQuery("UPDATE player SET player_id=2308257 WHERE player_id = '" . $id0 . "'" );
self::DbQuery("UPDATE player SET player_id=2308258 WHERE player_id = '" . $id1 . "'" );
//global
self::DbQuery("UPDATE global SET global_value=2308257 WHERE global_value = '" . $id0 . "'" );
self::DbQuery("UPDATE global SET global_value=2308258 WHERE global_value = '" . $id1 . "'" );
//stats
self::DbQuery("UPDATE stats SET stats_player_id=2308257 WHERE stats_player_id = '" . $id0 . "'" );
self::DbQuery("UPDATE stats SET stats_player_id=2308258 WHERE stats_player_id = '" . $id1 . "'" );
// 'other' game specific tables. example:
// tables specific to your schema that use player_ids
self::DbQuery("UPDATE card SET card_location_arg=2308257 WHERE card_location_arg = '" . $id0 . "'" );
self::DbQuery("UPDATE card SET card_location_arg=2308258 WHERE card_location_arg = '" . $id1 . "'" );
          }
</pre>

Актуальная версія на 22:28, 26 кастрычніка 2020

Studio Framework Navigation

File structure of a BGA game

Game logic (Server side)
Game interface (Client side)
Other components
BGA Studio game components reference
  • Deck: a PHP component to manage cards (deck, hands, picking cards, moving cards, shuffle deck, ...).
  • Counter: a JS component to manage a counter that can increase/decrease (ex: player's score).
  • Scrollmap: a JS component to manage a scrollable game area (useful when the game area can be infinite. Examples: Saboteur or Takenoko games).
  • Stock: a JS component to manage and display a set of game elements displayed at a position.
  • Zone: a JS component to manage a zone of the board where several game elements can come and leave, but should be well displayed together (See for example: token's places at Can't Stop).

Undocumented component (if somebody knows please help with docs)

  • Draggable: a JS component to manage drag'n'drop actions.
  • ExpandableSection: a JS component to manage a rectangular block of HTML than can be displayed/hidden.
  • Wrapper: a JS component to wrap a <div> element around its child, even if these elements are absolute positioned.
BGA Studio user guide


This page gives you practical tips to debug your game during development. Don't hesitate to share your difficulties with us so that we can improve this section.

Tools

To work on BGA Studio, we recommend that you use Google Chrome as it's currently the fastest browser for the BGA platform, and it's available for all OSes.

Another reason to use Chrome is that it embeds all the tools you need to work on BGA Studio. You can see them by pressing "F12" or from the menu ("Tools > Development tools").

A good practice is to use a second browser to develop the game, in order to verify that your game is working fine on this browser too.

To debug with Firefox browser, we advise you to use these 2 extensions:

To debug with other browsers (IE, Edge, Opera), we advise you to use one of the most recent versions. Latest versions of the browser will likely have better development tools than the previous ones...

General tip for debugging

In general for debugging, think of using the 'save & restore state' functionality. It enables you to save the state of your game just before the issue you are investigating, then come back to that point with one click as many times as needed to understand what is going wrong.

You can save up to 3 different states.

Debugging my game when it cannot start

If your game won't start because of an error, you are probably in one of these situations:

  • There is a SQL error in your dbmodel.sql file.
  • You have a syntax error in your PHP file.
  • Your PHP "setup" - or any method used during the game initial states - generates an exception.

If the error is not explicitly displayed when you click on "Express start", you should check the "Gameserver error log" as per Studio logs. More cases of why game can't start are described on the Troubleshooting page.

Debugging my PHP game logic (or my view)

Most of the time, debugging PHP is quite easy. Here's what I do when I want to develop/debug some game logic that is triggered by some game action:

  • At first, I make sure that I can reproduce the needed game situation with one click. To do this, I use the "save & restore" function.
  • Another possibility for this is to place a die('ok'); PHP statement right after the PHP I am developing/debugging. This way, I make sure that every request will fail and then nothing will be committed to the database.
  • Then, I use the var_dump function to dump PHP variables and check what's wrong, until it works.

Example:


// (...my code to debug)

var_dump( $my_variable );
die('ok');

// (...my code to debug)

Add traces to your code

You can use the following functions in your game to add server side logging:

self::dump( 'name_of_variable', $variable ); // dump variable, like var_dump but in the log debug level logging, goes to BGA request&SQL logs

self::debug( $message ); // debug level logging, goes to BGA request&SQL logs

self::trace( $message ); // info level logging, goes to BGA request&SQL logs

self::warn( $message ); // warning level logging, goes to BGA unexpected exceptions log

self::error( $message ); // error level logging, goes to BGA unexpected exceptions log

Check Studio logs for more details on how to access your logs.

This can be useful when you need to follow the flow of your code and not just stop it to see how it goes at some point.

Only the error log level will appear in production. This level should be used only for critical problems. Other levels will show only in the development environment and can be used as you see fit.

Note: tracing likely won't work in constructor and game setup, use other methods (such as dumping on stdout)

Debugging my HTML/CSS layout

Example situations

  • Why doesn't my game element show up in the interface?
  • Why hasn't my CSS property been applied to this element?
  • Why is this game element displayed at this position?

A useful tip when an element does not show up in the interface is to give it a red background:

#my_element {
  ... some CSS definitions ...
  background-color: red;
}

This way, you know if the element is not visible because of some CSS property or because of something else.

Another tip: sometimes, changing a CSS property has no visible effect on your interface. In that case, add a "display:none" property. If your element does not disappear, the bug probably comes from your CSS selector and not from your CSS property.

Using Chrome "Elements" tab (the first one), you can:

  • See the CURRENT HTML of your page. Remember that the classical "show page source" is inefficient with BGA as you are modifying the page source with your Javascript code.
  • Using the "magnifying glass", you can click on any part of your game interface and check its HTML code and associated CSS styles.
  • You can even modify directly some CSS properties and see how it looks immediately in the game interface.

When changing css you have to force reload (Ctrl+R). But it also reloads all images which is long, if you want it faster you can define this function in js file, and call it from Browser js console

 function reloadCss() {
	var links = document.getElementsByTagName("link");
	for (var cl in links) {
		var link = links[cl];
		if (link.rel === "stylesheet")
			link.href += "?";
	}
 }

Debugging Toolips CSS/Layout

To inspect tooltip you need to pin it so it does not disappear. Best way to do that is to inspect element which you have tooltip for, and in dev tools (or similar) force state to hover, i.e. select ":hov" icon and select :hover checkbox.

If this does not work: open the console (dev tools) large enough window, hover to make the tooltip appear and alt + tab to focus the console that will cover the tooltip. That way the onmouseout will never be triggered.

Debugging my Javascript game interface logic

Compared to PHP debugging, Javascript debugging can sometimes be painful.

Here are some tips to make your life easier while developing and debugging Javascript:

Do complex things on the PHP side

The most frequent case is the following: you want to compute possible moves in a game situation. Doing it in Javascript is a nightmare. Do it in PHP, and transfer the results to your client interface using the "args" game state property.

Note: See the Reversi tutorial for an example.

Add traces in your code

You can use the following:

console.log( variable_to_inspect )

It will give you the object structure of the variable in the Javascript console, without blocking the execution.

It's often a good idea to precede this call with a console.log( '### HERE ###' ); to find more easily the appropriate line in the console log.

alert( variable_to_inspect )

It will popup what you wish and pause the execution until you click ok.

This won't be useful for complex structures; only native types will be plainly displayed. But this is sometimes useful just with messages to make sure which way the execution goes.

Use Browser Debugger (e.g. Chrome)

Modern browsers also allow you to put breakpoints in your js code.

This will stop code execution on that line and will launch the JavaScript debugger.

In Chrome, to add a breakpoint: add a line to your .js file

debugger; 

Refresh the page F5, and make sure you have the Developer tools window open, press F12. When the break-point is hit you can then step through your code and visualise variables, etc.

Online format checkers

Copy and paste code for a quick code sanity check like the right number of brackets.

PHP: https://phpcodechecker.com/

JS: http://esprima.org/demo/validate.html

Some frequent errors

See Troubleshooting.

Get the database matching a bug report

For a way to automate the below steps, see this post: https://boardgamearena.com/forum/viewtopic.php?f=12&t=16454#p63167

---

When a player creates a bug report in production, a snapshot of the game database is taken. You can get access to this snapshot from the studio by following the steps below:

  • Create a table in the studio with the same game and number of players as the table for which the report has been written. Launch this table.
  • Open another tab on the studio and go to "Manage game" page for your project (you have to be admin for this project)
  • In the "Errors in production" section, fill up the fields "Bug report ID" (this is the ID of the bug report in production) and "Studio table ID" (this is the ID of the table you created above) then click the "⇨ Load bug report state into this table save slot #1" button.
  • If the snapshot is correctly retrieved, you see a "Done!" message.
  • Go back to the tab with your studio table and click "Load 1".
  • The page refreshes automatically and is broken. This is normal, as the player ids from the snapshot are the player ids of the production, not those of the studio. We'll need to update them.
    • Important note: if you see a "Done!" message but clicking "Load 1" doesn't bring any change, it's that the snapshot is unfortunately not available (most likely because the bug report was declared too long after the game ended and the database had already been garbage collected to reclaim space).
  • Click on the "Go to game database" button
  • For each table using player_ids, you'll need to update the player_ids from the production to use the player_ids from the studio. You can see the player_ids from the table page before entering the game by hovering over the player names.
  • Tables to update:
    • player
    • global (value with ID 2 is the active player)
    • stats
    • tables specific to your schema that use player_ids
  • If your changes to player_ids are not taken into account, it may be a cache problem: use the "Clear PHP cache" button on your "Manage game" page.
  • Then you should be able to play with the same state of the game as when the report was created in production.
  • If the game has ended, you can place it again in the game state you want to debug by setting the value with ID 1 in the global table to the appropriate state value, and the value with ID 2 to the player you want active).
  • Below is an example php function you may want to make. You can call this function from the chat window: LoadDebug()
  • change instances of 2308257, and 2308258 to you own BGA Studio logins YourLogin0 and YourLogin1
  • change $id0 and $id1 to the player_ids from the table you want to debug, and have recently imported.
  • Before you load Slot1, open a second tab with the table, because after loading the slot, that tab will be unusable. In the second tab you can call LoadDebug() in the chat window
	public function LoadDebug()
	{
		
		// These are the id's from the BGAtable I need to debug.
		$id0 = '85268563';
		$id1 = '85278138';	
		
		//player
		self::DbQuery("UPDATE player SET player_id=2308257 WHERE player_id = '" . $id0 . "'" );
		self::DbQuery("UPDATE player SET player_id=2308258 WHERE player_id = '" . $id1 . "'" );
		
		//global 
		self::DbQuery("UPDATE global SET global_value=2308257 WHERE global_value = '" . $id0 . "'" );
		self::DbQuery("UPDATE global SET global_value=2308258 WHERE global_value = '" . $id1 . "'" );
		
		//stats
		self::DbQuery("UPDATE stats SET stats_player_id=2308257 WHERE stats_player_id = '" . $id0 . "'" );
		self::DbQuery("UPDATE stats SET stats_player_id=2308258 WHERE stats_player_id = '" . $id1 . "'" );			
		
		// 'other' game specific tables. example:
		// tables specific to your schema that use player_ids
		self::DbQuery("UPDATE card SET card_location_arg=2308257 WHERE card_location_arg = '" . $id0 . "'" );
		self::DbQuery("UPDATE card SET card_location_arg=2308258 WHERE card_location_arg = '" . $id1 . "'" );
          }