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

Practical debugging: Разлика между версии

От Board Game Arena
Направо към навигацията Направо към търсенето
Редакция без резюме
 
(Не са показани 16 междинни версии от 2 потребители)
Ред 1: Ред 1:


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 the development. Don't hesitate to share with us your difficulties in order we can improve this section.
== 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.
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").
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.
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/web-developer/ Web developper]
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...
== General tip for debugging ==
In general for debugging, think of using the '[[Tools_and_tips_of_BGA_Studio#Save_.26_restore_state|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 ==
== Debugging my game when it cannot start ==
Ред 9: Ред 29:
* 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]].


== Debugging my PHP game logic (or my view) ==
== Debugging my PHP game logic (or my view) ==
Ред 16: Ред 36:


* 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 in 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, the PHP request will stop immediately, nothing will be commited to the database, and the game initial situation will remains.
* 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.
* Then, I use '''var_dump''' function to dump PHP variables and check what's wrong, until it works.
 
Example:
<pre>
 
// (...my code to debug)
 
var_dump( $my_variable );
die('ok');
 
// (...my code to debug)
 
</pre>
 
=== Add traces to your code ===
 
You can use the following functions in your game to add server side logging:
 
'''self::debug( $message );'''  // debug level logging
 
'''self::trace( $message );'''  // info level logging
 
'''self::warn( $message );'''  // warning level logging
 
'''self::error( $message );'''  // error level logging
 
To see the logs, you should check the "Current table error log" in the [[Studio_back-office|Studio backoffice]].
 
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.


