Custom Theming with Sencha themebuilder: Sencha GXT Theme Builder HTML

In Sencha’s GXT 3.1 beta, it includes an html file that runs a script that can parse a theme file and generate the approximate look and appearance of several sencha widgets. This allows for fast iteration of .theme development (and enables you to not have to rebuild the theme.jar file with every change). It definitely is extremely valuable in terms of saving time, however, the tool is far from perfect. It’s located in ../gxt-3.1.0-beta-20140225/themebuilder/bin/widgetdatasample/sliceme/index.html. You’ll have to extract the files from the .jar first.

Screen Shot 2014-02-28 at 10.56.52 AM

An example rendering using the html form included with the themebuilder.
An example rendering using the html form included with the themebuilder.

A few of the deficiencies:

  • It didn’t work in chrome
  • Not every widget gets rendered
  • You can’t see widgets within widgets
  • You’ll need to modify the reset.css if you want to see custom styling
  • A lot of the widgets don’t have text, so you can’t see what text would look like in them
  • It’s difficult to determine what the widgets map to since they are prefaced with the name of the job that the themebuilder uses to “slice” the look into images for cross-browser support for older browsers.

Here’s a few tips and tricks I’ve learned:

  • It didn’t work in chrome
    • Solution: It did work in firefox for me.
  • Not every widget gets rendered
    • Solution: Not much you can do here. Hopefully you can get to a point where your .theme is close enough so you can narrow down the widgets that you need to see to fix.
  • You can’t see widgets within widgets
    • Solution: Same as the above.
  • You can’t add custom styling because the .theme file doesn’t support it. If your app uses custom styles on top of the theme.jar, you won’t be able to see them.
    • Solution: There is a reset.css file in the same directory as the HTML file that is used to help style the rendered page. You can add .css classes here and using debug tools or firebug, insert your css class into the widget to see how it would look. You can do the same thing with external fonts.
    • See an example here:

      An example of modifying inline styles to get the look and feel right with compiled widgets.
      An example of modifying inline styles to get the look and feel right with compiled widgets.
  • A lot of the widgets don’t have text, so you can’t see what text would look like in theme
    • Solution: Same as the above. Except modify the inline HTML and add some text inside the innermost div.
    • An example of modifying the inline text of the widget using firebug.
      An example of modifying the inline text of the widget using firebug.
  • It’s difficult to determine what the widgets map to since they are prefaced with the name of the job that the themebuilder uses to “slice” the look into images for cross-browser support for older browsers.
    • Solution: This is kind of guess and check, but here’s a list of some of the less obvious mappings from the .theme file to what they correspond to in terms of gwt widgets:
    • In your .theme file,
    • 
          /* Dialog boxes - background
           */
          window {
            backgroundColor = theme.bgColor
            borderColor = util.darkenColor(backgroundColor, 0.2)
            headerGradient = util.gradientString(theme.headerGradientDetails)
          }
      
         /*
          * These are the overlays that disable fields.  Since they're grey, change the font to white.
          */
          mask {
            backgroundColor = "#000000"
            opacity = 0.5
            box {
              backgroundColor = "#303030"
              borderColor = "#555555"
              borderRadius = 0
              borderStyle = "solid"
              borderWidth = 2
              loadingImagePosition = "0 center"
              padding = util.padding(5)
              radiusMinusBorderWidth = util.max(0, borderRadius - borderWidth)
              text = theme.riverbedBodyWhite
              textPadding = util.padding(0, 0, 0, 21)
            }
          }
      
          //Dropdowns menus 
          fieldset {
            ...
            border=util.border('solid', '#bbbbbb', 1)
            text=theme.text  //Color of the unselected values in a dropdown menu
          }
      
          field {
              text=theme.text  //Color of the selected value in a dropdown in a toolbar
          }
      
      tabs {
            ...
            lastStopColor="#000000"  //color of the bottom of the tab
            tabHeight=20 //height of a tab
            tabSpacing=1 //horizontal spacing between the tabs
      
          }
      

GWT/GXT Theming Part 3 – Adding Custom Fonts

Okay, a softball for today. In order to add custom fonts to your application on top of Sencha’s themebuilder, you can take a few different approaches.

