[
  {
    "path": ".classpath",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<classpath>\n\t<classpathentry kind=\"con\" path=\"org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/jdk1.8.0_202\"/>\n\t<classpathentry kind=\"src\" path=\"src\"/>\n\t<classpathentry kind=\"src\" path=\"data\"/>\n\t<classpathentry kind=\"src\" path=\"properties\"/>\n\t<classpathentry kind=\"lib\" path=\"data/generated/tilemap.jar\"/>\n\t<classpathentry kind=\"lib\" path=\"libs/mead.jar\"/>\n\t<classpathentry kind=\"output\" path=\"bin\"/>\n</classpath>\n"
  },
  {
    "path": ".gitignore",
    "content": "# Compiled class file\n*.class\n\n# Log file\n*.log\n\n# BlueJ files\n*.ctxt\n\n# Mobile Tools for Java (J2ME)\n.mtj.tmp/\n\n# Package Files #\n*.war\n*.ear\n*.zip\n*.tar.gz\n*.rar\n\n# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml\nhs_err_pid*\n/bin/\n.DS_Store\n"
  },
  {
    "path": ".project",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<projectDescription>\n\t<name>Solitaire</name>\n\t<comment></comment>\n\t<projects>\n\t</projects>\n\t<buildSpec>\n\t\t<buildCommand>\n\t\t\t<name>org.eclipse.jdt.core.javabuilder</name>\n\t\t\t<arguments>\n\t\t\t</arguments>\n\t\t</buildCommand>\n\t</buildSpec>\n\t<natures>\n\t\t<nature>org.eclipse.jdt.core.javanature</nature>\n\t</natures>\n</projectDescription>\n"
  },
  {
    "path": ".settings/org.eclipse.core.resources.prefs",
    "content": "eclipse.preferences.version=1\nencoding/<project>=UTF-8\n"
  },
  {
    "path": ".settings/org.eclipse.jdt.core.prefs",
    "content": "eclipse.preferences.version=1\norg.eclipse.jdt.core.compiler.annotation.inheritNullAnnotations=disabled\norg.eclipse.jdt.core.compiler.annotation.missingNonNullByDefaultAnnotation=ignore\norg.eclipse.jdt.core.compiler.annotation.nonnull=org.eclipse.jdt.annotation.NonNull\norg.eclipse.jdt.core.compiler.annotation.nonnull.secondary=\norg.eclipse.jdt.core.compiler.annotation.nonnullbydefault=org.eclipse.jdt.annotation.NonNullByDefault\norg.eclipse.jdt.core.compiler.annotation.nonnullbydefault.secondary=\norg.eclipse.jdt.core.compiler.annotation.nullable=org.eclipse.jdt.annotation.Nullable\norg.eclipse.jdt.core.compiler.annotation.nullable.secondary=\norg.eclipse.jdt.core.compiler.annotation.nullanalysis=disabled\norg.eclipse.jdt.core.compiler.problem.APILeak=warning\norg.eclipse.jdt.core.compiler.problem.annotationSuperInterface=warning\norg.eclipse.jdt.core.compiler.problem.autoboxing=ignore\norg.eclipse.jdt.core.compiler.problem.comparingIdentical=error\norg.eclipse.jdt.core.compiler.problem.deadCode=warning\norg.eclipse.jdt.core.compiler.problem.deprecation=warning\norg.eclipse.jdt.core.compiler.problem.deprecationInDeprecatedCode=disabled\norg.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=disabled\norg.eclipse.jdt.core.compiler.problem.discouragedReference=warning\norg.eclipse.jdt.core.compiler.problem.emptyStatement=ignore\norg.eclipse.jdt.core.compiler.problem.explicitlyClosedAutoCloseable=ignore\norg.eclipse.jdt.core.compiler.problem.fallthroughCase=ignore\norg.eclipse.jdt.core.compiler.problem.fatalOptionalError=disabled\norg.eclipse.jdt.core.compiler.problem.fieldHiding=ignore\norg.eclipse.jdt.core.compiler.problem.finalParameterBound=warning\norg.eclipse.jdt.core.compiler.problem.finallyBlockNotCompletingNormally=warning\norg.eclipse.jdt.core.compiler.problem.forbiddenReference=error\norg.eclipse.jdt.core.compiler.problem.hiddenCatchBlock=warning\norg.eclipse.jdt.core.compiler.problem.includeNullInfoFromAsserts=disabled\norg.eclipse.jdt.core.compiler.problem.incompatibleNonInheritedInterfaceMethod=warning\norg.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch=warning\norg.eclipse.jdt.core.compiler.problem.indirectStaticAccess=ignore\norg.eclipse.jdt.core.compiler.problem.localVariableHiding=ignore\norg.eclipse.jdt.core.compiler.problem.methodWithConstructorName=warning\norg.eclipse.jdt.core.compiler.problem.missingDefaultCase=ignore\norg.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=ignore\norg.eclipse.jdt.core.compiler.problem.missingEnumCaseDespiteDefault=disabled\norg.eclipse.jdt.core.compiler.problem.missingHashCodeMethod=ignore\norg.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation=ignore\norg.eclipse.jdt.core.compiler.problem.missingOverrideAnnotationForInterfaceMethodImplementation=enabled\norg.eclipse.jdt.core.compiler.problem.missingSerialVersion=ignore\norg.eclipse.jdt.core.compiler.problem.missingSynchronizedOnInheritedMethod=ignore\norg.eclipse.jdt.core.compiler.problem.noEffectAssignment=error\norg.eclipse.jdt.core.compiler.problem.noImplicitStringConversion=warning\norg.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral=ignore\norg.eclipse.jdt.core.compiler.problem.nonnullParameterAnnotationDropped=warning\norg.eclipse.jdt.core.compiler.problem.nonnullTypeVariableFromLegacyInvocation=warning\norg.eclipse.jdt.core.compiler.problem.nullAnnotationInferenceConflict=error\norg.eclipse.jdt.core.compiler.problem.nullReference=warning\norg.eclipse.jdt.core.compiler.problem.nullSpecViolation=error\norg.eclipse.jdt.core.compiler.problem.nullUncheckedConversion=warning\norg.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=warning\norg.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore\norg.eclipse.jdt.core.compiler.problem.pessimisticNullAnalysisForFreeTypeVariables=warning\norg.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=ignore\norg.eclipse.jdt.core.compiler.problem.potentialNullReference=ignore\norg.eclipse.jdt.core.compiler.problem.potentiallyUnclosedCloseable=ignore\norg.eclipse.jdt.core.compiler.problem.rawTypeReference=warning\norg.eclipse.jdt.core.compiler.problem.redundantNullAnnotation=warning\norg.eclipse.jdt.core.compiler.problem.redundantNullCheck=ignore\norg.eclipse.jdt.core.compiler.problem.redundantSpecificationOfTypeArguments=ignore\norg.eclipse.jdt.core.compiler.problem.redundantSuperinterface=ignore\norg.eclipse.jdt.core.compiler.problem.reportMethodCanBePotentiallyStatic=ignore\norg.eclipse.jdt.core.compiler.problem.reportMethodCanBeStatic=ignore\norg.eclipse.jdt.core.compiler.problem.specialParameterHidingField=disabled\norg.eclipse.jdt.core.compiler.problem.staticAccessReceiver=warning\norg.eclipse.jdt.core.compiler.problem.suppressOptionalErrors=disabled\norg.eclipse.jdt.core.compiler.problem.suppressWarnings=enabled\norg.eclipse.jdt.core.compiler.problem.syntacticNullAnalysisForFields=disabled\norg.eclipse.jdt.core.compiler.problem.syntheticAccessEmulation=ignore\norg.eclipse.jdt.core.compiler.problem.terminalDeprecation=warning\norg.eclipse.jdt.core.compiler.problem.typeParameterHiding=warning\norg.eclipse.jdt.core.compiler.problem.unavoidableGenericTypeProblems=enabled\norg.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation=warning\norg.eclipse.jdt.core.compiler.problem.unclosedCloseable=warning\norg.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock=ignore\norg.eclipse.jdt.core.compiler.problem.unhandledWarningToken=warning\norg.eclipse.jdt.core.compiler.problem.unlikelyCollectionMethodArgumentType=warning\norg.eclipse.jdt.core.compiler.problem.unlikelyCollectionMethodArgumentTypeStrict=disabled\norg.eclipse.jdt.core.compiler.problem.unlikelyEqualsArgumentType=info\norg.eclipse.jdt.core.compiler.problem.unnecessaryElse=ignore\norg.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck=ignore\norg.eclipse.jdt.core.compiler.problem.unqualifiedFieldAccess=ignore\norg.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException=ignore\norg.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionExemptExceptionAndThrowable=enabled\norg.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionIncludeDocCommentReference=enabled\norg.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionWhenOverriding=disabled\norg.eclipse.jdt.core.compiler.problem.unusedExceptionParameter=ignore\norg.eclipse.jdt.core.compiler.problem.unusedImport=warning\norg.eclipse.jdt.core.compiler.problem.unusedLabel=warning\norg.eclipse.jdt.core.compiler.problem.unusedLocal=warning\norg.eclipse.jdt.core.compiler.problem.unusedObjectAllocation=ignore\norg.eclipse.jdt.core.compiler.problem.unusedParameter=ignore\norg.eclipse.jdt.core.compiler.problem.unusedParameterIncludeDocCommentReference=enabled\norg.eclipse.jdt.core.compiler.problem.unusedParameterWhenImplementingAbstract=disabled\norg.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=disabled\norg.eclipse.jdt.core.compiler.problem.unusedPrivateMember=warning\norg.eclipse.jdt.core.compiler.problem.unusedTypeParameter=ignore\norg.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning\norg.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning\n"
  },
  {
    "path": ".settings/org.eclipse.jdt.ui.prefs",
    "content": "eclipse.preferences.version=1\r\norg.eclipse.jdt.ui.ignorelowercasenames=true\r\norg.eclipse.jdt.ui.importorder=java;javax;org;com;framework;game;\r\norg.eclipse.jdt.ui.javadoc=true\r\norg.eclipse.jdt.ui.ondemandthreshold=99\r\norg.eclipse.jdt.ui.staticondemandthreshold=99\r\norg.eclipse.jdt.ui.text.custom_code_templates=<?xml version\\=\"1.0\" encoding\\=\"UTF-8\" standalone\\=\"no\"?><templates><template autoinsert\\=\"true\" context\\=\"gettercomment_context\" deleted\\=\"false\" description\\=\"Comment for getter method\" enabled\\=\"true\" id\\=\"org.eclipse.jdt.ui.text.codetemplates.gettercomment\" name\\=\"gettercomment\">/**\\n * @return the ${bare_field_name}\\n */</template><template autoinsert\\=\"true\" context\\=\"settercomment_context\" deleted\\=\"false\" description\\=\"Comment for setter method\" enabled\\=\"true\" id\\=\"org.eclipse.jdt.ui.text.codetemplates.settercomment\" name\\=\"settercomment\">/**\\n * @param ${param} the ${bare_field_name} to set\\n */</template><template autoinsert\\=\"false\" context\\=\"constructorcomment_context\" deleted\\=\"false\" description\\=\"Comment for created constructors\" enabled\\=\"true\" id\\=\"org.eclipse.jdt.ui.text.codetemplates.constructorcomment\" name\\=\"constructorcomment\">/**\\n * Constructs a new instance of this class type\\n *\\n * ${tags}\\n */</template><template autoinsert\\=\"false\" context\\=\"filecomment_context\" deleted\\=\"false\" description\\=\"Comment for created Java files\" enabled\\=\"true\" id\\=\"org.eclipse.jdt.ui.text.codetemplates.filecomment\" name\\=\"filecomment\">/**\\n* Daniel Ricci &lt;thedanny09@icloud.com&gt;\\n*\\n* Permission is hereby granted, free of charge, to any person\\n* obtaining a copy of this software and associated documentation\\n* files (the \"Software\"), to deal in the Software without restriction,\\n* including without limitation the rights to use, copy, modify, merge,\\n* publish, distribute, sublicense, and/or sell copies of the Software,\\n* and to permit persons to whom the Software is furnished to do so, subject\\n* to the following conditions\\:\\n*\\n* The above copyright notice and this permission notice shall be included in\\n* all copies or substantial portions of the Software.\\n*\\n*\\n* THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\\n* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\\n* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL\\n* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\\n* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\\n* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\\n* IN THE SOFTWARE.\\n*/\\n</template><template autoinsert\\=\"false\" context\\=\"typecomment_context\" deleted\\=\"false\" description\\=\"Comment for created types\" enabled\\=\"true\" id\\=\"org.eclipse.jdt.ui.text.codetemplates.typecomment\" name\\=\"typecomment\">/**\\n * @author Daniel Ricci &lt;thedanny09@icloud.com&gt;\\n */</template><template autoinsert\\=\"true\" context\\=\"fieldcomment_context\" deleted\\=\"false\" description\\=\"Comment for fields\" enabled\\=\"true\" id\\=\"org.eclipse.jdt.ui.text.codetemplates.fieldcomment\" name\\=\"fieldcomment\">/**\\n * \\n */</template><template autoinsert\\=\"false\" context\\=\"methodcomment_context\" deleted\\=\"false\" description\\=\"Comment for non-overriding methods\" enabled\\=\"true\" id\\=\"org.eclipse.jdt.ui.text.codetemplates.methodcomment\" name\\=\"methodcomment\">/**\\n *\\n *\\n * ${tags}\\n */</template><template autoinsert\\=\"false\" context\\=\"overridecomment_context\" deleted\\=\"false\" description\\=\"Comment for overriding methods\" enabled\\=\"true\" id\\=\"org.eclipse.jdt.ui.text.codetemplates.overridecomment\" name\\=\"overridecomment\"/><template autoinsert\\=\"true\" context\\=\"delegatecomment_context\" deleted\\=\"false\" description\\=\"Comment for delegate methods\" enabled\\=\"true\" id\\=\"org.eclipse.jdt.ui.text.codetemplates.delegatecomment\" name\\=\"delegatecomment\">/**\\n * ${tags}\\n * ${see_to_target}\\n */</template><template autoinsert\\=\"true\" context\\=\"newtype_context\" deleted\\=\"false\" description\\=\"Newly created files\" enabled\\=\"true\" id\\=\"org.eclipse.jdt.ui.text.codetemplates.newtype\" name\\=\"newtype\">${filecomment}\\n${package_declaration}\\n\\n${typecomment}\\n${type_declaration}</template><template autoinsert\\=\"true\" context\\=\"classbody_context\" deleted\\=\"false\" description\\=\"Code in new class type bodies\" enabled\\=\"true\" id\\=\"org.eclipse.jdt.ui.text.codetemplates.classbody\" name\\=\"classbody\">\\n</template><template autoinsert\\=\"true\" context\\=\"interfacebody_context\" deleted\\=\"false\" description\\=\"Code in new interface type bodies\" enabled\\=\"true\" id\\=\"org.eclipse.jdt.ui.text.codetemplates.interfacebody\" name\\=\"interfacebody\">\\n</template><template autoinsert\\=\"true\" context\\=\"enumbody_context\" deleted\\=\"false\" description\\=\"Code in new enum type bodies\" enabled\\=\"true\" id\\=\"org.eclipse.jdt.ui.text.codetemplates.enumbody\" name\\=\"enumbody\">\\n</template><template autoinsert\\=\"true\" context\\=\"annotationbody_context\" deleted\\=\"false\" description\\=\"Code in new annotation type bodies\" enabled\\=\"true\" id\\=\"org.eclipse.jdt.ui.text.codetemplates.annotationbody\" name\\=\"annotationbody\">\\n</template><template autoinsert\\=\"true\" context\\=\"catchblock_context\" deleted\\=\"false\" description\\=\"Code in new catch blocks\" enabled\\=\"true\" id\\=\"org.eclipse.jdt.ui.text.codetemplates.catchblock\" name\\=\"catchblock\">// ${todo} Auto-generated catch block\\n${exception_var}.printStackTrace();</template><template autoinsert\\=\"true\" context\\=\"methodbody_context\" deleted\\=\"false\" description\\=\"Code in created method stubs\" enabled\\=\"true\" id\\=\"org.eclipse.jdt.ui.text.codetemplates.methodbody\" name\\=\"methodbody\">// ${todo} Auto-generated method stub\\n${body_statement}</template><template autoinsert\\=\"true\" context\\=\"constructorbody_context\" deleted\\=\"false\" description\\=\"Code in created constructor stubs\" enabled\\=\"true\" id\\=\"org.eclipse.jdt.ui.text.codetemplates.constructorbody\" name\\=\"constructorbody\">${body_statement}\\n// ${todo} Auto-generated constructor stub</template><template autoinsert\\=\"true\" context\\=\"getterbody_context\" deleted\\=\"false\" description\\=\"Code in created getters\" enabled\\=\"true\" id\\=\"org.eclipse.jdt.ui.text.codetemplates.getterbody\" name\\=\"getterbody\">return ${field};</template><template autoinsert\\=\"true\" context\\=\"setterbody_context\" deleted\\=\"false\" description\\=\"Code in created setters\" enabled\\=\"true\" id\\=\"org.eclipse.jdt.ui.text.codetemplates.setterbody\" name\\=\"setterbody\">${field} \\= ${param};</template></templates>\r\n"
  },
  {
    "path": "LICENSE",
    "content": "MIT License\n\nCopyright (c) 2024 Daniel Ricci <thedanny09@icloud.com>\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n"
  },
  {
    "path": "README.md",
    "content": "# Solitaire\n\nThis game serves as a loving homage to the classic Solitaire experience originally found in Microsoft Windows 95. It faithfully preserves the essence and charm of the original game, with only minor bug fixes applied to ensure a seamless experience. My goal is to showcase and honor the timeless appeal of vanilla Solitaire for Windows 95, allowing players to relive those nostalgic moments with authenticity.\n\n![](README.gif)\n\n# Instructions\n\nTo run the game, make sure that you have Java 1.8 installed on your machine. If double-clicking on the .jar file doesn't work, you can also run the game through the command-line using java -jar solitaire.jar\n"
  },
  {
    "path": "assets/blogs/Autocomplete/AutoComplete.txt",
    "content": "In my last post, I decided to clean house and close a bunch of bugs that have been hanging around my backlog. Some of these bug fixes had to do with issues related to the `Undo` feature that I had implemented a while back. I also solved bugs related to the rendering of a card after performing certain operations, and issues related to toggling the `Outline` feature on/off. There was also a small fix that I did on the UI side so that vertical spacing between cards on each of the Tableau views would be consistent with that of the original game.\r\n\r\nThe feature that I will present to you today is the `Autocomplete` feature. This feature builds off the Automove feature where you double click on a card, and on the second mouse down of that card, an attempt will be performed to move that card to a valid position on one of the Foundation views, with priority given to the left-most Foundation position. I also closed up a bunch of bugs from the backlog as well, along with some bugs that were introduced because of this feature that was implemented.\r\n\r\nThe Autocomplete feature takes this a step further by automating this feature with respect to a certain set of cards on the board. The idea with being able to Autocomplete is that the user performs a right-click action anywhere on the board, including on any card available on the Tableau, or the Stock, or any card on the Talon pile.\r\n\r\nWhen this occurs, all top-most face-up cards on the Talon and Tableau piles will be auto-moved (if the move is valid) towards the Foundation view. This is a simple way to be able to move all your cards to the Foundation piles without having to drag the card over it or double click each individual card.\r\n\r\nHere is what the code looks like.\r\n\r\n    /**\r\n     * Performs an auto complete based on all available cards\r\n     */\r\n    private static void performCardsAutocomplete() {\r\n        ViewFactory viewFactory = AbstractFactory.getFactory(ViewFactory.class);\r\n        List<CardView> cards = new ArrayList<CardView>();\r\n        \r\n        // Get the top-most talon card\r\n        CardView talonCard = viewFactory.get(TalonPileView.class).getLastCard();\r\n        if(talonCard != null) {\r\n            cards.add(talonCard);\r\n        }\r\n        \r\n        // Get all available top-most front-facing cards\r\n        List<TableauPileView> tableauPileViews = viewFactory.getAll(TableauPileView.class);\r\n        Collections.reverse(tableauPileViews);\r\n        for(TableauPileView view : tableauPileViews) {\r\n            CardView card = view.getLastCard();\r\n            if(card != null && !card.isBacksideShowing()) {\r\n                cards.add(card);\r\n            }\r\n        }\r\n        \r\n        // Go through the list and apply the automove on each card until there are no cards\r\n        // left or all cards have been iterated over\r\n        while(cards.size() > 0) {\r\n            boolean keepGoing = false;\r\n            for(int i = 0; i < cards.size(); ++i) {\r\n                if(cards.get(i).performCardAutoMovement()) {\r\n                    cards.remove(i);\r\n                    keepGoing = true;\r\n                    break;\r\n                }\r\n            }\r\n            \r\n            if(!keepGoing) {\r\n                break;\r\n            }\r\n        }\r\n        \r\n        // If the talon card was moved then enabled the top-most card so that the next card can be played\r\n        // TODO Can this be self-contained??\r\n        if(talonCard != null && !cards.contains(talonCard)) {\r\n            CardView lastTalonCard = viewFactory.get(TalonPileView.class).getLastCard();\r\n            if(lastTalonCard != null) {\r\n                lastTalonCard.setEnabled(true);\r\n            }\r\n        }\r\n    }\r\n\r\nBased on the code above, this is how the functionality works. The first step is to gather the cards that will be operated on. So we create a list and populate it with the current card that is on the Talon (if any). After that, I go through each Foundation pile (starting at the left-most pile), and I try to get the top-most (card all the way at the bottom) if and only if the card has it's front face showing. So, the priority for these cards is Talon pile first followed by Tableau piles second starting with the left-most pile.\r\n\r\nThe next step is to go through this left, and for each card attempt to perform an Automove to the foundation. If a card can be Automoved, then I remove that card from the list and start the process all over again until I reach the end, or I have no more cards left in my list.\r\n\r\nFinally, I handle an edge case (Bug #142 shown below) that ensures that if the card from the Talon was moved, I initiate a method call to enable the next card. Ideally, this should be self-contained within the Talon, so I put a TODO within the comments and hopefully when I go through and refactor the code or solve a bug / implement a feature related to this I can include the change in that changeset\r\n\r\nHere is an example of the Autocomplete feature in action\r\n\r\n<<insert_here>>\r\n\r\nApart from the Autocomplete feature, I solved a bunch of bugs that I present to you below.\r\n\r\n1. After performing an automove, the talon card is not enabled\r\nhttps://github.com/danielricci/solitaire/issues/142\r\n\r\n2. Going from outline to non-outline with draw three lets you choose any of the three cards and not the right-most one only\r\nhttps://github.com/danielricci/solitaire/issues/141\r\n\r\n3. Dragging a foundation card will think it collided with itself, preventing an undo from happening\r\nhttps://github.com/danielricci/solitaire/issues/145\r\n\r\n4. Performing an undo when an ace goes to the foundation from the tableau does not always work\r\nhttps://github.com/danielricci/solitaire/issues/135\r\n\r\n5. When playing with a timer on, a dragged card still resets to the stock position\r\nhttps://github.com/danielricci/solitaire/issues/147\r\n\r\n6. Going from outline to non-outline doesn't let you move any tableau cards\r\nhttps://github.com/danielricci/solitaire/issues/150\r\n\r\n7. (Draw Three) - Going from outline to non-outline and then dragging a card and letting go puts it in the wrong position\r\nhttps://github.com/danielricci/solitaire/issues/146\r\n\r\n8. Opening the deck dialog and clicking OK will populate the wrong selected item\r\nhttps://github.com/danielricci/solitaire/issues/140\r\n\r\nThe next feature that I am going to work on is the win animation screen. You all know (should know) what this looks like, and I have been waiting a while to get this one done. There a couple of known bugs that need to be fixed as well, along with a couple of UI tweaks and a nice code cleanup pass. There are some translations that I need to fill in as well, and I have a few days of solid testing for both Mac and PC before stamping the game as done.\r\n\r\nYou can always follow my progress by following the game located at https://github.com/danielricci/solitaire and if you have any questions I will do my best to answer them. \r\n\r\nTake care, until my next blog post. \r\n"
  },
  {
    "path": "assets/blogs/Bug Fixes 1/blogpost.txt",
    "content": "In my last post, I talked about the `Undo` feature that was implemented. Undo allows you to revert the last valid move that you made and will put back the score that you had then, with a hit of two points. I demonstrated all the different ways that you can undo your move, basically all the different possible moves that constitute a valid `Undo` move.\r\n\r\nFurthermore, I introduced a bunch of bug fixes related to the game. I did not demonstrate how the bug fixes are now working, however future blog posts that include bug fixes will not be accompanied by a small demonstration of the expected result.\r\n\r\nI had scheduled some time for me to work on the `Autocomplete` feature. For this feature, the user will be able to right click anywhere on the board, and all the cards that are face up that can be moved to any of the foundations will be moved there. I don't see this feature taking a lot of time to implement since being able to move a card to the foundation has already been implemented, such as when the user double-clicks on a card.\r\n\r\nAs I was preparing myself to start work on this feature, I glanced over at the number of bugs that I logged, and I felt that it would be a nice gesture to get a few of the bugs out the door before I introduce a new feature that would undoubtedly introduce a few bugs here and there.\r\n\r\nTherefore, I took a step back and got to work on a bunch of bugs, which I will present to you below.\r\n\r\nhttps://github.com/danielricci/solitaire/issues/125\r\n1. Clicking on the stock and then performing an undo, does not subtract 2\r\n\r\nhttps://github.com/danielricci/solitaire/issues/126\r\n2. Double-clicking on an Ace will position itself momentarily at 0,0 if you hold the mouse down on the second mouse down\r\n\r\nhttps://github.com/danielricci/solitaire/issues/107\r\n3. Switching from outline to non-outline does not update the cards in the talon view\r\n\r\nhttps://github.com/danielricci/solitaire/issues/98\r\n4. When dragging multiple cards in outline mode, the outline does not look consistent\r\n\r\nhttps://github.com/danielricci/solitaire/issues/128\r\n5. In outline mode, doubling to automove a card shows a small green artifact on the status bar\r\n\r\nhttps://github.com/danielricci/solitaire/issues/131\r\n6. Talon Card Proportions\r\n\r\nhttps://github.com/danielricci/solitaire/issues/129\r\n7. Automove shows the card at the top left on the second mouse down\r\n\r\nhttps://github.com/danielricci/solitaire/issues/133\r\n8. Dragging more than one card causes the cards to be cut at the bottom when playing in a timed game\r\n\r\nhttps://github.com/danielricci/solitaire/issues/134\r\n9. Playing a timed game causes the card to jump to the origin every tick\r\n\r\nNow that I closed a lot of bugs, It's time to implement another feature. I will continue my work on the Autocomplete item.\r\n\r\nYou can always follow my progress by following the game located at https://github.com/danielricci/solitaire and if you have any questions I will do my best to answer them. \r\n\r\nTake care, until my next blog post. "
  },
  {
    "path": "assets/blogs/Deck Selection Images/Features.txt",
    "content": ""
  },
  {
    "path": "assets/blogs/Draw Three/entry.txt",
    "content": "In my last post, I implemented the `Card Back` deck selection feature, which allows you to choose between 12 built-in deck images that would change the card backs of all the cards in the game. You can view the blog post <<<here>>>.\r\n\r\nThe next feature that I implemented was the ability to play Solitaire using the `Draw Three` game mode, which allows you to play the game using three cards at a time. I also added the functionality for scoring when in this mode for both `Vegas` and `Standard`.\r\n\r\nHere is what the `Draw Three` game mode looks like, and how to set the game for this mode.\r\n\r\nFrom the `File` menu, choose `Options`. When the dialog open, click on the `Draw Three` radio button, and then click on `OK`. \r\n\r\n<Options dialog image>\r\n\r\nYou will notice that your game will restart, and you will now have three cards drawn at a time when you click on your Stock card.\r\n\r\n<Show the game when playing with three cards>\r\n\r\nThis feature took quite a while for me to implement as there were a lot of small things that I had to change.  Here is the list of features/functionalities that I had to work on to get my game to support the `Draw Three` game mode.\r\n\r\n1. When clicking on the Stock card, three cards should be loaded at a time instead of one.\r\n\r\nThis was simply a matter of taking the `blank card` that I use to partition my deck when playing in `Draw One`, and have it skip three cards at a time instead of one. At this point, all three cards will be stacked on top of each other, however, my next task would fix that up even further by applying an offset to each card.\r\n\r\n2. When three cards are shown, they should be rendered next to each other.\r\n\r\nThis task was done to compliment my first task. When loading three cards at a time, all that I needed to do was iterate through each card, and multiply the x-axis location of the card by (iteration * 12px).\r\n\r\nBecause of the GridBagLayout that I use to render the different piles in the game, I had some trouble with this at first. mostly with the view chopping off the two right-most cards because the view was initially only ever sized for rendering at most one card. \r\n\r\nI tried to take row 0, columns 1 and column 2, and merge them both together using a `colspan` in one of my GridBagConstraints, however this would cause some alignment problems, so I instead played with the insets and padding of the view, so that three cards could be rendered without any of the cards being chopped.\r\n\r\nHere is some of the code that I wrote to achieve this.\r\n\r\n<insert Java code here, GameView line 95>\r\n\r\n3. When three cards are loaded, the right-most card should be the only card that can be interacted with.\r\n\r\nThis was a little bit tricky because I didn't want to introduce a flag and then have to manage that depending on the different states of the game. Experience has taught me just how difficult it can be to manage the many different states of an object, and the more flags that you add to a class, the more things can go wrong.\r\n\r\nTherefore, I overwrote the setEnabled method of my view, and I would instead toggle mouse events associated with that view. I had to do this for both the CardView and the CardOutline since they both do not have a common class that they inherit from as of yet, apart from the generic PanelView class that is Engine specific and I didn't want to put the game-specific code in the engine.\r\n\r\n<insert code here>\r\n\r\n4. When a single card from the three card pile moves to the Tableau or the Foundation pile, the next right-most card should now be playable.\r\n\r\nThis involved two sub-tasks that I needed to introduce into the game. The first was to introduce a `mouseReleased` event on a card within the Talon deck, such that when the event would occur, I would verify if the card that was just dragged still exists in the Talon. \r\n\r\nIf the card existed then the move was invalid, so do nothing with the other cards. If the card was moved then take the right-most card and enable it. If there are no more cards left, show the at-most-three cards played and enable the right-most card there.\r\n\r\n<show code here>\r\n\r\n5. When playing using the `Vegas` scoring style, you should only be able to go through the entire deck at most three times\r\n\r\nThis code was actually already in place, however, there is currently no art to show that the deck can no longer be recycled. Here is the task for adding the required art to the Stock view.\r\n\r\nhttps://github.com/danielricci/solitaire/issues/39\r\n\r\n6. When playing using the `Draw Three` game mode using the `Standard` scoring style, 20 points should be taken off of the score whenever a deck has been recycled.\r\n\r\nThis was very straight-forward, here is the code for doing this.\r\n\r\n<insert code here>\r\n\r\n7. When playing using the `Draw Three` game mode, showing three cards should hide the currently shown cards.\r\n\r\nBy default, all cards are now marked as not having any visibility. When the three cards come into play, their visibility is shown, and when the card deck re-cycles, their visibility is set back to hidden. When the next set of three cards is shown, the previous at-most-three cards have their visibility set to hidden.\r\n\r\n8. When playing using the `Draw Three` game mode, if you move the three currently shown cards, the previously shown cards should now be made visible to you.\r\n\r\nThis involves looking for my hidden `Blank Card` that keeps tabs of where I am in the current deck. When all three cards have been dragged to one of the other piles (Foundation or Tableau) in the game, I use the blank card index to look for the three cards with a layer of +1,+2, and +3 to that of the blank card. Obviously, this will go up to at most three cards, to avoid any `IndexOutOfBoundsException` issues from being occurring.\r\n\r\nHere is the code related to that bit.\r\n\r\n<insert code here>\r\n\r\nHere are the other issues that I worked on. I have linked the bug issues that I logged, in there I have included screenshots of the actual issue, and you can also go and take a look at the changeset that solves that issue.\r\n\r\n1. You can now press on the `Enter` key when in the Options dialog instead of clicking on the `OK` button\r\n\r\nIssue<https://github.com/danielricci/solitaire/issues/104>\r\nChangeset<https://github.com/danielricci/solitaire/commit/832891bb9c00635073401ce60d51f11fb3d8495d>\r\n\r\n2. I fixed a bug where when you would play using the  `Draw Three` game mode using the `Outline` option, you could draw all three cards` outline instead of just the right-most card.\r\n\r\nIssue<https://github.com/danielricci/solitaire/issues/105>\r\nChangeset<https://github.com/danielricci/solitaire/commit/ea65c2b68d07d0811758016ecc37cb61a8183753>\r\n\r\n3. I fixed a bug where when you were using the `Outline` option, after performing a double-click on a card, if you were to hold the mouse down on the second click and keep it held, the outline would still be visible on the card. This was more of a rendering artifact, however, I still wanted to correct it.\r\n\r\nIssue<https://github.com/danielricci/solitaire/issues/106>\r\nChangeset<https://github.com/danielricci/solitaire/commit/014727604b27205a1ec7be23aa6c7f4b30406751>\r\n\r\n4. I fixed a bug where while playing using the `Draw Three` game mode, if you were to move one card and then play through the entire deck, the next time that you would play through the deck, one of the cards` visibility property would not properly reset, causing the cards currently shown to be offset improperly\r\n\r\nIssue<https://github.com/danielricci/solitaire/issues/108>\r\nChangeset<https://github.com/danielricci/solitaire/commit/a03a05d08fbf103c6f5021513fad427943014cd7>\r\n\r\n5. Added some enhanced logging to better debug the `Draw-Three` game mode.\r\n\r\nI linked the changeset under the main task for the `Draw Three` game mode, however, I will give an explanation below on how this all works and what the symbols actually mean.\r\n\r\nhttps://github.com/danielricci/solitaire/issues/12\r\n\r\n<insert logs and explanation here>"
  },
  {
    "path": "assets/blogs/Release Date/blog.txt",
    "content": "In my last post, I presented the win animation feature that I finished working on. This is the animation that happens when you win the game, similar to the one shown from the Win95 version of the game. This post is to update everyone on the hard release date that I have set for myself and to present what I have been doing for the past week. \r\nThe release date for the game will be March 15th, 2019.  \r\nHere is what I have left to do.  \r\nI have a few UI tweaks that I need to make.  \r\nI'm working on a cascading effect for the card when you play in `Draw Three` mode. \r\nDraw three proportions don't properly line up on the third pass - https://github.com/danielricci/solitaire/issues/167 \r\nThere are currently no new bugs that have been found as of yet, so that's good news going into the week-long stretch of testing. My testing will be done for both MacOS and Windows, so I'm going to come up with a quick test plan to run through.  \r\nI want to make sure that there is Javadoc and proper comments on all the code in my code base, which I have done a very good job at keeping that up to date however its always good to do a quick pass.  \r\nI need to build a version of the framework that I am using, and then build the 1.0 of the game and make sure that it runs well.  \r\nHere is what I have done in the past week.  \r\nI spent time working on various bug fixes and updating the game data to support transparent corners since until now the cards have just been squares with their corners rendered through. I also worked on and am currently finishing off the cascading effect for the Talon pile view \r\nStock Card Proportions\r\nhttps://github.com/danielricci/solitaire/issues/132 \r\nJust like in the original game, when you click the stock button, the cards will display a cascading effect that will `count down` as you go through the deck. \r\n\r\nTalon Card Proportions\r\nhttps://github.com/danielricci/solitaire/issues/130 \r\nAs shown above, notice how the cards cascade over each-other the more you go through the deck \r\nThere will be something similar done for Draw Three that I am working on right now. \r\nYou can always follow my progress by following the game located at https://github.com/danielricci/solitaire, and if you have any questions I will do my best to answer them. \r\nTake care, until my next blog post."
  },
  {
    "path": "assets/blogs/Undo/Undo.txt",
    "content": "In my last post, I introduced some new art assets into the game related to the stock card, and I added a visual effect for when you hover a card over a foundation when playing with the `outline` option checked on. \n\nThe game is definitely starting to look a lot more like the original Solitaire. However, there is still some polish needed on the UI, and of course, some missing features such as the right-click `autoplay` feature, and the grand finale feature for when the player wins the game. I'm so looking forward to that feature.\n\nFor the past 3-4 weeks, apart from some architectural adjustments to the code base, I worked on the undo feature. The undo feature lets you undo the last move that was played in the game, and of course, the score that was associated with the move. Performing an undo also has a cost associated with it, so your score will take a small hit of two points.\n\nOriginally, I had overlooked how the `Draw Three` game mode worked behind the scenes. Initially, each card was on it's own layer similar to how the `Draw One` game mode works, however, this implementation caused a bunch of edge case issues that I was not willing to hack, so I took a step back and I re-designed the Draw Three feature from the ground up to work properly this time.\n\nFurthermore, whenever you click on the stock, I did not realize that the three cards currently shown would then be positioned in an overlapping fashion, I thought and had implemented it so that those cards would be hidden, and when you had no more cards left to drag, you would show the three cards `behind` your hand. This implementation was wrong, so I corrected it.\n\nThis correction required me to associate each set of three cards with their own unique layer and position. Since JLayeredPane natively supports these two concepts, it wasn't as difficult to adapt my code to work like this. A few areas of the code that are difficult to do are things like knowing which position within the layer the card is in so that you can apply the correct x-axis offset. Being able to distinguish between the last card in a set of three cards being dragged out, and knowing that if there is no collision, that it needs to be played back on its own layer, not on the layer `now` being shown.\n\nSuffice to say, the undo now works very well, with a few bugs encountered here and there that have been logged.\n\nHere is the list of possible undoable actions.\n\n1. Clicking on the stock can now be undone. This will revert the cards being shown to the previous set of cards, depending on the game mode (Draw One vs. Draw Three).\n\n2. Moving a card from the Talon can now be properly undone.\n\n3. Moving a card from the Foundation can now be properly undone.\n\n4. Moving a card from the tableau can now be properly undone.\n\n5. Performing an undo will also remove the score that was associated with that move. Furthermore, performing an Undo will result in a loss of two points.\n\n6. You can only undo your last valid move.\n\n7. Clicking on a card that has its back shown cannot be undone, so you will lose the ability to undo for the previous move prior to that.\n\nApart from the undo feature, there were some lingering bugs that I wanted to solve. Here is the list of bugs that were fixed.\n\n1. Fixed an issue related to the deck images being imported into a low-res fashion.\n\n2. Fixed an issue where the foundation view would highlight when there was already a card on that foundation, and another card was being dragged over it.\n\n3. Fixed an issue where dragging a card from the talon to the foundation would cause the dragged card to not be shown properly\n\n4. Fixed an issue where dragging a king along with other cards onto an empty pile would cause the cards to not be properly displayed.\n\n5. Fixed a bug where restarting the stock deck would cause previous cards to still be shown and not properly aligned when playing in `Draw Three` game mode.\n\n6. Fixed an issue where dragging a card from the talon in `Draw Three` would not position the card back in the right place on the talon if there was no valid collision detected.\n\nThe next feature that I am implementing is the `auto-complete` feature where you right click on the board and all available valid moves are automatically performed for you. Once this is done\nI will work on churning out all the bugs and the remaining UI changes that have to be done.\n\nOnce the game is stable, I will implement the final task, the `game win` animation that we all absolutely loved to watch when we were kids (and still today) when the game was won.\n\nYou can always follow my progress by following the game located at https://github.com/danielricci/solitaire, and if you have any questions I will do my best to answer them.\n\nTake care, until my next blog post."
  },
  {
    "path": "assets/blogs/Win Animation/WinAnimation.txt",
    "content": "In my last post, I presented the Autocomplete feature that I implemented. This feature lets you right-click anywhere on the board (including cards), and all face-up top-most cards will attempt to put themselves in one of the four Foundation piles above the board. I also mentioned a handful of bug fixes that were done.\r\n\r\nThe last feature that I will demonstrate here is the `Win Animation` feature that occurs when you win the game or push the Alt+Shift+2 cheat code to win. \r\n\r\nThe `Win Animation` is an animation that is played when you win the game, that is when all the cards are properly situated on each of the four Foundation piles above the board. The animation starts at the left-most pile, ending at the rightmost pile for each group of cards (Kings first, then Queen, Jack, 10, etc).\r\n\r\nThe path that the card follows is similar to a sine/cosine wave. Each card has a wave randomly generated that fits within a specified period. These choices are limited to a set number of choices based on my observations of the original game, and there are quite a few randomly generated choices that can occur.\r\n\r\nI originally started prototyping this functionality using vanilla trigonometry, however, I found an implementation online that I felt was much simpler to implement, and that had much better readability for those not so fluent in the way of mathematical formulas. The implementation that I retrofitted into my game is the one from `Mr. Doob`, you can find the link to his code here.\r\n\r\nHere is what the win animation looks like\r\n\r\n<insert win animation here>\r\n\r\nThere are a few parts to the code to make this work, and I will explain the major players of this algorithm in snippets below. \r\n\r\nFor this functionality, I create a class called `WinAnimationHelper` to manage the animation process. This class has a static method called `processCards` that gets called when someone wants to process all the cards on the Foundation piles.\r\n\r\n    /**\r\n     * Process all the cards held by the foundation views\r\n     */\r\n    public static void processCards() {\r\n        // Get the list of foundation piles\r\n        List<FoundationPileView> foundationsList = AbstractFactory.getFactory(ViewFactory.class).getAll(FoundationPileView.class);\r\n        \r\n        // Reverse the list so that we start with the left-most pile.\r\n        Collections.reverse(foundationsList);\r\n\r\n        // Initialize this helper class\r\n        initialize();\r\n        \r\n        // Populate the queue of items to be processed\r\n        _foundations.addAll(foundationsList);\r\n    }\r\n\r\nOf interest is the `initialize()` method that I call above. This is a static method that creates a timer that processes a field called _foundations at a rate of 80 times per second. After I perform a call to add the available foundations to the queue, this timer will start to process them in a queue like fashion.\r\n\r\nFor each foundation pile that it processes, it will grab the top-most card and create a WinAnimationHelper object, passing in the card that it received.  Here is what the constructor of this class looks like/\r\n\r\n    /**\r\n     * The change in `x` over time\r\n     */\r\n    private double _deltaX = Math.floor(Math.random() * 6 - 3) * 2;\r\n    \r\n    /*\r\n     * The change in `y` over time\r\n     */\r\n    private double _deltaY = -Math.random() * 16;\r\n\r\n    /**\r\n     * Constructs a new instance of this class type\r\n     * \r\n     * @param cardView The card view to animate\r\n     */\r\n    private WinAnimationHelper(CardView cardView) {\r\n        _cardView = cardView;\r\n        Point position = cardView.getParentIView().getContainerClass().getLocation();\r\n        _x = position.getX();\r\n        _y = position.getY();\r\n\r\n        if(_deltaX == 0) {\r\n            _deltaX = 1;\r\n        }\r\n    }\r\n\r\nThe above code will first initialize the deltas for this card. For the rate of change in on the X-Axis, the domain of available values are from [-6, 4]. For the rate of change on the Y-Axis, the range of available values are from (-16.0, 0]. Then the class object is initialized, where I store a reference to the passed in card and I populate the other fields such as the initial position. I also handle an edge case where if the change in X is 0, I set it to 1 so that there is at least some movement along the X-Axis.\r\n\r\nAfter the object is constructed, my timer that created the object calls the method `update()` for each tick until the update can no longer occur because the card is out of bounds of the canvas dimensions.  Here is what the method looks like.\r\n\r\n    /**\r\n     * Performs an update by performing both a next step point calculation and a draw routine\r\n     *\r\n     * @return TRUE if the operation was successful, false otherwise\r\n     */\r\n    private boolean update() {\r\n\r\n        Point point = calculateNextStep();\r\n        if(point == null) {\r\n            return false;\r\n        }\r\n        \r\n        draw(point);\r\n        return true;    \r\n    }\r\n\r\nThe above code is very straight forward, calculate the next location of the card, and then draw to that point.\r\n\r\nHere is the `calculateNextStep` method.\r\n\r\n    /**\r\n     * Calculates the next position that the currently set card will be at\r\n     *\r\n     * @return The position associated with the next step where the card would be at \r\n     */\r\n    private Point calculateNextStep() {\r\n\r\n        // Take the change in X and the change in Y and apply them respectively\r\n        _x += _deltaX;\r\n        _y += _deltaY;\r\n\r\n        // If you are outside the left or right canvas limits then the card should not \r\n        // longer be positioned anywhere relevant so do not return any position\r\n        if(_x < -CardView.CARD_WIDTH || _x > _canvasWidth) {\r\n            return null;\r\n        }\r\n        \r\n        // If the position is outside canvas height (with respect to the bottom of the card)\r\n        if(_y > _canvasHeight - CardView.CARD_HEIGHT) {\r\n            \r\n            // Normalize the position of the card by placing it on the theoretical bottom of the canvas\r\n            _y = _canvasHeight - CardView.CARD_HEIGHT;\r\n            \r\n            // Take the change in `y` inverse it, this along will cause the card to bounce upwards\r\n            // Take only a small percentage of the delta so that it bounces less\r\n            _deltaY = -_deltaY * 0.85;\r\n        } \r\n\r\n        _deltaY += 0.98;\r\n\r\n        return new Point((int)_x, (int)_y);\r\n    }\r\n\r\nThe above code takes the currently computed deltas and adds them to the current x and y positions that were recorded by the card. If the `x` location is outside the bounds of the canvas then there is no more computation to be performed, this is our exit case.  If this is not the case then I check to see if the `y` position is outside the lower bounds of the canvas. If it is, I position the card the absolute bottom of the canvas and then I apply an inverse linear force to the current deltaY. This will cause the card to move upwards however only upwards by a certain percentage. This is an ever decreasing number that will simulate a `bounce` and that will eventually flatline itself with the y-axis if this statement is executed many times. Finally, I update the deltaY with a constant to ensure that the change in `y` counteracts the `bounce` effect.\r\n\r\nOnce this is computed, I perform a draw. Here is what the draw call looks like.\r\n\r\n    /**\r\n     * Draws the currently set card view to the specified position\r\n     *\r\n     * @param point The position to draw to\r\n     */\r\n    private void draw(Point point) {\r\n        CardView cardView = CardView.createLightWeightCard(_cardView);\r\n        cardView.render();\r\n        \r\n        ViewFactory viewFactory = AbstractFactory.getFactory(ViewFactory.class);\r\n        GameView gameView = viewFactory.get(GameView.class);\r\n        gameView.add(cardView, gameView.getComponentZOrder(viewFactory.get(StatusBarView.class)));\r\n        cardView.setBounds(new Rectangle(point.x, point.y, _cardView.getWidth(), _cardView.getHeight()));        \r\n    }\r\n\r\n\r\nThis was tough because I really wanted to simply change the position of a single card and reuse the same buffer for performing the draw call. Doing this however was not possible because the layout manager that I am using is a Swing manager called GridBagLayout, and it was showing many artifacts that were making this functionality look horrible. \r\n\r\nSo instead for each point that I calculate I create a lightweight representation of the specified card view which is in layman terms a JPanel with an image. I take this card and I update it to the position that I calculated previously. I also make sure that it is added to the GameView and that it is position in the proper z-order.\r\n\r\nThe finishing touches for this feature were to make sure that clicking anywhere during the animation or pressing on any key stops the animation and asks you if you want to play again, this is in line with the original game. I also noticed on the original game that when I move the mouse during the animation that the animation animates faster. I don't like this at all, so I made sure not to do that as it detracts from the awesomeness of the animation itself.\r\n\r\nSo that is how I implemented the win animation.\r\n\r\nI also fixed a few more bugs, that I will outline below\r\n\r\n1. performing an undo doesn't undo the score, it just subtracts 2\r\nhttps://github.com/danielricci/solitaire/issues/164\r\n\r\n2. Performing an automove no longer updates the score\r\nhttps://github.com/danielricci/solitaire/issues/155\r\n\r\n3. Cannot perform an undo after doing an Autocomplete\r\nhttps://github.com/danielricci/solitaire/issues/153\r\n\r\nThe next thing on my list is to normalize the UI. There are a few things that I noticed that the original game does that I have to implement. And of course, I need to validate that the UI as a whole looks/behaves like the original game as much as possible.\r\n\r\nTake care, until my next blog post."
  },
  {
    "path": "assets/editor/solitaire-data/tilemap.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n<root>\n    <data>\n        <entry>\n            <key>generated.TileMapData</key>\n            <value>&lt;?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?&gt;\n&lt;root identifier=\"e984a82d-092a-454f-984e-e38606a7f7e5\" name=\"c1\" layers=\"41e4ef0d-8383-4cc2-a31f-01041591ab40\" friendly=\"\" x1=\"0\" y1=\"0\" x2=\"71\" y2=\"96\"/&gt;\n</value>\n        </entry>\n        <entry>\n            <key>generated.TileMapData</key>\n            <value>&lt;?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?&gt;\n&lt;root identifier=\"0adc2583-1a94-48fd-9b6e-b1a141bb76e2\" name=\"c2\" layers=\"41e4ef0d-8383-4cc2-a31f-01041591ab40\" friendly=\"\" x1=\"71\" y1=\"0\" x2=\"142\" y2=\"96\"/&gt;\n</value>\n        </entry>\n        <entry>\n            <key>generated.TileMapData</key>\n            <value>&lt;?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?&gt;\n&lt;root identifier=\"2373e07c-6a5d-404a-bf07-14b2211653f1\" name=\"c3\" layers=\"41e4ef0d-8383-4cc2-a31f-01041591ab40\" friendly=\"\" x1=\"142\" y1=\"0\" x2=\"213\" y2=\"96\"/&gt;\n</value>\n        </entry>\n        <entry>\n            <key>generated.TileMapData</key>\n            <value>&lt;?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?&gt;\n&lt;root identifier=\"92298418-a59d-44df-89c9-7e0c028131f2\" name=\"c4\" layers=\"41e4ef0d-8383-4cc2-a31f-01041591ab40\" friendly=\"\" x1=\"213\" y1=\"0\" x2=\"284\" y2=\"96\"/&gt;\n</value>\n        </entry>\n        <entry>\n            <key>generated.TileMapData</key>\n            <value>&lt;?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?&gt;\n&lt;root identifier=\"76153ba2-26c0-4c1e-8ba4-2b558f948138\" name=\"c5\" layers=\"41e4ef0d-8383-4cc2-a31f-01041591ab40\" friendly=\"\" x1=\"284\" y1=\"0\" x2=\"355\" y2=\"96\"/&gt;\n</value>\n        </entry>\n        <entry>\n            <key>generated.TileMapData</key>\n            <value>&lt;?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?&gt;\n&lt;root identifier=\"dfe50140-8e9c-41cb-b21d-c0af51b78436\" name=\"c6\" layers=\"41e4ef0d-8383-4cc2-a31f-01041591ab40\" friendly=\"\" x1=\"355\" y1=\"0\" x2=\"426\" y2=\"96\"/&gt;\n</value>\n        </entry>\n        <entry>\n            <key>generated.TileMapData</key>\n            <value>&lt;?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?&gt;\n&lt;root identifier=\"fb2435a2-6492-439b-8d34-03e8229a3b8e\" name=\"c7\" layers=\"41e4ef0d-8383-4cc2-a31f-01041591ab40\" friendly=\"\" x1=\"426\" y1=\"0\" x2=\"497\" y2=\"96\"/&gt;\n</value>\n        </entry>\n        <entry>\n            <key>generated.TileMapData</key>\n            <value>&lt;?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?&gt;\n&lt;root identifier=\"0a0ecf52-7060-42f7-9d9d-72ffe26c8907\" name=\"c8\" layers=\"41e4ef0d-8383-4cc2-a31f-01041591ab40\" friendly=\"\" x1=\"497\" y1=\"0\" x2=\"568\" y2=\"96\"/&gt;\n</value>\n        </entry>\n        <entry>\n            <key>generated.TileMapData</key>\n            <value>&lt;?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?&gt;\n&lt;root identifier=\"7a84e376-6c0d-4ba6-a27f-adcf2a41476f\" name=\"c9\" layers=\"41e4ef0d-8383-4cc2-a31f-01041591ab40\" friendly=\"\" x1=\"568\" y1=\"0\" x2=\"639\" y2=\"96\"/&gt;\n</value>\n        </entry>\n        <entry>\n            <key>generated.TileMapData</key>\n            <value>&lt;?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?&gt;\n&lt;root identifier=\"f690e1b0-3c1b-4fd4-8754-09d5823bc76a\" name=\"c10\" layers=\"41e4ef0d-8383-4cc2-a31f-01041591ab40\" friendly=\"\" x1=\"639\" y1=\"0\" x2=\"710\" y2=\"96\"/&gt;\n</value>\n        </entry>\n        <entry>\n            <key>generated.TileMapData</key>\n            <value>&lt;?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?&gt;\n&lt;root identifier=\"ab0658dd-6958-4503-85ae-380dd54ec310\" name=\"c11\" layers=\"41e4ef0d-8383-4cc2-a31f-01041591ab40\" friendly=\"\" x1=\"710\" y1=\"0\" x2=\"781\" y2=\"96\"/&gt;\n</value>\n        </entry>\n        <entry>\n            <key>generated.TileMapData</key>\n            <value>&lt;?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?&gt;\n&lt;root identifier=\"58d2569a-ebd9-4049-b662-7c2dd68968c9\" name=\"c12\" layers=\"41e4ef0d-8383-4cc2-a31f-01041591ab40\" friendly=\"\" x1=\"781\" y1=\"0\" x2=\"852\" y2=\"96\"/&gt;\n</value>\n        </entry>\n        <entry>\n            <key>generated.TileMapData</key>\n            <value>&lt;?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?&gt;\n&lt;root identifier=\"9a666fae-7f67-4afa-8c4d-142d62c782d2\" name=\"c13\" layers=\"41e4ef0d-8383-4cc2-a31f-01041591ab40\" friendly=\"\" x1=\"852\" y1=\"0\" x2=\"923\" y2=\"96\"/&gt;\n</value>\n        </entry>\n        <entry>\n            <key>generated.TileMapData</key>\n            <value>&lt;?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?&gt;\n&lt;root identifier=\"d59b8ca9-5fa0-4f46-b7ac-93869a30117a\" name=\"d1\" layers=\"b0785b21-2e95-4eb0-8e4d-73f9748013fe\" friendly=\"\" x1=\"0\" y1=\"96\" x2=\"71\" y2=\"192\"/&gt;\n</value>\n        </entry>\n        <entry>\n            <key>generated.TileMapData</key>\n            <value>&lt;?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?&gt;\n&lt;root identifier=\"9ec05b58-89fb-4689-b800-175cc034fab1\" name=\"d2\" layers=\"b0785b21-2e95-4eb0-8e4d-73f9748013fe\" friendly=\"\" x1=\"71\" y1=\"96\" x2=\"142\" y2=\"192\"/&gt;\n</value>\n        </entry>\n        <entry>\n            <key>generated.TileMapData</key>\n            <value>&lt;?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?&gt;\n&lt;root identifier=\"d972f5c7-687b-4f65-aa17-f297ba99bc0e\" name=\"d3\" layers=\"b0785b21-2e95-4eb0-8e4d-73f9748013fe\" friendly=\"\" x1=\"142\" y1=\"96\" x2=\"213\" y2=\"192\"/&gt;\n</value>\n        </entry>\n        <entry>\n            <key>generated.TileMapData</key>\n            <value>&lt;?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?&gt;\n&lt;root identifier=\"4f89e5ae-3554-4465-a6df-c409b5030fa2\" name=\"d4\" layers=\"b0785b21-2e95-4eb0-8e4d-73f9748013fe\" friendly=\"\" x1=\"213\" y1=\"96\" x2=\"284\" y2=\"192\"/&gt;\n</value>\n        </entry>\n        <entry>\n            <key>generated.TileMapData</key>\n            <value>&lt;?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?&gt;\n&lt;root identifier=\"0b1e1a44-f5c7-4fc7-b1b3-1ea0fbfae73a\" name=\"d5\" layers=\"b0785b21-2e95-4eb0-8e4d-73f9748013fe\" friendly=\"\" x1=\"284\" y1=\"96\" x2=\"355\" y2=\"192\"/&gt;\n</value>\n        </entry>\n        <entry>\n            <key>generated.TileMapData</key>\n            <value>&lt;?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?&gt;\n&lt;root identifier=\"a8f33327-dfbd-4989-805d-88847490ff20\" name=\"d6\" layers=\"b0785b21-2e95-4eb0-8e4d-73f9748013fe\" friendly=\"\" x1=\"355\" y1=\"96\" x2=\"426\" y2=\"192\"/&gt;\n</value>\n        </entry>\n        <entry>\n            <key>generated.TileMapData</key>\n            <value>&lt;?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?&gt;\n&lt;root identifier=\"3ab272fa-f8cd-4c54-8c75-16ce3b5361c9\" name=\"d7\" layers=\"b0785b21-2e95-4eb0-8e4d-73f9748013fe\" friendly=\"\" x1=\"426\" y1=\"96\" x2=\"497\" y2=\"192\"/&gt;\n</value>\n        </entry>\n        <entry>\n            <key>generated.TileMapData</key>\n            <value>&lt;?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?&gt;\n&lt;root identifier=\"61c0327c-0e96-4893-8dc1-4692e046bb6b\" name=\"d8\" layers=\"b0785b21-2e95-4eb0-8e4d-73f9748013fe\" friendly=\"\" x1=\"497\" y1=\"96\" x2=\"568\" y2=\"192\"/&gt;\n</value>\n        </entry>\n        <entry>\n            <key>generated.TileMapData</key>\n            <value>&lt;?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?&gt;\n&lt;root identifier=\"44672b8c-c9c1-434d-803a-fca1b30ec92b\" name=\"d9\" layers=\"b0785b21-2e95-4eb0-8e4d-73f9748013fe\" friendly=\"\" x1=\"568\" y1=\"96\" x2=\"639\" y2=\"192\"/&gt;\n</value>\n        </entry>\n        <entry>\n            <key>generated.TileMapData</key>\n            <value>&lt;?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?&gt;\n&lt;root identifier=\"29e7d023-9cf2-4776-beef-5f390a6fbc59\" name=\"d10\" layers=\"b0785b21-2e95-4eb0-8e4d-73f9748013fe\" friendly=\"\" x1=\"639\" y1=\"96\" x2=\"710\" y2=\"192\"/&gt;\n</value>\n        </entry>\n        <entry>\n            <key>generated.TileMapData</key>\n            <value>&lt;?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?&gt;\n&lt;root identifier=\"a582dd25-9a24-46c2-ba98-1927e3e55ac5\" name=\"d11\" layers=\"b0785b21-2e95-4eb0-8e4d-73f9748013fe\" friendly=\"\" x1=\"710\" y1=\"96\" x2=\"781\" y2=\"192\"/&gt;\n</value>\n        </entry>\n        <entry>\n            <key>generated.TileMapData</key>\n            <value>&lt;?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?&gt;\n&lt;root identifier=\"ad1b28a4-61a9-4451-9759-9565cd7b0626\" name=\"d12\" layers=\"b0785b21-2e95-4eb0-8e4d-73f9748013fe\" friendly=\"\" x1=\"781\" y1=\"96\" x2=\"852\" y2=\"192\"/&gt;\n</value>\n        </entry>\n        <entry>\n            <key>generated.TileMapData</key>\n            <value>&lt;?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?&gt;\n&lt;root identifier=\"6e1a2bea-c6fd-4ec0-a800-8d65fd038674\" name=\"d13\" layers=\"b0785b21-2e95-4eb0-8e4d-73f9748013fe\" friendly=\"\" x1=\"852\" y1=\"96\" x2=\"923\" y2=\"192\"/&gt;\n</value>\n        </entry>\n        <entry>\n            <key>generated.TileMapData</key>\n            <value>&lt;?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?&gt;\n&lt;root identifier=\"2cc80226-f795-45e4-8c85-4f9acf7a1fb1\" name=\"h1\" layers=\"06be52cc-1d25-46cf-815f-2f47f0d4ae26\" friendly=\"\" x1=\"0\" y1=\"192\" x2=\"71\" y2=\"288\"/&gt;\n</value>\n        </entry>\n        <entry>\n            <key>generated.TileMapData</key>\n            <value>&lt;?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?&gt;\n&lt;root identifier=\"879ae6f3-950e-44a0-82c5-4752e957c1b7\" name=\"h2\" layers=\"06be52cc-1d25-46cf-815f-2f47f0d4ae26\" friendly=\"\" x1=\"71\" y1=\"192\" x2=\"142\" y2=\"288\"/&gt;\n</value>\n        </entry>\n        <entry>\n            <key>generated.TileMapData</key>\n            <value>&lt;?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?&gt;\n&lt;root identifier=\"d110f5d3-a456-4a14-a48a-33d03703e205\" name=\"h3\" layers=\"06be52cc-1d25-46cf-815f-2f47f0d4ae26\" friendly=\"\" x1=\"142\" y1=\"192\" x2=\"213\" y2=\"288\"/&gt;\n</value>\n        </entry>\n        <entry>\n            <key>generated.TileMapData</key>\n            <value>&lt;?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?&gt;\n&lt;root identifier=\"956d7658-3fc6-4422-84ae-2c0027e416e2\" name=\"h4\" layers=\"06be52cc-1d25-46cf-815f-2f47f0d4ae26\" friendly=\"\" x1=\"213\" y1=\"192\" x2=\"284\" y2=\"288\"/&gt;\n</value>\n        </entry>\n        <entry>\n            <key>generated.TileMapData</key>\n            <value>&lt;?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?&gt;\n&lt;root identifier=\"1be5f51f-7a2a-4d0b-8100-ad3343f796f5\" name=\"h5\" layers=\"06be52cc-1d25-46cf-815f-2f47f0d4ae26\" friendly=\"\" x1=\"284\" y1=\"192\" x2=\"355\" y2=\"288\"/&gt;\n</value>\n        </entry>\n        <entry>\n            <key>generated.TileMapData</key>\n            <value>&lt;?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?&gt;\n&lt;root identifier=\"1fbbdf52-331a-47f7-8d1e-e84398cefda8\" name=\"h6\" layers=\"06be52cc-1d25-46cf-815f-2f47f0d4ae26\" friendly=\"\" x1=\"355\" y1=\"192\" x2=\"426\" y2=\"288\"/&gt;\n</value>\n        </entry>\n        <entry>\n            <key>generated.TileMapData</key>\n            <value>&lt;?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?&gt;\n&lt;root identifier=\"53fe97cb-710f-4630-9c1c-8cdc03c77212\" name=\"h7\" layers=\"06be52cc-1d25-46cf-815f-2f47f0d4ae26\" friendly=\"\" x1=\"426\" y1=\"192\" x2=\"497\" y2=\"288\"/&gt;\n</value>\n        </entry>\n        <entry>\n            <key>generated.TileMapData</key>\n            <value>&lt;?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?&gt;\n&lt;root identifier=\"298a41cf-2be4-422a-9b59-f1aadc41f48e\" name=\"h8\" layers=\"06be52cc-1d25-46cf-815f-2f47f0d4ae26\" friendly=\"\" x1=\"497\" y1=\"192\" x2=\"568\" y2=\"288\"/&gt;\n</value>\n        </entry>\n        <entry>\n            <key>generated.TileMapData</key>\n            <value>&lt;?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?&gt;\n&lt;root identifier=\"db19c7f8-44d0-4e03-a848-747a3a31da9c\" name=\"h9\" layers=\"06be52cc-1d25-46cf-815f-2f47f0d4ae26\" friendly=\"\" x1=\"568\" y1=\"192\" x2=\"639\" y2=\"288\"/&gt;\n</value>\n        </entry>\n        <entry>\n            <key>generated.TileMapData</key>\n            <value>&lt;?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?&gt;\n&lt;root identifier=\"934f6d8b-bbbe-43b1-a28d-913c5c80fef9\" name=\"h10\" layers=\"06be52cc-1d25-46cf-815f-2f47f0d4ae26\" friendly=\"\" x1=\"639\" y1=\"192\" x2=\"710\" y2=\"288\"/&gt;\n</value>\n        </entry>\n        <entry>\n            <key>generated.TileMapData</key>\n            <value>&lt;?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?&gt;\n&lt;root identifier=\"7c588781-b5d9-493c-86dc-6b383cc33098\" name=\"h11\" layers=\"06be52cc-1d25-46cf-815f-2f47f0d4ae26\" friendly=\"\" x1=\"710\" y1=\"192\" x2=\"781\" y2=\"288\"/&gt;\n</value>\n        </entry>\n        <entry>\n            <key>generated.TileMapData</key>\n            <value>&lt;?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?&gt;\n&lt;root identifier=\"0d75364f-a431-41dc-9a23-75b0e200ffce\" name=\"h12\" layers=\"06be52cc-1d25-46cf-815f-2f47f0d4ae26\" friendly=\"\" x1=\"781\" y1=\"192\" x2=\"852\" y2=\"288\"/&gt;\n</value>\n        </entry>\n        <entry>\n            <key>generated.TileMapData</key>\n            <value>&lt;?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?&gt;\n&lt;root identifier=\"a3397bc9-187c-461a-b336-7059f6b8eadc\" name=\"h13\" layers=\"06be52cc-1d25-46cf-815f-2f47f0d4ae26\" friendly=\"\" x1=\"852\" y1=\"192\" x2=\"923\" y2=\"288\"/&gt;\n</value>\n        </entry>\n        <entry>\n            <key>generated.TileMapData</key>\n            <value>&lt;?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?&gt;\n&lt;root identifier=\"a4e9de58-b1c8-4a46-8b60-71c4c6a463c9\" name=\"s1\" layers=\"69229e15-6b70-464b-806b-8897329438a2\" friendly=\"\" x1=\"0\" y1=\"288\" x2=\"71\" y2=\"384\"/&gt;\n</value>\n        </entry>\n        <entry>\n            <key>generated.TileMapData</key>\n            <value>&lt;?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?&gt;\n&lt;root identifier=\"0db5fd69-a18f-4024-8a6b-b33b1514ebac\" name=\"s2\" layers=\"69229e15-6b70-464b-806b-8897329438a2\" friendly=\"\" x1=\"71\" y1=\"288\" x2=\"142\" y2=\"384\"/&gt;\n</value>\n        </entry>\n        <entry>\n            <key>generated.TileMapData</key>\n            <value>&lt;?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?&gt;\n&lt;root identifier=\"7abd8566-d1ef-40a6-95e3-7079a77155df\" name=\"s3\" layers=\"69229e15-6b70-464b-806b-8897329438a2\" friendly=\"\" x1=\"142\" y1=\"288\" x2=\"213\" y2=\"384\"/&gt;\n</value>\n        </entry>\n        <entry>\n            <key>generated.TileMapData</key>\n            <value>&lt;?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?&gt;\n&lt;root identifier=\"646ab72c-9789-4271-8fa9-e8d416c0dde2\" name=\"s4\" layers=\"69229e15-6b70-464b-806b-8897329438a2\" friendly=\"\" x1=\"213\" y1=\"288\" x2=\"284\" y2=\"384\"/&gt;\n</value>\n        </entry>\n        <entry>\n            <key>generated.TileMapData</key>\n            <value>&lt;?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?&gt;\n&lt;root identifier=\"635bb570-ae3b-4789-b519-1e2bde2efd2f\" name=\"s5\" layers=\"69229e15-6b70-464b-806b-8897329438a2\" friendly=\"\" x1=\"284\" y1=\"288\" x2=\"355\" y2=\"384\"/&gt;\n</value>\n        </entry>\n        <entry>\n            <key>generated.TileMapData</key>\n            <value>&lt;?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?&gt;\n&lt;root identifier=\"8bb9387c-1e83-47b5-916c-d606cd68dec3\" name=\"s6\" layers=\"69229e15-6b70-464b-806b-8897329438a2\" friendly=\"\" x1=\"355\" y1=\"288\" x2=\"426\" y2=\"384\"/&gt;\n</value>\n        </entry>\n        <entry>\n            <key>generated.TileMapData</key>\n            <value>&lt;?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?&gt;\n&lt;root identifier=\"481c9b0a-76b8-43d0-add7-e76075b61a9b\" name=\"s7\" layers=\"69229e15-6b70-464b-806b-8897329438a2\" friendly=\"\" x1=\"426\" y1=\"288\" x2=\"497\" y2=\"384\"/&gt;\n</value>\n        </entry>\n        <entry>\n            <key>generated.TileMapData</key>\n            <value>&lt;?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?&gt;\n&lt;root identifier=\"6d452f50-9a23-43ed-afa2-0dfaf51b9847\" name=\"s8\" layers=\"69229e15-6b70-464b-806b-8897329438a2\" friendly=\"\" x1=\"497\" y1=\"288\" x2=\"568\" y2=\"384\"/&gt;\n</value>\n        </entry>\n        <entry>\n            <key>generated.TileMapData</key>\n            <value>&lt;?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?&gt;\n&lt;root identifier=\"7e1e4dc6-176a-4a3f-82c8-1079d5662375\" name=\"s9\" layers=\"69229e15-6b70-464b-806b-8897329438a2\" friendly=\"\" x1=\"568\" y1=\"288\" x2=\"639\" y2=\"384\"/&gt;\n</value>\n        </entry>\n        <entry>\n            <key>generated.TileMapData</key>\n            <value>&lt;?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?&gt;\n&lt;root identifier=\"9aad43f8-e1fd-49a8-9f80-e533bc9e57d9\" name=\"s10\" layers=\"69229e15-6b70-464b-806b-8897329438a2\" friendly=\"\" x1=\"639\" y1=\"288\" x2=\"710\" y2=\"384\"/&gt;\n</value>\n        </entry>\n        <entry>\n            <key>generated.TileMapData</key>\n            <value>&lt;?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?&gt;\n&lt;root identifier=\"c90327e4-cd6e-4dde-83c2-1723739225f4\" name=\"s11\" layers=\"69229e15-6b70-464b-806b-8897329438a2\" friendly=\"\" x1=\"710\" y1=\"288\" x2=\"781\" y2=\"384\"/&gt;\n</value>\n        </entry>\n        <entry>\n            <key>generated.TileMapData</key>\n            <value>&lt;?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?&gt;\n&lt;root identifier=\"3b7a097a-c1f4-4190-ae55-d189a19978c6\" name=\"s12\" layers=\"69229e15-6b70-464b-806b-8897329438a2\" friendly=\"\" x1=\"781\" y1=\"288\" x2=\"852\" y2=\"384\"/&gt;\n</value>\n        </entry>\n        <entry>\n            <key>generated.TileMapData</key>\n            <value>&lt;?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?&gt;\n&lt;root identifier=\"00d3d8c0-a9d7-464e-a4fd-14c23f94184b\" name=\"s13\" layers=\"69229e15-6b70-464b-806b-8897329438a2\" friendly=\"\" x1=\"852\" y1=\"288\" x2=\"923\" y2=\"384\"/&gt;\n</value>\n        </entry>\n        <entry>\n            <key>generated.TileMapData</key>\n            <value>&lt;?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?&gt;\n&lt;root identifier=\"c89dfa47-5c49-4c56-836b-19b7dd6e5651\" name=\"deck_1\" layers=\"040cb294-c4ad-47a5-abbb-6a7c8d1f3482\" friendly=\"\" x1=\"923\" y1=\"0\" x2=\"994\" y2=\"96\"/&gt;\n</value>\n        </entry>\n        <entry>\n            <key>generated.TileMapData</key>\n            <value>&lt;?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?&gt;\n&lt;root identifier=\"9e231907-746e-466c-b50d-1eb3db576f7f\" name=\"deck_2\" layers=\"040cb294-c4ad-47a5-abbb-6a7c8d1f3482\" friendly=\"\" x1=\"994\" y1=\"0\" x2=\"1065\" y2=\"96\"/&gt;\n</value>\n        </entry>\n        <entry>\n            <key>generated.TileMapData</key>\n            <value>&lt;?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?&gt;\n&lt;root identifier=\"492b2a75-4ed9-431b-9c7f-c93330a33eb6\" name=\"deck_3\" layers=\"040cb294-c4ad-47a5-abbb-6a7c8d1f3482\" friendly=\"\" x1=\"1065\" y1=\"0\" x2=\"1136\" y2=\"96\"/&gt;\n</value>\n        </entry>\n        <entry>\n            <key>generated.TileMapData</key>\n            <value>&lt;?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?&gt;\n&lt;root identifier=\"e98cff41-88ec-47b0-bbd5-e684c97dc483\" name=\"deck_4\" layers=\"040cb294-c4ad-47a5-abbb-6a7c8d1f3482\" friendly=\"\" x1=\"1136\" y1=\"0\" x2=\"1207\" y2=\"96\"/&gt;\n</value>\n        </entry>\n        <entry>\n            <key>generated.TileMapData</key>\n            <value>&lt;?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?&gt;\n&lt;root identifier=\"c6c3c2d2-620d-4fdd-9fce-bc6190817c12\" name=\"deck_5\" layers=\"040cb294-c4ad-47a5-abbb-6a7c8d1f3482\" friendly=\"\" x1=\"1207\" y1=\"0\" x2=\"1278\" y2=\"96\"/&gt;\n</value>\n        </entry>\n        <entry>\n            <key>generated.TileMapData</key>\n            <value>&lt;?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?&gt;\n&lt;root identifier=\"b38f68aa-20ee-4be7-9840-136b838f7d8f\" name=\"deck_6\" layers=\"040cb294-c4ad-47a5-abbb-6a7c8d1f3482\" friendly=\"\" x1=\"1278\" y1=\"0\" x2=\"1349\" y2=\"96\"/&gt;\n</value>\n        </entry>\n        <entry>\n            <key>generated.TileMapData</key>\n            <value>&lt;?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?&gt;\n&lt;root identifier=\"8c8ed8dd-8d4e-4c70-a267-ba27d105b572\" name=\"deck_7\" layers=\"040cb294-c4ad-47a5-abbb-6a7c8d1f3482\" friendly=\"\" x1=\"1349\" y1=\"0\" x2=\"1420\" y2=\"96\"/&gt;\n</value>\n        </entry>\n        <entry>\n            <key>generated.TileMapData</key>\n            <value>&lt;?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?&gt;\n&lt;root identifier=\"a4ea2b81-8403-4b5a-8413-e54da2e9b147\" name=\"deck_8\" layers=\"040cb294-c4ad-47a5-abbb-6a7c8d1f3482\" friendly=\"\" x1=\"1420\" y1=\"0\" x2=\"1491\" y2=\"96\"/&gt;\n</value>\n        </entry>\n        <entry>\n            <key>generated.TileMapData</key>\n            <value>&lt;?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?&gt;\n&lt;root identifier=\"0e995a0b-0ab6-42e7-9ed9-d4900cfbe304\" name=\"deck_9\" layers=\"040cb294-c4ad-47a5-abbb-6a7c8d1f3482\" friendly=\"\" x1=\"1491\" y1=\"0\" x2=\"1562\" y2=\"96\"/&gt;\n</value>\n        </entry>\n        <entry>\n            <key>generated.TileMapData</key>\n            <value>&lt;?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?&gt;\n&lt;root identifier=\"25000197-ea3d-4912-9e83-cddddaf0d7dd\" name=\"deck_10\" layers=\"040cb294-c4ad-47a5-abbb-6a7c8d1f3482\" friendly=\"\" x1=\"1562\" y1=\"0\" x2=\"1633\" y2=\"96\"/&gt;\n</value>\n        </entry>\n        <entry>\n            <key>generated.TileMapData</key>\n            <value>&lt;?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?&gt;\n&lt;root identifier=\"25000198-ea3d-4912-9e83-cddddaf0d7dd\" name=\"deck_11\" layers=\"040cb294-c4ad-47a5-abbb-6a7c8d1f3482\" friendly=\"\" x1=\"1633\" y1=\"0\" x2=\"1704\" y2=\"96\"/&gt;\n</value>\n        </entry>\n        <entry>\n            <key>generated.TileMapData</key>\n            <value>&lt;?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?&gt;\n&lt;root identifier=\"25000199-ea3d-4912-9e83-cddddaf0d7dd\" name=\"deck_12\" layers=\"040cb294-c4ad-47a5-abbb-6a7c8d1f3482\" friendly=\"\" x1=\"1704\" y1=\"0\" x2=\"1775\" y2=\"96\"/&gt;\n</value>\n        </entry>\n        <entry>\n            <key>generated.TileMapData</key>\n            <value>&lt;?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?&gt;\n&lt;root identifier=\"25000200-ea3d-4912-9e83-cddddaf0d7dd\" name=\"foundation\" layers=\"69229e15-6b70-464b-806b-889732943899\" friendly=\"\" x1=\"1775\" y1=\"0\" x2=\"1846\" y2=\"96\"/&gt;\n</value>\n        </entry>\n        <entry>\n            <key>generated.TileMapData</key>\n            <value>&lt;?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?&gt;\n&lt;root identifier=\"25000200-ea3d-4912-9e83-cddddaf0d7de\" name=\"talon_restart\" layers=\"69229e15-6b70-464b-806b-889732943899\" friendly=\"\" x1=\"1846\" y1=\"0\" x2=\"1917\" y2=\"96\"/&gt;\n</value>\n        </entry>\n        <entry>\n            <key>generated.TileMapData</key>\n            <value>&lt;?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?&gt;\n&lt;root identifier=\"25000200-ea3d-4912-9e83-cddddaf0d7df\" name=\"talon_end\" layers=\"69229e15-6b70-464b-806b-889732943899\" friendly=\"\" x1=\"1917\" y1=\"0\" x2=\"1988\" y2=\"96\"/&gt;\n</value>\n        </entry>\n        <entry>\n            <key>generated.TileMapData</key>\n            <value>&lt;?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?&gt;\n&lt;root identifier=\"8eb12cd0-f6ca-4f8b-9d38-50ec2945dc41\" name=\"backside_empty\" layers=\"69229e15-6b70-464b-806b-889732943899\" friendly=\"\" x1=\"1988\" y1=\"0\" x2=\"2059\" y2=\"96\"/&gt;\n</value>\n        </entry>\n        <entry>\n            <key>generated.TileMapData</key>\n            <value>&lt;?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?&gt;\n&lt;root identifier=\"5a0c5e61-f5b6-4db7-a2a9-405e5fe3c039\" name=\"poker_1\" layers=\"08b388db-1b65-4952-8dff-8664adacf4c8\" friendly=\"\" x1=\"2059\" y1=\"0\" x2=\"2091\" y2=\"22\"/&gt;\n</value>\n        </entry>\n        <entry>\n            <key>generated.TileMapData</key>\n            <value>&lt;?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?&gt;\n&lt;root identifier=\"1a6307f6-0806-496f-9b4f-afbd7cbd7bba\" name=\"poker_2\" layers=\"08b388db-1b65-4952-8dff-8664adacf4c8\" friendly=\"\" x1=\"2091\" y1=\"0\" x2=\"2123\" y2=\"22\"/&gt;\n</value>\n        </entry>\n        <entry>\n            <key>generated.TileMapData</key>\n            <value>&lt;?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?&gt;\n&lt;root identifier=\"b1ea9525-0e4e-4fc8-8a63-55b2bcf77a95\" name=\"castle_0\" layers=\"08b388db-1b65-4952-8dff-8664adacf4c8\" friendly=\"\" x1=\"2123\" y1=\"0\" x2=\"2149\" y2=\"12\"/&gt;\n</value>\n        </entry>\n        <entry>\n            <key>generated.TileMapData</key>\n            <value>&lt;?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?&gt;\n&lt;root identifier=\"1e9ff1c3-ee06-4142-90f5-ec081d91060b\" name=\"robot_0\" layers=\"08b388db-1b65-4952-8dff-8664adacf4c8\" friendly=\"\" x1=\"2149\" y1=\"0\" x2=\"2173\" y2=\"7\"/&gt;\n</value>\n        </entry>\n        <entry>\n            <key>generated.TileMapData</key>\n            <value>&lt;?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?&gt;\n&lt;root identifier=\"2fc57747-aa27-41d5-b348-ed2be68fa384\" name=\"robot_1\" layers=\"08b388db-1b65-4952-8dff-8664adacf4c8\" friendly=\"\" x1=\"2173\" y1=\"0\" x2=\"2197\" y2=\"7\"/&gt;\n</value>\n        </entry>\n        <entry>\n            <key>generated.TileMapData</key>\n            <value>&lt;?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?&gt;\n&lt;root identifier=\"a0531693-d6c6-4c30-98da-00dfe117c8b2\" name=\"sun_0\" layers=\"08b388db-1b65-4952-8dff-8664adacf4c8\" friendly=\"\" x1=\"2197\" y1=\"0\" x2=\"2211\" y2=\"12\"/&gt;\n</value>\n        </entry>\n        <entry>\n            <key>generated.TileMapData</key>\n            <value>&lt;?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?&gt;\n&lt;root identifier=\"9200227b-5948-4d98-b64a-17846b71b717\" name=\"sun_1\" layers=\"08b388db-1b65-4952-8dff-8664adacf4c8\" friendly=\"\" x1=\"2211\" y1=\"0\" x2=\"2225\" y2=\"12\"/&gt;\n</value>\n        </entry>\n        <entry>\n            <key>generated.TileMapData</key>\n            <value>&lt;?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?&gt;\n&lt;root identifier=\"fdf06b20-0845-4acd-9661-9d01d8efee4a\" name=\"deck_7_1\" layers=\"08b388db-1b65-4952-8dff-8664adacf4c8\" friendly=\"\" x1=\"2225\" y1=\"0\" x2=\"2296\" y2=\"96\"/&gt;\n</value>\n        </entry>\n        <entry>\n            <key>generated.TileMapData</key>\n            <value>&lt;?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?&gt;\n&lt;root identifier=\"bc2a584b-5149-40cb-83d0-a5e67a69f9a6\" name=\"deck_7_2\" layers=\"08b388db-1b65-4952-8dff-8664adacf4c8\" friendly=\"\" x1=\"2296\" y1=\"0\" x2=\"2367\" y2=\"96\"/&gt;\n</value>\n        </entry>\n        <entry>\n            <key>generated.TileMapData</key>\n            <value>&lt;?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?&gt;\n&lt;root identifier=\"90e8f2f4-80e9-46f3-b56c-f60c072aed88\" name=\"deck_10_1\" layers=\"08b388db-1b65-4952-8dff-8664adacf4c8\" friendly=\"\" x1=\"2367\" y1=\"0\" x2=\"2438\" y2=\"96\"/&gt;\n</value>\n        </entry>\n        <entry>\n            <key>generated.TileMapData</key>\n            <value>&lt;?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?&gt;\n&lt;root identifier=\"4e0b645a-38fa-425e-bedb-c61c1061f714\" name=\"deck_11_1\" layers=\"08b388db-1b65-4952-8dff-8664adacf4c8\" friendly=\"\" x1=\"2438\" y1=\"0\" x2=\"2509\" y2=\"96\"/&gt;\n</value>\n        </entry>\n        <entry>\n            <key>generated.TileMapData</key>\n            <value>&lt;?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?&gt;\n&lt;root identifier=\"722fa391-4a49-4ddf-b954-4a189cd2f562\" name=\"deck_11_2\" layers=\"08b388db-1b65-4952-8dff-8664adacf4c8\" friendly=\"\" x1=\"2509\" y1=\"0\" x2=\"2580\" y2=\"96\"/&gt;\n</value>\n        </entry>\n        <entry>\n            <key>generated.TileMapData</key>\n            <value>&lt;?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?&gt;\n&lt;root identifier=\"e2ca4158-d3ec-468b-9afd-316d2e160587\" name=\"deck_12_1\" layers=\"08b388db-1b65-4952-8dff-8664adacf4c8\" friendly=\"\" x1=\"2580\" y1=\"0\" x2=\"2651\" y2=\"96\"/&gt;\n</value>\n        </entry>\n        <entry>\n            <key>generated.TileMapData</key>\n            <value>&lt;?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?&gt;\n&lt;root identifier=\"b4d443c9-6606-44df-a294-a3a78e57bad2\" name=\"deck_12_2\" layers=\"08b388db-1b65-4952-8dff-8664adacf4c8\" friendly=\"\" x1=\"2651\" y1=\"0\" x2=\"2722\" y2=\"96\"/&gt;\n</value>\n        </entry>\n    </data>\n</root>\n\n"
  },
  {
    "path": "assets/editor/solitaire.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n<root>\n    <data>\n        <entry>\n            <key>editor.models.TileMapModel</key>\n            <value>&lt;?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?&gt;\n&lt;tilemap name=\"cards\" rows=\"4\" columns=\"13\" width=\"71\" height=\"96\" x=\"0\" y=\"0\" UUID=\"dfbe0320-8dd0-485a-90dd-4e6b62b838c9\"&gt;\n    &lt;tile width=\"71\" height=\"96\" name=\"c1\" fname=\"\" image=\"iVBORw0KGgoAAAANSUhEUgAAAEcAAABgCAYAAABPGW+RAAABQ0lEQVR42u3dQQ6CMBAFUO9/aVypaGgZiobG/5p0YVj5Uob5BcLt9hqL+ZxvYzFeYw1EowNEYhQnFQ/OGZx1BYcDp4azRkkEgjOCs4WRBrSLszWjcSrZIx5nrw7F4fRWSNrqgSN4whEfpuuQU4HgwPlRE/gJowksTjhw4Ayl8sfvxJ5HEwhHtoIDBw4cOHDgGHDgwIEDZ8KgOxXObBtq0+DMuOMIB46a8384rZuGM2zqX4oz8h5UBM6ZF8XgwIFz+Oq0VYyjak4vS7Xu3Quegqcm0H4OHDgGHDhw4MCBAwfOH/3xpfCYMZx4nKOvLcTgjGzDwoEDpwzUqj+xNWdvFbmUw4GjCZSt4MxXZyrH4MBZmo1e71hsKq88+xNXkI88FBWLUzndojvkYh2CA0d8gPM1IPEBjuB5CQ6gDoxPODU+4XQHPcK2ncUHeigAAAAASUVORK5CYII=\" UUID=\"e984a82d-092a-454f-984e-e38606a7f7e5\"&gt;\n        &lt;layer&gt;41e4ef0d-8383-4cc2-a31f-01041591ab40&lt;/layer&gt;\n    &lt;/tile&gt;\n    &lt;tile width=\"71\" height=\"96\" name=\"c2\" fname=\"\" image=\"iVBORw0KGgoAAAANSUhEUgAAAEcAAABgCAYAAABPGW+RAAABbklEQVR42u3dy5KCMBAFUP7/p5mdzlTxCOgkN/RJFQvZgEfs7kQbluU9Vttr+zNW4z1+A9E4ACJxBWfrewhnB6Yi0CHO2T4xB87SBAMHTBtOb5i0D6IplfeGSQE6TeU9AnJq6RCRyqfE6XWycJ4Sczof/AVx9roMzp0FqBJF4CcrdJFF4DdPDg6c72enrWAcFXNaMsh/zaW2qvKYbDXyEo+feI7CmaIITK47ImflKRWrlUA4D8GpPODAgQMHDhw4cODAMeDAgQMHDhw4cODAgQMHDhw4cODAgQPHgAMHDhw4cODAgfPwN742/M0YTnmcq20LZXDuNLzE4IxoWZoGpzUOlMHp3cZ4tT0zqul+L0j2ar6NyFajW6fhwHloEfiIG330rljdImZAEdh61cbhpN4GqzRO477aOPGz8lHZ6eh4ZSaed45nJdBK4L0rtDTONEXgaJzSa8jTFoGppYNfPMWcz3AAHcB4hNPOI5x+AJD3TPnKgWPYAAAAAElFTkSuQmCC\" UUID=\"0adc2583-1a94-48fd-9b6e-b1a141bb76e2\"&gt;\n        &lt;layer&gt;41e4ef0d-8383-4cc2-a31f-01041591ab40&lt;/layer&gt;\n    &lt;/tile&gt;\n    &lt;tile width=\"71\" height=\"96\" name=\"c3\" fname=\"\" image=\"iVBORw0KGgoAAAANSUhEUgAAAEcAAABgCAYAAABPGW+RAAABhklEQVR42u3dwbKCMAyFYd7/petKwRnahgrtiefvjAtdXPG7kKQhjtu2r8Lj8/hahbWvIxAaDSAkojitaxEccPo4tefEHHOYLo4zTBPHPd5cxnkaSO0fEa5znj5oxTNVAke1dAilcnAWHmwqnBUxIHXMmZGdes9tcEYaULLbhzsP7pcOndz24e6DAwec+7PTWTCWijmRDPLUXuqsjySTrVae4vIbz1U4KYpA5bpDbm9VC5LWzS7VOABOFhznBQ444IADDjjggAMOOCxwMuKkHUGZCcPt4A6M9CABOOAQc1LiMIIycCmlGUFRgZEbJAAHnBwx5/26SvaSylZHHOtsxcaTIpB+DjgscMABBxxwwAEHHHAcPngJjBmDY49z9WsLNjgjrVibfk5qnGgcsMGZ3UO++vVMy7sP0b9ted8KHHD+tAhkymKgYmU+Z0EROPJ+ljOB0fezxgm+Bg4xJyvOzOwUPUvpBIIzdolZ49BDDsJY95DTFoHg5EUEp4UDUAOGn3Cq/ITTC5k90Vj3d4l/AAAAAElFTkSuQmCC\" UUID=\"2373e07c-6a5d-404a-bf07-14b2211653f1\"&gt;\n        &lt;layer&gt;41e4ef0d-8383-4cc2-a31f-01041591ab40&lt;/layer&gt;\n    &lt;/tile&gt;\n    &lt;tile width=\"71\" height=\"96\" name=\"c4\" fname=\"\" image=\"iVBORw0KGgoAAAANSUhEUgAAAEcAAABgCAYAAABPGW+RAAABh0lEQVR42u3d24oCMQwA0Pn/n9anXV3Y1k4vsZdT8EFQogeTaQoZr+u1Hh6/jz/rYb3WOxCNDBCJWpyfPISTgIGTgYGTgYGTSCU4mRoDJ5NOtekVkZIjYwzDiahZo2MM2ef0+NVNFANO8yawJaXgnFhzaq8cn57PGqM7Ts2B0owxujeeLSduI2E6/UqvppyGA6f+apB67X+FsmfN6R2juCu/26GnmtaefVBEjKbeqjT4kY1nyYfZchMYtYfY6iQwKk2WOEOOrBtwdsQ5ecGBAwcOHDhw4MCBY8GBAwcOHDhw4MCBAwcOHDhw4MCBAweOBQcOHDhw4MCBA2fzL14yCQTneJy7YwvH4NQMvAzDmW2kaCqc0ryOivF1nNnHGO+OZw4duk8VvW8PwN583RVW7GYYnYYDpz5G6CbwyBt9tO5A3SJmgU1g7n2hOLPflgpO4fvD0wrOojVH47kCzgrnO58a2uNxjj8JrKlXcEY3nqvjhF/KVyvIcGZpPHfCAZSB8RdOib9wegLjTk/MArUyJwAAAABJRU5ErkJggg==\" UUID=\"92298418-a59d-44df-89c9-7e0c028131f2\"&gt;\n        &lt;layer&gt;41e4ef0d-8383-4cc2-a31f-01041591ab40&lt;/layer&gt;\n    &lt;/tile&gt;\n    &lt;tile width=\"71\" height=\"96\" name=\"c5\" fname=\"\" image=\"iVBORw0KGgoAAAANSUhEUgAAAEcAAABgCAYAAABPGW+RAAABqElEQVR42u3d4Q7CIAxG0b3/S+Mv3TTCgJXyUS6JiS6a6sko0Ix5HGdLPD6Pr5ZoZ7sCoVEAQqIWp9QXwQHnHoduBY5NtwKHnNM+lPfgeKCOjDEMx+OsGx2jOiG3BPfolo4xwHFLyKFxLPpz2JxjNXLcvVaNYY7TU1BSjNGEUxPoScVtJIzRWXo86tPggNM/GuTe+y9RWuYc6xhNk8DcaFCbn36fW49WI2JkcSxP13ALTyuckJNArzlEiGJXLuFR7NoQBJwZC09wwKGBAw444IADDjjggAOO1BeSWOhK4agV1GRwFCuO4IBDzomH43lJyVI43peULIMz48IAcMDZNOe8jyuMXnKj1RVn69GKhSeTQOo54NDAAQcccMABBxxwwIn+w2t2AoGzPU7rtoVtcHrKsMNw1LYUSeHU9muvGNNx1Lcxtm7PHLrpPpf0Zm+AbXzf4ZbsFLZOgwNOfwzXSeCWN/p4OgPlFjELTAJ7PjsER/22VLWf3Rqn8hg4rqty5ZzTiBh/4SmHs2JthzJpSuD0YIEDDjkHnMmI4JRwACrA8BdOmb9wegFk7M4xQqf0nQAAAABJRU5ErkJggg==\" UUID=\"76153ba2-26c0-4c1e-8ba4-2b558f948138\"&gt;\n        &lt;layer&gt;41e4ef0d-8383-4cc2-a31f-01041591ab40&lt;/layer&gt;\n    &lt;/tile&gt;\n    &lt;tile width=\"71\" height=\"96\" name=\"c6\" fname=\"\" image=\"iVBORw0KGgoAAAANSUhEUgAAAEcAAABgCAYAAABPGW+RAAABp0lEQVR42u3d2w7CMAiA4b3/S9crT8u6tQwYhb+JiRoNy5eWHoZx276t8fg8/lqjfdsvEBonQEjM4uzHITgdGHAOYBhWHRxyzkXPYVgN4lQDGh5WEhwPVMsYZjgevc46hgmOx7B0jAGOW0JOjaMxntPmHK2Z4+p11BjqOJIDpYgxpnBGAt05cbOEUeql260xDQ448tmg99mjRKmZc7RjTC0Ce7PBaH7aP9eerSxidHE0u2u6jacWTspFoNcaIs0ZssXqc1kc77wBTkacyg0ccMABBxxwwAEHHHBo4ETASVmCon3R3A6+uOhUhQTggEPOCYFDCYqgm6ctQbG66OULCcAB55mc835fa2YJUYKiuc9JVYLCxpNFIOc54IADDjjggAMOOOCAAw44ThtWcMA5Brm6Y1EGR3KsWuY8JxTO6Lj2ivE4TvQz5NmfZ5a8+zD5uVr3rcABRx7DdRFIlYVgBUp9zgKLQMl3S9YEjn63NM7ge+C47soj55zHcaJtPMPhrHi2wzFpa+BIsMAZzFsMK+8V8oo4rnurRIDgnOEAdALDXzh1/sLpBW0yUp87IyDpAAAAAElFTkSuQmCC\" UUID=\"dfe50140-8e9c-41cb-b21d-c0af51b78436\"&gt;\n        &lt;layer&gt;41e4ef0d-8383-4cc2-a31f-01041591ab40&lt;/layer&gt;\n    &lt;/tile&gt;\n    &lt;tile width=\"71\" height=\"96\" name=\"c7\" fname=\"\" image=\"iVBORw0KGgoAAAANSUhEUgAAAEcAAABgCAYAAABPGW+RAAABt0lEQVR42u3d607DMAyG4d3/TZd/DBBtDvPhc/xGmsSmCm8P1IndVHu93uPi8f34NS7Ge/wEQuMBCIlZnKdzERxwxjij18g5TWHA+RSnK4w7TkQi94zhhhMx03nHeMSxhLF+84ExwAFHAadFzvl05hg9V41hjrPTUFKMsTWVzx7j9eYjYmzlnFEgcMDZnw3ujv0vUVqvui1jLPVz7maD2fz092fr2cojxi2O5b/rcYWnFc6Ri8CoNUTZfs5MwqPZlQCi9AeQwlE7dWWueCrmNnDAKY5DzkluXpXCiW5elcHJaEGAA07TnOPZvCo/W3k2r0qvc8oVnpEfVK3b6IbD5eDEOil9IwE44JBz0nHYgpJYYcttQVGpk+Q2EoADTk7Osa6wJbagKFfYqVtQqlXYFJ4nFZ6nDHDAAQcccMABBxxwwGGAcy3dZAdOe5zV2xba4Oy0Vdv0c6RwZs/rqBjpOOo95NXbM1tefVg8rtd1K3DA2Y8Rughkl8XGCpT9OQUWgaPfEYZTaU8gOOAUwamSc1L7OepbUGh2gWMPAw44czCte8g7ywBwwBErPE/CAegBhq9wuvkKpy+t+kiblbFRJwAAAABJRU5ErkJggg==\" UUID=\"fb2435a2-6492-439b-8d34-03e8229a3b8e\"&gt;\n        &lt;layer&gt;41e4ef0d-8383-4cc2-a31f-01041591ab40&lt;/layer&gt;\n    &lt;/tile&gt;\n    &lt;tile width=\"71\" height=\"96\" name=\"c8\" fname=\"\" image=\"iVBORw0KGgoAAAANSUhEUgAAAEcAAABgCAYAAABPGW+RAAABoUlEQVR42u2d4QrCMAwGff+Xnv+cytK1XZKmyRUGKkrgWL8mJ+Lrda6D63P9rIN1rm9A0GgAgsQInKt9CBwBTEVATTh3rwEHOMAhkKMEshdUyzom28rrrrOuow7Hqw3wqAMcz8xJD+fpfk6dORqnxt3z6HXU4MzIpMh1uuHcFXpi26zBPAXUhNNTCDjAmT8NpPddhaR25ljU6W4CpdOgJ5v+H1ucVlZ1LuFo3a4pB08NOGmbQK8eIoXPkQKvtAn0zg7gZINTeQFnBZy0gj16/7Gd7CqlSYEDHDJnORwEu6Kli1xHDU5ZTQoc4PhnjuSBthfsWjNOOsHO4EkTiM8BDnCAUwMOgcxRThPI+MDgCRzgbK8s0KSNUwTBThOod+tbg+EbT+AkhUPmMHiygAOcue0IHODIo0cLVBk4M8NqmT4nDJyIfc5SODsI9tGfZ5YU7IPvq6VJgQOc+TpuTSCCfaL7RLBvKrsGsqmWJu39bGk4na8Bx20qj545S+FEHDxDZM7OfgdNGmFbAQc4tXwygUwgqwEETgsOgBpg+Asn4S+c3h1gPYq4VB3UAAAAAElFTkSuQmCC\" UUID=\"0a0ecf52-7060-42f7-9d9d-72ffe26c8907\"&gt;\n        &lt;layer&gt;41e4ef0d-8383-4cc2-a31f-01041591ab40&lt;/layer&gt;\n    &lt;/tile&gt;\n    &lt;tile width=\"71\" height=\"96\" name=\"c9\" fname=\"\" image=\"iVBORw0KGgoAAAANSUhEUgAAAEcAAABgCAYAAABPGW+RAAAB70lEQVR42u2d247CMAwF+f+fZt+WXdSmduI4vkykSlAqGYb22D5N4PX6jDfb7/ZvvBmf8RcQNAaAIKGBc3UdAucGTEdAQzhP+4ADHOAAJ4oge4n4zjiqVC59A15ZbncccREoDe5VBnjEEcHRBG4Bx/KSKg8nkhaE0xxt1nh6Hj2OGZwZMylyHDGcp0ArbttuMKuAhnAkgYADnPlscHfclUhaa86OOOLG8y4bSLTp+/GObLUrziUcq9O1ZONpAadsEehVQ5Twc+4Er63ZdUI7gFMNTucBnBNwShvskeuPdGZXK5sUOMBBc47DwWA3dOkixzGDY2lfRrBjQ8KZeb0FnNVjwsIZfetS43v17HI12K16HKnxvapLbgb7qYbQYlZHqcZztWZJ13hGrVnSwDmReYADnORwZmdnaGuWtIKsvW08W7OkSOVeHzRdEeh1iaRrH9rO7AIOcLBJMdgzWBbcmpk49b1aEOAApxgcNOewt5vaQ64ygAOcJXsEOO3haJcttIGzMMGhfp0TBk7EOuconAzLGLXLM8MY7J5xlMf1skmBA5z5OG5FIAb7RPWJwZ7Y7BJqUz+bVCHcveAoq+qecNAcBVg3Pyeywa5cTtDyB1ml+4ADHOAAx6UM4NbMiVReCCBwRnAANADDXzjd/IXTDzvZ38tP/aThAAAAAElFTkSuQmCC\" UUID=\"7a84e376-6c0d-4ba6-a27f-adcf2a41476f\"&gt;\n        &lt;layer&gt;41e4ef0d-8383-4cc2-a31f-01041591ab40&lt;/layer&gt;\n    &lt;/tile&gt;\n    &lt;tile width=\"71\" height=\"96\" name=\"c10\" fname=\"\" image=\"iVBORw0KGgoAAAANSUhEUgAAAEcAAABgCAYAAABPGW+RAAAB+ElEQVR42u2d244CIRBE/f+f1qddLwk9DPSlgEPig8aknTMzTVUJ+ni8x5PH/+NrPBnv8QkIGgYgSPTA+bvnfp//vn48nFazAo5xFQEHOMABjhqcrAYeWScETtYMF13HHY7lV6LBeNcBTqYIPAbOqH3Ytud4zRpXz9XruMEZCZOU63TDuSo0k7ZFg5kFZMLpKQQc4IzPBq33WZLA6xYeqTMFp2c26DmwliTwOhEjdVx0zuzleudDztwSJcZzBk6Wqi4zntEaosJyuPYcq+GtZgVKROAqVmApONlWoNR4qgs64KwCJ8typOqcrJnHwwosE3aNaJYZK1ASk1YKuizLsRwcxSC/rOcQsBOwHxywqwg6uZgUOMDJ7zkRwbdEwO7lpSKC79KAPcN4rlIHEaiW56wygAMc4NCQt2jITOWIQOwDxhM4wNGPLIhJjVmEgB0R6Hfpex4oXwefDOe4hQS9t8iRS1Bmz/r2i5cUBR1wdkkCq8Hc2KZQugi6ZJG2PJxsVX1324IEnOrNJ62aEt4qw3LIwMm0Ah4nIBzOCtsY727PlArYKzbadrzvrJgUOMAZr5MmAgnYCdjPCNgvdI1mhlwV5F/8Rtl5cCxhCJwKOOo9pxxOdFA1U0cCjuoADnCAAxyFvBo41fZhQ4jAseAAyADDXzg1/sLpBbaw5qj3TuKAAAAAAElFTkSuQmCC\" UUID=\"f690e1b0-3c1b-4fd4-8754-09d5823bc76a\"&gt;\n        &lt;layer&gt;41e4ef0d-8383-4cc2-a31f-01041591ab40&lt;/layer&gt;\n    &lt;/tile&gt;\n    &lt;tile width=\"71\" height=\"96\" name=\"c11\" fname=\"\" image=\"iVBORw0KGgoAAAANSUhEUgAAAEcAAABgCAYAAABPGW+RAAAEp0lEQVR42u1di27jMAzz//+0Djega5xIJGXnoa7uEGzrFmdhaErWw2vt/bJ1/B7dy9br/doCtNAAAC0ksuDs5+ECZ4GjT6tvBWaBs8BZ4CxwPgKcT14WTIGzHyQCRxz4/xc/x/br7feNvHd4f5IJt4AzC1AbeY9ch/1Np4GD6Kg+ye78zTltd9PovQwwTfjdac1hFzs82Wjg18dummSOxq6R0JZTwJHmLgHoF5wLRbQsOHTqWQ+OJpYt+FwMHDqt7H240/IGcEpoTmytADitv8H9WN73KjjKWKMuyCngIOZ4bFBuRgFnRrNOMeXxk9WY408V/AQVcGZFfQqc3EUwOEc2fBE4THPY1Pha5qg3qILDAIrk4BLNiS6IrBGzViOmPGInu/FLrZW9/qQff8VSfs7xhhoUemzZfPY8tvBUncCIGXsGZG4uOk/xuW5zAtUpwJjTAUMWsd50QrrySDxnFJxwzoOQhb+A9cftrjEQ2TslEpi7UBAYc2IzYSgCABdOXzGkwZzRC5lj2PnzmPNiBQhwxVbTAcden01aJD8essgwB5llz6fqwLEe7FicHwCHxpwF5rDx4pvbgtK7CyXAgaY8ozmBaEYm/WOYkxFlqDmBNeoAQJrTCjIn9HNmNKdhR3BvrUqC4zEnAgYxx1/D+cfHMkfJR6EspucpQ+bU1hy+BmrQUgXaZAJzqlsr5ubvGeFbqiYzhjEnyq6WAAf5QRFzjqENkTmO5nQPIRj3UXBCv4WsofY3o4Zpo/HLMScKKyjMUQ83+ueMX3JahaYZaI6F8ZtezKNKDyPMLM0cSW9ImQus9LCj9mRSSI8yB7LGOV9JpTSoMVYPHDiljE2huKwFiryzykfediknkC02EctgAhGMW9IJZNPJGksbm5Q8bPJ0Kqg5kXmVQqogK4GYAy1lpWllImtGTDkLmtVlDnDIWH1PxglUhLgccxSHTCtU4OEQJdxaTHPIQrDt9UFdaGrMicx+KeaEppwEpdwSFC9NLIZbS/s5LCilaIsb60n4OLXBEZkTM8bCZhGlNSBT6fEMOEnNyS5FwlRQlAAoBw5JoRwFNxluDZzJP8McDxivnOVgqUgxQm3mEM0JlyCJcCtjzmmdek9YK1SYSQP1YhnLRzFHAWZGcy7p8cyCw8IQSHNQvbCaUkbMUYqtLgNHbffxrBVNwZASOcQcpDs35sqTvw+sEVrINpTRZOx7srJrvDoj7stCWQk/M6GX/T4KzkhRNcp65mqE8qZc+Nm5zMk0r/qlbayfwjp3ARZSyU1zFzFnpFHDd+3Hm0n0fgo/sA/ciflq0tEWn5H2Rd9q6u2Wyb6y8bK32V7xbONr7FJgcFr7YnAyLd5fyBzuyQ82+p6rOZntF5T2Rdx6rYGjtmFfbq3UJniFObSqy7T+95FGttudwCw4kj+13W0lmZq5zQkc3cnkLHA0T/yh5cPZ27zIh/F9fuzTwGHFB9LGQxaDsweITatSmtMmtqqyrK6lFsEFFp6zm5xlGmGVjdluAUc6/6Tt8bIA3QLOX9hEUTQWX7295gJngbPAWeAscCoAI3jwC5wFzhiACxwEzgIIALP+hVPwL5z+AU/k+yNm5kkRAAAAAElFTkSuQmCC\" UUID=\"ab0658dd-6958-4503-85ae-380dd54ec310\"&gt;\n        &lt;layer&gt;41e4ef0d-8383-4cc2-a31f-01041591ab40&lt;/layer&gt;\n    &lt;/tile&gt;\n    &lt;tile width=\"71\" height=\"96\" name=\"c12\" fname=\"\" image=\"iVBORw0KGgoAAAANSUhEUgAAAEcAAABgCAYAAABPGW+RAAAFIElEQVR42u2dCXLbMAxFcf9Lo+1M21gi/kItpJTQM26mtmNZT8DHQtCJ+Lrluv+/b265bl+3T0CLBgG0SLhwKh9ccACYnwoIwqksacFZcBacBWfBeRicN5cFQ+D8/te7f36wv+8Rxc/9Y3dZwjDLOQMHAToCx/3dy+Awk9yeWHvfwCOWU4E6eAIWoNNwnAMqF/sE47gVeuwIGAboEjjKZC39qcAIC+l1relwsCAnBwSsRn3IV8BhB0JwkNZUcCqt+XztGUCP0Zw9HMelVO6UxkkiuOzCzhfk0FajQDNAZxK/S0I5uhpH4CQI4UfgnM2MT8HpPUijNQRML5wK0GvgfFpMBSZMMKXpF7BfaTkUzAF/b6AYgJAc3KI5YUQWpgUlGKEhyKUUIKSDt0Wr/Ocwf5408wXkTo7IMsgI0JTC82gSyKxmL9z4PaMb0PAksKcvEqp++kwMMzCE3L0+a93pzaCnwQkjn2kAFZD2z23AFCKtNGw6HGT6MMpFmyhu7qBBFsitQAqQHXJwO5z9icncKHjXMEWyWcFxxXsonKa5tfm/1icovEDMG0A7i0kjqg3SnLr7t/0pajUjyUNW6ZQcl2bIXXDg1cIu1rhKAPEt2iBlZBPBou5rT4KTwN0oHHC1G6ss4HALwceeBieBS0CxDpLzgKK2siQVEIZrDjuRBCeLNUQ8By2nDQQoSg2PVg4oBsGyrtTWo5asp1qOTADN10LrIG2RKhU4uyZ2meUoi3Ag7d+rAtP0eb4+0P3NrqOWI11CdAyRm1Zw2iI1aVkx1XJwDlJDCuFiSIwTHBNFyrnRSoXfxK7nhnAEp4a9dbGptZUbPVBSmERnqnYGstSm+1heuBlwdmKYhplX1iPBKqshLpbTMuTClHcvlCUFg6f0KEAjn0WxcYIs66Pk2uJceVD17/WmLWh1FLtdkLNwsY0JGydZwarXrbDlhOjxDLecIAkZN+1zblUC3bmz/FwjGuxKDNOMWBSYAEc7A4VVT1+aSSesHwznysLYgMNQOKUFNaZMWhtuho0yZCP5jFlwaBUOml89RSjKd46ULeM1pyuKFfDMk4yOXnXdBIt5K540pd9HEAMOciHVikXD4lMtp1q807M7fohXncEw2yDTLIdPPvidwZ5WKqrYcZU/U3PomlG7jNzVZE+y7GODmh2tkkeUHnFV+ZJqfuWsPKfu1yQdsER5S7kAF3y4QJYUs+C4a0ZsckutravlYqdXPd1y0CgIH5A01tSNYUm2tl7r1ODywRkFCSKW5diJ0B6kf+W+rxnRivaUEZgwXCnMbZFGQMgZnUDVHXSm0ulonBqPM0ft4glwWrHGSznI5RooarASuRhww+lw3LWudmm37tuw/k7lZs9YmjFbqHLik9ZDSaNdFC1ZFS35ew6wHDmpbgHSjbUAveOeUVu1jeGSaNWzUcMBxCCXnT1DgI9sgLmhttJbfNTWoa4LJGZ3nM9EZqfvaXZZ8zJiKt1yEaNjqHKjx8FxS44eq8HziPk+OEpkKRy4p9Sbpme12m2a0/sdNj1wHHdy4Ki047Zo5UYdPRCFIwuzGpQrTYHTc8AeOBQuqMtYIjk1CTz7dVBdm8mEOyk47p7Qx8GhVb8pxF3bm94Ax1kTY1ajun+v1RwkvqglwbQGATry9VtDC89e11KjdGl+sRqLgOixYf2c48s+hlulD2gInLd/ieJtcL7DbcFZcBacBWfBeRicy5PA7wzodPnww+AtOAzOAkTArD/hBP6E0y93kn6S/56mSgAAAABJRU5ErkJggg==\" UUID=\"58d2569a-ebd9-4049-b662-7c2dd68968c9\"&gt;\n        &lt;layer&gt;41e4ef0d-8383-4cc2-a31f-01041591ab40&lt;/layer&gt;\n    &lt;/tile&gt;\n    &lt;tile width=\"71\" height=\"96\" name=\"c13\" fname=\"\" image=\"iVBORw0KGgoAAAANSUhEUgAAAEcAAABgCAYAAABPGW+RAAAEUElEQVR42u2di26sMAxE+f+fdqV71e4S7PE4CYkRRlq1+ygLh8nEcRx6HJ9N6vH3OG1S22f7BlQ0AKAi4cFp2531WsEpONdm1UJ4IxQKzpvBQDhvB+PCqd6qlDPXc548LLi9t5qhqP/7+Dyiz7WHd1zT4VjAiJ2SB9teWf+5DU/ug8MGgehLolL+937wocHj1boJTm9bD/tGA4qFMtysRq7AKjgj+34UnKPj6kf2/d10p8FBXz7LcyJybz+7DY53gujzzHNPDegYrJ8p4Yx4BAJgBaNb4aADZNp/BJB1gqgpb4PTc1IFp+DE4bDGiTwH7S8VHGR+aGyFTrz3fdaImZBjfpzz+2bHGCUS/KEeLKoc+DdvCgKRim6HM3N064H3jNnzstNnLP97AhzvyjP+Yn7GGLE/Dk4UElLXHxh5IBxmKGKdyAWilduRB8HpSWCpiSwjySXGa9KkVtPA0a5om/e9NhX75L00qdaUxPKlnXAO52RaQDCJzuSOtaYkybry88GK+RMp6Hs2wVLfJaEOeifVxFfDYa42qyALEAVGcJS9Ho7WAxE/LUDtXJQG5gQH9Ez54ETNVOwmA39XvMab688Bh1DPAQB5075ek9KGEGmVY8UyR+NBXs/FfI+bW1oJR+19Lt7CBYZaE4LKEWzE+5UDJE9VbRjqQcpBfuNmLncr5zDGNNxJYPWwfuMOT1bBoXLNBhwh1SMdfgOD1WXKMYyXaVYwyPOUI6CnylBI0FP9MFxNQXiOBWq9coLTw6im5nDCALVpCQdku3LwlEr8xD2A7Fz8duUgWVvZutkFS0uqSUfTnlA5oo/QNSOOVGlARStBYQrPQUkwPZrF6YmjM4ZaX/YWmlfHuR1NMTivY8MRkOpYDocN3S3PYdIWVtNQFWzAj5Tk3gJHzB7j7DlwYBlQj9qTfQ180yqH8RtPOa16rL+JfE8a5bB+A9WjAuNTsmngIA9Q/YZIi2qAupYBZIKjhfrMDIQ5TXNJeAVTshngqEYM0hORKRqY23EXkMhmz3FmP8MTd6JPH5+6ZcJzBgsgxuGYijHGU5HlQj0Kilak3Q7HSmXK4PyWVYBgBYmo0GFjswJX0RlbodKTWSPufcoBhUSo1/CKlrwE1oKiqxvgkCtlzOouEbegO7rlgOOceE+hZO8JpvEcawjhVcUzdYIzbgKQoiuf1Txmr0buKUafCseDwRht1Hxj69hjr0+H4zUnq3l5oEbeZxWufGY+nFnKYebFLH9C+2NTvCngRI15dPFbwSk4cTgoTEjjOcw69EiVRmR6ODCtvQ9Oz41FRhf5p4LDLDx7TRDIHHxk5U1k3ynyORlv/5In2RVpGmRdzSo4Ea+7baVeZLlQJBc86jnb4aC7tUVvYDb3BmrijummNCsWDJr2jT0f20gYcw35yTdRPJz5t9ffSduJxusmrQWnlNMHpjzHGZ4UnLuDwIJTW8Fh4BQgAKb+hZPxL5x+ANT8pnj4fc0QAAAAAElFTkSuQmCC\" UUID=\"9a666fae-7f67-4afa-8c4d-142d62c782d2\"&gt;\n        &lt;layer&gt;41e4ef0d-8383-4cc2-a31f-01041591ab40&lt;/layer&gt;\n    &lt;/tile&gt;\n    &lt;tile width=\"71\" height=\"96\" name=\"d1\" fname=\"\" image=\"iVBORw0KGgoAAAANSUhEUgAAAEcAAABgCAYAAABPGW+RAAABKUlEQVR42u3dQQ6CQAwFUO5/aYwLBQ3UMsRQ0tdkNrIxL+PMb2PCNC01W+/1UbNaag1EIwAiMYTTGA7OMM7z89eCAyeHs0ZpCgTnMM4WRkOgGGdrtcaJYJoB7eNEt1dLnGiHNNw9cDSecDSeeqvbtA+NgSRkOHCcOW4rOUdChgMHjoIDBw4cOHDgwIEDpyBOke9TD6fQDKkWTrHpYx2cgnPrGjhF/xMEpzROBuYioGtxjsBcAGTnOHPgyDkSsoSst9KVm+fAUXDgwIEDBw4cOHDgwIEDZ0gAzi5MMFjri5MYyfbESQ7z4cCB48xxW8k5EjKcWx7AiWdw4HwhJJ/1xBECz6Xj3jiJn1vv3urHOQQHzvG+Cg6csaYTDhyN519xAAUwXuG08wqnB2JR4Y6jlmo1AAAAAElFTkSuQmCC\" UUID=\"d59b8ca9-5fa0-4f46-b7ac-93869a30117a\"&gt;\n        &lt;layer&gt;b0785b21-2e95-4eb0-8e4d-73f9748013fe&lt;/layer&gt;\n    &lt;/tile&gt;\n    &lt;tile width=\"71\" height=\"96\" name=\"d2\" fname=\"\" image=\"iVBORw0KGgoAAAANSUhEUgAAAEcAAABgCAYAAABPGW+RAAABXUlEQVR42u3dQQ7CIBAF0N7/0jVurBppMTHMR94kbLqpeVAYaoZu2xG79mgvsYsjnoFonACR+Arnfu29wWnALAh0jnN1zZwDpw8GDpg+nAqYoE7oW8pHwgSN0uulfNSEHJg2ZCzloXlVfRJ4dq9iIDixG88emEKgOpxvYIqArvMcI6cwz/mLCRlOUc4xTZ5T9UOnyJAre3G6vZVd+Rbfi5nvcxYO/1vBgQMHDhw4cODAEXDgwIEDBw4cOHDgwIEDBw4cOHDgwIEj4MCBAwcOHDhw4MCBAwcOHDgjFeA0YRoFMHk4VWdnfADKwqkqfGsA5eAklE1G4oQW3dbjVJZOx8851XXlsatVynENcXnO9Ad9rDJyYrcPFTCd94ITnyGPfpw6D2xbM0NuHfNnb2VX/pPOWPd9TscoXROn8/FdGyc+CUzBiV+twvIqE/JUS3mUH5xLHEAnMD7h1PiE0w1sZiBQH106AQAAAABJRU5ErkJggg==\" UUID=\"9ec05b58-89fb-4689-b800-175cc034fab1\"&gt;\n        &lt;layer&gt;b0785b21-2e95-4eb0-8e4d-73f9748013fe&lt;/layer&gt;\n    &lt;/tile&gt;\n    &lt;tile width=\"71\" height=\"96\" name=\"d3\" fname=\"\" image=\"iVBORw0KGgoAAAANSUhEUgAAAEcAAABgCAYAAABPGW+RAAABe0lEQVR42u3dwQ6CMBCEYd7/pTFeRA9tlxC7M5m/CQcugh9t2V2qHMfVTrbP9tNO2tW+gdCYACFRxnnvjzZwwFnjjPaZc7Jh1jjBMHOc8PnmPs4OIKGLUI9zduCI9VIdHMFhXLuV/xtHNK7qDwJnx2oG6r9bWeLsOXp9i8K5A9MEtI6Q6TlHX8xhN+fsPEErnI6TtIlzuk7UIkLuvIoWuVXnVbTIyoPrOBpxjjVOeAMHHHDAAQcccMABBxwaOOCAE4ZjuQRlF4zlEpSdMNJLUBRgZJegqMBEr7IA5yEMS1Acl6DQc5hzwCHOIUImtyK3IiunngMOODRwwAEHHHDAAQcccMBJxxl8f3AmNaTses6i+phbCSzUrXNryDY4oj+6zX5uJT/ndD/Uk71bqTwrl4tzWGVh0nNk04cumMJxMnGKx8qMc4p/2JYZIRc/PzO3ssTZlZUXh3BuPQecZ0MsG2cx9zCsLG7lgnEVOOC4Jp4GOABNYHiF0+AVTi8I8FMP4EHiOwAAAABJRU5ErkJggg==\" UUID=\"d972f5c7-687b-4f65-aa17-f297ba99bc0e\"&gt;\n        &lt;layer&gt;b0785b21-2e95-4eb0-8e4d-73f9748013fe&lt;/layer&gt;\n    &lt;/tile&gt;\n    &lt;tile width=\"71\" height=\"96\" name=\"d4\" fname=\"\" image=\"iVBORw0KGgoAAAANSUhEUgAAAEcAAABgCAYAAABPGW+RAAABgUlEQVR42u3dyw6EIAyFYd//pZ3MYm4LKzrtgQM/iauZBPIp0JJUt+3Tdq739dN22qd9A6ERACFxG+f5+4KA5zgvGHACGHACGHAOphI4wRoDTjCd7k4vFWhRP3U4qrWqsJ+aOEe1mBf3k4+TMR0H6edaENiKWD1wUT/gSBLPlgFnDFzVTxrOlQH/M3BVP825FU/OlhM/LLHmZAR+U+JkRsbTxTlZOdWUEXLWHZk2t8rceqfKytV33vKYVHnnLXEWb+CAAw444IADDjjggEMDBxxwwAEHHHDAAQcccMABBxxwwAEHHHDAoYEDDjjggAMOOOCAAw444IADTroCOIcwBwUwtTijlxSdlE7V4YxejNZQdFeD41DG2AXHpQBWjuNWOi1dcxzryiW7lfPrGkrjnCVf9LHKkyNJH1zWnMb/giPDcYxz5Fm5U4Tc5chi1NzqwpRcLysfBsfhHCd4AsEJpiY43U4CnXCku5UTjnwrd1uQwemZeE6KA1AAwyecDj7h9AAwqoHSxffH8AAAAABJRU5ErkJggg==\" UUID=\"4f89e5ae-3554-4465-a6df-c409b5030fa2\"&gt;\n        &lt;layer&gt;b0785b21-2e95-4eb0-8e4d-73f9748013fe&lt;/layer&gt;\n    &lt;/tile&gt;\n    &lt;tile width=\"71\" height=\"96\" name=\"d5\" fname=\"\" image=\"iVBORw0KGgoAAAANSUhEUgAAAEcAAABgCAYAAABPGW+RAAABjUlEQVR42u3d0Q6DIAyFYd//pV12M7dkaBV6aOlPYrKLmZJvWqGK27aj7Wyf7afttKN9A6FxAoSECef9ubWBA841Dg2cMacVOOSc+5fypzgqUKc4fjiqI84xji0h3w2uOiWd44zHUeUsQZyxCfls35EdF8X5n3OeBiuB49XhER1XxRmGc6fDPR1XxTHh9F6hlj1yngQhIVfG6Q3IOKf6CLk38JJzq5G/yLKz8uKFrrHjnLLFLnBo4IADDjjggAMOOODQwAFnGZxAfYmFE6yGFAcn4MNSMXCCPk02H0d1rwuclXCE971z4YifmODIIeeAAw7jHEbIzK2YldPAAQcccMABBxxwwAEHHHDAAQccqQI4TZhGgc0XJ/qSoovSrB9O9MVohqK+D06GZYxTcLIsgJXjZFs6Lc05GdeVS65WmV/X4DrOKfmijypHjmT6kCnnGPapiWPcr+Y4x/jStpoj5Kk40edWxu/XnJWHwMlQw5lSssgKBI7tVAMHHHIOOFpDcC5xADqB4S+cGn/h9AKh/rCVN4D94gAAAABJRU5ErkJggg==\" UUID=\"0b1e1a44-f5c7-4fc7-b1b3-1ea0fbfae73a\"&gt;\n        &lt;layer&gt;b0785b21-2e95-4eb0-8e4d-73f9748013fe&lt;/layer&gt;\n    &lt;/tile&gt;\n    &lt;tile width=\"71\" height=\"96\" name=\"d6\" fname=\"\" image=\"iVBORw0KGgoAAAANSUhEUgAAAEcAAABgCAYAAABPGW+RAAABlElEQVR42u3dS67CMAxA0e5/00VMaJHID39S2zdSJ+ghR+c1wXYjOI5rnFyf62ucjGvcgdDoACGxjPN+/X6B04AB5wcMy6qBw54zuHNYVpM4xYDml9UqjjekQTwbHO87zSiePo73UjSMp4vjvVcZx9PbkHvvsQByiKeXIZfC0Z6oJpBTPDnOykQ1cFbjCWKOq3LunEOeO5TZc/4JVAJHEix9niMNmDpD1vhvlKitJEHTVuW0ShXznJI4xQc44IADDjjggAMOOOAwwAEHnKA4qZtd0ommbZNqTTTlERTNiaY7gqI90dKnLMARTpQjKJWOoHDnsOeAQ57z1DyHDJnaiqqcfg444IADDjjggAMOOEiAAw444Gyu6MHp9IJq93MGXcS6ncCJ/nPdHrI7TqSnD644EZ9bue05UR/qmX9aRX9WbpbncMoi+Z1jXj5E23Mm/r4mzuR7auY5k1/YVjND3oYTobbaivP0qnw7TpQejnvLIjIQOHNLDZzOhs6y2tJDjoZjWlul9ANniANQB4afcGr8hNMLiGLpTmJkAEMAAAAASUVORK5CYII=\" UUID=\"a8f33327-dfbd-4989-805d-88847490ff20\"&gt;\n        &lt;layer&gt;b0785b21-2e95-4eb0-8e4d-73f9748013fe&lt;/layer&gt;\n    &lt;/tile&gt;\n    &lt;tile width=\"71\" height=\"96\" name=\"d7\" fname=\"\" image=\"iVBORw0KGgoAAAANSUhEUgAAAEcAAABgCAYAAABPGW+RAAABo0lEQVR42u3dzRLCIAxG0b7/S9dxY3VRoEJ+PnKZ6UI3qUekSWDG47jGyfW5fsbJuMY3EBoNICSGcd6v7y5wwOnj9N5jzakJA840TlEYWxxvUIN4NjjeTzejeG2cWRgPIMN4a3G88yPjeOtwWjdqAeQQDxzzwnPkRlcCOcWbx3lyoytwnsabiNn/WTFzjvncocya80+gEjgzwbbPc2YDbp0hr/g2tq6tVnwbW1flRfvG6/Oc5DMgtnxIvnbo4yTcBsqBk3SfLB7HO7MGZwcc72peBsexL8PMYc0BBxzyHDJkaiuqcukPGXIEReHnEXIERWFhDTuCkv2RHHoEJXMyJ3PKApxEBSRHUOJbHcwc1hxwEuOQ55AhU1tRlSv2cxINcMABBxxwwAEHHHDAYYADDjimFT04jV5Q7X5Op4tYtxM40H+u20N2x1HafXDFUdy3cltzVDf1zJ9W6nvlZnkOpyw2nznm5YPyQQLzDBmcjfIcdxylDDkER6W26sBQlYfhqPVzwBmHAQecBzDmzS41HNdOIDhV/MDp4gDUgOEvnG7+wukFMOpn0EycDbgAAAAASUVORK5CYII=\" UUID=\"3ab272fa-f8cd-4c54-8c75-16ce3b5361c9\"&gt;\n        &lt;layer&gt;b0785b21-2e95-4eb0-8e4d-73f9748013fe&lt;/layer&gt;\n    &lt;/tile&gt;\n    &lt;tile width=\"71\" height=\"96\" name=\"d8\" fname=\"\" image=\"iVBORw0KGgoAAAANSUhEUgAAAEcAAABgCAYAAABPGW+RAAABvUlEQVR42u2dWw6DMAwEe/9Lt+pPX1LDy95444nEDwItGhLH60Rwu73bneN1fLU77d0+AUFjAAgSh+A8z/0ewPkDpiGgMZytc8ABDnAIyFUCshpmgl7OsFL3tiS9eDjq4ZioFwtHnR8l68XFnNE9GYAEenGzVSs40Q8aCUikdx3OkQeNACTUG8M5M3W36DlHBdrEnDNCLeBcEVs+z7kquHSGHGU6l/dWV0SXdeUz3r5VsWvG25+lmWofiscOfzgFy7I14BRdJ5sPR51ZA2cFOGo3bwNHXQei5xBzgAMc8hwyZLyVxF2r75PDWboS6BQ75LssXGadKbssHPIVm40EwCnkkdhlEahpA8eo1MGwIiADpzAckkDsA8aTkgXFrkXgUCYtMsvZwGFpBjj1PZkNHDYS0HOIOcAhzyFDxlstByfJXZ/V5LNUg95ar56j1NuIc30rgTtmyL41ZDkcp9UHKRzHdStZzHFd1EufrdzXytPynLYf+ujSc9Ltg1vM2XF9Tzg77+mZ5+z8YFvPDHkaHAdvNRVOdVc+Jea41nHk9RwHMNOGFXCA0yPeAIeAHMgPOJtwADQAwy+c/vzC6QFNggUl0BIMHgAAAABJRU5ErkJggg==\" UUID=\"61c0327c-0e96-4893-8dc1-4692e046bb6b\"&gt;\n        &lt;layer&gt;b0785b21-2e95-4eb0-8e4d-73f9748013fe&lt;/layer&gt;\n    &lt;/tile&gt;\n    &lt;tile width=\"71\" height=\"96\" name=\"d9\" fname=\"\" image=\"iVBORw0KGgoAAAANSUhEUgAAAEcAAABgCAYAAABPGW+RAAAB0klEQVR42u2d2wrCQAxE/f+fVnzxBm7TNpnmchb6IoUsxzWZGcXebu9153pdX+vOeq9PQNBYAILELjjP134v4PwBMxDQGs7Wa8ABDnCAk6Uhq0EG1Ns3yq0bUE+3oHp2EWgtrh7/gfVscKyF1foouJ6fQl5tNAKQoJ4dToLN5oHjvVFPQKJ65+Hs2agHIGG9NZwjo3vEyTmjbVr3nCOFRsA5U6y9zjlbsLVC9jKdbb2Vx7sxxpUPXT46ZySc4Qs4wMkGp/W0Sqg7cuicpIr1eoWc2Otc760Su+QckQVwHOGQITtstFWGzMmh59SBkyjQz6VzPL/xaKWQE2bWObyV+sSVceXqXlUqz1FPuTJw1PqoDBy1subk0HOA0xvO0e/WE/0oPE/AnvCHC7kCdjXUUsbzio8jeQ5wCNiV9QjYOTn0HBpyTTgC3VFX5wgUa22FHOx16nurQJfcw5U3WcABDnDc+xVwFpNu9rTa0EhzdY5BXc9VyHI4lbyVFE5FVy7rOVUji/BpVT0JDNM5ZMjNT064fejQkIFj10czdY7xvpkK2XjfTG9lPG0zXbnx4zgzzzH+MS1wgAMc4Cj10dyA/dJR3oIfcDbhAGgBhkc4/XmE0wPOU3ugNV42GgAAAABJRU5ErkJggg==\" UUID=\"44672b8c-c9c1-434d-803a-fca1b30ec92b\"&gt;\n        &lt;layer&gt;b0785b21-2e95-4eb0-8e4d-73f9748013fe&lt;/layer&gt;\n    &lt;/tile&gt;\n    &lt;tile width=\"71\" height=\"96\" name=\"d10\" fname=\"\" image=\"iVBORw0KGgoAAAANSUhEUgAAAEcAAABgCAYAAABPGW+RAAAB6UlEQVR42u2d2w7CMAxD+f+fBvHCZWKFscRxm1NpEiDA26G0jtdpl8uzXdke21u70p7tFRA0BoAg8ROc++NPz7evt4ezBdMM0G9w9noVcIADHOC4wFFDTNDLgaOe2ZL04uGop/5EvVg4e74oC1CyXpwJHO1oBiCBXlz50AJO1o5GAhLpnYdzZEcjAAn1xnCOeJpWPeeoQJsx5x+hVrNVNKCMMqDM5/wreBbMmc/IHPJMBymrraJ+DfXfQ1KVqytr9UAu9zkt4TiAKQRUB0dddtBzZoGjLjuks5Uq042AI/U56kw3umSxhKM+SHltVelXzFIALzgVA3k6HDJkEzNnkyHTc8zGHOuYFDiGPsdQz8Mhm+rV11bGevVVubEeK9iBAxzgAAc4neEwlWMCKR8oPIksgEPATsBeq0fPmWrMWe6kXtTOLns6+KzvWHohQdVBLh2wt1q8VDWwLhews9TWxDzSc1aCU1GwHhivgDPQ8ciQqy4p+qLnkyE7XPy2+Q6vDFkJVQ5npgtgpXBmjEllY86sGXL6bDV7Epjmc8iQF+85U8SkKr2997WfrUbvtfc52Xqj3mLtkBV6pXASM90QvXI4SZluiJ4FHNcGHOAABzgVcOQmcFZA6eXDkgyB8xUOgAZguIXTzi2cbi2VWrO+c2pRAAAAAElFTkSuQmCC\" UUID=\"29e7d023-9cf2-4776-beef-5f390a6fbc59\"&gt;\n        &lt;layer&gt;b0785b21-2e95-4eb0-8e4d-73f9748013fe&lt;/layer&gt;\n    &lt;/tile&gt;\n    &lt;tile width=\"71\" height=\"96\" name=\"d11\" fname=\"\" image=\"iVBORw0KGgoAAAANSUhEUgAAAEcAAABgCAYAAABPGW+RAAAEYklEQVR42u2d4ZKDIAyEef+Xzs39uKqYbDYBAXt0plOvrVU/lpCE4JVyPGQ/P8/LQ/bjeJwBbRoA0CYRhvP7/vm54Ww4fLf6p2A2nA1nw9lwXgHnzWFBG5wahgGH/fHPvrVLkNjOXGDmvIfAMQFFtiNgnM/7wQEOYOYgtxO3bJnSODQYxz62wyE842z/leQzBAYA6gOH2yncvR4xpMVS+2Q4v2cQMc73C+b2NwEVcVT3JBwgzxY4x35vhUPZnBicO5Rj/7oLuSqL2K2+BlncFkBw7Pd0OAygy7Eyhr3PUO4bOATH6gKechDcdZRDHsTqFviCO8KZYnMCyqllj2zQd8AhbY6cgJxtRysc7Xeg8Z/i5wRGK8ZZiygH7aseZ4qHjA6ijDaeT5RRzvG5032HxVadPGQfSivc0VF5KMrmu5K1jXyQUqUsahuXa9AFlaN2CyX6vnQr5/No0m055cBIO5i2uNqh+ECwhHLOF+/FTIWEgmItBOmj1tnKUU/e6ArZnI7lRtT+1jLKcVuXuFgWiqWc2pbdwM1STgug2p/RXrVuqjug9266jHKkAZBnuDU4SD2lgiOj4ai2IABIsq/GiFWMeG+4cuptzsbogP5alnk17YwyIFx8qyWUIwMUZIQVnvGeohwzcR60QRk4xUmdzFeOMTKg4b5JQVWs5EOaoJzLARX1PGGDLDgI0hTlMH6F5xOlFASUg44xN7YCtufces02yIBj/d7c2IpUjoC5qpCC1G5lTxa+WjkabA+sO/n3NuWgCxIHkGfY9QZ5iXLcuIkEBPNCoLGWVQ6T7GIAof001ayjnGLPLFBRNgBkOnxvUk5xLuhmYwQD8oz3a5RjesfasEsqCCnmVcopxFDLwCmM7XqTcjx3nYUjEUBB5ZR5sw92XsX0ZsFrREGMn1O6VXa15JAFJ59Y5UQV5HnI/dY+JOetQsmnAJyogtBs6HSbw6Qwo2nRDCDbjZhkc8wUpcRsTg8bpNmZacqxupJ6ssnEegTQOsrJTra1TvIRgOZ7yETgqcGJTgdHAC03Vy6OenoWEkQALZHPsUYpZhRJV1sUZvheqLKrEJVYLcVLuPpi8couPBsqTWVv0cVq05TTtBAtUSypFV7GK1qHKSc6S6pUkwpfZgtLdpdSDv4CbEGrfs/vvgUm1ZZRDgRjLreuL0zcilAPCl39jr6Ll2t2gkOsR88sfo0uKAn5Of4CmA5wwkt7UJluHo6VOlGVwy3XbISTWhRmgZBmOFYAnFx09x1wLE9c7Vb8cs0GOOmFqM/AQd1yrHKaljB71RLMUC4huONtTqNyGEDZ5Y+Un/P4aBW0OREvm0mcN8F53M8ZBCe9EG26hxzwc1BA+sT9t8bnkBMespkXeuKGQ6xSfY/++djKPFnn/mDm++nMgPiDyeioHIJpvANcMxzj72fgRMFkthOAhsH5ipsoEncw+L930t5wNpwNZ8PZcBYC49yMaMPZcNIO64aD4GxAAMz+F07Gv3D6ATnnzGBMQ62TAAAAAElFTkSuQmCC\" UUID=\"a582dd25-9a24-46c2-ba98-1927e3e55ac5\"&gt;\n        &lt;layer&gt;b0785b21-2e95-4eb0-8e4d-73f9748013fe&lt;/layer&gt;\n    &lt;/tile&gt;\n    &lt;tile width=\"71\" height=\"96\" name=\"d12\" fname=\"\" image=\"iVBORw0KGgoAAAANSUhEUgAAAEcAAABgCAYAAABPGW+RAAAE8klEQVR42u2d227jMAxE+f8/rUVftrHDuVC2xbRVAKPobpPGxyNySMppxPdj7OP/cXiM/fh+vALaNAigTcKG8/X9+dhwAJg/CgjDyZS04Ww4G86Gs+F8FpyfXBYsgfP9VR/xYgcCvs54OYH6ibgnuwwOA/R2oic4/OskIPHz98EhJtCB4yjnqJZxkn8RjmFWr8MxyodIv68pJ4c8Cch08/fAEVfEgfMGKVEIeDM1QIHUvgKOiDkZHKaacOKCCydEGIgn4ZjylEE5WU4o1pzhUEBtcMj6ZXAqWQoGY0c9FEpY4WAyII/SFaABWSyn9LWUeipgXgDdkMp1gEOp3FWNC4eqp0U5N/gclKGw6ibgtMScgnLe3WweN1D6zmqez4ZTjDnpshKGz0nl1wE96XOK2UqCMZSTxSvL87Q45MIvseon8H9nFZZS+vLaqlj6KzDnZYez1hFAyS0vqcqLcJAvyZZLBunsZc5wLlXqnXBQ3YQAZSCQqmaK0CgazsfgMDAIEKvAVaBmcDLlOYbzOeUQHzPbx6X11tDxii3P5XDOV5Mtp0pjvtL8Yh0Bd7k9sqzCAOQsN/Yc6IOg4oLbg5VwzqUDA+B+VRlPBd3qc54JyCPkVXOyGFtyzCtpQPnvWpDKUc8mysGZBe1MnW4xG5P13X3LCiwxpCo3k+WwPRXy2m2hz8kaXMh3uA12BdhRSMQHpPI09iTmTZUOFIqlnKBzsJ5lhWKPWTaoYWAGJwD8MGbxLdkqXVYvDXE37qB2a5YI1NLtW1Yk4B5aF6A+UsuJwckCv7OU1lflWWGYKCd1uGK5MQX6MWz0pfIgGYspJ4PjxrL85wdVUKtyYJvzBuW8dwHm/FOrct4a5IWYk77WoS+cpHRRJqACtk05ClA2XcBDxJcD9XUmHXiLchCg/N+PJ6+OdGYOALX7nIqCUjCiOc+gO4DalFNVENvM5KZypZysxGgygQMaLtriDN3qUCYwgFVw1NMy1KuUBGPSBMqYY8aetUM9qiBs9wdZfqzMUMpxupRtqdzpyaDej1ucQgUKo9gGR7URVGOs2tbI/I5W0OJspXZLsG0mTvvBamucANFOQUdVHuLOGrcnU52ZycZYt89xfBAa3TpgWWBW2+/aUrnTQ8EbAny1ueMdNTJqiDnekM3dhzMzRra7lCt7yNlJzjznrvExGwS2NNj5VRtgejmmNhRUZ+utLYvKVhAGcHabiq2gXhOIR7feJgSvYzcDbXTAcca4chOCsATVrXNvgLp8jrPcnJkX2+qmygaqHOPGlGVwZgeCzj4c2P5AQfnCLQbPwikoZxA4akYPA76xW74HjnX/gb+FH508tAok+M7cxnAfHOMGDQRHbTNBgBAYexws3us9cMxbexicSrpVYNCWW/6en4AzdVMYU8+wUjwDw3ZhuBfzo+HAmDMGvbOGbdamISD/tJcLcKZvRJ2Dk4EZokmfv++nlXPpFmbtSxzD6aqmJ+ZMKMdJ6XyLf101fdmqGHOYekpNLWMo2O9zJuAotyx7SUI1Eo7xOWTLfU6lCFXpW825LDi6PbLOIVvLawz+IUSGaryArOPi0tqqCkjXT8ZHYrX5nGJVzuA4e2sqyrHgZBe2q59jtzLILL6iHFw+PAjnx3+I4lNwfsVjw9lwNpwNZ8P5MDh3m8BfDehq+fB32G04Es4GRMDsP+EE/oTTP8f50FzZgg2fAAAAAElFTkSuQmCC\" UUID=\"ad1b28a4-61a9-4451-9759-9565cd7b0626\"&gt;\n        &lt;layer&gt;b0785b21-2e95-4eb0-8e4d-73f9748013fe&lt;/layer&gt;\n    &lt;/tile&gt;\n    &lt;tile width=\"71\" height=\"96\" name=\"d13\" fname=\"\" image=\"iVBORw0KGgoAAAANSUhEUgAAAEcAAABgCAYAAABPGW+RAAAEsUlEQVR42u2djW7bMAyE9f4vzWEosDoyeTxSlGQvCmBsTZvU/kIdf+W29vuQc/w7Ph5yHr+PK6BDAwA6JFw4f/+9HtZzB86Bc19WPYQvhMLB+WIwGM6Xg/HhHG91LKdUc96cFkz3Vtmg8ed1n0f/nPYzzMGcUz0c5Tn3l4DvXy/+8xO9f83CasqH11vKuOWQQSD8JYRetf49tYOE1VSrvoOR7XDUi5SUZjGwNOvQoNXACWlH/6QBp0kaEITVbKt5FhwTjA2oOcuuXayU8T4amHpvRQhrJZxmWoBQgJDWfEhDibcihBUGjVBkbY/SFG/I/mt6oylwbpZgwImAuYUD/rKNwlG1xvj5ZJzjC+uo5XgnOQJnruZkLi6gOZFINgJnjbeKWk4Czs8hS6yn3pWzmlMY51SI8twIOeOtEhGy5WkYl84CukHfFucEc6tIMpgFpOVy+9IHMiuPRMiZZfYoOINu0oX2WstBYT6TM3nv/WrL0S4WexFfZ0aE+TFwGDAtUj0srFE/Ag7z6fXFqQwMr+qnxTVzCuwDmuNdcF/NYyzAAuTBs16z3FtBIBeTVgvp3fd1MKgwj5PO/jXL45zrhd6WkXLx1+8hQBXa8wtINnkrs75rL5EeiijLJNO7mtvUiwiyAeVTgPESur9uvNi1X5ABFK2D2YBVjY7doWVc19RLwEFQvI4myqajXQcP0HI4DBQNhvZ1RGu092ld8w95wUVBIIaiibDesWT1wgLcQYGecom3QkvISjW4wBB5PkuAWUBL4TCfEGM9aLgAWU00Al8GxwvkonCY5eS57ZvV9Oe5XHMcQEhrvHGUqNU8B04CkAZnxGrEgPCIINCCxMcrzakKJkZVwAe2PEJuRnJppxR2j8mDA7XGAbS8EqidZAaOZ1nNSWZZa14fIRv/94I4ZjbQ0ykW0KPgMMIa1SVvHtAC5C3fZcuKtRrPjUfhQECyAY4gCxJSiAEUNhLGAwqb4LCAmCAOdRyiwowS4+XLygJkgcmUPCOph1ri2NW3ama4PyLC8XjHAiy74PiAxsqfsCgvHBR5ShAYmer0BhK4grxdyJdd9RxWULPtFWm4KI9aPeJ0NRY19fgx/Oxeh4Y6FhY4Z4xuaT2Hbc3itq24rWSmD4Y6DhsGCfwmvtfzHk0n0OjJlmWV2cXiwWOLUyiFQE5gQ+I5d/AoMumRHcdbBoeZ4/HmhyNDU8zvWu+tiAuJDAFkBykZjXktHMbdjozy7vFWEyyHeT/nxGideqXlpK0muN+CgVoCZ/bGDhdiYMt2BGqZ5aCZm8wy06t62slIfkcysXWqFM5oRo6No9/9K6FdyZlNd1PhVALiL5CBw23XLEkf1lhP4cbbqZYj41uYYztfJAcG3YNjmuZcz9hJA6pE2fVQmS3bU7yVASdaWGdzrdim28DG3RlxTlRz+A0ggQCuCs7sCNn1VkR3M1XOGIlzdsOBt51KwCqJkAM3UVoQIeu3lfJghfpOkdxqNhx+0zwzjR69wVlBVk7euK1+X7lIunfF3Bpv7FZ8NoxpEfJrb6IIbhp57qRtadCBgwX9wDmWQ4A5miPzvdV/uYyqgsAD5zwOHAbOAQTAnD/hZPwJpz8dNIyuYVpuggAAAABJRU5ErkJggg==\" UUID=\"6e1a2bea-c6fd-4ec0-a800-8d65fd038674\"&gt;\n        &lt;layer&gt;b0785b21-2e95-4eb0-8e4d-73f9748013fe&lt;/layer&gt;\n    &lt;/tile&gt;\n    &lt;tile width=\"71\" height=\"96\" name=\"h1\" fname=\"\" image=\"iVBORw0KGgoAAAANSUhEUgAAAEcAAABgCAYAAABPGW+RAAABVUlEQVR42u3dwW7CMBAEUP7/p1P1QIEKbBOoMmWeJV/IBT0FZ2dXIqfTZW32z75Zm3VZ10A0BkAkduOU4sF5Cef72nnDgbOGc41SCARnF849jDKgOc69XY0zgikCGuPMzqE6nNEdUnb3wBE84cDJepQX56u1A1kRqACEA+eobOVRvtXDzOucYpi1IrC4QFQhw4EDBw4cOHDgwLHgwIHz4TjBE9ZjcUbdxoBO5HE4s1ZsQKs2EyekwQ8HDpySp1XI3AzOvyoCg6atGfEhdD6fk60C5/NZwTNsPp+XyoPm85kti5Dvo58DBw4cOHDgwIEDx4IDB86fhtxunEl7pBdnobHWibPYku3DeaKZDwcOnH04jz5zII//VEARqEKGA+etB/HkGhw4vxAWr3XiyFavhc5unIWfW3eFPDmH4MBZyFdw4DwHJD7AETyPwAE0gPEKpwevcPoCv0IwQOUmIdwAAAAASUVORK5CYII=\" UUID=\"2cc80226-f795-45e4-8c85-4f9acf7a1fb1\"&gt;\n        &lt;layer&gt;06be52cc-1d25-46cf-815f-2f47f0d4ae26&lt;/layer&gt;\n    &lt;/tile&gt;\n    &lt;tile width=\"71\" height=\"96\" name=\"h2\" fname=\"\" image=\"iVBORw0KGgoAAAANSUhEUgAAAEcAAABgCAYAAABPGW+RAAABdklEQVR42u3d3Y7CIBAGUN//pd3szeqa8NNEmQ85JNy0F9STBoYxQ2+3R7vrf/1fu2uP9gxEowNE4hLO77XXDqcBcyBQH2d0zZwDZw4GDpg5nBUwvQm/eDGYW8pXwTyPF7BajpfyT03Io3AhIJyoW8p7P37Uvz4IhPONOGtGhvN2oGNSFlvi9JbVSqDyIHAm5qgAitg+VD1oYA4pB6c1dtTGs/oVD8oCZKZJQ9IjEuzR+ZztM4GHNn/qwYEDBw4cOHDgwNHgwIEDBw4cOHDgwIEDBw4cOHDgwIEDR4MDBw4cOHDgwIEDBw4cONcF4DRhOuUL5+JMFL5k4qys6eoA5eFUlku+jJuFs6LGa0ucVdWB2+GsrCu9UBpej1NRdD95qIDjGmIjZDhvhHF+zgKc+CAQTjjO4FomzqeDwtYxf1ss5aN7i/ZyeUHg7D35nNrd/5k4k2/j2TjR24cknC0ygUG5IxPydgn2GD84QxxAHRifcGp8wukHtX0FXbBvhWsAAAAASUVORK5CYII=\" UUID=\"879ae6f3-950e-44a0-82c5-4752e957c1b7\"&gt;\n        &lt;layer&gt;06be52cc-1d25-46cf-815f-2f47f0d4ae26&lt;/layer&gt;\n    &lt;/tile&gt;\n    &lt;tile width=\"71\" height=\"96\" name=\"h3\" fname=\"\" image=\"iVBORw0KGgoAAAANSUhEUgAAAEcAAABgCAYAAABPGW+RAAABjElEQVR42u3d0Q6CMAyFYd7/pWe8EblYV5Stp+u/hAs1QfKhrByqHMc5GstnuYzGOMc3EBoGEBJunPfj3gIOOGOc3mOOObVhxjiFYWyc4seb+zgzgKz1B+8cf50zYwOtHSAwW8bhjMoFgXLCN5Wvxhkt2xeBaXFWzFapcea/MziPA5WJLFLiWNNqJFB4EeipOSKAJE4fojZUMEPSwRE82dXCmX18S1Mhj4DIc3ZIAolJtT/imjiFBzjggAMOOOCAAw444DDAAWcHnC1aUFbApG1BWQUj34ISjUMjATjggKMCVH4qB+cHoJKnD2laUBSBOPFsCVpQlICILDpARBbkOeCAAw4DHHDAAQcccMABZxMBcLowRjxSF8cRrNXMc5yRbL0k8EaYXy9DTomz6upDOpyV161u/DS85hVP558KcK1ctkIG50EYmpcW4UhXyJE48hWyAs7guZp9yM711OxgT4FjVKfD12btFPKcBs6/XzFiUjJkB0yKJFAoOwIHnIyRRRIcgAwYbuHUuYXTCwCvznfeB53yAAAAAElFTkSuQmCC\" UUID=\"d110f5d3-a456-4a14-a48a-33d03703e205\"&gt;\n        &lt;layer&gt;06be52cc-1d25-46cf-815f-2f47f0d4ae26&lt;/layer&gt;\n    &lt;/tile&gt;\n    &lt;tile width=\"71\" height=\"96\" name=\"h4\" fname=\"\" image=\"iVBORw0KGgoAAAANSUhEUgAAAEcAAABgCAYAAABPGW+RAAABlElEQVR42u3dwW7DIAwA0P7/T3faYet2iAOpDaQ8pJwa1eipRMaVyePxGk/X7/VvPI3X+AtEIwAicRnn+/MNAc9xfmDgBDBwAhg4B0sJTvCMgRMsp5blFd2TuTxHxUnDie7rAe6FqYqTluecIfb+AnthsuMMw7myPK/gZMa5nAT2LCk4u+OsMulb4lyd+Mpx4GRvH3qeTUUTHhanKQnsyTwHTHhknLztQ2uylrfxKY+TjzOy3FEcpwZnZAWxMM75A/nd3GRMbUElcN0a8oajbW+16fCnHhw4cODAgQMHDhwDDhw4cODAgQMHDhw4cODAgQMHDhw4cAw4cODAgQMHDhw4cODAgdMvAOcQJmhf2BenofGlFmfVlqLGlqk6nFWb0Tqa7WpwVm5jnIqzegPsNJw7tE53tIbn4dyp6b7xUAHHNZRnyHASJ+z8nIVxGucBB07wfdOWVWZSmB1nCE40sbPPZsSZkiHf5fjN6RvPO9Vzgt09nPLtg0rgh+OoIfdVEOGU5zkf6wfnFAdQAOMVTgevcPoCrlKTpJyZzuMAAAAASUVORK5CYII=\" UUID=\"956d7658-3fc6-4422-84ae-2c0027e416e2\"&gt;\n        &lt;layer&gt;06be52cc-1d25-46cf-815f-2f47f0d4ae26&lt;/layer&gt;\n    &lt;/tile&gt;\n    &lt;tile width=\"71\" height=\"96\" name=\"h5\" fname=\"\" image=\"iVBORw0KGgoAAAANSUhEUgAAAEcAAABgCAYAAABPGW+RAAABw0lEQVR42u3d3Q7CIAyGYe//pjWe+JM4Wrb2o9iXZAfqQcnjwNKNebu9253jdXy1O+3dPoHQGAAh4cZ5vj46wAHHxmFYgRMzrMBhzpn/KbdwRoiRwKo4YTijsyzyDFTFmZ6Qj4JZQzBqiKriyHCsIwonMk7ohNwO56gzKztdCqdap7fEOdvxynHAiZiQf72+2nHVFxGeBHpyiCsdj8nrJXFsnNnAqnWZIE48zkwakAGUuvCMOmVVK/nEOLklC1WJIynO9Qy5bT2nMYwvCWxcS+aiHjjggAMOOOCAAw44NHDAAeePcYS3k+yFI76dZB+cBbeT/AeO4roXOOCA0wvnLFD7n3JwTgC1XD4Uhamztiq6naDOwrPgtflaq/Ji1+brlSwK9YV6DjjggAMOOOCAAw44NHDAASd1odsbxyiR9MVxFNdycapuKXKWZfNwqm5Gmyjo5+BU3sa4FKf6BthlODtsnZ7YGh6Hs9Ome+dDBXhcQ3qGDE5gh3l+TnEcSYa8I44sQ94Zx3gvFycyKYyMI8MZdcz6bFUcZx/ykkDvZyviyHF2r+VISxa7AoHjG2rggMOcA47WEBwTB6ABDH/hdPAXTg8nXljRpaVtlwAAAABJRU5ErkJggg==\" UUID=\"1be5f51f-7a2a-4d0b-8100-ad3343f796f5\"&gt;\n        &lt;layer&gt;06be52cc-1d25-46cf-815f-2f47f0d4ae26&lt;/layer&gt;\n    &lt;/tile&gt;\n    &lt;tile width=\"71\" height=\"96\" name=\"h6\" fname=\"\" image=\"iVBORw0KGgoAAAANSUhEUgAAAEcAAABgCAYAAABPGW+RAAABwklEQVR42u3dwY7CMAyEYd7/pYv2AqxE44SOJ0n9R+oFDrY+NWwyDcvj8R4H1+v6Nw7Ge3wCodEAQmIY5+/1zwucExhwvsAwrU5w+MwJ7hymVSdOMaD+aRXhtBCVwK46MpzWXaa8A111ZDjRFFRNUVcdG050qXCUdaQfyOVwRlbIJXFWa3pLnF8bX7kOOKqNZ08xU8O2Ol9xetYQVxrXrOstdWKc0cKufZmhjh7HGZQl18nBcQZmiXVyIwtXxJFUhwz553VO8Sw5XgQWzpJ5qAcOOOCAAw444IADDgMccMDZBKfMEZSrDd/6CIqi4dseQVE1zUECcMABx/nXiiMo4Ggb36GOfPtw+yMomY1rNz4TjqBkNZ6zMzQfQcloPHfrbD6Comzcky2Q5xB2gQMOOOCAwwAHHHDAAQecZQXAOYVpxB11cTqCspp5TmfEWi8JHAjn62XIU3FWf/owDWeH51YDXw2v+cSz858K8Kw8fYUMjrBhDi8tjmNZIe+IY1sh74wTvFbzHLINp9VY9N6sOlacxiozfG9GHTvO7lkOOJ1TlJj0YFpdCcyYVtMy5J1w0nblt/UDJ8QBqAHDTzid/ITTE5cWIforoVuGAAAAAElFTkSuQmCC\" UUID=\"1fbbdf52-331a-47f7-8d1e-e84398cefda8\"&gt;\n        &lt;layer&gt;06be52cc-1d25-46cf-815f-2f47f0d4ae26&lt;/layer&gt;\n    &lt;/tile&gt;\n    &lt;tile width=\"71\" height=\"96\" name=\"h7\" fname=\"\" image=\"iVBORw0KGgoAAAANSUhEUgAAAEcAAABgCAYAAABPGW+RAAAB0klEQVR42u3d0W6DMAyF4b7/SzPtZl2lQZJhn/jgPxIXraY5+qZBcjDt6/UeB8fP8TEOxnv8BkLjAgiJaZzv12cHOOCMcUbvcc7pCQPObZymMLE4VyfuyJO6qk4YztWVLfKqp6ozhXMHZjTp1Ymr6shwRkcUTmQdcMBJxqk0aUuc/068ch1wInblf72+O3HVHyJ8ETizhrgz8Zh1vaTOGGe1sCoLEtSJxzn7HTk7w9Q6OTiz56loIKuYVBV1JNU5v5Qr/jWE8UPe9kEBkxw/5OU5KpjE+GHfCrnqfgwccMABZ9MOG5zH4IjjBz8cZcxhiVNo0VcTRxlzWOIoYw5LHGXMYYlzHA/EadmCUimbKdWCUimbKdeCUmkTSSMBOOCAo44faEF5Go4ym9naguKQzWxrQXHJZra0oDhlM/IWFLdsRt6C4pbNyFtQGOCAAw444IADDjjggMMAB5yATWtvnEHc0RdnIijrmedMRqz9ksCFcL5fhrwVp/rdh204DvetFh4N73nHc/JDBbhXnr5CBidwwjQvmeCkbh/AASdnMVa9Dzl9V+7awT74md7PPshwnDMdcNZgwAFnEkaaBLrlx+CAE2gIzhAHoAsYvsLp5CucvgBHwDbXJzzzzwAAAABJRU5ErkJggg==\" UUID=\"53fe97cb-710f-4630-9c1c-8cdc03c77212\"&gt;\n        &lt;layer&gt;06be52cc-1d25-46cf-815f-2f47f0d4ae26&lt;/layer&gt;\n    &lt;/tile&gt;\n    &lt;tile width=\"71\" height=\"96\" name=\"h8\" fname=\"\" image=\"iVBORw0KGgoAAAANSUhEUgAAAEcAAABgCAYAAABPGW+RAAABzElEQVR42u2dwW4CMQwF+f+fpuqllKrECTy/OOuJlAMbJFsDeJ1ZYG+3x7gzf+bTuDMe4zcgaAwAQWIJzvexvxM4L8A0BDSGEx0DDnCAQ0HeVZBHz1NCdsWRfaxGIJVnPVccGZzoXaZqC1xxbHCiqYKjjCOtOe3grJytWsKplvSRcN5NvHIc4CgK8n+PP03c9ULIm8CZHuKTxDV9vSVODGc1sMsFGeLo4Tg3rclxcuDM1ik1oKM0qUtzJMXB57zd5zQGM9cENr6mxUU94ACnMJw2gl3VykdrVeNYZJe6oSwh2DGBwAEOcBDsCPbrwVlN/IQ48u3D5QV7ZuJZetQm2LMSz9KjVsGekXju1tks2JWJe9wCPgfZBRzgAIeCzKmcJpDtAxvPahtPlAWyCzgyOAh24AAHOFXgKJu1I79IMEosWqsaJ70JnF2rGgefAxzgAMdsEXvDCYp3XzgTp/2egn2yYewn2Be2G/0E+1Y41QX7NjgnCPaFn4b3FOyTfyqAQ96mLBDsmMDrwbF0yCfCsXXIJ8MJjvUU7DY4o8SitV1xrHAGXWa4tiPO9l05PudwMLaPFXCA07PeAIeCLOQHnBAOgAZguIXTi1s4fQEyvKBRH1NBJQAAAABJRU5ErkJggg==\" UUID=\"298a41cf-2be4-422a-9b59-f1aadc41f48e\"&gt;\n        &lt;layer&gt;06be52cc-1d25-46cf-815f-2f47f0d4ae26&lt;/layer&gt;\n    &lt;/tile&gt;\n    &lt;tile width=\"71\" height=\"96\" name=\"h9\" fname=\"\" image=\"iVBORw0KGgoAAAANSUhEUgAAAEcAAABgCAYAAABPGW+RAAAB+0lEQVR42u2d207DQAwF8/8/HdSXFpCyl9Q+tuOJlJc06LgD7HonCz2Oz3Fyvs8/x8nxOX4DgsYAECS24Lyu/T+BcwGmIaAxnNk14AAHOMCJGpBH91kO6qqc7an8KnB0r+Wsp8rZbgKvwmY/ZVZtgSpnG84oaFTU7LSCY5lj2iED54gvOhWcbEWXhHO38Mw5wLFoAmez1Z3CVd8I8yZwpYf4pnCbvl6SM4ezG6xyQYIcezhKi+ic4wNndZyyBlRKk6oUh1MOgv12n9MYzFoT2PiZFg/1gAOcxHBaCXaLVn72WtYcieyybihTCnZMIHCAAxwEO4K9PpzdwivkmC8fHi/YPQv30qMywe5VuMc6SS7YPQB5rpPkgt0SkGKdJBfsvqJE3tABBzjAaQDHervcnZxHTeV3ZqpSU7nHTtRHNIEWb/Dbr0sJR/VGyy08Vb8i5ZSFanBtbwJV0z+CnacPwAFOKziWzVrJjQSWyjNLjnsTuCvLs+WcbHsDDnCAo7WVveFMBu++cBam/TjBHpmz2DDGCfaonI3lRqxgj8gJhZN9f04YnAo7uzb+NLznnsDFfyrAbtIwZdEeDibwoXDcO+SqcCTLh4pwFmvoKdgX83sK9sV7ewr28FV5BZczuQYc4AAHOEoXhGAPE+zl+QFnCgdAAzB8hNPFRzj9AJX3fWZtiy2wAAAAAElFTkSuQmCC\" UUID=\"db19c7f8-44d0-4e03-a848-747a3a31da9c\"&gt;\n        &lt;layer&gt;06be52cc-1d25-46cf-815f-2f47f0d4ae26&lt;/layer&gt;\n    &lt;/tile&gt;\n    &lt;tile width=\"71\" height=\"96\" name=\"h10\" fname=\"\" image=\"iVBORw0KGgoAAAANSUhEUgAAAEcAAABgCAYAAABPGW+RAAACDElEQVR42u2d247CMAxE+f+fZrUvy4LIrXbGTn0iVeKm2hxCMp4m8Hi82pPj73hrT9qr/QcEjQ4gSEzB+b397f7n4+XhfIIpBmgOTqtXAQc4wAFOFJzeoO05oKviuMHpzWqeM54qjhucVlKjpFcTV8WRwRkdXnA847iKwLJwZga5UnC8BkngGBLPHAc4V+H0pkmPxFUfxDYR2Ju1LIl7qF0BmDk4q4GvgvGUENtrK0tw6xuzAJYUntZPRqWNNjqU4wHZqk0UmmWTjdKeynd22QBB569zdiV1Czgbu2x2MH4KGTjBgFJ4yBkBpTHYI4zvq7pGbrBHGd9XXyM12D2/FpZekdJgj9YsKlWNTQoc4GCwY7BXg1PGYD+hFAgz2HcmrqrJUheequJRbrDvSFxV1R9lWajsBrnBTgMOcIBzGhwGZKZyRCDlA4UnlkX+61aYXcDxTZirD8ABjjTpMpeDV8Xa7RYS9BIbPbdaChy3BKWV+Oxzlt51xOKlE0qO4+CwYDKH2gWOs4sYAyfL8v7BeevCmTh3jMEevaVo8vwxBnvkZrSFGDEGe+Q2xlA42TfAhsE5Yev0wtbwmgb75I8K4CFjsGOT4iG7a6PODyvVgzMjIcrD+XZfCsfT+PZW1RI4SuPb08iXwVEa39Y4IXBOacABDnCAk8G/Bo66fLg1Q+AM4QCoA4a/cGr8hdMPbXLy1LxJTPYAAAAASUVORK5CYII=\" UUID=\"934f6d8b-bbbe-43b1-a28d-913c5c80fef9\"&gt;\n        &lt;layer&gt;06be52cc-1d25-46cf-815f-2f47f0d4ae26&lt;/layer&gt;\n    &lt;/tile&gt;\n    &lt;tile width=\"71\" height=\"96\" name=\"h11\" fname=\"\" image=\"iVBORw0KGgoAAAANSUhEUgAAAEcAAABgCAYAAABPGW+RAAAEgUlEQVR42u2d23LDIAxE9f8/TacPTWOs1a4AA2nJjCfTtI7Nse4gavb7Kud4HZdXOa/f1zugQyMAdEik4Xx//n4cOAeOrlb/FMyBc+AcOAfOR8D55LSgD04NA8BRv/xyvvdzfY3gb3uD1Wlw3s+JngwEpMLxwFzir/qCBcZm4+AEAeDPgGtA33cmAXq/lqfG1c8X8O79ATDVNfvhCJFxBMcDZAi4cHAwQG2d34+BI9qSDJwhhrQD8lQ43s1T6Xl9jt6JEV0OJ9Lj+obr98D2ZODcge8AR9FjAgd5MwWMB+UKpxVQeQAOeQLeAJAktKiU69DSgEa58gScjM3pgdMvPcPgFF08s668A0677XkqQmbB1INwrtJY/OhblPKxcEp5JkJOGGRTo9oEmLFxTiJCRrnV9fNWg2xsBHKte2wQGD0BUwZ1VbUMnFSZQUw0l6UPCEwEZIjkOA/y9d2uN90EjgqJqXC2aGVO8rqt5CBIRjJx7zzkEfXkeDEcz+aoYIr71DVVvEnXznCwSuiQ6nPiWGpzybkM+FLixAeD6NkvZdC2i0GGA7xl3O1HXfhCQaMJCfIUOAaK3wySCiqqBhoBtF5yUFRKIBW1PKpAIfbFlpdJOyDRdwJFjYvmSQ4S/QZITHIyDyICMh0OzKESkIpZ6Iqz3xmXayfBkdytOqD6aTdB8T3VUptzA9WoCsVLGEUoUVoxbiFBw4Q8AiOrG7AxFGbBkbOBevc0yYlsRBS3MECG5tXFaHsbyTEQ3KVimAoQAxelG1tKDiuyhzWX6AkLSa5Sw54Ox89dcNHcnLpzIa68gPPQnNk2ksNnGvzClwsJQMeD9K+zleQg6YngwAwalDb9c2I4W0jOp8ApR60AyMS083TJmWmQ3US4LIKTcakzXPktGgcqvVxyVgWBCMw2krMifWBgtpGc+MZ5Zs4AhYltMKuxleTMKFlwVZpskONpkHXFLgRmOpwwSFtYJkVl3D1KFgsL7IV5sdlqFRo9NsDEFE0vpOlwoDQloGQn91oglR0kB7r7YC1z67Qwg8Ts2hTJYRn0zAUFcEXqSsnRvRpe8cWWocBo+zYrEcztT/dWJi4mYpGzsHippbl1Czhqth7NtZsASVnptbXkKGkFq/kyMGp6sM4gBwUrZdZCWVcYLdWVu/1WGeSCilQNU8tx8UyBtJFauQNM7LnDDWq8+n2IzYkXXPbBgWAEQMpaZtYiEDekEDh89fwgOMkWHxQL+cV6vaHE7RRUe7YegZNsDlOMc0sTG2yjDLd8wE13/XAyfZeiIX4UTqJdsw/Ogw2p2V50dRFDstF3DZwRBpnaGq/EMgVOZxM8y+xbdzG4uWgGB3zWCadv+wRW7mixN24gGm794GjAEIM8EM4TxnhpmXTExhsj9+BKufKlcITfZzr2cBdfJ5xHg8DGbaLCKV+W+5BmuK4IeXwQmN9gzAZscsa6BSVvFmzeNj7xVM8ftD1expZMg/MnNlEUkuL/u5P2gXPgHDgHzoGzERiyU9OBc+C0BasHDoFzAAVgzr9wAv/C6QtRQHHXUh7xYwAAAABJRU5ErkJggg==\" UUID=\"7c588781-b5d9-493c-86dc-6b383cc33098\"&gt;\n        &lt;layer&gt;06be52cc-1d25-46cf-815f-2f47f0d4ae26&lt;/layer&gt;\n    &lt;/tile&gt;\n    &lt;tile width=\"71\" height=\"96\" name=\"h12\" fname=\"\" image=\"iVBORw0KGgoAAAANSUhEUgAAAEcAAABgCAYAAABPGW+RAAAFC0lEQVR42u2djW7bMAyE+f4vzWEY1jg273iUZMlpFCAYgq5w9PnEf7lmr5fv98/77eX79XodAW0aBNAmIcP5+/n83nAAmC8FhOFEStpwNpwNZ8PZcJ4F55PTgilwGi7y9rsGYP+7zvU9IlB9HBwG5vjvGY4ZAfMWf50v6DA2GweHBIHqRSJJR/LOlJN/PwBmjOJr6UMFznFxRr4oUk7pxiU/HwMHgSrAeSkEG8NQUSf1yHCy9y1wGm3Oj80QvMRl+30UnKLVP6rGgTulnxGg5XCYkSvA+Q/Gi2AiQC84rYBGGGTFyCUXOavGgXdCajwDujoLbwIzHk6DPM9gojhFhRNe55vhaIDqYAbA8e69m8Fhi6Y2qAXQbelDQ6QZgankRZYktyVAt+RWHREyUg3zVCia7gJ0W+JJIuMqnHOUzFIHpDKp9CA2AcYGgUV5XqNiDAiByRJTCEmO2hdFyFcI54VEizP4/8oKejqc14I9BBKVIxCYDJCUyD4BznVxRxugljDx72hxEi+ULYFjsEBl1K6cf88KMFNP+QTlIJsSKchYlY8C1NX7ut5i5RgohscKCkBZbH8im4HqzrEtim3XNDjIkDIvVDHIbEF22Trc69n8Ypemmjzi5QuCdWZqs1zyflOUo7pk5qXYnY6gZEaaba/lyuE2Abv/0NYIauHQfb5yokVZknCi8gRTzQVM4K4t+LzQlSteysMvz9SDVBOWQ8gNWAqHb4lYOaiuzGxUphqlD/9I5URbJwKE7FGPapbCybwUsilHQMzjZKpR4CI7t1Q5DI6Fdx6AjuAA5cGczxbFOZcFUy8VuOIkCTWgHLVJGNmnZcoxaijxQtUiGAoGYTvZeJY+NULmcrfQMIf2CCjSQZs48m7+FOUwCWcG+VLaQJ0LksUzOFkN+zY4SMaxLYhduRmH8wbfeR6mphpzDHKyt1EA6MCuRHWgCEwlaBw7TaoqJ9nblYw6Lbaf1WQ46XRQN1qqnJbBJLM43gntjcdw2BZWakT3lklJghcaSg9UIKjJjS/YiGKmKycL0zMvgtw/rM2oBllIaabCwTWa6whtFU6ovAbVLFNO1iEwUTVR0Bg6Ace2Ji/ELWjqjVYNK9DTcOFJyglrKczeCKrJ2irMSymF+8nbCtdmlFSjWnCnmf9TlNM0dATiIqVwz8uiJraMJsMxUBOO1JKPj+QLRGp7nHKyGRxL6ilqnJK1kKtQJyknGzHRT+pBJVg8jREOKghtoukG+ZIWCCMjbEKiMraitIbWDi8Zn1pnRhqNyynb6DjslNmYpcqxZDCbHl/0qxpUmC7GNI+KkPn2yb2fYpDRuJzyvafAqRbkswl2tQjGplefDUc8pM+3GR+ODCuGLXC4sxgMh5yZaBk6UtIWb4WTHGMYC0c82kN75J6pynHnogJHOAAzDk7x7BMHVOyfVeGIR6fGwGk8HMYSSqacsOWT5E8th+764VTOXYouXo2T2uDoxzX74HQcSM1qNF8Px5IRNjltEap9LUfE2+EMOQSfdUOLTUL5pmoPF+iAM+LxCX1PL/BCjXhuhNwJJwJUKU5ZQTVQOZ8Ex4WHEWUtnNq2sgVwCoHWeYApc+2s+VcLQe6OkLsfExWXRFlimpVA2r/3HRFy1wPGcuVkD0LruqnROmbWc9K8SFBOL5ipcD7+IYp3wfkVrw1nw9lwNpwN52FwRgeBvxpQb/rwPew2nBTOBkTA7D/hBP6E0x+pfPNHIRXstAAAAABJRU5ErkJggg==\" UUID=\"0d75364f-a431-41dc-9a23-75b0e200ffce\"&gt;\n        &lt;layer&gt;06be52cc-1d25-46cf-815f-2f47f0d4ae26&lt;/layer&gt;\n    &lt;/tile&gt;\n    &lt;tile width=\"71\" height=\"96\" name=\"h13\" fname=\"\" image=\"iVBORw0KGgoAAAANSUhEUgAAAEcAAABgCAYAAABPGW+RAAAFDklEQVR42u2di5KbMAxF/f8/7c62013Aug8ZYycbZ4ZJkzQBDpKsJ1vKz6Pu7Xs7Pep+/DyOgDYNAmiTkHC+no8bem/D2XBatbpC+EAoHpwPBsPhfDgYDWevVltyhtqcdw4LHl+t7jqN/75fvp//b9nX7WfOfkfCCd4r6PO/23UPsR07X83S/doFcx+O6QRSG3UEVMDnFwnKbMfvXFVFqc5cOCEY8l0EyNmEKl2hPaNWGfF0T0zAsQxpsDE4kRS9JRzzII2ViKvZOIMc2Y2FcNhzuwLG7022Ob2AsESo96/PR6m5qtSzcMAVP0ta7QbTniB+nYUTSeZbwlFGU6kVW6kGwqmpE+sCVMfDUUb7AYOcNKIJMKPghP+Wy/3dpdw8sRQgEwzych3VUtIzzs8haQu6EwGGwXHjIgSmiuexTmCvG27kg9AqxE6CSg/ZyiNw7gRwRGUyhjJjjOsUmzMw9L/GRwhMEXbJMeDRvo6S/BJwVABZDEhK1ZihjQLW5WoFr1wg+pEHrJZrxyZFF2CpzQlPkF1tomI4bECBZbBPkEGcCocGhkDsEaA2/VmbuAkFkeWQECvG7z4O53TQHYBa6YnzwyqJrsD05JoHSE7sSyjV4uqFwaCrfzwWpVLz4NCrVFPSE6mBU35BYMol77wEDluqI4jI5a9JMKHqgmNiUve4zUFJcAaISY9SJ9e4l6ByscbmAEgo9oEBI5KYhFsAQ4m6wOacTkakC5CPkzHCCkpzbEtWqxJfYZzoHtOEUJUHTAqCc9Wqeo6XXC0SOWir8FdbVZ3sIWOpuda1UTKtt4UkKzEvAacQjzdtywwn0pGYNX7OXclhuWPDP2qcPSEx62IrwyD3qor6P8wdYCmUx+Gg4DDTetazjMf+lAazJHzAK5MXH5USOXwsCaYbnJhTuizw9DqzSIeEyMEoKYN5nOk2R4DhEPNq5TqRVMVWROVqaVchRcZQSyjEOE81yCWIryK/g5Zogy4O52RQyy4DtGy1ivwOZ7VyHD8HjrO0L/FzsnFQV8D5TpKTlRgaBxndGby0/EKS0yMxoyRK2j4g2VPh2DZGFvF0alQlygpIrl+PbUlppiagtJUJnh510q2wirEkTVq5xFSjq0KBcRLzDNxLVDxpLFN4yEBVCkmPAKRKRvP9nOhAiijGVR1NsyYk1s2xNPCEtWgDjDbCfn+N0+6yxObIpBPtDOVgECAlPY3avVLFE4FB+RhUv8oad5VSZU1XjweeBRhhZohRo5JTxLNVizRdTbM5TjqSXUlaC4c9PSyFgpuupiW7atGTcSppFcFRXaI9PX8LauXYv4gOKNtCi1SsJ7s3vWGyiLJtFgrbD5WSKXPlWSdQ1LUzQJiq2fMWPXD48dxLsKtBDDUK5F5xe5QpA0cMsAxptc3MZaIDdQy73Z3hwDFGn4bbHDVjqQDdBuOMQvkz7/fguOODw+Ak50mb306Ma96XHBA39aoWhdM5cHv+DX/QdxgcludBcDIj1G8FBw9f5OC4Q/cjhvxDOOC9YXDiWlK/A5g2oul5eO+2FEMMspPr6ZlFeAzOjPABpU0zIYYN8B3hsJWK5ozN1lrbN3HhzLA5PEtISsddt6JigCo32LW+BhyWa75z4zIM6LrT6t1Jwbxx2yNw9HhQ/vWYW/BhGMPg/JqbKJKbRu47aSMbtOHwvM6GsyXHALNtTn1+tfqVajTKCdxw9mPDceBsQATM/hNO4E84/QG9hpOZto9YbQAAAABJRU5ErkJggg==\" UUID=\"a3397bc9-187c-461a-b336-7059f6b8eadc\"&gt;\n        &lt;layer&gt;06be52cc-1d25-46cf-815f-2f47f0d4ae26&lt;/layer&gt;\n    &lt;/tile&gt;\n    &lt;tile width=\"71\" height=\"96\" name=\"s1\" fname=\"\" image=\"iVBORw0KGgoAAAANSUhEUgAAAEcAAABgCAYAAABPGW+RAAACAElEQVR42u3d24rDMAxF0f7/T6dv03RIHFmWreNqBwKFdgxZo+jiBvp6fY6D8+/8Og6Oz3EGQqMBhIQHpzIcOF6cc/YGBxwbzhmlKhA4vThXGBWBmjhXZ2kcy9xRHqdVvUritCKkYvSAw+AJDjhM5QyePzBbVQZifGB8AKcGjso/4HE/Z/WGl1KESpVytVtYBkcxx0mMD1cYCkDpOHcwCkCpOE8Rkw2UhmO5lbKBUnCsMNlAy3GsF64AtBSnB0EBaBmOJzqygZbg9MLcvV4NNB3HC6MANBVnJGIUgKbhROSY7Bw0Bcdbmp+q1WqgcJyeBq8HwLOWNI5lZ/Hub6LWksHx9C0WEGskRUfPNBzLBUW9nhU9qTgjkbMVjjW8I3NOz5qyOFFVyZt7tsOxVB9vn7M1zkj18XbWW+Qcazm3lPGfyDneRjByvS1xrJ8dWVMKx9vuR3w+skue2gQ+5YuRccC6ruxsZfkO3nJhEetKbln0Pu/TU+FmP0e0ZLPLAzMKtN0ectRtsepxFZkn2Hk+B5w5Oaokzuoku+VtpXiAAw44IbMgOP8AiJyLiLnabSyN09MygAMOOOFzXNlqZRlP6HPoc+hzGB/AASe3OlneAwec43a4bL1XEocOeXB0KI1jud3Y7GJ8ACd06AQHHN9EDg44DJ5TcQBqwPATTjc/4fQGfFZGq3GbXZcAAAAASUVORK5CYII=\" UUID=\"a4e9de58-b1c8-4a46-8b60-71c4c6a463c9\"&gt;\n        &lt;layer&gt;69229e15-6b70-464b-806b-8897329438a2&lt;/layer&gt;\n    &lt;/tile&gt;\n    &lt;tile width=\"71\" height=\"96\" name=\"s2\" fname=\"\" image=\"iVBORw0KGgoAAAANSUhEUgAAAEcAAABgCAYAAABPGW+RAAABgElEQVR42u3dQW6DMBAFUO5/abpqkyIwplXsb82zhBKxSOBB7JlRbLbt1Xbbz/ar7dqrvQPRaACReIJz9juEcwFTEaiJc7dPnwNn64KBA6YPZwZM0kXoGsoHH0wM0O1QPqpDTgwbIoby1LhqehDYkyGXxHlSQiiVeP6lxgKnOs5/KnRxETKcgUHZ8jifPLDWib+/RuKMuHJXn3sWlcd0yDNv7fjcahbOErlVcjgfl3geO0jFLlVAOLG5FRw4cOBocODAgQMHDhw4cODAgQMHDhw4cODAgaPBgQMHDhw4cODAgQMHDhw4cOBEnPx+81djOHAOKN/vj/vK4jyZ+BKDM3PqUjxOTx9QBmfmNMbeuWRR88rPOsiRQBGjVcrU6cihPGleeceSXJZriAoCLfQBZwzQqO+NSh9mdcJL4Dw52E8knh376uRWZxDRd87I3OrJd8aVLJJWtCxbCey5S0tXAjuXOq5bJoWz+lCeGFfpkFcaygMB4bRwADVgPMLp4hFOX8SGds8OOd5qAAAAAElFTkSuQmCC\" UUID=\"0db5fd69-a18f-4024-8a6b-b33b1514ebac\"&gt;\n        &lt;layer&gt;69229e15-6b70-464b-806b-8897329438a2&lt;/layer&gt;\n    &lt;/tile&gt;\n    &lt;tile width=\"71\" height=\"96\" name=\"s3\" fname=\"\" image=\"iVBORw0KGgoAAAANSUhEUgAAAEcAAABgCAYAAABPGW+RAAABm0lEQVR42u3d0c6CMAyGYe//pvFIQQJbh1n3Nd+7xPjrAYFH2dqu+X299rHx+D5+xsbYxxEIjQYQElGc1r0IDjh9nLvXzDnmMF0cZ5gmjvt8M4yTAaT0IYTjnAwctW+pDI7ibRxaymfjqMZVy4PASIZsuVqNlBCsEs8nNRZw3HH+qdDJ5VbgJAZl5XFmnljrwo/PkjgZn9zdca/qSDIT8sqvtnxutQqnRG6lHM7LJZ7nCZJil+gcAE4VHPcBDjjggAMOOOCAAw44DHCq4pRsQUk8mXotKJkw0i0oCjCyLSgqMLItKCowtKDQZQHONBjJFhRwwNHHOaYPtjhXF3+VW9muVuRW5FbUc8BhgAMOOOCAAw444IDjcvFbp9UYHHBOKJ+/z+/Z4oyUYu3qOSVxInOADc7KGnJ0d8N29yFybOt9K8mlXGlTL/DP3NjxlAoC6bIAJwdoRdBp2RMoHec8PdkZiWfgPa+98ujxLbssSuL0grKM9IVKYJXVSqkqCM7A3GN/W5VYyhXjKnDAKZh4VsEBqAHDTzjd/ITTG6IK3Uyd9KUDAAAAAElFTkSuQmCC\" UUID=\"7abd8566-d1ef-40a6-95e3-7079a77155df\"&gt;\n        &lt;layer&gt;69229e15-6b70-464b-806b-8897329438a2&lt;/layer&gt;\n    &lt;/tile&gt;\n    &lt;tile width=\"71\" height=\"96\" name=\"s4\" fname=\"\" image=\"iVBORw0KGgoAAAANSUhEUgAAAEcAAABgCAYAAABPGW+RAAABlElEQVR42u3d4QqDMAxG0b3/S7tfzk1s1tR+aWNvQRhDiDussSlEX69jbByf42dsjGN8A6FhACHRirPPQ3AKMOAYMOAYMOAUphI4Ro4Bx5hOrdMrClQVR4YTlauUcSTrnKhkro7THafHdJwljmsRWIuovvDgOPdxPNsBapheQF0Kz5b9kpnjgBOBc2e3bcY47pwDTuMCa0mc2iDWBZ0LVwVO7ziuqrwF6GpKKhKyKg611Sicx9ZWUUvz9DuBV8mOPeTgvAHO03BWH+CAAw444IADDjjggMMABxxwwAEHHHDAAQcccMABBxxwwAEHHHDAYYADDjjggAMOOOCAs8CP/9fwAg44J5T98/m7ZXE8jS8SnJlbiobj1MznUXHCcbK1Mdb2ksn6yq+S3UwNsDXnLd10L7+VZ+8rr8DjcQ2yRSAP+gAnBmh0HOd5KR8XdSsJh+N4Flij4zgQ16mthuNQW1VeSNQ2RJoti2wbXqV/IDjG1FweR1qVPwUn9G6VCSf8Vp4tIYMzqvB8Mg5ABgyvcCq8wukNp0k93oxQdtgAAAAASUVORK5CYII=\" UUID=\"646ab72c-9789-4271-8fa9-e8d416c0dde2\"&gt;\n        &lt;layer&gt;69229e15-6b70-464b-806b-8897329438a2&lt;/layer&gt;\n    &lt;/tile&gt;\n    &lt;tile width=\"71\" height=\"96\" name=\"s5\" fname=\"\" image=\"iVBORw0KGgoAAAANSUhEUgAAAEcAAABgCAYAAABPGW+RAAABvUlEQVR42u3dW47CMAxA0e5/0+ULKChNHTd+pL6R0CA0kpkj4sTupGzbd+w8Po+fsTO+4wiERgcICQlObx6CA841DgOcOdMKHHLO+FKuxfECtYpjhuP1ibOMI0rIo8G9pqR1nOk4XjnLI87UhCypdq1hDOJstz+uI+0Aa5hZQFMKT02/JHMccDxw7nTbMsYZwpHugcrhSAKUxJEG6b2h408rnNlxVEv5CFBrSlokZKs4qk2gdqf8uNpq9k75UbUVfZ2LnNNKdjS7nPMGOE9tk1Yd4IADDjjggAMOOOCAk+MNgbNALZcGJ2PfKAVO1sZaOE7mzmMojuc/BSyF433dG5wn4ERc2gUHnKI4x/KhLE7rj2/VVmVXK2oraiv6OeAwwAEHHHDAAQcccMABBxxwLjsB4IAjR3k//3+tLM5IE98EJ/ORonAcyXyOiuOOs9oxRul1MbNz5a1kl+kArOT3Sh+6N1/KVz9XLsDjdg1mm0Bu9AGOD1CGOC6rlXaDFRnHbZ+jDRwZR3rTtnK1VThO5trqDMK9n5P19pspcFbs6dAmFRapXH2ISMjgkHPA2Rks5SocgDowfIXTyVc4vQC91J5h/Xc0IwAAAABJRU5ErkJggg==\" UUID=\"635bb570-ae3b-4789-b519-1e2bde2efd2f\"&gt;\n        &lt;layer&gt;69229e15-6b70-464b-806b-8897329438a2&lt;/layer&gt;\n    &lt;/tile&gt;\n    &lt;tile width=\"71\" height=\"96\" name=\"s6\" fname=\"\" image=\"iVBORw0KGgoAAAANSUhEUgAAAEcAAABgCAYAAABPGW+RAAABxUlEQVR42u3dYY+DIAyAYf//n3afNh0RKdoWWl6S5ZbLcmVPhFHozm072s7j9/hrO+1oZyA0boCQ6MUpxyE4FRhwLmAYVhUc5pzGlcOwEuKsBiQeVk9wvDCt4pjheF1tlnFMcLyGo3UcdRyv+cojjuqELMl2rWEM4rxfIfdsB1jDaAGpJJ5P9ktmjgOOB86b3bYZ43ThaM41qXAkAZbEkQa569D5pxWOdhz1dU7tNeVz7QnZKk4VR+syTZlbaeCkza28luYp9nPKyW75zS7veQOcbDirN3DAAQcccMABBxxwwNH/415vIhRO2kICzQ6nKyTQ7nCqQgKLDqcqJLDoMIUEnJWDY9bhNIUE4IDji3Ne1qcqJHgLdJXzpCgkILcit2I/BxxwwAEHHHDAAQcccMABBxxwZnjzrS+8gANOgfJ9Xv5uWZyeDfnldgKH40jG86g47jjRTh+kZ1zLnltJXrf0iaf5R3n042ABHmflZotA6nPA8QGKEEd9ERipmtTlo/zpAmtkHLdFYLTcqpGB+2TlM9fnDMdpLbBGxpkCJ8JmFzgzTciRgcDpG2r8r3VwRq+Qo+KY51ZJAbnfzB0Mt3Cq3MLpA3CnBO2biHJKAAAAAElFTkSuQmCC\" UUID=\"8bb9387c-1e83-47b5-916c-d606cd68dec3\"&gt;\n        &lt;layer&gt;69229e15-6b70-464b-806b-8897329438a2&lt;/layer&gt;\n    &lt;/tile&gt;\n    &lt;tile width=\"71\" height=\"96\" name=\"s7\" fname=\"\" image=\"iVBORw0KGgoAAAANSUhEUgAAAEcAAABgCAYAAABPGW+RAAAB10lEQVR42u3d7W7CMAyFYe7/ptmvDajW1KH+OInfSAiEkDw9oml8Eo3H4zWePP4eH+PJeI13IDQGQEhYcUbXIjjgXONcvcec0xQGnLs4XWHCcbJQo+qE4WTd4SLrDHE8YCKBouu442StkTLquOJYut1omIA693Fm4oBoGC8gl8bzm7xEuQ44GTh30jbFOtPrHHC+XGC1xLEWGf1B789RON513MOus88cX3tPyFF1TnG8vqZb9lYeONv2VllL8y0y5ONkR9iVPG9UBGTL4ahdujI7nopzmwSO6uRfjqN8dyzFyQyulsLJzmbA2QGnIn4AB5ymOJHB1dITcnRwtXT70K63uruVXN3Jh+FsfwRFvcMuPYKi3GGXH0FR7bAljqAodtgcQRFpVsGJxGl9BAUccHJxvDtsmSMoqh12+REUeit6q/XyHLUBDjjggAMOOOCAAw44DHCMTSs44PyP8vv6+F5bnJlYtV2eU45juZ6r6qTjrJYhW3cq2u4+WD7Xet8q/Fa++qaeAY8dz7BFIKcswMkBUqljnLB7nglMxZlZYCnUScdR763KcZR7KytMeGSh/O83y3FWCbzAmYQBB5xrmLDIYqcMGRxwXCHBGeEANIDhJ5xOfsLpB4q73PjwVX6PAAAAAElFTkSuQmCC\" UUID=\"481c9b0a-76b8-43d0-add7-e76075b61a9b\"&gt;\n        &lt;layer&gt;69229e15-6b70-464b-806b-8897329438a2&lt;/layer&gt;\n    &lt;/tile&gt;\n    &lt;tile width=\"71\" height=\"96\" name=\"s8\" fname=\"\" image=\"iVBORw0KGgoAAAANSUhEUgAAAEcAAABgCAYAAABPGW+RAAAByUlEQVR42u2d2w6CMBBE+f+fxjdRQksLe+vuaUI0xjj1hG5nhyjbdoyd43v8jZ1xjF9A0OgAgsQMnKt1CJwGmIqAunDuXgMOcIBDQY5UkK2AaumoLSurM05TRwWO1ZLU1hGHY+WRLHREa85It6sNRkHn/W41Ewdog5ECJNJ4PslLIusAxwLOm7Qtos4UHMlakwrOiEBJOKMivQn9PmrBkdYR9zmt95yfSxdkLZ0mHKnTNGVvJQEnbW9lZc1TJIHnYkcSaFw3gJMNTvUBHC84KQP26ObMzQSuYM7cTKDGhFMF7JrB14I6m8mECdjJkIETKr4MGbADBzi2cK6yoBQB+1tAVz1PioCd3oreijwHOMABTg04FGS2ckwg7QONJ3CAswwcYlLg7GaAVtARN4Fc1Hsxce3WIfTlYHoreiu5D7eKFshzCLuAE+nL3/3gBTjAOUG5yoJKw5lx1+VMoDucyCbQHM5qAftoX1Y2YB95X+mYVH0rXz1DHoBHwK5mAsmQgWMDKIKOyW711GB56pj5nKfCnjqjf9hWMmB3hRO5twoB585geeq41ZyVcx2SwCjLCjjAqZMjU5ApyGIAgdODA6AOGG7h1LiF0weYebQFQ6Ox1AAAAABJRU5ErkJggg==\" UUID=\"6d452f50-9a23-43ed-afa2-0dfaf51b9847\"&gt;\n        &lt;layer&gt;69229e15-6b70-464b-806b-8897329438a2&lt;/layer&gt;\n    &lt;/tile&gt;\n    &lt;tile width=\"71\" height=\"96\" name=\"s9\" fname=\"\" image=\"iVBORw0KGgoAAAANSUhEUgAAAEcAAABgCAYAAABPGW+RAAAB9klEQVR42u2dW66DMAxEu/9N9/61vQhCTGzHjxMJtQKkMUcltodUvF7f8Wb7bP/Gm/Edv4CgMQAECQmcs/sQOBdgOgIawrnbBxzgAAc4kSZkL5hWOqJULgnCK8NZ6kwXgZIAvEoAa50pOBJxrxrJQ0e1Qp7pdq3BGOjcw9EIWCNwLx21xvOJXxJZBzgecFbctog6IjiSTNYKzoxASzizIqOAfj+t4GjrqPdWV+ccv2tPyFY6l3C0fqYleysNOGV7K6/SvITZdZzs2ptd3vMGcKrB6T5M4ZT1kCPXH+E85Ej1RygPOZq366WjCqeNhxzV28VDrmKTAgebNAYcqePYBs7ssfRwzuyOUdBPjm/xkFcBnd0iTy787jypTrreavW2KNtbaUzeqXqrqDULcCrA2ZGWgQOcpnAsC7rUE7J1QZfeQ145P1Wd43Wh4SvkNutzok6uKbtynEDgAMdlQubpA3BsAs+go14E8qx8IXCvzr5kbxVNh5VduywL1gQmHpOPfoADnAOUs46+NRxJjdQulW+HEzmVu8PJZpMKl7z0s0kFK816ml3mqTy7EzgBD5sUJxA42KQm/3/HJvVM5RltUuEy3l42qRBiL5tU+F+MXjapW2+V3eya2Acc4AAHOC41UttHM9tTeRGAwBnBAdAADK9wuniF0x+/YThzVf/fQQAAAABJRU5ErkJggg==\" UUID=\"7e1e4dc6-176a-4a3f-82c8-1079d5662375\"&gt;\n        &lt;layer&gt;69229e15-6b70-464b-806b-8897329438a2&lt;/layer&gt;\n    &lt;/tile&gt;\n    &lt;tile width=\"71\" height=\"96\" name=\"s10\" fname=\"\" image=\"iVBORw0KGgoAAAANSUhEUgAAAEcAAABgCAYAAABPGW+RAAACEUlEQVR42u2dwXLDIAxE8/8/7ZzapB5MAUkrYT9mcmjKjPCLC7traF6vTzt4/b7+tIP2ad+AoNEBBIkROD9/c+efz+8/Hs7VZAWczl0EHOAABzgV4ahARtUJg6Na3SLrhMBRLf/Rddzh9MxcNBjvOq4icMTtRoMJqGO3DzNxQDQYL0AuxnMlL6lcBzgKOJa0rWKdKTiW1enWcLwn4pFBj4wlHc7MxVz1nZUEo7+z1jHBWfm0W31mJMEsvNU6LjrHepvO9LfUSvFWXgOOVNVp3kroXaQ13eac1mSXASYLkHkpB44wbqgEKOWJJ3CAsxZ8e6tdWcCuCr691K5UBGYG35b+EhGYFXx79A8P2DcKvvUBe3UrQMBOwE7Afu+AHTjA0cLxDr7LBOxWQFHBd3rArvJWO9Qp5a2q1WF7P3CAA5zt4TAhs5QjArEPGE/gAGcbOMSkwDlkgHao4y4CeahnGLinFdjucbDV89x+I8HohT52C0rrQiOtwHabl6oJOuAARz4vpm2ATr1rgNOp3VoASsBRW4EVdZ0uAtVHitLhzIoz5WE0OZzdjjGOfhilAnblAdiJ8dSJSZVHp8OX8t0z5AF4BOxkyMAhYHcVjy1b8ciA/T9JEKqQq/9Ds97dUs5bqeukw4kOvj28VSqcyODbUqcMnIoNOMABDnAq5NbAybQPN4UInB4cAHXA8BVOF1/h9AafASFuGcY7bgAAAABJRU5ErkJggg==\" UUID=\"9aad43f8-e1fd-49a8-9f80-e533bc9e57d9\"&gt;\n        &lt;layer&gt;69229e15-6b70-464b-806b-8897329438a2&lt;/layer&gt;\n    &lt;/tile&gt;\n    &lt;tile width=\"71\" height=\"96\" name=\"s11\" fname=\"\" image=\"iVBORw0KGgoAAAANSUhEUgAAAEcAAABgCAYAAABPGW+RAAAEVUlEQVR42u2di3KrMAxE+f+f1p07GdpAvKuVLWRInRkmKaUBDmu9/Oi2/b5sbT/b4WXr9ft6B7RoEECLRBTOuR0uOAuO3qz+KpgFZ8FZcBacR8B5clowBOf8JQiOAtD2/W9ba793rCWptxzO6/NrUwBF96lgso6R4DA57j/vYH5uxAG0nUCwfVEwSrMZhqNExhE474B6NuWGVbuSAkeVZwTOFUY0+jelcDyb413UAS58j4PxFJ+WeCr7VTm3jH0PnF7VpcFRn0BEOS1IUUAjzfISgzzirV7HeU30IXCiJ/GUo7lXDc6oUR+C03uSEQP41XC8CBlF2/vur4UTCgI/bjAPTsvYp8NpexKDNqcHTrRZ7Z/RzfMHcIG3sv2y/v8yOUJugfHgKKFCWW51VZyDVNNSClPRY3IrJWSH33/4OwXKWF1nQuJp0F4dt1NU+JF5Y1CKOm8Hh7lr6DVAWYI1q5ZhfpRykOu8Sz14GpxozJERyPVAmmaQmXr8IG+Tg0F2ztvAadZ9HVVlKwddy3zlNIrjVD2DG23CDeOO7GGZcqLq2aNo6/jMvpv1XHyGBBOaFbILUD3vrvr0vp0BbaLNAaFBORwe3frq+QBjHJCnHBQvpXYHh5uVtaXbvjDcvDbWtETltJLVM6S6ZmUaIPQUVfesekOumMpmRcBs0Bg6zUN8R+dhqimFAxVDwLCmFwsqsWJaD6neICNPsGkXmRcY6qopb1btURH44jNHiUVUYzO8FVPMp6fYUqJlC6rGZsFRFXNVk1KcwRQ4x9Be81TIDihVxY9zE9Wc4yQrN8goHXCljm8ej8zQwSPVlKYPsqyLvJQHZloQKEk90RC7gSZQXmniSSV9sftWFTOnZGGxYCzbS+Gk1mjFoBwOU41SfI8loCQCFioGpRFyVDGjiafnqXoGYF6aPrCyAS1+dSSgLFZSSimlxS5PMUphXC1+8QdjbhhRnls17UCgvBktm/rNE9ui2vSBQIkqZ7TgDu3SNtuVkwkgVDkDXTVS6XRugR1n6pHOuKyOPtSfVZx4Rvq05nUTT2lWUXVVDjDwRn9Mh8MgVQ9PuS0c5v6vgMOG2N4WjhcGwLHHZJicMkfjknHIV8LBHW5CMf7ne8yJkO2ZylHHHR8HHzAVKhG83ceVj45azx38jY8XxlDnKkebiMrtjjpqnRX/Uf/84Xjj0xhSxiFHJ2p4Y4/VSbC9cNQJMKnD+yNTfPRg8GiAR+EEQ4NcOPF5lxoc8nRDNufr4ERtoNJR+PVwaNMy3Q6SIDLPIPdNhO81yDbkrZRrewScSCJ5qzhndKZLzyRYua4kB40XRsijq5n0rmkxqpyy9CF7mZf+lU70CPlWuRUalJC18FA4fbjSIPfkVghOz9JVMADs9Faprnz4mIRFz6IRMiuGlcDpBdO7XJ68PF8FnG9YRFF0Fn96ec0FZ8FZcBacBecOYLyEeMFZcLoBLjgMzgJEwKx/4QT+hdM/ufxluQ4Xq50AAAAASUVORK5CYII=\" UUID=\"c90327e4-cd6e-4dde-83c2-1723739225f4\"&gt;\n        &lt;layer&gt;69229e15-6b70-464b-806b-8897329438a2&lt;/layer&gt;\n    &lt;/tile&gt;\n    &lt;tile width=\"71\" height=\"96\" name=\"s12\" fname=\"\" image=\"iVBORw0KGgoAAAANSUhEUgAAAEcAAABgCAYAAABPGW+RAAAE20lEQVR42u2djXLjIAyEef+X1k1v7toYa1crwEAaMuNp2iR2+NA/wi3l52Hn+D4uDzuPn8croEODADokVDieDh44AMynAoJwPEk6cA6cA+fAOXA2g/POacEUOMkLuM8v5/p+7XUg16NXeqfDYRdEM+fBsgpIDScamDLwYXCYSGbhQCBAcrxDnYRH4SjpQ4vksM/9fU7UqkU6H4MTzcp1sPgLIWlxz0PUip0/Y3iHw2GqwOAgiYHvcwAxtWrxTEPhKBLB4FglOZ7nQnCYarW67mFwlBlogQNtEQDUA6YnBOkyyJGrreGwGXz1WBYY46Vw1Iuw2c3CiaWnPzLvhpO5CJOcy0AzcF6kx8ikbA+H2RzP3si27JPhSBHsTb04HC+mGg4nE/Irhi9y4R7QLCAUcT/mrey/Jfl6kQaFd5sTxTfQBtXvI+q1NLfKxDnuwN3XeSR9D/40QEtzK+uUnDravQ/k/vMCMiFBj5csRsCpB+8Bqn96741yNvIFvydoCRymVh4cb+AIMvWWTILq1ytI0+FYkDN5KuNn3EE0DiJoD8zlvCQYfR6OYYNaQI0G2RgYLLqDdCSISM6QAnsrHCu66iBVo1DECfFsTnHipccN8g1OID2RxDBp8cBQj1l9Zjs4qnFmtsUDY4JBV+Os6XAi25MCAyqEbALY39fAueh6lFMFYGrbgSYiVTteCIdJD6oHQzBg8Jrk2H5w7kUuB4xntIkaUbhu3GN7wvFU65YaVHA8MFHUjW0KLl2s91aemtQLdAgOAaM4AaVYtxQOWmaBK5iotEGaGjJe6ZEWlG6bEwCqIRSxVhxJEEpTtnDlISBgRDtmFCa1UcC5XnJsfgcYz9veTHJGHkVw/9tIThHqPM/8zotnU+FEX2g2nMh7Ta8hs9hiplr5a20L4LCuTyUHeqKFlq3ILpMc3gE6yGW/q+TAdaeiFc/jYM9wgSsAtExyWopNuNfHcI4VNFQaybPWSI5qAwQJgmrkgamT1wrQ3QYtgoOWVLjaCGoEOy1QIb9+bRObEwIEbbTU9cM1cq2Ytl5yGpun3S8sgilCCRZ9bgs4UTBYWCWQ1I+1Wg1fAFzmykvD8gmSFiv60k4kPVvBYYNALbRZMOG1l8OJyhUwEcVgopZe1NezJRx/1cGgK0UdWwoYNX97VS1UUplXzxEahhgYpTajNCLgAtwiOErD0L9PwLiHtctlG55QhD4djtpq5gHN1IIz3RpR8jofDmgY4qUOS9R8cw2WkVNYA6dRJU20MYpNsd3hqC0hqNdPzd7d9zSolfA9x0qO2k1OAQm7khkcVXKEbQztcLo3ani5V+E79NA5s5tXxA0w/U3aLVt8/HV13aYxlfIS5MZNd2PhZPddFqERKSyxfgocZjzd38G+LKXLdHs4qBEyA4dLTW5L5GMGuUlqxL0KLXCYtxK3iM+HAyPgoJ2NrWlFFcslcU6POrnRLiyTxvFNFk709yFBYNt9JUC2ndjbaUVvzo5uovRohNzaPM2Xki1MQdTmbHV/+9LcSlWt6G5P2U2v0w1yT25FC1mBKkQ3LorgTHHlPdKF2lfQHQ1YfNUKB6YjS+s5Uddn0KGqGtUoBHkEzrvfRPExOL/hceAcOAfOgXPgbAZneBD4mwF1pw8fBu/AYXAOIALm/Asn8C+c/gAutVG/HN01PQAAAABJRU5ErkJggg==\" UUID=\"3b7a097a-c1f4-4190-ae55-d189a19978c6\"&gt;\n        &lt;layer&gt;69229e15-6b70-464b-806b-8897329438a2&lt;/layer&gt;\n    &lt;/tile&gt;\n    &lt;tile width=\"71\" height=\"96\" name=\"s13\" fname=\"\" image=\"iVBORw0KGgoAAAANSUhEUgAAAEcAAABgCAYAAABPGW+RAAAEX0lEQVR42u2d624qMQyE8/4v7fPjqFAWX2YcJ15KkBBqC2jzrT3xJUnHeD7kPB/Pl4ecx/PxG9Ch4QA6JCI4V7+zfnfgHDjvbnWF8I1QIDjfDMaF8+1gQjhntjqWU6s5n5wWLJ+tZi3q/+drn8g1lcOxgM1eSATo5+/IKzroKThoEIgMHLno53uM1wG+UhbbCIfyc2fQyJMFM+1WM3cgI4TDGXiVwJYJchZOdiAzA0ddl9UmCA76+5mp9OqqqK6h710CBxlQNuZB4VRpYCkcdEA74Gg3inG/UjjIoLy7ywJi3CoCuxQOOqgD58BZAwd9DwMH+ew2zbHEMRJk5j0IHOYz+6bynz8mk0okMrZuRDS1s+WVtjgnk1tlNQcJAnUrG/25FfNZ9BUR4o+HYwVy3oBZgBqIW8N5hYJF3N7vLN2xwNwSzlsh63KRniXFmvRa/zEt5m5w3gc+nLubi6v87/SvobWeo9d3h2pJUZlUhzVcqxhqtbAJzriUNpkBRVW/CHTkTq2W81tL0AFocGTo3YdZq2mznEdrBbAYz7XEEOsHKGOQqNX0WM5lAGGbJXAts4dlWkBsNdIKZ8QugP4cz1qYSy1tB1PtXGDW0TqYaEDITt8yhtpJ7YEjvo8jMU6UP+kpABbw6Tdos+awliMKoDiZ5KzmGlHvh2NoB2I5mvVEWbU4eiXmTCX31xxPd+KyBAgfaCvvdStCczK5VfYzFeuKSt3K0p/YcrDFSUyyitSvl0bIA8mnZI3l6NO03yZuSTztwpI2g9j1HUsrorxNd98bWI5/IZzleHAEAB5ZT0s9BylGIeWHjCBHNSC5i+UgXVPNrTKCjKcmuWVypZaDJJ8zliPAd5rBoWyGwwRf0czFBIFIgPny/jcr3TmVO7DgcimYPmR0p8mtggQv7B8xqy0sqIDlSINb2fWSOThsyQLWnB63Uu5gAGa22EVZTqfmeLGF1fmcKZOyZdcWzTG7CIxLJYrrMojNIl2a4/k46lJiVBSvd1zAVo8ZYnT1rQZhNYK4gGI5knAtzWJaLYcXYqA3DrhWFGdtTzwty5kR4kg/BlhcyyzX26M5E0tFZrJyePtSh+W4sxPYion2PUSJaOWKtFLL8S3GzsmQ5W5x97NuRVq95Yi//o5ZiO0vhpw7FKANTlRfxvInbgnun4IDL4gC3czWJBxOtJi8FI4nrp7uMMv6mQGGcMTfxlAOh3Er1o1mNqJkNsBsg+PdZWaV+qptTka8tg+O5/tZOCs20R04B86gv2uL5ljiiOx7QAU5s58UDQO2WU7UzumA0xLnIEFgZrbKAEIi5OCcjfVuNVO0zxT52+s5mSNaoq4Fc0ZOBujG3IpI+JgDg7TDhghAFRpYtsoCAYMdL5U7k4vNrW4BB94sAqzTySSV3nvQg9uW7fHsOO6Oue7o2L8l7eBPOkQRKK+cYzbL0oe/DujAOZbDxWwHzurZ6i+6UVkQeOCcx4GDwDmAHDDnXzgZ/8LpHzaQM+tabWPNAAAAAElFTkSuQmCC\" UUID=\"00d3d8c0-a9d7-464e-a4fd-14c23f94184b\"&gt;\n        &lt;layer&gt;69229e15-6b70-464b-806b-8897329438a2&lt;/layer&gt;\n    &lt;/tile&gt;\n&lt;/tilemap&gt;\n</value>\n        </entry>\n        <entry>\n            <key>editor.models.TileMapModel</key>\n            <value>&lt;?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?&gt;\n&lt;tilemap name=\"backside\" rows=\"1\" columns=\"16\" width=\"71\" height=\"96\" x=\"48\" y=\"110\" UUID=\"5b188906-846d-4a90-8d89-e0e43a422abb\"&gt;\n    &lt;tile width=\"71\" height=\"96\" name=\"deck_1\" fname=\"\" image=\"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\" UUID=\"c89dfa47-5c49-4c56-836b-19b7dd6e5651\"&gt;\n        &lt;layer&gt;040cb294-c4ad-47a5-abbb-6a7c8d1f3482&lt;/layer&gt;\n    &lt;/tile&gt;\n    &lt;tile width=\"71\" height=\"96\" name=\"deck_2\" fname=\"\" image=\"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\" UUID=\"9e231907-746e-466c-b50d-1eb3db576f7f\"&gt;\n        &lt;layer&gt;040cb294-c4ad-47a5-abbb-6a7c8d1f3482&lt;/layer&gt;\n    &lt;/tile&gt;\n    &lt;tile width=\"71\" height=\"96\" name=\"deck_3\" fname=\"\" image=\"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\" UUID=\"492b2a75-4ed9-431b-9c7f-c93330a33eb6\"&gt;\n        &lt;layer&gt;040cb294-c4ad-47a5-abbb-6a7c8d1f3482&lt;/layer&gt;\n    &lt;/tile&gt;\n    &lt;tile width=\"71\" height=\"96\" name=\"deck_4\" fname=\"\" image=\"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\" UUID=\"e98cff41-88ec-47b0-bbd5-e684c97dc483\"&gt;\n        &lt;layer&gt;040cb294-c4ad-47a5-abbb-6a7c8d1f3482&lt;/layer&gt;\n    &lt;/tile&gt;\n    &lt;tile width=\"71\" height=\"96\" name=\"deck_5\" fname=\"\" image=\"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\" UUID=\"c6c3c2d2-620d-4fdd-9fce-bc6190817c12\"&gt;\n        &lt;layer&gt;040cb294-c4ad-47a5-abbb-6a7c8d1f3482&lt;/layer&gt;\n    &lt;/tile&gt;\n    &lt;tile width=\"71\" height=\"96\" name=\"deck_6\" fname=\"\" image=\"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\" UUID=\"b38f68aa-20ee-4be7-9840-136b838f7d8f\"&gt;\n        &lt;layer&gt;040cb294-c4ad-47a5-abbb-6a7c8d1f3482&lt;/layer&gt;\n    &lt;/tile&gt;\n    &lt;tile width=\"71\" height=\"96\" name=\"deck_7\" fname=\"\" image=\"iVBORw0KGgoAAAANSUhEUgAAAEcAAABgCAYAAABPGW+RAAAC+klEQVR42u2di5LDIAhF+f9vdqb7arepkYcGFCKdYdrdTd14chUR0gK8H4+0f/t4fP+ipP3bG1DCIAB5OAnEtoYDj1LKn/28rmz1ubmA01JNwkEhJJwKQiqnCQezzeEURC3prQiXvs06x3qpHxbOc/54rWW0zRTQDDjIAk/LEs5WcKqhgZrguHvBqcKFj79Xr9Hj4sIBsvPHYPN0zOGZPO4Ex8J7GcEpAjhNgA04nHrswg0rONjVxiJwBA6pwsZFiK0cszknknK4TmFeqPWzyFvdCQ7luofWOXeHc1AJ3BkODMBpbXaNvC/DhzuHDyNbE1vBKaXzeaeoXEM18eEYW2A422+Tei8nWQbHcH94+R7zJTj2a5i185IIDibRyHAkw46FA4REo8IB4bAj4Zw7z8ZNjuaanvNuMxiE87HHS2xkrbBWVM+dty4cZpdv6TCi4ExRziQ4Q6HFajgwCGckdtJUzoQ5h0/YURmClmGQdJUj7dcCOJyHAXPlOIRTZy57AbUUQg7HqHA4QM1Olacd24Pya3A3OBSgWHA6/4nEU/ROsCbDShSYMnDo/ZFoi0Bpv1g4knoYG+VczkyQcHrqfIaUI4fzyh5YG6goB+Yq551aKcbPqZxUTionlbOlt9p+nUPdYhgfDt0vw9jKg7kMPD2lgf1F5ZHyVuZwgtgCOBEqLGRpbCM4GmUpM9tyAkcyH0nh6LWlBqc8xguBPMOR9msIjuRENoGDJeZEpSuO4ZiUoJwrKrabc+jotbAK8gpHJSqvZddIxJ9y3RFcOR5mdMNB76arK6g+APWFFRpz19XCyMvKIcvLTurRrBW2bWtMOVRal5x3PCtHcScQBcR6LK/KUUsHF3pj/aKnWjvnqCwCucbXzBNzbhQxvOk+jreafkuR5y0LB3B8x1YJJ+EknISTcBJOunLJlb58xTXbWg6nrzNc4KfXVsLxDEc3Zbv+UwoSzjw4VwuObNryAkezTGT5J6O4GlZg1NYtPmY8v28mHJj8CifkK5y+AA8evcu1KqggAAAAAElFTkSuQmCC\" UUID=\"8c8ed8dd-8d4e-4c70-a267-ba27d105b572\"&gt;\n        &lt;layer&gt;040cb294-c4ad-47a5-abbb-6a7c8d1f3482&lt;/layer&gt;\n    &lt;/tile&gt;\n    &lt;tile width=\"71\" height=\"96\" name=\"deck_8\" fname=\"\" image=\"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\" UUID=\"a4ea2b81-8403-4b5a-8413-e54da2e9b147\"&gt;\n        &lt;layer&gt;040cb294-c4ad-47a5-abbb-6a7c8d1f3482&lt;/layer&gt;\n    &lt;/tile&gt;\n    &lt;tile width=\"71\" height=\"96\" name=\"deck_9\" fname=\"\" image=\"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\" UUID=\"0e995a0b-0ab6-42e7-9ed9-d4900cfbe304\"&gt;\n        &lt;layer&gt;040cb294-c4ad-47a5-abbb-6a7c8d1f3482&lt;/layer&gt;\n    &lt;/tile&gt;\n    &lt;tile width=\"71\" height=\"96\" name=\"deck_10\" fname=\"\" image=\"iVBORw0KGgoAAAANSUhEUgAAAEcAAABgCAYAAABPGW+RAAACXklEQVR42u3d0W7DIAwFUH/8HvawT0baqk1d0pSAAdv4giuhRNOUpifXhkTaSnS8vmP8j5fX4wcJcqTUNnjHPYBgYfRwDqBtYHrSo3rybVcqv/07Tn4LhHOc+CsQVQHzW2raTsW5nlAN5PVErr8vm5wWKGGc2pW7A0m3YLVEtfSc1iSZJqe1p1gAAc9W7yWXL8GYym+bN/fDyMM4w+lNDheoJ93wK+Qa0kjpG+MgXQg4HDJEN8U5PxKQOAZ1HpMLDIdTWklLAzfhEGO/fEIpSQElA+BmnNxBEXFUek5PrUv0icDBx3mWxlEiXnCkp/nlcCTfZ7myGp3mVXCoMu1v3ZBLVyxwCh88cAqLvMCJ5ASOGA5nBE7gBE7g9NwGBA57nNc7d/sb46Tq/r44jP3oOXv0HAqcUZyPz6/fETgZmNx+4AQOr6TWKa3AsW3I68xYLnAIFaftQ/bjEBoOGePQ+jjrAL3hjN8S9M1Ym+CMI22AM1Zq7nB0/6gUb3FoiNNXai5wbAdGgibhYNxqTMbx3agn4vhPDyQOBU4fmOQWrudYwUDOVhskRzY1CyVHHkYLzBjHDoawkgMIY4NjDwOSHGAYXRxcGOXkPFHm4DhPzrzURHLwkzMPByA52EBGs1WscxhNGQvIcBE4N0G9YMb3Vn6gQJ7n+J3uJz9Dnp8mh8+QOUj6UI6T4wPLeXJaepMOFlByuAtJWSSw5HDXTIpAWP9ZvwS0dXLubmrlymvB5OgAgSdHPj2LJKe2v2VySmmRb86LlJNcesCTUyor4dLC+YaiWlKEby2u31QU4wzzA3L0Sthlb1tdAAAAAElFTkSuQmCC\" UUID=\"25000197-ea3d-4912-9e83-cddddaf0d7dd\"&gt;\n        &lt;layer&gt;040cb294-c4ad-47a5-abbb-6a7c8d1f3482&lt;/layer&gt;\n    &lt;/tile&gt;\n    &lt;tile width=\"71\" height=\"96\" name=\"deck_11\" fname=\"\" image=\"iVBORw0KGgoAAAANSUhEUgAAAEcAAABgCAYAAABPGW+RAAAEQUlEQVR42u2di27rIBBE5/+/eaRWurluAM8uCzgPwJUQTepHGA7DLjgq8Pz5uctfyX5+QE5ZSDSV0HUTgbYRpkegW5xbnFucW5xbnFucW5z54pxVxGkRqOm6q4gTEaj5mn/ieKX3Ax/nlvWbRRr6/I8PbZRekZCcX9ajor+rVMUpRRoVpud6HxfnKoGiwnAmcdKGRUQKC1N4zkz0nGarkxkHxUEDFQgI/ZXiWI3wBELHcMGM5KgGeOJ4wkRFmlIcjyBUpmlMNCu9RBwlzBWhwFTiKIHQIAwnMeBLxbFE8ma7acWp5VaokOPmZxMOr1OEbEa0hjioGDQnFijLrYxG0airgswuUJWcQxBWhkqvQFORIwoLgWhRECVqusQTds5EBk0W0EmmCggxW1ZuHHAih5BTO9XsNppefLs42RCzgj6HvKl8ZijxVJ4TXaLAZAI1LVn0Rr+z0tO8nmORs8oCV0icw18EOdKQ2bq+PLk4VlbNHt9ZTRwyEOi1NhgrkoNk99BcP27cCV1CnH/CGL3+6YVyHJ8hqY/33yEOS3KupEE1BqMF+e8918xzK3GDckjJ49RFG2olijoGDikZMRCioLFOz8s8pEKO6gmLgKwcDRitveEl7g/nbzQ6iRDilL2jPIeVYUCjQd9WR4hu9pyqtwR7er4FdmNoqSEle+NFxNSGbss5TffJyCl6G/mQ8snBNdPy6EwXLuFHblIicudnzXPc+t2eg4sJjawEhsihpi8daryop2G9LokYJNr3HNpmHOoxBHu6Yzp/FZk95DBMDm0B3bE+4DVXCNIzW415DhvJ+bb4p0IOI56DK2aPzhlFEXgitpPSazxH5T9fGhl3kQPD2TNyLlqLwZu945rtYI+cxxB7eQM/nVPVI+QyEKyTw6/Pkzro8yNk6twquRhFYMfjfXEMa+s2lRjIPD+5D1snihg59QiZxbEMUMQGwig/uBCIojN6rj8U50ClEDkZx+vHV3h0DXn8uYEedapmSaR4XZLLQlD7Xv/FsRqmPIfZd5rSc3yBdB3vdU0lTg2mfB8GcbojmWbl5oGgfPykX4xZ6iA55VKpTc5adQc5vMnp85yV6oDnEDrHuslxyPHO2cdzkmdxeJMj1TuRlIu0q+eYj9uubsoBcvLpfC/vCZFD8RzyDqYcJOeZbNKMe3YmhzByLCxLkEMOhYpOxLygQB2eo7eIV/SgkOecBEFJzJoe1EgOxay1rgc1eg6ey5KoZe2cnqB4hGx8a095zioeZJKTrrGWZnx+cJtFcrqG97jkeMTs4D0nciC2LlScUxLF098X9Zznvk/+mtZa8qIBofAcnjyHcuPN9qgl45ySmNp0vXryWZADuUPo0YAFvCVIju85uy2yZw8SZOunxqxV7idvs/vgL0fssR1jeI4/S2ETQRo9Zy9BKp6z7uwzFiFv9RRFnBzsPoSM9aviPxXdJRPmF6EQLve7Oh6QAAAAAElFTkSuQmCC\" UUID=\"25000198-ea3d-4912-9e83-cddddaf0d7dd\"&gt;\n        &lt;layer&gt;040cb294-c4ad-47a5-abbb-6a7c8d1f3482&lt;/layer&gt;\n    &lt;/tile&gt;\n    &lt;tile width=\"71\" height=\"96\" name=\"deck_12\" fname=\"\" image=\"iVBORw0KGgoAAAANSUhEUgAAAEcAAABgCAYAAABPGW+RAAADbElEQVR42u3djW7rIAwFYN7/mS31SpvaS4iNbTDh0HlStGlN1/XrwfyEraX8/3jl8TkuHy+iPN5HDfRXnuxQgr4W4f09IjIdP+d+E84Vg3my1dc9qDdM8zO/C4TDaZFkmOt9jsGxgkg4poRVtx+B4wXxJqeGqWvUMTifX76KfyjOBYjwa84tMS2SA0c/pwUCxmFf6TY55idOt7oj9VLU1B44HLEmGEGGcKrEEGrNkZpBadNibFpSb3WrRQwQFI46QKu/Vzcxw/26OOg1pzjrhxfH1o0TXs0pIz1PJA5qzSkTBdZSe6xzKbjkcPUgYtziwmESs73mcOOYFUC25BDWOKc3/rDOtGOSA1pztGWECCBfcsDGOb3m1Wtmszhak4IZ53Ddq6VIj9YnrZeCm1tZ5kAROJbEQM6tuF5rBoidMnRqDGxywgaFymTSmhjY9ZxRIDkZZKox8MkZAbo2mTKdGDphDdnVXbsSYrsdfoHdVJCDaswxa8ifQxsIukB8CcLGKTKQXnzHE0PHXLcSrkSONiHuku8x4xwJpimSAU2o4K7neJrU/RUfLcL35PDnwxdkqUZQWBEWE0hHJCeqF7Le/wSciYHb1PlIONdtaSWkFxq7PxAOtyRhXYBakiAUHHHNZioxo2BAONJy6IqhvwkUBceyYjff61jBgHCsa73lqQSh4EiXXvYkCAhH2zQ9eiVyOEE7cKS/G7Ds7LRcOZhP0CYcK8zMUbqz8bgaE4pTir6NxJMW/2K6Y0HrSRwJYrTODCP1VgLbGvYEjpyQ+23RyTFvQJKK/EocDWbkolxkTeody3D6NaV+cFpWmOfStQinX0uuMJZX9AQYE84ozO85b6D283NIy3FiYai7ozy+N1uA46kxXph2H/EKqIgpEYuzpinJMFqtgknObhhpaDBzhOAgwmiPoTXPUJyTYeRmuQDnVJhrKwjAKZ0HORUmsCBnYlSchBFwEqZTcxJG7a0SRkxOwojTh4RRu/KEUXD+OkxnEJgwwiAQCwYGBxEGAicK5ltSw8zKsWCAcBLGnJzdMGA4CaMmBwEGEAcHhv/ZG3GQYKIuyq3BSRgBBwBmd3PicRJGwAGCgcNBSgxecoBgjsB5vsbQC+1/+RTv7oqVMPA4O2Ait6stXCbdCwOLkzDK+80kzB0m38JJeAunf/qU3TPwoRQwAAAAAElFTkSuQmCC\" UUID=\"25000199-ea3d-4912-9e83-cddddaf0d7dd\"&gt;\n        &lt;layer&gt;040cb294-c4ad-47a5-abbb-6a7c8d1f3482&lt;/layer&gt;\n    &lt;/tile&gt;\n    &lt;tile width=\"71\" height=\"96\" name=\"foundation\" fname=\"\" image=\"iVBORw0KGgoAAAANSUhEUgAAAEcAAABgCAYAAABPGW+RAAAA4klEQVR42u3WuwqAMBBFwfvp+XMFkYgRJdvGKbbwUS3LcJKW7ZiYPn0nbXhhrn3cN/Xy0x+fMy7HTCwnk2e38neXU7kc5jCndjmMKYBsmMMcnaNzmMMcnaNzmMMco3N0DnOYo3N0DnOYo3N0jsthDnN0js5hDnN0js5xOcxhjs7ROcxhjs7ROcxhjsvROTqHOczROTqHOczROTrHMIc5OkfnMIc5OkfnMIc5rkTn6BzmMEfn6BzmMEfnMEjnMIc5OkfnMIc5OkfnuBzGMEfn6BzmMEfn6JwFL4cxH8/PUzLnTnYqjwQbNAxDhwAAAABJRU5ErkJggg==\" UUID=\"25000200-ea3d-4912-9e83-cddddaf0d7dd\"&gt;\n        &lt;layer&gt;69229e15-6b70-464b-806b-889732943899&lt;/layer&gt;\n    &lt;/tile&gt;\n    &lt;tile width=\"71\" height=\"96\" name=\"talon_restart\" fname=\"\" image=\"iVBORw0KGgoAAAANSUhEUgAAAEcAAABgCAYAAABPGW+RAAABYklEQVR42u3dQQ7CMAxE0R6dmxuJRSlCqmiJPePkx/K64S2qJrHDtr1HkHt+jNge5J4HIDBOgIAABxxwwAEHHHDAAYcEBxxwwAEHnEP+EsvgjIjpcDKiPU5FtMNRRAscZVjjOIQdTtaPUSINwamaeDXQ3ziq90HFc8twlJ8JEhyHj7XMOdzGcVsTZcznFo7rYnH0vFJwlNsMUhxnmNFzvIQTk+CEAsdpF88Kx3GbswwnJsOJKhznTfJ0nJgUJ7JxOhyxgAOOGU5MjhNZOJ2OdsEBBxxwwAEHHHDAAScfZ/nlAwtPcMApx1l+m5QNdo5mONTjONjxrHzpQgJKUCheouxNXjAZRihlBZOU2lKkXVvePwKq8nmyxpArE1d1zgztt3IKmtGS32+0MVbjKJDa9pV3bJsuv5GgU8O9/C4LxysauAUFHHDAAQcccMABBxxwwAEHHHDA6YED0AkMf+H0na/xBK3MWmALjbJoAAAAAElFTkSuQmCC\" UUID=\"25000200-ea3d-4912-9e83-cddddaf0d7de\"&gt;\n        &lt;layer&gt;69229e15-6b70-464b-806b-889732943899&lt;/layer&gt;\n    &lt;/tile&gt;\n    &lt;tile width=\"71\" height=\"96\" name=\"talon_end\" fname=\"\" image=\"iVBORw0KGgoAAAANSUhEUgAAAEcAAABgCAYAAABPGW+RAAAB6UlEQVR42u2d2W6DMBBF+fT+eVpFarqpCbZnudccpHmLzMyBmFnhOL6OG/KQH8fteEMe8g0QMJ4AAgRwgAMc4AAHOMABDnAQ4AAHOMABDnA2hfPx67u4Gjyk/wicz4VdAQ3rfxbO74XdAE3pfwbOfwu7AJrW/xWcVwurA1rSP+LOUQW0rPfqnqMKKETflaeVKqAwPWf9HFVAofrNeMiqgML1mg0f1ACl6LMSW6kAStNjNfDsBpR6/oiovAtQ+nmjUhbVgErOF5nPqQJUdiGik13ZipfeoRmZwCwDyve2rDRptCEtm35mDjnKoDZ3ITvBvmpYqx9VUX2YNbDdA68qzYwaKhGaVNatzhosE9RWF/VswHRVPC3AdJaD5cF018qlwSg0EkjnpF3gXO7OYc9JeGJtDQc/p8BL3grOiNGXiq1mjL1EVL5i5Nb5nAjjtswERhq1VQ45w5gtqg+ZRljXrSqUt6x4Vl5Vq1p5x4Zp0WXR6YtI9+couPmSnV1KEbRUT6Bickqim1Q579vah+zQxd7Swe40/1A6++A4OVMyNeM8c5U6b+U+jHbWhjQ4zjOeqX8r5+ng1A3Zea489VHu/KaBVCeQ1zUgwAEOcIADHOAABzjAAQ4CHOAABzjAUYYDoCdg+ITTX7kf723NIVNzoSy+AAAAAElFTkSuQmCC\" UUID=\"25000200-ea3d-4912-9e83-cddddaf0d7df\"&gt;\n        &lt;layer&gt;69229e15-6b70-464b-806b-889732943899&lt;/layer&gt;\n    &lt;/tile&gt;\n    &lt;tile width=\"71\" height=\"96\" name=\"backside_empty\" fname=\"\" UUID=\"8eb12cd0-f6ca-4f8b-9d38-50ec2945dc41\"&gt;\n        &lt;layer&gt;69229e15-6b70-464b-806b-889732943899&lt;/layer&gt;\n    &lt;/tile&gt;\n&lt;/tilemap&gt;\n</value>\n        </entry>\n        <entry>\n            <key>editor.models.TileMapModel</key>\n            <value>&lt;?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?&gt;\n&lt;tilemap name=\"poker_animation\" rows=\"1\" columns=\"2\" width=\"32\" height=\"22\" x=\"0\" y=\"0\" UUID=\"ab639c59-e44c-4c9b-a2f3-61b2c6b7086b\"&gt;\n    &lt;tile width=\"32\" height=\"22\" name=\"poker_1\" fname=\"\" image=\"iVBORw0KGgoAAAANSUhEUgAAACAAAAAWCAYAAAChWZ5EAAAA00lEQVR42sWVgQqAMAhE7/9/2igqnLlTm9FAlqP0eVOCCGRq2Hc5dpzPx67O7XuxL0Ms8ORPCCSTRFA3RFS59kGT5aGgi8rIr4nfJp0Vk1DAflyXm/nIyr/aeEQJJXHTHVcgEY3W3fkfKQEWHGb+0arE1YRR5Wb5irzwRSkAZ06HM20WpKyEAbDB3OQ6GFUkX/kAoAN5stvqKQibIgagA7kAyTXtkSxAqEYBJEo+BeiCQQeAf88/AVRAYH/hnQC0YR/JOcQSgO0RZp8BrPYB/ky+2wZmWjk4uHBnLAAAAABJRU5ErkJggg==\" UUID=\"5a0c5e61-f5b6-4db7-a2a9-405e5fe3c039\"&gt;\n        &lt;layer&gt;08b388db-1b65-4952-8dff-8664adacf4c8&lt;/layer&gt;\n    &lt;/tile&gt;\n    &lt;tile width=\"32\" height=\"22\" name=\"poker_2\" fname=\"\" image=\"iVBORw0KGgoAAAANSUhEUgAAACAAAAAWCAYAAAChWZ5EAAAA4ElEQVR42r2VCw7DIAxDff9LZ2rVVQ4hHyBbpYjRIfxijAoRiFu4RrlHPL/vkd6P6/K5qL0Qi1sIFEUyqBci65znCMXqUOCmKvYz8a6o10zBgRFi3e5ojhX7uRqdoO6C1L5HIGLfHTiB7GoZIS7+f9MJWHF95kac15Uc8aC+Iax0rpWmAAYkgxByAIUzVwCFx+4LI/5cQ73YPfPNx2RkBjBeM2P3AQDvHwLohTJP/QFMGcC40QDgibsALkxj52UAN9kN4ssAKyAYP+GdANPAuuKHGVjJSFQ/A/hrCLvFr/oAoqlQIUMaf4AAAAAASUVORK5CYII=\" UUID=\"1a6307f6-0806-496f-9b4f-afbd7cbd7bba\"&gt;\n        &lt;layer&gt;08b388db-1b65-4952-8dff-8664adacf4c8&lt;/layer&gt;\n    &lt;/tile&gt;\n&lt;/tilemap&gt;\n</value>\n        </entry>\n        <entry>\n            <key>editor.models.TileMapModel</key>\n            <value>&lt;?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?&gt;\n&lt;tilemap name=\"castle_animations\" rows=\"1\" columns=\"1\" width=\"26\" height=\"12\" x=\"0\" y=\"0\" UUID=\"96f80568-84f2-4dd1-852b-11b108fddb82\"&gt;\n    &lt;tile width=\"26\" height=\"12\" name=\"castle_0\" fname=\"\" image=\"iVBORw0KGgoAAAANSUhEUgAAABoAAAAMCAYAAAB8xa1IAAAAR0lEQVR42mNgYPj/nxiMDojVh8AM5Ggi2yIGnJI0sAgXJt4g/OJYBMjzDSHHUjkecDuWvolhZFlEraRPcWqiatBRmvT//wcAhK1Ry7OMezoAAAAASUVORK5CYII=\" UUID=\"b1ea9525-0e4e-4fc8-8a63-55b2bcf77a95\"&gt;\n        &lt;layer&gt;08b388db-1b65-4952-8dff-8664adacf4c8&lt;/layer&gt;\n    &lt;/tile&gt;\n&lt;/tilemap&gt;\n</value>\n        </entry>\n        <entry>\n            <key>editor.models.TileMapModel</key>\n            <value>&lt;?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?&gt;\n&lt;tilemap name=\"robot_animations\" rows=\"1\" columns=\"2\" width=\"24\" height=\"7\" x=\"0\" y=\"0\" UUID=\"f948f215-40bf-4dca-bb31-788f73156cb8\"&gt;\n    &lt;tile width=\"24\" height=\"7\" name=\"robot_0\" fname=\"\" image=\"iVBORw0KGgoAAAANSUhEUgAAABgAAAAHCAYAAAAS9422AAAAQ0lEQVR42r2QQQoAIAgE5/+f3qAQPLiQCRlzsMMsKwIFGDSALHbjgrhBhbwKe22ClZkmroX7GwWcXRuyPN63gA7dEy1wvWen+eMQ9AAAAABJRU5ErkJggg==\" UUID=\"1e9ff1c3-ee06-4142-90f5-ec081d91060b\"&gt;\n        &lt;layer&gt;08b388db-1b65-4952-8dff-8664adacf4c8&lt;/layer&gt;\n    &lt;/tile&gt;\n    &lt;tile width=\"24\" height=\"7\" name=\"robot_1\" fname=\"\" image=\"iVBORw0KGgoAAAANSUhEUgAAABgAAAAHCAYAAAAS9422AAAASklEQVR42q2QSQ4AIAjE+v9Pj/GAISriBumFQycMAhkE6AG8OJooiB2UyH3I1QdengWtvohu9NKsqkFk626qClq1zEU/A044ragAZQ9qpCnFAgkAAAAASUVORK5CYII=\" UUID=\"2fc57747-aa27-41d5-b348-ed2be68fa384\"&gt;\n        &lt;layer&gt;08b388db-1b65-4952-8dff-8664adacf4c8&lt;/layer&gt;\n    &lt;/tile&gt;\n&lt;/tilemap&gt;\n</value>\n        </entry>\n        <entry>\n            <key>editor.models.TileMapModel</key>\n            <value>&lt;?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?&gt;\n&lt;tilemap name=\"beach_animations\" rows=\"1\" columns=\"2\" width=\"14\" height=\"12\" x=\"0\" y=\"0\" UUID=\"5365e20a-c399-4cc4-a780-de751ca7fdaa\"&gt;\n    &lt;tile width=\"14\" height=\"12\" name=\"sun_0\" fname=\"\" image=\"iVBORw0KGgoAAAANSUhEUgAAAA4AAAAMCAYAAABSgIzaAAAAU0lEQVR42p2RCw4AEAxD3/0vPSF+Y8ZImphqZwqSFyHUHfIDJYQB76wLZ/IFVRPvWOrt7Rjz4MxokZ4BN+cTx5qj9yEqx1YGwxfl9SxahScD604CkUGqZO4bEkQAAAAASUVORK5CYII=\" UUID=\"a0531693-d6c6-4c30-98da-00dfe117c8b2\"&gt;\n        &lt;layer&gt;08b388db-1b65-4952-8dff-8664adacf4c8&lt;/layer&gt;\n    &lt;/tile&gt;\n    &lt;tile width=\"14\" height=\"12\" name=\"sun_1\" fname=\"\" image=\"iVBORw0KGgoAAAANSUhEUgAAAA4AAAAMCAYAAABSgIzaAAAAV0lEQVR42p2RiQoAIAhD3///dFF0rdKOYJCOzZYQ0uEJ5Ub4gQihw+s14UjeoGjeJ+Z6eTubPDgZd6RnwMnZ4pj36H2I7LGWMoEJ6/K1fRKKhZWqiiw+AsLXoG5EnP5iAAAAAElFTkSuQmCC\" UUID=\"9200227b-5948-4d98-b64a-17846b71b717\"&gt;\n        &lt;layer&gt;08b388db-1b65-4952-8dff-8664adacf4c8&lt;/layer&gt;\n    &lt;/tile&gt;\n&lt;/tilemap&gt;\n</value>\n        </entry>\n        <entry>\n            <key>editor.models.TileMapModel</key>\n            <value>&lt;?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?&gt;\n&lt;tilemap name=\"backside_animations\" rows=\"1\" columns=\"7\" width=\"71\" height=\"96\" x=\"54\" y=\"250\" UUID=\"6ec291a6-ead4-4551-9186-c6dda3616fbc\"&gt;\n    &lt;tile width=\"71\" height=\"96\" name=\"deck_7_1\" fname=\"\" image=\"iVBORw0KGgoAAAANSUhEUgAAAEcAAABgCAYAAABPGW+RAAADB0lEQVR42u2dbXLEIAiGvUPv1fufpL+cST/SzSZGEBUUIjvD7EezNj55FVHchPB+bG6HXR4/H0S3w96AHAYCSMNJALY0nLDFGHf7fZ3Y7HNTASenGocDQnA4CQRXThYOZIvDiYBa3FshLn2ZcY70UN8snP/+4zWW4TZRQCPgAAM8LnM4S8FJmgZohOOeBScJFy5/T16Dx9mFE9DKn4PN2zGnZ/S4GxwJ7yUEJxLgZAFm4JTUIxduSMGBrjYUgQNwUBVmLoJt5Yj1OZaUU6oU5IVy70ne6klwMNfdNM55OpyTSsKT4YQGOLnJrpbvefjw5PChZWpiKTgxVj6vFJVzqMY+HGEzDGf5aVLt6STT4AjOD0+fY+6CIz+GmdsvkeBAErUMh9LsinACIlGrcAKx2aFw7pUvxk2K+pqa884zaIRzmeNFJrJmWC6qL503L5zCLN/UZoTBGaKcQXCaQovZcEIFnC18HAZV8HxMrdXAGdDnlBfsUjgHBOABQeJVDrVeE+CkMHKAZJWjEA4IAlAQpB7os2Xh7O+//iycm+j2uZv1ZvVcOJX/hOIpSjakWZEC0wIcfH7E2iCQWq8iHEo+jIxyulcmUDg1eT5NyqHDea0eSFtgUU4Yq5z30koUfnbluHJcOa6cJb3V8uMcbIuhfTh4vQRjKw2mMvDUtAysLyq3tG4lDseITYBjIcOCtowtBIcjLWVkWUrgUPojKhy+stjgxK09EUgzHGq9muBQTmQROLnF+PL2Hf1wRFJQ7hkVy/U5ePQaiwrSCoclKk9ll1mIT2IZG64cDjOq4YC76dIMqgugurCCo+/qTYzsVg6aXnZTD2eusGxZbcrJbuaIWRX1BKRjlcM4EwgCKnosrcphWw6O+MR6p6ea2+ewDAJLhc/pJ8ZsFBHcdG/HWw3fUqR5ykIBHN2xlcNxOA7H4Tgch+OunHKlu684Z1nT4dRVphT48ZXlcDTD4V2ynf8rBQ5nHJzehCOZsrTA4UwTmf7LKKqaVRAq6xE/M+73mzEHxm/hBNzC6Rt9t8K1ssa9egAAAABJRU5ErkJggg==\" UUID=\"fdf06b20-0845-4acd-9661-9d01d8efee4a\"&gt;\n        &lt;layer&gt;08b388db-1b65-4952-8dff-8664adacf4c8&lt;/layer&gt;\n    &lt;/tile&gt;\n    &lt;tile width=\"71\" height=\"96\" name=\"deck_7_2\" fname=\"\" image=\"iVBORw0KGgoAAAANSUhEUgAAAEcAAABgCAYAAABPGW+RAAADC0lEQVR42u2dW3LDIAxF2UP31f2vpF/MuI80iY3RAyyBZOQZTdLUpeb4ghAIJ6X3sYW97HD8fJDDXvYGFDAQQBYuArCl4aQt5/yw3/eFzb42E3Bqqgk4IISAU0AI5VThQLY4nAyoJbwV4tKXGedoD/XdwvnvP55jGWlTBTQCDjDAk7KAsxScommAxjjvXnCKcOHw++I9eJ5fOAmt/D7YPJ2ze0XPO8HR8F5KcDIDThVgBQ6lHr1wQwsOdLehCByAg6qwchN8K0etz/GkHKpSkBeq/czyVneCg7nurnHO3eHsVJLuDCd1wKlNdvX8XYQPdw4feqYmloKTc+PrSlG5hGr8w1E2x3CWnya1nk4yDY7i/PD0OeZLcPTHMHP7JRYcSKKe4XCaHQknIRL1Cicxmx0K51x5Mm4y1Ne0XHedQSecwxwvMpE1w2pRPXXdsnCIWb6pzQiDM0Q5g+B0hRaz4aQGOFv6eBlUwf05rdYCZ0CfQy/YlXBeEIADgiSrHG69JsChjl4FuYZDKYYCVFPV/rNbwql9XoWwfT5sr8L09WfumxUIgdG0bMNp/CccT0HZkGbFCkwJOPj8iLdBILdeJBxOPoyOci6vTKBwWvJ8upTDh/NcPdC2JKKcNFY576WVrPwaygnlhHJCOUt6q+XHOdgWQ/9w8HopxlYWzGTgaWkZ2F5U7mndSh2OE5sAx0OGBW8ZWwmORFrKyLKMwOH0R1w4cmWJwclbfyKQZTjcenXB4VzIInBqi/H09h37cFRSUM4ZFcv1OXj0mkkFWYUjEpWXsqssxBexjA9XDocZzXDA3XRlBtUBUFtYIdF3XU2MvKwcNL3spB7JXGHdsvqUU93MkasquhKQjlWO4EwgCIj0WFaVI7YcnPGJ9Yueam6fIzIIpAqf00+M2SiiuOnej7cavqXI8pSFATi2Y6uAE3ACTsAJOAEnXDnnTl++45JlTYfTVhkq8JMrK+BYhiO7ZDv/KQUBZxycqwlHOmVZgSOZJjL9ySimmlVSKusWjxmP75txBya+wgn4CqdvvInFsvgHZO4AAAAASUVORK5CYII=\" UUID=\"bc2a584b-5149-40cb-83d0-a5e67a69f9a6\"&gt;\n        &lt;layer&gt;08b388db-1b65-4952-8dff-8664adacf4c8&lt;/layer&gt;\n    &lt;/tile&gt;\n    &lt;tile width=\"71\" height=\"96\" name=\"deck_10_1\" fname=\"\" image=\"iVBORw0KGgoAAAANSUhEUgAAAEcAAABgCAYAAABPGW+RAAACbklEQVR42u3dy07EMAwFUH8FS76WBQu+l1UkHoNKH5M0TuI4volHihoQKu2Z6zwqwRDtry9v/+30+vlGgGwhlDXeeXcgWJh+ODvQMjA16el68WXvVPz4d574EQhnv/AzEGUB40cqOg7FuV5QDuR8Idefl01OCZQwTu6dS4GEJFguUSVjTmmSVJNTOqZoAAHPVs8lFy9Bn8qTgzf3ZuRhjOHUJocLVJNu+BVyDqml9JVxkN4IMJzXl8/HOX6PW9u+Bsc5PhKQOAdVnZMPDIhzvaGtLw9chEOM/v0FhSAB1P4m8YCLcWL7HzScbmNOTa23jxOOMwPOVhp7idjAkZ/mJ8KR/z1TlZXENN8FhzLT/tIDcuroOJkbd5ybRZ7jeHIcRwyH0xzHcRzHcWq2AY7Dbsf1Tqq/ME7I9tfFYfR9zFljzCHHacV5e/94NMeJwMT6juM4vJKap7QcR3dAnmfGMoFDqDhlN1mPQ2g4pIxD8+PMA/SE074lqJuxFsFpR1oAp63UzOH0/aNSvMWhIk5dqZnA0W0YCRqEg7HVGIxje6AeiGM/PZA45Dh1YJJHuDFHCwZytlogObKpmSg58jC9wJRx9GAIKzmAMDo4+jAgyQGG6YuDC9M5ORvKGBzjyRmXGk8OfnLG4QAkBxtIabbydQ5jUMYCUlwEjk1QLZjy3soOFMjzHLvT/eBnyOPTZPAZMgepP5Th5NjAMp6ckrGpDxZQcrgLSVkksORw10wdgbD+s/4d0NLJSW1q5cprwuT0AQJPjnx6JklOrr9kcu7SIj84T1JOcukBT85dWQmXFs4nFOWSIry1uH5SkbcjzDcefE+y2QfxkwAAAABJRU5ErkJggg==\" UUID=\"90e8f2f4-80e9-46f3-b56c-f60c072aed88\"&gt;\n        &lt;layer&gt;08b388db-1b65-4952-8dff-8664adacf4c8&lt;/layer&gt;\n    &lt;/tile&gt;\n    &lt;tile width=\"71\" height=\"96\" name=\"deck_11_1\" fname=\"\" image=\"iVBORw0KGgoAAAANSUhEUgAAAEcAAABgCAYAAABPGW+RAAAEb0lEQVR42u2djXLbIBCE9xX7/q+yE7dJo5ifveNAsmPAmWGIZSSF5WO5Q+oUuP/c3uWnZD83kPOV28ft4+NPV/k8p3ndRKA5hflXeoX5EShy/W+BlhAnnRbesa3E6fWTbcRpUWIe221aHR0PHdtJHCWAJ9KWhhwRZh/PKeIcz4S74pxVxOkJBI/2W4kTESht2yeOV04ss7J+kDiWSKpNJzlGGRUJyfllfVb0J8ZQvjilSGeFGbner4tzlUBRYTiTOGnHIiKFhSk8ZyZ6qtWqMuOgOOigAgGhX1IcqxOeQBiYLpiRHNUBTxxPmKhIU4rjEYTGMo2JVqWHiKOEuSIUmEocJRA6hOEkBnypOJZI3mo3rTit3AoNctz8bMLpVUXIZkRriIOGQXNigbLcyugUjbopyOwCNck5BGFjqowKNBU5orAQiBYFUaKmSzxh50xk0GQBnWSqgBCzZeVGg4ocQi7tVKvb2fTi1cXJppgV9DnkTeUzpxJP5TnRLQpMJlDXlsVo9DsrPd37ORY5q2xwhcQ5/EWQIw2ZvfvLk4tjZdUc8Z3VxCEDgV5vh7EiOT9i0dk/7nwSuoQ4X8IYo/7bG+U4/oakPo4/QxyW5FxJg+oMzhbkv49cM8+txA3KKSXbqYt21EoU1QYOKRkxEKKgs07PyzykQY4aCYuArBwdOFt700vcH853NAaJEOKUo6M8h41pQKNDr1ZHiO72nKa3BEd6vg12Y2qpKSVH40HEtKZuzzld98nIKUYb+ZTyycE1y/LZlS5cwq/cpETkzs+W57j1sz0HFxMa2QkMkUNNXzrVeNFIw/pcEnGSaN9zaJtxaMQQHOmB5fxRZI6QwzA5tAV05/oJr7lCkJHV6pznsJOcV4t/GuQw4jm4YvUYXFEUgRWxg5Re4zkq/3nRyHiIHBjOnpFz0V4Mnuwd1zwO9sj5P8Ue3sHfzqnaEXIZCLbJ4cvnSQP0+REydW6VXIwisONxXLRha9+mEQOZ5yf3Ye9CESOnHSGzaMsARewgjPIPFwJRDMbI9U/FOVApRE7G8flLPKOGbF930KNO1SyJFJ9LclkIat/rWxyrY8pz7t+X5/gC6To+6ppKVB2mPA6DOD2QTLNysyEoXz8ZF2OWOkhOuVVqk7NWPUAO3+SMec5KdcBzCJ1jvclxyPHO2cdzkndx+CZHqleRlIu0q+eYr9uubsoBcvLlfC/vCZFD8R7yDqYcJOeebNKMe3YmhzByLCxLkEMOhYpOxLygQAOeox8Rr+hBIc+pBEFJzJoe1EkOxaq1rgd1eg7u25JoZe2cnqB4hGz8qz3lOat4kElOusdamnH94jaL5HQN73HJ8YjZwXsqciAeXag4pySK1feLes79uU/+mdZe8qIBofAcVp5D+eDN9qgl45ySmNZyvXryWZAD+YTQowELeEuQHN9zdttkz14kyPZPjVWrfJ68zdMHfztij8cxhuf4qxQ2EaTTc/YSpOE5664+5yLkrd6iiJOD3aeQsX9V/E9F75IJ8xfUiQfRQ/fDAAAAAABJRU5ErkJggg==\" UUID=\"4e0b645a-38fa-425e-bedb-c61c1061f714\"&gt;\n        &lt;layer&gt;08b388db-1b65-4952-8dff-8664adacf4c8&lt;/layer&gt;\n    &lt;/tile&gt;\n    &lt;tile width=\"71\" height=\"96\" name=\"deck_11_2\" fname=\"\" image=\"iVBORw0KGgoAAAANSUhEUgAAAEcAAABgCAYAAABPGW+RAAAEd0lEQVR42u2dC3IbIRBE+w45We5/lS4rieO1+PQMA7uSBchVFNZqP+bRNDOwqQD3n9u7fJfs5wZyvnL7uH18/O4q/65p3jcBNCeYv6UXzDegyP2/AC0BJx0W3rGt4PT6yTZwWioxj+02rI6Gh47tBEcB8CBtacgRMPt4ThHneCbcFeesAqcEdMOvrFRgdoOTArLgpOf2wfHKiWlW1g+Ck5YDjPV9p3KMMgoJyfVlfRb6E2MoH04J6SyYkfv9OJyrAEXBcCY4acMikMJgCs+ZST3VbFWZcRAOOlSBAOiXhGM1wgOEgeGCGZWjGuDB8cBEIU0Jx1MQGtM0JpqVHgJHgbkiFJgKjgKEDjCcxIAvhWNB8ma7aeG0cis0lOPmZxMOrypCNiNaAw4aBs2JAWW5ldEoGnUTyOyAmso5gLAxVEYBTaUcUVgAoqWCqKKmSzxh50xk0GQBnWSqgBCzZeXGCZVyCDm1U81uZ9OLV4eTDTEr6HOUN5XPnEo8ledElygwGaCuJYvR6HdW9XSv51jKWWWBKwTn8BehHGnI7F1fnhyOlVVzxHdWg0MGAr3eBmNF5XzDorN+3LkTugScTzBGr//0QjmOvyGpj+PPgMNSOVeqQTUGZwvy30fumedW4gHlkJLnqZt21AqKOgeOUjLFQEBBZ51el3lIQzmqJywFZOVowNnaG17i+XC+o9FJhIBT9o7yHDaGAY0GvVodUXS35zS9JdjT8y2wG0NLDSnZGw9STGvo9lzT9ZxMOUVvIx9SvnJwzbR8dqYLl/ArN6kicudny3Pc+tmeg4sVGlkJDCmHWn3pUONFPQ3rc6mIk4r2PYe2GYd6DMGeHpjOH6XMEeUwrBzaAN2xfsJrrgAyMlud8xx2KufV4p+GchjxHFwxewzOKEqBlWIHVXqN56j850Uj4yHlwHD2TDkXrcXgyd5xzXawp5z/Q+zhDfzpnKodIZeBYFs5fPk8aUB9foRMnVslN6MI7HgcF+ewtW7TiIHM65PnsHeiiCmnHSGzOJcBFbFDYZR/uABE0Rkj9z8V50ClELkyjs+f8Iwa8vy6gZ7qVM1SkeJzqVwWQO1nfcGxGqY85/59eY0PSNfxXteqRNVgyuMwFKc7kmlWbp4IytdPxmHMUgeVUy6V2spZqx5QDt/KGfOcleqA5xA6x3orx1GOd80+npO8i8O3ciS9Skk5pF09x3zddnVTDignn8738p6QcijeQ97BlIPKuSebNOOenZVDGDkWllWQoxwKik7EvCCgAc/RW8QrelDIcyogKBWzpgd1Kodi1lrXgzo9B/dlSbSydk6voHiEbPyrPeU5q3iQqZx0jbU04/rFbRbJ6Rre4yrHU8wO3lMpB2LrQsU5paJYfb+o59z3ffLPtNaSFw0Iheew8hzKjTfbo5aMc0rFtKbr1ZPPQjmQO4SeGrCAtwSV43vObovs2YsE2fqpMWuV+8nb7D74yxF7bMcYnuPPUtgESKfn7AWk4Tnrzj7nIuSt3qKIKwe7DyFj/ar4n4reJQPzB+Rc+tRfOUIXAAAAAElFTkSuQmCC\" UUID=\"722fa391-4a49-4ddf-b954-4a189cd2f562\"&gt;\n        &lt;layer&gt;08b388db-1b65-4952-8dff-8664adacf4c8&lt;/layer&gt;\n    &lt;/tile&gt;\n    &lt;tile width=\"71\" height=\"96\" name=\"deck_12_1\" fname=\"\" image=\"iVBORw0KGgoAAAANSUhEUgAAAEcAAABgCAYAAABPGW+RAAAD0klEQVR42u3dAXLiMAwFUN+hJ9v7X8XT7MI2wVEkS7IV/E2dmQwFAiWv37IdQknptWxrPdbTsuW81n0tgX7LzjYl6GMR9ttyzqb1ue0n4ZwxmJ0tfq5B7TDkOT8LhMOhSDLM+THT4FhBJBxTwor7p8DxgniTU8KUNWoanOPFF/EPxTkBZfyac0kMRXLg6NtQIGAc9i9Nk2Pe8XypO1IvlUntgcMRa4IRpAmnSExGrTlSM0g0LcamJfVWl1rEAEHhqAO08rayiRkeV8VBrznJWT+8OLZuPOPVnNTS80TioNac1FFgLbXHOpeCSw5XDyLGLS4cJjHDaw43jrkDyJacjDXOqY0/rDPtmOSA1hztMEIEkC85YOOcWvOqNbNeHK1JwYxzuO7VUqRb65PWS8HNrSxzoAgcS2Ig51Zcr9UDxE4ZKjUGNjlhg0JlMmlNDOzxnFYgORnZVGPgk9MCdG4yqTsxeYZjyK7u2pUQ2/3wB9hNBTmoxkxzDPlYtYGgC8SXIGycJAPpxbc9MVA15/v7j7hu6Wt7Lv8uH6/z+ePjsridbqddP57j5xJ6nFOD4YAeqwVAA9uBoOdWWmLK6xyMJzE0OY/r1yYFjlP7S7eCSNCXmpMnSg7dsZYmVLvOwcDiWJLQUoSl+3Oqnxc4cID3KrB7LxRRUzyA2kmTw86esHTP+/Z3JQgGRzpmI73wA6ZAikrQ3owhcKTDoWpiyKI9znodBsdyxI6OQ063lStFciaIdgBDcbSZNd1RFqbc0UqSPIkZjiO99UJxyp3kmhJNTQ2p1tvB4GgnTVOccidZHOMi1aQhONLnBixndnI4aoocSBrMrThWGK3mWJLQArU3s7fjpKSfRmJ5/8m7sx6kITgShLXOtOJ4kMre7204ckKu90Unx1S8CYwGFIajwbS8Kde7WD9YdhtOvaa8YLynsUXg9NadLpx6LTnDaG/kW8Y574TpwmmF+b/NDkQv2z8i1PaRor4PwTaMclthcvWM8kiUoMFtX43xwtDziO+AipgSsTj3NCUZRqtVMMkZDSMNDXrWEBxEGO13aM0zFGdmGLlZ3oAzK8y5FQTgpMovmRUmsCCvxKg4C0bAWTCVmrNg1N5qwYjJWTDi9GHBqF35glFwfjtMZRC4YIRBIBYMDA4iDAROFMynpIaZlWPBAOEsGHNyRsOA4SwYNTkIMIA4ODD8cw/EQYKJelPuHpwFI+AAwIxuTjzOghFwgGDgcJASg5ccIJgpcN5fY/KG9r98kvfsijth4HFGwESernbjYdKxMLA4C0b5vpkFc4VZX+EkfIXTX0VYUj6lwmaOAAAAAElFTkSuQmCC\" UUID=\"e2ca4158-d3ec-468b-9afd-316d2e160587\"&gt;\n        &lt;layer&gt;08b388db-1b65-4952-8dff-8664adacf4c8&lt;/layer&gt;\n    &lt;/tile&gt;\n    &lt;tile width=\"71\" height=\"96\" name=\"deck_12_2\" fname=\"\" image=\"iVBORw0KGgoAAAANSUhEUgAAAEcAAABgCAYAAABPGW+RAAAD00lEQVR42u3dDXLjIAwFYO7Qk+39r8LUu8nWDhYSEiDCI8UzTJqfpvVX8QDHaUJ4bcduV7ttR4y7nS0F+i0721RBH4tw3hZjNLXnYz8J547B7GzydQnqhCHP+VkgHA5FkmHu37MMjhVEwjFVWHL/Eji1ILWVk8KkGbUMzvXLJ+XvinMDiviZk1UMRarA0R9DgYBx2L80rRzzjscsd6RRKpLsgcMRM8EI0oSTVExEzRypGwRaLcauJY1WWRYxQFA46gQtvS3tYobvK+KgZ06ozI9aHNswHvEyJ7SMPJ44qJkTOgLWkj3WtRRc5XB54DFvqcJhKmZ65nDzmBFAtsqJWPOc0vzDutL2qRzQzNEOI3gA1VUO2Dyn1L1K3awXR+tSMPMcbni1hHRrPmmjFNzayrIG8sCxVAzk2oobtXqA2CVDIWNgK8dtUqgsJq0VA3s8pxVIroxoyhj4ymkBuneZ0F0xcYVjyFXDdVWF2O6HP8BuCmSnjFnmGPLVtIlgFUhdBWHjBBlID9/2ioHKnO/vP2I7wtfx3P5dPn7P55ePy+R2+jjt+vUcP5fQ85wSDAf0aBYADewEgl5baRWTXudgaiqGVs7jet6lwHFKf+lWEAk6y5y4UOVQoJYuVLrOwcDilP7SafOqoBjK5wVOnOC9AvbcYWl0ubrVz3a7raOCtJMmp509YRmeM4S0pfc3VhAMjnTMppQxGUz6OEMlSWBnN4bAkQ6HmirmpvDF4mRIChAMjuWInZYxNxzDRp+XVgwEjraypjsiZkzjRjMJBkd66YXi0KE660IdOOnzw+BoJ01TnHQnWJxOqCk40vsGLGd2cjhZFTngSDBDcawwWuZYMkMM6A6YYTgh6KeRWF5/agpXJ5ghOBKENWdacWqQ0tHvbThyheT3eVdOMbwFmLdljgbT8qKcxxBtacNwypnygqk9jc0DZ2ogl7PkDqO9kG+Z57wTpgunFeb/Y04getn+FqG2txT1vQm2YZbbChOLZ5R7ojhNbvsyphaGnkc8AspjScTijOlKMoyWVTCVMxtGmhr0NBccRBjtZ2jd0xVnZRi5Ww7AWRXm3gsccELhh6wK4xjIu2JUnA0j4GyYQuZsGHW02jBi5WwYcfmwYdShfMMoOL8dpjAJ3DDCJBALBgYHEQYCxwvmU6qGWZVjwQDhbBhz5cyGAcPZMGrlIMAA4uDA8M89EQcJxutFuTE4G0bAAYCZ3Z14nA0j4ADBwOEgVQxe5QDBLIHz/oyJB9r/8gm1Z1eMhIHHmQHjebrawMOkc2FgcTaM8nkzGyaH2R/hJHyE01/m3WJpyJD2mQAAAABJRU5ErkJggg==\" UUID=\"b4d443c9-6606-44df-a294-a3a78e57bad2\"&gt;\n        &lt;layer&gt;08b388db-1b65-4952-8dff-8664adacf4c8&lt;/layer&gt;\n    &lt;/tile&gt;\n&lt;/tilemap&gt;\n</value>\n        </entry>\n        <entry>\n            <key>editor.models.ProjectModel</key>\n            <value>&lt;?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?&gt;\n&lt;project name=\"Solitaire\" UUID=\"224afa8d-1775-4831-8127-624b5397024f\"/&gt;\n</value>\n        </entry>\n        <entry>\n            <key>editor.models.TileLayerModel</key>\n            <value>&lt;?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?&gt;\n&lt;layer name=\"hearts\" UUID=\"06be52cc-1d25-46cf-815f-2f47f0d4ae26\"/&gt;\n</value>\n        </entry>\n        <entry>\n            <key>editor.models.TileLayerModel</key>\n            <value>&lt;?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?&gt;\n&lt;layer name=\"clubs\" UUID=\"41e4ef0d-8383-4cc2-a31f-01041591ab40\"/&gt;\n</value>\n        </entry>\n        <entry>\n            <key>editor.models.TileLayerModel</key>\n            <value>&lt;?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?&gt;\n&lt;layer name=\"diamonds\" UUID=\"b0785b21-2e95-4eb0-8e4d-73f9748013fe\"/&gt;\n</value>\n        </entry>\n        <entry>\n            <key>editor.models.TileLayerModel</key>\n            <value>&lt;?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?&gt;\n&lt;layer name=\"spades\" UUID=\"69229e15-6b70-464b-806b-8897329438a2\"/&gt;\n</value>\n        </entry>\n        <entry>\n            <key>editor.models.TileLayerModel</key>\n            <value>&lt;?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?&gt;\n&lt;layer name=\"misc\" UUID=\"69229e15-6b70-464b-806b-889732943899\"/&gt;\n</value>\n        </entry>\n        <entry>\n            <key>editor.models.TileLayerModel</key>\n            <value>&lt;?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?&gt;\n&lt;layer name=\"backsides\" UUID=\"040cb294-c4ad-47a5-abbb-6a7c8d1f3482\"/&gt;\n</value>\n        </entry>\n        <entry>\n            <key>editor.models.TileLayerModel</key>\n            <value>&lt;?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?&gt;\n&lt;layer name=\"animations\" UUID=\"08b388db-1b65-4952-8dff-8664adacf4c8\"/&gt;\n</value>\n        </entry>\n    </data>\n</root>\n\n"
  },
  {
    "path": "assets/initial requirements.txt",
    "content": "Solitaire Requirements\r\n\r\n- Solitaire window icon\r\n- Game Menu (Deal F2 | Undo, Deck..., Options... | Exit)\r\n- Help Menu (About Solitaire)\r\n- Clicking on deal should start a new Game\r\n- Click on undo should undo the last move played\r\n- Display the number of cards remaining on the stack\r\n- Deck should display a list of predefined deck images\r\n- Clicking on Options should display the options window\r\n- Options window - draw one\r\n- Options window - draw three\r\n- Scoring - Standard\r\n- Scoring - Vegas\r\n- Scoring - None\r\n- There should be a way to display information at the botton of the Game\r\n- Timed game toggle display\r\n- Status bar on/off\r\n- Outline dragging on/off\r\n- Support for dragging a card and detecting edge hit\r\n- Support for dragging a card and the card image follows the mouse\r\n- When double clicking on a card, if there is a move it should perform it\r\n- When there are no more moves left to make, the game should be over\r\n- Game over\r\n- Game win animation\r\n- The game should support music and sound effects"
  },
  {
    "path": "data/generated/tilemap.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n<root>\n    <data>\n        <entry>\n            <key>generated.TileMapData</key>\n            <value>&lt;?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?&gt;\n&lt;root identifier=\"e984a82d-092a-454f-984e-e38606a7f7e5\" name=\"c1\" layers=\"41e4ef0d-8383-4cc2-a31f-01041591ab40\" friendly=\"\" x1=\"0\" y1=\"0\" x2=\"71\" y2=\"96\"/&gt;\n</value>\n        </entry>\n        <entry>\n            <key>generated.TileMapData</key>\n            <value>&lt;?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?&gt;\n&lt;root identifier=\"0adc2583-1a94-48fd-9b6e-b1a141bb76e2\" name=\"c2\" layers=\"41e4ef0d-8383-4cc2-a31f-01041591ab40\" friendly=\"\" x1=\"71\" y1=\"0\" x2=\"142\" y2=\"96\"/&gt;\n</value>\n        </entry>\n        <entry>\n            <key>generated.TileMapData</key>\n            <value>&lt;?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?&gt;\n&lt;root identifier=\"2373e07c-6a5d-404a-bf07-14b2211653f1\" name=\"c3\" layers=\"41e4ef0d-8383-4cc2-a31f-01041591ab40\" friendly=\"\" x1=\"142\" y1=\"0\" x2=\"213\" y2=\"96\"/&gt;\n</value>\n        </entry>\n        <entry>\n            <key>generated.TileMapData</key>\n            <value>&lt;?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?&gt;\n&lt;root identifier=\"92298418-a59d-44df-89c9-7e0c028131f2\" name=\"c4\" layers=\"41e4ef0d-8383-4cc2-a31f-01041591ab40\" friendly=\"\" x1=\"213\" y1=\"0\" x2=\"284\" y2=\"96\"/&gt;\n</value>\n        </entry>\n        <entry>\n            <key>generated.TileMapData</key>\n            <value>&lt;?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?&gt;\n&lt;root identifier=\"76153ba2-26c0-4c1e-8ba4-2b558f948138\" name=\"c5\" layers=\"41e4ef0d-8383-4cc2-a31f-01041591ab40\" friendly=\"\" x1=\"284\" y1=\"0\" x2=\"355\" y2=\"96\"/&gt;\n</value>\n        </entry>\n        <entry>\n            <key>generated.TileMapData</key>\n            <value>&lt;?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?&gt;\n&lt;root identifier=\"dfe50140-8e9c-41cb-b21d-c0af51b78436\" name=\"c6\" layers=\"41e4ef0d-8383-4cc2-a31f-01041591ab40\" friendly=\"\" x1=\"355\" y1=\"0\" x2=\"426\" y2=\"96\"/&gt;\n</value>\n        </entry>\n        <entry>\n            <key>generated.TileMapData</key>\n            <value>&lt;?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?&gt;\n&lt;root identifier=\"fb2435a2-6492-439b-8d34-03e8229a3b8e\" name=\"c7\" layers=\"41e4ef0d-8383-4cc2-a31f-01041591ab40\" friendly=\"\" x1=\"426\" y1=\"0\" x2=\"497\" y2=\"96\"/&gt;\n</value>\n        </entry>\n        <entry>\n            <key>generated.TileMapData</key>\n            <value>&lt;?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?&gt;\n&lt;root identifier=\"0a0ecf52-7060-42f7-9d9d-72ffe26c8907\" name=\"c8\" layers=\"41e4ef0d-8383-4cc2-a31f-01041591ab40\" friendly=\"\" x1=\"497\" y1=\"0\" x2=\"568\" y2=\"96\"/&gt;\n</value>\n        </entry>\n        <entry>\n            <key>generated.TileMapData</key>\n            <value>&lt;?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?&gt;\n&lt;root identifier=\"7a84e376-6c0d-4ba6-a27f-adcf2a41476f\" name=\"c9\" layers=\"41e4ef0d-8383-4cc2-a31f-01041591ab40\" friendly=\"\" x1=\"568\" y1=\"0\" x2=\"639\" y2=\"96\"/&gt;\n</value>\n        </entry>\n        <entry>\n            <key>generated.TileMapData</key>\n            <value>&lt;?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?&gt;\n&lt;root identifier=\"f690e1b0-3c1b-4fd4-8754-09d5823bc76a\" name=\"c10\" layers=\"41e4ef0d-8383-4cc2-a31f-01041591ab40\" friendly=\"\" x1=\"639\" y1=\"0\" x2=\"710\" y2=\"96\"/&gt;\n</value>\n        </entry>\n        <entry>\n            <key>generated.TileMapData</key>\n            <value>&lt;?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?&gt;\n&lt;root identifier=\"ab0658dd-6958-4503-85ae-380dd54ec310\" name=\"c11\" layers=\"41e4ef0d-8383-4cc2-a31f-01041591ab40\" friendly=\"\" x1=\"710\" y1=\"0\" x2=\"781\" y2=\"96\"/&gt;\n</value>\n        </entry>\n        <entry>\n            <key>generated.TileMapData</key>\n            <value>&lt;?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?&gt;\n&lt;root identifier=\"58d2569a-ebd9-4049-b662-7c2dd68968c9\" name=\"c12\" layers=\"41e4ef0d-8383-4cc2-a31f-01041591ab40\" friendly=\"\" x1=\"781\" y1=\"0\" x2=\"852\" y2=\"96\"/&gt;\n</value>\n        </entry>\n        <entry>\n            <key>generated.TileMapData</key>\n            <value>&lt;?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?&gt;\n&lt;root identifier=\"9a666fae-7f67-4afa-8c4d-142d62c782d2\" name=\"c13\" layers=\"41e4ef0d-8383-4cc2-a31f-01041591ab40\" friendly=\"\" x1=\"852\" y1=\"0\" x2=\"923\" y2=\"96\"/&gt;\n</value>\n        </entry>\n        <entry>\n            <key>generated.TileMapData</key>\n            <value>&lt;?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?&gt;\n&lt;root identifier=\"d59b8ca9-5fa0-4f46-b7ac-93869a30117a\" name=\"d1\" layers=\"b0785b21-2e95-4eb0-8e4d-73f9748013fe\" friendly=\"\" x1=\"0\" y1=\"96\" x2=\"71\" y2=\"192\"/&gt;\n</value>\n        </entry>\n        <entry>\n            <key>generated.TileMapData</key>\n            <value>&lt;?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?&gt;\n&lt;root identifier=\"9ec05b58-89fb-4689-b800-175cc034fab1\" name=\"d2\" layers=\"b0785b21-2e95-4eb0-8e4d-73f9748013fe\" friendly=\"\" x1=\"71\" y1=\"96\" x2=\"142\" y2=\"192\"/&gt;\n</value>\n        </entry>\n        <entry>\n            <key>generated.TileMapData</key>\n            <value>&lt;?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?&gt;\n&lt;root identifier=\"d972f5c7-687b-4f65-aa17-f297ba99bc0e\" name=\"d3\" layers=\"b0785b21-2e95-4eb0-8e4d-73f9748013fe\" friendly=\"\" x1=\"142\" y1=\"96\" x2=\"213\" y2=\"192\"/&gt;\n</value>\n        </entry>\n        <entry>\n            <key>generated.TileMapData</key>\n            <value>&lt;?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?&gt;\n&lt;root identifier=\"4f89e5ae-3554-4465-a6df-c409b5030fa2\" name=\"d4\" layers=\"b0785b21-2e95-4eb0-8e4d-73f9748013fe\" friendly=\"\" x1=\"213\" y1=\"96\" x2=\"284\" y2=\"192\"/&gt;\n</value>\n        </entry>\n        <entry>\n            <key>generated.TileMapData</key>\n            <value>&lt;?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?&gt;\n&lt;root identifier=\"0b1e1a44-f5c7-4fc7-b1b3-1ea0fbfae73a\" name=\"d5\" layers=\"b0785b21-2e95-4eb0-8e4d-73f9748013fe\" friendly=\"\" x1=\"284\" y1=\"96\" x2=\"355\" y2=\"192\"/&gt;\n</value>\n        </entry>\n        <entry>\n            <key>generated.TileMapData</key>\n            <value>&lt;?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?&gt;\n&lt;root identifier=\"a8f33327-dfbd-4989-805d-88847490ff20\" name=\"d6\" layers=\"b0785b21-2e95-4eb0-8e4d-73f9748013fe\" friendly=\"\" x1=\"355\" y1=\"96\" x2=\"426\" y2=\"192\"/&gt;\n</value>\n        </entry>\n        <entry>\n            <key>generated.TileMapData</key>\n            <value>&lt;?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?&gt;\n&lt;root identifier=\"3ab272fa-f8cd-4c54-8c75-16ce3b5361c9\" name=\"d7\" layers=\"b0785b21-2e95-4eb0-8e4d-73f9748013fe\" friendly=\"\" x1=\"426\" y1=\"96\" x2=\"497\" y2=\"192\"/&gt;\n</value>\n        </entry>\n        <entry>\n            <key>generated.TileMapData</key>\n            <value>&lt;?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?&gt;\n&lt;root identifier=\"61c0327c-0e96-4893-8dc1-4692e046bb6b\" name=\"d8\" layers=\"b0785b21-2e95-4eb0-8e4d-73f9748013fe\" friendly=\"\" x1=\"497\" y1=\"96\" x2=\"568\" y2=\"192\"/&gt;\n</value>\n        </entry>\n        <entry>\n            <key>generated.TileMapData</key>\n            <value>&lt;?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?&gt;\n&lt;root identifier=\"44672b8c-c9c1-434d-803a-fca1b30ec92b\" name=\"d9\" layers=\"b0785b21-2e95-4eb0-8e4d-73f9748013fe\" friendly=\"\" x1=\"568\" y1=\"96\" x2=\"639\" y2=\"192\"/&gt;\n</value>\n        </entry>\n        <entry>\n            <key>generated.TileMapData</key>\n            <value>&lt;?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?&gt;\n&lt;root identifier=\"29e7d023-9cf2-4776-beef-5f390a6fbc59\" name=\"d10\" layers=\"b0785b21-2e95-4eb0-8e4d-73f9748013fe\" friendly=\"\" x1=\"639\" y1=\"96\" x2=\"710\" y2=\"192\"/&gt;\n</value>\n        </entry>\n        <entry>\n            <key>generated.TileMapData</key>\n            <value>&lt;?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?&gt;\n&lt;root identifier=\"a582dd25-9a24-46c2-ba98-1927e3e55ac5\" name=\"d11\" layers=\"b0785b21-2e95-4eb0-8e4d-73f9748013fe\" friendly=\"\" x1=\"710\" y1=\"96\" x2=\"781\" y2=\"192\"/&gt;\n</value>\n        </entry>\n        <entry>\n            <key>generated.TileMapData</key>\n            <value>&lt;?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?&gt;\n&lt;root identifier=\"ad1b28a4-61a9-4451-9759-9565cd7b0626\" name=\"d12\" layers=\"b0785b21-2e95-4eb0-8e4d-73f9748013fe\" friendly=\"\" x1=\"781\" y1=\"96\" x2=\"852\" y2=\"192\"/&gt;\n</value>\n        </entry>\n        <entry>\n            <key>generated.TileMapData</key>\n            <value>&lt;?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?&gt;\n&lt;root identifier=\"6e1a2bea-c6fd-4ec0-a800-8d65fd038674\" name=\"d13\" layers=\"b0785b21-2e95-4eb0-8e4d-73f9748013fe\" friendly=\"\" x1=\"852\" y1=\"96\" x2=\"923\" y2=\"192\"/&gt;\n</value>\n        </entry>\n        <entry>\n            <key>generated.TileMapData</key>\n            <value>&lt;?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?&gt;\n&lt;root identifier=\"2cc80226-f795-45e4-8c85-4f9acf7a1fb1\" name=\"h1\" layers=\"06be52cc-1d25-46cf-815f-2f47f0d4ae26\" friendly=\"\" x1=\"0\" y1=\"192\" x2=\"71\" y2=\"288\"/&gt;\n</value>\n        </entry>\n        <entry>\n            <key>generated.TileMapData</key>\n            <value>&lt;?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?&gt;\n&lt;root identifier=\"879ae6f3-950e-44a0-82c5-4752e957c1b7\" name=\"h2\" layers=\"06be52cc-1d25-46cf-815f-2f47f0d4ae26\" friendly=\"\" x1=\"71\" y1=\"192\" x2=\"142\" y2=\"288\"/&gt;\n</value>\n        </entry>\n        <entry>\n            <key>generated.TileMapData</key>\n            <value>&lt;?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?&gt;\n&lt;root identifier=\"d110f5d3-a456-4a14-a48a-33d03703e205\" name=\"h3\" layers=\"06be52cc-1d25-46cf-815f-2f47f0d4ae26\" friendly=\"\" x1=\"142\" y1=\"192\" x2=\"213\" y2=\"288\"/&gt;\n</value>\n        </entry>\n        <entry>\n            <key>generated.TileMapData</key>\n            <value>&lt;?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?&gt;\n&lt;root identifier=\"956d7658-3fc6-4422-84ae-2c0027e416e2\" name=\"h4\" layers=\"06be52cc-1d25-46cf-815f-2f47f0d4ae26\" friendly=\"\" x1=\"213\" y1=\"192\" x2=\"284\" y2=\"288\"/&gt;\n</value>\n        </entry>\n        <entry>\n            <key>generated.TileMapData</key>\n            <value>&lt;?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?&gt;\n&lt;root identifier=\"1be5f51f-7a2a-4d0b-8100-ad3343f796f5\" name=\"h5\" layers=\"06be52cc-1d25-46cf-815f-2f47f0d4ae26\" friendly=\"\" x1=\"284\" y1=\"192\" x2=\"355\" y2=\"288\"/&gt;\n</value>\n        </entry>\n        <entry>\n            <key>generated.TileMapData</key>\n            <value>&lt;?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?&gt;\n&lt;root identifier=\"1fbbdf52-331a-47f7-8d1e-e84398cefda8\" name=\"h6\" layers=\"06be52cc-1d25-46cf-815f-2f47f0d4ae26\" friendly=\"\" x1=\"355\" y1=\"192\" x2=\"426\" y2=\"288\"/&gt;\n</value>\n        </entry>\n        <entry>\n            <key>generated.TileMapData</key>\n            <value>&lt;?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?&gt;\n&lt;root identifier=\"53fe97cb-710f-4630-9c1c-8cdc03c77212\" name=\"h7\" layers=\"06be52cc-1d25-46cf-815f-2f47f0d4ae26\" friendly=\"\" x1=\"426\" y1=\"192\" x2=\"497\" y2=\"288\"/&gt;\n</value>\n        </entry>\n        <entry>\n            <key>generated.TileMapData</key>\n            <value>&lt;?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?&gt;\n&lt;root identifier=\"298a41cf-2be4-422a-9b59-f1aadc41f48e\" name=\"h8\" layers=\"06be52cc-1d25-46cf-815f-2f47f0d4ae26\" friendly=\"\" x1=\"497\" y1=\"192\" x2=\"568\" y2=\"288\"/&gt;\n</value>\n        </entry>\n        <entry>\n            <key>generated.TileMapData</key>\n            <value>&lt;?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?&gt;\n&lt;root identifier=\"db19c7f8-44d0-4e03-a848-747a3a31da9c\" name=\"h9\" layers=\"06be52cc-1d25-46cf-815f-2f47f0d4ae26\" friendly=\"\" x1=\"568\" y1=\"192\" x2=\"639\" y2=\"288\"/&gt;\n</value>\n        </entry>\n        <entry>\n            <key>generated.TileMapData</key>\n            <value>&lt;?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?&gt;\n&lt;root identifier=\"934f6d8b-bbbe-43b1-a28d-913c5c80fef9\" name=\"h10\" layers=\"06be52cc-1d25-46cf-815f-2f47f0d4ae26\" friendly=\"\" x1=\"639\" y1=\"192\" x2=\"710\" y2=\"288\"/&gt;\n</value>\n        </entry>\n        <entry>\n            <key>generated.TileMapData</key>\n            <value>&lt;?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?&gt;\n&lt;root identifier=\"7c588781-b5d9-493c-86dc-6b383cc33098\" name=\"h11\" layers=\"06be52cc-1d25-46cf-815f-2f47f0d4ae26\" friendly=\"\" x1=\"710\" y1=\"192\" x2=\"781\" y2=\"288\"/&gt;\n</value>\n        </entry>\n        <entry>\n            <key>generated.TileMapData</key>\n            <value>&lt;?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?&gt;\n&lt;root identifier=\"0d75364f-a431-41dc-9a23-75b0e200ffce\" name=\"h12\" layers=\"06be52cc-1d25-46cf-815f-2f47f0d4ae26\" friendly=\"\" x1=\"781\" y1=\"192\" x2=\"852\" y2=\"288\"/&gt;\n</value>\n        </entry>\n        <entry>\n            <key>generated.TileMapData</key>\n            <value>&lt;?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?&gt;\n&lt;root identifier=\"a3397bc9-187c-461a-b336-7059f6b8eadc\" name=\"h13\" layers=\"06be52cc-1d25-46cf-815f-2f47f0d4ae26\" friendly=\"\" x1=\"852\" y1=\"192\" x2=\"923\" y2=\"288\"/&gt;\n</value>\n        </entry>\n        <entry>\n            <key>generated.TileMapData</key>\n            <value>&lt;?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?&gt;\n&lt;root identifier=\"a4e9de58-b1c8-4a46-8b60-71c4c6a463c9\" name=\"s1\" layers=\"69229e15-6b70-464b-806b-8897329438a2\" friendly=\"\" x1=\"0\" y1=\"288\" x2=\"71\" y2=\"384\"/&gt;\n</value>\n        </entry>\n        <entry>\n            <key>generated.TileMapData</key>\n            <value>&lt;?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?&gt;\n&lt;root identifier=\"0db5fd69-a18f-4024-8a6b-b33b1514ebac\" name=\"s2\" layers=\"69229e15-6b70-464b-806b-8897329438a2\" friendly=\"\" x1=\"71\" y1=\"288\" x2=\"142\" y2=\"384\"/&gt;\n</value>\n        </entry>\n        <entry>\n            <key>generated.TileMapData</key>\n            <value>&lt;?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?&gt;\n&lt;root identifier=\"7abd8566-d1ef-40a6-95e3-7079a77155df\" name=\"s3\" layers=\"69229e15-6b70-464b-806b-8897329438a2\" friendly=\"\" x1=\"142\" y1=\"288\" x2=\"213\" y2=\"384\"/&gt;\n</value>\n        </entry>\n        <entry>\n            <key>generated.TileMapData</key>\n            <value>&lt;?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?&gt;\n&lt;root identifier=\"646ab72c-9789-4271-8fa9-e8d416c0dde2\" name=\"s4\" layers=\"69229e15-6b70-464b-806b-8897329438a2\" friendly=\"\" x1=\"213\" y1=\"288\" x2=\"284\" y2=\"384\"/&gt;\n</value>\n        </entry>\n        <entry>\n            <key>generated.TileMapData</key>\n            <value>&lt;?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?&gt;\n&lt;root identifier=\"635bb570-ae3b-4789-b519-1e2bde2efd2f\" name=\"s5\" layers=\"69229e15-6b70-464b-806b-8897329438a2\" friendly=\"\" x1=\"284\" y1=\"288\" x2=\"355\" y2=\"384\"/&gt;\n</value>\n        </entry>\n        <entry>\n            <key>generated.TileMapData</key>\n            <value>&lt;?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?&gt;\n&lt;root identifier=\"8bb9387c-1e83-47b5-916c-d606cd68dec3\" name=\"s6\" layers=\"69229e15-6b70-464b-806b-8897329438a2\" friendly=\"\" x1=\"355\" y1=\"288\" x2=\"426\" y2=\"384\"/&gt;\n</value>\n        </entry>\n        <entry>\n            <key>generated.TileMapData</key>\n            <value>&lt;?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?&gt;\n&lt;root identifier=\"481c9b0a-76b8-43d0-add7-e76075b61a9b\" name=\"s7\" layers=\"69229e15-6b70-464b-806b-8897329438a2\" friendly=\"\" x1=\"426\" y1=\"288\" x2=\"497\" y2=\"384\"/&gt;\n</value>\n        </entry>\n        <entry>\n            <key>generated.TileMapData</key>\n            <value>&lt;?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?&gt;\n&lt;root identifier=\"6d452f50-9a23-43ed-afa2-0dfaf51b9847\" name=\"s8\" layers=\"69229e15-6b70-464b-806b-8897329438a2\" friendly=\"\" x1=\"497\" y1=\"288\" x2=\"568\" y2=\"384\"/&gt;\n</value>\n        </entry>\n        <entry>\n            <key>generated.TileMapData</key>\n            <value>&lt;?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?&gt;\n&lt;root identifier=\"7e1e4dc6-176a-4a3f-82c8-1079d5662375\" name=\"s9\" layers=\"69229e15-6b70-464b-806b-8897329438a2\" friendly=\"\" x1=\"568\" y1=\"288\" x2=\"639\" y2=\"384\"/&gt;\n</value>\n        </entry>\n        <entry>\n            <key>generated.TileMapData</key>\n            <value>&lt;?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?&gt;\n&lt;root identifier=\"9aad43f8-e1fd-49a8-9f80-e533bc9e57d9\" name=\"s10\" layers=\"69229e15-6b70-464b-806b-8897329438a2\" friendly=\"\" x1=\"639\" y1=\"288\" x2=\"710\" y2=\"384\"/&gt;\n</value>\n        </entry>\n        <entry>\n            <key>generated.TileMapData</key>\n            <value>&lt;?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?&gt;\n&lt;root identifier=\"c90327e4-cd6e-4dde-83c2-1723739225f4\" name=\"s11\" layers=\"69229e15-6b70-464b-806b-8897329438a2\" friendly=\"\" x1=\"710\" y1=\"288\" x2=\"781\" y2=\"384\"/&gt;\n</value>\n        </entry>\n        <entry>\n            <key>generated.TileMapData</key>\n            <value>&lt;?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?&gt;\n&lt;root identifier=\"3b7a097a-c1f4-4190-ae55-d189a19978c6\" name=\"s12\" layers=\"69229e15-6b70-464b-806b-8897329438a2\" friendly=\"\" x1=\"781\" y1=\"288\" x2=\"852\" y2=\"384\"/&gt;\n</value>\n        </entry>\n        <entry>\n            <key>generated.TileMapData</key>\n            <value>&lt;?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?&gt;\n&lt;root identifier=\"00d3d8c0-a9d7-464e-a4fd-14c23f94184b\" name=\"s13\" layers=\"69229e15-6b70-464b-806b-8897329438a2\" friendly=\"\" x1=\"852\" y1=\"288\" x2=\"923\" y2=\"384\"/&gt;\n</value>\n        </entry>\n        <entry>\n            <key>generated.TileMapData</key>\n            <value>&lt;?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?&gt;\n&lt;root identifier=\"c89dfa47-5c49-4c56-836b-19b7dd6e5651\" name=\"deck_1\" layers=\"040cb294-c4ad-47a5-abbb-6a7c8d1f3482\" friendly=\"\" x1=\"923\" y1=\"0\" x2=\"994\" y2=\"96\"/&gt;\n</value>\n        </entry>\n        <entry>\n            <key>generated.TileMapData</key>\n            <value>&lt;?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?&gt;\n&lt;root identifier=\"9e231907-746e-466c-b50d-1eb3db576f7f\" name=\"deck_2\" layers=\"040cb294-c4ad-47a5-abbb-6a7c8d1f3482\" friendly=\"\" x1=\"994\" y1=\"0\" x2=\"1065\" y2=\"96\"/&gt;\n</value>\n        </entry>\n        <entry>\n            <key>generated.TileMapData</key>\n            <value>&lt;?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?&gt;\n&lt;root identifier=\"492b2a75-4ed9-431b-9c7f-c93330a33eb6\" name=\"deck_3\" layers=\"040cb294-c4ad-47a5-abbb-6a7c8d1f3482\" friendly=\"\" x1=\"1065\" y1=\"0\" x2=\"1136\" y2=\"96\"/&gt;\n</value>\n        </entry>\n        <entry>\n            <key>generated.TileMapData</key>\n            <value>&lt;?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?&gt;\n&lt;root identifier=\"e98cff41-88ec-47b0-bbd5-e684c97dc483\" name=\"deck_4\" layers=\"040cb294-c4ad-47a5-abbb-6a7c8d1f3482\" friendly=\"\" x1=\"1136\" y1=\"0\" x2=\"1207\" y2=\"96\"/&gt;\n</value>\n        </entry>\n        <entry>\n            <key>generated.TileMapData</key>\n            <value>&lt;?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?&gt;\n&lt;root identifier=\"c6c3c2d2-620d-4fdd-9fce-bc6190817c12\" name=\"deck_5\" layers=\"040cb294-c4ad-47a5-abbb-6a7c8d1f3482\" friendly=\"\" x1=\"1207\" y1=\"0\" x2=\"1278\" y2=\"96\"/&gt;\n</value>\n        </entry>\n        <entry>\n            <key>generated.TileMapData</key>\n            <value>&lt;?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?&gt;\n&lt;root identifier=\"b38f68aa-20ee-4be7-9840-136b838f7d8f\" name=\"deck_6\" layers=\"040cb294-c4ad-47a5-abbb-6a7c8d1f3482\" friendly=\"\" x1=\"1278\" y1=\"0\" x2=\"1349\" y2=\"96\"/&gt;\n</value>\n        </entry>\n        <entry>\n            <key>generated.TileMapData</key>\n            <value>&lt;?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?&gt;\n&lt;root identifier=\"8c8ed8dd-8d4e-4c70-a267-ba27d105b572\" name=\"deck_7\" layers=\"040cb294-c4ad-47a5-abbb-6a7c8d1f3482\" friendly=\"\" x1=\"1349\" y1=\"0\" x2=\"1420\" y2=\"96\"/&gt;\n</value>\n        </entry>\n        <entry>\n            <key>generated.TileMapData</key>\n            <value>&lt;?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?&gt;\n&lt;root identifier=\"a4ea2b81-8403-4b5a-8413-e54da2e9b147\" name=\"deck_8\" layers=\"040cb294-c4ad-47a5-abbb-6a7c8d1f3482\" friendly=\"\" x1=\"1420\" y1=\"0\" x2=\"1491\" y2=\"96\"/&gt;\n</value>\n        </entry>\n        <entry>\n            <key>generated.TileMapData</key>\n            <value>&lt;?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?&gt;\n&lt;root identifier=\"0e995a0b-0ab6-42e7-9ed9-d4900cfbe304\" name=\"deck_9\" layers=\"040cb294-c4ad-47a5-abbb-6a7c8d1f3482\" friendly=\"\" x1=\"1491\" y1=\"0\" x2=\"1562\" y2=\"96\"/&gt;\n</value>\n        </entry>\n        <entry>\n            <key>generated.TileMapData</key>\n            <value>&lt;?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?&gt;\n&lt;root identifier=\"25000197-ea3d-4912-9e83-cddddaf0d7dd\" name=\"deck_10\" layers=\"040cb294-c4ad-47a5-abbb-6a7c8d1f3482\" friendly=\"\" x1=\"1562\" y1=\"0\" x2=\"1633\" y2=\"96\"/&gt;\n</value>\n        </entry>\n        <entry>\n            <key>generated.TileMapData</key>\n            <value>&lt;?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?&gt;\n&lt;root identifier=\"25000198-ea3d-4912-9e83-cddddaf0d7dd\" name=\"deck_11\" layers=\"040cb294-c4ad-47a5-abbb-6a7c8d1f3482\" friendly=\"\" x1=\"1633\" y1=\"0\" x2=\"1704\" y2=\"96\"/&gt;\n</value>\n        </entry>\n        <entry>\n            <key>generated.TileMapData</key>\n            <value>&lt;?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?&gt;\n&lt;root identifier=\"25000199-ea3d-4912-9e83-cddddaf0d7dd\" name=\"deck_12\" layers=\"040cb294-c4ad-47a5-abbb-6a7c8d1f3482\" friendly=\"\" x1=\"1704\" y1=\"0\" x2=\"1775\" y2=\"96\"/&gt;\n</value>\n        </entry>\n        <entry>\n            <key>generated.TileMapData</key>\n            <value>&lt;?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?&gt;\n&lt;root identifier=\"25000200-ea3d-4912-9e83-cddddaf0d7dd\" name=\"foundation\" layers=\"69229e15-6b70-464b-806b-889732943899\" friendly=\"\" x1=\"1775\" y1=\"0\" x2=\"1846\" y2=\"96\"/&gt;\n</value>\n        </entry>\n        <entry>\n            <key>generated.TileMapData</key>\n            <value>&lt;?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?&gt;\n&lt;root identifier=\"25000200-ea3d-4912-9e83-cddddaf0d7de\" name=\"talon_restart\" layers=\"69229e15-6b70-464b-806b-889732943899\" friendly=\"\" x1=\"1846\" y1=\"0\" x2=\"1917\" y2=\"96\"/&gt;\n</value>\n        </entry>\n        <entry>\n            <key>generated.TileMapData</key>\n            <value>&lt;?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?&gt;\n&lt;root identifier=\"25000200-ea3d-4912-9e83-cddddaf0d7df\" name=\"talon_end\" layers=\"69229e15-6b70-464b-806b-889732943899\" friendly=\"\" x1=\"1917\" y1=\"0\" x2=\"1988\" y2=\"96\"/&gt;\n</value>\n        </entry>\n        <entry>\n            <key>generated.TileMapData</key>\n            <value>&lt;?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?&gt;\n&lt;root identifier=\"8eb12cd0-f6ca-4f8b-9d38-50ec2945dc41\" name=\"backside_empty\" layers=\"69229e15-6b70-464b-806b-889732943899\" friendly=\"\" x1=\"1988\" y1=\"0\" x2=\"2059\" y2=\"96\"/&gt;\n</value>\n        </entry>\n        <entry>\n            <key>generated.TileMapData</key>\n            <value>&lt;?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?&gt;\n&lt;root identifier=\"5a0c5e61-f5b6-4db7-a2a9-405e5fe3c039\" name=\"poker_1\" layers=\"08b388db-1b65-4952-8dff-8664adacf4c8\" friendly=\"\" x1=\"2059\" y1=\"0\" x2=\"2091\" y2=\"22\"/&gt;\n</value>\n        </entry>\n        <entry>\n            <key>generated.TileMapData</key>\n            <value>&lt;?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?&gt;\n&lt;root identifier=\"1a6307f6-0806-496f-9b4f-afbd7cbd7bba\" name=\"poker_2\" layers=\"08b388db-1b65-4952-8dff-8664adacf4c8\" friendly=\"\" x1=\"2091\" y1=\"0\" x2=\"2123\" y2=\"22\"/&gt;\n</value>\n        </entry>\n        <entry>\n            <key>generated.TileMapData</key>\n            <value>&lt;?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?&gt;\n&lt;root identifier=\"b1ea9525-0e4e-4fc8-8a63-55b2bcf77a95\" name=\"castle_0\" layers=\"08b388db-1b65-4952-8dff-8664adacf4c8\" friendly=\"\" x1=\"2123\" y1=\"0\" x2=\"2149\" y2=\"12\"/&gt;\n</value>\n        </entry>\n        <entry>\n            <key>generated.TileMapData</key>\n            <value>&lt;?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?&gt;\n&lt;root identifier=\"1e9ff1c3-ee06-4142-90f5-ec081d91060b\" name=\"robot_0\" layers=\"08b388db-1b65-4952-8dff-8664adacf4c8\" friendly=\"\" x1=\"2149\" y1=\"0\" x2=\"2173\" y2=\"7\"/&gt;\n</value>\n        </entry>\n        <entry>\n            <key>generated.TileMapData</key>\n            <value>&lt;?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?&gt;\n&lt;root identifier=\"2fc57747-aa27-41d5-b348-ed2be68fa384\" name=\"robot_1\" layers=\"08b388db-1b65-4952-8dff-8664adacf4c8\" friendly=\"\" x1=\"2173\" y1=\"0\" x2=\"2197\" y2=\"7\"/&gt;\n</value>\n        </entry>\n        <entry>\n            <key>generated.TileMapData</key>\n            <value>&lt;?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?&gt;\n&lt;root identifier=\"a0531693-d6c6-4c30-98da-00dfe117c8b2\" name=\"sun_0\" layers=\"08b388db-1b65-4952-8dff-8664adacf4c8\" friendly=\"\" x1=\"2197\" y1=\"0\" x2=\"2211\" y2=\"12\"/&gt;\n</value>\n        </entry>\n        <entry>\n            <key>generated.TileMapData</key>\n            <value>&lt;?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?&gt;\n&lt;root identifier=\"9200227b-5948-4d98-b64a-17846b71b717\" name=\"sun_1\" layers=\"08b388db-1b65-4952-8dff-8664adacf4c8\" friendly=\"\" x1=\"2211\" y1=\"0\" x2=\"2225\" y2=\"12\"/&gt;\n</value>\n        </entry>\n        <entry>\n            <key>generated.TileMapData</key>\n            <value>&lt;?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?&gt;\n&lt;root identifier=\"fdf06b20-0845-4acd-9661-9d01d8efee4a\" name=\"deck_7_1\" layers=\"08b388db-1b65-4952-8dff-8664adacf4c8\" friendly=\"\" x1=\"2225\" y1=\"0\" x2=\"2296\" y2=\"96\"/&gt;\n</value>\n        </entry>\n        <entry>\n            <key>generated.TileMapData</key>\n            <value>&lt;?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?&gt;\n&lt;root identifier=\"bc2a584b-5149-40cb-83d0-a5e67a69f9a6\" name=\"deck_7_2\" layers=\"08b388db-1b65-4952-8dff-8664adacf4c8\" friendly=\"\" x1=\"2296\" y1=\"0\" x2=\"2367\" y2=\"96\"/&gt;\n</value>\n        </entry>\n        <entry>\n            <key>generated.TileMapData</key>\n            <value>&lt;?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?&gt;\n&lt;root identifier=\"90e8f2f4-80e9-46f3-b56c-f60c072aed88\" name=\"deck_10_1\" layers=\"08b388db-1b65-4952-8dff-8664adacf4c8\" friendly=\"\" x1=\"2367\" y1=\"0\" x2=\"2438\" y2=\"96\"/&gt;\n</value>\n        </entry>\n        <entry>\n            <key>generated.TileMapData</key>\n            <value>&lt;?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?&gt;\n&lt;root identifier=\"4e0b645a-38fa-425e-bedb-c61c1061f714\" name=\"deck_11_1\" layers=\"08b388db-1b65-4952-8dff-8664adacf4c8\" friendly=\"\" x1=\"2438\" y1=\"0\" x2=\"2509\" y2=\"96\"/&gt;\n</value>\n        </entry>\n        <entry>\n            <key>generated.TileMapData</key>\n            <value>&lt;?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?&gt;\n&lt;root identifier=\"722fa391-4a49-4ddf-b954-4a189cd2f562\" name=\"deck_11_2\" layers=\"08b388db-1b65-4952-8dff-8664adacf4c8\" friendly=\"\" x1=\"2509\" y1=\"0\" x2=\"2580\" y2=\"96\"/&gt;\n</value>\n        </entry>\n        <entry>\n            <key>generated.TileMapData</key>\n            <value>&lt;?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?&gt;\n&lt;root identifier=\"e2ca4158-d3ec-468b-9afd-316d2e160587\" name=\"deck_12_1\" layers=\"08b388db-1b65-4952-8dff-8664adacf4c8\" friendly=\"\" x1=\"2580\" y1=\"0\" x2=\"2651\" y2=\"96\"/&gt;\n</value>\n        </entry>\n        <entry>\n            <key>generated.TileMapData</key>\n            <value>&lt;?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?&gt;\n&lt;root identifier=\"b4d443c9-6606-44df-a294-a3a78e57bad2\" name=\"deck_12_2\" layers=\"08b388db-1b65-4952-8dff-8664adacf4c8\" friendly=\"\" x1=\"2651\" y1=\"0\" x2=\"2722\" y2=\"96\"/&gt;\n</value>\n        </entry>\n    </data>\n</root>\n\n"
  },
  {
    "path": "properties/resources/Localization.csv",
    "content": "key,en_ca\r\nAbout,About Solitaire\r\nAboutMessage,Step into a nostalgic world with this homage to the classic Solitaire from Windows 95. Experience the same addictive gameplay now refined for a flawless journey. Immerse yourself in the timeless charm of this beloved card game brought back to life for new and old players alike.\r\nTitle,Solitaire\r\nGame,Game\r\nGameIcon,content/solitaire_logo.png\r\nGameOver,Deal Again?\r\nGameOverHeader,Solitaire\r\nGitHub,https://github.com/danielricci/solitaire\r\nHelp,Help\r\nDeal,Deal\r\nUndo,Undo\r\nDeck,Deck...\r\nOptions,Options...\r\nExit,Exit\r\nGameWonStatusBar, Bonus: %s  Press Esc or a mouse button to stop...\r\nScoreTitle, Score:"
  },
  {
    "path": "properties/resources/LocalizationStrings.java",
    "content": "/**\r\n * MIT License\r\n * \r\n * Copyright (c) 2019 Daniel Ricci {@literal <thedanny09@icloud.com>}\r\n * \r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"Software\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n * \r\n * The above copyright notice and this permission notice shall be included in all\r\n * copies or substantial portions of the Software.\r\n * \r\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\r\n * SOFTWARE.\r\n */\r\n\r\npackage resources;\r\n\r\n/**\r\n * The list of available keys for localization lookup\r\n * \r\n * @author {@literal Daniel Ricci {@literal <thedanny09@icloud.com>}}\r\n *\r\n */\r\npublic class LocalizationStrings {\r\n     public static String ABOUT = \"About\";\r\n     public static String ABOUT_MESSAGE = \"AboutMessage\";\r\n     public static String TITLE = \"Title\";\r\n     public static String GAME = \"Game\";\r\n     public static String GAME_ICON = \"GameIcon\";\r\n     public static String GAME_OVER = \"GameOver\";\r\n     public static String GAME_OVER_HEADER = \"GameOverHeader\";\r\n     public static String GAME_WON_STATUS_BAR = \"GameWonStatusBar\";\r\n     public static String GITHUB = \"GitHub\";\r\n     public static String HELP = \"Help\";\r\n     public static String DEAL = \"Deal\";\r\n     public static String UNDO = \"Undo\";\r\n     public static String DECK = \"Deck\";\r\n     public static String OPTIONS = \"Options\";\r\n     public static String EXIT = \"Exit\";\r\n     public static String SCORE_TITLE = \"ScoreTitle\";\r\n}"
  },
  {
    "path": "src/game/application/Game.java",
    "content": "package game.application;\r\n\r\nimport java.awt.Dimension;\r\nimport java.awt.EventQueue;\r\nimport java.awt.event.KeyAdapter;\r\nimport java.awt.event.KeyEvent;\r\nimport java.awt.event.WindowEvent;\r\nimport java.io.File;\r\nimport java.util.List;\r\n\r\nimport javax.swing.AbstractButton;\r\nimport javax.swing.UIManager;\r\n\r\nimport framework.core.factories.AbstractFactory;\r\nimport framework.core.factories.ViewFactory;\r\nimport framework.core.navigation.MenuBuilder;\r\nimport framework.core.system.Application;\r\nimport framework.core.system.EngineProperties;\r\nimport framework.core.system.EngineProperties.Property;\r\nimport framework.utils.globalisation.Localization;\r\n\r\nimport game.config.OptionsPreferences;\r\nimport game.menu.AboutMenuItem;\r\nimport game.menu.DeckMenuItem;\r\nimport game.menu.ExitMenuItem;\r\nimport game.menu.GitHubMenuItem;\r\nimport game.menu.NewGameMenuItem;\r\nimport game.menu.OnTopMenuItem;\r\nimport game.menu.OptionsMenuItem;\r\nimport game.menu.UndoMenuItem;\r\nimport game.views.FoundationPileView;\r\nimport game.views.GameView;\r\nimport game.views.TableauPileView;\r\nimport game.views.TalonPileView;\r\nimport game.views.helpers.DeckAnimationHelper;\r\nimport game.views.helpers.WinAnimationHelper;\r\n\r\nimport resources.LocalizationStrings;\r\n\r\n/**\r\n * @author Daniel Ricci {@literal <thedanny09@icloud.com>}\r\n */\r\npublic final class Game extends Application {\r\n\r\n    /**\r\n     * Constructs a new instance of this class type\r\n     * \r\n     * @param isDebug The debug mode flag\r\n     */\r\n    private Game(boolean isDebug) {\r\n        super(isDebug);\r\n        setMinimumSize(new Dimension(620, 436));\r\n        \r\n        OptionsPreferences options = new OptionsPreferences();\r\n        options.load();\r\n        setLocationRelativeTo(null);\r\n        setAlwaysOnTop(options.alwaysOnTop);\r\n        setIconImage(Localization.instance().getLocalizedData(LocalizationStrings.GAME_ICON));\r\n        if(isDebug) {\r\n            addKeyListener(new KeyAdapter() {\r\n                @Override public void keyPressed(KeyEvent event) {\r\n                    ViewFactory viewFactory = AbstractFactory.getFactory(ViewFactory.class);\r\n                    if(event.getKeyCode() == KeyEvent.VK_F1) {\r\n                        event.consume();\r\n                        OptionsPreferences options = new OptionsPreferences();\r\n                        options.load();\r\n                        System.out.println(options);\r\n                        \r\n                        System.out.println(viewFactory.get(TalonPileView.class).toString());\r\n                        \r\n                        List<TableauPileView> pileViews =  viewFactory.getAll(TableauPileView.class);\r\n                        for(int i = pileViews.size() - 1; i >= 0; --i) {\r\n                            System.out.println(pileViews.get(i));\r\n                        }\r\n                        List<FoundationPileView> foundationViews =  viewFactory.getAll(FoundationPileView.class);\r\n                        for(int i = foundationViews.size() - 1; i >= 0; --i) {\r\n                            System.out.println(foundationViews.get(i));\r\n                        }\r\n                    }\r\n                    else if(event.getKeyCode() == KeyEvent.VK_F3) {\r\n                        event.consume();\r\n                        System.out.println(viewFactory.get(TalonPileView.class).toString());\r\n                    }\r\n                }\r\n            });\r\n        }\r\n        \r\n        addKeyListener(new KeyAdapter() {\r\n            @Override public void keyReleased(KeyEvent event) {\r\n                boolean _locked = false;\r\n                \r\n                //Alt + Shift + 2\r\n                if(event.getKeyCode() == KeyEvent.VK_2 && event.getModifiersEx() == (KeyEvent.ALT_DOWN_MASK | KeyEvent.SHIFT_DOWN_MASK)) {\r\n                    if(!_locked) { \r\n                        _locked = true;\r\n                        GameView.forceGameWin();\r\n                        _locked = false;\r\n                    }\r\n                }\r\n            }\r\n        });\r\n    }\r\n    \r\n    /**\r\n     * Main entry-point method\r\n     * \r\n     * @param args The arguments associated to the application entry point\r\n     */\r\n    public static void main(String[] args) {\r\n        EventQueue.invokeLater(new Runnable() {\r\n            @Override public void run() {\r\n                boolean debugMode = false;\r\n                for(String arg : args) {\r\n                    switch(arg.trim()) {\r\n                    case \"debug\": {\r\n                        debugMode = true;\r\n                        break;\r\n                    }\r\n                    }\r\n                }\r\n                \r\n                if(debugMode) {\r\n                    EngineProperties.instance().setProperty(Property.LOG_DIRECTORY,  System.getProperty(\"user.dir\") + File.separator);\r\n                    EngineProperties.instance().setProperty(Property.ENGINE_OUTPUT, Boolean.toString(true));\r\n                    EngineProperties.instance().setProperty(Property.DISPLAY_EXCEPTIONS, Boolean.toString(true));    \r\n                }\r\n                \r\n                EngineProperties.instance().setProperty(Property.DATA_PATH_XML, \"/generated/tilemap.xml\");\r\n                EngineProperties.instance().setProperty(Property.DATA_PATH_SHEET, \"/generated/tilemap.png\");\r\n                EngineProperties.instance().setProperty(Property.LOCALIZATION_PATH_CVS, \"/resources/Localization.csv\");\r\n                EngineProperties.instance().setProperty(Property.SUPPRESS_SIGNAL_REGISTRATION_OUTPUT, Boolean.toString(false));\r\n                EngineProperties.instance().setProperty(Property.DISABLE_TRANSLATIONS_PLACEHOLDER, Boolean.toString(!debugMode));\r\n                \r\n                Game game = new Game(debugMode);\r\n                game.setVisible(true);   \r\n            }\r\n        });\r\n    }\r\n    \r\n    @Override public void onRestart() {\r\n        super.onRestart();\r\n        \r\n        if(AbstractFactory.isRunning()) {\r\n            \r\n            // Clear the factory of it's contents\r\n            AbstractFactory.clearFactories();\r\n            \r\n            // Remove everything from the application UI\r\n            Application.instance.getContentPane().removeAll();\r\n            \r\n            // Indicate that the application is no longer in a restart state\r\n            isRestarting = false;\r\n        }\r\n\r\n        WinAnimationHelper.clear();\r\n        DeckAnimationHelper.getInstance().clear();\r\n        \r\n        // Spawn a new game view and render its contents\r\n        GameView gameView = AbstractFactory.getFactory(ViewFactory.class).add(new GameView(), true);\r\n        instance.setContentPane(gameView);\r\n        gameView.render();\r\n    }\r\n\r\n\r\n    \r\n    @Override public void windowOpened(WindowEvent windowEvent) {\r\n    \tSystem.out.println(\"Window Opened\");    \t\r\n    \tsuper.windowOpened(windowEvent);\r\n    \t\r\n    \t   // Set the title\r\n        setTitle(Localization.instance().getLocalizedString(LocalizationStrings.TITLE));\r\n        \r\n        // Always show mnemonics in the menu system\r\n        UIManager.put(\"Button.showMnemonics\", Boolean.TRUE);\r\n        \r\n        // Game Menu\r\n        MenuBuilder.start(getJMenuBar())\r\n        .addMenu(Localization.instance().getLocalizedString(LocalizationStrings.GAME), KeyEvent.VK_G)\r\n        .addMenuItem(NewGameMenuItem.class)\r\n        .addSeparator()\r\n        .addMenuItem(UndoMenuItem.class)\r\n        .addMenuItem(DeckMenuItem.class)\r\n        .addMenuItem(OptionsMenuItem.class)\r\n        .addSeparator()\r\n        .addMenuItem(ExitMenuItem.class);\r\n                \r\n        // Extras\r\n        MenuBuilder.start(getJMenuBar())\r\n        .addMenu(\"Extras\")\r\n        .addMenuItem(OnTopMenuItem.class);\r\n\r\n        // Help Menu\r\n        MenuBuilder.start(getJMenuBar())\r\n        .addMenu(Localization.instance().getLocalizedString(LocalizationStrings.HELP), KeyEvent.VK_H)\r\n        .addMenuItem(GitHubMenuItem.class)\r\n        .addSeparator()\r\n        .addMenuItem(AboutMenuItem.class);\r\n\r\n        // Perform a new game programmatically\r\n        MenuBuilder.search(getJMenuBar(), NewGameMenuItem.class).getComponent(AbstractButton.class).doClick();\r\n    }\r\n}"
  },
  {
    "path": "src/game/config/OptionsPreferences.java",
    "content": "package game.config;\n\nimport java.util.logging.Level;\n\nimport framework.core.system.GamePreferences;\nimport framework.utils.logging.Tracelog;\n\nimport game.views.OptionsDialogView;\n\nimport generated.DataLookup;\n\npublic final class OptionsPreferences extends GamePreferences {\n\n    public enum DrawOption { ONE, THREE };\n    \n    public enum ScoringOption { STANDARD, VEGAS, NONE };\n    \n    public boolean timedGame;\n    \n    public boolean statusBar;\n    \n    public boolean outlineDragging;\n    \n    public boolean cumulativeScore;\n    \n    public DrawOption drawOption;\n    \n    public ScoringOption scoringOption;\n    \n    public DataLookup.BACKSIDES deck;\n    \n    public boolean alwaysOnTop;\n    \n    public OptionsPreferences() {\n        super(OptionsDialogView.class);\n    }\n\n    @Override public void load() {\n        drawOption = DrawOption.values()[preferences.getInt(\"drawOption\", DrawOption.ONE.ordinal())];\n        scoringOption = ScoringOption.values()[preferences.getInt(\"scoringOption\", ScoringOption.STANDARD.ordinal())];\n        timedGame = preferences.getBoolean(\"timedGame\", false);\n        statusBar = preferences.getBoolean(\"statusBar\", false);\n        outlineDragging = preferences.getBoolean(\"outlineDragging\", false);\n        cumulativeScore = preferences.getBoolean(\"cumulativeScore\", false);\n        deck = DataLookup.BACKSIDES.values()[preferences.getInt(\"deck\", DataLookup.BACKSIDES.DECK_1.ordinal())];\n        alwaysOnTop = preferences.getBoolean(\"alwaysOnTop\", false);\n    }\n\n    @Override public void save() {\n        try {\n            preferences.putInt(\"drawOption\", drawOption.ordinal());\n            preferences.putInt(\"scoringOption\", scoringOption.ordinal());\n            preferences.putBoolean(\"timedGame\", timedGame);\n            preferences.putBoolean(\"statusBar\", statusBar);\n            preferences.putBoolean(\"outlineDragging\", outlineDragging);\n            preferences.putBoolean(\"cumulativeScore\", cumulativeScore);\n            preferences.putInt(\"deck\", deck.ordinal());\n            preferences.putBoolean(\"alwaysOnTop\", alwaysOnTop);\n            preferences.flush();\n        } \n        catch (Exception exception) {\n            Tracelog.log(Level.SEVERE, true, exception);\n        }\n    }\n    \n    @Override public String toString() {\n        StringBuilder builder = new StringBuilder();\n        String header = \"=========\" + this.getClass().getSimpleName() + \"=========\";\n        builder.append(header + System.getProperty(\"line.separator\"));\n        builder.append(\"Draw Option: \" + drawOption + System.getProperty(\"line.separator\"));\n        builder.append(\"Scoring Option: \" + scoringOption + System.getProperty(\"line.separator\"));\n        builder.append(\"Timed Game: \" + Boolean.toString(timedGame) + System.getProperty(\"line.separator\"));\n        builder.append(\"Status Bar: \" + Boolean.toString(statusBar) + System.getProperty(\"line.separator\"));\n        builder.append(\"Outline Dragging: \" + Boolean.toString(outlineDragging) + System.getProperty(\"line.separator\"));\n        builder.append(\"Cumulative Score: \" + Boolean.toString(cumulativeScore) + System.getProperty(\"line.separator\"));\n        builder.append(\"Deck: \" + deck.toString() + System.getProperty(\"line.separator\"));\n        builder.append(\"Always on Top: \" + alwaysOnTop + System.getProperty(\"line.seperator\"));\n        builder.append(new String(new char[header.length()]).replace(\"\\0\", \"=\"));\n        return builder.toString();\n    }\n}"
  },
  {
    "path": "src/game/controllers/CardController.java",
    "content": "package game.controllers;\r\n\r\nimport framework.core.mvc.controller.BaseController;\r\n\r\nimport game.entities.AbstractCardEntity;\r\nimport game.models.CardModel;\r\n\r\npublic class CardController extends BaseController {\r\n\r\n    /**\r\n     * The card model associated to this controller\r\n     */\r\n    private final CardModel _card;\r\n    \r\n    /**\r\n     * Constructs a new instance of this class type\r\n     * \r\n     * @param card The card model to associate to this controller\r\n     */\r\n    public CardController(CardModel card) {\r\n        _card = card;\r\n    }\r\n\r\n    /**\r\n     * @return The card associated to this view \r\n     */\r\n    public CardModel getCard() {\r\n        return _card;\r\n    }\r\n\r\n    /**\r\n     * Refreshes the content of the controller\r\n     */\r\n    public void refresh() {\r\n        _card.refresh();\r\n    }\r\n    \r\n    public boolean isKing() {\r\n        return _card.getCardEntity().isCardKing();\r\n    }\r\n\r\n    /**\r\n     * Verifies if the specified card provided can be used within this current card\r\n     * \r\n     * @param card The card to verify if it can be used to put over this card\r\n     * \r\n     * @return TRUE if this card is before the specified card and of the same suite, FALSE otherwise \r\n     */\r\n    public boolean isValidFoundationMove(CardModel card) {\r\n        AbstractCardEntity thisCardEntity = _card.getCardEntity();\r\n        AbstractCardEntity cardEntity = card.getCardEntity();\r\n        return cardEntity.isSameSuite(thisCardEntity) && cardEntity.isCardRankedAfter(thisCardEntity); \r\n    }\r\n}"
  },
  {
    "path": "src/game/controllers/MovementRecorderController.java",
    "content": "package game.controllers;\r\n\r\nimport java.util.logging.Level;\r\n\r\nimport framework.communication.internal.signal.ISignalListener;\r\nimport framework.core.factories.AbstractFactory;\r\nimport framework.core.factories.ViewFactory;\r\nimport framework.core.mvc.controller.BaseController;\r\nimport framework.utils.logging.Tracelog;\r\n\r\nimport game.models.MovementModel;\r\nimport game.models.MovementModel.MovementType;\r\nimport game.views.GameView;\r\nimport game.views.IUndoable;\r\n\r\n/**\r\n * The controller that handles recording of movement\r\n * \r\n * @author Daniel Ricci {@literal <thedanny09@icloud.com>}\r\n */\r\npublic class MovementRecorderController extends BaseController {\r\n    \r\n    /**\r\n     * The model representation of a movement\r\n     */\r\n    private final MovementModel _movementModel = new MovementModel();\r\n    \r\n    /**\r\n     * This flag indicates if the current state of the game can perform an undo\r\n     */\r\n    private boolean _canUndo;\r\n    \r\n    /**\r\n     * This flag indicates if this instance can record undo's.\r\n     */\r\n    private boolean _lockRecording;\r\n    \r\n    /**\r\n     * The last recorded `from` movement\r\n     */\r\n    private IUndoable _source;\r\n    \r\n    /**\r\n     * The last recorded `from` movement\r\n     */\r\n    private IUndoable _destination;\r\n    \r\n    /**\r\n     * Records the specified movement from one pile view implement to the other\r\n     *\r\n     * @param source The pile view implementation source\r\n     * @param destination The pile view implementation destination\r\n     * \r\n     */\r\n    public void recordMovement(IUndoable source, IUndoable destination) {\r\n        // Do not proceed with the record movement if the lock is enabled\r\n        if(_lockRecording) {\r\n            return;\r\n        }\r\n        \r\n        // Reset the values of this recorder\r\n        reset();\r\n\r\n        // Perform a backup on the source location\r\n        _source = source;\r\n        _source.performBackup();\r\n        _destination = destination;\r\n        \r\n        MovementType fromMovement = MovementType.fromClass(source);\r\n        MovementType toMovement = MovementType.fromClass(destination);\r\n\r\n        //Tracelog.log(Level.INFO, true, String.format(\"Movement Detected: from [%s] to [%s]\", fromMovement, toMovement));\r\n            \r\n        if(fromMovement == MovementType.NONE || toMovement == MovementType.NONE) {\r\n            _canUndo = false;\r\n        }\r\n        else {\r\n            _canUndo = true;\r\n        }\r\n            \r\n        // Update the model\r\n        _movementModel.setMovement(fromMovement, toMovement, false);\r\n    }\r\n        \r\n    /**\r\n     * Performs an undo of the last recorded move\r\n     */\r\n    public void undoLastMovement() {\r\n        if(!canUndo()) {\r\n            Tracelog.log(Level.SEVERE, true, \"Cannot perform an undo\");\r\n            return;\r\n        }\r\n\r\n        // Prevent recording undo's, to avoid performing an undo and have that movement recorded\r\n        _lockRecording = true;\r\n\r\n        // Undo the last action associated to the source\r\n        _source.undoLastAction();\r\n        \r\n        // Update the model to notify listeners that a movement has occurred\r\n        _movementModel.setMovement(MovementType.fromClass(_source), MovementType.fromClass(_destination), true);\r\n\r\n        // Repaint the source and destination\r\n        AbstractFactory.getFactory(ViewFactory.class).get(GameView.class).repaint();\r\n        _source.getContainerClass().repaint();\r\n        _destination.getContainerClass().repaint();\r\n        \r\n        // Reset the state of this recorder\r\n        reset();\r\n               \r\n        // Enable back the lock\r\n        _lockRecording = false;\r\n    }\r\n\r\n    /**\r\n     * @return TRUE if an undo operation can be made, FALSE otherwise\r\n     */\r\n    public boolean canUndo() {\r\n        return _canUndo;\r\n    }\r\n    \r\n    /**\r\n     * Clears the undo availability\r\n     */\r\n    public void clearUndo() {\r\n        _canUndo = false;\r\n        reset();\r\n    }\r\n    \r\n    /**\r\n     * Resets the contents of this recorder\r\n     */\r\n    private void reset() {\r\n        _canUndo = false;\r\n        \r\n        if(_source != null) {\r\n            _source.clearBackup();\r\n        }\r\n        _source = null;\r\n        \r\n        if(_destination != null) {\r\n            _destination.clearBackup();\r\n        }\r\n        _destination = null;\r\n    }\r\n    \r\n    public void addSignalListener(ISignalListener listener) {\r\n        _movementModel.addListener(listener);\r\n    }\r\n}"
  },
  {
    "path": "src/game/entities/AbstractCardEntity.java",
    "content": "package game.entities;\n\nimport java.awt.Image;\nimport java.util.UUID;\n\nimport framework.core.entity.DataEntity;\n\nimport generated.DataLookup.BACKSIDES;\nimport generated.DataLookup.LAYER;\n\npublic abstract class AbstractCardEntity extends DataEntity {\n\n    /**\n     * The backside entity associated to this card\n     */\n    public final BacksideCardEntity backsideCardEntity = new BacksideCardEntity();\n    \n    /**\n     * The layer associated to this entity\n     */\n    protected final LAYER layer;\n    \n    /**\n     * The UUID associated to the entity data\n     */\n    protected final UUID identifier;\n    \n    /**\n     * The ordinal associated to the entity data\n     */\n    protected final int ordinal;\n    \n    /**\n     * Constructs a new instance of this class type\n     */\n    protected AbstractCardEntity() {\n        layer = null;\n        identifier = null;\n        ordinal = -1;\n    }\n    \n    /**\n     * Constructs a new instance of this class type\n     * \n     * @param layer The layer to set this card entity to\n     * @param ordinal The oridinal position of the card\n     * @param the uuid associated to the card\n     */\n    protected AbstractCardEntity(LAYER layer, int ordinal, UUID identifier) {\n        this.layer = layer;\n        this.identifier = identifier;\n        this.ordinal = ordinal;\n        \n        setActiveData(identifier);\n    }\n    \n    /**\n     * Indicates if this card is before the one specified.\n     * \n     * Note: This method is suite agnostic\n     * \n     * @param card The card to check rank against\n     * \n     * @return TRUE if the card is ranked before the one specified, false otherwise\n     */\n    public final boolean isCardRankedBefore(AbstractCardEntity card) {\n        return ordinal + 1 == card.ordinal;\n    }\n    \n    /**\n     * Indicates if this card is after the one specified.\n     * \n     * Note: This method is suite agnostic\n     * \n     * @param card The card to check rank against\n     * \n     * @return TRUE if the card is ranked after the one specified, false otherwise\n     */\n    public final boolean isCardRankedAfter(AbstractCardEntity card) {\n        return ordinal - 1 == card.ordinal;\n    }\n\n    /**\n     * @return TRUE if this card is an ACE, false otherwise\n     */\n    public final boolean isAceCard() {\n        return ordinal == 0;\n    }\n    \n    /**\n     * Indicates if this card's suite is opposite to the card specified. An opposite suite is one that is of different color\n     *\n     * @param card The abstract card entity\n     *  \n     * @return TRUE if this card's suite is opposite to the one specified, FALSE otherwise\n     */\n    public abstract boolean isOppositeSuite(AbstractCardEntity card);\n\n    /**\n     * Indicates if this card's suite is the same as the specified card\n     * \n     * @param card The card check suite against\n     * \n     * @return TRUE if this card and the card specified are of the SAME suit, FALSE otherwise\n     */\n    public final boolean isSameSuite(AbstractCardEntity card) {\n        return card.layer.equals(layer);\n    }\n    \n    /**\n     * Sets the visibility of the cards' backside\n     * \n     * @param isVisible TRUE if the backside of the card is visible, FALSE otherwise\n     */\n    public final void setBacksideVisible(boolean isVisible) {\n        backsideCardEntity.setIsBacksideShowing(isVisible);\n    }\n    \n    /**\n     * @return TRUE if the backside is visible, FALSE otherwise\n     */\n    public boolean getBacksideVisible() {\n        return backsideCardEntity.getIsBacksideShowing();\n    }\n    \n    /**\n     * @return TRUE if this card is a king, FALSE otherwise\n     */\n    public final boolean isCardKing() {\n        return ordinal == 12;\n    }\n    \n    @Override public void refresh() {\n        backsideCardEntity.refresh();\n    }\n    \n    @Override public Image getRenderableContent() {\n        if(getBacksideVisible()) {\n            return backsideCardEntity.getRenderableContent();\n        }\n        return super.getRenderableContent();\n    }\n    \n    @Override public String toString() {\n        if(layer != null) {\n            return (!getBacksideVisible() ? \"[F]\" : \"[B]\") + (\"\\t\") + (ordinal + 1) + \" of \" + layer.toString();    \n        }\n        return super.toString();\n    }\n\n    /**\n     * Sets the backside of this entity\n     *\n     * @param backside The backside to set this entity with\n     */\n    public void setBackside(BACKSIDES backside) {\n        backsideCardEntity.setActiveData(backside.identifier);\n    }\n}"
  },
  {
    "path": "src/game/entities/BacksideCardEntity.java",
    "content": "package game.entities;\r\n\r\nimport framework.core.entity.DataEntity;\r\n\r\nimport game.config.OptionsPreferences;\r\n\r\nimport generated.DataLookup;\r\n\r\npublic class BacksideCardEntity extends DataEntity {\r\n\t\r\n\tpublic static final String DECK_BACKSIDE_CHANGED = \"DECK_BACKSIDE_CHANGED\";\r\n\t\r\n\tprivate boolean isBacksideVisible = false;\r\n\r\n\tprivate DataLookup.BACKSIDES _backside;\r\n\r\n\tpublic BacksideCardEntity() {\t\t\r\n\t\tthis.setBackside();\r\n\t}\r\n\t\r\n\tpublic void setIsBacksideShowing(boolean isShowing) {\r\n\t\tisBacksideVisible = isShowing;\r\n\t}\r\n\r\n\tpublic boolean getIsBacksideShowing() {\r\n\t\treturn isBacksideVisible;\r\n\t}\r\n\r\n\tpublic DataLookup.BACKSIDES getBacksideData() {\r\n\t\treturn _backside;\r\n\t}\r\n\r\n\tprivate void setBackside() {\r\n\t\tOptionsPreferences preferences = new OptionsPreferences();\r\n\t\tpreferences.load();\r\n\t\t\r\n\t\tif (_backside == preferences.deck) {\r\n\t\t\treturn;\r\n\t\t}\r\n\t\t_backside = preferences.deck;\r\n\t\tsuper.setActiveData(preferences.deck.identifier);\t\t\r\n\t}\r\n\t\t\r\n\t@Override public void refresh() {\r\n\t\tsetBackside();\r\n\t}\r\n}"
  },
  {
    "path": "src/game/entities/ClubCardEntity.java",
    "content": "package game.entities;\r\n\r\nimport generated.DataLookup;\r\nimport generated.DataLookup.CLUBS;\r\nimport generated.DataLookup.LAYER;\r\n\r\npublic final class ClubCardEntity extends AbstractCardEntity {\r\n    \r\n    public ClubCardEntity(CLUBS card) {\r\n        super(DataLookup.LAYER.CLUBS, card.ordinal(), card.identifier);\r\n    }\r\n\r\n    @Override public boolean isOppositeSuite(AbstractCardEntity card) {\r\n        return card.layer == LAYER.HEARTS || card.layer == LAYER.DIAMONDS; \r\n    }\r\n}"
  },
  {
    "path": "src/game/entities/DiamondCardEntity.java",
    "content": "package game.entities;\r\n\r\nimport generated.DataLookup;\r\nimport generated.DataLookup.LAYER;\r\n\r\npublic final class DiamondCardEntity extends AbstractCardEntity {\r\n    \r\n    public DiamondCardEntity(DataLookup.DIAMONDS card) {\r\n        super(DataLookup.LAYER.DIAMONDS, card.ordinal(), card.identifier);\r\n    }\r\n    @Override public boolean isOppositeSuite(AbstractCardEntity card) {\r\n        return card.layer == LAYER.SPADES || card.layer == LAYER.CLUBS; \r\n    }\r\n}"
  },
  {
    "path": "src/game/entities/FoundationCardEntity.java",
    "content": "package game.entities;\r\n\r\nimport generated.DataLookup;\r\n\r\npublic final class FoundationCardEntity extends BacksideCardEntity {\r\n    \r\n    public FoundationCardEntity() {\r\n        setActiveData(DataLookup.MISC.FOUNDATION.identifier);\r\n    }\r\n}"
  },
  {
    "path": "src/game/entities/HeartCardEntity.java",
    "content": "package game.entities;\r\n\r\nimport generated.DataLookup;\r\nimport generated.DataLookup.LAYER;\r\n\r\npublic final class HeartCardEntity extends AbstractCardEntity {\r\n    public HeartCardEntity(DataLookup.HEARTS card) {\r\n        super(DataLookup.LAYER.HEARTS, card.ordinal(), card.identifier);\r\n    }\r\n    @Override public boolean isOppositeSuite(AbstractCardEntity card) {\r\n        return card.layer == LAYER.SPADES || card.layer == LAYER.CLUBS; \r\n    }\r\n}"
  },
  {
    "path": "src/game/entities/NullCardEntity.java",
    "content": "package game.entities;\r\n\r\npublic final class NullCardEntity extends AbstractCardEntity {\r\n    \r\n    public NullCardEntity() {\r\n        backsideCardEntity.setIsBacksideShowing(true);\r\n    }\r\n    \r\n    @Override public boolean isOppositeSuite(AbstractCardEntity card) {\r\n        return false; \r\n    }\r\n}"
  },
  {
    "path": "src/game/entities/SpadeCardEntity.java",
    "content": "package game.entities;\r\n\r\nimport generated.DataLookup;\r\nimport generated.DataLookup.LAYER;\r\n\r\npublic final class SpadeCardEntity extends AbstractCardEntity {\r\n    public SpadeCardEntity(DataLookup.SPADES card) {\r\n        super(DataLookup.LAYER.SPADES, card.ordinal(), card.identifier);\r\n    }\r\n    @Override public boolean isOppositeSuite(AbstractCardEntity card) {\r\n        return card.layer == LAYER.HEARTS || card.layer == LAYER.DIAMONDS; \r\n    }\r\n}"
  },
  {
    "path": "src/game/entities/StockCardEntity.java",
    "content": "package game.entities;\r\n\r\nimport generated.DataLookup;\r\n\r\npublic final class StockCardEntity extends AbstractCardEntity {\r\n    public static int identifier = 0;\r\n    public int identity = ++identifier;\r\n    \r\n    public StockCardEntity() {\r\n        setBacksideVisible(true);\r\n    }\r\n    \r\n    public void enableTalonRecycled() {\r\n        setActiveData(DataLookup.MISC.TALON_RESTART.identifier);\r\n        setBacksideVisible(false);\r\n    }\r\n    \r\n    public void enableTalonEnd() {\r\n        setActiveData(DataLookup.MISC.TALON_END.identifier);\r\n        setBacksideVisible(false);\r\n    }\r\n    \r\n    @Override public void refresh() {\r\n    \tsuper.refresh();\r\n    }\r\n        \r\n    @Override public boolean isOppositeSuite(AbstractCardEntity card) {\r\n        return false;\r\n    }\r\n    \r\n    @Override public String toString() {\r\n        return \"Identity: \" + identity;\r\n    }\r\n}"
  },
  {
    "path": "src/game/menu/AboutMenuItem.java",
    "content": "package game.menu;\r\n\r\nimport java.awt.event.ActionEvent;\r\nimport java.awt.event.KeyEvent;\r\nimport java.util.EventObject;\r\n\r\nimport javax.swing.JComponent;\r\nimport javax.swing.JMenuItem;\r\nimport javax.swing.JOptionPane;\r\nimport javax.swing.JPanel;\r\nimport javax.swing.JScrollPane;\r\nimport javax.swing.JTextArea;\r\nimport javax.swing.UIManager;\r\n\r\nimport framework.core.factories.AbstractFactory;\r\nimport framework.core.factories.ViewFactory;\r\nimport framework.core.navigation.AbstractMenuItem;\r\nimport framework.core.system.Application;\r\nimport framework.utils.globalisation.Localization;\r\n\r\nimport game.views.StatusBarView;\r\n\r\nimport resources.LocalizationStrings;\r\n\r\n/**\r\n * The about menu item that displays information about the application\r\n * \r\n * @author Daniel Ricci {@literal <thedanny09@icloud.com>}\r\n *\r\n */\r\npublic class AboutMenuItem extends AbstractMenuItem {\r\n\r\n    /**\r\n     * Constructs a new instance of this class type\r\n     *\r\n     * @param parent The parent associated to this menu item\r\n     */\r\n    public AboutMenuItem(JComponent parent) {\r\n        super(new JMenuItem(Localization.instance().getLocalizedString(LocalizationStrings.ABOUT)), parent);\r\n        super.getComponent(JMenuItem.class).setMnemonic(KeyEvent.VK_A);\r\n    }\r\n    \r\n    @Override protected void onEntered(EventObject event) {\r\n        super.onEntered(event);\r\n        AbstractFactory.getFactory(ViewFactory.class).get(StatusBarView.class).setMenuDescription(\"About Solitaire\");\r\n    }\r\n    \r\n    @Override protected void onExited(EventObject event) {\r\n        super.onExited(event);\r\n        AbstractFactory.getFactory(ViewFactory.class).get(StatusBarView.class).clearMenuDescription();\r\n    }\r\n\r\n    @Override public void onExecute(ActionEvent actionEvent) {\r\n        JTextArea textArea = new JTextArea(8, 20);\r\n        textArea.setText(Localization.instance().getLocalizedString(LocalizationStrings.ABOUT_MESSAGE));\r\n        textArea.setEditable(false);\r\n        textArea.setLineWrap(true);\r\n        textArea.setWrapStyleWord(true);\r\n        textArea.setBackground(UIManager.getColor(\"OptionsPane.background\"));\r\n        \r\n        JScrollPane scrollPane = new JScrollPane(textArea);\r\n        scrollPane.setBorder(null);\r\n        JPanel panel = new JPanel();\r\n        panel.add(scrollPane);\r\n\r\n        // Create a custom dialog\r\n        JOptionPane.showMessageDialog(\r\n        \t\tApplication.instance, \r\n        \t\tpanel, \r\n        \t\tLocalization.instance().getLocalizedString(LocalizationStrings.ABOUT), \r\n        \t\tJOptionPane.INFORMATION_MESSAGE);\r\n    }\r\n}"
  },
  {
    "path": "src/game/menu/DeckMenuItem.java",
    "content": "package game.menu;\r\n\r\nimport java.awt.event.ActionEvent;\r\nimport java.awt.event.KeyEvent;\r\nimport java.util.EventObject;\r\n\r\nimport javax.swing.JComponent;\r\nimport javax.swing.JMenuItem;\r\nimport javax.swing.JOptionPane;\r\n\r\nimport framework.communication.internal.signal.arguments.EventArgs;\r\nimport framework.core.factories.AbstractFactory;\r\nimport framework.core.factories.ModelFactory;\r\nimport framework.core.factories.ViewFactory;\r\nimport framework.core.navigation.AbstractMenuItem;\r\nimport framework.utils.globalisation.Localization;\r\n\r\nimport game.config.OptionsPreferences;\r\nimport game.entities.BacksideCardEntity;\r\nimport game.models.CardModel;\r\nimport game.views.DeckSelectionDialogView;\r\nimport game.views.StatusBarView;\r\nimport game.views.StockView;\r\n\r\nimport resources.LocalizationStrings;\r\n\r\n/**\r\n * Menu item for starting a new game\r\n * \r\n * @author Daniel Ricci {@literal <thedanny09@icloud.com>}\r\n *\r\n */\r\npublic class DeckMenuItem extends AbstractMenuItem {\r\n\r\n    /**\r\n     * Constructs a new instance of this class type\r\n     *\r\n     * @param parent The parent associated to this menu item\r\n     */\r\n    public DeckMenuItem(JComponent parent) {\r\n        super(new JMenuItem(Localization.instance().getLocalizedString(LocalizationStrings.DECK)), parent);\r\n        super.getComponent(JMenuItem.class).setMnemonic(KeyEvent.VK_C);\r\n    }\r\n    \r\n    @Override protected void onEntered(EventObject event) {\r\n        super.onEntered(event);\r\n        AbstractFactory.getFactory(ViewFactory.class).get(StatusBarView.class).setMenuDescription(\"Choose new deck back\");\r\n    }\r\n    \r\n    @Override protected void onExited(EventObject event) {\r\n        super.onExited(event);\r\n        AbstractFactory.getFactory(ViewFactory.class).get(StatusBarView.class).clearMenuDescription();\r\n    }\r\n\r\n    @Override public void onExecute(ActionEvent actionEvent) {\r\n        \r\n        // Clear the description when the execution has occurred. This is so that the description does not stay\r\n        // stuck until the dialog has closed\r\n        AbstractFactory.getFactory(ViewFactory.class).get(StatusBarView.class).clearMenuDescription();\r\n        \r\n        DeckSelectionDialogView view = new DeckSelectionDialogView();\r\n        view.render();\r\n        if(view.getDialogResult() == JOptionPane.OK_OPTION) {\r\n            \r\n            // Update all the backsides of all the cards in the game\r\n            EventArgs args = new EventArgs(this, CardModel.EVENT_UPDATE_BACKSIDE);\r\n            AbstractFactory.getFactory(ModelFactory.class).multicastSignalListeners(CardModel.class, args);\r\n            \r\n            OptionsPreferences preferences = new OptionsPreferences();\r\n            preferences.load();\r\n\r\n            // Send out the signal to the stockview\r\n            AbstractFactory.getFactory(ViewFactory.class).multicastSignalListeners(StockView.class, new EventArgs(this, BacksideCardEntity.DECK_BACKSIDE_CHANGED));\r\n        }\r\n    }\r\n}"
  },
  {
    "path": "src/game/menu/ExitMenuItem.java",
    "content": "package game.menu;\r\n\r\nimport java.awt.event.ActionEvent;\r\nimport java.awt.event.KeyEvent;\r\nimport java.awt.event.WindowEvent;\r\nimport java.util.EventObject;\r\n\r\nimport javax.swing.JComponent;\r\nimport javax.swing.JMenuItem;\r\n\r\nimport framework.core.factories.AbstractFactory;\r\nimport framework.core.factories.ViewFactory;\r\nimport framework.core.navigation.AbstractMenuItem;\r\nimport framework.core.system.Application;\r\nimport framework.utils.globalisation.Localization;\r\n\r\nimport game.views.StatusBarView;\r\n\r\n/**\r\n * Menu item for exiting the game\r\n * \r\n * @author Daniel Ricci {@literal <thedanny09@icloud.com>}\r\n *\r\n */\r\npublic class ExitMenuItem extends AbstractMenuItem {\r\n\r\n    /**\r\n     * Constructs a new instance of this class type\r\n     *\r\n     * @param parent The parent associated to this menu item\r\n     */\r\n    public ExitMenuItem(JComponent parent) {\r\n        super(new JMenuItem(Localization.instance().getLocalizedString(\"Exit\")), parent);\r\n        super.getComponent(JMenuItem.class).setMnemonic(KeyEvent.VK_X);\r\n    }\r\n    \r\n    @Override protected void onEntered(EventObject event) {\r\n        super.onEntered(event);\r\n        AbstractFactory.getFactory(ViewFactory.class).get(StatusBarView.class).setMenuDescription(\"Exit Solitaire\");\r\n    }\r\n    \r\n    @Override protected void onExited(EventObject event) {\r\n        super.onExited(event);\r\n        AbstractFactory.getFactory(ViewFactory.class).get(StatusBarView.class).clearMenuDescription();\r\n    }\r\n\r\n    @Override public void onExecute(ActionEvent actionEvent) {\r\n        Application.instance.dispatchEvent(new WindowEvent(Application.instance, WindowEvent.WINDOW_CLOSING));\r\n    }\r\n}"
  },
  {
    "path": "src/game/menu/GitHubMenuItem.java",
    "content": "package game.menu;\n\nimport java.awt.Desktop;\nimport java.awt.event.ActionEvent;\nimport java.net.URI;\nimport java.util.EventObject;\n\nimport javax.swing.JComponent;\nimport javax.swing.JMenuItem;\n\nimport framework.core.factories.AbstractFactory;\nimport framework.core.factories.ViewFactory;\nimport framework.core.navigation.AbstractMenuItem;\nimport framework.utils.globalisation.Localization;\n\nimport game.views.StatusBarView;\n\nimport resources.LocalizationStrings;\n\npublic class GitHubMenuItem extends AbstractMenuItem {\n    public GitHubMenuItem(JComponent parent) {\n        super(new JMenuItem(\"GitHub Repository\"), parent);\n    }\n    \n    @Override protected void onEntered(EventObject event) {\n        super.onEntered(event);\n        AbstractFactory.getFactory(ViewFactory.class).get(StatusBarView.class).setMenuDescription(\"GitHub Repository - \" + Localization.instance().getLocalizedString(LocalizationStrings.GITHUB));\n    }\n    \n    @Override protected void onExited(EventObject event) {\n        super.onExited(event);\n        AbstractFactory.getFactory(ViewFactory.class).get(StatusBarView.class).clearMenuDescription();\n    }\n\n    @Override public void onExecute(ActionEvent actionEvent) {\n    \tString url = Localization.instance().getLocalizedString(LocalizationStrings.GITHUB);\n\t\ttry {\n            if (Desktop.isDesktopSupported()) {\n                Desktop desktop = Desktop.getDesktop();\n                desktop.browse(new URI(url));\n            } else {\n                Runtime.getRuntime().exec(\"cmd /c start \" + url);\n            }\n\t\t}\n\t\tcatch(Exception exception) {\n\t\t\texception.printStackTrace();\n\t\t}\n    }\n}"
  },
  {
    "path": "src/game/menu/NewGameMenuItem.java",
    "content": "package game.menu;\r\n\r\nimport java.awt.event.ActionEvent;\r\nimport java.awt.event.KeyEvent;\r\nimport java.util.EventObject;\r\n\r\nimport javax.swing.JComponent;\r\nimport javax.swing.JMenuItem;\r\nimport javax.swing.KeyStroke;\r\n\r\nimport framework.core.factories.AbstractFactory;\r\nimport framework.core.factories.ViewFactory;\r\nimport framework.core.navigation.AbstractMenuItem;\r\nimport framework.core.system.Application;\r\nimport framework.utils.globalisation.Localization;\r\n\r\nimport game.views.StatusBarView;\r\n\r\n/**\r\n * Menu item for starting a new game\r\n * \r\n * @author Daniel Ricci {@literal <thedanny09@icloud.com>}\r\n *\r\n */\r\npublic class NewGameMenuItem extends AbstractMenuItem {\r\n\r\n    /**\r\n     * Constructs a new instance of this class type\r\n     *\r\n     * @param parent The parent associated to this menu item\r\n     */\r\n    public NewGameMenuItem(JComponent parent) {\r\n        super(new JMenuItem(Localization.instance().getLocalizedString(\"Deal\")), parent);\r\n        super.getComponent(JMenuItem.class).setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_F2, 0, true));\r\n        super.getComponent(JMenuItem.class).setMnemonic(KeyEvent.VK_D);\r\n    }\r\n    \r\n    @Override protected void onEntered(EventObject event) {\r\n        super.onEntered(event);\r\n        AbstractFactory.getFactory(ViewFactory.class).get(StatusBarView.class).setMenuDescription(\"Deal a new game\");\r\n    }\r\n    \r\n    @Override protected void onExited(EventObject event) {\r\n        super.onExited(event);\r\n        AbstractFactory.getFactory(ViewFactory.class).get(StatusBarView.class).clearMenuDescription();\r\n    }\r\n\r\n    @Override public void onExecute(ActionEvent actionEvent) {\r\n        Application.instance.onRestart();\r\n    }\r\n}\r\n"
  },
  {
    "path": "src/game/menu/OnTopMenuItem.java",
    "content": "package game.menu;\r\n\r\nimport java.awt.event.ActionEvent;\r\nimport java.util.EventObject;\r\n\r\nimport javax.swing.JCheckBoxMenuItem;\r\nimport javax.swing.JComponent;\r\n\r\nimport framework.core.factories.AbstractFactory;\r\nimport framework.core.factories.ViewFactory;\r\nimport framework.core.navigation.AbstractMenuItem;\r\nimport framework.core.system.Application;\r\nimport framework.utils.globalisation.Localization;\r\n\r\nimport game.config.OptionsPreferences;\r\nimport game.views.StatusBarView;\r\n\r\n/**\r\n * The always-on-top menu item that keeps the game above all other applications\r\n * \r\n * @author Daniel Ricci {@literal <thedanny09@icloud.com>}\r\n *\r\n */\r\npublic class OnTopMenuItem extends AbstractMenuItem {\r\n\r\n    /**\r\n     * Constructs a new instance of this class type\r\n     *\r\n     * @param parent The parent associated to this menu item\r\n     */\r\n    public OnTopMenuItem(JComponent parent) {\r\n    \tsuper(new JCheckBoxMenuItem(Localization.instance().getLocalizedString(\"Always on Top\"), Application.instance.isAlwaysOnTop()), parent);\r\n    }\r\n    \r\n    @Override protected void onEntered(EventObject event) {\r\n        super.onEntered(event);\r\n        AbstractFactory.getFactory(ViewFactory.class).get(StatusBarView.class).setMenuDescription(\"Sets this application to always show above other applications\");\r\n    }\r\n    \r\n    @Override protected void onExited(EventObject event) {\r\n        super.onExited(event);\r\n        AbstractFactory.getFactory(ViewFactory.class).get(StatusBarView.class).clearMenuDescription();\r\n    }\r\n    \r\n    @Override protected boolean isEnabled() {\r\n    \treturn super.isEnabled() && Application.instance.isAlwaysOnTopSupported();\r\n    }\r\n    \r\n    @Override public void onExecute(ActionEvent actionEvent) {\r\n    \tOptionsPreferences preferences = new OptionsPreferences();\r\n    \tpreferences.load();\r\n    \tpreferences.alwaysOnTop = !preferences.alwaysOnTop;\r\n    \tpreferences.save();\r\n    \t\r\n    \tApplication.instance.setAlwaysOnTop(preferences.alwaysOnTop);\r\n    }\r\n}"
  },
  {
    "path": "src/game/menu/OptionsMenuItem.java",
    "content": "package game.menu;\r\n\r\nimport java.awt.event.ActionEvent;\r\nimport java.awt.event.KeyEvent;\r\nimport java.util.EventObject;\r\n\r\nimport javax.swing.AbstractButton;\r\nimport javax.swing.JComponent;\r\nimport javax.swing.JMenuItem;\r\nimport javax.swing.JOptionPane;\r\n\r\nimport framework.communication.internal.signal.arguments.EventArgs;\r\nimport framework.core.factories.AbstractFactory;\r\nimport framework.core.factories.ViewFactory;\r\nimport framework.core.navigation.AbstractMenuItem;\r\nimport framework.core.navigation.MenuBuilder;\r\nimport framework.core.system.Application;\r\nimport framework.utils.globalisation.Localization;\r\n\r\nimport game.views.CardView;\r\nimport game.views.OptionsDialogView;\r\nimport game.views.StatusBarView;\r\n\r\nimport resources.LocalizationStrings;\r\n\r\n/**\r\n * Menu item for pulling up the options menu\r\n * \r\n * @author Daniel Ricci {@literal <thedanny09@icloud.com>}\r\n *\r\n */\r\npublic class OptionsMenuItem extends AbstractMenuItem {\r\n\r\n    /**\r\n     * Constructs a new instance of this class type\r\n     *\r\n     * @param parent The parent associated to this menu item\r\n     */\r\n    public OptionsMenuItem(JComponent parent) {\r\n        super(new JMenuItem(Localization.instance().getLocalizedString(LocalizationStrings.OPTIONS)), parent);\r\n        super.getComponent(JMenuItem.class).setMnemonic(KeyEvent.VK_O);\r\n    }\r\n    \r\n    @Override protected void onEntered(EventObject event) {\r\n        super.onEntered(event);\r\n        AbstractFactory.getFactory(ViewFactory.class).get(StatusBarView.class).setMenuDescription(\"Change Solitaire options\");\r\n    }\r\n    \r\n    @Override protected void onExited(EventObject event) {\r\n        super.onExited(event);\r\n        AbstractFactory.getFactory(ViewFactory.class).get(StatusBarView.class).clearMenuDescription();\r\n    }\r\n\r\n    @Override public void onExecute(ActionEvent actionEvent) {\r\n        \r\n        // Clear the description when the execution has occured. This is so that the description does not stay\r\n        // stuck until the dialog has closed\r\n        AbstractFactory.getFactory(ViewFactory.class).get(StatusBarView.class).clearMenuDescription();\r\n        \r\n        OptionsDialogView options = new OptionsDialogView();\r\n        options.render();\r\n        \r\n        if(options.getDialogResult() == JOptionPane.OK_OPTION) {\r\n            if(options.refreshGameRequired) {\r\n                Application.instance.isRestarting = true;\r\n                MenuBuilder.search(Application.instance.getJMenuBar(), NewGameMenuItem.class).getComponent(AbstractButton.class).doClick();\r\n            }\r\n            else {\r\n                if(options.statusBarChanged) {\r\n                    AbstractFactory.getFactory(ViewFactory.class).get(StatusBarView.class).synchronizeWithOptions();\r\n                }\r\n                if(options.outlineDraggingChanged) {\r\n                    EventArgs args = new EventArgs(this, CardView.EVENT_OUTLINE_SYNCHRONIZE);\r\n                    args.setSuppressUpdate(true);\r\n                    AbstractFactory.getFactory(ViewFactory.class).multicastSignalListeners(CardView.class, args);\r\n                }\r\n            }\r\n        }\r\n    }\r\n}"
  },
  {
    "path": "src/game/menu/UndoMenuItem.java",
    "content": "package game.menu;\r\n\r\nimport java.awt.event.ActionEvent;\r\nimport java.awt.event.KeyEvent;\r\nimport java.util.EventObject;\r\n\r\nimport javax.swing.JComponent;\r\nimport javax.swing.JMenuItem;\r\n\r\nimport framework.core.factories.AbstractFactory;\r\nimport framework.core.factories.ControllerFactory;\r\nimport framework.core.factories.ViewFactory;\r\nimport framework.core.navigation.AbstractMenuItem;\r\nimport framework.utils.globalisation.Localization;\r\n\r\nimport game.controllers.MovementRecorderController;\r\nimport game.views.StatusBarView;\r\n\r\n/**\r\n * Menu item for starting a new game\r\n * \r\n * @author Daniel Ricci {@literal <thedanny09@icloud.com>}\r\n *\r\n */\r\npublic class UndoMenuItem extends AbstractMenuItem {\r\n\r\n    /**\r\n     * Constructs a new instance of this class type\r\n     *\r\n     * @param parent The parent associated to this menu item\r\n     */\r\n    public UndoMenuItem(JComponent parent) {\r\n        super(new JMenuItem(Localization.instance().getLocalizedString(\"Undo\")), parent);\r\n        super.getComponent(JMenuItem.class).setMnemonic(KeyEvent.VK_U);\r\n    }\r\n    \r\n    @Override protected void onEntered(EventObject event) {\r\n        super.onEntered(event);\r\n        AbstractFactory.getFactory(ViewFactory.class).get(StatusBarView.class).setMenuDescription(\"Undo last action\");\r\n    }\r\n    \r\n    @Override protected void onExited(EventObject event) {\r\n        super.onExited(event);\r\n        AbstractFactory.getFactory(ViewFactory.class).get(StatusBarView.class).clearMenuDescription();\r\n    }\r\n    \r\n    @Override protected boolean isEnabled() {\r\n        return AbstractFactory.getFactory(ControllerFactory.class).get(MovementRecorderController.class).canUndo();\r\n    }\r\n    \r\n    @Override public void onExecute(ActionEvent actionEvent) {\r\n        AbstractFactory.getFactory(ControllerFactory.class).get(MovementRecorderController.class).undoLastMovement();\r\n    }\r\n}"
  },
  {
    "path": "src/game/models/CardModel.java",
    "content": "package game.models;\r\n\r\nimport java.awt.Image;\r\nimport java.util.ArrayList;\r\nimport java.util.Collections;\r\nimport java.util.List;\r\n\r\nimport framework.communication.internal.signal.ISignalReceiver;\r\nimport framework.communication.internal.signal.arguments.EventArgs;\r\nimport framework.core.factories.AbstractFactory;\r\nimport framework.core.factories.ModelFactory;\r\nimport framework.core.mvc.model.BaseModel;\r\n\r\nimport game.config.OptionsPreferences;\r\nimport game.entities.AbstractCardEntity;\r\nimport game.entities.ClubCardEntity;\r\nimport game.entities.DiamondCardEntity;\r\nimport game.entities.HeartCardEntity;\r\nimport game.entities.SpadeCardEntity;\r\n\r\nimport generated.DataLookup;\r\n\r\npublic class CardModel extends BaseModel {\r\n    \r\n    public static final String EVENT_UPDATE_BACKSIDE = \"EVENT_UPDATE_BACKSIDE\";\r\n    \r\n    private final AbstractCardEntity _cardEntity;\r\n        \r\n    public CardModel(AbstractCardEntity cardEntity) {\r\n        _cardEntity = cardEntity;\r\n        \r\n        addSignal(EVENT_UPDATE_BACKSIDE, new ISignalReceiver<EventArgs>() {\r\n            @Override public void signalReceived(EventArgs event) {\r\n                OptionsPreferences preferences = new OptionsPreferences();\r\n                preferences.load();\r\n                _cardEntity.setBackside(preferences.deck);\r\n                refresh();\r\n            }\r\n        });\r\n    }\r\n        \r\n    public boolean isEmpty() {\r\n        return _cardEntity == null;\r\n    }\r\n    \r\n    public void setBackside(boolean backside) {\r\n        _cardEntity.setBacksideVisible(backside);\r\n    }\r\n    \r\n    public boolean getIsBackside() {\r\n        return _cardEntity.getBacksideVisible();\r\n    }\r\n    \r\n    public static List<CardModel> newInstances() {\r\n        List<CardModel> entities = new ArrayList<CardModel>();\r\n        ModelFactory factory = AbstractFactory.getFactory(ModelFactory.class);\r\n        for(DataLookup.HEARTS heart : DataLookup.HEARTS.values()) {\r\n            entities.add(factory.add(new CardModel(new HeartCardEntity(heart))));\r\n        }\r\n        for(DataLookup.CLUBS club : DataLookup.CLUBS.values()) {\r\n            entities.add(factory.add(new CardModel(new ClubCardEntity(club))));\r\n        }\r\n        for(DataLookup.DIAMONDS diamond : DataLookup.DIAMONDS.values()) {\r\n            entities.add(factory.add(new CardModel(new DiamondCardEntity(diamond))));\r\n        }\r\n        for(DataLookup.SPADES spade : DataLookup.SPADES.values()) {\r\n            entities.add(factory.add(new CardModel(new SpadeCardEntity(spade))));\r\n        }\r\n        Collections.shuffle(entities);\r\n        return entities;\r\n    }\r\n    \r\n    public AbstractCardEntity getCardEntity() {\r\n        return _cardEntity;\r\n    }\r\n    \r\n    /**\r\n     * Checks if the passed in card is ordinally before and of opposite suite to this card\r\n     * @param card The card\r\n     * \r\n     * @return TRUE if the card passed in is both ordinally before and of opposite suite to this card, FALSE otherwise\r\n     */\r\n    public boolean isCardBeforeAndOppositeSuite(CardModel card) {\r\n        //System.out.println(\"Attempting to place \" + card._cardEntity.toString() + \" over \" + _cardEntity.toString());\r\n        return !_cardEntity.getBacksideVisible() && !card._cardEntity.getBacksideVisible() && card._cardEntity.isOppositeSuite(_cardEntity) && card._cardEntity.isCardRankedBefore(_cardEntity);\r\n    }\r\n    \r\n    @Override public String toString() {\r\n        return _cardEntity.toString();\r\n    }\r\n    \r\n    @Override public Image getRenderableContent() {\r\n        if(_cardEntity == null) {\r\n            return null;\r\n        }\r\n        return _cardEntity.getRenderableContent();\r\n    }\r\n}"
  },
  {
    "path": "src/game/models/MovementModel.java",
    "content": "package game.models;\r\n\r\nimport framework.core.mvc.model.BaseModel;\r\n\r\nimport game.views.FoundationPileView;\r\nimport game.views.StockView;\r\nimport game.views.TableauPileView;\r\nimport game.views.TalonPileView;\r\n\r\npublic class MovementModel extends BaseModel {\r\n    \r\n    public enum MovementType {\r\n        STOCK,\r\n        TALON,\r\n        FOUNDATION,\r\n        TABLEAU, \r\n        NONE;\r\n        \r\n        public static MovementType fromClass(Object clazz) {\r\n            if(clazz instanceof StockView) {\r\n                return MovementType.STOCK;\r\n            }\r\n            else if(clazz instanceof TalonPileView) {\r\n                return MovementType.TALON;\r\n            }\r\n            else if(clazz instanceof FoundationPileView) {\r\n                return MovementType.FOUNDATION;\r\n            }\r\n            else if(clazz instanceof TableauPileView) {\r\n                return MovementType.TABLEAU;\r\n            }\r\n            else {\r\n                return MovementType.NONE;\r\n            }\r\n        }\r\n    }\r\n    \r\n    private MovementType _from;\r\n    \r\n    private MovementType _to;\r\n    \r\n    private boolean _isUndo;\r\n    \r\n    public void setMovement(MovementType from, MovementType to, boolean isUndo) {\r\n        _from = from;\r\n        _to = to;\r\n        _isUndo = isUndo;\r\n        \r\n        doneUpdating();\r\n    }\r\n    \r\n    public MovementType getFrom() {\r\n        return _from;\r\n    }\r\n    \r\n    public MovementType getTo() {\r\n        return _to;\r\n    }\r\n    \r\n    public boolean getIsUndo() {\r\n        return _isUndo;\r\n    }\r\n}"
  },
  {
    "path": "src/game/views/AbstractPileView.java",
    "content": "package game.views;\n\nimport java.awt.BorderLayout;\nimport java.awt.Component;\nimport java.awt.Container;\nimport java.awt.Dimension;\nimport java.awt.Point;\nimport java.awt.Rectangle;\nimport java.util.ArrayList;\nimport java.util.Arrays;\nimport java.util.Collections;\nimport java.util.List;\n\nimport javax.swing.JLayeredPane;\n\nimport framework.core.factories.AbstractFactory;\nimport framework.core.factories.ViewFactory;\nimport framework.core.mvc.view.PanelView;\n\n/**\n * Abstract representation of a pile view\n * \n * @author Daniel Ricci {@literal <thedanny09@icloud.com>}\n */\npublic abstract class AbstractPileView extends PanelView implements IUndoable {\n        \n    /**\n     * The layered pane that holds the list of cards\n     */\n    protected final JLayeredPane layeredPane = new JLayeredPane();\n\n    /**\n     * The list of cards that were previously moved, used for undo purposes\n     */\n    private final List<Component> _previousCards = new ArrayList<Component>();\n    \n    /**\n     * Constructs a new instance of this class type\n     */\n    protected AbstractPileView() {\n        setLayout(new BorderLayout());\n        setPreferredSize(new Dimension(CardView.CARD_WIDTH, this.getPreferredSize().height));\n        setOpaque(false);\n        add(layeredPane, BorderLayout.CENTER);\n    }\n\n    /**\n     * Removes the highlights from this view and its underlying cards\n     */\n    public void removeHighlight() {\n        for(Component comp : layeredPane.getComponents()) {\n            CardView cardView = (CardView)comp;\n            cardView.setIsHighlighted(false);\n        }\n        setIsHighlighted(false);\n        repaint();\n    }\n\n    /**\n     * @return The last ordered card held within this pile view\n     */\n    public CardView getLastCard() {\n        if(layeredPane.getComponentCount() == 0) {\n            return null;\n        }\n        \n        Component comp = layeredPane.getComponents()[0];\n        if(!(comp instanceof CardView)) {\n            return null;\n        }\n        \n        return (CardView)comp;\n    }\n        \n    /**\n     * Adds the specified card view to this pile\n     *\n     * @param cardView The card to add to this pile\n     * \n     */\n    public void addCard(CardView cardView) {\n        addCard(cardView, layeredPane.getComponents().length);\n    }\n    \n    public void addCard(CardView cardView, int layerPosition) {\n     \n        // Hold onto a reference of the parent for repainting reasons\n        Container parentCardView = cardView.getParent();\n        \n        // Get the list of components associated to the card view.\n        // This list represents all the children associated to the said CardView.this reference.\n        List<Component> components = new ArrayList<Component>(Arrays.asList(cardView.layeredPane.getComponents()));\n        \n        // Add the card view component, this will add it to the end\n        components.add(cardView);\n        \n        // Reverse the list because layered panes associate objects closer to layer 0 as being closer to the screen.\n        Collections.reverse(components);\n\n        // Add the cards to this pile view\n        for(Component comp : components) {\n            layeredPane.add(comp);\n            layeredPane.setLayer(comp, layerPosition);\n            Point offset = getCardOffset((CardView)comp);\n            comp.setBounds(new Rectangle(offset.x, offset.y, comp.getPreferredSize().width, comp.getPreferredSize().height));\n\n            ++layerPosition;\n        }\n        \n        parentCardView.repaint();\n        repaint();\n    }\n    \n    /**\n     * Gets the offset that should be set to the specified card view\n     *\n     * @param cardView The cardView\n     * \n     * @return The offset that this card should be at\n     */\n    protected abstract Point getCardOffset(CardView cardView);\n    \n    /**\n     * @return The components associated to the layered pane of this view, grouped by layer identifier.\n     */\n    protected final List<Component[]> getComponentsGroupedByLayer() {\n        List<Component[]> components = new ArrayList<Component[]>();\n        for(int i = 0; i <= layeredPane.highestLayer(); ++i) {\n            Component[] comps = layeredPane.getComponentsInLayer(i);\n            if(comps.length > 0) {\n                components.add(layeredPane.getComponentsInLayer(i));\n            }\n        }\n        \n        return components;\n    }\n    \n    @Override public void undoLastAction() {\n        List<Component> componentsList = Arrays.asList(layeredPane.getComponents());\n        for(Component comp : _previousCards) {\n            if(!componentsList.contains(comp)) {\n                addCard((CardView) comp);\n            }\n        }\n        \n        repaint();\n    }\n\n    @Override public void performBackup() {\n\n        // Get all the cards currently in the pile view\n        List<Component> allComponents = Arrays.asList(layeredPane.getComponents());\n        Collections.reverse(allComponents);\n        _previousCards.addAll(allComponents);\n        \n        // Attempt to get the card that is currently being dragged.\n        // Note: This is only valid in a non-outline scenario. In this scenario, the card that we are getting\n        //       here is the card that was clicked on. The subsequent cards that are being dragged along with it\n        //       if any can be found in the layered pane associated to this clicked card.\n        CardView cardView = AbstractFactory.getFactory(ViewFactory.class).get(GameView.class).getCardComponent();\n        if(cardView != null) {\n            _previousCards.add(cardView);\n            \n            List<Component> components = Arrays.asList(cardView.layeredPane.getComponents());\n            Collections.reverse(components);\n            \n            // Add any subsequent cards below the clicked card if any\n            for(Component comp : components) {\n                _previousCards.add(comp);\n            }\n        }\n    }\n\n    @Override public void clearBackup() {        \n        _previousCards.clear();\n    }\n        \n    @Override public void render() {\n        super.render();\n        for(Component component : layeredPane.getComponents()) {\n            if(component instanceof CardView) {\n                CardView view = (CardView) component;\n                view.render();\n            }\n        }\n        repaint();\n    }\n    \n    @Override public String toString() {\n        StringBuilder builder = new StringBuilder();\n        String header = \"========\" + this.getClass().getSimpleName().toUpperCase() + \"========\";\n        builder.append(header + System.getProperty(\"line.separator\"));\n        \n        for(Component comp : layeredPane.getComponents()) {\n            builder.append(comp + System.getProperty(\"line.separator\"));\n        }\n        builder.append(new String(new char[header.length()]).replace(\"\\0\", \"=\"));\n        \n        return builder.toString();\n    }\n}"
  },
  {
    "path": "src/game/views/CardOutlineView.java",
    "content": "package game.views;\n\nimport java.awt.Component;\nimport java.awt.Dimension;\nimport java.awt.Point;\nimport java.awt.Rectangle;\nimport java.awt.event.MouseAdapter;\nimport java.awt.event.MouseEvent;\nimport java.awt.event.MouseMotionAdapter;\nimport java.util.Arrays;\nimport java.util.Collections;\nimport java.util.List;\n\nimport javax.swing.BoxLayout;\nimport javax.swing.JLayeredPane;\nimport javax.swing.SwingUtilities;\nimport javax.swing.border.Border;\n\nimport framework.core.factories.AbstractFactory;\nimport framework.core.factories.ControllerFactory;\nimport framework.core.factories.ViewFactory;\nimport framework.core.mvc.view.PanelView;\nimport framework.core.mvc.view.layout.DragListener;\nimport framework.core.physics.CollisionListener;\nimport framework.core.physics.ICollidable;\nimport framework.utils.MouseListenerEvent;\nimport framework.utils.MouseListenerEvent.SupportedActions;\n\nimport game.controllers.MovementRecorderController;\nimport game.views.components.ExclusiveLineBorder;\n\n/**\n * This view represents the outline of a normal card view\n * \n * @author Daniel Ricci {@literal <thedanny09@icloud.com>}\n *\n */\npublic final class CardOutlineView extends PanelView {\n\n    /**\n     * The current bounds that have been set to this outline\n     */\n    private Rectangle _bounds = null;\n    \n    /**\n     * The card drag events for this outline view\n     * \n     * @author Daniel Ricci {@literal <thedanny09@icloud.com>}\n     *\n     */\n    private class CardDragEvents extends MouseMotionAdapter {\n        \n        private PanelView _collidedView = null;\n        \n        @Override public void mouseDragged(MouseEvent event) {\n            \n            if(!isEnabled()) {\n                return;\n            }\n            \n            // If we are dragging the mouse but the drag listener is not working properly go no further\n            if(!_dragListener.isDragging() || !_dragListener.getIsEnabled()) {\n            \treturn;\n            }\n            \n            ICollidable collider = _collisionListener.getCollision();\n            if(collider != null) {\n                \n                // Determine what the collision was with. Either it was with a card, or\n                // it is with the Foundation or an empty PileView\n                PanelView collidedView = (PanelView)collider;\n                \n                if(collidedView instanceof AbstractPileView) {\n                    CardView card = ((AbstractPileView)collidedView).getLastCard();\n                    if(card != null) {\n                        collidedView = card;\n                    }    \n                }\n                \n                // If there was something that was already collided with\n                // then remove the highlight\n                if(_collidedView != null) {\n                    _collidedView.setIsHighlighted(false);\n                }\n\n                // Set the newly collided view\n                _collidedView = collidedView;\n                _collidedView.setIsHighlighted(true);\n            }\n            else {\n                if(_collidedView != null) {\n                    _collidedView.setIsHighlighted(false);\n                }\n                _collidedView = null;\n            }\n        }\n    }\n\n    /**\n     * The card selection events for this outline view\n     * \n     * @author Daniel Ricci {@literal <thedanny09@icloud.com>}\n     *\n     */\n    private class CardSelectionEvents extends MouseListenerEvent {\n        \n        public CardSelectionEvents() {\n            super(SupportedActions.LEFT);\n        }\n        \n        @Override public void mousePressed(MouseEvent event) {\n\n            super.mousePressed(event);\n            if(event.isConsumed()) {\n                return;\n            }\n            \n            if(!isEnabled()) {\n                return;\n            }\n            \n            // Indicates if the auto move had occurred successfully\n            boolean hasAutomoveWorked = false;\n            \n            // If the click count is two then perform the double click event of the underlying card\n            // and go no further. This will handle cases where the outline mode is enabled, and the user\n            // double clicks to put a potential card in the foundation\n            if(event.getClickCount() == 2) {\n                \n                // Get a reference to the parent of the underlying card view\n                Component parent = _cardView.getParent();\n                \n                // Perform the double click operation\n                hasAutomoveWorked = _cardView.performCardAutoMovement();\n                if(hasAutomoveWorked) {\n                    // Stop the drag listener from dragging, this is because you could still drag when you have the\n                \t// second mouse down, and this causes the border outline to still render. This is also guard is other\n                \t// mouseDragged events in this class, where we check to see that the dragListener component is being dragged\n                    _dragListener.stopDragEvent();\n                }\n                \n                // Perform a repaint of the parent\n                parent.repaint();\n            }\n        \n            if(!hasAutomoveWorked) {\n\n                // Get the list of components that are in the parent container\n                Component[] components = ((JLayeredPane) _cardView.getParent()).getComponents();\n                \n                // Go through the list of cards until the one that is being dragged is found. This is done\n                // in a vanilla for loop so that we can take advantage of the index found\n                for(int i = components.length - 1; i >= 0; --i) {\n                    if(components[i].equals(_cardView)) {\n    \n                        // Get the list of cardviews from the found card view that is being dragged to the end\n                        List<CardView> cardViews = Arrays.asList(Arrays.copyOfRange(components, 0, i, CardView[].class));\n                        \n                        // Reverse the list so that when the iteration occurs, it uses the same ordering that is represente visually\n                        Collections.reverse(cardViews);\n    \n                        // Fixes a bug where the layered pane is chopped from the waist down\n                        _layeredPane.setSize(_layeredPane.getWidth(), _layeredPane.getHeight() + (cardViews.size() * 12));\n                       \n                        // Go through the list of cards and add them to the layered pane within the outline\n                        for(int j = 0; j < cardViews.size(); ++j) {\n                            CardOutlineView outline = cardViews.get(j).getOutlineView();\n                            _layeredPane.add(outline);\n                            _layeredPane.setLayer(outline, j);\n                            \n                            // The bounds here contains `-1` because I want the border to be perfectly overlapped\n                            outline.setBounds(new Rectangle(-1, 12 * (j + 1), cardViews.get(j).getPreferredSize().width, cardViews.get(j).getPreferredSize().height + _layeredPane.getHeight()));\n                        }\n    \n                        // Position the card at the same place where the drag was attempted from, because when you\n                        // add to the application it will position the component at the origin which is not desired\n                        Point initialLocation = _cardView.getLocation();\n                        \n                        // Update the bounds of the card view\n                        _bounds = new Rectangle(_cardView.getParent().getParent().getLocation().x + initialLocation.x + 1, _cardView.getParent().getParent().getLocation().y + initialLocation.y + 1, _layeredPane.getWidth(), _layeredPane.getHeight());\n                        \n                        // Get a reference to the game view and status view, and add the card into the proper\n                        // z-order so that it appears underneath the status bar, but over everything else in the game\n                        ViewFactory viewFactory = AbstractFactory.getFactory(ViewFactory.class);\n                        GameView gameView = viewFactory.get(GameView.class);\n                        StatusBarView statusBarView = viewFactory.get(StatusBarView.class);\n\n                        gameView.add(CardOutlineView.this, gameView.getComponentZOrder(statusBarView) + 1);\n                        gameView.repaint();\n\n                        // Do not continue iterating, the card was found so there is nothing left to do\n                        break;\n                    }\n                }            \n            }\n        }\n        \n        @Override public void mouseReleased(MouseEvent event) {\n            \n            super.mouseReleased(event);\n            if(event.isConsumed()) {\n                return;\n            }\n            \n            if(!isEnabled()) {\n                return;\n            }\n            \n            ICollidable collider = _collisionListener.getCollision();\n            _bounds = null;\n            \n            if(collider != null) {\n            \n                // Get a reference to the pile view that has has been collided with\n                AbstractPileView pileViewCollider = (AbstractPileView) collider;\n                \n                // Get the before movement type to know where the move is coming from\n                AbstractPileView fromPileView = (AbstractPileView) _cardView.getParent().getParent();\n\n                // Record that the movement occurred\n                AbstractFactory.getFactory(ControllerFactory.class).get(MovementRecorderController.class).recordMovement(fromPileView, pileViewCollider);\n                \n                // Unselect all the cards within this pile view to remove the outline xor'd highlight\n                pileViewCollider.removeHighlight();\n                \n                // Repaint the pile view\n                pileViewCollider.repaint();\n\n                // Add this card to the new location\n                int initialSize = pileViewCollider.layeredPane.getComponents().length;\n                pileViewCollider.layeredPane.add(_cardView);\n                pileViewCollider.layeredPane.setLayer(_cardView, initialSize);\n                Point offset = pileViewCollider.getCardOffset(_cardView);\n                _cardView.setBounds(new Rectangle(offset.x, offset.y, _cardView.getPreferredSize().width, _cardView.getPreferredSize().height));\n\n                // Increment the initial size to prepare for the other cards to be inserted\n                ++initialSize;\n                \n                // Get the list of layered components and go through each of them, adding each one\n                // to the proper destination\n                List<Component> layeredComponents = Arrays.asList(_layeredPane.getComponents());\n                Collections.reverse(layeredComponents);\n                for(int i = 0; i < layeredComponents.size(); ++i) {\n                    CardOutlineView outline = (CardOutlineView) layeredComponents.get(i);\n                    pileViewCollider.layeredPane.add(outline._cardView);\n                    pileViewCollider.layeredPane.setLayer(outline._cardView, initialSize + i);\n                    outline._cardView.add(outline);\n                    outline.setBorder(null);\n                    Point offsetOutline = pileViewCollider.getCardOffset(outline._cardView);\n                    outline._cardView.setBounds(new Rectangle(offsetOutline.x, offsetOutline.y, outline._cardView.getPreferredSize().width, outline._cardView.getPreferredSize().height));\n                }\n                _layeredPane.removeAll();\n                pileViewCollider.repaint();\n                \n\n            }\n            else {\n                Component[] layeredComponents = _layeredPane.getComponents();\n                for(int i = 0; i < layeredComponents.length; ++i) {\n                    CardOutlineView outline = (CardOutlineView) layeredComponents[i];\n                    outline._cardView.add(outline);\n                    outline.setBorder(null);\n                }\n            }\n\n            // Add the this outline back to it's underlying card view\n            CardOutlineView.this.setBorder(null);\n            _cardView.add(CardOutlineView.this);\n\n            // Repaint the components involved\n            ViewFactory viewFactory = AbstractFactory.getFactory(ViewFactory.class);\n            GameView gameView = viewFactory.get(GameView.class);\n            gameView.repaint();\n\n            _cardView.getParent().repaint();\n            \n            // Set the drag listener to be enabled. This is because it could have been disabled from other workflows, however if \n            // the code got this far it should be re-enabled\n            _dragListener.setEnabled(true);\n            \n            // See if the board is in a winning state\n            GameView.scanGameForWin();\n        }\n    }\n    \n    /**\n     * The layered pane that holds the potential list of cards that would be dragged along-side this card vuew\n     */\n    private final JLayeredPane _layeredPane = new JLayeredPane();\n\n    /**\n     * The draggable listener associated to this view\n     */\n    private final DragListener _dragListener = new DragListener(SupportedActions.LEFT);\n\n    /**\n     * The collision listener associated to this view\n     */\n    private final CollisionListener _collisionListener = new CollisionListener(this, SupportedActions.LEFT);\n    \n    /**\n     * The card view associated to this outline\n     */\n    private final CardView _cardView;\n    \n    /**\n     * The border layout associated to this view\n     */\n    private final Border _border = new ExclusiveLineBorder(1);\n    \n    /**\n     * Constructs a new instance of this class type\n     * \n     * @param cardView The card view to associate to this outline\n     */\n    public CardOutlineView(CardView cardView) {\n        setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));\n        setPreferredSize(new Dimension(CardView.CARD_WIDTH, CardView.CARD_HEIGHT));\n        setOpaque(false);\n        add(_layeredPane);\n        \n        addMouseListener(_dragListener);\n        addMouseMotionListener(_dragListener);\n        \n        addMouseListener(_collisionListener);\n        addMouseMotionListener(_collisionListener);\n        \n        addMouseListener(new CardSelectionEvents());\n        addMouseMotionListener(new CardDragEvents());\n        \n        // Set the controller of this outline to the same controller of the specified card\n        _cardView = cardView;\n        getViewProperties().setEntity(cardView.getViewProperties().getEntity());\n\n        addMouseListener(new MouseAdapter() {\n            @Override public void mousePressed(MouseEvent event) {\n                if(!SwingUtilities.isRightMouseButton(event)) {\n                    AbstractFactory.getFactory(ViewFactory.class).get(TimerView.class).startGameTimer();\n                    removeMouseListener(this);\n                }\n            }\n        });\n        \n        MouseListenerEvent mle = new MouseListenerEvent(SupportedActions.LEFT) {\n            @Override public void mouseDragged(MouseEvent event) {\n                super.mouseDragged(event);\n\n                // 1. Event is consumed\n                // 2. This card outline is not in an enabled state\n                // 3. The drag listener component is not in the state of being dragged\n                // 4. The drag listener is not enabled\n                if(event.isConsumed() || !isEnabled() || !_dragListener.isDragging() || !_dragListener.getIsEnabled()) {\n                \treturn;\n                }\n                \n                // If the border has not yet been set\n                if(getBorder() != _border) {\n                    \n                    // Set this border of this outline\n                    setBorder(_border);\n                    \n                    // Go through the list of outlines owned by this outline and show their borders\n                    // Note: On mouse release should handle removing the borders set withint his drag event\n                    for(Component component : _layeredPane.getComponents()) {\n                        if(component instanceof CardOutlineView) {\n                            CardOutlineView outline = ((CardOutlineView)component);\n                            outline.setBorder(outline._border);\n                        }\n                    }\n                }                    \n            }\n        };\n        addMouseListener(mle);\n        addMouseMotionListener(mle);\n    }\n    \n    @Override public void setEnabled(boolean enabled) {\n        super.setEnabled(enabled);\n        \n        // Propagate the state change to the card view. Ensure that no circular reference could ever occur\n        if(_cardView.isEnabled() != enabled) {\n            _cardView.setEnabled(enabled);\n        }\n        \n        _dragListener.setEnabled(enabled);\n        _collisionListener.setEnabled(enabled);\n    }\n    \n    @Override public void setBounds(int x, int y, int width, int height) {\n    \t//System.out.printf(\"(%d,%d,%d%d)\\n\", x, y, width, height);\n\n    \t// Prevent issues related to the view being updated because of other components, causing this component\n        // to be position improperly.\n        if(_bounds != null && !_dragListener.isDragging()) {\n            super.setBounds(_bounds.x, _bounds.y, _bounds.width, _bounds.height);\n        }\n        else if(y != 6) {\n            super.setBounds(x, y, width, height);\n        }\n    }\n}"
  },
  {
    "path": "src/game/views/CardView.java",
    "content": "package game.views;\n\nimport java.awt.Color;\nimport java.awt.Component;\nimport java.awt.Dimension;\nimport java.awt.Graphics;\nimport java.awt.Point;\nimport java.awt.Rectangle;\nimport java.awt.event.MouseAdapter;\nimport java.awt.event.MouseEvent;\nimport java.util.Arrays;\nimport java.util.Collections;\nimport java.util.List;\nimport java.util.Optional;\nimport java.util.logging.Level;\n\nimport javax.swing.BoxLayout;\nimport javax.swing.JLayeredPane;\nimport javax.swing.SwingUtilities;\n\nimport framework.api.IView;\nimport framework.communication.internal.signal.ISignalReceiver;\nimport framework.communication.internal.signal.arguments.EventArgs;\nimport framework.core.factories.AbstractFactory;\nimport framework.core.factories.ControllerFactory;\nimport framework.core.factories.ViewFactory;\nimport framework.core.graphics.IRenderable;\nimport framework.core.mvc.view.PanelView;\nimport framework.core.mvc.view.layout.DragListener;\nimport framework.core.physics.CollisionListener;\nimport framework.core.physics.ICollidable;\nimport framework.utils.MouseListenerEvent;\nimport framework.utils.MouseListenerEvent.SupportedActions;\nimport framework.utils.logging.Tracelog;\n\nimport game.config.OptionsPreferences;\nimport game.config.OptionsPreferences.DrawOption;\nimport game.controllers.CardController;\nimport game.controllers.MovementRecorderController;\nimport game.models.CardModel;\nimport game.views.helpers.ViewHelper;\n\n/**\n * This view represents the representation of a single card\n * \n * @author Daniel Ricci {@literal <thedanny09@icloud.com>}\n *\n */\npublic final class CardView extends PanelView implements ICollidable {\n\n    /**\n     * The card selection events for this outline view\n     * \n     * @author Daniel Ricci {@literal <thedanny09@icloud.com>}\n     *\n     */\n    private final class CardSelectionEvents extends MouseListenerEvent {\n        \n        /**\n         * The parent layer pane\n         */\n        private JLayeredPane _parentLayeredPane;\n        \n        /**\n         * The parent panel view\n         */\n        private IView _parentPanelView;\n        \n        /**\n         * Constructs a new instance of this class type\n         */\n        public CardSelectionEvents() {\n            super(SupportedActions.LEFT);\n        }\n        \n        @Override public void mousePressed(MouseEvent event) {\n            super.mousePressed(event);\n            if(getIsConsumed() && event.isConsumed()) {\n                return;\n            }\n            \n            if(!isEnabled()) {\n                return;\n            }\n            \n            // Get the parent of this card view, used as a reference to go back to whatever we were coming from\n            _parentLayeredPane = (JLayeredPane) CardView.this.getParent();\n            \n            // Get the parent IView w.r.t this card view, this is used to make sure that we are not trying to collide with ourselves\n            _parentPanelView = CardView.this.getParentIView();\n\n            // Get the list of components that the parent owns\n            Component[] components =_parentLayeredPane.getComponents();\n\n            // Find the card that is being dragged and take all the siblings below it and populate them into the\n            // layered pane composed by the CardView.this reference\n            mainLabel : for(int i = components.length - 1; i >= 0; --i) {\n\n                if(components[i].equals(CardView.this)) {\n\n                    // Get the siblings of cards within the components list (excluding CardView.this)\n                    List<CardView> cardViews = Arrays.asList(Arrays.copyOfRange(components, 0, i, CardView[].class));\n\n                    // Reverse the list because layered panes associate objects closer to layer 0 as being closer to the screen.\n                    Collections.reverse(cardViews);\n\n                    // Fixes a bug where the layered pane is chopped from the waist down\n                    CardView.this.layeredPane.setSize(layeredPane.getWidth(), layeredPane.getHeight() + (cardViews.size() * 15));\n                    \n                    // For each sibling add it into the associated layered pane and position it correctly within\n                    // the pane, accounting for the fact that CardView.this is the temporary 'root'\n                    for(int j = 0; j < cardViews.size(); ++j) {\n                        layeredPane.add(cardViews.get(j));\n                        layeredPane.setLayer(cardViews.get(j), j);\n                        \n                        // Account for the border offsets of -1 for left and bottom\n                        cardViews.get(j).setBounds(new Rectangle(0, (15 * (j + 1)), cardViews.get(j).getPreferredSize().width, cardViews.get(j).getPreferredSize().height));\n                        _parentLayeredPane.remove(cardViews.get(j));\n                    }\n\n                    // Position the card at the same place where the drag was attempted from, because when you\n                    // add to the application it will position the component at the origin which is not desired\n                    Point initialLocation = CardView.this.getLocation();\n                    \n                    // Note: Add +2 to the width and height because of the initial border size offset\n                    Rectangle rectangle = new Rectangle(_parentLayeredPane.getParent().getLocation().x + initialLocation.x, _parentLayeredPane.getParent().getLocation().y + initialLocation.y, layeredPane.getWidth(), layeredPane.getHeight());\n                    CardView.this.setBounds(rectangle);\n\n                    // Remove the card view reference from it's initial parent\n                    _parentLayeredPane.remove(CardView.this);\n                    \n                    // Get a reference to the game view and status view, and add the card into the proper\n                    // z-order so that it appears underneath the status bar, but over everything else in the game\n                    ViewFactory viewFactory = AbstractFactory.getFactory(ViewFactory.class);\n                    GameView gameView = viewFactory.get(GameView.class);\n                    StatusBarView statusBarView = viewFactory.get(StatusBarView.class);\n\n                    gameView.add(CardView.this, gameView.getComponentZOrder(statusBarView) + 1);\n                    gameView.repaint();\n\n                    break mainLabel;\n                }\n            }\n        }\n\n        @Override public void mouseReleased(MouseEvent event) {\n            \n            super.mouseReleased(event);\n            if(getIsConsumed() && event.isConsumed()) {\n                return;\n            }\n            \n            if(!isEnabled()) {\n                return;\n            }\n            \n            if(_parentLayeredPane == null) {\n                _parentPanelView = null;\n                return;\n            }\n            \n            // If there is a valid collider, set that as the new parent\n            if(_collisionListener.getCollision() != null) {\n                AbstractPileView pileView = (AbstractPileView) _collisionListener.getCollision();\n                \n                // Do not go further if what we have collided with is where we were already, that is not considered a valid collision.\n                // Note: Should this go inside of the drag listener?\n                if(!pileView.equals(_parentPanelView)) { \n                    // Get the before movement type to know where the move is coming from\n                    Optional<Component> layeredPane = Arrays.asList(pileView.getComponents()).stream().filter(z -> z.getClass() == JLayeredPane.class).findFirst();\n                    if(layeredPane.isPresent()) {\n                        AbstractFactory.getFactory(ControllerFactory.class).get(MovementRecorderController.class).recordMovement((IUndoable)_parentLayeredPane.getParent(), pileView);                  \n                        _parentLayeredPane = (JLayeredPane) layeredPane.get();\n                    }\n                    else {\n                        Tracelog.log(Level.SEVERE, true, \"Could not find JLayeredPane within the CardView mouseReleased event...\");\n                        return;\n                    }\n                }\n            }\n            \n            // Get the offset that was set, and use this within our calculations\n            AbstractPileView parent = (AbstractPileView) _parentLayeredPane.getParent();\n            parent.addCard(CardView.this);\n            _parentLayeredPane = null;\n            _parentPanelView = null;\n        }\n    }\n    \n    /**\n     * This mouse adapter handles events when the card is pressed with the mouse\n     */\n    private MouseListenerEvent _mouseActionListener = new MouseListenerEvent(SupportedActions.LEFT) {\n        @Override public void mousePressed(MouseEvent event) {\n            super.mousePressed(event);\n            if(getIsConsumed() && event.isConsumed()) {\n                return;\n            }\n            \n            if(!isEnabled()) {\n                return;\n            }\n\n            if(CardView.this.getParent().getComponents()[0].equals(CardView.this)) {\n                if(event.getClickCount() == 1) {\n                    uncoverBackside(false);\n                }\n                else {\n                    performCardAutoMovement();\n                }\n            }\n        }\n    };\n    \n    /**\n     * The preferred width of this card\n     */\n    public static final int CARD_WIDTH = 71;\n\n    /**\n     * The preferred height of this card\n     */\n    public static final int CARD_HEIGHT = 96;\n\n    /**\n     * The controller associated to this card view\n     */\n    private CardController _controller;\n\n    /**\n     * The draggable listener associated to this view\n     */\n    private final DragListener _dragListener = new DragListener(SupportedActions.LEFT);\n\n    /**\n     * The collision listener associated to this view\n     */\n    private final CollisionListener _collisionListener = new CollisionListener(this, SupportedActions.LEFT);\n\n    /**\n     * The layered pane that holds the potential list of cards that would be dragged along-side this card vuew\n     */\n    protected final JLayeredPane layeredPane = new JLayeredPane();\n   \n    /**\n     * Indicates if selections are enabled\n     */\n    private boolean _highlightsEnabled;\n    \n    /**\n     * The card selection events associated to this card view\n     */\n    private final CardSelectionEvents _cardSelectionEvents = new CardSelectionEvents();\n    \n    /**\n     * The card outline associated to this view\n     */\n    private CardOutlineView _cardOutline;\n    \n    /**\n     * Signal indicating that this view should synchronizr with the outline option\n     */\n    public final static String EVENT_OUTLINE_SYNCHRONIZE = \"EVENT_OUTLINE_SYNCHRONIZE\";\n    \n    private CardView() {\n        getViewProperties().setShouldAlwaysRedraw(true);\n        setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));\n        setPreferredSize(new Dimension(CARD_WIDTH, CARD_HEIGHT));\n        setOpaque(false);\n        setBackground(Color.BLACK);\n        \n        add(layeredPane);\n    }\n    \n    /**\n     * Constructs a new instance of this class type\n     * \n     * @param cardModel The cards model underlying this card view\n     */\n    public CardView(CardModel cardModel) {\n        this();\n        \n        cardModel.addListener(this);\n        _controller = new CardController(cardModel);\n        getViewProperties().setEntity(_controller);   \n\n        // Create the card outline view and render it\n        _cardOutline = new CardOutlineView(this);\n        _cardOutline.render();\n        \n        addMouseListener(_dragListener);\n        addMouseMotionListener(_dragListener);\n        \n        addMouseListener(_collisionListener);\n        addMouseMotionListener(_collisionListener);\n        \n        // Add the mouse listener responsible for handling single clicks and double clicks on this card.\n        // Note: This will sometimes not be called depending on if the outline is enabled or not, since the \n        //       outline sits on top of this card. However, when the backside is being shown, this would indeed\n        //       be called, however the double click will not be called since the single click will\n        //       initiate the outline, thus the double click of the outline will be called\n        //\n        // Note: This mouse listener should be before any other mouse listener within this class\n        addMouseListener(_mouseActionListener);\n\n        addMouseListener(new MouseAdapter() {\n            @Override public void mousePressed(MouseEvent event) {\n                if(!SwingUtilities.isRightMouseButton(event)) {\n                    AbstractFactory.getFactory(ViewFactory.class).get(TimerView.class).startGameTimer();\n                    removeMouseListener(this);\n                }\n            }\n        });\n        \n        // Register this view and it's underlying outline to perform auto moves\n        ViewHelper.registerForCardsAutocomplete(this);\n        ViewHelper.registerForCardsAutocomplete(_cardOutline);\n        \n        // Register this view to handle the events raised by the card selection events\n        addMouseListener(_cardSelectionEvents);\n        addMouseMotionListener(_cardSelectionEvents);\n        \n        // Listen in on events when we need to synchronize withthe online option\n        addSignal(EVENT_OUTLINE_SYNCHRONIZE, new ISignalReceiver<EventArgs>() {\n            @Override public void signalReceived(EventArgs event) {\n                synchronizeWithOptions();\n\n                // When playing in draw three, make sure that cards that are not top-most are not enabled. This\n                // needs to be done after the synchronize.\n                OptionsPreferences optionsPreferences = new OptionsPreferences();\n                optionsPreferences.load();\n                if(optionsPreferences.drawOption == DrawOption.THREE && CardView.this.getParentIView().getClass() == TalonPileView.class) {\n                    if(((JLayeredPane)getParent()).getPosition(CardView.this) > 0) {\n                        _dragListener.setEnabled(false);\n                        _collisionListener.setEnabled(false);\n                        _cardSelectionEvents.setEnabled(false);\n                    }\n                }\n            }\n        });       \n        synchronizeWithOptions();\n    }\n    \n    public static CardView createLightWeightCard(CardView cardView) {\n        CardView newCardView = new CardView();\n        newCardView.setEnabled(cardView.isEnabled());\n        cardView.getRenderableContent().forEach(z -> newCardView.addRenderableContent(z));\n        return newCardView;\n    }\n    \n    /**\n     * Synchronizes this card view w.r.t the current outline options that are set within the game.\n     */\n    private void synchronizeWithOptions() {\n        // Verify if the option for highlighting is enabled or not\n        OptionsPreferences optionsPreferences = new OptionsPreferences();\n        optionsPreferences.load();\n        _highlightsEnabled = optionsPreferences.outlineDragging;\n\n        // If the card has its backside shown or the outline option is enabled\n        // then do not allow dragging or collision to work as normal\n        boolean isAvailable = !_controller.getCard().getIsBackside() && !optionsPreferences.outlineDragging;\n        _dragListener.setEnabled(isAvailable);\n        _collisionListener.setEnabled(isAvailable);\n        \n        // If the backside is not being shown, then add the event handler for card drag event\n        // Note: In the event that the options preferences calls for outline mode, the entire\n        //       operation of performing a click-down, click-up, should be done by outline and\n        //       not this card explicitely.\n        if(!_controller.getCard().getIsBackside()) {\n            if(!optionsPreferences.outlineDragging) {\n                remove(_cardOutline);\n            }\n            else {\n                add(_cardOutline);\n            }\n        } \n        \n        // The selection events associated to this view should only be enabled if the\n        // backside is not shown and the outline mode is not enabled\n        _cardSelectionEvents.setEnabled(!_controller.getCard().getIsBackside() && !optionsPreferences.outlineDragging);\n    }\n    \n    /**\n     * @return The card outline associated to this view\n     */\n    public CardOutlineView getOutlineView() {\n        return _cardOutline;\n    }\n    \n    /**\n     * Attempts to uncover the backside of this view\n     * \n     * @param forceBackside TRUE if the backside should be force uncovered, FALSE otherwise\n     */\n    public void uncoverBackside(boolean forceBackside) {\n        if(_controller.getCard().getIsBackside()) {\n            _controller.getCard().setBackside(false);\n            _controller.getCard().refresh();\n            \n            // Record the movement\n            if(!forceBackside) {\n                AbstractFactory.getFactory(ControllerFactory.class).get(MovementRecorderController.class).recordMovement((IUndoable)CardView.this.getParentIView(), null);\n            }\n\n            // Only allow this card view to have dragging and collision working `vanilla`\n            // style if the outline option is not selected\n            OptionsPreferences preferences = new OptionsPreferences();\n            preferences.load();\n            if(!preferences.outlineDragging) {\n                _dragListener.setEnabled(true);\n                _collisionListener.setEnabled(true);\n                _cardSelectionEvents.setEnabled(true);\n            }\n            \n            if(preferences.outlineDragging) {\n                add(_cardOutline);\n                _cardOutline.setVisible(true);\n            }\n            \n            repaint();\n        }\n    }\n    \n    /**\n     * @return TRUE of the backside is showing, FALSE otherwise\n     */\n    public boolean isBacksideShowing() {\n        return _controller.getCard().getIsBackside();\n    }\n    \n    /**\n     * Performs an auto card movement, attempting to move this card to the foundation\n     * \n     * @return TRUE if the auto movement was successfull, FALSE otherwise\n     */\n    public boolean performCardAutoMovement() {\n        return performCardAutoMovement(false);\n    }\n\n    /**\n     * Performs an auto card movement, attempting to move this card to the foundation\n     * \n     * @param forcefully If the movement is forcefully being done (when the user cheats to win the game)\n     * \n     * @return TRUE if the auto movement was successfull, FALSE otherwise\n     */\n    public boolean performCardAutoMovement(boolean forcefully) {\n        if(!_controller.getCard().getIsBackside() && !(getParentIView() instanceof FoundationPileView)) {\n            \n            // Make sure that we are not double clicking on an ACE. That doesn't make much sense here in this case\n            if(AbstractFactory.getFactory(ViewFactory.class).getAll(FoundationPileView.class).stream().anyMatch(z -> z.layeredPane.getComponentCount() == 1 && z.layeredPane.getComponents()[0] == CardView.this)) {\n                return false;\n            }\n            \n            // Get the list of foundation views. \n            List<FoundationPileView> foundationViews = AbstractFactory.getFactory(ViewFactory.class).getAll(FoundationPileView.class);\n            \n            // Reverse the list, so that the card populating the left-most foundation view, this just looks a lot better\n            Collections.reverse(foundationViews);\n            \n            // Go through the list of foundation views and see if there is a match\n            for(FoundationPileView foundationView : foundationViews) {\n                if(foundationView.isValidCollision(CardView.this)) {\n                    \n                    if(!forcefully) {\n                        // Record the fact that a movement occurred \n                        AbstractFactory.getFactory(ControllerFactory.class).get(MovementRecorderController.class).recordMovement((AbstractPileView)CardView.this.getParentIView(), foundationView);\n                    }\n                    \n                    // Stop the current drag listener of this card from doing anything, so that things\n                    // like drag will stop being processed\n                    _dragListener.stopDragEvent();\n                    \n                    // Add to the layered pane destination\n                    foundationView.addCard(CardView.this);\n                                        \n                    // Repaint the components\n                    layeredPane.repaint();\n                    foundationView.repaint();\n                   \n                    // Repaint the game view, this will fix a rendering bug where in outline mode, the status bar and\n                    // the tableau view would not render properly. Look at bug #128.\n                    AbstractFactory.getFactory(ViewFactory.class).get(GameView.class).repaint();\n                    \n                    return true;\n                }\n            }                            \n        }\n        \n        return false;\n    }\n    \n    @Override public void setEnabled(boolean enabled) {\n        super.setEnabled(enabled);\n        \n        // Propagate the state change to the outline. Ensure that no circular reference could ever occur\n        if(_cardOutline != null && _cardOutline.isEnabled() != enabled) {\n            _cardOutline.setEnabled(enabled);\n        }\n\n        _dragListener.setEnabled(enabled);\n        _collisionListener.setEnabled(enabled);\n    }\n    \n    @Override public void preprocessGraphics(IRenderable renderableData, Graphics context) {        \n        super.preprocessGraphics(renderableData, context);\n        if(_highlightsEnabled && getIsHighlighted()) {\n            context.setXORMode(Color.WHITE);\n        }\n    }\n    \n    @Override public void removeAll() {\n        super.removeAll();\n        _dragListener.setEnabled(false);\n        _collisionListener.setEnabled(false);\n    }\n\n    @Override public void render() {\n    \tsuper.render();\n    \t\n    \t// Fixes a bug where clicking and then eventually dragging the cards causes a ton of issues with the size\n    \trenderProperties.x = 0;\n        renderProperties.y = 0;\n        renderProperties.width = this.getPreferredSize().width;\n        renderProperties.height = this.getPreferredSize().height;\n    \t\n        if(_controller != null) {\n            _controller.refresh();\n        }\n    }\n\n    @Override public void update(EventArgs event) {\n        super.update(event);\n        addRenderableContent((IRenderable)event.getSource()); \n        repaint();\n    }\n    \n    @Override public void setBounds(int x, int y, int width, int height) {\n        // For now, this is here to fix a bug where the timer updating on the status bar will\n        // cause a revalidation of the gridbag that the game view has, causing the card that is dragging\n        // to be reset to the `origin`.\n    \t//System.out.printf(\"(%d,%d,%d%d)\\n\", x, y, width, height);\n\n        if(x == 13 && y == 6) {\n            return;\n        }\n\n        super.setBounds(x, y, width, height);\n    }\n        \n    @Override public String toString() {\n        // Hold onto the layer position\n        int layer = JLayeredPane.getLayer(this);\n        \n        // Attempt to get the position within the layer.\n        int positionWithinLayer = -1;\n        if(this.getParent() instanceof JLayeredPane) {\n            JLayeredPane parentLayeredPane = (JLayeredPane) this.getParent();\n            List<Component> components = Arrays.asList(parentLayeredPane.getComponentsInLayer(layer));\n            positionWithinLayer = components.indexOf(CardView.this);\n        }\n        return String.format(\"%s%s%s\\t[%d][%d]\",\n            isVisible() ? \"[V]\" : \"[H]\",\n            isEnabled() ? \"[E]\" : \"[D]\",\n            getViewProperties().getEntity(CardController.class).getCard(),\n            layer,\n            positionWithinLayer\n        );\n    }\n    \n    @Override public boolean isValidCollision(Component source) {\n        IView view = (IView)source;\n\n        // A card is coming into this card, and we are on the foundation view\n        if(getParent().getParent() instanceof FoundationPileView) {\n            CardController thisCardViewController = view.getViewProperties().getEntity(CardController.class);\n            return _controller.isValidFoundationMove(thisCardViewController.getCard());            \n        }\n        // The card is coming onto this card which is on the pile view (should be, there are only two options for this game)\n        else {\n            CardController cardViewController = this.getViewProperties().getEntity(CardController.class);\n            return cardViewController.getCard().isCardBeforeAndOppositeSuite(view.getViewProperties().getEntity(CardController.class).getCard());\n        }\n    }\n\n    @Override public void onCollisionStart(Component source) {\n        // Set the opaque to true to color in the card. It is originally false so \n        // that the corners with are transparent will not be shown, since setting this\n        // to true forces the card dimensions to show something.\n        this.setOpaque(true);\n    }\n\n    @Override public void onCollisionStop(Component source) {\n        // Set the opaque back to false which is the default for all cards\n        this.setOpaque(false);\n    }\n}"
  },
  {
    "path": "src/game/views/DeckSelectionDialogView.java",
    "content": "package game.views;\n\nimport java.awt.Color;\nimport java.awt.Dimension;\nimport java.awt.FlowLayout;\nimport java.awt.GridBagConstraints;\nimport java.awt.GridBagLayout;\nimport java.awt.Insets;\nimport java.awt.event.ActionEvent;\nimport java.awt.event.ActionListener;\nimport java.awt.event.MouseAdapter;\nimport java.awt.event.MouseEvent;\nimport java.util.ArrayList;\nimport java.util.List;\n\nimport javax.swing.BorderFactory;\nimport javax.swing.BoxLayout;\nimport javax.swing.DefaultButtonModel;\nimport javax.swing.ImageIcon;\nimport javax.swing.JButton;\nimport javax.swing.JOptionPane;\nimport javax.swing.JPanel;\n\nimport framework.core.entity.DataEntity;\nimport framework.core.mvc.view.DialogView;\nimport framework.core.system.Application;\nimport framework.utils.globalisation.Localization;\n\nimport game.config.OptionsPreferences;\n\nimport generated.DataLookup;\nimport generated.DataLookup.BACKSIDES;\n\n/**\n * The deck selection dialog view shows the list of deck images that the user can choose from while playing the game\n *\n * @author Daniel Ricci {@literal <thedanny09@icloud.com>}\n *\n */\npublic final class DeckSelectionDialogView extends DialogView {\n\n    /**\n     * This class represents a model that is used within one of the deck buttons\n     * \n     * @author Daniel Ricci {@literal <thedanny09@icloud.com>}\n     */\n    private class FixedStateButtonModel extends DefaultButtonModel {\n        @Override public boolean isPressed() {\n            return false;\n        }\n        @Override public boolean isRollover() {\n            return false;\n        }\n        @Override public boolean isArmed() {\n            return false;\n        }\n        @Override public boolean isSelected() {\n            return false;\n        }\n    }\n    \n    /**\n     * The number of rows in the card list\n     */\n    private final int _cardRows = 2;\n    \n    /**\n     * The number of columns in the card list\n     */\n    private final int _cardColumns = 6;\n    \n    /**\n     * The button width\n     */\n    private final int _buttonWidth = 45;\n            \n    /**\n     * The button height\n     */\n    private final int _buttonHeight = 74;\n    \n    /**\n     * The image width of the button\n     */\n    private final int _buttonImageWidth = 39;\n    \n    /**\n     * The image height of the button\n     */\n    private final int _buttonImageHeight = 68;\n    \n    /**\n     * The OK button\n     */\n    private final JButton _okButton = new JButton(\"OK\");\n    \n    /**\n     * The Cancel button\n     */\n    private final JButton _cancelButton = new JButton(\"Cancel\");\n    \n    /**\n     * The current active button\n     */\n    private JButton _activeButton;\n    \n    /**\n     * The list of buttons that hold a deck option\n     */\n    private final List<JButton> _deckButtons = new ArrayList<JButton>();\n    \n    /**\n     * Constructs a new instance of this class type\n     */\n    public DeckSelectionDialogView() {\n        super(Application.instance, Localization.instance().getLocalizedString(\"Select Card Back\"));\n        getContentPane().setLayout(new BoxLayout(getContentPane(), BoxLayout.Y_AXIS));\n        setAutomaticDialogCentering(true);\n        setModal(true);\n        setAlwaysOnTop(true);\n        setResizable(false);\n    }\n    \n    @Override protected void enterActionPerformed(ActionEvent event) {\n        _okButton.doClick();\n    }\n    \n    @Override public void render() {\n        \n        // Get a reference to all the backside data values\n        DataLookup.BACKSIDES[] backsides = DataLookup.BACKSIDES.values();\n        \n        // Set the initial constraints for the grid bag layout\n        GridBagConstraints drawPanelConstraints = new GridBagConstraints();\n        drawPanelConstraints.weighty = 1;\n        drawPanelConstraints.weightx = 1;\n        drawPanelConstraints.insets = new Insets(5, 5, 5, 5);\n        \n        // The panel that holds the list of cards\n        JPanel cardPanel = new JPanel(new GridBagLayout());\n        \n        OptionsPreferences preferences = new OptionsPreferences();\n        preferences.load();\n        \n        // Go through card rows and card columns, and populate each index with a JButton\n        // containing one of the card images\n        for(int row = 0, index = 0; row < _cardRows; ++row) {\n            drawPanelConstraints.gridy = row;\n            for(int column = 0; column < _cardColumns; ++column, ++index) {\n                \n                // Create the backside entity and assign it to the button\n                //BacksideCardEntity entity = new BacksideCardEntity();\n                DataEntity entity = new DataEntity(backsides[index].identifier);\n                \n                // Create the button and set the size we want it to be\n                JButton button = new JButton(new ImageIcon(entity.getRenderableContent().getScaledInstance(_buttonImageWidth, _buttonImageHeight, java.awt.Image.SCALE_SMOOTH)));\n                \n                // Set the border of the button based on what was currently set in the preferences, and make sure to set it as active within this dialog\n                if(preferences.deck == backsides[index]) {\n                    button.setBorder(BorderFactory.createLineBorder(Color.BLUE, 2));\n                    _activeButton = button;\n                }\n                \n                button.setModel(new FixedStateButtonModel());\n                button.setContentAreaFilled(false);\n                button.setFocusPainted(false);\n                button.setPreferredSize(new Dimension(_buttonWidth, _buttonHeight));\n                button.putClientProperty(button, backsides[index]);\n                \n                // Add a listener event for when the deck image is selected\n                button.addMouseListener(new MouseAdapter() {\n                    @Override public void mousePressed(MouseEvent event) {\n                        _deckButtons.forEach(z -> z.setBorder(BorderFactory.createEmptyBorder()));\n                        button.setBorder(BorderFactory.createLineBorder(Color.BLUE, 2));\n                        _activeButton = button;\n                        // If more than one click count was registered, then do what the OK button would do.\n                        // Note that I don't call doClick because I don't want the OK button to look like it was clicked\n                        if(event.getClickCount() > 1) {\n                            ok();\n                        }\n                    }\n                });\n                \n                // Add a reference to the list of buttons\n                _deckButtons.add(button);\n                \n                // Specify the proper column constraint\n                drawPanelConstraints.gridx = column;\n                \n                // Add the button to the panel\n                cardPanel.add(button, drawPanelConstraints);\n            }\n        }\n\n        // The OK button action event\n        _okButton.addActionListener(new ActionListener() {\n            @Override public void actionPerformed(ActionEvent event) {\n                ok();\n            }\n        });\n\n        // The Cancel button action event        \n        _cancelButton.addActionListener(new ActionListener() {\n            @Override public void actionPerformed(ActionEvent event) {\n                cancel();\n            }\n        });\n        \n        // Add the okay and cancel buttons\n        JPanel actionsPanel = new JPanel(new FlowLayout(FlowLayout.CENTER));\n        actionsPanel.add(_okButton);\n        actionsPanel.add(_cancelButton);\n        \n        // Add the main housing panels to this dialog\n        add(cardPanel);\n        add(actionsPanel);\n        \n        // Pack the UI to fit\n        pack();\n\n        // Render the UI\n        super.render();\n    }\n    \n    private void cancel() {\n    \tsetDialogResult(JOptionPane.CANCEL_OPTION);\n        setVisible(false);\n    }\n    \n    private void ok() {\n        BACKSIDES back = (BACKSIDES) _activeButton.getClientProperty(_activeButton);\n        OptionsPreferences preferences = new OptionsPreferences();\n        preferences.load();\n        \n        if(preferences.deck == back) {\n        \tcancel();\n        }\n        else {\n        \tpreferences.deck = back;\n\t        preferences.save();\n\t        setDialogResult(JOptionPane.OK_OPTION);\n\t        setVisible(false);\n\t    }\n    }\n}"
  },
  {
    "path": "src/game/views/FoundationPileView.java",
    "content": "package game.views;\n\nimport java.awt.Color;\nimport java.awt.Component;\nimport java.awt.Dimension;\nimport java.awt.Graphics;\nimport java.awt.Point;\nimport java.awt.event.MouseAdapter;\nimport java.awt.event.MouseEvent;\n\nimport javax.swing.SwingUtilities;\n\nimport framework.api.IView;\nimport framework.communication.internal.signal.arguments.EventArgs;\nimport framework.core.factories.AbstractFactory;\nimport framework.core.factories.ViewFactory;\nimport framework.core.graphics.IRenderable;\nimport framework.core.physics.ICollidable;\n\nimport game.controllers.CardController;\nimport game.entities.FoundationCardEntity;\nimport game.views.helpers.ViewHelper;\n\n/**\n * This view represents the foundation pile view\n * \n * @author Daniel Ricci {@literal <thedanny09@icloud.com>}\n */\npublic final class FoundationPileView extends AbstractPileView implements ICollidable {\n\n    /**\n     * Creates a new instance of this class type\n     */\n    public FoundationPileView() {\n        \n        // The background the the opaqueness of this view\n        // must be set this way to achieve the proper xor effect\n        this.setBackground(Color.BLACK);\n        this.setOpaque(true);\n        addRenderableContent(new FoundationCardEntity());\n        ViewHelper.registerForCardsAutocomplete(this);\n        \n        addMouseListener(new MouseAdapter() {\n            @Override public void mousePressed(MouseEvent event) {\n                if(!SwingUtilities.isRightMouseButton(event)) {\n                    AbstractFactory.getFactory(ViewFactory.class).get(TimerView.class).startGameTimer();\n                    removeMouseListener(this);\n                }\n            }\n        });\n    }\n\n    @Override public void preprocessGraphics(IRenderable renderableData, Graphics context) {\n        super.preprocessGraphics(renderableData, context);\n        if(getIsHighlighted() && layeredPane.getComponentCount() == 0) {\n            context.setXORMode(Color.WHITE);\n        }\n    }\n    \n    @Override public Dimension getPreferredSize() {\n        return new Dimension(CardView.CARD_WIDTH, CardView.CARD_HEIGHT);\n    }\n\n    @Override public void update(EventArgs event) {\n        super.update(event);\n        repaint();\n    }\n\n    @Override public boolean isValidCollision(Component source) {\n        if (layeredPane.getComponentCount() == 0) {\n            return ((IView) source).getViewProperties().getEntity(CardController.class).getCard().getCardEntity().isAceCard();\n        } else {\n            CardView thisCardView = (CardView) layeredPane.getComponent(0);\n            return thisCardView.isValidCollision(source);\n        }\n    }\n\n    @Override public void addCard(CardView cardView) {\n        super.addCard(cardView);\n        GameView.scanGameForWin();\n    }\n\n    @Override protected Point getCardOffset(CardView cardView) {\n        return new Point(0, 0);\n    }\n\n    @Override public void onCollisionStart(Component source) {\n        CardView cardView = this.getLastCard();\n        if(cardView != null) {\n            cardView.onCollisionStart(source);\n        }\n    }\n\n    @Override public void onCollisionStop(Component source) {\n        CardView cardView = this.getLastCard();\n        if(cardView != null) {\n            cardView.onCollisionStop(source);\n        }\n    }\n}"
  },
  {
    "path": "src/game/views/GameView.java",
    "content": "package game.views;\n\nimport java.awt.Color;\nimport java.awt.Component;\nimport java.awt.GridBagConstraints;\nimport java.awt.GridBagLayout;\nimport java.awt.Insets;\nimport java.awt.event.MouseAdapter;\nimport java.awt.event.MouseEvent;\nimport java.util.ArrayList;\nimport java.util.List;\n\nimport javax.swing.AbstractButton;\nimport javax.swing.JOptionPane;\nimport javax.swing.SwingUtilities;\n\nimport framework.core.factories.AbstractFactory;\nimport framework.core.factories.ControllerFactory;\nimport framework.core.factories.ViewFactory;\nimport framework.core.mvc.view.PanelView;\nimport framework.core.navigation.MenuBuilder;\nimport framework.core.system.Application;\nimport framework.utils.globalisation.Localization;\n\nimport game.config.OptionsPreferences;\nimport game.controllers.MovementRecorderController;\nimport game.menu.NewGameMenuItem;\nimport game.models.CardModel;\nimport game.views.helpers.ViewHelper;\nimport game.views.helpers.WinAnimationHelper;\n\nimport resources.LocalizationStrings;\n\n/**\n * The game view wraps a draggable layout around the entire game\n * \n * @author {@literal Daniel Ricci {@literal <thedanny09@icloud.com>}}\n *\n */\npublic final class GameView extends PanelView {\n\n    /**\n     * Creates a new instance of this class type\n     */\n    public GameView() {\n        this.setLayout(new GridBagLayout());\n        this.setBackground(new Color(0, 128, 0));\n        \n        // Configure constraint initial values\n        final int _rowSize = 2;\n        final int _columnSize = 7;\n        GridBagConstraints gameConstraints = new GridBagConstraints();\n        gameConstraints.weightx = 1.0;\n        gameConstraints.anchor = GridBagConstraints.NORTH;\n        \n        ViewFactory viewFactory = AbstractFactory.getFactory(ViewFactory.class);\n        \n        // Create the total list of cards\n        List<CardModel> cards = CardModel.newInstances();\n        \n        // Create the globally available movement controller\n        AbstractFactory.getFactory(ControllerFactory.class).add(new MovementRecorderController(), true);\n        \n        for(int row = _rowSize - 1; row >= 0; --row) {\n            gameConstraints.gridy = row;\n\n            if(gameConstraints.gridy ==  1) {\n                gameConstraints.weighty = 1;\n                gameConstraints.insets = new Insets(10, 0, 0, 0);\n                gameConstraints.fill = GridBagConstraints.VERTICAL;\n            }\n            else {\n                gameConstraints.weighty = 0;\n                gameConstraints.insets = new Insets(10, 0, 0, 0);\n            }\n\n            for(int col = _columnSize - 1; col >= 0; --col) {\n                gameConstraints.gridx = col;\n                \n                if(gameConstraints.gridy == 0) {\n                    switch(gameConstraints.gridx) {\n                    case 0: {\n                        // Create the stock view \n                        StockView stockView = viewFactory.add(new StockView(), true);\n                        GridBagConstraints constraints = (GridBagConstraints)gameConstraints.clone();\n                        constraints.insets = new Insets(gameConstraints.insets.top, 4, 0, 0);\n                        this.add(stockView, constraints);\n                        break;\n                    }\n                    case 1: {\n                        // Create the talon view\n                        TalonPileView talonView = viewFactory.add(new TalonPileView(cards), true);\n                        GridBagConstraints constraints = (GridBagConstraints)gameConstraints.clone();\n                        constraints.insets = new Insets(gameConstraints.insets.top, 0, -5, -30);\n                        constraints.ipadx = 30;\n                        constraints.ipady = 5;\n                        this.add(talonView, constraints, 0);                        \n                        break;\n                    }\n                    case 3:\n                    case 4:\n                    case 5:\n                    case 6:\n                        // Create the foundation view\n                        FoundationPileView foundationView = viewFactory.add(new FoundationPileView());\n                        GridBagConstraints constraints = (GridBagConstraints)gameConstraints.clone();\n                        constraints.fill = GridBagConstraints.NONE;\n                        this.add(foundationView, constraints);\n                    break;\n                    }\n                }\n                else {\n                    \n                    List<CardModel> subList = cards.subList(0, gameConstraints.gridx + 1);\n                    TableauPileView view = viewFactory.add(new TableauPileView(new ArrayList<CardModel>(subList)));\n                    subList.clear();\n                    \n                    this.add(view, gameConstraints);\n                }\n            }\n        }\n        \n        addStatusBarView();\n        addMouseListener(new MouseAdapter() {\n            @Override public void mousePressed(MouseEvent event) {\n                OptionsPreferences preferences = new OptionsPreferences();\n                preferences.load();\n                if(preferences.timedGame) {\n                    if(!SwingUtilities.isRightMouseButton(event)) {\n                        AbstractFactory.getFactory(ViewFactory.class).get(TimerView.class).startGameTimer();\n                        removeMouseListener(this);\n                    }\n                }\n            }\n        });\n        \n        ViewHelper.registerForCardsAutocomplete(this);\n    }\n    \n    /**\n     * Adds the status bar view to this view\n     */\n    private void addStatusBarView() {\n        StatusBarView statusBarView = AbstractFactory.getFactory(ViewFactory.class).add(new StatusBarView(), true);\n        GridBagConstraints barConstraints = new GridBagConstraints(); \n        barConstraints.anchor = GridBagConstraints.SOUTH;\n        barConstraints.gridx = 0;\n        barConstraints.gridy = 1;\n        barConstraints.fill = GridBagConstraints.HORIZONTAL;\n        barConstraints.weightx = 1.0;\n        barConstraints.weighty = 1.0;\n        barConstraints.gridwidth = 7;\n        barConstraints.insets = new Insets(0, -2, 0, -2);\n        add(statusBarView, barConstraints, 0);\n    }\n    \n    /**\n     * Gets the current card component used on this view. This is the card\n     * that would exist when performing a drag operation\n     *\n     * @return The currently dragged card of this view\n     */\n    public CardView getCardComponent() {\n        for(Component comp : getComponents()) {\n            if(comp instanceof CardView) {\n                return (CardView) comp;\n            }\n        }\n        \n        return null;\n    }\n    \n    /**\n     * Scans the board for a win condition\n     */\n    public static void scanGameForWin() {\n        boolean isWinner = true;\n        for(FoundationPileView foundationView : AbstractFactory.getFactory(ViewFactory.class).getAll(FoundationPileView.class)) {\n            if(foundationView.layeredPane.getComponentCount() != 13) {\n                isWinner = false;\n                break;\n            }\n        }\n        \n        if(isWinner) {\n            processWin();\n        }\n    }\n    \n    /**\n     * Forces the game to win\n     */\n    public static void forceGameWin() {\n        \n        List<CardView> cards = AbstractFactory.getFactory(ViewFactory.class).getAll(CardView.class);\n        cards.stream().forEach(z -> z.uncoverBackside(true));\n        cards.stream().forEach(z -> z.setVisible(true));\n        \n        while(cards.size() > 0) {\n            boolean keepGoing = false;\n            for(int i = 0; i < cards.size(); ++i) {\n                if(cards.get(i).performCardAutoMovement(true)) {\n                    cards.get(i).setEnabled(false);\n                    cards.remove(i);\n                    keepGoing = true;\n                    break;\n                }\n            }\n            \n            if(!keepGoing) {\n                break;\n            }\n        }\n    }\n    \n    /**\n     * Process the events that will occur after a win has been detected \n     */\n    private static void processWin() {\n        // Stop the game timer\n        TimerView gameTimerView = AbstractFactory.getFactory(ViewFactory.class).get(TimerView.class);\n        gameTimerView.stop();\n\n        // Update the score with the bonus\n        long bonus = AbstractFactory.getFactory(ViewFactory.class).get(ScoreView.class).updateScoreBonus(gameTimerView.getTime());\n        \n        // Show the updated text on the status bar\n        AbstractFactory.getFactory(ViewFactory.class).get(StatusBarView.class).setMenuDescription(String.format(Localization.instance().getLocalizedString(LocalizationStrings.GAME_WON_STATUS_BAR), bonus));\n        \n        // Perform the animation on all the cards\n        WinAnimationHelper.processCards();\n    }\n    \n    /**\n     * Shows the game over dialog, prompting the user to choose what they would like to do\n     */\n    public static void showGameOverDialog() {\n        // Show the dialog indicating that game has won\n        if(JOptionPane.showConfirmDialog(Application.instance, Localization.instance().getLocalizedString(LocalizationStrings.GAME_OVER), Localization.instance().getLocalizedString(LocalizationStrings.GAME_OVER_HEADER), JOptionPane.YES_NO_OPTION, JOptionPane.WARNING_MESSAGE) == JOptionPane.YES_OPTION) { \n            MenuBuilder.search(Application.instance.getJMenuBar(), NewGameMenuItem.class).getComponent(AbstractButton.class).doClick();\n        }\n        else {\n            // Clear the description and other status bar texts\n            AbstractFactory.getFactory(ViewFactory.class).get(StatusBarView.class).clearMenuDescription();\n\n            \n            GameView gameView = AbstractFactory.getFactory(ViewFactory.class).get(GameView.class);\n            // Get the tree and synchronize against it. Exceptions will be thrown during the removal process if we dont\n            synchronized(gameView.getTreeLock()) {\n                Component[] components = AbstractFactory.getFactory(ViewFactory.class).get(GameView.class).getComponents();\n                for(int i = 0; i < components.length; ++i) {\n                    if(!(components[i] instanceof StatusBarView)) {\n                        gameView.remove(components[i]);\n                    }\n                }\n                Application.instance.repaint();\n            }                \n        }\n    }\n}"
  },
  {
    "path": "src/game/views/IUndoable.java",
    "content": "package game.views;\n\nimport framework.api.IView;\n\n/**\n * Defines the functionality required to perform an undo operation on a particular component\n * \n * @author Daniel Ricci {@literal <thedanny09@icloud.com>}\n */\npublic interface IUndoable extends IView {    \n           \n    /**\n     * Performs an undo based on the last backup that was performed on this component\n     */\n    public void undoLastAction();\n\n    /**\n     * Performs a logical backup with respect to the state and business logic of this component\n     */\n    public void performBackup();\n    \n    /**\n     * Clears the backup associated to this component\n     */\n    public void clearBackup();\n}"
  },
  {
    "path": "src/game/views/OptionsDialogView.java",
    "content": "package game.views;\n\nimport java.awt.FlowLayout;\nimport java.awt.GridLayout;\nimport java.awt.event.ActionEvent;\nimport java.awt.event.ActionListener;\nimport java.awt.event.ItemEvent;\nimport java.awt.event.ItemListener;\n\nimport javax.swing.BorderFactory;\nimport javax.swing.BoxLayout;\nimport javax.swing.ButtonGroup;\nimport javax.swing.JButton;\nimport javax.swing.JCheckBox;\nimport javax.swing.JOptionPane;\nimport javax.swing.JPanel;\nimport javax.swing.JRadioButton;\n\nimport framework.core.mvc.view.DialogView;\nimport framework.core.system.Application;\nimport framework.utils.globalisation.Localization;\n\nimport game.config.OptionsPreferences;\nimport game.config.OptionsPreferences.DrawOption;\nimport game.config.OptionsPreferences.ScoringOption;\n\n/**\n * The options view shows the settings that change the way the game is played\n *\n * @author Daniel Ricci {@literal <thedanny09@icloud.com>}\n *\n */\npublic final class OptionsDialogView extends DialogView {\n\n    /**\n     * Indicates if the options that were changed (if any) require the game to reset to take effect\n     */\n    public boolean refreshGameRequired;\n    \n    /**\n     * Indicates if the status bar option has changed since it's last saved value\n     */\n    public boolean statusBarChanged;\n    \n    /**\n     * Indicates if the outline dragging option has changed since it's last saved value\n     */\n    public boolean outlineDraggingChanged;\n    \n    /**\n     * Indicates if the cumulative score option has changed since it's last saved value\n     */\n    public boolean cumulativeScoreChanged;\n    \n    // The OK button\n    private JButton okButton = new JButton(\"OK\");\n    \n    /**\n     * Constructs a new instance of this class type\n     */\n    public OptionsDialogView() {\n        super(Application.instance, Localization.instance().getLocalizedString(\"Options\"));\n        \n        // Properties of this view\n        getContentPane().setLayout(new BoxLayout(getContentPane(), BoxLayout.Y_AXIS));\n        setAutomaticDialogCentering(true);\n        setModal(true);\n        setAlwaysOnTop(true);\n        setResizable(false);\n        \n        // The main panel that houses this view\n        JPanel mainPanel = new JPanel();\n        \n        // Use a grid to lay out the contents\n        mainPanel.setLayout(new GridLayout(2, 2));\n        \n        // Load the option for this view\n        OptionsPreferences preferences = new OptionsPreferences();\n        preferences.load();\n        \n        // Draw radio buttons\n        GridLayout drawPanelGridLayout = new GridLayout(2, 1);\n        drawPanelGridLayout.setVgap(-10);\n        JPanel drawPanel = new JPanel();\n        drawPanel.setLayout(drawPanelGridLayout);\n        drawPanel.setBorder(BorderFactory.createTitledBorder(\"Draw\"));\n        JRadioButton drawOneRadioButton = new JRadioButton(\"Draw One\", preferences.drawOption == DrawOption.ONE);\n        drawOneRadioButton.putClientProperty(drawOneRadioButton, DrawOption.ONE);\n        JRadioButton drawThreeRadioButton = new JRadioButton(\"Draw Three\", preferences.drawOption == DrawOption.THREE);\n        drawThreeRadioButton.putClientProperty(drawThreeRadioButton, DrawOption.THREE);\n        \n        // Button group for the draw radio buttons\n        ButtonGroup drawPanelGroup = new ButtonGroup();\n        drawPanelGroup.add(drawOneRadioButton);\n        drawPanelGroup.add(drawThreeRadioButton);\n        drawPanel.add(drawOneRadioButton);\n        drawPanel.add(drawThreeRadioButton);\n\n        // Scoring Panel UI\n        GridLayout scoringPanelGridLayout = new GridLayout(3, 1);\n        scoringPanelGridLayout.setVgap(-5);\n        JPanel scoringPanel = new JPanel();\n        scoringPanel.setLayout(scoringPanelGridLayout);\n        scoringPanel.setBorder(BorderFactory.createTitledBorder(\"Scoring\"));\n        \n        // Scoring radio buttons\n        JRadioButton standardRadioButton = new JRadioButton(\"Standard\", preferences.scoringOption == ScoringOption.STANDARD);\n        standardRadioButton.putClientProperty(standardRadioButton, ScoringOption.STANDARD);\n        JRadioButton vegasRadioButton = new JRadioButton(\"Vegas\", preferences.scoringOption == ScoringOption.VEGAS);\n        vegasRadioButton.putClientProperty(vegasRadioButton, ScoringOption.VEGAS);\n        JRadioButton noneRadioButton = new JRadioButton(\"None\", preferences.scoringOption == ScoringOption.NONE);\n        noneRadioButton.putClientProperty(noneRadioButton, ScoringOption.NONE);\n        \n        // Button group for the scoring radio buttons\n        ButtonGroup scoringPanelGroup = new ButtonGroup();\n        scoringPanelGroup.add(standardRadioButton);\n        scoringPanelGroup.add(vegasRadioButton);\n        scoringPanelGroup.add(noneRadioButton);\n        scoringPanel.add(standardRadioButton);\n        scoringPanel.add(vegasRadioButton);\n        scoringPanel.add(noneRadioButton);\n\n        // Left side options\n        GridLayout leftSideGridLayout = new GridLayout(3, 1);\n        JPanel barOptionsPanelLeft = new JPanel();\n        barOptionsPanelLeft.setLayout(leftSideGridLayout);\n\n        // Mutually exclusive checkbox settings\n        JCheckBox timedGameCheckBox = new JCheckBox(\"Timed Game\", preferences.timedGame); \n        barOptionsPanelLeft.add(timedGameCheckBox);\n        JCheckBox statusBarCheckBox = new JCheckBox(\"Status Bar\", preferences.statusBar);\n        barOptionsPanelLeft.add(statusBarCheckBox);\n        JCheckBox outlineDraggingCheckbox = new JCheckBox(\"Outline Dragging\", preferences.outlineDragging);\n        barOptionsPanelLeft.add(outlineDraggingCheckbox);\n        \n        // Right side options\n        JPanel barOptionsPanelRight = new JPanel();\n        barOptionsPanelRight.setLayout(new BoxLayout(barOptionsPanelRight, BoxLayout.Y_AXIS));\n        JCheckBox cumulativeScoreCheckBox = new JCheckBox(\"Cumulative Score\", preferences.cumulativeScore);\n        cumulativeScoreCheckBox.setEnabled(vegasRadioButton.isSelected());\n        \n        // Add an item listener to the vegas radio button to alter the state of the cumulative score\n        vegasRadioButton.addItemListener(new ItemListener() {\n            @Override public void itemStateChanged(ItemEvent event) {\n                cumulativeScoreCheckBox.setEnabled(event.getStateChange() == ItemEvent.SELECTED);\n            }\n        });\n\n        barOptionsPanelRight.add(cumulativeScoreCheckBox);\n\n        okButton.addActionListener(new ActionListener() {\n            @Override public void actionPerformed(ActionEvent event) {\n                \n                // Draw panel result\n                JRadioButton drawPanelSelection = drawOneRadioButton.isSelected() ? drawOneRadioButton : drawThreeRadioButton;\n                DrawOption drawOptionNew = (DrawOption)drawPanelSelection.getClientProperty(drawPanelSelection);\n                refreshGameRequired = preferences.drawOption != drawOptionNew;\n                preferences.drawOption = drawOptionNew;\n                \n                // Scoring result\n                JRadioButton scoringPanelSelection = null;\n                if(standardRadioButton.isSelected()) {\n                    scoringPanelSelection = standardRadioButton;\n                }\n                else if(vegasRadioButton.isSelected()) {\n                    scoringPanelSelection = vegasRadioButton;\n                }\n                else {\n                    scoringPanelSelection = noneRadioButton;\n                }\n                ScoringOption scoringOption = (ScoringOption)scoringPanelSelection.getClientProperty(scoringPanelSelection);\n                refreshGameRequired |= scoringOption != preferences.scoringOption;\n                preferences.scoringOption = scoringOption;\n                \n                // Timed game\n                boolean timedGame = timedGameCheckBox.isSelected();\n                refreshGameRequired |= timedGame != preferences.timedGame;\n                preferences.timedGame = timedGame;\n                \n                // Status bar\n                boolean statusBar = statusBarCheckBox.isSelected();\n                statusBarChanged = preferences.statusBar != statusBar;\n                preferences.statusBar = statusBar;\n                \n                // Outline dragging\n                boolean outlineDragging = outlineDraggingCheckbox.isSelected();\n                outlineDraggingChanged = preferences.outlineDragging != outlineDragging;\n                preferences.outlineDragging = outlineDragging;\n                \n                // Cumulative Score\n                boolean cumulativeScore = cumulativeScoreCheckBox.isSelected();\n                cumulativeScoreChanged = preferences.cumulativeScore != cumulativeScore;\n                preferences.cumulativeScore = cumulativeScore;\n                \n                // Save the contents of the preferences and then close this dialog\n                preferences.save();\n                setDialogResult(JOptionPane.OK_OPTION);\n                setVisible(false);\n            }\n        });\n        \n        // The Cancel button\n        JButton cancelButton = new JButton(\"Cancel\");\n        cancelButton.addActionListener(new ActionListener() {\n            @Override public void actionPerformed(ActionEvent event) {\n                setDialogResult(JOptionPane.CANCEL_OPTION);\n                setVisible(false);\n            }\n        });\n        \n        // Add the OK button and the Cancel button\n        JPanel actionsPanel = new JPanel(new FlowLayout(FlowLayout.CENTER));\n        actionsPanel.add(okButton);\n        actionsPanel.add(cancelButton);\n\n        // Add the sub-panels to the main panel\n        mainPanel.add(drawPanel);\n        mainPanel.add(scoringPanel);\n        mainPanel.add(barOptionsPanelLeft);\n        mainPanel.add(barOptionsPanelRight);\n        \n        // Add the main panel and the action panel to the main view;\n        add(mainPanel);\n        add(actionsPanel);\n    }\n    \n    @Override protected void enterActionPerformed(ActionEvent event) {\n        super.enterActionPerformed(event);\n        this.okButton.doClick();\n    }\n}"
  },
  {
    "path": "src/game/views/ScoreView.java",
    "content": "package game.views;\n\nimport java.awt.Color;\nimport java.awt.FlowLayout;\n\nimport javax.swing.JLabel;\n\nimport framework.communication.internal.signal.arguments.EventArgs;\nimport framework.core.mvc.view.PanelView;\nimport framework.utils.globalisation.Localization;\n\nimport game.config.OptionsPreferences;\nimport game.config.OptionsPreferences.DrawOption;\nimport game.config.OptionsPreferences.ScoringOption;\nimport game.models.MovementModel;\nimport game.models.MovementModel.MovementType;\n\nimport resources.LocalizationStrings;\n\n/**\n * This view shows the game score\n * \n * @author Daniel Ricci {@literal <thedanny09@icloud.com>}\n */\npublic class ScoreView extends PanelView {\n\n    /**\n     * The label that represents the title of this class\n     */\n    protected final JLabel scoreTitle = new JLabel(Localization.instance().getLocalizedString(LocalizationStrings.SCORE_TITLE));\n    \n    /**\n     * The label that represents the visual representation of this class\n     */\n    protected final JLabel scoreValue = new JLabel();\n    \n    /**\n     * The current score \n     */\n    protected static long SCORE_CURRENT;\n    \n    /**\n     * The previous score\n     */\n    @SuppressWarnings(\"unused\")\n    private static long SCORE_BEFORE = SCORE_CURRENT;\n    \n    /**\n     * Constructs a new instance of this class type\n     */\n    public ScoreView() {\n        this.setBackground(Color.WHITE);\n\n        // Set the VGap so that the score renders appropriately\n        FlowLayout layout = (FlowLayout) this.getLayout();\n        layout.setVgap(0);\n\n        add(scoreTitle);\n        add(scoreValue);\n    }\n    \n    /**\n     * Adds the specified offset to the current score.\n     *\n     * @param offsetToScore The score to offset the current score with, a +- value of something defined on your end\n     */\n    protected void addToScore(long offsetToScore) {\n        SCORE_CURRENT = Math.max(0, SCORE_CURRENT + offsetToScore);\n        scoreValue.setText(toString());        \n    }\n    \n    /**\n     * Adds the specified offset to the current score. This method will perform a backup of what the\n     * score previously was. How this method differs from the `addToScore` method is that it\n     * is friendly for performing an undo.\n     * \n     * The reason to not call this method over the other is in the case where the score being perform\n     * could not ever be undone, such as when 10 seconds has elapsed and the score loses -2, you can never\n     * get that back so dont backup the score there\n     *\n     * @param offsetToScore The score to offset the current score with, a +- value of something defined on your end\n     */\n    private void addToScoreAndBackup(long offsetToScore) {\n        SCORE_BEFORE = SCORE_CURRENT;\n        addToScore(offsetToScore);\n    }\n       \n    /**\n     * Updates the score based on the bonus logic\n     *\n     * @param seconds The number of seconds that has elapsed in the game\n     * \n     * @return The bonus that will be used\n     */\n    public long updateScoreBonus(long seconds) {\n        long bonus = 0;\n        \n        if(seconds > 30) {\n            bonus = 700000 / seconds;\n            addToScore(bonus);\n        }\n        \n        return bonus;\n    }\n    \n    /**\n     * Updates the score based on the specified deck plays.\n     *\n     * @param deckPlays The number of decks played\n     */\n    public void updateScoreDeckFinished(int deckPlays) {\n        OptionsPreferences preferences = new OptionsPreferences();\n        preferences.load();\n        \n        if(preferences.drawOption == DrawOption.THREE && preferences.scoringOption == ScoringOption.STANDARD) {\n            if(deckPlays > 3) {\n                addToScoreAndBackup(-20);\n            }\n        }\n        else {\n            addToScoreAndBackup(-100);    \n        }\n    }\n    \n    /**\n     * Updates the score based on a timer interval tick of the game\n     */\n    public void updateScoreTimerTick() {\n        addToScore(-2);\n    }\n    \n    /**\n     * Updates the score based on a cards' backside being revealed\n     */\n    public void updateScoreCardTurnOver() {\n        addToScore(5);\n    }\n    \n    /**\n     * Updates the score based on an operation\n     *\n     * @param from where the operation started from\n     * @param to where the operation ended at\n     * @param isUndo If the operation being done is an undo operation\n     * \n     */\n     protected void updateScore(MovementType from, MovementType to, boolean isUndo) {\n         long scoreFromMovement = getMovementScore(from, to, isUndo); \n         addToScoreAndBackup(scoreFromMovement + (isUndo ? - 2 : 0));\n     }\n     \n    private long getMovementScore(MovementType from, MovementType to, boolean isUndo) {\n        \n        long score = 0;\n        \n        if(from == MovementType.TALON && to == MovementType.TABLEAU) {\n            score = 5;\n        }\n        else if(from == MovementType.TALON && to == MovementType.FOUNDATION) {\n            score = 10;\n        }\n        else if (from == MovementType.TABLEAU && to == MovementType.FOUNDATION) {\n            score = 10;\n        }\n        else if(from == MovementType.FOUNDATION && to == MovementType.TABLEAU) {\n            score = -15;\n        }\n        \n        // If the score is being undone then flip the sign of the score\n        if(isUndo) {\n            score *= -1;\n        }\n        \n        return score;\n    }\n     \n    @Override public void render() {\n        super.render();\n        addToScore(0);\n    }\n    \n    @Override public void destructor() {\n        super.destructor();\n        SCORE_CURRENT = 0;\n        SCORE_BEFORE = 0;\n    }\n        \n    @Override public String toString() {\n        return String.valueOf(SCORE_CURRENT);\n    }\n    \n    @Override public final void update(EventArgs event) {\n        if(event.getSource() instanceof MovementModel) {\n            MovementModel movement = (MovementModel) event.getSource();\n            updateScore(movement.getFrom(), movement.getTo(), movement.getIsUndo());\n        }\n    }\n}"
  },
  {
    "path": "src/game/views/StatusBarView.java",
    "content": "package game.views;\n\nimport java.awt.BorderLayout;\nimport java.awt.Color;\nimport java.awt.Dimension;\nimport java.awt.event.MouseAdapter;\nimport java.awt.event.MouseEvent;\n\nimport javax.swing.BorderFactory;\nimport javax.swing.JLabel;\nimport javax.swing.JPanel;\nimport javax.swing.border.EmptyBorder;\n\nimport framework.core.factories.AbstractFactory;\nimport framework.core.factories.ControllerFactory;\nimport framework.core.factories.ViewFactory;\nimport framework.core.mvc.view.PanelView;\n\nimport game.config.OptionsPreferences;\nimport game.config.OptionsPreferences.ScoringOption;\nimport game.controllers.MovementRecorderController;\n\npublic final class StatusBarView extends PanelView {\n\n    /**\n     * The game timer view\n     */\n    private final TimerView _gameTimerView = AbstractFactory.getFactory(ViewFactory.class).add(new TimerView(), true);\n    \n    /**\n     * The game score view\n     */\n    private ScoreView _scoreView = null;\n    \n    /**\n     * The menu description label\n     */\n    private final JLabel _menuDescription = new JLabel();\n    \n    /**\n     * Constructs a new instance of this class type\n     */\n    public StatusBarView() {\n        this.setBackground(Color.WHITE);\n\n        this.setLayout(new BorderLayout());\n        this.setPreferredSize(new Dimension(getPreferredSize().width, 17));\n        this.setFocusable(false);\n        setBorder(BorderFactory.createMatteBorder(1, 0, 0, 0, Color.GRAY));\n        \n        // Add a dummy mouse listener to avoid the click from hitting the green background\n        addMouseListener(new MouseAdapter() {\n            @Override public void mousePressed(MouseEvent event) {\n            }\n        });\n        \n        // Menu Descrition\n        _menuDescription.setBorder(new EmptyBorder(0, 5, 0, 0));\n        add(_menuDescription, BorderLayout.WEST);\n        \n        // Game Score + Game Timer\n        JPanel rightSidePanel = new JPanel(new BorderLayout());\n        rightSidePanel.setBorder(BorderFactory.createEmptyBorder());\n\n        \n        // The scoring option should only be shown in Standard and Vegas scoring modes\n        OptionsPreferences preferences = new OptionsPreferences();\n        preferences.load();\n        \n        // Create the score view based on the currently set scoring standard      \n        _scoreView = AbstractFactory.getFactory(ViewFactory.class).add(preferences.scoringOption == ScoringOption.VEGAS ? new VegasScoreView() : new ScoreView(), true);\n        _scoreView.setBorder(null);\n        _scoreView.render();\n        \n        // register the score view to recieve events from the movement controller\n        AbstractFactory.getFactory(ControllerFactory.class).get(MovementRecorderController.class).addSignalListener(_scoreView);\n        \n        if(preferences.scoringOption != ScoringOption.NONE) {\n            rightSidePanel.add(_scoreView,BorderLayout.WEST);    \n        }\n        \n        rightSidePanel.add(_gameTimerView, BorderLayout.EAST);\n        add(rightSidePanel, BorderLayout.EAST); \n        \n        // Synchronize w.r.t the currently set options\n        synchronizeWithOptions();\n    }\n    \n    /**\n     * Sets the menu description\n\n     * @param text The description to set\n     */\n    public void setMenuDescription(String text) {\n        _menuDescription.setText(text);\n    }\n    \n    /**\n     * Convenience method to clear the text\n     */\n    public void clearMenuDescription() {\n        setMenuDescription(\"\");\n    }\n    \n    /**\n     * Synchronizes the options results w.r.t the status bar and it's related content\n     */\n    public void synchronizeWithOptions() {\n        OptionsPreferences preferences = new OptionsPreferences();\n        preferences.load();\n        this.setVisible(preferences.statusBar);\n        _gameTimerView.setVisible(preferences.timedGame);\n        _scoreView.setVisible(preferences.scoringOption != ScoringOption.NONE);\n    }\n    \n    @Override public void render() {\n        synchronizeWithOptions();\n    }\n}"
  },
  {
    "path": "src/game/views/StockView.java",
    "content": "package game.views;\r\n\r\nimport java.awt.Dimension;\r\nimport java.awt.Graphics;\r\nimport java.awt.event.MouseAdapter;\r\nimport java.awt.event.MouseEvent;\r\nimport java.util.ArrayList;\r\nimport java.util.List;\r\n\r\nimport javax.swing.SwingUtilities;\r\n\r\nimport framework.communication.internal.signal.ISignalReceiver;\r\nimport framework.communication.internal.signal.arguments.EventArgs;\r\nimport framework.communication.internal.signal.arguments.ViewEventArgs;\r\nimport framework.core.factories.AbstractFactory;\r\nimport framework.core.factories.ViewFactory;\r\nimport framework.core.graphics.IRenderable;\r\nimport framework.core.mvc.view.PanelView;\r\nimport framework.utils.MouseListenerEvent;\r\nimport framework.utils.MouseListenerEvent.SupportedActions;\r\n\r\nimport game.entities.BacksideCardEntity;\r\nimport game.entities.StockCardEntity;\r\nimport game.views.TalonPileView.TalonCardState;\r\nimport game.views.helpers.DeckAnimationHelper;\r\nimport game.views.helpers.ViewHelper;\r\n\r\nimport generated.DataLookup;\r\n\r\n/**\r\n * This view handles the functionality related to the Stock. This view will show the \r\n * collated cards view based on the deck face, and when you click on this view it will\r\n * cause the Talon to update the card list that it holds.\r\n * \r\n * @author Daniel Ricci {@literal <thedanny09@icloud.com>}\r\n */\r\npublic final class StockView extends PanelView implements IUndoable {\r\n \r\n    /**\r\n     * The list of card entities that make up this view\r\n     */\r\n    private final List<StockCardEntity> _stockCardEntities = new ArrayList<StockCardEntity>() {{\r\n       add(new StockCardEntity());\r\n       add(new StockCardEntity());\r\n       add(new StockCardEntity());\r\n    }};\r\n        \r\n    /**\r\n     * A reference to the Talon view. This is stored so that we don't need to query the view factory to get the Talon\r\n     * which is costly given where it is being used\r\n     */\r\n    private final TalonPileView _talonView = AbstractFactory.getFactory(ViewFactory.class).get(TalonPileView.class);\r\n    \r\n    /**\r\n     * Constructs a new instance of this class type\r\n     */\r\n    public StockView() {\r\n        setOpaque(false);\r\n        ViewHelper.registerForCardsAutocomplete(this);\r\n        \r\n        addMouseListener(new MouseAdapter() {\r\n            @Override public void mousePressed(MouseEvent event) {\r\n                if(!SwingUtilities.isRightMouseButton(event)) {\r\n                    AbstractFactory.getFactory(ViewFactory.class).get(TimerView.class).startGameTimer();\r\n                    removeMouseListener(this);\r\n                }\r\n            }\r\n        });        \r\n        addMouseListener(new MouseListenerEvent(SupportedActions.LEFT) {\r\n            @Override public void mousePressed(MouseEvent event) {\r\n                \r\n                super.mousePressed(event);\r\n                if(getIsConsumed()) {\r\n                    return;\r\n                }\r\n\r\n                _talonView.cycleNextHand();\r\n                \r\n                TalonCardState talonState = _talonView.getState();\r\n                if(talonState == TalonCardState.DECK_PLAYED) {\r\n                    if(_talonView.isTalonEnded()) {\r\n                        _stockCardEntities.get(0).enableTalonEnd();\r\n                    }\r\n                    else {\r\n                        _stockCardEntities.get(0).enableTalonRecycled();\r\n                    }\r\n                    \r\n                    DeckAnimationHelper.getInstance().setScene(_stockCardEntities);\r\n                }\r\n                else {\r\n\r\n                \tStockCardEntity stockCardEntity = _stockCardEntities.get(0);\r\n                \tBoolean needsUpdate = stockCardEntity.getActiveDataIdentifier() == DataLookup.MISC.TALON_RESTART.identifier || stockCardEntity.getActiveDataIdentifier() == DataLookup.MISC.TALON_END.identifier;\r\n\r\n                    _stockCardEntities.remove(0);\r\n                    _stockCardEntities.add(0, new StockCardEntity());\r\n                    \r\n                    if(needsUpdate) {\r\n                        DeckAnimationHelper.getInstance().setScene(_stockCardEntities);\r\n                    }\r\n                    \r\n                    if(!SwingUtilities.isRightMouseButton(event)) {\r\n                        AbstractFactory.getFactory(ViewFactory.class).get(TimerView.class).startGameTimer();\r\n                    }\r\n                }\r\n                \r\n                // Force an update to occur. We don't really need to worry about data binding\r\n                // for something as straight forward as updating this view\r\n                update(new ViewEventArgs(StockView.this, \"\"));\r\n            }\r\n        });        \r\n        addSignal(BacksideCardEntity.DECK_BACKSIDE_CHANGED, new ISignalReceiver<EventArgs>() {\r\n            @Override public void signalReceived(EventArgs event) {\r\n                _stockCardEntities.stream().forEach(z -> z.refresh());\r\n                DeckAnimationHelper.getInstance().setScene(_stockCardEntities);\r\n            }\r\n        });\r\n        addSignal(DeckAnimationHelper.DECK_ANIMATION_UPDATED, new ISignalReceiver<EventArgs>() {\r\n            @Override public void signalReceived(EventArgs event) {\r\n            \t//repaint();\r\n            }\r\n        });\r\n    }\r\n    \r\n    @Override public void preprocessGraphics(IRenderable renderableData, Graphics context) {\r\n        super.preprocessGraphics(renderableData, context);\r\n        \r\n        int index = -1;\r\n        for(StockCardEntity stockCardEntity : _stockCardEntities) {\r\n            if(stockCardEntity.equals(renderableData)) {\r\n                index = _stockCardEntities.indexOf(stockCardEntity);\r\n                break;\r\n            }\r\n        }\r\n        \r\n        switch(index)\r\n        {\r\n        case 0:\r\n            this.renderProperties.canDraw = true;\r\n            this.renderProperties.x = 0;\r\n            this.renderProperties.y = 0;\r\n            this.renderProperties.width = CardView.CARD_WIDTH;\r\n            this.renderProperties.height = CardView.CARD_HEIGHT;\r\n            break;\r\n        case 1:\r\n            this.renderProperties.canDraw = _stockCardEntities.get(0).getBacksideVisible() && _talonView.isPhaseTwo();\r\n            this.renderProperties.x = 2; \r\n            this.renderProperties.y = 1;\r\n            this.renderProperties.width = CardView.CARD_WIDTH;\r\n            this.renderProperties.height = CardView.CARD_HEIGHT;\r\n\r\n            break;\r\n        case 2:\r\n            this.renderProperties.canDraw = _stockCardEntities.get(0).getBacksideVisible() && _talonView.isPhaseOne();\r\n            this.renderProperties.x = 4;\r\n            this.renderProperties.y = 2;\r\n            this.renderProperties.width = CardView.CARD_WIDTH;\r\n            this.renderProperties.height = CardView.CARD_HEIGHT;\r\n\r\n            break;\r\n        }\r\n        \r\n        this.renderProperties.renderData = DeckAnimationHelper.getInstance().getRenderableContent();\r\n    }\r\n    \r\n    @Override public Dimension getPreferredSize() {\r\n        return new Dimension(CardView.CARD_WIDTH + 4, CardView.CARD_HEIGHT + 2);\r\n    }\r\n\r\n    @Override public void render() { \t\r\n        super.render();\r\n        \r\n        DeckAnimationHelper.getInstance().setScene(_stockCardEntities);\r\n        update(new ViewEventArgs(StockView.this, \"\"));\r\n    }\r\n\r\n    @Override public void update(EventArgs event) {\r\n        super.update(event);\r\n        addRenderableContent(DeckAnimationHelper.getInstance());\r\n        repaint();\r\n    }\r\n\r\n    @Override public void undoLastAction() {\r\n        _talonView.revertLastHand();\r\n\r\n        if(_talonView.isDeckPlayed()) {\r\n            _stockCardEntities.get(0).enableTalonRecycled();\r\n        }\r\n        else {\r\n            _stockCardEntities.remove(0);\r\n            _stockCardEntities.add(0, new StockCardEntity());\r\n        }\r\n        \r\n        render();\r\n    }\r\n\r\n    @Override public void performBackup() {\r\n        // Not needed\r\n    }\r\n\r\n    @Override public void clearBackup() {\r\n        // Not needed\r\n    }\r\n}"
  },
  {
    "path": "src/game/views/TableauPileView.java",
    "content": "package game.views;\n\nimport java.awt.Color;\nimport java.awt.Component;\nimport java.awt.Dimension;\nimport java.awt.Graphics;\nimport java.awt.Point;\nimport java.awt.Rectangle;\nimport java.util.Arrays;\nimport java.util.Collections;\nimport java.util.List;\nimport java.util.logging.Level;\n\nimport framework.api.IView;\nimport framework.core.factories.AbstractFactory;\nimport framework.core.factories.ViewFactory;\nimport framework.core.graphics.IRenderable;\nimport framework.core.mvc.view.PanelView;\nimport framework.core.physics.ICollidable;\nimport framework.utils.logging.Tracelog;\n\nimport game.config.OptionsPreferences;\nimport game.controllers.CardController;\nimport game.models.CardModel;\n\n/**\n * This view represents a single Tableau pile \n * \n * @author Daniel Ricci {@literal <thedanny09@icloud.com>}\n */\npublic class TableauPileView extends AbstractPileView implements ICollidable {\n    \n    /**\n     * The backside offset that the card should assume\n     */\n    private final int CARD_OFFSET_BACKSIDE = 3;\n    \n    /**\n     * The offset for each card when in this view\n     */\n    private final int CARD_OFFSET = 15;\n    \n    /**\n     * This panel is used as a placeholder within this view when there are no cards to be shown\n     */\n    private final PanelView _noCardPanelView = new PanelView();\n\n    /**\n     * A reference to the options preferences resource\n     */\n    private final OptionsPreferences _preferences = new OptionsPreferences();\n    \n    /**\n     * Constructs a new instance of this class type\n     */\n    private TableauPileView() {\n        \n        // Force the rendering engine to attempt to render this view so that it can\n        // render the panel view when no cards are available and the player is in outline mode\n        setIsForceRendering(true);\n        setOpaque(true);\n        setBackground(new Color(0, 128, 0));\n        \n        // Set the background of the panel and render it\n        _noCardPanelView.setBackground(Color.BLACK);\n        _noCardPanelView.render();\n    }\n    \n    /**\n     * Constructs a new instance of this class type\n     * \n     * @param cards A list of card models to associate to this pile view\n     */\n    public TableauPileView(List<CardModel> cards) {\n        this();\n        for(int i = 0; i < cards.size(); ++i) {\n            //Create the card view\n            cards.get(i).setBackside(i + 1 < cards.size());\n            CardView view = AbstractFactory.getFactory(ViewFactory.class).add(new CardView(cards.get(i)));\n            \n            // Add the view to the layered pane\n            layeredPane.add(view);\n            layeredPane.setLayer(view, i);\n            \n            // Set the bounds of the view within the layered pane\n            Point offset = getCardOffset(view);\n            view.setBounds(new Rectangle(offset.x, offset.y, view.getPreferredSize().width, view.getPreferredSize().height));\n        }\n    }\n    \n    @Override public void preprocessGraphics(IRenderable renderableData, Graphics context) {\n        super.preprocessGraphics(renderableData, context);\n        if(getIsHighlighted() && layeredPane.getComponentCount() == 0) {\n            _preferences.load();\n            if(_preferences.outlineDragging) {\n                _noCardPanelView.setSize(new Dimension(CardView.CARD_WIDTH, CardView.CARD_HEIGHT));\n                _noCardPanelView.setPreferredSize(_noCardPanelView.getSize());\n                add(_noCardPanelView);\n                context.setXORMode(Color.WHITE);\n            }\n        }\n        else {\n            remove(_noCardPanelView);\n        }\n    }\n\n    @Override public void render() {\n        super.render();\n        for(Component component : layeredPane.getComponents()) {\n            if(component instanceof CardView) {\n                CardView view = (CardView) component;\n                view.render();\n            }\n        }\n        repaint();\n    }\n    \n    @Override protected Point getCardOffset(CardView cardView) {\n        \n        List<Component> cardComponents = Arrays.asList(layeredPane.getComponents());\n        Collections.reverse(cardComponents);\n        int index = cardComponents.indexOf(cardView);\n        if(index == -1) {\n            Tracelog.log(Level.SEVERE, true, \"Cannot find the offset for the card \" + cardView);\n            return new Point();\n        }\n        \n        // If there is only one card then it will have an offset of 0\n        if(index == 0) {\n            return new Point();\n        }\n       \n        // Get a reference to the previous card and it's bounds\n        CardView previousCard = (CardView)cardComponents.get(index - 1);\n        Rectangle previousCardBounds = previousCard.getBounds();\n        \n        // If the card before this one has it's backside showing, then it should be\n        // positioned 3 pixels lower than that card\n        if(previousCard.isBacksideShowing()) {\n            return new Point(0, previousCardBounds.y + CARD_OFFSET_BACKSIDE);\n        }\n        // Subsequent cards should be 12 pixels down from the previous card\n        else {\n            return new Point(0, previousCardBounds.y + CARD_OFFSET);\n        }\n    }\n\n    @Override public boolean isValidCollision(Component source) {\n\n        // If there are no components then only allow a king to be placed\n        if(layeredPane.getComponentCount() == 0) {\n            IView cardView = (IView)source;\n            boolean isValidCollision = cardView.getViewProperties().getEntity(CardController.class).getCard().getCardEntity().isCardKing(); \n            return isValidCollision;\n        }\n        \n        if(!(layeredPane.getComponent(0) instanceof CardView) ){\n            return false;\n        }\n        \n        // Get the bottom most card within the pile view.\n        CardView cardView = (CardView) layeredPane.getComponent(0);\n\n        // Get the bounds associated to this pile view\n        Rectangle thisBounds = this.getBounds();\n        \n        Rectangle thatBounds = cardView.getBounds();\n        Rectangle rect = new Rectangle(\n            thisBounds.x + thatBounds.x, \n            thisBounds.y + thatBounds.y, \n            source.getWidth(),\n            source.getHeight()\n        );\n        \n        // If the intersection is valid then verify if the card allows\n        // for the collision\n        if(source.getBounds().intersects(rect)) {\n            return cardView.isValidCollision(source); \n        }\n        \n        return false;\n    }\n\n    @Override public void onCollisionStart(Component source) {\n        CardView cardView = this.getLastCard();\n        if(cardView != null) {\n            cardView.onCollisionStart(source);\n        }\n    }\n\n    @Override public void onCollisionStop(Component source) {\n        CardView cardView = this.getLastCard();\n        if(cardView != null) {\n            cardView.onCollisionStop(source);\n        }\n    }   \n}"
  },
  {
    "path": "src/game/views/TalonPileView.java",
    "content": "package game.views;\r\n\r\nimport java.awt.Color;\r\nimport java.awt.Component;\r\nimport java.awt.Dimension;\r\nimport java.awt.Point;\r\nimport java.awt.Rectangle;\r\nimport java.awt.event.MouseAdapter;\r\nimport java.awt.event.MouseEvent;\r\nimport java.util.ArrayList;\r\nimport java.util.Arrays;\r\nimport java.util.Collections;\r\nimport java.util.List;\r\nimport java.util.SortedSet;\r\nimport java.util.TreeSet;\r\nimport java.util.logging.Level;\r\nimport java.util.stream.Collectors;\r\n\r\nimport javax.swing.JLayeredPane;\r\nimport javax.swing.SwingUtilities;\r\n\r\nimport framework.core.factories.AbstractFactory;\r\nimport framework.core.factories.ControllerFactory;\r\nimport framework.core.factories.ViewFactory;\r\nimport framework.core.mvc.view.PanelView;\r\nimport framework.core.physics.ICollidable;\r\nimport framework.utils.MouseListenerEvent;\r\nimport framework.utils.MouseListenerEvent.SupportedActions;\r\nimport framework.utils.logging.Tracelog;\r\n\r\nimport game.config.OptionsPreferences;\r\nimport game.config.OptionsPreferences.DrawOption;\r\nimport game.config.OptionsPreferences.ScoringOption;\r\nimport game.controllers.MovementRecorderController;\r\nimport game.models.CardModel;\r\nimport game.views.helpers.ViewHelper;\r\n\r\n/**\r\n * This views represents the talon pile view. This view will display cards whenever the user clicks on\r\n * the Stock view. This view will adapt itself based on the options set (draw three vs. draw one)\r\n * \r\n * @author Daniel Ricci {@literal <thedanny09@icloud.com>}\r\n */\r\npublic final class TalonPileView extends AbstractPileView implements ICollidable {\r\n\r\n    /**\r\n     * Specifies the offset of each card within this view\r\n     */\r\n    private int CARD_OFFSET_X = 12;\r\n    \r\n    /**\r\n     * The available states of the talon\r\n     * \r\n     * @author Daniel Ricci {@literal <thedanny09@icloud.com>}\r\n     */\r\n    public enum TalonCardState {\r\n        // An Empty Deck\r\n        EMPTY,\r\n        // The Deck has been played through\r\n        DECK_PLAYED,\r\n        // Normal card played\r\n        NORMAL\r\n    }\r\n\r\n    /**\r\n     * A helper class for holding onto a layer and it's associated card state\r\n     * \r\n     * @author Daniel Ricci {@literal <thedanny09@icloud.com>}\r\n     */\r\n    private class TalonCardReference {\r\n        \r\n        /**\r\n         * The layer of the last card that was clicked\r\n         */\r\n        public final int layer;\r\n        \r\n        /**\r\n         * The last card that was clicked w.r.t this view\r\n         */\r\n        public final CardView card;\r\n        \r\n        /**\r\n         * Constructs a new instance of this class type\r\n         *\r\n         * @param card A card view\r\n         * @param layer A specified layer\r\n         */\r\n        public TalonCardReference(CardView card, int layer) {\r\n            this.card = card;\r\n            this.layer = layer;\r\n        }\r\n        \r\n        /**\r\n         * Constructs a new instance of this class type\r\n         *\r\n         * @param card A card view\r\n         */\r\n        public TalonCardReference(CardView card) {\r\n            this.card = card;\r\n            this.layer = JLayeredPane.getLayer(card);\r\n        }\r\n        \r\n        @Override public String toString() {\r\n            return String.format(\"Layer: %s | Card: %s\", this.layer, this.card);\r\n        }\r\n    }\r\n    \r\n    /**\r\n     * The total number of cards that this view contains by default\r\n     */\r\n    public static final int TOTAL_CARD_SIZE = 24;\r\n    \r\n    /**\r\n     * The last card hand state of this talon\r\n     */\r\n    private TalonCardState _lastCardHandState = null;\r\n    \r\n    /**\r\n     * The number of times that the deck was played\r\n     */\r\n    private int _deckPlays;\r\n    \r\n    /**\r\n     * This flag indicates if the deck is in a recycled state\r\n     */\r\n    private boolean _isDeckInRecycledState;\r\n    \r\n    /**\r\n     * The blank card associated to the talon view\r\n     */\r\n    private final PanelView _blankCard = new PanelView();\r\n\r\n    /**\r\n     * The last card that was interacted with\r\n     */\r\n    private TalonCardReference _lastCardInteracted = null;\r\n    \r\n    /**\r\n     * The card that can be undone\r\n     */\r\n    private TalonCardReference _undoableCard = null;\r\n    \r\n    /**\r\n     * Constructs a new instance of this class type\r\n     */\r\n    private TalonPileView() {\r\n        _blankCard.setBackground(new Color(0, 128, 0));\r\n        // Arbitrary number, big enough to do some damage\r\n        _blankCard.setPreferredSize(new Dimension(1000, 1000));\r\n        _blankCard.setBounds(new Rectangle(0, 0, _blankCard.getPreferredSize().width, _blankCard.getPreferredSize().height));\r\n        _blankCard.setVisible(true);\r\n        \r\n        OptionsPreferences preferences = new OptionsPreferences();\r\n        preferences.load();\r\n        if(preferences.drawOption == DrawOption.THREE) {\r\n            CARD_OFFSET_X = 12;\r\n        }\r\n        else {\r\n            CARD_OFFSET_X = 0;    \r\n        }\r\n        \r\n        // The blank card will always be in this view, so right clicking on it should autocomplete\r\n        // whatever is on the board\r\n        ViewHelper.registerForCardsAutocomplete(_blankCard);\r\n        \r\n        // Add a listener to the blank card since it is sitting above the board. If someone tries to click in this area\r\n        // the timer will start, unknowing to the player that they really clicked on a special area of the board\r\n        _blankCard.addMouseListener(new MouseAdapter() {\r\n            @Override public void mousePressed(MouseEvent event) {\r\n                if(!SwingUtilities.isRightMouseButton(event)) {\r\n                    AbstractFactory.getFactory(ViewFactory.class).get(TimerView.class).startGameTimer();\r\n                    _blankCard.removeMouseListener(this);\r\n                }\r\n            }\r\n        });\r\n    }\r\n    \r\n    /**\r\n     * Constructs a new instance of this class type\r\n     * \r\n     * @param cards The card models to load within this view\r\n     */\r\n    public TalonPileView(List<CardModel> cards) {\r\n        this();\r\n        \r\n        if(cards.size() > TOTAL_CARD_SIZE) {\r\n            Tracelog.log(Level.SEVERE, true, \"Talon has been allocated more than the currently set max card size that can be allocated!\");\r\n        }\r\n        \r\n        OptionsPreferences preferences = new OptionsPreferences();\r\n        preferences.load();\r\n        \r\n        for(int i = 0, layer = 0; i < cards.size(); ++i) {\r\n            CardView cardView = AbstractFactory.getFactory(ViewFactory.class).add(new CardView(cards.get(i)));\r\n            MouseListenerEvent adapter = new MouseListenerEvent(SupportedActions.LEFT) {\r\n                @Override public void mousePressed(MouseEvent event) {\r\n                    \r\n                    super.mousePressed(event);\r\n                    if(event.isConsumed() && getIsConsumed()) {\r\n                        return;\r\n                    }\r\n                    \r\n                    // Do not allow non-enabled cards to run\r\n                    if(!cardView.isEnabled()) {\r\n                        return;\r\n                    }\r\n                    \r\n                    // Take the card that was pressed on and record it's layer location \r\n                    _lastCardInteracted = new TalonCardReference(cardView);\r\n                }\r\n                @Override public void mouseReleased(MouseEvent event) {\r\n            \r\n                    super.mouseReleased(event);\r\n                    if(event.isConsumed() && getIsConsumed()) {\r\n                        return;\r\n                    }\r\n                    \r\n                    // Prevent other released events from being called by other cards that are not yet enabled\r\n                    if(!cardView.isEnabled()) {\r\n                        return;\r\n                    }\r\n                   \r\n                    // If the card is no longer associated to the talon then attempt to get the next one\r\n                    if(!(cardView.getParentIView() instanceof TalonPileView)) {\r\n                        \r\n                        // The top-most card cannot be the layered pane\r\n                        boolean cond1 = layeredPane.highestLayer() != JLayeredPane.getLayer(_blankCard);\r\n                        \r\n                        // There must not be any more visible cards (excluding the blank card)\r\n                        boolean cond2 = Arrays.asList(layeredPane.getComponents()).stream().anyMatch(z -> !z.equals(_blankCard) && z.isVisible());\r\n                        \r\n                        if(cond1 && !cond2) {\r\n                            for(int iterations = 0, layerId = JLayeredPane.getLayer(_blankCard) + 1; layerId <= layeredPane.highestLayer() || iterations < 3; ++layerId, ++iterations) {\r\n                                Component component = layeredPane.getComponentsInLayer(layerId)[0];\r\n                                component.setVisible(true);\r\n                            }\r\n                        }\r\n                    }\r\n                    // The card was put back, so position it accordingly so that it can be shown again\r\n                    // Make sure that the card is enabled. Since when a card is not enabled, the event\r\n                    // handlers are not applied to the card\r\n                    else if(cardView.isEnabled()){\r\n                        // If the blank card is on the same layer as this card, put this card to the next layer above. \r\n                        // This could only occur if this was already top-most\r\n                        if(JLayeredPane.getLayer(_blankCard) == JLayeredPane.getLayer(cardView)) {\r\n                            layeredPane.setLayer(cardView, JLayeredPane.getLayer(cardView) + 1);\r\n                        }\r\n                        setBounds(cardView);\r\n                    }\r\n                    \r\n                    // When the mouse is released, ensure that the component located at the highest layer is enabled\r\n                    layeredPane.getComponentsInLayer(layeredPane.highestLayer())[0].setEnabled(true);\r\n                }\r\n            };\r\n            cardView.addMouseListener(adapter);\r\n            cardView.getOutlineView().addMouseListener(adapter);\r\n            \r\n            // Set the default bounds of the card\r\n            cardView.setBounds(new Rectangle(0, 0, cardView.getPreferredSize().width, cardView.getPreferredSize().height));\r\n            \r\n            // All cards are disabled by default, and should be disabled by default after a subsequent deck has been played through\r\n            cardView.setEnabled(false);\r\n            \r\n            // Add the card to the layered pane and set it's layer accordingly\r\n            layeredPane.add(cardView);\r\n            \r\n            if(preferences.drawOption == DrawOption.THREE) {\r\n                layeredPane.setLayer(cardView, layer / 3);\r\n                ++layer;\r\n            }\r\n            else {\r\n                layeredPane.setLayer(cardView, i);\r\n            }\r\n        }\r\n        \r\n        // Add the blank card last, and make sure that it has the topmost layer\r\n        layeredPane.add(_blankCard);\r\n        layeredPane.setLayer(_blankCard, layeredPane.highestLayer() + 1);\r\n    }\r\n    \r\n    /**\r\n     * @return TRUE if the pile style has not yet gone through 4 cards, FALSE otherwise\r\n     */\r\n    public boolean isPhaseOne() {\r\n        return getBlankCardPosition() < 4 - getCardsRemainingCount();\r\n    }\r\n    \r\n    /**\r\n     * @return TRUE if the pile style has not yet gone through 14 cards, FALSE otherwise\r\n     */\r\n    public boolean isPhaseTwo() {\r\n        return getBlankCardPosition() < 14 - getCardsRemainingCount();\r\n    }\r\n    \r\n    /**\r\n     * @return TRUE if the Talon has been played through fully, FALSE otherwise\r\n     */\r\n    public boolean isDeckPlayed() {\r\n        return layeredPane.lowestLayer() == JLayeredPane.getLayer(_blankCard);\r\n    }\r\n    \r\n    /**\r\n     * @return TRUE if the Talon has gone through the specified number \r\n     *         of deck shuffles (based on the options preferences currently set), FALSE otherwise\r\n     */\r\n    public boolean isTalonEnded() {\r\n        OptionsPreferences preferences = new OptionsPreferences();\r\n        preferences.load();\r\n        \r\n        if(preferences.drawOption == DrawOption.ONE && preferences.scoringOption == ScoringOption.VEGAS && _deckPlays == 1) {\r\n            return true;\r\n        }\r\n        \r\n        if(preferences.drawOption == DrawOption.THREE && preferences.scoringOption == ScoringOption.VEGAS && _deckPlays == 3) {\r\n            return true;\r\n        }\r\n        \r\n        return false;\r\n    }\r\n    \r\n    /**\r\n     * @return The current state of the Talon based on the last operation played\r\n     */\r\n    public TalonCardState getState() {\r\n        return _lastCardHandState;\r\n    }\r\n    \r\n    /**\r\n     * Reverts the last hand played\r\n     */\r\n    public void revertLastHand() {\r\n    \t\r\n    \tif(JLayeredPane.getLayer(_blankCard) == layeredPane.highestLayer()) {\r\n            _isDeckInRecycledState = false;\r\n            layeredPane.setLayer(_blankCard, layeredPane.lowestLayer() - 1);\r\n        }\r\n        else {\r\n        \t\r\n        \tif(JLayeredPane.getLayer(_blankCard) == layeredPane.lowestLayer()) {\r\n        \t\t_deckPlays = Math.max(0, --_deckPlays);\r\n        \t}\r\n        \t\r\n            // Disable all the cards\r\n\t        Arrays.asList(layeredPane.getComponents()).forEach(z -> z.setEnabled(false));\r\n\r\n\t        OptionsPreferences preferences = new OptionsPreferences();\r\n\t        preferences.load();\r\n\t        \r\n\t        if(preferences.drawOption == DrawOption.ONE) {\r\n\t            // Get the top-most component and set it underneath the blank card.\r\n\t            Component comp = layeredPane.getComponentsInLayer(layeredPane.highestLayer())[0];\r\n\t            comp.setVisible(false);\r\n\t\r\n\t            layeredPane.setLayer(comp, JLayeredPane.getLayer(_blankCard));\r\n\t            layeredPane.getComponentsInLayer(layeredPane.highestLayer())[0].setEnabled(true);\r\n\t            this.setBounds(comp);\r\n\t\r\n\t            // From the bottom upwards, re-order the layer of each card\r\n\t            Component[] components = layeredPane.getComponents();\r\n\t            for(int layer = 0, i = components.length - 1; i >= 0; --i, ++layer) {\r\n\t                layeredPane.setLayer(components[i], layer);\r\n\t            }\r\n\t        }\r\n\t        else {\r\n\t            // From the blank card upwards, up each components layer by 1\r\n\t            int blankCardLayer = JLayeredPane.getLayer(_blankCard);\r\n\t            Component[] components = layeredPane.getComponents();\r\n\t            for(Component comp : components) {\r\n\t                if(layeredPane.getLayer(comp) >= blankCardLayer) {\r\n\t                    layeredPane.setLayer(comp, layeredPane.getLayer(comp) + 1);\r\n\t                }\r\n\t            }\r\n\t            \r\n\t            // Take the top three cards and move them to the original blank card index\r\n\t            //\r\n\t            //  Note: Because of how draw three works, we need to do this after all the cards of the layer have had\r\n\t            // their visibility properly set to false\r\n\t            Component[] cardsBeingReverted = layeredPane.getComponentsInLayer(layeredPane.highestLayer());\r\n\t            for(Component comp : cardsBeingReverted) {\r\n\t                layeredPane.setLayer(comp, blankCardLayer);\r\n\t                comp.setVisible(false);\r\n\t            }\r\n\t            Arrays.asList(cardsBeingReverted).stream().filter(z -> z instanceof CardView).forEach(z -> this.setBounds(z));\r\n\t            \r\n\t            // Take the highest layered cards at this point, set their screen position accordingly, and enable\r\n\t            // the first card to be moved\r\n\t            Component[] highestCards = layeredPane.getComponentsInLayer(layeredPane.highestLayer());\r\n\t            \r\n\t            // If the card is not the blank card, then remove the cards and re-add them, they will\r\n\t            // go through the process of being properly re-positioned\r\n\t            if(!(highestCards.length == 1 && highestCards[0] == _blankCard)) {\r\n\t               for(Component comp : highestCards) {\r\n\t                   setBounds(comp);\r\n\t               }\r\n\t               \r\n\t               highestCards[0].setEnabled(true);\r\n\t            }\r\n\t        }\r\n        }\r\n    }\r\n    \r\n    /**\r\n     * Displays the next card hand on this view\r\n     */\r\n    public void cycleNextHand() {\r\n        \r\n        // If the talon can no longer be played with, then go no futher\r\n        if(isTalonEnded()) {\r\n            _lastCardHandState = TalonCardState.DECK_PLAYED;\r\n            return;\r\n        }\r\n        \r\n        // If there is only one component then dont go further. The idea is that the \"blank\" placeholder view that\r\n        // mimics that switching of cards should never be removed from this view, thus if that is the only view that\r\n        // exists then it should mean that all the playing cards having been removed from this view\r\n        if(layeredPane.getComponentCount() == 1) {\r\n            Tracelog.log(Level.INFO, true, \"There are no more cards left in the Talon to play.\");\r\n            _lastCardHandState = TalonCardState.EMPTY;\r\n            return;\r\n        }\r\n        \r\n        // Notify the movement controller that there was a movement that occured of the talon, from the stock view\r\n        AbstractFactory.getFactory(ControllerFactory.class).get(MovementRecorderController.class).recordMovement(AbstractFactory.getFactory(ViewFactory.class).get(StockView.class), this);\r\n        \r\n        // If we are in a recycle deck state then recycle the deck\r\n        if(_isDeckInRecycledState) {\r\n        \tlayeredPane.setLayer(_blankCard, layeredPane.lowestLayer() - 1);\r\n            recycleDeck();\r\n        }\r\n        \r\n        // If we are at the end then restart the deck\r\n        if(JLayeredPane.getLayer(_blankCard) == layeredPane.lowestLayer()) {\r\n            // New deck has the score updated\r\n            AbstractFactory.getFactory(ViewFactory.class).get(ScoreView.class).updateScoreDeckFinished(_deckPlays);\r\n            \r\n            // The next pass will recycle the deck\r\n            _isDeckInRecycledState = true;\r\n            \r\n            // Mask the top layer of the deck to make it appear that the deck has reshuffled, this is to make undoing at this\r\n            // stage a million times easier, just flip the card back to the bottom\r\n            layeredPane.setLayer(_blankCard, layeredPane.highestLayer() + 1);\r\n        }\r\n        else {\r\n            \r\n            OptionsPreferences preferences = new OptionsPreferences();\r\n            preferences.load();\r\n\r\n            // Disable all the cards\r\n            Arrays.asList(layeredPane.getComponents()).forEach(z -> z.setEnabled(false));\r\n            \r\n            if(preferences.drawOption == DrawOption.ONE) {\r\n                // Get the card that is directly below the blank card\r\n                Component cardDirectlyBelowBlankCard = layeredPane.getComponent(layeredPane.getIndexOf(_blankCard) + 1);\r\n                cardDirectlyBelowBlankCard.setVisible(true);\r\n                \r\n                // Set the layer of the card that is directly below the blank card, to the highest layer\r\n                layeredPane.setLayer(cardDirectlyBelowBlankCard, layeredPane.highestLayer() + 1);\r\n                cardDirectlyBelowBlankCard.setEnabled(true);\r\n                \r\n                this.setBounds(cardDirectlyBelowBlankCard);\r\n                resyncDeckLayers();\r\n            }\r\n            else {\r\n                // Reposition all the cards to the origin\r\n                repositionCardsAboveBlankCardToOrigin();\r\n                \r\n                // Take the blank card and position to the layer one below. Take that layer where the blank card is at\r\n                // and make the other cards top most. Also make sure to position them correctly and set their bounds\r\n                int blankCardLayerIndex = JLayeredPane.getLayer(_blankCard);\r\n                int cardsUnderBlankCard = blankCardLayerIndex - 1;\r\n                int highestLayer = layeredPane.highestLayer();\r\n                Component[] components = layeredPane.getComponentsInLayer(cardsUnderBlankCard);\r\n                for(Component component : components) {\r\n                    component.setVisible(true);\r\n                    component.setEnabled(components[0].equals(component));\r\n                    layeredPane.setLayer(component, highestLayer + 1);\r\n                    this.setBounds(component);\r\n                }\r\n                // Note: Set the layer of the blank card after the positioning of the other cards occur, or the blank card\r\n                // will also be moved back to top, not something we want to do.\r\n                layeredPane.setLayer(_blankCard, cardsUnderBlankCard);\r\n                resyncDeckLayers();\r\n            }\r\n\r\n            if(layeredPane.lowestLayer() == JLayeredPane.getLayer(_blankCard)) {\r\n                ++_deckPlays;\r\n                _lastCardHandState = TalonCardState.DECK_PLAYED;\r\n                return;\r\n            }\r\n        }\r\n                \r\n        _lastCardHandState = TalonCardState.NORMAL;\r\n    }\r\n    \r\n    /**\r\n     * @return The position of where the deck of this talon is CURRENTLY is at, which is\r\n     *         based on the blank card location within all the components in the layered pane\r\n     */\r\n    private int getBlankCardPosition() {\r\n        return layeredPane.getIndexOf(_blankCard);\r\n    }\r\n    \r\n    /**\r\n     * Gets the deck position of the specified component, w.r.t the business logic ordering of the deck\r\n     *\r\n     * @param component The component\r\n     * \r\n     * @return The deck position within the deck\r\n     */\r\n    private int getPosition(Component component) {\r\n        \r\n        int position = 0;\r\n        \r\n        List<Component> components = Arrays.asList(layeredPane.getComponents());\r\n        Collections.reverse(components);\r\n\r\n        if(!component.isVisible()) {\r\n            // Take the total number of cards in the layered pane, subtract 1 to remove the special hidden\r\n            // card, and subtract the index of the component.\r\n            position = layeredPane.getComponentCount() - components.indexOf(component) - 1;\r\n        }\r\n        else {\r\n            OptionsPreferences preferences = new OptionsPreferences();\r\n            preferences.load();\r\n            if(preferences.drawOption == DrawOption.ONE) {\r\n                position = components.stream().filter(z -> z.isVisible() && z instanceof CardView).collect(Collectors.toList()).indexOf(component) + 1;\r\n            }\r\n            else {\r\n                \r\n                // Get the list of layers, and make sure they are totally ordered\r\n                SortedSet<Integer> uniqueLayers = new TreeSet<Integer>();\r\n                components.stream().filter(z -> z.isVisible() && z instanceof CardView).forEach(z -> uniqueLayers.add(layeredPane.getLayer(z)));\r\n\r\n                List<Component> componentsOrdered = new ArrayList<Component>();\r\n                for(int uniqueLayer : uniqueLayers) {\r\n                    componentsOrdered.addAll(Arrays.asList(layeredPane.getComponentsInLayer(uniqueLayer)));\r\n                }\r\n\r\n                position = componentsOrdered.indexOf(component) + 1;\r\n            }\r\n        }\r\n        \r\n        return position;\r\n    }\r\n    \r\n    /**\r\n     * @return The number of cards remaining based on the original count of this view\r\n     */\r\n    private int getCardsRemainingCount() {\r\n        return TOTAL_CARD_SIZE - (layeredPane.getComponentCount() - 1);\r\n    }\r\n     \r\n    /**\r\n     * Recycles the deck\r\n     */\r\n    private void recycleDeck() {\r\n        OptionsPreferences preferences = new OptionsPreferences();\r\n        preferences.load();\r\n\r\n        // Remove the blank card from the layered pane, put it back at the end, much easier\r\n        layeredPane.remove(_blankCard);\r\n    \t\r\n        // The list of components\r\n        Component[] components = layeredPane.getComponents();\r\n        \r\n        if(preferences.drawOption == DrawOption.ONE) {\r\n            for(int i = components.length - 1; i >= 0; --i) {\r\n                Component component = components[i];\r\n                layeredPane.setLayer(component, i);\r\n                component.setEnabled(false);\r\n                component.setVisible(false);\r\n            }\r\n        }\r\n        else {\r\n            for(int i = 0; i < components.length; ++i) {\r\n            \tComponent component = components[i];\r\n            \tlayeredPane.setLayer(component, i / 3);\r\n            \tcomponent.setEnabled(false);\r\n                component.setVisible(false);\r\n            }        \t\r\n        }\r\n        \r\n        // Add back the blank card as the top-most card\r\n        layeredPane.add(_blankCard);\r\n        layeredPane.setLayer(_blankCard, layeredPane.highestLayer() + 1);\r\n\r\n    \t// Update the flag indicating that the deck is recycled\r\n    \t_isDeckInRecycledState = false;\r\n    }\r\n     \r\n    /*\r\n     * Re-syncs the deck, ensuring that the layers are sequentially ordered\r\n     */\r\n    private void resyncDeckLayers() {\r\n        OptionsPreferences preferences = new OptionsPreferences();\r\n        preferences.load();\r\n        \r\n        if(preferences.drawOption == DrawOption.ONE) {\r\n            // Starting from the lowest layer upwards, re-synchronize all the layer positions of the cards.\r\n            for(int i = layeredPane.getComponentCount() - 1, layerId = 0;  i >= 0; --i, ++layerId) {\r\n                // Re-synchronize the layer position of the card\r\n                layeredPane.setLayer(layeredPane.getComponent(i), layerId);\r\n            }\r\n        }\r\n        else if(preferences.drawOption == DrawOption.THREE) {\r\n            \r\n            // Get the list of components grouped by their layer\r\n            List<Component[]> componentsGroupedByLayer = getComponentsGroupedByLayer();\r\n            \r\n            // Re-input components by their layer, ensuring that their layer is ordered\r\n            // sequentially WITHOUT any gaps between layer numbers\r\n            for(int i = 0; i < componentsGroupedByLayer.size(); ++i) {\r\n                Component[] components = componentsGroupedByLayer.get(i);\r\n                for(int j = 0; j < components.length; ++j) {\r\n                    layeredPane.setLayer(components[j], i);\r\n                }\r\n            }\r\n        }\r\n    }\r\n   \r\n    /**\r\n     * Repositions the list of cards within the layered pane so that the ordering is sequential\r\n     * \r\n     * (Draw Three Specific)\r\n     */\r\n    private void repositionCardsAboveBlankCardToOrigin() {\r\n        // Before proceeding, everything that has a higher layer than the blank card needs to be re-positioned to the origin\r\n        if(layeredPane.highestLayer() != JLayeredPane.getLayer(_blankCard)) {\r\n            int layer = layeredPane.highestLayer();\r\n            while(layer != JLayeredPane.getLayer(_blankCard)) {\r\n                List<Component> components = Arrays.asList(layeredPane.getComponentsInLayer(layer));\r\n                for(Component component : components) {\r\n                    // For the draw one implementation style\r\n                    this.setBoundsDrawOneImpl(component, getPosition(component));\r\n                }\r\n                \r\n                --layer;\r\n            }\r\n        }\r\n    }\r\n    \r\n    /**\r\n     * Sets the bounds of the specified component\r\n     *\r\n     * @param component The component to set bounds\r\n     */\r\n    private void setBounds(Component component) {\r\n\r\n        // Calculate the deck position of the specified component\r\n        int position = getPosition(component);\r\n        \r\n        // The position of the card when playing with `three` is all that concerns us since position matters, vs `single` card which are all stacked.\r\n        OptionsPreferences preferences = new OptionsPreferences();\r\n        preferences.load();\r\n        \r\n        if(preferences.drawOption == DrawOption.THREE) {\r\n            setBoundsDrawThreeImpl(component, position);\r\n        }\r\n        else {\r\n            setBoundsDrawOneImpl(component, position);\r\n        }\r\n    }\r\n\r\n    /**\r\n     * Implementation of setting the bounds of the specified component at the specified position\r\n     * when the game is in `Draw Three` mode\r\n     *\r\n     * @param component The component\r\n     * @param position The position\r\n     */\r\n    private void setBoundsDrawOneImpl(Component component, int position) {\r\n        int x = 0;\r\n        int y = 0;\r\n        \r\n        if(position < 12) {\r\n            x = 0;\r\n            y = 0;\r\n        }\r\n        else if (position < 22) {\r\n            x = 2;\r\n            y = 1;\r\n        }\r\n        else {\r\n            x = 4;\r\n            y = 2;\r\n        }\r\n        \r\n        // Set the default bounds of the card view\r\n        Rectangle bounds = new Rectangle(x, y, component.getPreferredSize().width, component.getPreferredSize().height);\r\n        component.setBounds(bounds);\r\n    }\r\n    \r\n    /**\r\n     * Implementation of setting the bounds of the specified component at the specified position\r\n     * when the game is in `Draw Three` mode\r\n     *\r\n     * @param component The component\r\n     * @param position The position\r\n     */\r\n    private void setBoundsDrawThreeImpl(Component component, int position) {\r\n        int xModifier = 0;\r\n        int yModifier = 0;\r\n\r\n        if(position < 13) {\r\n            xModifier = 0;\r\n            yModifier = 0;\r\n        }\r\n        else if(position < 22) {\r\n            xModifier = 2;\r\n            yModifier = 1;\r\n            \r\n        }\r\n        else {\r\n            xModifier = 4;\r\n            yModifier = 2;\r\n        }            \r\n        \r\n        // Re-order the cards that exist currently, before determining where this card should be placed.\r\n        Component[] components = layeredPane.getComponentsInLayer(layeredPane.getLayer(component));\r\n        for(int i = components.length - 1; i >= 0; --i) {\r\n            \r\n            Rectangle bounds = new Rectangle(0, 0, component.getPreferredSize().width, component.getPreferredSize().height);\r\n            \r\n            int positionIndex = layeredPane.getPosition(components[i]);\r\n            int offset = 3 - components.length;\r\n            switch(positionIndex + offset) {\r\n            case 0:\r\n                bounds.x = 2 * CARD_OFFSET_X;\r\n                bounds.y = 2;\r\n                break;\r\n            case 1:\r\n                bounds.x = CARD_OFFSET_X;\r\n                bounds.y = 1;\r\n                break;\r\n            case 2:\r\n                bounds.x = 0;\r\n                bounds.y = 0;\r\n                break;\r\n            }\r\n            \r\n            bounds.x += xModifier;\r\n            bounds.y += yModifier;\r\n            \r\n            // Set the new bounds of the specified component\r\n            components[i].setBounds(bounds);\r\n        }            \r\n    }\r\n    \r\n    @Override public void addCard(CardView cardView) {\r\n        OptionsPreferences preferences = new OptionsPreferences();\r\n        preferences.load();\r\n        if(preferences.drawOption == DrawOption.THREE) {\r\n            addCard(cardView, _lastCardInteracted.layer);\r\n            layeredPane.setPosition(cardView, 0);           \r\n        }\r\n        else {\r\n            super.addCard(cardView);\r\n        }\r\n    }\r\n    \r\n    @Override public String toString() {\r\n        StringBuilder builder = new StringBuilder();\r\n        String header = \"========\" + this.getClass().getSimpleName().toUpperCase() + \"========\";\r\n        builder.append(header + System.getProperty(\"line.separator\"));\r\n        \r\n        int blankLayer = JLayeredPane.getLayer(_blankCard);\r\n        JLayeredPane blankParentLayeredPane = (JLayeredPane) _blankCard.getParent();\r\n        List<Component> components = Arrays.asList(blankParentLayeredPane.getComponentsInLayer(blankLayer));\r\n        int blankPositionWithinlayer = components.indexOf(_blankCard);\r\n        \r\n        for(Component comp : layeredPane.getComponents()) {\r\n            if(comp instanceof CardView) {\r\n                builder.append(comp + System.getProperty(\"line.separator\"));\r\n            }\r\n            else if(comp.equals(_blankCard)) {\r\n                builder.append(\"===BLANK CARD===\\t[\" + blankLayer + \"][\" + blankPositionWithinlayer + \"]\" + System.getProperty(\"line.separator\"));\r\n            }\r\n        }\r\n        \r\n        builder.append(System.getProperty(\"line.separator\"));\r\n        builder.append(\"Decks Played: \" + _deckPlays + System.getProperty(\"line.separator\"));\r\n        builder.append(\"Last Card Hand State: \" + _lastCardHandState + System.getProperty(\"line.separator\"));\r\n        builder.append(\"Undoable Card: \" + String.valueOf(_undoableCard) + System.getProperty(\"line.separator\"));\r\n        builder.append(\"Last Card Interacted: \" + String.valueOf(_lastCardInteracted) + System.getProperty(\"line.separator\"));\r\n        builder.append(\"Is Deck In Recycle State: \" + String.valueOf(_isDeckInRecycledState) + System.getProperty(\"line.separator\"));\r\n        builder.append(System.getProperty(\"line.separator\"));\r\n        builder.append(new String(new char[header.length()]).replace(\"\\0\", \"=\"));\r\n        \r\n        return builder.toString();\r\n    }\r\n    \r\n    @Override public void render() {\r\n        super.render();\r\n        for(Component comp : layeredPane.getComponents()) {\r\n            if(!comp.equals(_blankCard)) {\r\n                comp.setVisible(false);\r\n            }\r\n        }\r\n    }\r\n\r\n    @Override public boolean isValidCollision(Component source) {\r\n        return false;\r\n    }\r\n\r\n    @Override public void undoLastAction() {\r\n        \r\n        // If there was a card recoreded\r\n        if(_undoableCard != null ) {\r\n            \r\n            // Get the highest component and set the enabled flag to so that it does not move anymore\r\n            Component highestComponent = layeredPane.getComponentsInLayer(layeredPane.highestLayer())[0];\r\n            highestComponent.setEnabled(false);\r\n            \r\n            // This is required to be done, because when we call `addCard` below, it uses the `_lastCardInteracted`, so we\r\n            // update this value accordingly\r\n            TalonCardReference temp = _lastCardInteracted;\r\n            _lastCardInteracted = _undoableCard;\r\n            addCard(_undoableCard.card);\r\n            _lastCardInteracted = temp;\r\n            \r\n            // Set the bounds of the card\r\n            setBounds(_undoableCard.card);\r\n            repaint();\r\n        }\r\n    }\r\n\r\n    @Override public void performBackup() {\r\n        \r\n        // Get the card that is owned by the game view. When a drag occurs, the card is owned by the game view so that\r\n        // it can be freely dragged around the entire game.\r\n        CardView cardView = AbstractFactory.getFactory(ViewFactory.class).get(GameView.class).getCardComponent();\r\n        \r\n        // If the card cannot be found and if the talon doesnt have the blank card as the top most card\r\n        if(cardView == null && layeredPane.highestLayer() != JLayeredPane.getLayer(_blankCard)) {\r\n            \r\n            // Take the card that is at the top-most of the talon. This is the case when we are\r\n            // playing in outline mode, and the card still exists on the talon, because the card outline\r\n            // is the thing that is actually movings\r\n            cardView = (CardView) layeredPane.getComponentsInLayer(layeredPane.highestLayer())[0];\r\n        }\r\n        \r\n        // If no card was specified and a backup is required, take the top most\r\n        // card. This can only happen if an automove occurs\r\n        if(_lastCardInteracted == null) {\r\n            _lastCardInteracted = new TalonCardReference(getLastCard());\r\n        }\r\n        \r\n        // Set the undoable card as the card that can be undone\r\n        _undoableCard = new TalonCardReference(cardView, _lastCardInteracted.layer);            \r\n    }\r\n\r\n    @Override public void clearBackup() {\r\n        _undoableCard = null;\r\n    }\r\n\r\n    @Override protected Point getCardOffset(CardView cardView) {\r\n        // Not needed\r\n        return new Point(0, 0);\r\n    }\r\n\r\n    @Override public void onCollisionStart(Component source) {\r\n        // Not needed\r\n    }\r\n\r\n    @Override public void onCollisionStop(Component source) {\r\n        // Not needed\r\n    }\r\n}"
  },
  {
    "path": "src/game/views/TimerView.java",
    "content": "package game.views;\n\nimport java.awt.Color;\nimport java.awt.FlowLayout;\nimport java.util.Timer;\nimport java.util.TimerTask;\n\nimport javax.swing.JLabel;\n\nimport framework.core.factories.AbstractFactory;\nimport framework.core.factories.ViewFactory;\nimport framework.core.mvc.view.PanelView;\n\npublic final class TimerView extends PanelView {\n\n    private Timer _timer = new Timer(true);\n\n    private JLabel _label = new JLabel();\n    \n    private long _time = 0;\n    \n    private boolean _running;\n    \n    private boolean _cancelled;\n    \n    /**\n     * Constructs a new instance of this class type\n     */\n    public TimerView() {\n        this.setBackground(Color.WHITE);\n        _label.setText(this.toString());\n        add(_label);\n\n        // Set the VGap so that the time renders appropriately\n        FlowLayout layout = (FlowLayout) this.getLayout();\n        layout.setVgap(0);\n    }\n    \n    public void startGameTimer() {\n        if(_cancelled || _running || !isVisible()) {\n            return;\n        }\n        \n        _running = true;\n        _time = 0;        \n        _timer.schedule(new TimerTask() {\n            @Override public void run() {\n                ++_time;\n                _label.setText(TimerView.this.toString());\n                if(_time % 10 == 0) {\n                    AbstractFactory.getFactory(ViewFactory.class).get(ScoreView.class).updateScoreTimerTick();\n                }\n            }\n        }, 1000, 1000);\n    }\n    \n    public long getTime() {\n        return _time;\n    }\n    \n    public void stop() {\n        _cancelled = true;\n        _timer.cancel();\n        _running = false;\n    }\n    \n    @Override public void destructor() {\n        _cancelled = true;\n        _timer.cancel();\n        super.destructor();\n    }\n    \n    @Override public String toString() {\n        return \"Time: \" + String.valueOf(_time);\n    }\n}\n"
  },
  {
    "path": "src/game/views/VegasScoreView.java",
    "content": "package game.views;\n\nimport java.awt.Color;\nimport java.util.logging.Level;\n\nimport framework.core.system.Application;\nimport framework.utils.logging.Tracelog;\n\nimport game.config.OptionsPreferences;\nimport game.models.MovementModel.MovementType;\n\n/**\n * This view shows the game score when playing in a vegas styled environment\n * \n * @author Daniel Ricci {@literal <thedanny09@icloud.com>}\n */\npublic class VegasScoreView extends ScoreView {\n\n    /**\n     * Constructs a new instance of this class type\n     */\n    public VegasScoreView() {\n        OptionsPreferences preferences = new OptionsPreferences();\n        preferences.load();\n        if(preferences.cumulativeScore) {\n            SCORE_CURRENT += -52;            \n        }\n        else {\n            SCORE_CURRENT = -52;\n        }\n    }\n    \n    @Override protected void addToScore(long score) {\n        SCORE_CURRENT += score;\n        scoreValue.setText(toString());\n    }\n    \n    @Override public long updateScoreBonus(long seconds) {\n        return 0;\n    }\n    \n    @Override public void updateScoreDeckFinished(int deckPlays) {\n    }\n    \n    @Override public void updateScoreTimerTick() {\n    }\n    \n    @Override public void updateScoreCardTurnOver() {\n    }\n    \n    @Override protected void updateScore(MovementType from, MovementType to, boolean isUndo) {\n        long scoreBefore = SCORE_CURRENT;\n        if(from == MovementType.TALON && to == MovementType.TABLEAU) {\n            addToScore(isUndo ? -5 : 5);\n        }\n        else if(from == MovementType.TALON && to == MovementType.FOUNDATION) {\n            addToScore(isUndo ? -5 : 5);\n        }\n        else if (from == MovementType.TABLEAU && to == MovementType.FOUNDATION) {\n            addToScore(isUndo ? -5 : 5);\n        }\n        else if(from == MovementType.FOUNDATION && to == MovementType.TABLEAU) {\n            addToScore(isUndo ? 5 : -5);\n        }\n        else {\n            return;\n        }\n                \n        Tracelog.log(Level.INFO, true, String.format(\"Score %s: Changed from %d to %d after performing move [%s] to [%s]\", isUndo ? \"Undo\" : \"Updated\",scoreBefore, SCORE_CURRENT, from, to));\n    }\n    \n\n    @Override public void destructor() {\n        OptionsPreferences preferences = new OptionsPreferences();\n        preferences.load();\n        if(!preferences.cumulativeScore || Application.instance.isRestarting) {\n            super.destructor();\n        }\n    }\n    \n    @Override public String toString() {\n        \n        if(SCORE_CURRENT < 0) {\n            scoreValue.setForeground(Color.RED);\n        }\n        else {\n            scoreValue.setForeground(Color.BLACK);\n        }\n        \n        String result = \"$\";\n        if(SCORE_CURRENT < 0) {\n            result = \"-\" + result;\n        }\n        \n        return result + String.valueOf(Math.abs(SCORE_CURRENT));\n    }\n}\n"
  },
  {
    "path": "src/game/views/components/ExclusiveLineBorder.java",
    "content": "package game.views.components;\r\n\r\nimport java.awt.Color;\r\nimport java.awt.Component;\r\nimport java.awt.Graphics;\r\n\r\nimport javax.swing.border.LineBorder;\r\n\r\n/**\r\n * Creates a line border that attempts to render it's edges by applying an XOR bitmask with \r\n * the underlying pixel color (per-pixel precision)\r\n *\r\n * @author Daniel Ricci {@literal <thedanny09@gmail.com> }\r\n *\r\n */\r\npublic class ExclusiveLineBorder extends LineBorder {\r\n\r\n    /**\r\n     * Constructs a new instance of this class type\r\n     *\r\n     * @param thickness The thickness of the borders\r\n     */\r\n    public ExclusiveLineBorder(int thickness) {\r\n        super(Color.BLACK, thickness, true);\r\n    }\r\n\r\n    @Override public void paintBorder(Component component, Graphics graphic, int x, int y, int width, int height) {\r\n        graphic.setXORMode(Color.WHITE);\r\n        super.paintBorder(component, graphic, x, y, width, height);\r\n    }\r\n}"
  },
  {
    "path": "src/game/views/helpers/DeckAnimationHelper.java",
    "content": "package game.views.helpers;\n\nimport java.awt.Image;\nimport java.util.ArrayList;\nimport java.util.List;\nimport java.util.Timer;\nimport java.util.TimerTask;\nimport java.util.logging.Level;\nimport java.util.stream.Collectors;\n\nimport framework.communication.internal.signal.arguments.EventArgs;\nimport framework.core.factories.AbstractFactory;\nimport framework.core.factories.DataFactory;\nimport framework.core.factories.ViewFactory;\nimport framework.core.graphics.IRenderable;\nimport framework.core.graphics.IRenderableContainer;\nimport framework.utils.logging.Tracelog;\n\nimport game.entities.StockCardEntity;\nimport game.views.StockView;\n\nimport generated.DataLookup;\n\npublic class DeckAnimationHelper implements IRenderableContainer {\n\tprivate List<StockCardEntity> stockCardEntities;\n\tprivate List<Image> deckImageAnimations;\n\t\n\tprivate Image deckImageOriginal;\n\tprivate Image currentDeckImageAnimation;\n\t\n\tprivate int delay = 0;\n\tprivate int period = 1000;\n\n\tprivate Timer timer;\n\n\tpublic static final String DECK_ANIMATION_UPDATED = \"DECK_ANIMATION_UPDATED\";\n\n\tprivate static volatile DeckAnimationHelper instance = null;\n\t\n\tprivate DeckAnimationHelper() {\n\t}\n\t\n\tpublic static DeckAnimationHelper getInstance() {\n\t\tsynchronized(DeckAnimationHelper.class) {\n\t\t\tif(instance == null) {\n\t\t\t\tinstance = new DeckAnimationHelper();\n\t\t\t}\n\t\t}\n\t\t\n\t\treturn instance;\n\t}\n\t\n\tpublic void clear() {\n\t\tif(timer != null) {\n\t\t\ttimer.cancel();\n\t\t\ttimer = null;\n        }\n\t\t\n\t\tthis.currentDeckImageAnimation = null;\n\t\tthis.deckImageOriginal = null;\n\t\tthis.stockCardEntities = null;\n\t}\n\t\n\tpublic void setScene(List<StockCardEntity> stockCardEntities) {\n\t\tthis.clear();\n\t\t\n\t\tthis.stockCardEntities = stockCardEntities;\n\t\t\n\t\tStockCardEntity stockCardEntity = stockCardEntities.get(0);\n\t\tif(stockCardEntity.getActiveDataIdentifier() == DataLookup.MISC.TALON_RESTART.identifier || stockCardEntity.getActiveDataIdentifier() == DataLookup.MISC.TALON_END.identifier) {\n\t\t\tthis.deckImageOriginal = stockCardEntity.getRenderableContent(); \n\t\t\treturn;\n\t\t}\n\t\t\n\t\tImage deckImageOriginal = stockCardEntities.get(0).backsideCardEntity.getRenderableContent();\n\t\tif(this.deckImageOriginal == deckImageOriginal) {\n\t\t\treturn;\n\t\t}\n\t\t\n\t\tthis.deckImageAnimations = new ArrayList<Image>();\n\t\tswitch(stockCardEntities.get(0).backsideCardEntity.getBacksideData()) {\n\t\t\tcase DECK_7: // ROBOT\n\t\t\t\tthis.deckImageAnimations.addAll(\n\t\t\t\t\tAbstractFactory.getFactory(DataFactory.class).getDataEntities(\n\t\t\t\t\t\t\tDataLookup.ANIMATIONS.DECK_7_2.identifier,\n\t\t\t\t\t\t\tDataLookup.ANIMATIONS.DECK_7_1.identifier,\n\t\t\t\t\t\t\tnull,\n\t\t\t\t\t\t\tDataLookup.ANIMATIONS.DECK_7_1.identifier\n\t\t\t\t));\n\t\t\t\t\n\t\t\t\tthis.period = 800;\n\t\t\t\tthis.delay = 0;\n\t\t\t\tbreak;\n\t\t\tcase DECK_10: // CASTLE\n\t\t\t\tthis.deckImageAnimations.addAll(AbstractFactory.getFactory(DataFactory.class).getDataEntities(\n\t\t\t\t\t\tnull,\n\t\t\t\t\t\tDataLookup.ANIMATIONS.DECK_10_1.identifier\n\t\t\t\t\t));\n\t\t\t\tthis.period = 1000;\n\t\t\t\tthis.delay = 0;\n\t\t\t\tbreak;\n\t\t\tcase DECK_11: // BEACH\n\t\t\t\tthis.deckImageAnimations.addAll(AbstractFactory.getFactory(DataFactory.class).getDataEntities(\n\t\t\t\t\t\tnull,\n\t\t\t\t\t\tDataLookup.ANIMATIONS.DECK_11_1.identifier,\n\t\t\t\t\t\tDataLookup.ANIMATIONS.DECK_11_2.identifier\n\t\t\t\t\t));\n\t\t\t\t\n\t\t\t\tthis.period = 1500;\n\t\t\t\tthis.delay = 8500;\n\t\t\t\tbreak;\n\t\t\tcase DECK_12: // POKER\n\t\t\t\tthis.deckImageAnimations.addAll(AbstractFactory.getFactory(DataFactory.class).getDataEntities(\n\t\t\t\t\t\tnull,\n\t\t\t\t\t\tDataLookup.ANIMATIONS.DECK_12_1.identifier,\n\t\t\t\t\t\tDataLookup.ANIMATIONS.DECK_12_2.identifier,\n\t\t\t\t\t\tDataLookup.ANIMATIONS.DECK_12_1.identifier\n\t\t\t\t\t));\n\t\t\t\t\n\t\t\t\tthis.period = 1000;\n\t\t\t\tthis.delay = 9000;\n\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tbreak;\n\t\t}\n\t\t\n\t\tthis.deckImageOriginal = deckImageOriginal;\n\t\tthis.currentDeckImageAnimation = null;\n\t\tthis.timer = new Timer(true);\n\t\tthis.timer.schedule(new TimerTask() {\n\t\t\tprivate int index = 0;\n\t\t\t@Override public void run() {\n\t\t\t\t//System.out.println(index + \" of \" + (deckImageAnimations.size() - 1));\n\t\t\t\tif(deckImageAnimations.isEmpty()) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tcurrentDeckImageAnimation = deckImageAnimations.get(index);\t\n\t\t\t\tAbstractFactory.getFactory(ViewFactory.class).multicastSignalListeners(StockView.class, new EventArgs(this, DECK_ANIMATION_UPDATED));\n\t\t\t\t\n\t\t\t\tif(index == 0) {\n\t\t\t\t\t//System.out.println(\"Sleeping for \" + delay + \" milliseconds\");\n\t\t\t\t\ttry {\n\t\t\t\t\t\tThread.sleep(delay);\n\t\t\t\t\t} catch (Exception exception){\n\t\t\t\t\t\tTracelog.log(Level.WARNING, true, exception);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tindex = (index + 1) % deckImageAnimations.size();\n\t\t\t}\n\t\t}, 0, period);\n\t}\n\t\n\t@Override public List<IRenderable> getRenderableContents() {\n\t\treturn this.stockCardEntities.stream().map(z -> z.toRenderable()).collect(Collectors.toList());\n\t}\n\n\t@Override public Image getRenderableContent() {\n\t\tif(this.currentDeckImageAnimation == null) {\n\t\t\treturn this.deckImageOriginal;\n\t\t}\n\t\t\n\t\treturn this.currentDeckImageAnimation;\t\t\n\t}\n}"
  },
  {
    "path": "src/game/views/helpers/ViewHelper.java",
    "content": "package game.views.helpers;\n\nimport java.awt.event.MouseEvent;\nimport java.util.ArrayList;\nimport java.util.Collections;\nimport java.util.List;\n\nimport javax.swing.SwingUtilities;\n\nimport framework.api.IView;\nimport framework.core.factories.AbstractFactory;\nimport framework.core.factories.ViewFactory;\nimport framework.utils.MouseListenerEvent;\nimport framework.utils.MouseListenerEvent.SupportedActions;\n\nimport game.views.CardView;\nimport game.views.TableauPileView;\nimport game.views.TalonPileView;\n\n/**\n * Helper class for common view related functionality\n * \n * @author Daniel Ricci {@literal <thedanny09@icloud.com>}\n */\npublic class ViewHelper {\n    \n    /**\n     * Registers the specified view so that it can initiate an Autocomplete opertation \n     *\n     * @param view The specified view to register this event onto\n     */\n    public static void registerForCardsAutocomplete(IView view) {\n        view.getContainerClass().addMouseListener(new MouseListenerEvent(SupportedActions.RIGHT) {\n            @Override public void mousePressed(MouseEvent event) {\n                super.mousePressed(event);\n                if(this.getIsConsumed()) {\n                    return;\n                }\n                if(SwingUtilities.isLeftMouseButton(event)) {\n                    return;\n                }\n                \n                performCardsAutocomplete();\n            }\n        });\n    }\n    \n    /**\n     * Performs an auto complete based on all available cards\n     */\n    private static void performCardsAutocomplete() {\n        ViewFactory viewFactory = AbstractFactory.getFactory(ViewFactory.class);\n        List<CardView> cards = new ArrayList<CardView>();\n        \n        // Get the top-most talon card\n        CardView talonCard = viewFactory.get(TalonPileView.class).getLastCard();\n        if(talonCard != null) {\n            cards.add(talonCard);    \n        }\n        \n        // Get all available top-most front-facing cards\n        List<TableauPileView> tableauPileViews = viewFactory.getAll(TableauPileView.class);\n        Collections.reverse(tableauPileViews);\n        for(TableauPileView view : tableauPileViews) {\n            CardView card = view.getLastCard();\n            if(card != null && !card.isBacksideShowing()) {\n                cards.add(card);\n            }\n        }\n        \n        // Go through the list and apply the automove on each card until there are no cards\n        // left or all cards have been iterated over\n        while(cards.size() > 0) {\n            boolean keepGoing = false;\n            for(int i = 0; i < cards.size(); ++i) {\n                if(cards.get(i).performCardAutoMovement()) {\n                    cards.remove(i);\n                    keepGoing = true;\n                    break;\n                }\n            }\n            \n            if(!keepGoing) {\n                break;\n            }\n        }\n        \n        // If the talon card was moved then enabled the top-most card so that the next card can be played\n        // TODO Can this be self-contained??\n        if(talonCard != null && !cards.contains(talonCard)) {\n            CardView lastTalonCard = viewFactory.get(TalonPileView.class).getLastCard();\n            if(lastTalonCard != null) {\n                lastTalonCard.setEnabled(true);\n            }\n        }\n    }\n}"
  },
  {
    "path": "src/game/views/helpers/WinAnimationHelper.java",
    "content": "package game.views.helpers;\n\nimport java.awt.Point;\nimport java.awt.Rectangle;\nimport java.awt.event.ComponentAdapter;\nimport java.awt.event.ComponentEvent;\nimport java.awt.event.KeyAdapter;\nimport java.awt.event.KeyEvent;\nimport java.awt.event.MouseAdapter;\nimport java.awt.event.MouseEvent;\nimport java.util.Collections;\nimport java.util.LinkedList;\nimport java.util.List;\nimport java.util.Queue;\nimport java.util.Timer;\nimport java.util.TimerTask;\n\nimport framework.core.factories.AbstractFactory;\nimport framework.core.factories.ViewFactory;\nimport framework.core.system.Application;\n\nimport game.config.OptionsPreferences;\nimport game.views.CardView;\nimport game.views.FoundationPileView;\nimport game.views.GameView;\nimport game.views.StatusBarView;\n\n/**\n * This helper class performs a win animation on the specified card\n * \n * @author Daniel Ricci {@literal <thedanny09@icloud.com>}\n */\npublic class WinAnimationHelper {\n\n    /** \n     * The timer used to update the position of the cards associated to the foundations\n     */\n    private static Timer _timer;\n\n    /**\n     * The queue of foundation views, ordered in priority of rendering importance\n     */\n    private static final Queue<FoundationPileView> _foundations = new LinkedList<FoundationPileView>();\n    \n    /**\n     * The key adapter that handles when a key is pressed during the animation phase\n     */\n    private static final KeyAdapter _keyAdapter = new KeyAdapter() {\n        @Override public void keyPressed(KeyEvent event) {\n            clear();\n            GameView.showGameOverDialog();\n        }\n    };\n    \n    /**\n     * The mouse adapter that handles when a mouse button is pressed during the animation phase\n     */\n    private static final MouseAdapter _mouseAdapter = new MouseAdapter() {\n        @Override public void mousePressed(MouseEvent event) {\n            clear();\n            GameView.showGameOverDialog();\n        }\n    };\n    \n    /**\n     * The component adapter that handles when the window changes size during the animation phase\n     * which causes the layout manager to destroy the layout of the game\n     */\n    private static final ComponentAdapter _componentAdapter = new ComponentAdapter() {\n        @Override public void componentResized(ComponentEvent event) {\n            clear();\n            GameView.showGameOverDialog();\n        }        \n    };\n    \n    /**\n     * The canvas width\n     */\n    private static int _canvasWidth;\n    \n    /**\n     * The canvas height\n     */\n    private static int _canvasHeight;\n    \n    /**\n     * The card view that is being manipulated\n     */\n    private final CardView _cardView;\n\n    /**\n     * The x-position being used for the card coordinate\n     */\n    private double _x;\n    \n    /**\n     * The y-position being used for the card coordinate\n     */\n    private double _y;\n    \n    /**\n     * The change in `x` over time\n     */\n    private double _deltaX = Math.floor(Math.random() * 6 - 3) * 2;\n    \n    /*\n     * The change in `y` over time\n     */\n    private double _deltaY = -Math.random() * 16;\n    \n    /**\n     * Constructs a new instance of this class type\n     * \n     * @param cardView The card view to animate\n     */\n    private WinAnimationHelper(CardView cardView) {\n        _cardView = cardView;\n        Point position = cardView.getParentIView().getContainerClass().getLocation();\n        _x = position.getX();\n        _y = position.getY();\n\n        if(_deltaX == 0) {\n            _deltaX = 1;\n        }\n    }\n    \n    /**\n     * Process all the cards held by the foundation views\n     */\n    public static void processCards() {\n        // Get the list of foundation piles\n        List<FoundationPileView> foundationsList = AbstractFactory.getFactory(ViewFactory.class).getAll(FoundationPileView.class);\n        \n        // Reverse the list so that we start with the left-most pile.\n        Collections.reverse(foundationsList);\n\n        // Initialize this helper class\n        initialize();\n        \n        // Populate the queue of items to be processed\n        _foundations.addAll(foundationsList);\n    }\n    \n    /**\n     * Initializes this helper in preparation for rendering the cards associated to the foundations\n     */\n    private static void initialize() {\n        OptionsPreferences preferences = new OptionsPreferences();\n        preferences.load();\n        \n        GameView gameView = AbstractFactory.getFactory(ViewFactory.class).get(GameView.class);\n        _canvasWidth = gameView.getWidth();\n        _canvasHeight = gameView.getHeight() - (preferences.statusBar ? AbstractFactory.getFactory(ViewFactory.class).get(StatusBarView.class).getHeight() : 0);\n        \n        // Clear this class before proceeding\n        clear();\n\n        Application.instance.getJMenuBar().addMouseListener(_mouseAdapter);\n        for(int i = 0; i < Application.instance.getJMenuBar().getMenuCount(); ++i) {\n            Application.instance.getJMenuBar().getMenu(i).setEnabled(false);\n        }\n\n        // Add the listeners for detecting whenever a click or a mouse event occurs during\n        // the animation so that the animation will stop and the dialog for starting a new game will get prompted\n        gameView.addMouseListener(_mouseAdapter);\n        Application.instance.addKeyListener(_keyAdapter);\n        Application.instance.addComponentListener(_componentAdapter);\n        \n        _timer = new Timer(true);\n        _timer.schedule(new TimerTask() {\n            WinAnimationHelper helper = null;\n            boolean hadValues = false;\n            @Override public void run() {\n                if(_foundations.size() > 0) {\n                    hadValues = true;\n                    if(helper != null) {\n                        if(!helper.update()) {\n                            helper._cardView.getParent().remove(helper._cardView);\n                            helper = null;\n                        }\n                    }\n                    else {\n                        // Get a reference to the current head of the foundations list\n                        FoundationPileView foundation = _foundations.poll();\n\n                        // If the foundation exists then remove it from the list and get the\n                        // last card. Provided that it exists then create a helper object to\n                        // animate the card and put the foundation at the back of the queue\n                        if(foundation != null) {\n                            _foundations.remove(foundation);\n                            CardView card = foundation.getLastCard();\n                            if(card != null) {\n                                helper = new WinAnimationHelper(card);\n                                _foundations.add(foundation);\n                            }\n                        }\n                    }\n                }\n                else {\n                    if(hadValues) {\n                        clear();\n                        GameView.showGameOverDialog();\n                    }\n                }\n            }\n        }, 0, 1000/80);\n    }\n\n    /**\n     * Performs an update by performing both a next step point calculation and a draw routine\n     *\n     * @return TRUE if the operation was successful, false otherwise\n     */\n    private boolean update() {\n\n        Point point = calculateNextStep();\n        if(point == null) {\n            return false;\n        }\n        \n        draw(point);\n        return true;    \n    }\n    \n    /**\n     * Draws the currently set card view to the specified position\n     *\n     * @param point The position to draw to\n     */\n    private void draw(Point point) {\n        CardView cardView = CardView.createLightWeightCard(_cardView);\n        cardView.render();\n        \n        ViewFactory viewFactory = AbstractFactory.getFactory(ViewFactory.class);\n        GameView gameView = viewFactory.get(GameView.class);\n        gameView.add(cardView, 0);\n        cardView.setBounds(new Rectangle(point.x, point.y, _cardView.getWidth(), _cardView.getHeight()));        \n    }\n    \n    /**\n     * Calculates the next position that the currently set card will be at\n     *\n     * @return The position associated to the next step where the card would be at \n     */\n    private Point calculateNextStep() {\n\n        // Take the change in X and the change in Y and apply them respectively\n        _x += _deltaX;\n        _y += _deltaY;\n\n        // If you are outside the left or right canvas limits then the card should not \n        // longer be positioned anywhere relevant so do not return any position\n        if(_x < -CardView.CARD_WIDTH || _x > _canvasWidth) {\n            return null;\n        }\n        \n        // If the position is outside canvas height (with respect to the bottom of the card)\n        if(_y > _canvasHeight - CardView.CARD_HEIGHT) {\n            \n            // Normalize the position of the card by placing it on the theoretical bottom of the canvas\n            _y = _canvasHeight - CardView.CARD_HEIGHT;\n            \n            // Take the change in `y` inverse it, this along will cause the card to bounce upwards\n            // Take only a small percentage of the delta so that it bounces less\n            _deltaY = -_deltaY * 0.85;\n        } \n\n        _deltaY += 0.98;\n\n        return new Point((int)_x, (int)_y);\n    }\n    \n    /**\n     * Clears the contents of this helper\n     */\n    public static void clear() {\n        if(_timer != null) {\n            _timer.cancel();\n            _timer = null;\n        }\n        \n        ViewFactory viewFactory = AbstractFactory.getFactory(ViewFactory.class);\n        if(viewFactory != null) {\n            GameView gameView = viewFactory.get(GameView.class);\n            if(gameView != null) {\n                gameView.removeMouseListener(_mouseAdapter);\n            }\n        }\n        Application.instance.removeKeyListener(_keyAdapter);\n        Application.instance.getJMenuBar().removeMouseListener(_mouseAdapter);\n        Application.instance.removeComponentListener(_componentAdapter);\n\n        // Enable back all the menu items\n        // TODO - Can this can actually be put within the MenuBuilder and then just be called from there?\n        for(int i = 0; i < Application.instance.getJMenuBar().getMenuCount(); ++i) {\n            Application.instance.getJMenuBar().getMenu(i).setEnabled(true);\n        }\n        \n        _foundations.clear();\n    }\n}"
  }
]