├── .gitignore ├── .mvn └── wrapper │ ├── maven-wrapper.jar │ └── maven-wrapper.properties ├── mvnw ├── mvnw.cmd ├── pom.xml ├── reactive-card-magic-presentation ├── images │ ├── 1non-blocking-read-1521513540917.png │ ├── 1non-blocking-write-1521513541572.png │ ├── card-pips │ │ ├── 0C-pip.png │ │ ├── 0D-pip.png │ │ ├── 0H-pip.png │ │ ├── 0S-pip.png │ │ ├── 2C-pip.png │ │ ├── 2D-pip.png │ │ ├── 2H-pip.png │ │ ├── 2S-pip.png │ │ ├── 3C-pip.png │ │ ├── 3D-pip.png │ │ ├── 3H-pip.png │ │ ├── 3S-pip.png │ │ ├── 4C-pip.png │ │ ├── 4D-pip.png │ │ ├── 4H-pip.png │ │ ├── 4S-pip.png │ │ ├── 5C-pip.png │ │ ├── 5D-pip.png │ │ ├── 5H-pip.png │ │ ├── 5S-pip.png │ │ ├── 6C-pip.png │ │ ├── 6D-pip.png │ │ ├── 6H-pip.png │ │ ├── 6S-pip.png │ │ ├── 7C-pip.png │ │ ├── 7D-pip.png │ │ ├── 7H-pip.png │ │ ├── 7S-pip.png │ │ ├── 8C-pip.png │ │ ├── 8D-pip.png │ │ ├── 8H-pip.png │ │ ├── 8S-pip.png │ │ ├── 9C-pip.png │ │ ├── 9D-pip.png │ │ ├── 9H-pip.png │ │ ├── 9S-pip.png │ │ ├── AC-pip.png │ │ ├── AD-pip.png │ │ ├── AH-pip.png │ │ ├── AS-pip.png │ │ ├── JC-pip.png │ │ ├── JD-pip.png │ │ ├── JH-pip.png │ │ ├── JS-pip.png │ │ ├── KC-pip.png │ │ ├── KD-pip.png │ │ ├── KH-pip.png │ │ ├── KS-pip.png │ │ ├── QC-pip.png │ │ ├── QD-pip.png │ │ ├── QH-pip.png │ │ └── QS-pip.png │ ├── deal-only-hearts-screenshot.png │ ├── deal-poker-hand-screenshot.png │ ├── diagram-boot-reactor-lower-left.png │ ├── diagram-boot-reactor.png │ ├── front-matter │ │ ├── about-james-weaver.png │ │ ├── pivotal-mission-values.png │ │ ├── pivotal-mission.png │ │ └── title-slide-matter.png │ ├── hand-freq-json-ss.png │ ├── heart.png │ ├── logos │ │ └── pivotal-logo.png │ ├── marble-diagrams │ │ ├── flux │ │ │ ├── collectlist.png │ │ │ ├── filter.png │ │ │ ├── flux-marble-diagram.png │ │ │ ├── index.png │ │ │ ├── sort.png │ │ │ ├── sort.pxm │ │ │ └── take.png │ │ └── mono │ │ │ ├── map1.png │ │ │ └── mono-marble-diagram.png │ ├── rcm-app-shots │ │ ├── rcm-app-deal-poker.png │ │ ├── rcm-app-new-deck.png │ │ ├── rcm-app-only-hearts.png │ │ ├── rcm-app-three-kind.png │ │ └── rcm-app-two-pairs.png │ ├── spring-mvc-and-webflux-venn.png │ ├── tuples-screenshot.png │ └── z-ORIG-blank-card.png ├── reactive-card-magic.key └── reactive-card-magic.pdf └── src ├── main ├── java │ └── com │ │ └── javafxpert │ │ └── carddeckdemo │ │ ├── CardDeckDemoApplication.java │ │ ├── deck │ │ ├── configuration │ │ │ ├── CardDeckImagesServerProperties.java │ │ │ ├── DataLoaderCardDeck.java │ │ │ └── PokerServerProperties.java │ │ ├── controller │ │ │ └── CardDeckController.java │ │ ├── domain │ │ │ ├── Card.java │ │ │ └── CardHand.java │ │ ├── repository │ │ │ └── CardDeckRepository.java │ │ └── service │ │ │ ├── CardDeckService.java │ │ │ ├── CardShufflingService.java │ │ │ ├── PokerService.java │ │ │ └── impl │ │ │ ├── DefaultCardDeckService.java │ │ │ ├── DefaultCardShufflingService.java │ │ │ └── ProxyPokerService.java │ │ └── poker │ │ ├── Cards.java │ │ ├── configuration │ │ └── DataLoaderHandFrequencies.java │ │ ├── controller │ │ └── PokerController.java │ │ ├── domain │ │ ├── HandFrequency.java │ │ ├── PokerHand.java │ │ └── ScoreHand.java │ │ ├── repository │ │ └── HandFrequencyRepository.java │ │ └── service │ │ └── PokerService.java └── resources │ ├── META-INF │ └── additional-spring-configuration-metadata.json │ ├── application.properties │ └── static │ ├── app.js │ ├── images │ ├── 0C.png │ ├── 0D.png │ ├── 0H.png │ ├── 0S.png │ ├── 2C.png │ ├── 2D.png │ ├── 2H.png │ ├── 2S.png │ ├── 3C.png │ ├── 3D.png │ ├── 3H.png │ ├── 3S.png │ ├── 4C.png │ ├── 4D.png │ ├── 4H.png │ ├── 4S.png │ ├── 5C.png │ ├── 5D.png │ ├── 5H.png │ ├── 5S.png │ ├── 6C.png │ ├── 6D.png │ ├── 6H.png │ ├── 6S.png │ ├── 7C.png │ ├── 7D.png │ ├── 7H.png │ ├── 7S.png │ ├── 8C.png │ ├── 8D.png │ ├── 8H.png │ ├── 8S.png │ ├── 9C.png │ ├── 9D.png │ ├── 9H.png │ ├── 9S.png │ ├── AC.png │ ├── AD.png │ ├── AH.png │ ├── AS.png │ ├── JC.png │ ├── JD.png │ ├── JH.png │ ├── JS.png │ ├── KC.png │ ├── KD.png │ ├── KH.png │ ├── KS.png │ ├── QC.png │ ├── QD.png │ ├── QH.png │ ├── QS.png │ ├── gray_back_reactor.png │ └── spring-project-reactor.png │ ├── index.html │ └── styles.css └── test └── java └── com └── javafxpert └── carddeckdemo ├── CardDeckDemoApplicationTests.java ├── PokerHandTester.java ├── controllers └── CardDeckControllerTest.java ├── model └── CardTest.java ├── services └── CardDeckServiceTest.java └── util └── ScoreHandTest.java /.gitignore: -------------------------------------------------------------------------------- 1 | target/ 2 | !.mvn/wrapper/maven-wrapper.jar 3 | 4 | ### STS ### 5 | .apt_generated 6 | .classpath 7 | .factorypath 8 | .project 9 | .settings 10 | .springBeans 11 | .sts4-cache 12 | 13 | ### IntelliJ IDEA ### 14 | .idea 15 | *.iws 16 | *.iml 17 | *.ipr 18 | 19 | ### NetBeans ### 20 | nbproject/private/ 21 | build/ 22 | nbbuild/ 23 | dist/ 24 | nbdist/ 25 | .nb-gradle/ -------------------------------------------------------------------------------- /.mvn/wrapper/maven-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JavaFXpert/card-deck-demo/eefe994dadd4af117fe406256a7495ea6da0de12/.mvn/wrapper/maven-wrapper.jar -------------------------------------------------------------------------------- /.mvn/wrapper/maven-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionUrl=https://repo1.maven.org/maven2/org/apache/maven/apache-maven/3.5.3/apache-maven-3.5.3-bin.zip 2 | -------------------------------------------------------------------------------- /mvnw: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # ---------------------------------------------------------------------------- 3 | # Licensed to the Apache Software Foundation (ASF) under one 4 | # or more contributor license agreements. See the NOTICE file 5 | # distributed with this work for additional information 6 | # regarding copyright ownership. The ASF licenses this file 7 | # to you under the Apache License, Version 2.0 (the 8 | # "License"); you may not use this file except in compliance 9 | # with the License. You may obtain a copy of the License at 10 | # 11 | # http://www.apache.org/licenses/LICENSE-2.0 12 | # 13 | # Unless required by applicable law or agreed to in writing, 14 | # software distributed under the License is distributed on an 15 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 | # KIND, either express or implied. See the License for the 17 | # specific language governing permissions and limitations 18 | # under the License. 19 | # ---------------------------------------------------------------------------- 20 | 21 | # ---------------------------------------------------------------------------- 22 | # Maven2 Start Up Batch script 23 | # 24 | # Required ENV vars: 25 | # ------------------ 26 | # JAVA_HOME - location of a JDK home dir 27 | # 28 | # Optional ENV vars 29 | # ----------------- 30 | # M2_HOME - location of maven2's installed home dir 31 | # MAVEN_OPTS - parameters passed to the Java VM when running Maven 32 | # e.g. to debug Maven itself, use 33 | # set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 34 | # MAVEN_SKIP_RC - flag to disable loading of mavenrc files 35 | # ---------------------------------------------------------------------------- 36 | 37 | if [ -z "$MAVEN_SKIP_RC" ] ; then 38 | 39 | if [ -f /etc/mavenrc ] ; then 40 | . /etc/mavenrc 41 | fi 42 | 43 | if [ -f "$HOME/.mavenrc" ] ; then 44 | . "$HOME/.mavenrc" 45 | fi 46 | 47 | fi 48 | 49 | # OS specific support. $var _must_ be set to either true or false. 50 | cygwin=false; 51 | darwin=false; 52 | mingw=false 53 | case "`uname`" in 54 | CYGWIN*) cygwin=true ;; 55 | MINGW*) mingw=true;; 56 | Darwin*) darwin=true 57 | # Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home 58 | # See https://developer.apple.com/library/mac/qa/qa1170/_index.html 59 | if [ -z "$JAVA_HOME" ]; then 60 | if [ -x "/usr/libexec/java_home" ]; then 61 | export JAVA_HOME="`/usr/libexec/java_home`" 62 | else 63 | export JAVA_HOME="/Library/Java/Home" 64 | fi 65 | fi 66 | ;; 67 | esac 68 | 69 | if [ -z "$JAVA_HOME" ] ; then 70 | if [ -r /etc/gentoo-release ] ; then 71 | JAVA_HOME=`java-config --jre-home` 72 | fi 73 | fi 74 | 75 | if [ -z "$M2_HOME" ] ; then 76 | ## resolve links - $0 may be a link to maven's home 77 | PRG="$0" 78 | 79 | # need this for relative symlinks 80 | while [ -h "$PRG" ] ; do 81 | ls=`ls -ld "$PRG"` 82 | link=`expr "$ls" : '.*-> \(.*\)$'` 83 | if expr "$link" : '/.*' > /dev/null; then 84 | PRG="$link" 85 | else 86 | PRG="`dirname "$PRG"`/$link" 87 | fi 88 | done 89 | 90 | saveddir=`pwd` 91 | 92 | M2_HOME=`dirname "$PRG"`/.. 93 | 94 | # make it fully qualified 95 | M2_HOME=`cd "$M2_HOME" && pwd` 96 | 97 | cd "$saveddir" 98 | # echo Using m2 at $M2_HOME 99 | fi 100 | 101 | # For Cygwin, ensure paths are in UNIX format before anything is touched 102 | if $cygwin ; then 103 | [ -n "$M2_HOME" ] && 104 | M2_HOME=`cygpath --unix "$M2_HOME"` 105 | [ -n "$JAVA_HOME" ] && 106 | JAVA_HOME=`cygpath --unix "$JAVA_HOME"` 107 | [ -n "$CLASSPATH" ] && 108 | CLASSPATH=`cygpath --path --unix "$CLASSPATH"` 109 | fi 110 | 111 | # For Migwn, ensure paths are in UNIX format before anything is touched 112 | if $mingw ; then 113 | [ -n "$M2_HOME" ] && 114 | M2_HOME="`(cd "$M2_HOME"; pwd)`" 115 | [ -n "$JAVA_HOME" ] && 116 | JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`" 117 | # TODO classpath? 118 | fi 119 | 120 | if [ -z "$JAVA_HOME" ]; then 121 | javaExecutable="`which javac`" 122 | if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then 123 | # readlink(1) is not available as standard on Solaris 10. 124 | readLink=`which readlink` 125 | if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then 126 | if $darwin ; then 127 | javaHome="`dirname \"$javaExecutable\"`" 128 | javaExecutable="`cd \"$javaHome\" && pwd -P`/javac" 129 | else 130 | javaExecutable="`readlink -f \"$javaExecutable\"`" 131 | fi 132 | javaHome="`dirname \"$javaExecutable\"`" 133 | javaHome=`expr "$javaHome" : '\(.*\)/bin'` 134 | JAVA_HOME="$javaHome" 135 | export JAVA_HOME 136 | fi 137 | fi 138 | fi 139 | 140 | if [ -z "$JAVACMD" ] ; then 141 | if [ -n "$JAVA_HOME" ] ; then 142 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 143 | # IBM's JDK on AIX uses strange locations for the executables 144 | JAVACMD="$JAVA_HOME/jre/sh/java" 145 | else 146 | JAVACMD="$JAVA_HOME/bin/java" 147 | fi 148 | else 149 | JAVACMD="`which java`" 150 | fi 151 | fi 152 | 153 | if [ ! -x "$JAVACMD" ] ; then 154 | echo "Error: JAVA_HOME is not defined correctly." >&2 155 | echo " We cannot execute $JAVACMD" >&2 156 | exit 1 157 | fi 158 | 159 | if [ -z "$JAVA_HOME" ] ; then 160 | echo "Warning: JAVA_HOME environment variable is not set." 161 | fi 162 | 163 | CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher 164 | 165 | # traverses directory structure from process work directory to filesystem root 166 | # first directory with .mvn subdirectory is considered project base directory 167 | find_maven_basedir() { 168 | 169 | if [ -z "$1" ] 170 | then 171 | echo "Path not specified to find_maven_basedir" 172 | return 1 173 | fi 174 | 175 | basedir="$1" 176 | wdir="$1" 177 | while [ "$wdir" != '/' ] ; do 178 | if [ -d "$wdir"/.mvn ] ; then 179 | basedir=$wdir 180 | break 181 | fi 182 | # workaround for JBEAP-8937 (on Solaris 10/Sparc) 183 | if [ -d "${wdir}" ]; then 184 | wdir=`cd "$wdir/.."; pwd` 185 | fi 186 | # end of workaround 187 | done 188 | echo "${basedir}" 189 | } 190 | 191 | # concatenates all lines of a file 192 | concat_lines() { 193 | if [ -f "$1" ]; then 194 | echo "$(tr -s '\n' ' ' < "$1")" 195 | fi 196 | } 197 | 198 | BASE_DIR=`find_maven_basedir "$(pwd)"` 199 | if [ -z "$BASE_DIR" ]; then 200 | exit 1; 201 | fi 202 | 203 | export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"} 204 | echo $MAVEN_PROJECTBASEDIR 205 | MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS" 206 | 207 | # For Cygwin, switch paths to Windows format before running java 208 | if $cygwin; then 209 | [ -n "$M2_HOME" ] && 210 | M2_HOME=`cygpath --path --windows "$M2_HOME"` 211 | [ -n "$JAVA_HOME" ] && 212 | JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"` 213 | [ -n "$CLASSPATH" ] && 214 | CLASSPATH=`cygpath --path --windows "$CLASSPATH"` 215 | [ -n "$MAVEN_PROJECTBASEDIR" ] && 216 | MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"` 217 | fi 218 | 219 | WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain 220 | 221 | exec "$JAVACMD" \ 222 | $MAVEN_OPTS \ 223 | -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \ 224 | "-Dmaven.home=${M2_HOME}" "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \ 225 | ${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@" 226 | -------------------------------------------------------------------------------- /mvnw.cmd: -------------------------------------------------------------------------------- 1 | @REM ---------------------------------------------------------------------------- 2 | @REM Licensed to the Apache Software Foundation (ASF) under one 3 | @REM or more contributor license agreements. See the NOTICE file 4 | @REM distributed with this work for additional information 5 | @REM regarding copyright ownership. The ASF licenses this file 6 | @REM to you under the Apache License, Version 2.0 (the 7 | @REM "License"); you may not use this file except in compliance 8 | @REM with the License. You may obtain a copy of the License at 9 | @REM 10 | @REM http://www.apache.org/licenses/LICENSE-2.0 11 | @REM 12 | @REM Unless required by applicable law or agreed to in writing, 13 | @REM software distributed under the License is distributed on an 14 | @REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | @REM KIND, either express or implied. See the License for the 16 | @REM specific language governing permissions and limitations 17 | @REM under the License. 18 | @REM ---------------------------------------------------------------------------- 19 | 20 | @REM ---------------------------------------------------------------------------- 21 | @REM Maven2 Start Up Batch script 22 | @REM 23 | @REM Required ENV vars: 24 | @REM JAVA_HOME - location of a JDK home dir 25 | @REM 26 | @REM Optional ENV vars 27 | @REM M2_HOME - location of maven2's installed home dir 28 | @REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands 29 | @REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a key stroke before ending 30 | @REM MAVEN_OPTS - parameters passed to the Java VM when running Maven 31 | @REM e.g. to debug Maven itself, use 32 | @REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 33 | @REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files 34 | @REM ---------------------------------------------------------------------------- 35 | 36 | @REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on' 37 | @echo off 38 | @REM enable echoing my setting MAVEN_BATCH_ECHO to 'on' 39 | @if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO% 40 | 41 | @REM set %HOME% to equivalent of $HOME 42 | if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%") 43 | 44 | @REM Execute a user defined script before this one 45 | if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre 46 | @REM check for pre script, once with legacy .bat ending and once with .cmd ending 47 | if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat" 48 | if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\mavenrc_pre.cmd" 49 | :skipRcPre 50 | 51 | @setlocal 52 | 53 | set ERROR_CODE=0 54 | 55 | @REM To isolate internal variables from possible post scripts, we use another setlocal 56 | @setlocal 57 | 58 | @REM ==== START VALIDATION ==== 59 | if not "%JAVA_HOME%" == "" goto OkJHome 60 | 61 | echo. 62 | echo Error: JAVA_HOME not found in your environment. >&2 63 | echo Please set the JAVA_HOME variable in your environment to match the >&2 64 | echo location of your Java installation. >&2 65 | echo. 66 | goto error 67 | 68 | :OkJHome 69 | if exist "%JAVA_HOME%\bin\java.exe" goto init 70 | 71 | echo. 72 | echo Error: JAVA_HOME is set to an invalid directory. >&2 73 | echo JAVA_HOME = "%JAVA_HOME%" >&2 74 | echo Please set the JAVA_HOME variable in your environment to match the >&2 75 | echo location of your Java installation. >&2 76 | echo. 77 | goto error 78 | 79 | @REM ==== END VALIDATION ==== 80 | 81 | :init 82 | 83 | @REM Find the project base dir, i.e. the directory that contains the folder ".mvn". 84 | @REM Fallback to current working directory if not found. 85 | 86 | set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR% 87 | IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir 88 | 89 | set EXEC_DIR=%CD% 90 | set WDIR=%EXEC_DIR% 91 | :findBaseDir 92 | IF EXIST "%WDIR%"\.mvn goto baseDirFound 93 | cd .. 94 | IF "%WDIR%"=="%CD%" goto baseDirNotFound 95 | set WDIR=%CD% 96 | goto findBaseDir 97 | 98 | :baseDirFound 99 | set MAVEN_PROJECTBASEDIR=%WDIR% 100 | cd "%EXEC_DIR%" 101 | goto endDetectBaseDir 102 | 103 | :baseDirNotFound 104 | set MAVEN_PROJECTBASEDIR=%EXEC_DIR% 105 | cd "%EXEC_DIR%" 106 | 107 | :endDetectBaseDir 108 | 109 | IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig 110 | 111 | @setlocal EnableExtensions EnableDelayedExpansion 112 | for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a 113 | @endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS% 114 | 115 | :endReadAdditionalConfig 116 | 117 | SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe" 118 | 119 | set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar" 120 | set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain 121 | 122 | %MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %* 123 | if ERRORLEVEL 1 goto error 124 | goto end 125 | 126 | :error 127 | set ERROR_CODE=1 128 | 129 | :end 130 | @endlocal & set ERROR_CODE=%ERROR_CODE% 131 | 132 | if not "%MAVEN_SKIP_RC%" == "" goto skipRcPost 133 | @REM check for post script, once with legacy .bat ending and once with .cmd ending 134 | if exist "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat" 135 | if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\mavenrc_post.cmd" 136 | :skipRcPost 137 | 138 | @REM pause the script if MAVEN_BATCH_PAUSE is set to 'on' 139 | if "%MAVEN_BATCH_PAUSE%" == "on" pause 140 | 141 | if "%MAVEN_TERMINATE_CMD%" == "on" exit %ERROR_CODE% 142 | 143 | exit /B %ERROR_CODE% 144 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 4.0.0 5 | 6 | com.javafxpert 7 | card-deck-demo 8 | 0.0.1-SNAPSHOT 9 | jar 10 | 11 | card-deck-demo 12 | Card deck related Web on Reactive Stack demo 13 | 14 | 15 | org.springframework.boot 16 | spring-boot-starter-parent 17 | 2.0.1.RELEASE 18 | 19 | 20 | 21 | 22 | UTF-8 23 | UTF-8 24 | 8 25 | 26 | 27 | 28 | 29 | org.springframework.boot 30 | spring-boot-starter-actuator 31 | 32 | 33 | org.springframework.boot 34 | spring-boot-starter-data-mongodb-reactive 35 | 36 | 37 | 38 | 39 | 40 | 41 | org.springframework.boot 42 | spring-boot-starter-webflux 43 | 44 | 45 | 46 | org.springframework.boot 47 | spring-boot-configuration-processor 48 | true 49 | 50 | 51 | 52 | org.springframework.boot 53 | spring-boot-starter-test 54 | test 55 | 56 | 57 | io.projectreactor 58 | reactor-test 59 | test 60 | 61 | 62 | io.projectreactor.addons 63 | reactor-extra 64 | 65 | 66 | de.flapdoodle.embed 67 | de.flapdoodle.embed.mongo 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | org.junit.jupiter 76 | junit-jupiter-api 77 | test 78 | 79 | 80 | org.springframework.boot 81 | spring-boot-configuration-processor 82 | true 83 | 84 | 85 | 86 | 87 | 88 | 89 | org.springframework.boot 90 | spring-boot-maven-plugin 91 | 92 | 93 | 94 | 95 | 96 | 97 | -------------------------------------------------------------------------------- /reactive-card-magic-presentation/images/1non-blocking-read-1521513540917.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JavaFXpert/card-deck-demo/eefe994dadd4af117fe406256a7495ea6da0de12/reactive-card-magic-presentation/images/1non-blocking-read-1521513540917.png -------------------------------------------------------------------------------- /reactive-card-magic-presentation/images/1non-blocking-write-1521513541572.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JavaFXpert/card-deck-demo/eefe994dadd4af117fe406256a7495ea6da0de12/reactive-card-magic-presentation/images/1non-blocking-write-1521513541572.png -------------------------------------------------------------------------------- /reactive-card-magic-presentation/images/card-pips/0C-pip.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JavaFXpert/card-deck-demo/eefe994dadd4af117fe406256a7495ea6da0de12/reactive-card-magic-presentation/images/card-pips/0C-pip.png -------------------------------------------------------------------------------- /reactive-card-magic-presentation/images/card-pips/0D-pip.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JavaFXpert/card-deck-demo/eefe994dadd4af117fe406256a7495ea6da0de12/reactive-card-magic-presentation/images/card-pips/0D-pip.png -------------------------------------------------------------------------------- /reactive-card-magic-presentation/images/card-pips/0H-pip.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JavaFXpert/card-deck-demo/eefe994dadd4af117fe406256a7495ea6da0de12/reactive-card-magic-presentation/images/card-pips/0H-pip.png -------------------------------------------------------------------------------- /reactive-card-magic-presentation/images/card-pips/0S-pip.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JavaFXpert/card-deck-demo/eefe994dadd4af117fe406256a7495ea6da0de12/reactive-card-magic-presentation/images/card-pips/0S-pip.png -------------------------------------------------------------------------------- /reactive-card-magic-presentation/images/card-pips/2C-pip.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JavaFXpert/card-deck-demo/eefe994dadd4af117fe406256a7495ea6da0de12/reactive-card-magic-presentation/images/card-pips/2C-pip.png -------------------------------------------------------------------------------- /reactive-card-magic-presentation/images/card-pips/2D-pip.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JavaFXpert/card-deck-demo/eefe994dadd4af117fe406256a7495ea6da0de12/reactive-card-magic-presentation/images/card-pips/2D-pip.png -------------------------------------------------------------------------------- /reactive-card-magic-presentation/images/card-pips/2H-pip.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JavaFXpert/card-deck-demo/eefe994dadd4af117fe406256a7495ea6da0de12/reactive-card-magic-presentation/images/card-pips/2H-pip.png -------------------------------------------------------------------------------- /reactive-card-magic-presentation/images/card-pips/2S-pip.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JavaFXpert/card-deck-demo/eefe994dadd4af117fe406256a7495ea6da0de12/reactive-card-magic-presentation/images/card-pips/2S-pip.png -------------------------------------------------------------------------------- /reactive-card-magic-presentation/images/card-pips/3C-pip.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JavaFXpert/card-deck-demo/eefe994dadd4af117fe406256a7495ea6da0de12/reactive-card-magic-presentation/images/card-pips/3C-pip.png -------------------------------------------------------------------------------- /reactive-card-magic-presentation/images/card-pips/3D-pip.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JavaFXpert/card-deck-demo/eefe994dadd4af117fe406256a7495ea6da0de12/reactive-card-magic-presentation/images/card-pips/3D-pip.png -------------------------------------------------------------------------------- /reactive-card-magic-presentation/images/card-pips/3H-pip.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JavaFXpert/card-deck-demo/eefe994dadd4af117fe406256a7495ea6da0de12/reactive-card-magic-presentation/images/card-pips/3H-pip.png -------------------------------------------------------------------------------- /reactive-card-magic-presentation/images/card-pips/3S-pip.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JavaFXpert/card-deck-demo/eefe994dadd4af117fe406256a7495ea6da0de12/reactive-card-magic-presentation/images/card-pips/3S-pip.png -------------------------------------------------------------------------------- /reactive-card-magic-presentation/images/card-pips/4C-pip.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JavaFXpert/card-deck-demo/eefe994dadd4af117fe406256a7495ea6da0de12/reactive-card-magic-presentation/images/card-pips/4C-pip.png -------------------------------------------------------------------------------- /reactive-card-magic-presentation/images/card-pips/4D-pip.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JavaFXpert/card-deck-demo/eefe994dadd4af117fe406256a7495ea6da0de12/reactive-card-magic-presentation/images/card-pips/4D-pip.png -------------------------------------------------------------------------------- /reactive-card-magic-presentation/images/card-pips/4H-pip.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JavaFXpert/card-deck-demo/eefe994dadd4af117fe406256a7495ea6da0de12/reactive-card-magic-presentation/images/card-pips/4H-pip.png -------------------------------------------------------------------------------- /reactive-card-magic-presentation/images/card-pips/4S-pip.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JavaFXpert/card-deck-demo/eefe994dadd4af117fe406256a7495ea6da0de12/reactive-card-magic-presentation/images/card-pips/4S-pip.png -------------------------------------------------------------------------------- /reactive-card-magic-presentation/images/card-pips/5C-pip.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JavaFXpert/card-deck-demo/eefe994dadd4af117fe406256a7495ea6da0de12/reactive-card-magic-presentation/images/card-pips/5C-pip.png -------------------------------------------------------------------------------- /reactive-card-magic-presentation/images/card-pips/5D-pip.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JavaFXpert/card-deck-demo/eefe994dadd4af117fe406256a7495ea6da0de12/reactive-card-magic-presentation/images/card-pips/5D-pip.png -------------------------------------------------------------------------------- /reactive-card-magic-presentation/images/card-pips/5H-pip.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JavaFXpert/card-deck-demo/eefe994dadd4af117fe406256a7495ea6da0de12/reactive-card-magic-presentation/images/card-pips/5H-pip.png -------------------------------------------------------------------------------- /reactive-card-magic-presentation/images/card-pips/5S-pip.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JavaFXpert/card-deck-demo/eefe994dadd4af117fe406256a7495ea6da0de12/reactive-card-magic-presentation/images/card-pips/5S-pip.png -------------------------------------------------------------------------------- /reactive-card-magic-presentation/images/card-pips/6C-pip.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JavaFXpert/card-deck-demo/eefe994dadd4af117fe406256a7495ea6da0de12/reactive-card-magic-presentation/images/card-pips/6C-pip.png -------------------------------------------------------------------------------- /reactive-card-magic-presentation/images/card-pips/6D-pip.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JavaFXpert/card-deck-demo/eefe994dadd4af117fe406256a7495ea6da0de12/reactive-card-magic-presentation/images/card-pips/6D-pip.png -------------------------------------------------------------------------------- /reactive-card-magic-presentation/images/card-pips/6H-pip.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JavaFXpert/card-deck-demo/eefe994dadd4af117fe406256a7495ea6da0de12/reactive-card-magic-presentation/images/card-pips/6H-pip.png -------------------------------------------------------------------------------- /reactive-card-magic-presentation/images/card-pips/6S-pip.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JavaFXpert/card-deck-demo/eefe994dadd4af117fe406256a7495ea6da0de12/reactive-card-magic-presentation/images/card-pips/6S-pip.png -------------------------------------------------------------------------------- /reactive-card-magic-presentation/images/card-pips/7C-pip.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JavaFXpert/card-deck-demo/eefe994dadd4af117fe406256a7495ea6da0de12/reactive-card-magic-presentation/images/card-pips/7C-pip.png -------------------------------------------------------------------------------- /reactive-card-magic-presentation/images/card-pips/7D-pip.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JavaFXpert/card-deck-demo/eefe994dadd4af117fe406256a7495ea6da0de12/reactive-card-magic-presentation/images/card-pips/7D-pip.png -------------------------------------------------------------------------------- /reactive-card-magic-presentation/images/card-pips/7H-pip.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JavaFXpert/card-deck-demo/eefe994dadd4af117fe406256a7495ea6da0de12/reactive-card-magic-presentation/images/card-pips/7H-pip.png -------------------------------------------------------------------------------- /reactive-card-magic-presentation/images/card-pips/7S-pip.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JavaFXpert/card-deck-demo/eefe994dadd4af117fe406256a7495ea6da0de12/reactive-card-magic-presentation/images/card-pips/7S-pip.png -------------------------------------------------------------------------------- /reactive-card-magic-presentation/images/card-pips/8C-pip.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JavaFXpert/card-deck-demo/eefe994dadd4af117fe406256a7495ea6da0de12/reactive-card-magic-presentation/images/card-pips/8C-pip.png -------------------------------------------------------------------------------- /reactive-card-magic-presentation/images/card-pips/8D-pip.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JavaFXpert/card-deck-demo/eefe994dadd4af117fe406256a7495ea6da0de12/reactive-card-magic-presentation/images/card-pips/8D-pip.png -------------------------------------------------------------------------------- /reactive-card-magic-presentation/images/card-pips/8H-pip.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JavaFXpert/card-deck-demo/eefe994dadd4af117fe406256a7495ea6da0de12/reactive-card-magic-presentation/images/card-pips/8H-pip.png -------------------------------------------------------------------------------- /reactive-card-magic-presentation/images/card-pips/8S-pip.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JavaFXpert/card-deck-demo/eefe994dadd4af117fe406256a7495ea6da0de12/reactive-card-magic-presentation/images/card-pips/8S-pip.png -------------------------------------------------------------------------------- /reactive-card-magic-presentation/images/card-pips/9C-pip.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JavaFXpert/card-deck-demo/eefe994dadd4af117fe406256a7495ea6da0de12/reactive-card-magic-presentation/images/card-pips/9C-pip.png -------------------------------------------------------------------------------- /reactive-card-magic-presentation/images/card-pips/9D-pip.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JavaFXpert/card-deck-demo/eefe994dadd4af117fe406256a7495ea6da0de12/reactive-card-magic-presentation/images/card-pips/9D-pip.png -------------------------------------------------------------------------------- /reactive-card-magic-presentation/images/card-pips/9H-pip.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JavaFXpert/card-deck-demo/eefe994dadd4af117fe406256a7495ea6da0de12/reactive-card-magic-presentation/images/card-pips/9H-pip.png -------------------------------------------------------------------------------- /reactive-card-magic-presentation/images/card-pips/9S-pip.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JavaFXpert/card-deck-demo/eefe994dadd4af117fe406256a7495ea6da0de12/reactive-card-magic-presentation/images/card-pips/9S-pip.png -------------------------------------------------------------------------------- /reactive-card-magic-presentation/images/card-pips/AC-pip.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JavaFXpert/card-deck-demo/eefe994dadd4af117fe406256a7495ea6da0de12/reactive-card-magic-presentation/images/card-pips/AC-pip.png -------------------------------------------------------------------------------- /reactive-card-magic-presentation/images/card-pips/AD-pip.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JavaFXpert/card-deck-demo/eefe994dadd4af117fe406256a7495ea6da0de12/reactive-card-magic-presentation/images/card-pips/AD-pip.png -------------------------------------------------------------------------------- /reactive-card-magic-presentation/images/card-pips/AH-pip.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JavaFXpert/card-deck-demo/eefe994dadd4af117fe406256a7495ea6da0de12/reactive-card-magic-presentation/images/card-pips/AH-pip.png -------------------------------------------------------------------------------- /reactive-card-magic-presentation/images/card-pips/AS-pip.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JavaFXpert/card-deck-demo/eefe994dadd4af117fe406256a7495ea6da0de12/reactive-card-magic-presentation/images/card-pips/AS-pip.png -------------------------------------------------------------------------------- /reactive-card-magic-presentation/images/card-pips/JC-pip.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JavaFXpert/card-deck-demo/eefe994dadd4af117fe406256a7495ea6da0de12/reactive-card-magic-presentation/images/card-pips/JC-pip.png -------------------------------------------------------------------------------- /reactive-card-magic-presentation/images/card-pips/JD-pip.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JavaFXpert/card-deck-demo/eefe994dadd4af117fe406256a7495ea6da0de12/reactive-card-magic-presentation/images/card-pips/JD-pip.png -------------------------------------------------------------------------------- /reactive-card-magic-presentation/images/card-pips/JH-pip.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JavaFXpert/card-deck-demo/eefe994dadd4af117fe406256a7495ea6da0de12/reactive-card-magic-presentation/images/card-pips/JH-pip.png -------------------------------------------------------------------------------- /reactive-card-magic-presentation/images/card-pips/JS-pip.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JavaFXpert/card-deck-demo/eefe994dadd4af117fe406256a7495ea6da0de12/reactive-card-magic-presentation/images/card-pips/JS-pip.png -------------------------------------------------------------------------------- /reactive-card-magic-presentation/images/card-pips/KC-pip.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JavaFXpert/card-deck-demo/eefe994dadd4af117fe406256a7495ea6da0de12/reactive-card-magic-presentation/images/card-pips/KC-pip.png -------------------------------------------------------------------------------- /reactive-card-magic-presentation/images/card-pips/KD-pip.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JavaFXpert/card-deck-demo/eefe994dadd4af117fe406256a7495ea6da0de12/reactive-card-magic-presentation/images/card-pips/KD-pip.png -------------------------------------------------------------------------------- /reactive-card-magic-presentation/images/card-pips/KH-pip.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JavaFXpert/card-deck-demo/eefe994dadd4af117fe406256a7495ea6da0de12/reactive-card-magic-presentation/images/card-pips/KH-pip.png -------------------------------------------------------------------------------- /reactive-card-magic-presentation/images/card-pips/KS-pip.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JavaFXpert/card-deck-demo/eefe994dadd4af117fe406256a7495ea6da0de12/reactive-card-magic-presentation/images/card-pips/KS-pip.png -------------------------------------------------------------------------------- /reactive-card-magic-presentation/images/card-pips/QC-pip.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JavaFXpert/card-deck-demo/eefe994dadd4af117fe406256a7495ea6da0de12/reactive-card-magic-presentation/images/card-pips/QC-pip.png -------------------------------------------------------------------------------- /reactive-card-magic-presentation/images/card-pips/QD-pip.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JavaFXpert/card-deck-demo/eefe994dadd4af117fe406256a7495ea6da0de12/reactive-card-magic-presentation/images/card-pips/QD-pip.png -------------------------------------------------------------------------------- /reactive-card-magic-presentation/images/card-pips/QH-pip.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JavaFXpert/card-deck-demo/eefe994dadd4af117fe406256a7495ea6da0de12/reactive-card-magic-presentation/images/card-pips/QH-pip.png -------------------------------------------------------------------------------- /reactive-card-magic-presentation/images/card-pips/QS-pip.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JavaFXpert/card-deck-demo/eefe994dadd4af117fe406256a7495ea6da0de12/reactive-card-magic-presentation/images/card-pips/QS-pip.png -------------------------------------------------------------------------------- /reactive-card-magic-presentation/images/deal-only-hearts-screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JavaFXpert/card-deck-demo/eefe994dadd4af117fe406256a7495ea6da0de12/reactive-card-magic-presentation/images/deal-only-hearts-screenshot.png -------------------------------------------------------------------------------- /reactive-card-magic-presentation/images/deal-poker-hand-screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JavaFXpert/card-deck-demo/eefe994dadd4af117fe406256a7495ea6da0de12/reactive-card-magic-presentation/images/deal-poker-hand-screenshot.png -------------------------------------------------------------------------------- /reactive-card-magic-presentation/images/diagram-boot-reactor-lower-left.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JavaFXpert/card-deck-demo/eefe994dadd4af117fe406256a7495ea6da0de12/reactive-card-magic-presentation/images/diagram-boot-reactor-lower-left.png -------------------------------------------------------------------------------- /reactive-card-magic-presentation/images/diagram-boot-reactor.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JavaFXpert/card-deck-demo/eefe994dadd4af117fe406256a7495ea6da0de12/reactive-card-magic-presentation/images/diagram-boot-reactor.png -------------------------------------------------------------------------------- /reactive-card-magic-presentation/images/front-matter/about-james-weaver.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JavaFXpert/card-deck-demo/eefe994dadd4af117fe406256a7495ea6da0de12/reactive-card-magic-presentation/images/front-matter/about-james-weaver.png -------------------------------------------------------------------------------- /reactive-card-magic-presentation/images/front-matter/pivotal-mission-values.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JavaFXpert/card-deck-demo/eefe994dadd4af117fe406256a7495ea6da0de12/reactive-card-magic-presentation/images/front-matter/pivotal-mission-values.png -------------------------------------------------------------------------------- /reactive-card-magic-presentation/images/front-matter/pivotal-mission.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JavaFXpert/card-deck-demo/eefe994dadd4af117fe406256a7495ea6da0de12/reactive-card-magic-presentation/images/front-matter/pivotal-mission.png -------------------------------------------------------------------------------- /reactive-card-magic-presentation/images/front-matter/title-slide-matter.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JavaFXpert/card-deck-demo/eefe994dadd4af117fe406256a7495ea6da0de12/reactive-card-magic-presentation/images/front-matter/title-slide-matter.png -------------------------------------------------------------------------------- /reactive-card-magic-presentation/images/hand-freq-json-ss.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JavaFXpert/card-deck-demo/eefe994dadd4af117fe406256a7495ea6da0de12/reactive-card-magic-presentation/images/hand-freq-json-ss.png -------------------------------------------------------------------------------- /reactive-card-magic-presentation/images/heart.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JavaFXpert/card-deck-demo/eefe994dadd4af117fe406256a7495ea6da0de12/reactive-card-magic-presentation/images/heart.png -------------------------------------------------------------------------------- /reactive-card-magic-presentation/images/logos/pivotal-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JavaFXpert/card-deck-demo/eefe994dadd4af117fe406256a7495ea6da0de12/reactive-card-magic-presentation/images/logos/pivotal-logo.png -------------------------------------------------------------------------------- /reactive-card-magic-presentation/images/marble-diagrams/flux/collectlist.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JavaFXpert/card-deck-demo/eefe994dadd4af117fe406256a7495ea6da0de12/reactive-card-magic-presentation/images/marble-diagrams/flux/collectlist.png -------------------------------------------------------------------------------- /reactive-card-magic-presentation/images/marble-diagrams/flux/filter.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JavaFXpert/card-deck-demo/eefe994dadd4af117fe406256a7495ea6da0de12/reactive-card-magic-presentation/images/marble-diagrams/flux/filter.png -------------------------------------------------------------------------------- /reactive-card-magic-presentation/images/marble-diagrams/flux/flux-marble-diagram.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JavaFXpert/card-deck-demo/eefe994dadd4af117fe406256a7495ea6da0de12/reactive-card-magic-presentation/images/marble-diagrams/flux/flux-marble-diagram.png -------------------------------------------------------------------------------- /reactive-card-magic-presentation/images/marble-diagrams/flux/index.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JavaFXpert/card-deck-demo/eefe994dadd4af117fe406256a7495ea6da0de12/reactive-card-magic-presentation/images/marble-diagrams/flux/index.png -------------------------------------------------------------------------------- /reactive-card-magic-presentation/images/marble-diagrams/flux/sort.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JavaFXpert/card-deck-demo/eefe994dadd4af117fe406256a7495ea6da0de12/reactive-card-magic-presentation/images/marble-diagrams/flux/sort.png -------------------------------------------------------------------------------- /reactive-card-magic-presentation/images/marble-diagrams/flux/sort.pxm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JavaFXpert/card-deck-demo/eefe994dadd4af117fe406256a7495ea6da0de12/reactive-card-magic-presentation/images/marble-diagrams/flux/sort.pxm -------------------------------------------------------------------------------- /reactive-card-magic-presentation/images/marble-diagrams/flux/take.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JavaFXpert/card-deck-demo/eefe994dadd4af117fe406256a7495ea6da0de12/reactive-card-magic-presentation/images/marble-diagrams/flux/take.png -------------------------------------------------------------------------------- /reactive-card-magic-presentation/images/marble-diagrams/mono/map1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JavaFXpert/card-deck-demo/eefe994dadd4af117fe406256a7495ea6da0de12/reactive-card-magic-presentation/images/marble-diagrams/mono/map1.png -------------------------------------------------------------------------------- /reactive-card-magic-presentation/images/marble-diagrams/mono/mono-marble-diagram.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JavaFXpert/card-deck-demo/eefe994dadd4af117fe406256a7495ea6da0de12/reactive-card-magic-presentation/images/marble-diagrams/mono/mono-marble-diagram.png -------------------------------------------------------------------------------- /reactive-card-magic-presentation/images/rcm-app-shots/rcm-app-deal-poker.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JavaFXpert/card-deck-demo/eefe994dadd4af117fe406256a7495ea6da0de12/reactive-card-magic-presentation/images/rcm-app-shots/rcm-app-deal-poker.png -------------------------------------------------------------------------------- /reactive-card-magic-presentation/images/rcm-app-shots/rcm-app-new-deck.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JavaFXpert/card-deck-demo/eefe994dadd4af117fe406256a7495ea6da0de12/reactive-card-magic-presentation/images/rcm-app-shots/rcm-app-new-deck.png -------------------------------------------------------------------------------- /reactive-card-magic-presentation/images/rcm-app-shots/rcm-app-only-hearts.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JavaFXpert/card-deck-demo/eefe994dadd4af117fe406256a7495ea6da0de12/reactive-card-magic-presentation/images/rcm-app-shots/rcm-app-only-hearts.png -------------------------------------------------------------------------------- /reactive-card-magic-presentation/images/rcm-app-shots/rcm-app-three-kind.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JavaFXpert/card-deck-demo/eefe994dadd4af117fe406256a7495ea6da0de12/reactive-card-magic-presentation/images/rcm-app-shots/rcm-app-three-kind.png -------------------------------------------------------------------------------- /reactive-card-magic-presentation/images/rcm-app-shots/rcm-app-two-pairs.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JavaFXpert/card-deck-demo/eefe994dadd4af117fe406256a7495ea6da0de12/reactive-card-magic-presentation/images/rcm-app-shots/rcm-app-two-pairs.png -------------------------------------------------------------------------------- /reactive-card-magic-presentation/images/spring-mvc-and-webflux-venn.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JavaFXpert/card-deck-demo/eefe994dadd4af117fe406256a7495ea6da0de12/reactive-card-magic-presentation/images/spring-mvc-and-webflux-venn.png -------------------------------------------------------------------------------- /reactive-card-magic-presentation/images/tuples-screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JavaFXpert/card-deck-demo/eefe994dadd4af117fe406256a7495ea6da0de12/reactive-card-magic-presentation/images/tuples-screenshot.png -------------------------------------------------------------------------------- /reactive-card-magic-presentation/images/z-ORIG-blank-card.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JavaFXpert/card-deck-demo/eefe994dadd4af117fe406256a7495ea6da0de12/reactive-card-magic-presentation/images/z-ORIG-blank-card.png -------------------------------------------------------------------------------- /reactive-card-magic-presentation/reactive-card-magic.key: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JavaFXpert/card-deck-demo/eefe994dadd4af117fe406256a7495ea6da0de12/reactive-card-magic-presentation/reactive-card-magic.key -------------------------------------------------------------------------------- /reactive-card-magic-presentation/reactive-card-magic.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JavaFXpert/card-deck-demo/eefe994dadd4af117fe406256a7495ea6da0de12/reactive-card-magic-presentation/reactive-card-magic.pdf -------------------------------------------------------------------------------- /src/main/java/com/javafxpert/carddeckdemo/CardDeckDemoApplication.java: -------------------------------------------------------------------------------- 1 | package com.javafxpert.carddeckdemo; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | @SpringBootApplication 7 | public class CardDeckDemoApplication { 8 | 9 | public static void main(String[] args) { 10 | SpringApplication.run(CardDeckDemoApplication.class, args); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/main/java/com/javafxpert/carddeckdemo/deck/configuration/CardDeckImagesServerProperties.java: -------------------------------------------------------------------------------- 1 | package com.javafxpert.carddeckdemo.deck.configuration; 2 | 3 | import java.net.URI; 4 | 5 | import org.springframework.boot.context.properties.ConfigurationProperties; 6 | import org.springframework.stereotype.Component; 7 | import org.springframework.web.util.UriComponentsBuilder; 8 | 9 | @Component 10 | @ConfigurationProperties("card.deck.images.server") 11 | public class CardDeckImagesServerProperties { 12 | 13 | private String host; 14 | private String port; 15 | 16 | public String getHost() { 17 | return host; 18 | } 19 | 20 | public void setHost(String host) { 21 | this.host = host; 22 | } 23 | 24 | public String getPort() { 25 | return port; 26 | } 27 | 28 | public void setPort(String port) { 29 | this.port = port; 30 | } 31 | 32 | public String getBaseURI() { 33 | return UriComponentsBuilder.fromHttpUrl(host) 34 | .port(port) 35 | .build() 36 | .toUriString(); 37 | 38 | } 39 | 40 | public String getURI(String pathSegment) { 41 | return UriComponentsBuilder.fromHttpUrl(host) 42 | .port(port) 43 | .pathSegment(pathSegment) 44 | .build() 45 | .toUriString(); 46 | 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/main/java/com/javafxpert/carddeckdemo/deck/configuration/DataLoaderCardDeck.java: -------------------------------------------------------------------------------- 1 | package com.javafxpert.carddeckdemo.deck.configuration; 2 | 3 | import com.javafxpert.carddeckdemo.deck.domain.Card; 4 | import com.javafxpert.carddeckdemo.deck.repository.CardDeckRepository; 5 | import reactor.core.publisher.Flux; 6 | 7 | import org.springframework.boot.CommandLineRunner; 8 | import org.springframework.context.annotation.Bean; 9 | import org.springframework.context.annotation.Configuration; 10 | 11 | @Configuration 12 | public class DataLoaderCardDeck { 13 | 14 | @Bean 15 | public CommandLineRunner cardDeckDataLoaderCommandLineRunner( 16 | CardDeckRepository cardDeckRepository, 17 | CardDeckImagesServerProperties cardDeckImagesServerProperties) { 18 | String imagesUri = cardDeckImagesServerProperties.getURI("/images"); 19 | 20 | return (args) -> cardDeckRepository.deleteAll() 21 | .thenMany(Flux.just( 22 | new Card("AS", imagesUri), 23 | new Card("2S", imagesUri), 24 | new Card("3S", imagesUri), 25 | new Card("4S", imagesUri), 26 | new Card("5S", imagesUri), 27 | new Card("6S", imagesUri), 28 | new Card("7S", imagesUri), 29 | new Card("8S", imagesUri), 30 | new Card("9S", imagesUri), 31 | new Card("0S", imagesUri), 32 | new Card("JS", imagesUri), 33 | new Card("QS", imagesUri), 34 | new Card("KS", imagesUri), 35 | 36 | new Card("AD", imagesUri), 37 | new Card("2D", imagesUri), 38 | new Card("3D", imagesUri), 39 | new Card("4D", imagesUri), 40 | new Card("5D", imagesUri), 41 | new Card("6D", imagesUri), 42 | new Card("7D", imagesUri), 43 | new Card("8D", imagesUri), 44 | new Card("9D", imagesUri), 45 | new Card("0D", imagesUri), 46 | new Card("JD", imagesUri), 47 | new Card("QD", imagesUri), 48 | new Card("KD", imagesUri), 49 | 50 | new Card("AC", imagesUri), 51 | new Card("2C", imagesUri), 52 | new Card("3C", imagesUri), 53 | new Card("4C", imagesUri), 54 | new Card("5C", imagesUri), 55 | new Card("6C", imagesUri), 56 | new Card("7C", imagesUri), 57 | new Card("8C", imagesUri), 58 | new Card("9C", imagesUri), 59 | new Card("0C", imagesUri), 60 | new Card("JC", imagesUri), 61 | new Card("QC", imagesUri), 62 | new Card("KC", imagesUri), 63 | 64 | new Card("AH", imagesUri), 65 | new Card("2H", imagesUri), 66 | new Card("3H", imagesUri), 67 | new Card("4H", imagesUri), 68 | new Card("5H", imagesUri), 69 | new Card("6H", imagesUri), 70 | new Card("7H", imagesUri), 71 | new Card("8H", imagesUri), 72 | new Card("9H", imagesUri), 73 | new Card("0H", imagesUri), 74 | new Card("JH", imagesUri), 75 | new Card("QH", imagesUri), 76 | new Card("KH", imagesUri) 77 | )) 78 | .transform(cardDeckRepository::saveAll) 79 | .subscribe(System.out::println); 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /src/main/java/com/javafxpert/carddeckdemo/deck/configuration/PokerServerProperties.java: -------------------------------------------------------------------------------- 1 | package com.javafxpert.carddeckdemo.deck.configuration; 2 | 3 | import org.springframework.boot.context.properties.ConfigurationProperties; 4 | import org.springframework.stereotype.Component; 5 | import org.springframework.web.util.UriComponentsBuilder; 6 | 7 | @Component 8 | @ConfigurationProperties("poker.server") 9 | public class PokerServerProperties { 10 | 11 | private String host; 12 | private String port; 13 | 14 | public String getHost() { 15 | return host; 16 | } 17 | 18 | public void setHost(String host) { 19 | this.host = host; 20 | } 21 | 22 | public String getPort() { 23 | return port; 24 | } 25 | 26 | public void setPort(String port) { 27 | this.port = port; 28 | } 29 | 30 | public String getBaseURI() { 31 | return UriComponentsBuilder.fromHttpUrl(host) 32 | .port(port) 33 | .build() 34 | .toUriString(); 35 | 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/main/java/com/javafxpert/carddeckdemo/deck/controller/CardDeckController.java: -------------------------------------------------------------------------------- 1 | package com.javafxpert.carddeckdemo.deck.controller; 2 | 3 | import java.util.Comparator; 4 | import java.util.Optional; 5 | 6 | import com.javafxpert.carddeckdemo.deck.domain.CardHand; 7 | import com.javafxpert.carddeckdemo.deck.service.CardDeckService; 8 | import com.javafxpert.carddeckdemo.deck.service.CardShufflingService; 9 | import com.javafxpert.carddeckdemo.deck.service.PokerService; 10 | import org.springframework.context.annotation.Bean; 11 | import org.springframework.web.reactive.function.server.RequestPredicates; 12 | import org.springframework.web.reactive.function.server.RouterFunction; 13 | import org.springframework.web.reactive.function.server.RouterFunctions; 14 | import org.springframework.web.reactive.function.server.ServerResponse; 15 | import reactor.core.publisher.Flux; 16 | import reactor.core.publisher.Mono; 17 | import reactor.core.scheduler.Schedulers; 18 | import reactor.util.function.Tuple2; 19 | import reactor.util.function.Tuple3; 20 | import reactor.util.function.Tuples; 21 | 22 | import org.springframework.beans.factory.annotation.Autowired; 23 | import org.springframework.web.bind.annotation.GetMapping; 24 | import org.springframework.web.bind.annotation.PathVariable; 25 | import org.springframework.web.bind.annotation.RequestMapping; 26 | import org.springframework.web.bind.annotation.RequestParam; 27 | import org.springframework.web.bind.annotation.RestController; 28 | 29 | @RestController 30 | @RequestMapping("/cards/deck") 31 | public class CardDeckController { 32 | private final CardDeckService cardDeckService; 33 | private final PokerService pokerService; 34 | private final CardShufflingService cardShufflingService; 35 | 36 | @Autowired 37 | public CardDeckController( 38 | CardDeckService cardDeckService, 39 | PokerService pokerService, 40 | CardShufflingService cardShufflingService) { 41 | this.cardDeckService = cardDeckService; 42 | this.pokerService = pokerService; 43 | this.cardShufflingService = cardShufflingService; 44 | } 45 | 46 | @GetMapping("/new") 47 | public Mono getCardDeck(@RequestParam(defaultValue = "52") 48 | int numcards) { 49 | return cardDeckService.generate() 50 | .take(numcards) 51 | .collectList() 52 | .map(l -> new CardHand(l, "New Deck")); 53 | } 54 | 55 | @Bean 56 | RouterFunction newDeckRoutes(CardDeckService cds) { 57 | int defaultNumCards = 52; 58 | return RouterFunctions.route( 59 | RequestPredicates.GET("/newdeck"), 60 | request -> cds.generate() 61 | .take(request.queryParam("numcards") 62 | .map(Integer::parseInt).orElse(defaultNumCards)) 63 | .collectList() 64 | .map(l -> new CardHand(l,"New Deck")) 65 | .flatMap(ServerResponse.ok()::syncBody)); 66 | } 67 | 68 | @GetMapping("/{suit}") 69 | public Mono getCardDeckBySuit( 70 | @PathVariable String suit, 71 | @RequestParam(defaultValue = "10") int numcards 72 | ) { 73 | return cardDeckService.generate() 74 | .filter(card -> card.getSuit() 75 | .equalsIgnoreCase(suit)) 76 | .take(numcards) 77 | .collectList() 78 | .map(l -> new CardHand(l, "Only " + suit)); 79 | } 80 | 81 | @GetMapping("/cut") 82 | public Mono getCardDeckCut(@RequestParam(defaultValue = "") String cards) { 83 | return Mono.just(cards) 84 | .as(cardDeckService::parseString) 85 | .transform(cardShufflingService::cutCards) 86 | .collectList() 87 | .map(l -> new CardHand(l, "Cut Cards")); 88 | } 89 | 90 | @GetMapping("/overhandshuffle") 91 | public Mono getCardDeckOverhandShuffle(@RequestParam(defaultValue = "") String cards) { 92 | return Mono.just(cards) 93 | .as(cardDeckService::parseString) 94 | .transform(cardShufflingService::overhandShuffle) 95 | .collectList() 96 | .map(l -> new CardHand(l, "Overhand Shuffle")); 97 | } 98 | 99 | @GetMapping("/riffleshuffle") 100 | public Mono getCardDeckRiffleShuffle(@RequestParam(defaultValue = "") String cards) { 101 | return Mono.just(cards) 102 | .as(cardDeckService::parseString) 103 | .transform(cardShufflingService::riffleShuffle) 104 | .collectList() 105 | .map(l -> new CardHand(l, "Riffle Shuffle")); 106 | } 107 | 108 | @GetMapping("/randomshuffle") 109 | public Mono getCardDeckRandomShuffle(@RequestParam(defaultValue = "") String cards) { 110 | return Mono.just(cards) 111 | .as(cardDeckService::parseString) 112 | .transform(cardShufflingService::randomShuffle) 113 | .collectList() 114 | .map(l -> new CardHand(l, "Random Shuffle")); 115 | } 116 | 117 | @GetMapping("/dealpokerhand") 118 | public Mono getCardDeckDealPokerHand(@RequestParam (defaultValue = "") String cards) { 119 | return Mono.just(cards) 120 | .as(cardDeckService::parseString) 121 | .transform(cardShufflingService::dealPokerHand) 122 | .collectList() 123 | .flatMap(l -> pokerService.handNameFromDeck(Flux.fromIterable(l)) 124 | .map(handName -> new CardHand(l, handName))); 125 | 126 | } 127 | 128 | @GetMapping("/shuffledeal") 129 | public Mono getCardDeckShuffleDeal(@RequestParam (defaultValue = "") String cards) { 130 | return Mono.just(cards) 131 | .as(cardDeckService::parseString) 132 | .transform(cardShufflingService::shuffleWell) 133 | .transform(cardShufflingService::dealPokerHand) 134 | .collectList() 135 | .flatMap(l -> pokerService.handNameFromDeck(Flux.fromIterable(l)) 136 | .map(handName -> new CardHand(l, handName))); 137 | } 138 | 139 | @GetMapping("/shuffledealrepeat") 140 | public Flux> shuffleDealRepeatCollectStats(@RequestParam (defaultValue = "10") int numtimes) { 141 | Comparator> t3Comparator = Comparator.comparingLong(Tuple2::getT2); 142 | return Flux 143 | .range(0, numtimes) 144 | .flatMap(i -> 145 | Flux.defer(cardDeckService::generate) 146 | .compose(cardShufflingService::shuffleWell) 147 | .compose(cardShufflingService::dealPokerHand) 148 | .subscribeOn(Schedulers.parallel()) 149 | .collectList() 150 | .flatMap(l -> pokerService.handNameFromDeck(Flux.fromIterable(l)) 151 | .map(handName -> new CardHand(l, handName))) 152 | ) 153 | .groupBy(CardHand::getName) 154 | .flatMap(gf -> gf.count().map(c -> Tuples.of(gf.key(), c, Math.round(c * 10000.0 / numtimes) / 100.0))) 155 | .sort(t3Comparator); 156 | } 157 | } 158 | -------------------------------------------------------------------------------- /src/main/java/com/javafxpert/carddeckdemo/deck/domain/Card.java: -------------------------------------------------------------------------------- 1 | /* 2 | Card images from http://acbl.mybigcommerce.com/52-playing-cards/ 3 | Card data model inspired by Chase Robert's elegant Deck of Cards API https://deckofcardsapi.com/ 4 | */ 5 | package com.javafxpert.carddeckdemo.deck.domain; 6 | 7 | import org.springframework.data.annotation.Id; 8 | import org.springframework.data.mongodb.core.mapping.Document; 9 | 10 | import java.util.Objects; 11 | 12 | import com.fasterxml.jackson.annotation.JsonCreator; 13 | import com.fasterxml.jackson.annotation.JsonIgnoreProperties; 14 | import com.fasterxml.jackson.annotation.JsonProperty; 15 | 16 | @Document 17 | @JsonIgnoreProperties(ignoreUnknown = true) 18 | public class Card implements Comparable { 19 | @Id 20 | private String id; 21 | private String code; 22 | private String value; 23 | private String suit; 24 | private String image; 25 | private int worth; 26 | private int seq; 27 | private String imagesUri; 28 | 29 | @JsonCreator 30 | public Card(@JsonProperty("code") String code, 31 | @JsonProperty("image") String imagesUri) { 32 | this.code = code; 33 | String valueCode = code.substring(0,1); 34 | switch (valueCode) { 35 | case "A": 36 | value = "ACE"; 37 | worth = 0; 38 | break; 39 | case "2": 40 | value = "2"; 41 | worth = 1; 42 | break; 43 | case "3": 44 | value = "3"; 45 | worth = 2; 46 | break; 47 | case "4": 48 | value = "4"; 49 | worth = 3; 50 | break; 51 | case "5": 52 | value = "5"; 53 | worth = 4; 54 | break; 55 | case "6": 56 | value = "6"; 57 | worth = 5; 58 | break; 59 | case "7": 60 | value = "7"; 61 | worth = 6; 62 | break; 63 | case "8": 64 | value = "8"; 65 | worth = 7; 66 | break; 67 | case "9": 68 | value = "9"; 69 | worth = 8; 70 | break; 71 | case "0": 72 | value = "10"; 73 | worth = 9; 74 | break; 75 | case "J": 76 | value = "JACK"; 77 | worth = 10; 78 | break; 79 | case "Q": 80 | value = "QUEEN"; 81 | worth = 11; 82 | break; 83 | case "K": 84 | value = "KING"; 85 | worth = 12; 86 | } 87 | 88 | String suitCode = code.substring(1,2); 89 | switch (suitCode) { 90 | case "C": 91 | suit = "CLUBS"; 92 | seq = worth + (13 * ((12 - worth + 0) % 4)); 93 | break; 94 | case "H": 95 | suit = "HEARTS"; 96 | seq = worth + (13 * ((12 - worth + 1) % 4)); 97 | break; 98 | case "S": 99 | suit = "SPADES"; 100 | seq = worth + (13 * ((12 - worth + 2) % 4)); 101 | break; 102 | case "D": 103 | suit = "DIAMONDS"; 104 | seq = worth + (13 * ((12 - worth + 3) % 4)); 105 | } 106 | 107 | image = imagesUri + "/" + code + ".png"; 108 | } 109 | 110 | public String getId() { 111 | return id; 112 | } 113 | 114 | public void setId(String id) { 115 | this.id = id; 116 | } 117 | 118 | public String getCode() { 119 | return code; 120 | } 121 | 122 | public String getValue() { 123 | return value; 124 | } 125 | 126 | public String getSuit() { 127 | return suit; 128 | } 129 | 130 | public String getImage() { 131 | return image; 132 | } 133 | 134 | public int getWorth() { 135 | return worth; 136 | } 137 | 138 | public int getSeq() { 139 | return seq; 140 | } 141 | 142 | public String getImagesUri() { 143 | return imagesUri; 144 | } 145 | 146 | @Override 147 | public int compareTo(Object o) { 148 | return ((Card)o).getWorth(); 149 | } 150 | 151 | @Override 152 | public boolean equals(Object o) { 153 | if (this == o) return true; 154 | if (o == null || getClass() != o.getClass()) return false; 155 | Card card = (Card) o; 156 | return worth == card.worth && 157 | seq == card.seq && 158 | Objects.equals(id, card.id) && 159 | Objects.equals(code, card.code) && 160 | Objects.equals(value, card.value) && 161 | Objects.equals(suit, card.suit) && 162 | Objects.equals(image, card.image) && 163 | Objects.equals(imagesUri, card.imagesUri); 164 | } 165 | 166 | @Override 167 | public int hashCode() { 168 | 169 | return Objects.hash(id, code, value, suit, image, worth, seq, imagesUri); 170 | } 171 | 172 | @Override 173 | public String toString() { 174 | return "Card{" + 175 | "id='" + id + '\'' + 176 | ", code='" + code + '\'' + 177 | ", value='" + value + '\'' + 178 | ", suit='" + suit + '\'' + 179 | ", image='" + image + '\'' + 180 | ", worth=" + worth + 181 | ", seq=" + seq + 182 | ", imagesUri='" + imagesUri + '\'' + 183 | '}'; 184 | } 185 | } 186 | -------------------------------------------------------------------------------- /src/main/java/com/javafxpert/carddeckdemo/deck/domain/CardHand.java: -------------------------------------------------------------------------------- 1 | package com.javafxpert.carddeckdemo.deck.domain; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | import com.fasterxml.jackson.annotation.JsonCreator; 7 | import com.javafxpert.carddeckdemo.deck.domain.Card; 8 | 9 | public class CardHand { 10 | 11 | private final List cards; 12 | private final String name; 13 | 14 | @JsonCreator 15 | public CardHand(List cards, String name) { 16 | this.cards = new ArrayList<>(cards); 17 | this.name = name; 18 | } 19 | 20 | public List getCards() { 21 | return cards; 22 | } 23 | 24 | public String getName() { 25 | return name; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/main/java/com/javafxpert/carddeckdemo/deck/repository/CardDeckRepository.java: -------------------------------------------------------------------------------- 1 | package com.javafxpert.carddeckdemo.deck.repository; 2 | 3 | import com.javafxpert.carddeckdemo.deck.domain.Card; 4 | 5 | import org.springframework.data.mongodb.repository.ReactiveMongoRepository; 6 | 7 | public interface CardDeckRepository extends ReactiveMongoRepository { 8 | } 9 | -------------------------------------------------------------------------------- /src/main/java/com/javafxpert/carddeckdemo/deck/service/CardDeckService.java: -------------------------------------------------------------------------------- 1 | package com.javafxpert.carddeckdemo.deck.service; 2 | 3 | import com.javafxpert.carddeckdemo.deck.domain.Card; 4 | import reactor.core.publisher.Flux; 5 | import reactor.core.publisher.Mono; 6 | 7 | public interface CardDeckService { 8 | 9 | Flux generate(); 10 | 11 | Flux parseString(Mono deck); 12 | } 13 | -------------------------------------------------------------------------------- /src/main/java/com/javafxpert/carddeckdemo/deck/service/CardShufflingService.java: -------------------------------------------------------------------------------- 1 | package com.javafxpert.carddeckdemo.deck.service; 2 | 3 | import com.javafxpert.carddeckdemo.deck.domain.Card; 4 | import reactor.core.publisher.Flux; 5 | 6 | public interface CardShufflingService { 7 | 8 | Flux cutCards(Flux cardFlux); 9 | 10 | Flux overhandShuffle(Flux cardFlux); 11 | 12 | Flux riffleShuffle(Flux cardFlux); 13 | 14 | Flux dealPokerHand(Flux cardFlux); 15 | 16 | Flux shuffleWell(Flux cardFlux); 17 | 18 | Flux randomShuffle(Flux cardFlux); 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/com/javafxpert/carddeckdemo/deck/service/PokerService.java: -------------------------------------------------------------------------------- 1 | package com.javafxpert.carddeckdemo.deck.service; 2 | 3 | import com.javafxpert.carddeckdemo.deck.domain.Card; 4 | import reactor.core.publisher.Flux; 5 | import reactor.core.publisher.Mono; 6 | 7 | public interface PokerService { 8 | 9 | Mono handNameFromDeck(Flux cardFlux); 10 | } 11 | -------------------------------------------------------------------------------- /src/main/java/com/javafxpert/carddeckdemo/deck/service/impl/DefaultCardDeckService.java: -------------------------------------------------------------------------------- 1 | package com.javafxpert.carddeckdemo.deck.service.impl; 2 | 3 | import org.springframework.stereotype.Service; 4 | 5 | import com.javafxpert.carddeckdemo.deck.configuration.CardDeckImagesServerProperties; 6 | import com.javafxpert.carddeckdemo.deck.domain.Card; 7 | import com.javafxpert.carddeckdemo.deck.repository.CardDeckRepository; 8 | import com.javafxpert.carddeckdemo.deck.service.CardDeckService; 9 | import reactor.core.publisher.Flux; 10 | import reactor.core.publisher.Mono; 11 | 12 | import java.util.Comparator; 13 | import java.util.stream.Collectors; 14 | 15 | @Service 16 | public class DefaultCardDeckService implements CardDeckService { 17 | 18 | private static final String DELIMITER = ","; 19 | private static final Comparator seqComparator = Comparator.comparing(Card::getId); 20 | 21 | private final CardDeckRepository cardDeckRepository; 22 | private final String imagesUri; 23 | 24 | 25 | public DefaultCardDeckService(CardDeckImagesServerProperties cardDeckImagesServerProperties, 26 | CardDeckRepository cardDeckRepository) { 27 | this.cardDeckRepository = cardDeckRepository; 28 | this.imagesUri = cardDeckImagesServerProperties.getURI("/images"); 29 | } 30 | 31 | @Override 32 | public Flux parseString(Mono deck) { 33 | return deck 34 | .map(c -> c.replaceAll(" ", "")) 35 | .filter(c -> c.length() >= 29) 36 | .as(this::createFluxFromCardsString) 37 | .switchIfEmpty(Flux.defer(this::generate)); 38 | } 39 | 40 | @Override 41 | public Flux generate() { 42 | return cardDeckRepository.findAll().sort(seqComparator); 43 | } 44 | 45 | private Flux createFluxFromCardsString(Mono cardStr) { 46 | return cardStr.flatMapMany(cs -> Flux.fromArray(cs.split(DELIMITER))) 47 | .map(code -> new Card(code, imagesUri)); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/main/java/com/javafxpert/carddeckdemo/deck/service/impl/DefaultCardShufflingService.java: -------------------------------------------------------------------------------- 1 | package com.javafxpert.carddeckdemo.deck.service.impl; 2 | 3 | import com.javafxpert.carddeckdemo.deck.domain.Card; 4 | import com.javafxpert.carddeckdemo.deck.service.CardShufflingService; 5 | import reactor.core.publisher.Flux; 6 | import reactor.util.function.Tuple2; 7 | import reactor.util.function.Tuples; 8 | 9 | import java.util.ArrayList; 10 | import java.util.Collections; 11 | import java.util.Comparator; 12 | import java.util.List; 13 | 14 | import org.springframework.stereotype.Service; 15 | 16 | import static java.lang.Math.*; 17 | 18 | @Service 19 | public class DefaultCardShufflingService implements CardShufflingService { 20 | private static final Comparator worthComparator = Comparator.comparingInt(Card::getWorth); 21 | 22 | @Override 23 | public Flux cutCards(Flux cardFlux) { 24 | return cardFlux.collectList() 25 | .map(list -> Tuples.of(Flux.fromIterable(list), (int)(random() * (list.size() - 1) + 1))) 26 | .flatMapMany(tuple2 -> 27 | tuple2.getT1() 28 | .skip(tuple2.getT2()) 29 | .concatWith(tuple2.getT1().take(tuple2.getT2())) 30 | ); 31 | } 32 | 33 | @Override 34 | public Flux overhandShuffle(Flux cardFlux) { 35 | return cardFlux.collectList() 36 | .flatMapIterable(l -> { 37 | int maxChunk = 5; 38 | int numCardsLeft = l.size(); 39 | List cardList = new ArrayList<>(); 40 | 41 | while (numCardsLeft > 0) { 42 | List tempCardFlux = l.subList(0, numCardsLeft); 43 | int numCardsToTransfer = min((int) (random() * maxChunk + 1), 44 | numCardsLeft); 45 | cardList.addAll( 46 | tempCardFlux.subList(tempCardFlux.size() - numCardsToTransfer, tempCardFlux.size()) 47 | ); 48 | 49 | numCardsLeft -= numCardsToTransfer; 50 | } 51 | return cardList; 52 | }); 53 | } 54 | 55 | /** 56 | * 57 | * Note: The floor() and ceil() methods are used to accommodate and odd number of cards 58 | */ 59 | @Override 60 | public Flux riffleShuffle(Flux cardFlux) { 61 | return cardFlux.collectList() 62 | .flatMapMany(l -> Flux.zip( 63 | Flux.fromStream(l.stream().limit((long) (ceil(l.size() / 2.0)))), 64 | Flux.fromStream(l.stream().skip((long) (floor(l.size() / 2.0)))) 65 | )) 66 | .flatMap(tuple2 -> Flux.just(tuple2.getT1(), tuple2.getT2())) 67 | .distinct(); 68 | } 69 | 70 | @Override 71 | public Flux dealPokerHand(Flux cardFlux) { 72 | return cardFlux.index() 73 | .take(9) 74 | .filter(t -> t.getT1() % 2 == 0) 75 | .map(Tuple2::getT2) 76 | .sort(worthComparator); 77 | } 78 | 79 | @Override 80 | public Flux shuffleWell(Flux cardFlux) { 81 | return cardFlux.transform(this::overhandShuffle) 82 | .transform(this::riffleShuffle) 83 | .transform(this::overhandShuffle) 84 | .transform(this::riffleShuffle) 85 | .transform(this::overhandShuffle) 86 | .transform(this::riffleShuffle) 87 | .transform(this::overhandShuffle) 88 | .transform(this::riffleShuffle) 89 | .transform(this::overhandShuffle) 90 | .transform(this::overhandShuffle) 91 | .transform(this::cutCards); 92 | } 93 | 94 | @Override 95 | public Flux randomShuffle(Flux cardFlux) { 96 | return cardFlux.collectList() 97 | .flatMapIterable(l -> { 98 | List cardList = new ArrayList<>(l); 99 | Collections.shuffle(cardList); 100 | return cardList; 101 | }); 102 | } 103 | 104 | } 105 | -------------------------------------------------------------------------------- /src/main/java/com/javafxpert/carddeckdemo/deck/service/impl/ProxyPokerService.java: -------------------------------------------------------------------------------- 1 | package com.javafxpert.carddeckdemo.deck.service.impl; 2 | 3 | import com.javafxpert.carddeckdemo.deck.configuration.PokerServerProperties; 4 | import com.javafxpert.carddeckdemo.deck.domain.Card; 5 | import com.javafxpert.carddeckdemo.deck.service.PokerService; 6 | import reactor.core.publisher.Flux; 7 | import reactor.core.publisher.Mono; 8 | 9 | import org.springframework.stereotype.Service; 10 | import org.springframework.web.reactive.function.client.WebClient; 11 | 12 | @Service 13 | public class ProxyPokerService implements PokerService { 14 | private final WebClient pokerWebClient; 15 | 16 | public ProxyPokerService( 17 | PokerServerProperties properties, 18 | WebClient.Builder clientBuilder) { 19 | this.pokerWebClient = clientBuilder.baseUrl(properties.getBaseURI()) 20 | .build(); 21 | } 22 | 23 | @Override 24 | public Mono handNameFromDeck(Flux cardFlux) { 25 | return pokerWebClient.post() 26 | .uri("/poker/idhand") 27 | .body(cardFlux, Card.class) 28 | .retrieve() 29 | .bodyToMono(String.class); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/main/java/com/javafxpert/carddeckdemo/poker/Cards.java: -------------------------------------------------------------------------------- 1 | package com.javafxpert.carddeckdemo.poker; 2 | 3 | import java.util.*; 4 | 5 | /** 6 | * Cards class for playing cards. Uses simple integer-based system 7 | * where the card face value is n mod 13 and the suit is n mod 4 8 | * @author /u/Philboyd_Studge on 3/26/2016. 9 | */ 10 | public class Cards { 11 | private static final int DECK_SIZE = 52; 12 | private static final int FACES = 13; 13 | private static final String[] FACE_NAMES = { "Ace", "Two", "Three", "Four", 14 | "Five", "Six", "Seven", "Eight", 15 | "Nine", "Ten", "Jack", "Queen", "King"}; 16 | private static final String[] SUIT_NAMES = { "Clubs", "Hearts", "Spades", "Diamonds"}; 17 | 18 | Random rand = new Random(); 19 | 20 | private int[] deck; // deck itself 21 | private int pointer; // current position in deck 22 | 23 | 24 | /** 25 | * Constructor 26 | */ 27 | public Cards() { 28 | deck = new int[DECK_SIZE]; 29 | 30 | // initialize deck to values 0 - 51 31 | for (int i = 0; i < DECK_SIZE; i++) { 32 | deck[i] = i; 33 | } 34 | } 35 | 36 | /** 37 | * Get card integer value at position n 38 | * @param n position in deck 39 | * @return integer card value 40 | */ 41 | public int getCard(int n) { 42 | return deck[n]; 43 | } 44 | 45 | /** 46 | * Fisher-yates shuffle 47 | */ 48 | public void shuffle() { 49 | pointer = 0; 50 | for (int i = DECK_SIZE - 1; i > 0; i--) { 51 | int j = rand.nextInt(i); 52 | if (j != i) { 53 | swap(j, i); 54 | } 55 | } 56 | } 57 | 58 | private void swap(int first, int second) { 59 | int temp = deck[first]; 60 | deck[first] = deck[second]; 61 | deck[second] = temp; 62 | } 63 | 64 | /** 65 | * Get face value 0 - 12 for card 66 | * note: off by one compared to actual card face 67 | * @param card integer value of card 68 | * @return face value 69 | */ 70 | public static int getFaceValue(int card) { 71 | return card % FACES; 72 | } 73 | 74 | /** 75 | * Get suit 0 - 3 for card 76 | * '& 3' a bitwise way of saying '% 4' 77 | * @param card integer value of card 78 | * @return suit 79 | */ 80 | public static int getSuit(int card) { 81 | return card & 3; 82 | } 83 | 84 | /** 85 | * Get string representation of card 86 | * @param card integer value of card 87 | * @return string of card name 88 | */ 89 | public static String getCardName(int card) { 90 | return FACE_NAMES[getFaceValue(card)] + " of " + SUIT_NAMES[getSuit(card)]; 91 | } 92 | 93 | /** 94 | * Deal n cards from the deck 95 | * re-shuffles if not enough cards left for a full hand 96 | * @param n number of cards to deal 97 | * @return Linked list of integers representing the hand 98 | */ 99 | public List deal(int n) { 100 | if (n < 1) return null; 101 | 102 | // don't reshuffle in the middle of a hand 103 | if (DECK_SIZE - pointer < n) shuffle(); 104 | 105 | 106 | List hand = new LinkedList<>(); 107 | for (int i = 0; i < n; i++) { 108 | hand.add(dealCard()); 109 | } 110 | return hand; 111 | } 112 | 113 | /** 114 | * deal single card and increment pointer 115 | * @return 116 | */ 117 | private int dealCard() { 118 | return deck[pointer++]; 119 | } 120 | 121 | 122 | } 123 | -------------------------------------------------------------------------------- /src/main/java/com/javafxpert/carddeckdemo/poker/configuration/DataLoaderHandFrequencies.java: -------------------------------------------------------------------------------- 1 | package com.javafxpert.carddeckdemo.poker.configuration; 2 | 3 | import org.springframework.boot.CommandLineRunner; 4 | import org.springframework.context.annotation.Bean; 5 | import org.springframework.context.annotation.Configuration; 6 | 7 | import com.javafxpert.carddeckdemo.poker.domain.HandFrequency; 8 | import com.javafxpert.carddeckdemo.poker.domain.PokerHand; 9 | import com.javafxpert.carddeckdemo.poker.repository.HandFrequencyRepository; 10 | import reactor.core.publisher.Flux; 11 | 12 | @Configuration 13 | public class DataLoaderHandFrequencies { 14 | 15 | @Bean 16 | public CommandLineRunner handFrequencyDataLoadCommandLineRunner( 17 | HandFrequencyRepository handFrequencyRepository) { 18 | return (args) -> handFrequencyRepository.deleteAll() 19 | .thenMany(Flux.just( 20 | new HandFrequency(PokerHand.HIGH_CARD.getName(), 0, 0.0), 21 | new HandFrequency(PokerHand.ONE_PAIR.getName(), 0, 0.0), 22 | new HandFrequency(PokerHand.TWO_PAIR.getName(), 0, 0.0), 23 | new HandFrequency(PokerHand.THREE_OF_A_KIND.getName(), 0, 0.0), 24 | new HandFrequency(PokerHand.STRAIGHT.getName(), 0, 0.0), 25 | new HandFrequency(PokerHand.FLUSH.getName(), 0, 0.0), 26 | new HandFrequency(PokerHand.FULL_HOUSE.getName(), 0, 0.0), 27 | new HandFrequency(PokerHand.FOUR_OF_A_KIND.getName(), 0, 0.0), 28 | new HandFrequency(PokerHand.STRAIGHT_FLUSH.getName(), 0, 0.0), 29 | new HandFrequency(PokerHand.ROYAL_FLUSH.getName(), 0, 0.0) 30 | )) 31 | .transform(handFrequencyRepository::saveAll) 32 | .subscribe(System.out::println); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/main/java/com/javafxpert/carddeckdemo/poker/controller/PokerController.java: -------------------------------------------------------------------------------- 1 | package com.javafxpert.carddeckdemo.poker.controller; 2 | 3 | import com.javafxpert.carddeckdemo.deck.domain.Card; 4 | import com.javafxpert.carddeckdemo.deck.service.impl.DefaultCardDeckService; 5 | import com.javafxpert.carddeckdemo.poker.domain.HandFrequency; 6 | import com.javafxpert.carddeckdemo.poker.service.PokerService; 7 | import com.javafxpert.carddeckdemo.poker.domain.ScoreHand; 8 | import org.springframework.web.bind.annotation.GetMapping; 9 | import reactor.core.publisher.Flux; 10 | import reactor.core.publisher.Mono; 11 | 12 | import org.springframework.context.annotation.Bean; 13 | import org.springframework.http.ResponseEntity; 14 | import org.springframework.web.bind.annotation.PostMapping; 15 | import org.springframework.web.bind.annotation.RequestMapping; 16 | import org.springframework.web.bind.annotation.RestController; 17 | import org.springframework.web.reactive.function.server.RequestPredicates; 18 | import org.springframework.web.reactive.function.server.RouterFunction; 19 | import org.springframework.web.reactive.function.server.RouterFunctions; 20 | import org.springframework.web.reactive.function.server.ServerResponse; 21 | 22 | @RestController 23 | @RequestMapping("/poker") 24 | public class PokerController { 25 | private final PokerService pokerService; 26 | 27 | public PokerController(PokerService pokerService) { 28 | this.pokerService = pokerService; 29 | } 30 | 31 | @GetMapping("/handfrequencies") 32 | public Flux handFrequencies() { 33 | return pokerService.retrieveHandFrequencies(); 34 | } 35 | 36 | @PostMapping("/hand") 37 | public Mono> identifyHand(Flux cardFlux) { 38 | return cardFlux.map(Card::getSeq) 39 | .collectList() 40 | .filter(l -> l.size() == 5) 41 | .map(list -> new ScoreHand(list).getRank().getName()) 42 | .flatMap(handName -> 43 | pokerService.updateHandFrequency(Mono.just(handName)) 44 | .then(Mono.just(ResponseEntity.ok(handName))) 45 | ) 46 | .defaultIfEmpty(ResponseEntity.badRequest().body("Illegal number of cards")); 47 | } 48 | 49 | @Bean 50 | RouterFunction idHandRoutes() { 51 | return RouterFunctions.route( 52 | RequestPredicates.POST("/poker/idhand"), request -> 53 | request.bodyToFlux(Card.class) 54 | .map(Card::getSeq) 55 | .collectList() 56 | .filter(l -> l.size() == 5) 57 | .map(list -> new ScoreHand(list).getRank().getName()) 58 | .flatMap(handName -> 59 | pokerService.updateHandFrequency(Mono.just(handName)) 60 | .then(ServerResponse.ok().syncBody(handName)) 61 | ) 62 | .switchIfEmpty(ServerResponse.badRequest().syncBody("Illegal number of cards")) 63 | ); 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /src/main/java/com/javafxpert/carddeckdemo/poker/domain/HandFrequency.java: -------------------------------------------------------------------------------- 1 | package com.javafxpert.carddeckdemo.poker.domain; 2 | 3 | import org.springframework.data.annotation.Id; 4 | import org.springframework.data.mongodb.core.mapping.Document; 5 | 6 | import java.util.Objects; 7 | 8 | @Document 9 | public class HandFrequency { 10 | @Id 11 | private String handName; 12 | private long frequency; 13 | private double frequencyPercent; 14 | 15 | @Override 16 | public String toString() { 17 | return "HandFrequency{" + 18 | "handName='" + handName + '\'' + 19 | ", frequency=" + frequency + 20 | ", frequencyPercent=" + frequencyPercent + 21 | '}'; 22 | } 23 | 24 | @Override 25 | public boolean equals(Object o) { 26 | if (this == o) return true; 27 | if (o == null || getClass() != o.getClass()) return false; 28 | HandFrequency that = (HandFrequency) o; 29 | return frequency == that.frequency && 30 | Double.compare(that.frequencyPercent, frequencyPercent) == 0 && 31 | Objects.equals(handName, that.handName); 32 | } 33 | 34 | @Override 35 | public int hashCode() { 36 | 37 | return Objects.hash(handName, frequency, frequencyPercent); 38 | } 39 | 40 | public HandFrequency(String handName, long frequency, double frequencyPercent) { 41 | this.handName = handName; 42 | this.frequency = frequency; 43 | this.frequencyPercent = frequencyPercent; 44 | } 45 | 46 | public String getHandName() { 47 | return handName; 48 | } 49 | 50 | public void setHandName(String handName) { 51 | this.handName = handName; 52 | } 53 | 54 | public long getFrequency() { 55 | return frequency; 56 | } 57 | 58 | public void setFrequency(long frequency) { 59 | this.frequency = frequency; 60 | } 61 | 62 | public double getFrequencyPercent() { 63 | return frequencyPercent; 64 | } 65 | 66 | public void setFrequencyPercent(double frequencyPercent) { 67 | this.frequencyPercent = frequencyPercent; 68 | } 69 | 70 | } 71 | -------------------------------------------------------------------------------- /src/main/java/com/javafxpert/carddeckdemo/poker/domain/PokerHand.java: -------------------------------------------------------------------------------- 1 | package com.javafxpert.carddeckdemo.poker.domain; 2 | 3 | /** 4 | * enum for ranking a poker hand 5 | * @author /u/Philboyd_Studge on 3/26/2016. 6 | */ 7 | public enum PokerHand { 8 | HIGH_CARD("High Card"), 9 | ONE_PAIR("One Pair"), 10 | TWO_PAIR("Two Pairs"), 11 | THREE_OF_A_KIND("Three of a Kind"), 12 | STRAIGHT("Straight"), 13 | FLUSH("Flush"), 14 | FULL_HOUSE("Full House"), 15 | FOUR_OF_A_KIND("Four of a Kind"), 16 | STRAIGHT_FLUSH("Straight Flush"), 17 | ROYAL_FLUSH("Royal Flush"); 18 | 19 | private String name; 20 | 21 | PokerHand(String name) { 22 | this.name = name; 23 | } 24 | 25 | public String getName() { return name; } 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/com/javafxpert/carddeckdemo/poker/domain/ScoreHand.java: -------------------------------------------------------------------------------- 1 | package com.javafxpert.carddeckdemo.poker.domain; 2 | 3 | import java.util.Arrays; 4 | import java.util.List; 5 | 6 | import com.javafxpert.carddeckdemo.poker.Cards; 7 | import com.javafxpert.carddeckdemo.poker.domain.PokerHand; 8 | 9 | /** 10 | * Score a hand of poker 11 | * for 5 cards, no wild cards. 12 | * @author /u/Philboyd_Studge on 3/26/2016. 13 | */ 14 | public class ScoreHand { 15 | 16 | // constants for evaluating pairs 17 | public static final int ONE_PAIR = 7; 18 | public static final int TWO_PAIR = 9; 19 | public static final int THREE_OF_A_KIND = 11; 20 | public static final int FULL_HOUSE = 13; 21 | public static final int FOUR_OF_A_KIND = 17; 22 | 23 | List hand; // the hand 24 | int[] faceFrequency = new int[13]; // frequency table for face values 25 | int[] suitFrequency = new int[4]; // frequency table for suits 26 | boolean hasAce; // hand contains at least one Ace 27 | boolean isRoyal; // hand contains a straight that is 'royal' i.e. A-10-J-Q-K 28 | PokerHand rank; // calculated rank of the hand 29 | int highCard; // highest card in hand for tiebreakers 30 | 31 | /** 32 | * Constructor 33 | * @param hand list of integers in range 0 - 51, must have only 5 elements 34 | */ 35 | public ScoreHand(List hand) { 36 | if (hand.size() != 5) { 37 | throw new IllegalArgumentException("Hand incorrect size"); 38 | } 39 | this.hand = hand; 40 | getFrequencies(); 41 | rank = PokerHand.HIGH_CARD; 42 | findHighCard(); 43 | rankHand(); 44 | } 45 | 46 | public PokerHand getRank() { 47 | return rank; 48 | } 49 | 50 | public int getHighCard() { 51 | return highCard; 52 | } 53 | 54 | private void rankHand() { 55 | 56 | // find all possibilities of straights first 57 | if (isStraight()) { 58 | if (isFlush()) { 59 | rank = isRoyal ? PokerHand.ROYAL_FLUSH : PokerHand.STRAIGHT_FLUSH; 60 | } else { 61 | rank = PokerHand.STRAIGHT; 62 | } 63 | } else { 64 | if (isFlush()) rank = PokerHand.FLUSH; 65 | } 66 | 67 | // now find pairs/other multiples 68 | int pairs = getPairSum(); 69 | switch (pairs) { 70 | case ONE_PAIR: 71 | if (rank.compareTo(PokerHand.ONE_PAIR) < 0) rank = PokerHand.ONE_PAIR; 72 | break; 73 | case TWO_PAIR: 74 | if (rank.compareTo(PokerHand.TWO_PAIR) < 0) rank = PokerHand.TWO_PAIR; 75 | break; 76 | case THREE_OF_A_KIND: 77 | if (rank.compareTo(PokerHand.THREE_OF_A_KIND) < 0) rank = PokerHand.THREE_OF_A_KIND; 78 | break; 79 | case FULL_HOUSE: 80 | if (rank.compareTo(PokerHand.FULL_HOUSE) < 0) rank = PokerHand.FULL_HOUSE; 81 | break; 82 | case FOUR_OF_A_KIND: 83 | if (rank.compareTo(PokerHand.FOUR_OF_A_KIND) < 0) rank = PokerHand.FOUR_OF_A_KIND; 84 | break; 85 | default: 86 | 87 | } 88 | } 89 | 90 | /** 91 | * fill frequency tables with hand data 92 | */ 93 | private void getFrequencies() { 94 | for (int each : hand) { 95 | 96 | // kill three birds with one for-loop 97 | if (Cards.getFaceValue(each) == 0) hasAce = true; 98 | faceFrequency[Cards.getFaceValue(each)]++; 99 | suitFrequency[Cards.getSuit(each)]++; 100 | } 101 | } 102 | 103 | /** 104 | * use frequency of suits table to find a flush 105 | * @return true if all cards the same suit 106 | */ 107 | private boolean isFlush() { 108 | for (int each : suitFrequency) { 109 | if (each == 5) return true; 110 | } 111 | return false; 112 | } 113 | 114 | /** 115 | * get a sorted int array for use in finding straights 116 | * @return sorted array of card face values 117 | */ 118 | private int[] getSortedArray() { 119 | int[] sorted = new int[5]; 120 | int i = 0; 121 | for (int each : hand) { 122 | sorted[i++] = Cards.getFaceValue(each); 123 | } 124 | Arrays.sort(sorted); 125 | return sorted; 126 | } 127 | 128 | /** 129 | * check for straights 130 | * @return true if a 5-card run exists 131 | */ 132 | private boolean isStraight() { 133 | int[] sorted = getSortedArray(); 134 | 135 | // ugly but why not 136 | if (hasAce && sorted[1] > 1) { 137 | if (sorted[1]==9 && sorted[2]==10 && 138 | sorted[3]==11 && sorted[4]== 12) { 139 | isRoyal = true; 140 | return true; 141 | } 142 | } else { 143 | for (int i = 1; i < 5; i++) { 144 | if (sorted[i] - sorted[i - 1] != 1) return false; 145 | } 146 | return true; 147 | } 148 | return false; 149 | } 150 | 151 | /** 152 | * use the face value frequency table to get a 153 | * unique number for the different possibilities 154 | * @return pair sum number that will correspond to the constants above 155 | */ 156 | private int getPairSum() { 157 | int sum = 0; 158 | for (int each : faceFrequency) { 159 | sum += each * each; 160 | } 161 | return sum; 162 | } 163 | 164 | /** 165 | * find and set the high card for tiebreaker purposes 166 | */ 167 | private void findHighCard() { 168 | if (hasAce) { 169 | for (int each : hand) { 170 | if (Cards.getFaceValue(each) == 0) highCard = each; 171 | } 172 | } else { 173 | int max = -1; 174 | for (int each : hand) { 175 | if (Cards.getFaceValue(each) > max) { 176 | max = Cards.getFaceValue(each); 177 | highCard = each; 178 | } 179 | } 180 | } 181 | 182 | } 183 | 184 | } 185 | -------------------------------------------------------------------------------- /src/main/java/com/javafxpert/carddeckdemo/poker/repository/HandFrequencyRepository.java: -------------------------------------------------------------------------------- 1 | package com.javafxpert.carddeckdemo.poker.repository; 2 | 3 | import com.javafxpert.carddeckdemo.poker.domain.HandFrequency; 4 | 5 | import org.springframework.data.mongodb.repository.ReactiveMongoRepository; 6 | 7 | public interface HandFrequencyRepository extends ReactiveMongoRepository { 8 | } 9 | -------------------------------------------------------------------------------- /src/main/java/com/javafxpert/carddeckdemo/poker/service/PokerService.java: -------------------------------------------------------------------------------- 1 | package com.javafxpert.carddeckdemo.poker.service; 2 | 3 | import java.time.Duration; 4 | 5 | import com.javafxpert.carddeckdemo.poker.domain.HandFrequency; 6 | import com.javafxpert.carddeckdemo.poker.repository.HandFrequencyRepository; 7 | import reactor.core.publisher.Flux; 8 | import reactor.core.publisher.Mono; 9 | 10 | import org.springframework.data.domain.Sort; 11 | import org.springframework.stereotype.Service; 12 | 13 | @Service 14 | public class PokerService { 15 | private final HandFrequencyRepository handFrequencyRepository; 16 | 17 | public PokerService(HandFrequencyRepository handFrequencyRepository) { 18 | this.handFrequencyRepository = handFrequencyRepository; 19 | } 20 | 21 | public Mono updateHandFrequency(Mono handNameMono) { 22 | return handFrequencyRepository 23 | .findById(handNameMono) 24 | .map(hf -> new HandFrequency(hf.getHandName(), hf.getFrequency() + 1, 0.0)) 25 | .flatMap(handFrequencyRepository::save) 26 | .timeout(Duration.ofMillis(500)) 27 | .retryWhen(t -> t.zipWith(Flux.range(0, 5)).delayElements(Duration.ofMillis(200))) 28 | .then(); 29 | } 30 | 31 | public Flux retrieveHandFrequencies() { 32 | return handFrequencyRepository.findAll(Sort.by("frequency")) 33 | .collectList() 34 | .flatMapMany(l -> { 35 | long totalFrequencies = l.stream() 36 | .mapToLong(HandFrequency::getFrequency) 37 | .sum(); 38 | 39 | return Flux.fromStream(l.stream()) 40 | .map(hf -> new HandFrequency(hf.getHandName(), 41 | hf.getFrequency(), 42 | hf.getFrequency() * 100 / totalFrequencies)); 43 | }); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/main/resources/META-INF/additional-spring-configuration-metadata.json: -------------------------------------------------------------------------------- 1 | { 2 | "groups": [ 3 | { 4 | "name": "card.deck.images.server", 5 | "type": "com.javafxpert.carddeckdemo.deck.configuration.CardDeckImagesServerProperties", 6 | "sourceType": "com.javafxpert.carddeckdemo.deck.configuration.CardDeckImagesServerProperties", 7 | "description": "Images Server Configurations Properties." 8 | }, 9 | { 10 | "name": "poker.server", 11 | "type": "com.javafxpert.carddeckdemo.deck.configuration.PokerServerProperties", 12 | "sourceType": "com.javafxpert.carddeckdemo.deck.configuration.PokerServerProperties", 13 | "description": "Poker Server Configurations Properties." 14 | } 15 | ], 16 | "properties": [ 17 | { 18 | "name": "card.deck.images.server.host", 19 | "type": "java.lang.String", 20 | "sourceType": "com.javafxpert.carddeckdemo.deck.configuration.CardDeckImagesServerProperties", 21 | "description": "Endpoint URI for images sources." 22 | }, 23 | { 24 | "name": "card.deck.images.server.host", 25 | "type": "java.lang.String", 26 | "sourceType": "com.javafxpert.carddeckdemo.deck.configuration.CardDeckImagesServerProperties", 27 | "description": "Endpoint's URI PORT for images sources." 28 | }, 29 | { 30 | "name": "poker.server.host", 31 | "type": "java.lang.String", 32 | "sourceType": "com.javafxpert.carddeckdemo.deck.configuration.PokerServerProperties", 33 | "description": "Endpoint URI for poker sources." 34 | }, 35 | { 36 | "name": "poker.server.host", 37 | "type": "java.lang.String", 38 | "sourceType": "com.javafxpert.carddeckdemo.deck.configuration.PokerServerProperties", 39 | "description": "Endpoint's URI PORT for poker sources." 40 | } 41 | ] 42 | } -------------------------------------------------------------------------------- /src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | poker.server.host=http://127.0.0.1 2 | poker.server.port=8080 3 | card.deck.images.server.host=http://127.0.0.1 4 | card.deck.images.server.port=8080 -------------------------------------------------------------------------------- /src/main/resources/static/app.js: -------------------------------------------------------------------------------- 1 | let playingCards = []; 2 | let cardStr = ""; // Comma-delimited string of card codes held in the client 3 | let cardBackImg = 'http://127.0.0.1:8080/images/gray_back_reactor.png'; 4 | 5 | // mmessage display node 6 | let messageDisplayNode = document.getElementById("message-display"); 7 | 8 | // card area nodes 9 | let playingCardsNode = document.getElementById("playing-cards"); 10 | 11 | // other nodes 12 | let newDeckNode = document.getElementById("new-deck") 13 | let onlyHeartsNode = document.getElementById("only-hearts"); 14 | let cutDeckNode = document.getElementById("cut-deck"); 15 | let overhandShuffleNode = document.getElementById("overhand-shuffle"); 16 | let riffleShuffleNode = document.getElementById("riffle-shuffle"); 17 | let randomShuffleNode = document.getElementById("random-shuffle"); 18 | let dealPokerHandNode = document.getElementById("deal-poker-hand"); 19 | let shuffleDealNode = document.getElementById("shuffle-deal"); 20 | 21 | 22 | // On click events 23 | newDeckNode.onclick = () => dealCards('newDeck'); 24 | onlyHeartsNode.onclick = () => dealCards('onlyHearts'); 25 | cutDeckNode.onclick = () => dealCards('cutCards'); 26 | overhandShuffleNode.onclick = () => dealCards('overhandShuffle'); 27 | riffleShuffleNode.onclick = () => dealCards('riffleShuffle'); 28 | randomShuffleNode.onclick = () => dealCards('randomShuffle'); 29 | dealPokerHandNode.onclick = () => dealCards('dealPokerHand'); 30 | shuffleDealNode.onclick = () => dealCards('shuffleDeal'); 31 | 32 | function dealCards(modeArg) { 33 | var fetchStr = "http://localhost:8080/cards/deck/new?numcards=52"; 34 | if (modeArg === "newDeck") { 35 | //fetchStr = "http://localhost:8080/cards/deck/new?numcards=52"; 36 | fetchStr = "http://localhost:8080/newdeck?numcards=52"; 37 | } 38 | else if (modeArg === "onlyHearts") { 39 | fetchStr = "http://localhost:8080/cards/deck/Hearts"; 40 | } 41 | else if (modeArg === "cutCards") { 42 | fetchStr = "http://localhost:8080/cards/deck/cut?cards=" + cardStr; 43 | } 44 | else if (modeArg === "overhandShuffle") { 45 | fetchStr = "http://localhost:8080/cards/deck/overhandshuffle?cards=" + cardStr; 46 | } 47 | else if (modeArg === "riffleShuffle") { 48 | fetchStr = "http://localhost:8080/cards/deck/riffleshuffle?cards=" + cardStr; 49 | } 50 | else if (modeArg === "randomShuffle") { 51 | fetchStr = "http://localhost:8080/cards/deck/randomshuffle?cards=" + cardStr; 52 | } 53 | else if (modeArg === "dealPokerHand") { 54 | fetchStr = "http://localhost:8080/cards/deck/dealpokerhand?cards=" + cardStr; 55 | } 56 | else if (modeArg === "shuffleDeal") { 57 | fetchStr = "http://localhost:8080/cards/deck/shuffledeal?cards=" + cardStr; 58 | } 59 | resetPlayingArea(); 60 | newDeckNode.style.display = "block"; 61 | onlyHeartsNode.style.display = "block"; 62 | cutDeckNode.style.display = "block"; 63 | overhandShuffleNode.style.display = "block"; 64 | riffleShuffleNode.style.display = "block"; 65 | randomShuffleNode.style.display = "block"; 66 | dealPokerHandNode.style.display = "block"; 67 | shuffleDealNode.style.display = "block"; 68 | 69 | fetch(fetchStr) 70 | .then(res => res.json()) 71 | .then(res => { 72 | cardStr = ""; 73 | res.cards.forEach((c, i) => { 74 | playingCards.push(c); 75 | let cardDomElement = document.createElement("img"); 76 | cardDomElement.src = c.image; 77 | cardDomElement.alt = c.image; 78 | cardDomElement.addEventListener("click", 79 | evt => cardDomElement.src = (cardDomElement.src == cardDomElement.alt ? cardBackImg : cardDomElement.alt)); 80 | 81 | 82 | cardStr += c.code; 83 | if (i < res.cards.length - 1) { 84 | cardStr += ","; 85 | } 86 | playingCardsNode.appendChild(cardDomElement) 87 | messageDisplayNode.textContent = res.name; 88 | }) 89 | 90 | }) 91 | .catch(console.error) 92 | } 93 | 94 | 95 | function resetPlayingArea() { 96 | playingCards = []; 97 | roundLost = false; 98 | roundWon = false; 99 | roundTied = false; 100 | messageDisplayNode.textContent = ""; 101 | while (playingCardsNode.firstChild) { 102 | playingCardsNode.removeChild(playingCardsNode.firstChild); 103 | } 104 | } 105 | 106 | 107 | -------------------------------------------------------------------------------- /src/main/resources/static/images/0C.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JavaFXpert/card-deck-demo/eefe994dadd4af117fe406256a7495ea6da0de12/src/main/resources/static/images/0C.png -------------------------------------------------------------------------------- /src/main/resources/static/images/0D.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JavaFXpert/card-deck-demo/eefe994dadd4af117fe406256a7495ea6da0de12/src/main/resources/static/images/0D.png -------------------------------------------------------------------------------- /src/main/resources/static/images/0H.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JavaFXpert/card-deck-demo/eefe994dadd4af117fe406256a7495ea6da0de12/src/main/resources/static/images/0H.png -------------------------------------------------------------------------------- /src/main/resources/static/images/0S.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JavaFXpert/card-deck-demo/eefe994dadd4af117fe406256a7495ea6da0de12/src/main/resources/static/images/0S.png -------------------------------------------------------------------------------- /src/main/resources/static/images/2C.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JavaFXpert/card-deck-demo/eefe994dadd4af117fe406256a7495ea6da0de12/src/main/resources/static/images/2C.png -------------------------------------------------------------------------------- /src/main/resources/static/images/2D.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JavaFXpert/card-deck-demo/eefe994dadd4af117fe406256a7495ea6da0de12/src/main/resources/static/images/2D.png -------------------------------------------------------------------------------- /src/main/resources/static/images/2H.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JavaFXpert/card-deck-demo/eefe994dadd4af117fe406256a7495ea6da0de12/src/main/resources/static/images/2H.png -------------------------------------------------------------------------------- /src/main/resources/static/images/2S.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JavaFXpert/card-deck-demo/eefe994dadd4af117fe406256a7495ea6da0de12/src/main/resources/static/images/2S.png -------------------------------------------------------------------------------- /src/main/resources/static/images/3C.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JavaFXpert/card-deck-demo/eefe994dadd4af117fe406256a7495ea6da0de12/src/main/resources/static/images/3C.png -------------------------------------------------------------------------------- /src/main/resources/static/images/3D.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JavaFXpert/card-deck-demo/eefe994dadd4af117fe406256a7495ea6da0de12/src/main/resources/static/images/3D.png -------------------------------------------------------------------------------- /src/main/resources/static/images/3H.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JavaFXpert/card-deck-demo/eefe994dadd4af117fe406256a7495ea6da0de12/src/main/resources/static/images/3H.png -------------------------------------------------------------------------------- /src/main/resources/static/images/3S.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JavaFXpert/card-deck-demo/eefe994dadd4af117fe406256a7495ea6da0de12/src/main/resources/static/images/3S.png -------------------------------------------------------------------------------- /src/main/resources/static/images/4C.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JavaFXpert/card-deck-demo/eefe994dadd4af117fe406256a7495ea6da0de12/src/main/resources/static/images/4C.png -------------------------------------------------------------------------------- /src/main/resources/static/images/4D.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JavaFXpert/card-deck-demo/eefe994dadd4af117fe406256a7495ea6da0de12/src/main/resources/static/images/4D.png -------------------------------------------------------------------------------- /src/main/resources/static/images/4H.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JavaFXpert/card-deck-demo/eefe994dadd4af117fe406256a7495ea6da0de12/src/main/resources/static/images/4H.png -------------------------------------------------------------------------------- /src/main/resources/static/images/4S.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JavaFXpert/card-deck-demo/eefe994dadd4af117fe406256a7495ea6da0de12/src/main/resources/static/images/4S.png -------------------------------------------------------------------------------- /src/main/resources/static/images/5C.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JavaFXpert/card-deck-demo/eefe994dadd4af117fe406256a7495ea6da0de12/src/main/resources/static/images/5C.png -------------------------------------------------------------------------------- /src/main/resources/static/images/5D.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JavaFXpert/card-deck-demo/eefe994dadd4af117fe406256a7495ea6da0de12/src/main/resources/static/images/5D.png -------------------------------------------------------------------------------- /src/main/resources/static/images/5H.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JavaFXpert/card-deck-demo/eefe994dadd4af117fe406256a7495ea6da0de12/src/main/resources/static/images/5H.png -------------------------------------------------------------------------------- /src/main/resources/static/images/5S.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JavaFXpert/card-deck-demo/eefe994dadd4af117fe406256a7495ea6da0de12/src/main/resources/static/images/5S.png -------------------------------------------------------------------------------- /src/main/resources/static/images/6C.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JavaFXpert/card-deck-demo/eefe994dadd4af117fe406256a7495ea6da0de12/src/main/resources/static/images/6C.png -------------------------------------------------------------------------------- /src/main/resources/static/images/6D.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JavaFXpert/card-deck-demo/eefe994dadd4af117fe406256a7495ea6da0de12/src/main/resources/static/images/6D.png -------------------------------------------------------------------------------- /src/main/resources/static/images/6H.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JavaFXpert/card-deck-demo/eefe994dadd4af117fe406256a7495ea6da0de12/src/main/resources/static/images/6H.png -------------------------------------------------------------------------------- /src/main/resources/static/images/6S.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JavaFXpert/card-deck-demo/eefe994dadd4af117fe406256a7495ea6da0de12/src/main/resources/static/images/6S.png -------------------------------------------------------------------------------- /src/main/resources/static/images/7C.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JavaFXpert/card-deck-demo/eefe994dadd4af117fe406256a7495ea6da0de12/src/main/resources/static/images/7C.png -------------------------------------------------------------------------------- /src/main/resources/static/images/7D.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JavaFXpert/card-deck-demo/eefe994dadd4af117fe406256a7495ea6da0de12/src/main/resources/static/images/7D.png -------------------------------------------------------------------------------- /src/main/resources/static/images/7H.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JavaFXpert/card-deck-demo/eefe994dadd4af117fe406256a7495ea6da0de12/src/main/resources/static/images/7H.png -------------------------------------------------------------------------------- /src/main/resources/static/images/7S.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JavaFXpert/card-deck-demo/eefe994dadd4af117fe406256a7495ea6da0de12/src/main/resources/static/images/7S.png -------------------------------------------------------------------------------- /src/main/resources/static/images/8C.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JavaFXpert/card-deck-demo/eefe994dadd4af117fe406256a7495ea6da0de12/src/main/resources/static/images/8C.png -------------------------------------------------------------------------------- /src/main/resources/static/images/8D.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JavaFXpert/card-deck-demo/eefe994dadd4af117fe406256a7495ea6da0de12/src/main/resources/static/images/8D.png -------------------------------------------------------------------------------- /src/main/resources/static/images/8H.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JavaFXpert/card-deck-demo/eefe994dadd4af117fe406256a7495ea6da0de12/src/main/resources/static/images/8H.png -------------------------------------------------------------------------------- /src/main/resources/static/images/8S.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JavaFXpert/card-deck-demo/eefe994dadd4af117fe406256a7495ea6da0de12/src/main/resources/static/images/8S.png -------------------------------------------------------------------------------- /src/main/resources/static/images/9C.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JavaFXpert/card-deck-demo/eefe994dadd4af117fe406256a7495ea6da0de12/src/main/resources/static/images/9C.png -------------------------------------------------------------------------------- /src/main/resources/static/images/9D.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JavaFXpert/card-deck-demo/eefe994dadd4af117fe406256a7495ea6da0de12/src/main/resources/static/images/9D.png -------------------------------------------------------------------------------- /src/main/resources/static/images/9H.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JavaFXpert/card-deck-demo/eefe994dadd4af117fe406256a7495ea6da0de12/src/main/resources/static/images/9H.png -------------------------------------------------------------------------------- /src/main/resources/static/images/9S.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JavaFXpert/card-deck-demo/eefe994dadd4af117fe406256a7495ea6da0de12/src/main/resources/static/images/9S.png -------------------------------------------------------------------------------- /src/main/resources/static/images/AC.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JavaFXpert/card-deck-demo/eefe994dadd4af117fe406256a7495ea6da0de12/src/main/resources/static/images/AC.png -------------------------------------------------------------------------------- /src/main/resources/static/images/AD.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JavaFXpert/card-deck-demo/eefe994dadd4af117fe406256a7495ea6da0de12/src/main/resources/static/images/AD.png -------------------------------------------------------------------------------- /src/main/resources/static/images/AH.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JavaFXpert/card-deck-demo/eefe994dadd4af117fe406256a7495ea6da0de12/src/main/resources/static/images/AH.png -------------------------------------------------------------------------------- /src/main/resources/static/images/AS.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JavaFXpert/card-deck-demo/eefe994dadd4af117fe406256a7495ea6da0de12/src/main/resources/static/images/AS.png -------------------------------------------------------------------------------- /src/main/resources/static/images/JC.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JavaFXpert/card-deck-demo/eefe994dadd4af117fe406256a7495ea6da0de12/src/main/resources/static/images/JC.png -------------------------------------------------------------------------------- /src/main/resources/static/images/JD.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JavaFXpert/card-deck-demo/eefe994dadd4af117fe406256a7495ea6da0de12/src/main/resources/static/images/JD.png -------------------------------------------------------------------------------- /src/main/resources/static/images/JH.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JavaFXpert/card-deck-demo/eefe994dadd4af117fe406256a7495ea6da0de12/src/main/resources/static/images/JH.png -------------------------------------------------------------------------------- /src/main/resources/static/images/JS.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JavaFXpert/card-deck-demo/eefe994dadd4af117fe406256a7495ea6da0de12/src/main/resources/static/images/JS.png -------------------------------------------------------------------------------- /src/main/resources/static/images/KC.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JavaFXpert/card-deck-demo/eefe994dadd4af117fe406256a7495ea6da0de12/src/main/resources/static/images/KC.png -------------------------------------------------------------------------------- /src/main/resources/static/images/KD.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JavaFXpert/card-deck-demo/eefe994dadd4af117fe406256a7495ea6da0de12/src/main/resources/static/images/KD.png -------------------------------------------------------------------------------- /src/main/resources/static/images/KH.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JavaFXpert/card-deck-demo/eefe994dadd4af117fe406256a7495ea6da0de12/src/main/resources/static/images/KH.png -------------------------------------------------------------------------------- /src/main/resources/static/images/KS.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JavaFXpert/card-deck-demo/eefe994dadd4af117fe406256a7495ea6da0de12/src/main/resources/static/images/KS.png -------------------------------------------------------------------------------- /src/main/resources/static/images/QC.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JavaFXpert/card-deck-demo/eefe994dadd4af117fe406256a7495ea6da0de12/src/main/resources/static/images/QC.png -------------------------------------------------------------------------------- /src/main/resources/static/images/QD.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JavaFXpert/card-deck-demo/eefe994dadd4af117fe406256a7495ea6da0de12/src/main/resources/static/images/QD.png -------------------------------------------------------------------------------- /src/main/resources/static/images/QH.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JavaFXpert/card-deck-demo/eefe994dadd4af117fe406256a7495ea6da0de12/src/main/resources/static/images/QH.png -------------------------------------------------------------------------------- /src/main/resources/static/images/QS.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JavaFXpert/card-deck-demo/eefe994dadd4af117fe406256a7495ea6da0de12/src/main/resources/static/images/QS.png -------------------------------------------------------------------------------- /src/main/resources/static/images/gray_back_reactor.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JavaFXpert/card-deck-demo/eefe994dadd4af117fe406256a7495ea6da0de12/src/main/resources/static/images/gray_back_reactor.png -------------------------------------------------------------------------------- /src/main/resources/static/images/spring-project-reactor.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JavaFXpert/card-deck-demo/eefe994dadd4af117fe406256a7495ea6da0de12/src/main/resources/static/images/spring-project-reactor.png -------------------------------------------------------------------------------- /src/main/resources/static/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Reactive Card Magic 7 | 8 | 9 | 10 | 11 |