Yay different fonts!
Yay different fonts!
  1. You can add the font type to an external css file and pass in the font-family into your .theme file
  2. You can add custom appearance classes for each widget to get a particular font. See here.

I ultimately settled on the first approach because it saved me the time of having to create a separate appearance class for each widget I wanted to style. That and Sencha’s .theme file actually has a “text” value for most of its widgets. It’s probably one of the most customizable aspects of the themebuilder.

Here’s how I did it:

theme {

  name = "customTheme"
  basePackage = "com.example"

  ...

  // CUSTOM FONTS
  /* TRADE GOTHIC/ARIAL */
    customSmallFont = util.fontStyle("\'TradeGothicW01-BoldCn20 675334\', Arial, Helvetica, sans-serif", "13px", "#000000", "normal")
}

You can see here that I escaped the single quotes for a font-family that contained spaces. This font string gets compiled through and actually makes it out to the ultimate .css that styles various widgets. Prior to using single escaped quotes, I just entered in the entire string in double quotes, which compiled and built a theme, but did not make it through to the .css in the end.

If your font doesn’t have spaces, you can simply use the entire string, but escaping with single quotes seems to work well. Here’s what my external .css file looks like at the end:

/* my external css file */
@font-face {
    font-family: 'TradeGothicW01-BoldCn20 675334';
    src: url('fonts/tradegothicltpro-bdcn20-webfont.eot');
    src: url('fonts/tradegothicltpro-bdcn20-webfont.eot?#iefix') format('embedded-opentype'),
         url('fonts/tradegothicltpro-bdcn20-webfont.woff') format('woff'),
         url('fonts/tradegothicltpro-bdcn20-webfont.ttf') format('truetype'),
         url('fonts/tradegothicltpro-bdcn20-webfont.svg#TradeGothicW01-BoldCn20 675334') format('svg');
    font-weight: normal;
    font-style: normal;

}

That’s all there is to it!

GWT/GXT Theming Part 2 – Adding Custom Appearance Classes on top of Sencha Themebuilder

Likely one of the first things you’ll encounter if using the themebuilder is how to create a custom style for something the themebuilder doesn’t support. In my adventures trying to build on top of Sencha’s themebuilder, it became apparent to me that they intended the tool to be used in a standalone fashion. That is, one runs the themer.sh or themer.bat file to generate the theme.jar file and you plug and play it in conjunction with GWT.