== Debugging my HTML/CSS layout ==
== Debugging my HTML/CSS layout ==
Situation examples:
* 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:
<pre>
#my_element {
  ... some CSS definitions ...
  background-color: red;
}
</pre>
This way, you know if the element is not visible because of some of its CSS property or because of anything 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.
Using Chrome "Elements" tab (thre 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 it's 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.


== Debugging my Javascript game interface logic ==
== Debugging my Javascript game interface logic ==
Compare to PHP debugging, Javascript debugging can sometimes be painful.
Here's are some tips to make your life easier while developing and debugging Javascript:
=== Do complex things on PHP side ===
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.
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.
Note: check Reversi example for this.
=== 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 get plainly displayed. But this is sometimes useful just with messages to make sure which way the execution goes.


== Some frequent errors ==
== Some frequent errors ==


=== when launching the game "Fatal error during creation of database ebd_quoridor_389 Not logged." ===
Check that you didn't use $g_user or getCurrentPlayerId() in setupNewGame() function or in an "args" function of your state.
As these functions are not consequences of a user action, there is no current player defined.
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.
=== when refreshing the web page, the interface remains on "Application loading..." ===
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).
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.
=== When I do a move, I got "Move recorded, waiting for update ..." forever ===
"Move recorded" means that your ajaxcall request has been sent to the server and returned normally.
"Waiting for update" means that your client interface is waiting for some notifications from the server that correspond to the move we just did.
If this message stays forever, it is probably that your PHP code does not send any notification when the move happens, which is abnormal. To fix this: add a notifyAllPlayers or a notifyPlayer call in your PHP code.
=== Some player action is triggered randomly when I click somewhere on the game area ===
You probably used "dojo.connect" on a null object. In this case, dojo.connect associate the event (ex: "onclick") to the whole game area.
Most of the time it happens in this situation, when my_object element does not exists:
<pre>
  dojo.connect( $("my_object"), "onclick", this, function() {
    ...
  }
</pre>
To determine if this is the case, place "alert( $("my_object") )" before the dojo.connect to check if the object exists or not.


== What is the best way to debug? ==
=== Javascript does not know how to sum two numbers ===


On the server side (PHP), you can use one of these:
Be careful when you manipulate integers returned by notifications: most of the time, Javascript considers they are Strings and not Integers.
* die(var_dump( $variable_to_inspect );
* throw new BgaUserException(var_dump( $variable_to_inspect );


On the client side (Javascript), we recommand installing Firebug for Firefox (or using the 'Developer tools' with Chrome that have about the same functionalities), then:
As a result:
* console.log( variable_to_inspect ); will give you the object structure of the variable in the Firebug 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.
<pre>
* alert( variable_to_inspect ); 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.
    var i=1;
    i += notif.args.increment; // With notif.args.increment='1'
    alert( i );                 // i=11 instead of 2 !! Javascript concatenate 2 strings !
</pre>


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.
To solve this, you should use the "toint" function:
<pre>
    var i=1;
    i += toint( notif.args.increment );  // With notif.args.increment='1'
    alert( i );                // i=2 :)
</pre>


=== Some frequent errors ===
=== Javascript: do not use substr with negative numbers ===


; The following error occurs when launching the game "Fatal error during creation of database ebd_quoridor_389 Not logged."
To get the last characters of a string, use "slice" instead of "substr" which has a bug on IE:
: Check that you didn't use $g_user or getCurrentPlayerId() in setupNewGame() function or in an "args" function of your state. As these functions are not consequences of a user action, there is no current player defined. 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.
<pre>
    var three_last_characters = string.substr( -3 );  // Wrong
    var three_last_characters = string.slice( -3 );    // Correct
</pre>

Текуща версия към 21:40, 20 ноември 2014

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.

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.

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").

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.

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

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...

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 don'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.

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 in 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 commited to the database, anyway.
  • Then, I use 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::debug( $message ); // debug level logging

self::trace( $message ); // info level logging

self::warn( $message ); // warning level logging

self::error( $message ); // error level logging

To see the logs, you should check the "Current table error log" in the Studio backoffice.

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.

Debugging my HTML/CSS layout

Situation examples:

  • 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:

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

This way, you know if the element is not visible because of some of its CSS property or because of anything 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.

Using Chrome "Elements" tab (thre 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 it's 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.

Debugging my Javascript game interface logic

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

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

Do complex things on PHP side

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.

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.

Note: check Reversi example for this.

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 get plainly displayed. But this is sometimes useful just with messages to make sure which way the execution goes.

Some frequent errors

when launching the game "Fatal error during creation of database ebd_quoridor_389 Not logged."

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

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

As a general rule, you should use getActivePlayerId() and not getCurrentPlayerId(). See the presentation on the game state machine for more information.

when refreshing the web page, the interface remains on "Application loading..."

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).

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.

When I do a move, I got "Move recorded, waiting for update ..." forever

"Move recorded" means that your ajaxcall request has been sent to the server and returned normally.

"Waiting for update" means that your client interface is waiting for some notifications from the server that correspond to the move we just did.

If this message stays forever, it is probably that your PHP code does not send any notification when the move happens, which is abnormal. To fix this: add a notifyAllPlayers or a notifyPlayer call in your PHP code.

Some player action is triggered randomly when I click somewhere on the game area

You probably used "dojo.connect" on a null object. In this case, dojo.connect associate the event (ex: "onclick") to the whole game area.

Most of the time it happens in this situation, when my_object element does not exists:

   dojo.connect( $("my_object"), "onclick", this, function() {
     ...
   }

To determine if this is the case, place "alert( $("my_object") )" before the dojo.connect to check if the object exists or not.

Javascript does not know how to sum two numbers

Be careful when you manipulate integers returned by notifications: most of the time, Javascript considers they are Strings and not Integers.

As a result:

    var i=1;
    i += notif.args.increment;  // With notif.args.increment='1'
    alert( i );                 // i=11 instead of 2 !! Javascript concatenate 2 strings !

To solve this, you should use the "toint" function:

    var i=1;
    i += toint( notif.args.increment );  // With notif.args.increment='1'
    alert( i );                 // i=2 :)

Javascript: do not use substr with negative numbers

To get the last characters of a string, use "slice" instead of "substr" which has a bug on IE:

    var three_last_characters = string.substr( -3 );   // Wrong
    var three_last_characters = string.slice( -3 );    // Correct