Reactive Card Magic

12 |
13 | 14 |
15 |
16 |

 

17 |
18 | 19 |
20 |
21 | 22 |
23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 |
32 | 33 |
34 | 35 |
36 | 37 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /src/main/resources/static/styles.css: -------------------------------------------------------------------------------- 1 | body { 2 | background: #277714; 3 | } 4 | 5 | h1 { 6 | margin: 2rem; 7 | text-align: center; 8 | color: white; 9 | font-family: Futura; 10 | } 11 | 12 | h2 { 13 | text-align: center; 14 | color: white; 15 | font-family: Futura; 16 | font-size: 26px; 17 | } 18 | 19 | #message-display { 20 | text-align: center; 21 | font-family: Futura; 22 | font-size: 26px; 23 | color: white; 24 | } 25 | 26 | .outer-container { 27 | display: flex; 28 | flex-flow: row nowrap; 29 | align-items: center; 30 | } 31 | 32 | #game-area{ 33 | position: relative; 34 | z-index: 1; 35 | width: 100%; 36 | background: #277714; 37 | } 38 | 39 | #playing-cards { 40 | display: flex; 41 | justify-content: center; 42 | height: 450px; 43 | display: table; 44 | margin: 0 auto; 45 | } 46 | 47 | #action-area { 48 | justify-content: center; 49 | z-index: 10; 50 | display: flex; 51 | flex-direction: row; 52 | } 53 | 54 | button { 55 | font-family: Futura; 56 | font-weight: bold; 57 | background: #ffffff; 58 | color: black; 59 | padding: 1rem; 60 | font-size: 1rem; 61 | border-radius: 10px; 62 | outline: none; 63 | border: none; 64 | line-height: 20px; 65 | padding-top: 20px; 66 | transition: all 0.2s ease 0s; 67 | 68 | -webkit-box-shadow: inset 0px 0px 5px 2px rgba(0,0,0,0.75); 69 | -moz-box-shadow: inset 0px 0px 5px 2px rgba(0,0,0,0.75); 70 | box-shadow: inset 0px 0px 5px 2px rgba(0,0,0,0.75); 71 | } 72 | button:hover { 73 | cursor: pointer; 74 | color: red; 75 | } 76 | button:active { 77 | color: red; 78 | -webkit-box-shadow: inset 0px 0px 14px 5px rgba(0,0,0,0.75); 79 | -moz-box-shadow: inset 0px 0px 14px 5px rgba(0,0,0,0.75); 80 | box-shadow: inset 0px 0px 14px 5px rgba(0,0,0,0.75); 81 | } 82 | 83 | img { 84 | width: 65px; 85 | height: 100px; 86 | margin: 1px 2px 1px 2px; 87 | } 88 | 89 | @media (min-width: 1200px) { 90 | body { 91 | //padding: 0 12%; 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /src/test/java/com/javafxpert/carddeckdemo/CardDeckDemoApplicationTests.java: -------------------------------------------------------------------------------- 1 | package com.javafxpert.carddeckdemo; 2 | 3 | import org.junit.Test; 4 | import org.junit.runner.RunWith; 5 | import org.springframework.boot.test.context.SpringBootTest; 6 | import org.springframework.test.context.junit4.SpringRunner; 7 | 8 | @RunWith(SpringRunner.class) 9 | @SpringBootTest 10 | public class CardDeckDemoApplicationTests { 11 | 12 | @Test 13 | public void contextLoads() { 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /src/test/java/com/javafxpert/carddeckdemo/PokerHandTester.java: -------------------------------------------------------------------------------- 1 | package com.javafxpert.carddeckdemo; 2 | 3 | import java.util.HashMap; 4 | import java.util.List; 5 | import java.util.Map; 6 | 7 | import com.javafxpert.carddeckdemo.poker.Cards; 8 | import com.javafxpert.carddeckdemo.poker.domain.PokerHand; 9 | import com.javafxpert.carddeckdemo.poker.domain.ScoreHand; 10 | import org.junit.Test; 11 | 12 | /** 13 | * @author /u/Philboyd_Studge on 3/27/2016. 14 | */ 15 | public class PokerHandTester { 16 | 17 | @Test 18 | public void test(String[] args) { 19 | Cards deck = new Cards(); 20 | deck.shuffle(); 21 | 22 | Map frequencyMap = new HashMap<>(); 23 | int total = 1000000; 24 | 25 | for (int i = 0; i < total; i++) { 26 | List hand = deck.deal(5); 27 | 28 | PokerHand temp = new ScoreHand(hand).getRank(); 29 | frequencyMap.put(temp, frequencyMap.getOrDefault(temp, 0) + 1); 30 | } 31 | 32 | for (PokerHand each : PokerHand.values()) { 33 | int count = frequencyMap.getOrDefault(each, 0); 34 | System.out.println(each.getName() + " : " + count); 35 | System.out.printf("%.4f%%%n", (( count / (double) total) * 100)); 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/test/java/com/javafxpert/carddeckdemo/controllers/CardDeckControllerTest.java: -------------------------------------------------------------------------------- 1 | package com.javafxpert.carddeckdemo.controllers; 2 | 3 | import com.javafxpert.carddeckdemo.deck.configuration.CardDeckImagesServerProperties; 4 | import com.javafxpert.carddeckdemo.deck.controller.CardDeckController; 5 | import com.javafxpert.carddeckdemo.deck.domain.Card; 6 | import com.javafxpert.carddeckdemo.deck.repository.CardDeckRepository; 7 | import com.javafxpert.carddeckdemo.deck.service.impl.DefaultCardDeckService; 8 | import com.javafxpert.carddeckdemo.deck.service.impl.ProxyPokerService; 9 | import org.junit.jupiter.api.Test; 10 | 11 | import org.reactivestreams.Publisher; 12 | import org.springframework.data.domain.Example; 13 | import org.springframework.data.domain.Sort; 14 | import reactor.core.publisher.Flux; 15 | import reactor.core.publisher.Mono; 16 | import reactor.test.StepVerifier; 17 | 18 | class CardDeckControllerTest { 19 | CardDeckImagesServerProperties 20 | cardDeckImagesServerProperties = new CardDeckImagesServerProperties(); 21 | CardDeckRepository cardDeckRepository = new CardDeckRepository() { 22 | @Override 23 | public Mono insert(S s) { 24 | return null; 25 | } 26 | 27 | @Override 28 | public Flux insert(Iterable iterable) { 29 | return null; 30 | } 31 | 32 | @Override 33 | public Flux insert(Publisher publisher) { 34 | return null; 35 | } 36 | 37 | @Override 38 | public Flux findAll(Example example) { 39 | return null; 40 | } 41 | 42 | @Override 43 | public Flux findAll(Example example, Sort sort) { 44 | return null; 45 | } 46 | 47 | @Override 48 | public Mono findOne(Example example) { 49 | return null; 50 | } 51 | 52 | @Override 53 | public Mono count(Example example) { 54 | return null; 55 | } 56 | 57 | @Override 58 | public Mono exists(Example example) { 59 | return null; 60 | } 61 | 62 | @Override 63 | public Flux findAll(Sort sort) { 64 | return null; 65 | } 66 | 67 | @Override 68 | public Mono save(S s) { 69 | return null; 70 | } 71 | 72 | @Override 73 | public Flux saveAll(Iterable iterable) { 74 | return null; 75 | } 76 | 77 | @Override 78 | public Flux saveAll(Publisher publisher) { 79 | return null; 80 | } 81 | 82 | @Override 83 | public Mono findById(String s) { 84 | return null; 85 | } 86 | 87 | @Override 88 | public Mono findById(Publisher publisher) { 89 | return null; 90 | } 91 | 92 | @Override 93 | public Mono existsById(String s) { 94 | return null; 95 | } 96 | 97 | @Override 98 | public Mono existsById(Publisher publisher) { 99 | return null; 100 | } 101 | 102 | @Override 103 | public Flux findAll() { 104 | return null; 105 | } 106 | 107 | @Override 108 | public Flux findAllById(Iterable iterable) { 109 | return null; 110 | } 111 | 112 | @Override 113 | public Flux findAllById(Publisher publisher) { 114 | return null; 115 | } 116 | 117 | @Override 118 | public Mono count() { 119 | return null; 120 | } 121 | 122 | @Override 123 | public Mono deleteById(String s) { 124 | return null; 125 | } 126 | 127 | @Override 128 | public Mono deleteById(Publisher publisher) { 129 | return null; 130 | } 131 | 132 | @Override 133 | public Mono delete(Card card) { 134 | return null; 135 | } 136 | 137 | @Override 138 | public Mono deleteAll(Iterable iterable) { 139 | return null; 140 | } 141 | 142 | @Override 143 | public Mono deleteAll(Publisher publisher) { 144 | return null; 145 | } 146 | 147 | @Override 148 | public Mono deleteAll() { 149 | return null; 150 | } 151 | }; 152 | // CardDeckController cardDeckController = new CardDeckController(new DefaultCardDeckService( 153 | // cardDeckImagesServerProperties, cardDeckRepository), 154 | // new ProxyPokerService(new Po), 155 | // cardDeckImagesServerProperties); 156 | 157 | /* TODO: Fix this text to accommodate that a Mono is now returned 158 | @Test 159 | void getCardDeckRiffleShuffle() { 160 | String cardsStrA = "AS,2S,3S,4S,5S,AH,2H,3H,4H,5H"; 161 | StepVerifier.create( 162 | cardDeckController.getCardDeckRiffleShuffle(cardsStrA)) 163 | .expectNext(new Card("AS", "null:null/images")) 164 | .expectNext(new Card("AH", "null:null/images")) 165 | .expectNext(new Card("2S", "null:null/images")) 166 | .expectNext(new Card("2H", "null:null/images")) 167 | .expectNext(new Card("3S", "null:null/images")) 168 | .expectNext(new Card("3H", "null:null/images")) 169 | .expectNext(new Card("4S", "null:null/images")) 170 | .expectNext(new Card("4H", "null:null/images")) 171 | .expectNext(new Card("5S", "null:null/images")) 172 | .expectNext(new Card("5H", "null:null/images")) 173 | .expectComplete() 174 | .verify(); 175 | } 176 | */ 177 | 178 | 179 | // @Test 180 | // void retrievePokerHandName() { 181 | // cardDeckImagesServerProperties.setCardimageshost("http://127.0.0.1"); 182 | // cardDeckImagesServerProperties.setCardimagesport("8080"); 183 | // Flux cardFlux = Flux.just( 184 | // new Card("AC", ""), 185 | // new Card("2C", ""), 186 | // new Card("3C", ""), 187 | // new Card("4C", ""), 188 | // new Card("5C", "") 189 | // ); 190 | // 191 | //// StepVerifier.create(cardDeckController.(cardFlux)) 192 | //// .expectNext("Straight Flush") 193 | //// .verifyComplete(); 194 | // //assertEquals("Straight Flush", cardDeckController.handNameFromDeck(cardFlux)); 195 | // } 196 | } 197 | -------------------------------------------------------------------------------- /src/test/java/com/javafxpert/carddeckdemo/model/CardTest.java: -------------------------------------------------------------------------------- 1 | package com.javafxpert.carddeckdemo.model; 2 | 3 | import com.javafxpert.carddeckdemo.deck.domain.Card; 4 | 5 | import static org.junit.jupiter.api.Assertions.assertEquals; 6 | 7 | class CardTest { 8 | Card cardAS = new Card("AS" , ""); 9 | Card card2S = new Card("2S" , ""); 10 | Card card3S = new Card("3S" , ""); 11 | Card card4S = new Card("4S" , ""); 12 | Card card5S = new Card("5S" , ""); 13 | Card card6S = new Card("6S" , ""); 14 | Card card7S = new Card("7S" , ""); 15 | Card card8S = new Card("8S" , ""); 16 | Card card9S = new Card("9S" , ""); 17 | Card card0S = new Card("0S" , ""); 18 | Card cardJS = new Card("JS" , ""); 19 | Card cardQS = new Card("QS" , ""); 20 | Card cardKS = new Card("KS" , ""); 21 | 22 | Card cardAD = new Card("AD" , ""); 23 | 24 | Card cardAC = new Card("AC" , ""); 25 | 26 | Card cardAH = new Card("AH" , ""); 27 | 28 | @org.junit.jupiter.api.Test 29 | void getCode() { 30 | assertEquals("AS", cardAS.getCode()); 31 | } 32 | 33 | @org.junit.jupiter.api.Test 34 | void getValue() { 35 | assertEquals("ACE", cardAS.getValue()); 36 | assertEquals("2", card2S.getValue()); 37 | assertEquals("3", card3S.getValue()); 38 | assertEquals("4", card4S.getValue()); 39 | assertEquals("5", card5S.getValue()); 40 | assertEquals("6", card6S.getValue()); 41 | assertEquals("7", card7S.getValue()); 42 | assertEquals("8", card8S.getValue()); 43 | assertEquals("9", card9S.getValue()); 44 | assertEquals("10", card0S.getValue()); 45 | assertEquals("JACK", cardJS.getValue()); 46 | assertEquals("QUEEN", cardQS.getValue()); 47 | assertEquals("KING", cardKS.getValue()); 48 | } 49 | 50 | @org.junit.jupiter.api.Test 51 | void getSuit() { 52 | assertEquals("SPADES", cardAS.getSuit()); 53 | assertEquals("DIAMONDS", cardAD.getSuit()); 54 | assertEquals("CLUBS", cardAC.getSuit()); 55 | assertEquals("HEARTS", cardAH.getSuit()); 56 | } 57 | 58 | @org.junit.jupiter.api.Test 59 | void getImage() { 60 | assertEquals("/AS.png", cardAS.getImage()); 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /src/test/java/com/javafxpert/carddeckdemo/services/CardDeckServiceTest.java: -------------------------------------------------------------------------------- 1 | package com.javafxpert.carddeckdemo.services; 2 | 3 | import com.javafxpert.carddeckdemo.deck.configuration.CardDeckImagesServerProperties; 4 | import com.javafxpert.carddeckdemo.deck.domain.Card; 5 | import com.javafxpert.carddeckdemo.deck.repository.CardDeckRepository; 6 | import com.javafxpert.carddeckdemo.deck.service.impl.DefaultCardDeckService; 7 | import org.junit.jupiter.api.Test; 8 | import org.reactivestreams.Publisher; 9 | import org.springframework.data.domain.Example; 10 | import org.springframework.data.domain.Sort; 11 | import reactor.core.publisher.Flux; 12 | import reactor.core.publisher.Mono; 13 | import reactor.test.StepVerifier; 14 | 15 | class CardDeckServiceTest { 16 | CardDeckImagesServerProperties 17 | cardDeckImagesServerProperties = new CardDeckImagesServerProperties(); 18 | CardDeckRepository cardDeckRepository = new CardDeckRepository() { 19 | @Override 20 | public Mono insert(S s) { 21 | return null; 22 | } 23 | 24 | @Override 25 | public Flux insert(Iterable iterable) { 26 | return null; 27 | } 28 | 29 | @Override 30 | public Flux insert(Publisher publisher) { 31 | return null; 32 | } 33 | 34 | @Override 35 | public Flux findAll(Example example) { 36 | return null; 37 | } 38 | 39 | @Override 40 | public Flux findAll(Example example, Sort sort) { 41 | return null; 42 | } 43 | 44 | @Override 45 | public Mono findOne(Example example) { 46 | return null; 47 | } 48 | 49 | @Override 50 | public Mono count(Example example) { 51 | return null; 52 | } 53 | 54 | @Override 55 | public Mono exists(Example example) { 56 | return null; 57 | } 58 | 59 | @Override 60 | public Flux findAll(Sort sort) { 61 | return null; 62 | } 63 | 64 | @Override 65 | public Mono save(S s) { 66 | return null; 67 | } 68 | 69 | @Override 70 | public Flux saveAll(Iterable iterable) { 71 | return null; 72 | } 73 | 74 | @Override 75 | public Flux saveAll(Publisher publisher) { 76 | return null; 77 | } 78 | 79 | @Override 80 | public Mono findById(String s) { 81 | return null; 82 | } 83 | 84 | @Override 85 | public Mono findById(Publisher publisher) { 86 | return null; 87 | } 88 | 89 | @Override 90 | public Mono existsById(String s) { 91 | return null; 92 | } 93 | 94 | @Override 95 | public Mono existsById(Publisher publisher) { 96 | return null; 97 | } 98 | 99 | @Override 100 | public Flux findAll() { 101 | return null; 102 | } 103 | 104 | @Override 105 | public Flux findAllById(Iterable iterable) { 106 | return null; 107 | } 108 | 109 | @Override 110 | public Flux findAllById(Publisher publisher) { 111 | return null; 112 | } 113 | 114 | @Override 115 | public Mono count() { 116 | return null; 117 | } 118 | 119 | @Override 120 | public Mono deleteById(String s) { 121 | return null; 122 | } 123 | 124 | @Override 125 | public Mono deleteById(Publisher publisher) { 126 | return null; 127 | } 128 | 129 | @Override 130 | public Mono delete(Card card) { 131 | return null; 132 | } 133 | 134 | @Override 135 | public Mono deleteAll(Iterable iterable) { 136 | return null; 137 | } 138 | 139 | @Override 140 | public Mono deleteAll(Publisher publisher) { 141 | return null; 142 | } 143 | 144 | @Override 145 | public Mono deleteAll() { 146 | return null; 147 | } 148 | }; 149 | DefaultCardDeckService cardDeckService = new DefaultCardDeckService( 150 | cardDeckImagesServerProperties, 151 | cardDeckRepository); 152 | } 153 | -------------------------------------------------------------------------------- /src/test/java/com/javafxpert/carddeckdemo/util/ScoreHandTest.java: -------------------------------------------------------------------------------- 1 | package com.javafxpert.carddeckdemo.util; 2 | 3 | import com.javafxpert.carddeckdemo.deck.domain.Card; 4 | import com.javafxpert.carddeckdemo.poker.Cards; 5 | import com.javafxpert.carddeckdemo.poker.domain.PokerHand; 6 | import com.javafxpert.carddeckdemo.poker.domain.ScoreHand; 7 | import org.junit.jupiter.api.Test; 8 | 9 | import java.util.ArrayList; 10 | import java.util.Arrays; 11 | import java.util.List; 12 | 13 | import static org.junit.jupiter.api.Assertions.assertEquals; 14 | 15 | class ScoreHandTest { 16 | Cards cards = new Cards(); 17 | 18 | @Test 19 | void aceDiamondsTest() { 20 | int aceDiamondsSeq = new Card("AD", "").getSeq(); 21 | assertEquals("Ace of Diamonds", cards.getCardName(aceDiamondsSeq)); 22 | } 23 | 24 | @Test 25 | void aceClubsTest() { 26 | int aceClubsSeq = new Card("AC", "").getSeq(); 27 | assertEquals("Ace of Clubs", cards.getCardName(aceClubsSeq)); 28 | } 29 | 30 | @Test 31 | void twoDiamondsTest() { 32 | int twoDiamondsSeq = new Card("2D", "").getSeq(); 33 | assertEquals("Two of Diamonds", cards.getCardName(twoDiamondsSeq)); 34 | } 35 | 36 | @Test 37 | void twoClubsTest() { 38 | int twoClubsSeq = new Card("2C", "").getSeq(); 39 | assertEquals("Two of Clubs", cards.getCardName(twoClubsSeq)); 40 | } 41 | 42 | @Test 43 | void twoHeartsTest() { 44 | int twoHeartsSeq = new Card("2H", "").getSeq(); 45 | assertEquals("Two of Hearts", cards.getCardName(twoHeartsSeq)); 46 | } 47 | 48 | @Test 49 | void twoSpadesTest() { 50 | int twoSpadesSeq = new Card("2S", "").getSeq(); 51 | assertEquals("Two of Spades", cards.getCardName(twoSpadesSeq)); 52 | } 53 | 54 | @Test 55 | void threeDiamondsTest() { 56 | int threeDiamondsSeq = new Card("3D", "").getSeq(); 57 | assertEquals("Three of Diamonds", cards.getCardName(threeDiamondsSeq)); 58 | } 59 | 60 | @Test 61 | void threeClubsTest() { 62 | int threeClubsSeq = new Card("3C", "").getSeq(); 63 | assertEquals("Three of Clubs", cards.getCardName(threeClubsSeq)); 64 | } 65 | 66 | @Test 67 | void threeHeartsTest() { 68 | int threeHeartsSeq = new Card("3H", "").getSeq(); 69 | assertEquals("Three of Hearts", cards.getCardName(threeHeartsSeq)); 70 | } 71 | 72 | @Test 73 | void threeSpadesTest() { 74 | int threeSpadesSeq = new Card("3S", "").getSeq(); 75 | assertEquals("Three of Spades", cards.getCardName(threeSpadesSeq)); 76 | } 77 | 78 | 79 | @Test 80 | void KingSpadesTest() { 81 | int kingSpadesSeq = new Card("KS", "").getSeq(); 82 | assertEquals("King of Spades", cards.getCardName(kingSpadesSeq)); 83 | } 84 | 85 | @Test 86 | void highCardTest() { 87 | List cardSeqList = new ArrayList( 88 | Arrays.asList( 89 | new Card("QD", "").getSeq(), 90 | new Card("4C", "").getSeq(), 91 | new Card("2H", "").getSeq(), 92 | new Card("KS", "").getSeq(), 93 | new Card("3D", "").getSeq()) 94 | ); 95 | assertEquals(PokerHand.HIGH_CARD, new ScoreHand(cardSeqList).getRank()); 96 | } 97 | 98 | @Test 99 | void onePairTest() { 100 | List cardSeqList = new ArrayList( 101 | Arrays.asList( 102 | new Card("2S", "").getSeq(), 103 | new Card("4C", "").getSeq(), 104 | new Card("3H", "").getSeq(), 105 | new Card("KS", "").getSeq(), 106 | new Card("3D", "").getSeq()) 107 | ); 108 | assertEquals(PokerHand.ONE_PAIR, new ScoreHand(cardSeqList).getRank()); 109 | } 110 | 111 | @Test 112 | void twoPairTest() { 113 | List cardSeqList = new ArrayList( 114 | Arrays.asList( 115 | new Card("KH", "").getSeq(), 116 | new Card("4C", "").getSeq(), 117 | new Card("3H", "").getSeq(), 118 | new Card("KS", "").getSeq(), 119 | new Card("3D", "").getSeq()) 120 | ); 121 | assertEquals(PokerHand.TWO_PAIR, new ScoreHand(cardSeqList).getRank()); 122 | } 123 | 124 | @Test 125 | void threeOfAKindTest() { 126 | List cardSeqList = new ArrayList( 127 | Arrays.asList( 128 | new Card("KC", "").getSeq(), 129 | new Card("4C", "").getSeq(), 130 | new Card("KH", "").getSeq(), 131 | new Card("KS", "").getSeq(), 132 | new Card("3D", "").getSeq()) 133 | ); 134 | assertEquals(PokerHand.THREE_OF_A_KIND, new ScoreHand(cardSeqList).getRank()); 135 | } 136 | 137 | @Test 138 | void fourOfAKindTest() { 139 | List cardSeqList = new ArrayList( 140 | Arrays.asList( 141 | new Card("KC", "").getSeq(), 142 | new Card("4C", "").getSeq(), 143 | new Card("KH", "").getSeq(), 144 | new Card("KS", "").getSeq(), 145 | new Card("KD", "").getSeq()) 146 | ); 147 | assertEquals(PokerHand.FOUR_OF_A_KIND, new ScoreHand(cardSeqList).getRank()); 148 | } 149 | 150 | @Test 151 | void fullHouseTest() { 152 | List cardSeqList = new ArrayList( 153 | Arrays.asList( 154 | new Card("KH", "").getSeq(), 155 | new Card("3C", "").getSeq(), 156 | new Card("3H", "").getSeq(), 157 | new Card("KS", "").getSeq(), 158 | new Card("3D", "").getSeq()) 159 | ); 160 | assertEquals(PokerHand.FULL_HOUSE, new ScoreHand(cardSeqList).getRank()); 161 | } 162 | 163 | @Test 164 | void straightTest() { 165 | List cardSeqList = new ArrayList( 166 | Arrays.asList( 167 | new Card("2C", "").getSeq(), 168 | new Card("3C", "").getSeq(), 169 | new Card("4H", "").getSeq(), 170 | new Card("5S", "").getSeq(), 171 | new Card("6D", "").getSeq()) 172 | ); 173 | assertEquals(PokerHand.STRAIGHT, new ScoreHand(cardSeqList).getRank()); 174 | } 175 | 176 | @Test 177 | void straightLowAceTest() { 178 | List cardSeqList = new ArrayList( 179 | Arrays.asList( 180 | new Card("AC", "").getSeq(), 181 | new Card("2C", "").getSeq(), 182 | new Card("3H", "").getSeq(), 183 | new Card("4S", "").getSeq(), 184 | new Card("5D", "").getSeq()) 185 | ); 186 | assertEquals(PokerHand.STRAIGHT, new ScoreHand(cardSeqList).getRank()); 187 | } 188 | 189 | @Test 190 | void straightHighAceTest() { 191 | List cardSeqList = new ArrayList( 192 | Arrays.asList( 193 | new Card("0C", "").getSeq(), 194 | new Card("JC", "").getSeq(), 195 | new Card("QH", "").getSeq(), 196 | new Card("KS", "").getSeq(), 197 | new Card("AD", "").getSeq()) 198 | ); 199 | assertEquals(PokerHand.STRAIGHT, new ScoreHand(cardSeqList).getRank()); 200 | } 201 | 202 | @Test 203 | void straightFlushTest() { 204 | List cardSeqList = new ArrayList( 205 | Arrays.asList( 206 | new Card("2D", "").getSeq(), 207 | new Card("3D", "").getSeq(), 208 | new Card("4D", "").getSeq(), 209 | new Card("5D", "").getSeq(), 210 | new Card("6D", "").getSeq()) 211 | ); 212 | assertEquals(PokerHand.STRAIGHT_FLUSH, new ScoreHand(cardSeqList).getRank()); 213 | } 214 | 215 | @Test 216 | void royalStraightTest() { 217 | List cardSeqList = new ArrayList( 218 | Arrays.asList( 219 | new Card("0C", "").getSeq(), 220 | new Card("JC", "").getSeq(), 221 | new Card("QD", "").getSeq(), 222 | new Card("KC", "").getSeq(), 223 | new Card("AC", "").getSeq()) 224 | ); 225 | assertEquals(PokerHand.STRAIGHT, new ScoreHand(cardSeqList).getRank()); 226 | } 227 | 228 | @Test 229 | void royalFlushTest() { 230 | List cardSeqList = new ArrayList( 231 | Arrays.asList( 232 | new Card("0C", "").getSeq(), 233 | new Card("JC", "").getSeq(), 234 | new Card("QC", "").getSeq(), 235 | new Card("KC", "").getSeq(), 236 | new Card("AC", "").getSeq()) 237 | ); 238 | assertEquals(PokerHand.ROYAL_FLUSH, new ScoreHand(cardSeqList).getRank()); 239 | } 240 | 241 | @Test 242 | void flushTest() { 243 | List cardSeqList = new ArrayList( 244 | Arrays.asList( 245 | new Card("2D", "").getSeq(), 246 | new Card("4D", "").getSeq(), 247 | new Card("5D", "").getSeq(), 248 | new Card("7D", "").getSeq(), 249 | new Card("AD", "").getSeq()) 250 | ); 251 | assertEquals(PokerHand.FLUSH, new ScoreHand(cardSeqList).getRank()); 252 | } 253 | 254 | 255 | } 256 | --------------------------------------------------------------------------------