However, because the theme file is applied uniformly across your application, what happens if you don’t want buttons in one place to look like buttons in another? This came up when building our webapp, where we wanted our top-level nav to have one color and appearance on hover and other buttons within the application to have another color. As it turns out, there’s no way to specify this in the .theme file.

  • One set of buttons (rendered by the themebuilder)
  • Screen Shot 2014-02-27 at 2.25.46 PM

  • Another set of buttons (custom appearance)
  • Screen Shot 2014-02-27 at 2.29.29 PM

  • Yet another set of buttons (customer appearance)
  • Screen Shot 2014-02-27 at 2.30.20 PM

    So how did I do this? In fact, there isn’t an easy way currently. I had to go digging through the compiled appearance classes made by the themebuilder.jar file in search of an answer. Here’s an example of what the themebuilder spits out for a button made with your custom .theme file.

    Step 1: Create an custom appearance class for your button/widget that extends Sencha’s appearance class

    So the first step I found to creating custom styling on top of the themebuilder was to create my own appearance class. However, I didn’t want to start from scratch because Sencha already provides a good basis (e.g. by applying the fonts, default colors, creating sliced image files, etc). It’s true that a lot of these things go out of the window when creating your own appearance class and you can lose multi-browser support, but in our case, it was better than keeping all the buttons looking exactly the same.

    Here’s example of a custom appearance class for the dark grey buttons you see above.

    /**
     * HeaderButtonAppearance extends a theme appearance created by Sencha's
     * themebuilder.jar file.  It uses the gifs and base css created by Sencha's
     * themebuilder then adds additional css styling and modifies the rendering
     * logic to display header buttons.  
     */
    public class HeaderButtonAppearance<M> extends ButtonCellDefaultAppearance<M> {
    
      	final HeaderButtonStyle customStyle;
    	
    	/**
    	 * These are "resources" that comprise a ButtonCellAppearance
    	 * This interface describes the resources used by this button appearance.  This is not 
    	 * Sencha-specific.  I had originally tried extending the Css3ButtonResources class that 
             * the themebuilder spits out, but it required keeping the entire .css class in my package as well.
    	 */
      	public interface HeaderButtonResources extends ClientBundle {
      		@Source("HeaderButtonCell.css")
      		HeaderButtonStyle style();
      	}
      	
            //These methods are my new styles.
      	public interface HeaderButtonStyle extends CssResource {
      		String headerButton();
      		
      		String outerButton();
      	}
      	
      	public HeaderButtonAppearance() {
      		HeaderButtonResources headerResources = GWT.create(HeaderButtonResources.class);
      		customStyle = headerResources.style();
      		StyleInjectorHelper.ensureInjected(headerResources.style(), true);
      	}
      	
      	@Override
        public void render(ButtonCell<M> cell, Context context, M value, SafeHtmlBuilder sb) {
      	    Css3ButtonResources resources = GWT.create(Css3ButtonResources.class);
      	    Css3ButtonStyle style = resources.style();
                //Additional rendering stuff here, use style.____() to access the custom themebuilder styles
                //Sencha by default uses a two nested divs to render a button.  You may have to extract the precise
                //.class file from the theme.jar file to see how the html is constructed.
    
       }
    }
    
      There are a few quirks regarding this appearance class to be aware of:

    • In the *ButtonStyle interface, the string method maps to a css class name in the *ButtonResources interface css file.
    • The .css file that is used for the mapping must be in the same package as the appearance class
    • In order to use the styles made available through the compiled css and appearance classes built by the themebuilder, you have to instantiate a ClientBundle and access the css classes through the Css3ButtonStyle interface.
    • Because the default rendering of the button renders the themebuilder’s classes (e.g. for buttons, there are two nested divs, where the outer has .button {} applied and the inner has .buttonInner {} applied, I had to rewrite the render method myself. In my replacement, I swapped out the .button and .buttonInner classes for my own css classes. I maintain everything else.
    • I think there has to be a better way to do this. For example, I experimented with injecting html (an innermost div) into the cell which accepts only my css. That way, I could avoid having to @Override the render class and modify the html on the backend. However, it didn’t end up working very well because even with injecting my own css, I could not overwrite the styling applied to the parent divs. Ultimately, I think one could write a utility to go in and scrape out the other classes applied by the themebuilder, but this seemed like it would be a real hassle.

    Step 2: Define the .css classes in a file in the same package for your custom appearance

    Here’s an example of what my .css class looked like.

    .outerButton {
      border: none;
      background-color: #3892D3;
      background: transparent;
      padding: 4px;
      cursor: pointer;
      outline: none;
      padding-right:30px;
    }
    
    .headerButton {
      	padding: 0px;
      	text-align: left;
    	font-family: Arial, Helvetica, sans-serif;  /* actual font is not arial */
    	font-size: 17px;
    }
    
    .headerButton:hover {
    	color: white;
    }
    

    If you look at my HeaderButtonStyle class, you’ll notice that the css class names map directly to the functions in the interface. GWT takes care of the actual mapping of values. These are the classes that I can use to style my widget and are accessible via my instance of the HeaderButtonStyle. Here’s an example of how I render the HeaderStyleButton:

    
    @Override
        public void render(ButtonCell<M> cell, Context context, M value, SafeHtmlBuilder sb) {
                //The default style CSS Resource in case I need to access styles built by the themebuilder
    
      	    Css3ButtonResources resources = GWT.create(Css3ButtonResources.class);
      	    Css3ButtonStyle style = resources.style();
    
                //Begin actual construction of the button widget
      		
      	    String constantHtml = cell.getHTML();
      	    boolean hasConstantHtml = constantHtml != null && constantHtml.length() != 0;
    
      	    boolean isBoolean = value != null && value instanceof Boolean;
    
      	    String text = hasConstantHtml ? cell.getText() : (value != null && !isBoolean)
      	        ? SafeHtmlUtils.htmlEscape(value.toString()) : "";
    
      	    String scaleClass = "";
      	    String iconClass = "";
      	    String additionalCssClasses = customStyle.headerButton();
    
                //Size-dependent styling
      	    ButtonScale scale = cell.getScale();
    
      	    switch (scale) {
      	      case SMALL:
      	        scaleClass = style.small();
      	        break;
    
      	      case MEDIUM:
      	        scaleClass = style.medium();
      	        break;
    
      	      case LARGE:
      	        scaleClass = style.large();
      	        break;
      	    }
    
                //Outer button class, you could add anything else you want here
      	    String buttonClass = customStyle.outerButton();
    
      	    boolean hasText = text != null && !text.equals("");
      	    if (!hasText) {
      	      buttonClass += " " + style.noText();
      	    }
     
                //The css classes applied to the inner div
                String innerClass = "";
      	    innerClass += " " + scaleClass;
      	    innerClass += " " + additionalCssClasses;
    
      	    SafeHtmlBuilder builder = new SafeHtmlBuilder();
    
      	    builder.appendHtmlConstant("<div class='" + buttonClass + "'>");
      	    builder.appendHtmlConstant("<div class='" + innerClass + "'>");
    
      	    builder.appendHtmlConstant(text);
      	    builder.appendHtmlConstant("</div></div>");
      	    sb.append(builder.toSafeHtml());
      	  }
    
    

    Step 3: Instantiate your widget using your custom appearance.

    TextButton button = new TextButton(new TextButtonCell(
            			new HeaderButtonAppearance<String>()), "Text for Button");
    

    You can see that when I instantiate a button, I pass in an appearance class instantiated with the type of value that the button receives (a string in this case). If you look at the prebuilt java classes (e.g. Css3ButtonCellAppearance) from the themebuilder, you’ll notice that the default constructor with no parameters will instantiate a cell with the default appearance. That’s why it’s necessary to use the constructor where you pass in the actual custom appearance class.

    Custom styling and appearance classes on top of Sencha themebuilder GXT 3.1 (Part 1 – Using the Themebuilder)

    I must find somewhere for my collected knowledge on the “joy” of using Sencha themebuilder. At my company, we’re currently working on building a custom style for our web application. Somewhere in the past, the decision was made to use Sencha GXT for their custom widgets and styling on top of GWT. Like most frameworks, things went smoothly as long as we were using the functionality out of the box. However, when we tried venturing outside, we were quickly reprimanded by the limitations of the framework.

    In our scenario, we needed to brand our application differently than one of the built-in Sencha themes. Fortunately for us, or so we thought, Sencha created a nice tool in the knick-of-time called the “themebuilder” (currently in beta as of 2/25/2014). The themebuilder alleviates some pains of styling if you stay strictly within the guardrails, but quickly becomes inadequate if you need to do styling on top of it.

    Part A: About the themebuilder and running it.

      Running it is easy (just make sure you are using java version 1.7+). On a mac:

    • You run ./themer.sh with certain command line options. The themer script reads in a custom Sencha file (*.theme) which it then uses to compile and build a set of appearance classes which GWT accepts. Here’s an example of the command I used:
    • ./themer.sh ../examples/mytheme/mytheme.theme
    • As of the beta 2/25/2014, the running the themer will by default override the .jar file.

    • The .theme file is a huge pain to work with. It’s Sencha’s own proprietary format. It’s currently not well documented, which makes it very difficult to know how certain values within the .theme file map to Sencha widgets and how these get mapped on top of GWT and then what eventually gets spat out in your browser. Here’s a snippet:
      theme {
        /* First, create a name for your theme, and define a package to place it in */
        name = "myCustomTheme"
        basePackage = "com.example"
      
        /* Next, configure these basic defaults, to be used throughout the file */
        text = util.fontStyle("Arial, Helvetica, sans-serif", "12px", "#000000", "normal")
        textWhite = util.fontStyle("Arial, Helvetica, sans-serif", "12px", "#eeeeee", "normal")
      
        borderRadius = 6
      
        bgColor = "#ffffff"
        headerBgColor = "#666666"
        menuHoverColor = "#e7e7e7"
        menuSelectColor = "#b7daff"
        headerBgColorLight = "#f9f9f9"
      
        iconColor = "#777777"
        ...
      }
      

      You can see that the file is not quite json, java, or css. It’s some mishmash of everything, but it allows you to define variables and reference them later on in the .theme. This is Sencha’s claim for the themebuilders utility. By simply changing a few values (e.g. the background color, font color, font text, etc.), you can change the entire look and feel of your web application. That is all fine and dandy, but what is not described is what things you actually can and can’t change. For example, here’s a list of things I found that the themebuilder is not capable of:

      • Styling a widget in one instance different from another
      • Adding custom fonts
      • Styling nested widgets differently from non-nested widget (e.g. a button in one panel looking different than a button in another)
      • Support for icons libraries like font-awesome or glyphicon
      • Styling text within a toolbar (the LabelToolItem widget)
      • Styling the body content various content panels widgets (ContentPanel, FramedPanel, AccordionPanelAppearance, Window, Dialog)
      • Stylizing a button when its menu is open vs. closed

      In the next series of posts, I’ll be showing you how I solved each of these issues. Stay tuned for more.

      A general tip: When modifying the .theme file, I used sublime text and had the syntax set to “Javascript.” This enabled some basic coloring and recognition of comments and strings. The coloring was very helpful.

      Part B: Applying the custom theme on top of your GWT project
      This part is more specific to GWT users, but may be helpful to some. I’m currently working in a build environment using Java 1.7, Eclipse Version: Kepler Service Release 1, Build id: 20130919-0819, GWT plugin version 1.8.9 to Eclipse, and maven. Assuming that you’re already configured and up and running with GXT and GWT, you should have an App.gwt.xml file that looks something like this:

      <?xml version="1.0" encoding="UTF-8"?>
      <!DOCTYPE module PUBLIC "-//Google Inc.//DTD Google Web Toolkit 2.5.1//EN"
        "http://google-web-toolkit.googlecode.com/svn/tags/2.5.1/distro-source/core/src/gwt-module.dtd">
      
      <module rename-to='mymodule'>
      ...
      	<!-- GXT Theme -->
       	<inherits name='com.example.Theme' /> 
      ...
      </module>
      

      The key line is the GXT Theme line where GWT applies a theme on top of all of its widgets. This theme name should follow the convention set forth in your .theme file.

        name = "myCustomTheme"
        basePackage = "com.example"
      

      After you build your theme.jar file using the custom .theme file (I used the skeleton.theme file included which has all the values in it), you need to add the jar to your buildpath (or to maven as a dependency). I found that the fastest workflow for me was to modify the .theme file, use an html tool that Sencha includes to approximate the styles, and have my buildpath point directly to the .jar file where it’s created by the themebuilder. For more on this html tool (which helps speed up theme creation), see this post.

      Edit: The new beta themebuilder (released by Sencha on 2/25/2014) spits out some instructions on how to do this, along with the context name of your theme.jar file.

      Here’s a sample:

      The customTheme theme has finished generating.
      Copy the jar (/path/to/theme/customTheme.jar) into your project and copy the following line into your gwt.xml file:
      
          <inherits name="com.example.Theme" />
      

      Then, I run GWT Server through my eclipse in debug mode, which picks up the changes to the theme. Because GWT is trying to rapidly render and compile all of the javascript files and apply the custom theme, it tends to operate very slowly.

      Hopefully if everything went according to play, you should see a different style on top of your application. In the next posts, I’ll start getting into customizing the theme and some workarounds for its deficiencies.

    Tic Tac Toe

    So recently, I was given a coding assignment to create a Tic-Tac-Toe game, following some parameters. I was given full design freedom, but was tasked with emphasizing good coding structure/organization, algorithm use, and simplicity. There were also three types of strategies to design, including a player who tries to always win, one who always tries to tie, and one who plays randomly. It was a good assignment to test to see how far I’ve developed in these past several months. In retrospect, I think I did a respectable job. I ended up using lots of design patterns I hadn’t used before. It’s hard to say whether I’ve surpassed where I was when I left for law school, but taking my programming seriously has definitely elevated me quickly compared with where I was just a few months ago. In any case, here is a summary of the project with code available on my github (https://github.com/rocketegg/Projects/tree/gh-pages/Tic-Tac-Toe):

    TIC-TAC-TOE prompt

    1. A short description of how you approached the problem including design tradeoffs and future improvements.

    I approached the problem from more of a design angle than for sheer performance. Tic-tac-toe is a simple game, so even though many checking run in O(n^2) and take linear memory, this shouldn’t impede performance from a practical sense. It makes the source code more readable as well. I refrained from programming in a way that would box one in to a simple 3×3 grid. For example, the checks for whether the tic-tac-toe game has a winner could theoretically all be run in constant time since there are at most 8 winning configurations.

    Thus, it was my decision to focus more on extensibility so that any part of the program can be improved (as in the real world, based on time and requirement constraints). For example, players can easily be created by implementing the “Player.java” class. Each player has an associated chooseMove() method to implement, which returns a move based on a type of strategy. Following the strategy design pattern, strategies are also easily created and extensible as well. Thus, the win strategy is comprised on several substrategies (not all broken out into classes for simplicity sake) of deciding if there is a winning move to take, a losing move to block, choosing the optimal move, etc.

    In this way, future improvements could easily be made by adding strategies and employing them as part of the broader Win/Tie/Random strategies. One rule I did not have time to implement was a rule based on creation of a “fork” or a situation in which two possible winning scenarios are created so that the opponent is guaranteed a loss. Alongside that strategy would be the counterpart strategy of blocking a fork from forming.

    2. Working java code with instructions on how to run it.

    To run the java code, simply download and build the code and execute the application. The main class instantiates a menu which should be self-explanatory. I focused less on making this menu pretty, however doing so would not be difficult (just time-consuming).

    3. A description of the algorithm used including the strengths and weaknesses.

    As stated above, the algorithms are simple for the sake of readability. They could be improved in numerous ways. For instance, comparing win states for rows/columns could be done in constant time by doing 8 comparisons each based on a particular win configuration. Alternatively, one could create a string to represent a game board: e.g. “XXO|OXO|OXO” could represent the positions in snaking order. Then arithmetic based on a character array could be done to save memory and computation time. Finally (but not comprehensively), one could implement the algorithm using a depth-first-search algorithm. One thought I had was to implement the algorithm using DFS which would search for each possible win scenario given a board configuration. There wouldn’t be too many since board states in tic-tac-toe are often “forced” by needing to block an opponent’s winning position. A stack would be kept given the moves for the particular win scenario currently being followed by the DFS algorithm. When an opponent moves, the algorithm would recompute the win scenarios and choose another one to follow. I implemented a similar algorithm in my code (also available in my github at https://github.com/rocketegg/Practice/tree/master/src/solver) to solve the “peg jumping” game that is common in many bars.

    UPDATE: I’ve since implemented the minimax algorithm as a strategy for solving Tic-Tac-Toe. It was an interesting task, but very hard to debug. The logic is complex (especially with alpha-beta pruning), but it’s extensibility is fantastic. One hiccup I encountered when developing the algorithm was the scoring mechanism. Using just a default -1, 0, and 1 for “O” wins, “Tie game” or “X” wins turned out to be a bad decision (or one that rendered teh minimax strategy nearly useless) because the computer would evaluate a losing strategy that could eventually win (e.g. where the opponent could just immediately win) with the same weight as an immediate win (both have a 1 max value). This turns out to be a common problem with minimax algorithms in general. Thus, I had to tweak the scoring mechanism to take account of the depth of the recursive call. In any case, here is the minimax strategy :

    private BestMove chooseMinimaxMove(TicTacToeBoard board, String side) {
                   int bestScore;
                    GridCell bestMove = null;
                    String otherSide = side.equals("X") ? "O" : "X";
                    if ((bestScore = TicTacToeBoardExaminer.getScore(board, side, depth)) != TicTacToeBoardExaminer.NO_WINNER_YET) {
                            return new BestMove(null, bestScore);
                    }
                    ArrayList<GridCell> possibleMoves = TicTacToeBoardExaminer.getAllOpenMoves(board, side);
                    
                    if (side.equals("X"))        { //Player's turn
                            bestScore = -11;
                    } else {        //Opponent's turn
                            bestScore = 11;
                    }
    
                    BestMove b = null;
                    for (GridCell move : possibleMoves) {
                            board.update(move);
                            GridCell undoMove = new GridCell(move.getRow(), move.getCol(), true, " ");
                            b = chooseMinimaxMove(board, otherSide, depth+1);
                            board.update(undoMove);
                            if (side.equals("X")) {        //player turn
                                    if (b.getScore() > bestScore) {
                                            bestScore = b.getScore();
                                            bestMove = move;
                                    }
                            } else if (side.equals("O")){        //opponent turn
                                    if (b.getScore() < bestScore) {
                                            bestScore = b.getScore();
                                            bestMove = move;
                                    }
                            }
                            
                            //Simple Pruning
                            if (bestScore == TicTacToeBoardExaminer.maxWinScore(side)) {
                                    return new BestMove(bestMove, bestScore);
                            }
                    }
                    return new BestMove(bestMove, bestScore);
            }
            }
            
            /**
             * Just a wrapper class to hold a gridcell and a score
             * @author Gamer
             *
             */
            private class BestMove {
                    private GridCell move;
                    private int score;
                    
                    public BestMove(GridCell move, int score) {
                            this.move = move;
                            this.score = score;
                    }
                    
                    public GridCell getMove() {
                            return move;
                    }
                    
                    public int getScore() {
                            return score;
                    }
            }
    

    Additionally, as part of the minimax strategy, it’s really important to have a good scoring strategy with well-defined limits. Here is what I implemented:

            /**
             * Returns a score (if possible) based on a board configuration and 
             * if you are the side
             * Depth n - means that 10 is the max score - if the game is over on the first move
             *   otherwise, if there is a winning board, subtract the depth because it potentially
             *   opens up to a loss
             * Scores:
             *                 10 - n: side has won, n is depth
             *            -10 + n: other side has won, where n is depth
             *      0: is tie
             *      100: No winner yet
             *  
             * @param board
             * @param side
             * @return
             */
            public static int getScore(TicTacToeBoard board, String side, int depth) {
                    if (sideHasWon(board, "X"))
                            return PLAYER_WIN - depth;
                    else if (sideHasWon(board, "O"))
                            return OPPONENT_WIN + depth;
                    else if (board.getAllOpenCells().size() == 0 && side.equals("X"))
                            return TIE;// - depth;
                    else if (board.getAllOpenCells().size() == 0 && side.equals("O"))
                            return TIE;// + depth;
                    else
                            return NO_WINNER_YET;
            }
    

    4. Any alternate approaches considered.

    See above.

    5. A test suite that measures that probability of each of the computer based opponents winning when pitted against one another.

    I don’t have a fully-fledged test suite, however from the game menu, one can test n-games based on differing players (read: strategies). For example, one can test the win strategy against the tie strategy (i.e. Champ vs Toby) n-number of times. The results for 1000 games range at roughly about 250 games won for Champ, 0 games won for Toby, and the rest tied. One could easily translate this into roughly a 25% win rate when pitted against Toby. When pitted against the random strategy, this win rate creeps to about 90% with a 9% tie rate and about a 1% loss rate. In computing each of these statistics, the player who starts the game is rotated back and forth.

    6. Anything else you think would be valuable.

    I have extensively documented my source code so that it is easier to read. The main classes that one should look at are the TicTacToeGame class which encapsulates an entire game and the Player and Strategy classes to see how the logic is implemented in the backend. I would be happy to answer any other questions about my approach.

    Two weeks in

    Today marks the completion of the second week since I’ve gone back to software engineering.  In all honesty, it’s been a tough transition.  There are so many technologies to catch up on since I was last a programmer.  I find myself googling pretty much every new concept I see, not understanding the answer, then googling further until I can recurse back to the top.  Java code looks unfamiliar to me.  Or perhaps the code I was writing in the past was just unsophisticated and didn’t follow good design patterns.  But it was easier to understand, or so it seems.

    I know starting this blog I stated all my grand ambitions to change law with software.  So far, nothing has materialized.  I think I’m just lazy and need to get started building something.  However, it has been a pretty good few weeks so far.  Simply absorbing new concepts has been invaluable.  The good and bad of my startup is that we are so short-staffed that I have to have my hands in a little bit of everything.  At least I’m hoping that doing so will give me some quick on-the-job training that will help make me more employable in the future.  Here’s to hitting the ground running …