diff --git a/.gitignore b/.gitignore new file mode 100644 index 000000000..2ad7b4dfe --- /dev/null +++ b/.gitignore @@ -0,0 +1,158 @@ +# Default ignored files +/shelf/ +/.idea/workspace.xml +# Datasource local storage ignored files +/../../../../../../../:\Users\jisun\Documents\projects\baseball\.idea/dataSources/ +/dataSources.local.xml +# Editor-based HTTP Client requests +/httpRequests/ + +# Created by https://www.toptal.com/developers/gitignore/api/java-web,windows,java,intellij+all +# Edit at https://www.toptal.com/developers/gitignore?templates=java-web,windows,java,intellij+all + +### Intellij+all ### +# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider +# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 + +# User-specific stuff +.idea/**/workspace.xml +.idea/**/tasks.xml +.idea/**/usage.statistics.xml +.idea/**/dictionaries +.idea/**/shelf + +# Generated files +.idea/**/contentModel.xml + +# Sensitive or high-churn files +.idea/**/dataSources/ +.idea/**/dataSources.ids +.idea/**/dataSources.local.xml +.idea/**/sqlDataSources.xml +.idea/**/dynamic.xml +.idea/**/uiDesigner.xml +.idea/**/dbnavigator.xml + +# Gradle +.idea/**/gradle.xml +.idea/**/libraries + +# Gradle and Maven with auto-import +# When using Gradle or Maven with auto-import, you should exclude module files, +# since they will be recreated, and may cause churn. Uncomment if using +# auto-import. +# .idea/artifacts +# .idea/compiler.xml +# .idea/jarRepositories.xml +# .idea/modules.xml +# .idea/*.iml +# .idea/modules +# *.iml +# *.ipr + +# CMake +cmake-build-*/ + +# Mongo Explorer plugin +.idea/**/mongoSettings.xml + +# File-based project format +*.iws + +# IntelliJ +out/ + +# mpeltonen/sbt-idea plugin +.idea_modules/ + +# JIRA plugin +atlassian-ide-plugin.xml + +# Cursive Clojure plugin +.idea/replstate.xml + +# Crashlytics plugin (for Android Studio and IntelliJ) +com_crashlytics_export_strings.xml +crashlytics.properties +crashlytics-build.properties +fabric.properties + +# Editor-based Rest Client +.idea/httpRequests + +# Android studio 3.1+ serialized cache file +.idea/caches/build_file_checksums.ser + +### Intellij+all Patch ### +# Ignores the whole .idea folder and all .iml files +# See https://github.com/joeblau/gitignore.io/issues/186 and https://github.com/joeblau/gitignore.io/issues/360 + +.idea + +# Reason: https://github.com/joeblau/gitignore.io/issues/186#issuecomment-249601023 + +*.iml +modules.xml +.idea/misc.xml +*.ipr + +# Sonarlint plugin +.idea/sonarlint + +### Java ### +# Compiled class file +*.class + +# Log file +*.log + +# BlueJ files +*.ctxt + +# Mobile Tools for Java (J2ME) +.mtj.tmp/ + +# Package Files # +*.jar +*.war +*.nar +*.ear +*.zip +*.tar.gz +*.rar + +# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml +hs_err_pid* + +### Java-Web ### +## ignoring target file +target/ + +### Windows ### +# Windows thumbnail cache files +Thumbs.db +Thumbs.db:encryptable +ehthumbs.db +ehthumbs_vista.db + +# Dump file +*.stackdump + +# Folder config file +[Dd]esktop.ini + +# Recycle Bin used on file shares +$RECYCLE.BIN/ + +# Windows Installer files +*.cab +*.msi +*.msix +*.msm +*.msp + +# Windows shortcuts +*.lnk + +# End of https://www.toptal.com/developers/gitignore/api/java-web,windows,java,intellij+all + diff --git a/BE/.gitignore b/BE/.gitignore new file mode 100644 index 000000000..0a47efd5c --- /dev/null +++ b/BE/.gitignore @@ -0,0 +1,194 @@ +HELP.md +.gradle +build/ +!gradle/wrapper/gradle-wrapper.jar +!**/src/main/**/build/ +!**/src/test/**/build/ + +### STS ### +.apt_generated +.classpath +.factorypath +.project +.settings +.springBeans +.sts4-cache +bin/ +!**/src/main/**/bin/ +!**/src/test/**/bin/ + +### IntelliJ IDEA ### +.idea +*.iws +*.iml +*.ipr +out/ +!**/src/main/**/out/ +!**/src/test/**/out/ + +### NetBeans ### +/nbproject/private/ +/nbbuild/ +/dist/ +/nbdist/ +/.nb-gradle/ + +### VS Code ### +.vscode/ + + +# Created by https://www.toptal.com/developers/gitignore/api/java-web,windows,java,intellij+all +# Edit at https://www.toptal.com/developers/gitignore?templates=java-web,windows,java,intellij+all + +### Intellij+all ### +# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider +# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 + +# User-specific stuff +.idea/**/workspace.xml +.idea/**/tasks.xml +.idea/**/usage.statistics.xml +.idea/**/dictionaries +.idea/**/shelf +.idea/**/dataSources/ +.idea/**/dataSources.ids +.idea/**/dataSources.local.xml +.idea/**/sqlDataSources.xml +.idea/**/dynamic.xml +.idea/**/uiDesigner.xml +.idea/**/dbnavigator.xml + +# Generated files +.idea/**/contentModel.xml + +# Sensitive or high-churn files +.idea/dataSources/ +.idea/dataSources.ids +.idea/dataSources.local.xml +.idea/sqlDataSources.xml +.idea/dynamic.xml +.idea/uiDesigner.xml +.idea/dbnavigator.xml +.idea/ +# Gradle +.idea/**/gradle.xml +.idea/**/libraries + +# Gradle and Maven with auto-import +# When using Gradle or Maven with auto-import, you should exclude module files, +# since they will be recreated, and may cause churn. Uncomment if using +# auto-import. +# .idea/artifacts +# .idea/compiler.xml +# .idea/jarRepositories.xml +# .idea/modules.xml +# .idea/*.iml +# .idea/modules +# *.iml +# *.ipr + +# CMake +cmake-build-*/ + +# Mongo Explorer plugin +.idea/**/mongoSettings.xml + +# File-based project format +*.iws + +# IntelliJ +out/ + +# mpeltonen/sbt-idea plugin +.idea_modules/ + +# JIRA plugin +atlassian-ide-plugin.xml + +# Cursive Clojure plugin +.idea/replstate.xml + +# Crashlytics plugin (for Android Studio and IntelliJ) +com_crashlytics_export_strings.xml +crashlytics.properties +crashlytics-build.properties +fabric.properties + +# Editor-based Rest Client +.idea/httpRequests + +# Android studio 3.1+ serialized cache file +.idea/caches/build_file_checksums.ser + +### Intellij+all Patch ### +# Ignores the whole .idea folder and all .iml files +# See https://github.com/joeblau/gitignore.io/issues/186 and https://github.com/joeblau/gitignore.io/issues/360 + +.idea/ + +# Reason: https://github.com/joeblau/gitignore.io/issues/186#issuecomment-249601023 + +*.iml +modules.xml +.idea/misc.xml +*.ipr + +# Sonarlint plugin +.idea/sonarlint + +### Java ### +# Compiled class file +*.class + +# Log file +*.log + +# BlueJ files +*.ctxt + +# Mobile Tools for Java (J2ME) +.mtj.tmp/ + +# Package Files # +*.jar +*.war +*.nar +*.ear +*.zip +*.tar.gz +*.rar + +# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml +hs_err_pid* + +### Java-Web ### +## ignoring target file +target/ + +### Windows ### +# Windows thumbnail cache files +Thumbs.db +Thumbs.db:encryptable +ehthumbs.db +ehthumbs_vista.db + +# Dump file +*.stackdump + +# Folder config file +[Dd]esktop.ini + +# Recycle Bin used on file shares +$RECYCLE.BIN/ + +# Windows Installer files +*.cab +*.msi +*.msix +*.msm +*.msp + +# Windows shortcuts +*.lnk + +# End of https://www.toptal.com/developers/gitignore/api/java-web,windows,java,intellij+all diff --git a/BE/build.gradle b/BE/build.gradle new file mode 100644 index 000000000..ef45245d1 --- /dev/null +++ b/BE/build.gradle @@ -0,0 +1,77 @@ +plugins { + id 'org.springframework.boot' version '2.4.5' + id 'io.spring.dependency-management' version '1.0.11.RELEASE' + id 'java' +} + +group = 'codesquad' +version = '0.0.1-SNAPSHOT' +sourceCompatibility = '11' + +configurations { + compileOnly { + extendsFrom annotationProcessor + } +} + +repositories { + mavenCentral() +} + +dependencies { + implementation 'org.springframework.boot:spring-boot-starter-data-jdbc' + implementation 'org.springframework.boot:spring-boot-starter-web' + compileOnly 'org.projectlombok:lombok' + runtimeOnly 'mysql:mysql-connector-java' + annotationProcessor 'org.projectlombok:lombok' + testImplementation 'org.springframework.boot:spring-boot-starter-test' +} + +test { + useJUnitPlatform() +} + +def webappDir = "$projectDir/baseball/fe" + +sourceSets { + main { + resources { + srcDirs = ["$webappDir/build", "$projectDir/src/main/resources"] + } + } +} + +processResources { + dependsOn "copyWebApp" +} + +task copyWebApp(type: Copy) { + dependsOn "buildReact" + from "$webappDir/build" + into "$projectDir/src/main/resources/static" +} + +task buildReact(type: Exec) { + dependsOn "installReact" + workingDir "$webappDir" + inputs.dir "$webappDir" + group = BasePlugin.BUILD_GROUP + if (System.getProperty('os.name').toLowerCase(Locale.ROOT).contains('windows')) { + commandLine "npm.cmd", "run-script", "build" + } else { + commandLine "npm", "run-script", "build" + } +} + +task installReact(type: Exec) { + workingDir "$webappDir" + inputs.dir "$webappDir" + group = BasePlugin.BUILD_GROUP + if (System.getProperty('os.name').toLowerCase(Locale.ROOT).contains('windows')) { + commandLine "npm.cmd", "audit", "fix" + commandLine 'npm.cmd', 'install' + } else { + commandLine "npm", "audit", "fix" + commandLine 'npm', 'install' + } +} diff --git a/BE/gradle/wrapper/gradle-wrapper.properties b/BE/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 000000000..442d9132e --- /dev/null +++ b/BE/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,5 @@ +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-6.8.3-bin.zip +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists diff --git a/BE/gradlew b/BE/gradlew new file mode 100644 index 000000000..4f906e0c8 --- /dev/null +++ b/BE/gradlew @@ -0,0 +1,185 @@ +#!/usr/bin/env sh + +# +# Copyright 2015 the original author or authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +############################################################################## +## +## Gradle start up script for UN*X +## +############################################################################## + +# Attempt to set APP_HOME +# Resolve links: $0 may be a link +PRG="$0" +# Need this for relative symlinks. +while [ -h "$PRG" ] ; do + ls=`ls -ld "$PRG"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG=`dirname "$PRG"`"/$link" + fi +done +SAVED="`pwd`" +cd "`dirname \"$PRG\"`/" >/dev/null +APP_HOME="`pwd -P`" +cd "$SAVED" >/dev/null + +APP_NAME="Gradle" +APP_BASE_NAME=`basename "$0"` + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD="maximum" + +warn () { + echo "$*" +} + +die () { + echo + echo "$*" + echo + exit 1 +} + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "`uname`" in + CYGWIN* ) + cygwin=true + ;; + Darwin* ) + darwin=true + ;; + MINGW* ) + msys=true + ;; + NONSTOP* ) + nonstop=true + ;; +esac + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + else + JAVACMD="$JAVA_HOME/bin/java" + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD="java" + which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." +fi + +# Increase the maximum file descriptors if we can. +if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then + MAX_FD_LIMIT=`ulimit -H -n` + if [ $? -eq 0 ] ; then + if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then + MAX_FD="$MAX_FD_LIMIT" + fi + ulimit -n $MAX_FD + if [ $? -ne 0 ] ; then + warn "Could not set maximum file descriptor limit: $MAX_FD" + fi + else + warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" + fi +fi + +# For Darwin, add options to specify how the application appears in the dock +if $darwin; then + GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" +fi + +# For Cygwin or MSYS, switch paths to Windows format before running java +if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then + APP_HOME=`cygpath --path --mixed "$APP_HOME"` + CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` + + JAVACMD=`cygpath --unix "$JAVACMD"` + + # We build the pattern for arguments to be converted via cygpath + ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` + SEP="" + for dir in $ROOTDIRSRAW ; do + ROOTDIRS="$ROOTDIRS$SEP$dir" + SEP="|" + done + OURCYGPATTERN="(^($ROOTDIRS))" + # Add a user-defined pattern to the cygpath arguments + if [ "$GRADLE_CYGPATTERN" != "" ] ; then + OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" + fi + # Now convert the arguments - kludge to limit ourselves to /bin/sh + i=0 + for arg in "$@" ; do + CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` + CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option + + if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition + eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` + else + eval `echo args$i`="\"$arg\"" + fi + i=`expr $i + 1` + done + case $i in + 0) set -- ;; + 1) set -- "$args0" ;; + 2) set -- "$args0" "$args1" ;; + 3) set -- "$args0" "$args1" "$args2" ;; + 4) set -- "$args0" "$args1" "$args2" "$args3" ;; + 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; + 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; + 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; + 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; + 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; + esac +fi + +# Escape application args +save () { + for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done + echo " " +} +APP_ARGS=`save "$@"` + +# Collect all arguments for the java command, following the shell quoting and substitution rules +eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" + +exec "$JAVACMD" "$@" diff --git a/BE/gradlew.bat b/BE/gradlew.bat new file mode 100644 index 000000000..107acd32c --- /dev/null +++ b/BE/gradlew.bat @@ -0,0 +1,89 @@ +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem + +@if "%DEBUG%" == "" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%" == "" set DIRNAME=. +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if "%ERRORLEVEL%" == "0" goto execute + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto execute + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* + +:end +@rem End local scope for the variables with windows NT shell +if "%ERRORLEVEL%"=="0" goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 +exit /b 1 + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/BE/settings.gradle b/BE/settings.gradle new file mode 100644 index 000000000..c1cccd8ee --- /dev/null +++ b/BE/settings.gradle @@ -0,0 +1 @@ +rootProject.name = 'baseball' diff --git a/BE/src/main/java/codesquad/baseball/BaseballApplication.java b/BE/src/main/java/codesquad/baseball/BaseballApplication.java new file mode 100644 index 000000000..cfaed7670 --- /dev/null +++ b/BE/src/main/java/codesquad/baseball/BaseballApplication.java @@ -0,0 +1,13 @@ +package codesquad.baseball; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class BaseballApplication { + + public static void main(String[] args) { + SpringApplication.run(BaseballApplication.class, args); + } + +} diff --git a/BE/src/main/java/codesquad/baseball/DTO/ApiResponse.java b/BE/src/main/java/codesquad/baseball/DTO/ApiResponse.java new file mode 100644 index 000000000..f893ed90d --- /dev/null +++ b/BE/src/main/java/codesquad/baseball/DTO/ApiResponse.java @@ -0,0 +1,21 @@ +package codesquad.baseball; + +import codesquad.baseball.DTO.*; +import codesquad.baseball.domain.Inning; +import com.fasterxml.jackson.annotation.JsonPropertyOrder; +import lombok.AllArgsConstructor; +import lombok.Getter; + +@Getter +@AllArgsConstructor +@JsonPropertyOrder({"matchId", "inning", "nextHitter", "expeditionTeam", "homeTeam", "pitcher", "hitter", "teamLog"}) +public class ApiResponse { + Long matchId; + Inning inning; + PlayerLogDTO nextHitter; + TeamDTO expeditionTeam; + TeamDTO homeTeam; + PlayerDTO pitcher; + PlayerDTO hitter; + TeamLogDTO teamLog; +} diff --git a/BE/src/main/java/codesquad/baseball/DTO/PlayerDTO.java b/BE/src/main/java/codesquad/baseball/DTO/PlayerDTO.java new file mode 100644 index 000000000..cd80bb94d --- /dev/null +++ b/BE/src/main/java/codesquad/baseball/DTO/PlayerDTO.java @@ -0,0 +1,25 @@ +package codesquad.baseball.DTO; + +import codesquad.baseball.domain.Player; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +@AllArgsConstructor +public class PlayerDTO { + private String role; + private String name; + private int pitchCount; + private int plateAppearances; + private int hits; + + public PlayerDTO(String role, Player player) { + this.role = role; + this.name = player.getName(); + this.pitchCount = player.getPlayerGameInfo().getPitchCount(); + this.plateAppearances = player.getPlayerGameInfo().getPlateAppearance(); + this.hits = player.getPlayerGameInfo().getHits(); + } +} diff --git a/BE/src/main/java/codesquad/baseball/DTO/PlayerGameScoreDTO.java b/BE/src/main/java/codesquad/baseball/DTO/PlayerGameScoreDTO.java new file mode 100644 index 000000000..23da4587d --- /dev/null +++ b/BE/src/main/java/codesquad/baseball/DTO/PlayerGameScoreDTO.java @@ -0,0 +1,25 @@ +package codesquad.baseball.DTO; + +import codesquad.baseball.domain.Player; +import lombok.Getter; +import lombok.NoArgsConstructor; + +import java.util.List; + +@Getter +@NoArgsConstructor +public class PlayerGameScoreDTO { + private String playerName; + private int plateAppearance; + private int hits; + private int out; + private Long average; + + public PlayerGameScoreDTO(Player player) { + this.playerName = player.getName(); + this.plateAppearance = player.getPlayerGameInfo().getPlateAppearance(); + this.hits = player.getPlayerGameInfo().getHits(); + this.out = player.getPlayerGameInfo().getOut(); + this.average = player.getPlayerGameInfo().getAverage(); + } +} diff --git a/BE/src/main/java/codesquad/baseball/DTO/PlayerListPopUpDTO.java b/BE/src/main/java/codesquad/baseball/DTO/PlayerListPopUpDTO.java new file mode 100644 index 000000000..054cc6609 --- /dev/null +++ b/BE/src/main/java/codesquad/baseball/DTO/PlayerListPopUpDTO.java @@ -0,0 +1,27 @@ +package codesquad.baseball.DTO; + +import codesquad.baseball.domain.Player; +import codesquad.baseball.domain.Team; +import com.fasterxml.jackson.annotation.JsonPropertyOrder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +import java.util.ArrayList; +import java.util.List; + +@Getter +@NoArgsConstructor +@JsonPropertyOrder({"teamName", "user", "playerGameScore"}) +public class PlayerListPopUpDTO { + private String teamName; + private boolean isUser; + private List playerGameScore = new ArrayList<>(); + + public PlayerListPopUpDTO (Team team) { + this.teamName = team.getName(); + this.isUser = team.isUser(); + for(Player player: team.getPlayerList()) { + playerGameScore.add(new PlayerGameScoreDTO(player)); + } + } +} diff --git a/BE/src/main/java/codesquad/baseball/DTO/PlayerLogDTO.java b/BE/src/main/java/codesquad/baseball/DTO/PlayerLogDTO.java new file mode 100644 index 000000000..881046c05 --- /dev/null +++ b/BE/src/main/java/codesquad/baseball/DTO/PlayerLogDTO.java @@ -0,0 +1,47 @@ +package codesquad.baseball.DTO; + +import codesquad.baseball.domain.Constants; +import codesquad.baseball.domain.History; +import codesquad.baseball.domain.Player; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonPropertyOrder; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; + +import java.util.List; + +@Getter +@Setter +@NoArgsConstructor +@AllArgsConstructor +@JsonPropertyOrder({"teamId", "totalTeamScore", "playerBattingOrder", "playerName", "lastAction", "historyList"}) +public class PlayerLogDTO { + + private Long teamId; + private int totalTeamScore; + private int playerBattingOrder; + private String playerName; + private String lastAction; + private List historyList; + + public PlayerLogDTO(Player player, Long teamId) { + this.teamId = teamId; + this.playerBattingOrder = player.getPlayerGameInfo().getBattingOrder(); + this.playerName = player.getName(); + this.lastAction = player.getLastAction(); + this.historyList = player.getHistoryList(); + } + + @JsonIgnore + public boolean isLastActionOut() { + return this.lastAction.equals(Constants.OUT_ACTION); + } + + @JsonIgnore + public boolean isLastActionHit() { + return this.lastAction.equals(Constants.HIT_ACTION); + } + +} diff --git a/BE/src/main/java/codesquad/baseball/DTO/TeamDTO.java b/BE/src/main/java/codesquad/baseball/DTO/TeamDTO.java new file mode 100644 index 000000000..2670b1451 --- /dev/null +++ b/BE/src/main/java/codesquad/baseball/DTO/TeamDTO.java @@ -0,0 +1,19 @@ +package codesquad.baseball.DTO; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.Setter; +import codesquad.baseball.domain.*; + +@Getter +@Setter +@AllArgsConstructor +public class TeamDTO { + private String name; + private int totalScore; + + public TeamDTO(Team team) { + this.name = team.getName(); + this.totalScore = team.getTotalScore(); + } +} diff --git a/BE/src/main/java/codesquad/baseball/DTO/TeamGameScoreDTO.java b/BE/src/main/java/codesquad/baseball/DTO/TeamGameScoreDTO.java new file mode 100644 index 000000000..9107a0889 --- /dev/null +++ b/BE/src/main/java/codesquad/baseball/DTO/TeamGameScoreDTO.java @@ -0,0 +1,25 @@ +package codesquad.baseball.DTO; + +import codesquad.baseball.domain.Team; +import codesquad.baseball.domain.TeamGameScore; +import com.fasterxml.jackson.annotation.JsonPropertyOrder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +import java.util.List; + +@Getter +@NoArgsConstructor +@JsonPropertyOrder({"teamName", "user", "teamGameScore"}) +public class TeamGameScoreDTO { + private String teamName; + private boolean isUser; + + private List teamGameScore; + + public TeamGameScoreDTO(Team team) { + this.teamName = team.getName(); + this.isUser = team.isUser(); + this.teamGameScore = team.getTeamGameScoreList(); + } +} diff --git a/BE/src/main/java/codesquad/baseball/DTO/TeamLogDTO.java b/BE/src/main/java/codesquad/baseball/DTO/TeamLogDTO.java new file mode 100644 index 000000000..67532a523 --- /dev/null +++ b/BE/src/main/java/codesquad/baseball/DTO/TeamLogDTO.java @@ -0,0 +1,24 @@ +package codesquad.baseball.DTO; + +import codesquad.baseball.domain.Player; +import codesquad.baseball.domain.Team; +import lombok.Getter; +import lombok.NoArgsConstructor; + +import java.util.ArrayList; +import java.util.List; + +@Getter +@NoArgsConstructor +public class TeamLogDTO { + private List playerLog = new ArrayList<>(); + + public TeamLogDTO(Team team, Player player) { + int playerIndex = team.getPlayerList().indexOf(player); + for (int i = 0; i < playerIndex; i++) { + Player targetPlayer = team.getPlayerList().get(i); + this.playerLog.add(new PlayerLogDTO(targetPlayer, team.getId())); + } + + } +} diff --git a/BE/src/main/java/codesquad/baseball/controller/GameController.java b/BE/src/main/java/codesquad/baseball/controller/GameController.java new file mode 100644 index 000000000..382fed0c9 --- /dev/null +++ b/BE/src/main/java/codesquad/baseball/controller/GameController.java @@ -0,0 +1,52 @@ +package codesquad.baseball.controller; + +import codesquad.baseball.ApiResponse; +import codesquad.baseball.DTO.*; +import codesquad.baseball.domain.Team; +import codesquad.baseball.service.GameService; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; + +import java.util.HashMap; +import java.util.List; + +@CrossOrigin +@RestController +@RequestMapping("/api/game") +public class GameController { + + private final GameService gameService; + + public GameController(GameService gameService) { + this.gameService = gameService; + } + + @GetMapping("/teams") + public ResponseEntity> selectTeam() { + List teamList = gameService.findTeams(); + return new ResponseEntity<>(teamList, HttpStatus.OK); + } + + @PostMapping + public ResponseEntity initialize(@RequestBody HashMap teamInfo) { + ApiResponse apiResponse = gameService.getGameInfo(teamInfo); + return new ResponseEntity<>(apiResponse, HttpStatus.OK); + } + + @PostMapping("/{matchId}/exchange") + public ResponseEntity exchangePlayer(@PathVariable Long matchId, @RequestBody PlayerLogDTO playerLog) { + ApiResponse apiResponse = gameService.exchangePlayer(matchId, playerLog); + return new ResponseEntity<>(apiResponse, HttpStatus.OK); + } + + @GetMapping("/{matchId}/record/players") + public ResponseEntity showPlayerList(@PathVariable Long matchId) { + return new ResponseEntity<>(gameService.getPlayerInfo(matchId), HttpStatus.OK); + } + + @GetMapping("/{matchId}/record/teams") + public ResponseEntity showDetailScoreList(@PathVariable Long matchId) { + return new ResponseEntity<>(gameService.getTeamGameScores(matchId), HttpStatus.OK); + } +} diff --git a/BE/src/main/java/codesquad/baseball/domain/Constants.java b/BE/src/main/java/codesquad/baseball/domain/Constants.java new file mode 100644 index 000000000..a79af5562 --- /dev/null +++ b/BE/src/main/java/codesquad/baseball/domain/Constants.java @@ -0,0 +1,23 @@ +package codesquad.baseball.domain; + + + +public class Constants { + public static final String HIT_ACTION = "안타"; + public static final String OUT_ACTION = "아웃"; + public static final String FOUR_BALL_ACTION = "볼넷"; + + public static final int MAX_OUT_NUMBER = 3; + + public static final String PITCHER = "투수"; + public static final String HITTER = "타자"; + public static final String OFFENSE = "공격"; + public static final String DEFENSE = "수비"; + public static final String TOP = "초"; + public static final String BOTTOM = "말"; + + public static final String STRIKE = "strike"; + public static final String BALL = "ball"; + public static final String HIT = "hit"; + public static final String OUT = "out"; +} diff --git a/BE/src/main/java/codesquad/baseball/domain/History.java b/BE/src/main/java/codesquad/baseball/domain/History.java new file mode 100644 index 000000000..280584bcc --- /dev/null +++ b/BE/src/main/java/codesquad/baseball/domain/History.java @@ -0,0 +1,35 @@ +package codesquad.baseball.domain; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.RequiredArgsConstructor; +import lombok.Setter; +import org.springframework.data.annotation.Id; + +import static codesquad.baseball.domain.Constants.HIT; +import static codesquad.baseball.domain.Constants.OUT; + +@Getter +@Setter +@AllArgsConstructor +@RequiredArgsConstructor +public class History { + @Id + @JsonIgnore + private Long id; + private String actionName; + private int strike; + private int ball; + private int out; + + @JsonIgnore + public boolean isActionOut() { + return actionName.equals(OUT); + } + + @JsonIgnore + public boolean isActionHit() { + return actionName.equals(HIT); + } +} diff --git a/BE/src/main/java/codesquad/baseball/domain/Inning.java b/BE/src/main/java/codesquad/baseball/domain/Inning.java new file mode 100644 index 000000000..7b3206758 --- /dev/null +++ b/BE/src/main/java/codesquad/baseball/domain/Inning.java @@ -0,0 +1,79 @@ +package codesquad.baseball.domain; + +import lombok.NoArgsConstructor; + +@NoArgsConstructor +public class Inning { + + private int out; + private int inningNumber; + private String role; + private String cycle; + + public Inning(int out, int inningNumber, String role, String cycle) { + this.out = out; + this.inningNumber = inningNumber; + this.role = role; + this.cycle = cycle; + } + + public static Inning initiateInning(boolean isHome) { + if (isHome) { + return new Inning(0, 1, Constants.DEFENSE, Constants.TOP); + } + return new Inning(0, 1, Constants.OFFENSE, Constants.TOP); + } + + public int updateOut(boolean isPlayerOut) { + if (isPlayerOut) { + this.out += 1; + } + return out; + } + + private Inning changeRole() { + if (this.role.equals(Constants.DEFENSE)) { + this.role = Constants.OFFENSE; + return this; + } + this.role = Constants.DEFENSE; + return this; + } + + private Inning changeCycle() { + if (this.cycle.equals(Constants.TOP)) { + this.cycle = Constants.BOTTOM; + return this; + } + this.cycle = Constants.TOP; + this.inningNumber += 1; + return this; + } + + public boolean needChange() { + return this.out == Constants.MAX_OUT_NUMBER; + } + + public Inning changeInning() { + changeCycle(); + changeRole(); + this.out = 0; + return this; + } + + public int getOut() { + return out; + } + + public int getInningNumber() { + return inningNumber; + } + + public String getRole() { + return role; + } + + public String getCycle() { + return cycle; + } +} diff --git a/BE/src/main/java/codesquad/baseball/domain/Match.java b/BE/src/main/java/codesquad/baseball/domain/Match.java new file mode 100644 index 000000000..c3b10a66b --- /dev/null +++ b/BE/src/main/java/codesquad/baseball/domain/Match.java @@ -0,0 +1,54 @@ +package codesquad.baseball.domain; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import lombok.*; +import org.springframework.data.annotation.Id; + +@Getter +@Setter +@AllArgsConstructor +@NoArgsConstructor +@RequiredArgsConstructor +public class Match { + @Id + private Long id; + + @NonNull + private Long myTeamId; + + @NonNull + private Long counterTeamId; + + @NonNull + private Inning currentInning; + + @NonNull + private boolean isHome; + + @JsonIgnore + public Long getHomeTeamId() { + if (isHome) { + return myTeamId; + } + return counterTeamId; + } + + @JsonIgnore + public Long getExpeditionTeamId() { + if (isHome) { + return counterTeamId; + } + return myTeamId; + } + + @JsonIgnore + public Long getOtherTeamId(Long teamId) { + if (teamId.equals(counterTeamId)) { + return myTeamId; + } + if (teamId.equals(myTeamId)) { + return counterTeamId; + } + return -1L; + } +} diff --git a/BE/src/main/java/codesquad/baseball/domain/Player.java b/BE/src/main/java/codesquad/baseball/domain/Player.java new file mode 100644 index 000000000..f14183c6f --- /dev/null +++ b/BE/src/main/java/codesquad/baseball/domain/Player.java @@ -0,0 +1,53 @@ +package codesquad.baseball.domain; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.Setter; +import org.springframework.data.annotation.Id; + +import java.util.List; + +@Getter +@Setter +@AllArgsConstructor +public class Player { + @Id + private Long id; + + private String name; + + private PlayerGameInfo playerGameInfo; + private List historyList; + private String lastAction; + + public void addHistory(List histories) { + historyList.addAll(histories); + } + + public void clearHistory() { + historyList.clear(); + } + + public void clearLastAction() { + lastAction = null; + } + + @JsonIgnore + public boolean isPitcher() { + return playerGameInfo.getRole().equals(Constants.PITCHER); + } + + @JsonIgnore + public void addPitchCount(int pitches) { + getPlayerGameInfo().addPitchCount(pitches); + } + + @JsonIgnore + public void updatePlayerGameInfo(String lastAction) { + boolean hitSuccess = lastAction.equals(Constants.HIT_ACTION); + boolean isOut = lastAction.equals(Constants.OUT_ACTION); + playerGameInfo.updatePlayerGameInfo(hitSuccess, isOut); + this.lastAction = lastAction; + } +} diff --git a/BE/src/main/java/codesquad/baseball/domain/PlayerGameInfo.java b/BE/src/main/java/codesquad/baseball/domain/PlayerGameInfo.java new file mode 100644 index 000000000..33fb964cc --- /dev/null +++ b/BE/src/main/java/codesquad/baseball/domain/PlayerGameInfo.java @@ -0,0 +1,52 @@ +package codesquad.baseball.domain; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.Setter; +import org.springframework.data.annotation.Id; + +@Getter +@Setter +@AllArgsConstructor +public class PlayerGameInfo { + + @Id + private Long id; + + private int battingOrder; + private String role; + private int pitchCount; + + private int plateAppearance; + private int hits; + private int out; + private Long average; + + public void reset() { + pitchCount =0; + plateAppearance = 0; + hits = 0; + out = 0; + average = 0L; + } + + @JsonIgnore + public void addPitchCount(int pitches) { + pitchCount += pitches; + } + + @JsonIgnore + public void updatePlayerGameInfo(boolean hitSuccess, boolean isOut) { + this.plateAppearance += 1; + if (hitSuccess) { + this.hits += 1; + return; + } + if (isOut) { + this.out += 1; + } + this.average = (long) hits / (long) plateAppearance; + } + +} diff --git a/BE/src/main/java/codesquad/baseball/domain/Team.java b/BE/src/main/java/codesquad/baseball/domain/Team.java new file mode 100644 index 000000000..fe3c5da12 --- /dev/null +++ b/BE/src/main/java/codesquad/baseball/domain/Team.java @@ -0,0 +1,105 @@ +package codesquad.baseball.domain; + +import codesquad.baseball.exception.PlayerNotFoundException; +import com.fasterxml.jackson.annotation.JsonIgnore; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; +import org.springframework.data.annotation.Id; + +import java.util.ArrayList; +import java.util.List; + +@Getter +@Setter +@NoArgsConstructor +@AllArgsConstructor +public class Team { + @Id + private Long id; + + private String name; + + @JsonIgnore + private boolean isUser; + + @JsonIgnore + private List historyList = new ArrayList<>(); + + @JsonIgnore + private List teamGameScoreList = new ArrayList<>(); + + @JsonIgnore + private List playerList = new ArrayList<>(); + + @JsonIgnore + public int getTotalScore() { + int total = 0; + for (TeamGameScore teamGameScore : teamGameScoreList) { + total += teamGameScore.getScore(); + } + return total; + } + + @JsonIgnore + public Team initializeTotalScore() { + teamGameScoreList.clear(); + return this; + } + + @JsonIgnore + public void addDefaultScore(int inningNumber) { + TeamGameScore teamGameScore = new TeamGameScore(inningNumber, 0); + teamGameScoreList.add(teamGameScore); + } + + @JsonIgnore + public void createTotalScore(int inningNumber) { + TeamGameScore teamGameScore = new TeamGameScore(inningNumber, 0); + teamGameScoreList.add(teamGameScore); + } + + @JsonIgnore + public void setTotalScore(int inningNumber, int totalScore) { + teamGameScoreList.get(inningNumber - 1).setScore(totalScore); + } + + @JsonIgnore + public Player getNextPlayer(int currentPlayerOrder) { + try { + return playerList.get(currentPlayerOrder); + } catch (IndexOutOfBoundsException e) { + return getFirstHitter(); + } + } + + @JsonIgnore + public Player getPitcher() { + return playerList.stream() + .filter(Player::isPitcher) + .findFirst() + .orElseThrow(PlayerNotFoundException::new); + } + + @JsonIgnore + public Player getFirstHitter() { + return playerList.get(0); + } + + @JsonIgnore + public Player findPlayerByName(String name) { + return playerList.stream() + .filter(player -> player.getName().equals(name)) + .findFirst() + .orElseThrow(PlayerNotFoundException::new); + } + + @JsonIgnore + public void clearAllHistory() { + for (Player player : playerList) { + player.clearHistory(); + player.clearLastAction(); + } + } +} diff --git a/BE/src/main/java/codesquad/baseball/domain/TeamGameScore.java b/BE/src/main/java/codesquad/baseball/domain/TeamGameScore.java new file mode 100644 index 000000000..7d76aab30 --- /dev/null +++ b/BE/src/main/java/codesquad/baseball/domain/TeamGameScore.java @@ -0,0 +1,28 @@ +package codesquad.baseball.domain; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; +import org.springframework.data.annotation.Id; + +@Getter +@Setter +@NoArgsConstructor +@AllArgsConstructor +public class TeamGameScore { + @JsonIgnore + @Id + private Long id; + + private int inningNumber; + + private int score; + + public TeamGameScore(int inningNumber, int score) { + this.inningNumber = inningNumber; + this.score = score; + } + +} diff --git a/BE/src/main/java/codesquad/baseball/exception/ElementNotFoundException.java b/BE/src/main/java/codesquad/baseball/exception/ElementNotFoundException.java new file mode 100644 index 000000000..f605558db --- /dev/null +++ b/BE/src/main/java/codesquad/baseball/exception/ElementNotFoundException.java @@ -0,0 +1,7 @@ +package codesquad.baseball.exception; + +public class ElementNotFoundException extends RuntimeException { + public ElementNotFoundException(String message) { + super(message); + } +} diff --git a/BE/src/main/java/codesquad/baseball/exception/GlobalExceptionHandler.java b/BE/src/main/java/codesquad/baseball/exception/GlobalExceptionHandler.java new file mode 100644 index 000000000..08645480d --- /dev/null +++ b/BE/src/main/java/codesquad/baseball/exception/GlobalExceptionHandler.java @@ -0,0 +1,16 @@ +package codesquad.baseball.exception; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.web.bind.annotation.ControllerAdvice; +import org.springframework.web.bind.annotation.ExceptionHandler; + +@ControllerAdvice +public class GlobalExceptionHandler { + private static final Logger logger = LoggerFactory.getLogger(GlobalExceptionHandler.class); + + @ExceptionHandler(ElementNotFoundException.class) + public void handleElementNotFoundException(ElementNotFoundException e) { + logger.error(e.getMessage()); + } +} diff --git a/BE/src/main/java/codesquad/baseball/exception/MatchNotFoundException.java b/BE/src/main/java/codesquad/baseball/exception/MatchNotFoundException.java new file mode 100644 index 000000000..c2fae69ea --- /dev/null +++ b/BE/src/main/java/codesquad/baseball/exception/MatchNotFoundException.java @@ -0,0 +1,7 @@ +package codesquad.baseball.exception; + +public class MatchNotFoundException extends ElementNotFoundException { + public MatchNotFoundException() { + super("해당 아이디의 게임을 찾을 수 없습니다."); + } +} diff --git a/BE/src/main/java/codesquad/baseball/exception/PlayerNotFoundException.java b/BE/src/main/java/codesquad/baseball/exception/PlayerNotFoundException.java new file mode 100644 index 000000000..b8a7262ef --- /dev/null +++ b/BE/src/main/java/codesquad/baseball/exception/PlayerNotFoundException.java @@ -0,0 +1,7 @@ +package codesquad.baseball.exception; + +public class PlayerNotFoundException extends ElementNotFoundException { + public PlayerNotFoundException() { + super("해당 아이디의 플레이어를 찾을 수 없습니다."); + } +} diff --git a/BE/src/main/java/codesquad/baseball/exception/TeamNotFoundException.java b/BE/src/main/java/codesquad/baseball/exception/TeamNotFoundException.java new file mode 100644 index 000000000..ca209fe49 --- /dev/null +++ b/BE/src/main/java/codesquad/baseball/exception/TeamNotFoundException.java @@ -0,0 +1,7 @@ +package codesquad.baseball.exception; + +public class TeamNotFoundException extends ElementNotFoundException { + public TeamNotFoundException() { + super("해당 아이디의 팀을 찾을 수 없습니다."); + } +} diff --git a/BE/src/main/java/codesquad/baseball/repository/MatchRepository.java b/BE/src/main/java/codesquad/baseball/repository/MatchRepository.java new file mode 100644 index 000000000..05ee62338 --- /dev/null +++ b/BE/src/main/java/codesquad/baseball/repository/MatchRepository.java @@ -0,0 +1,7 @@ +package codesquad.baseball.repository; + +import codesquad.baseball.domain.Match; +import org.springframework.data.repository.CrudRepository; + +public interface MatchRepository extends CrudRepository { +} diff --git a/BE/src/main/java/codesquad/baseball/repository/TeamRepository.java b/BE/src/main/java/codesquad/baseball/repository/TeamRepository.java new file mode 100644 index 000000000..461f99c1e --- /dev/null +++ b/BE/src/main/java/codesquad/baseball/repository/TeamRepository.java @@ -0,0 +1,7 @@ +package codesquad.baseball.repository; + +import codesquad.baseball.domain.Team; +import org.springframework.data.repository.CrudRepository; + +public interface TeamRepository extends CrudRepository { +} diff --git a/BE/src/main/java/codesquad/baseball/service/GameService.java b/BE/src/main/java/codesquad/baseball/service/GameService.java new file mode 100644 index 000000000..d2a496a73 --- /dev/null +++ b/BE/src/main/java/codesquad/baseball/service/GameService.java @@ -0,0 +1,197 @@ +package codesquad.baseball.service; + +import codesquad.baseball.ApiResponse; +import codesquad.baseball.DTO.*; +import codesquad.baseball.domain.Inning; +import codesquad.baseball.domain.Match; +import codesquad.baseball.domain.Player; +import codesquad.baseball.domain.Team; +import codesquad.baseball.exception.MatchNotFoundException; +import codesquad.baseball.exception.TeamNotFoundException; +import codesquad.baseball.repository.MatchRepository; +import codesquad.baseball.repository.TeamRepository; +import org.springframework.stereotype.Service; + +import java.util.HashMap; +import java.util.List; + +@Service +public class GameService { + + private final TeamRepository teamRepository; + private final MatchRepository matchRepository; + + public GameService(TeamRepository teamRepository, MatchRepository matchRepository) { + this.teamRepository = teamRepository; + this.matchRepository = matchRepository; + } + + public ApiResponse getGameInfo(HashMap teamInfo) { + Match match = createMatch(teamInfo); + + setMyTeamIsUserTrue(match); + initializeTeamScore(match); + Team offenseTeam = findFirstOffenseTeam(match); + reset(offenseTeam); + Team defenseTeam = findFirstDefenseTeam(match); + reset(defenseTeam); + setOffenseTeamDefaultScore(offenseTeam); + + Player firstHitter = offenseTeam.getFirstHitter(); + Player pitcher = defenseTeam.getPitcher(); + return createApiResponse(match, offenseTeam, firstHitter, pitcher); + } + + private void reset(Team team) { + for (Player player : team.getPlayerList()) { + player.getPlayerGameInfo().reset(); + } + } + + public ApiResponse createApiResponse(Match match, Team offenseTeam, Player hitter, Player pitcher) { + return new ApiResponse(match.getId(), match.getCurrentInning(), + new PlayerLogDTO(hitter, offenseTeam.getId()), new TeamDTO(findExpeditionTeam(match)), new TeamDTO(findHomeTeam(match)), + new PlayerDTO("투수", pitcher), new PlayerDTO("타자", hitter), new TeamLogDTO(offenseTeam, hitter)); + } + + private void setMyTeamIsUserTrue(Match match) { + Team myTeam = findTeam(match.getMyTeamId()); + myTeam.setUser(true); + saveTeam(myTeam); + } + + private void initializeTeamScore(Match match) { + saveTeam(findExpeditionTeam(match).initializeTotalScore()); + saveTeam(findHomeTeam(match).initializeTotalScore()); + } + + private void setOffenseTeamDefaultScore(Team offenseTeam) { + offenseTeam.addDefaultScore(1); + saveTeam(offenseTeam); + } + + private Team findHomeTeam(Match match) { + return findTeam(match.getHomeTeamId()); + } + + private Team findExpeditionTeam(Match match) { + return findTeam(match.getExpeditionTeamId()); + } + + private Team findFirstOffenseTeam(Match match) { + if (match.isHome()) { + return findTeam(match.getCounterTeamId()); + } + return findTeam(match.getMyTeamId()); + } + + private Team findFirstDefenseTeam(Match match) { + return findTeam(match.getHomeTeamId()); + } + + public PlayerListPopUpDTO[] getPlayerInfo(Long matchId) { + Match match = findMatch(matchId); + Team myTeam = findTeam(match.getMyTeamId()); + Team counterTeam = findTeam(match.getCounterTeamId()); + PlayerListPopUpDTO expeditionTeamPlayerList = new PlayerListPopUpDTO(myTeam); + PlayerListPopUpDTO homeTeamPlayerList = new PlayerListPopUpDTO(counterTeam); + return new PlayerListPopUpDTO[]{expeditionTeamPlayerList, homeTeamPlayerList}; + } + + public TeamGameScoreDTO[] getTeamGameScores(Long matchId) { + Match match = findMatch(matchId); + Team homeTeam = findHomeTeam(match); + Team expeditionTeam = findExpeditionTeam(match); + return new TeamGameScoreDTO[]{new TeamGameScoreDTO(expeditionTeam), new TeamGameScoreDTO(homeTeam)}; + } + + public Team findTeam(Long teamId) { + return teamRepository.findById(teamId).orElseThrow(TeamNotFoundException::new); + } + + public List findTeams() { + return (List) teamRepository.findAll(); + } + + public Team saveTeam(Team team) { + return teamRepository.save(team); + } + + public Match findMatch(Long matchId) { + return matchRepository.findById(matchId).orElseThrow(MatchNotFoundException::new); + } + + public Long getSavedMatchId(Match match) { + return matchRepository.save(match).getId(); + } + + public Match saveMatch(Match match) { + return matchRepository.save(match); + } + + public Match createMatch(HashMap teamInfo) { + Long myTeamId = Long.valueOf(teamInfo.get("myTeamId")); + Long counterTeamId = Long.valueOf(teamInfo.get("counterTeamId")); + boolean isHome = Boolean.parseBoolean(teamInfo.get("isHome")); + Inning inning = Inning.initiateInning(isHome); + return saveMatch(new Match(myTeamId, counterTeamId, inning, isHome)); + } + + public ApiResponse exchangePlayer(Long matchId, PlayerLogDTO playerLog) { + Match match = findMatch(matchId); + Inning currentInning = match.getCurrentInning(); + + Team offenseTeam = updateOffenseTeam(playerLog, currentInning.getInningNumber()); + Long offenseTeamId = offenseTeam.getId(); + + Long defenseTeamId = match.getOtherTeamId(offenseTeamId); + Team defenseTeam = findTeam(defenseTeamId); + Player pitcher = updatePitcher(defenseTeam, playerLog); + + currentInning.updateOut(playerLog.isLastActionOut()); + saveMatch(match); + + Player nextHitter = offenseTeam.getNextPlayer(playerLog.getPlayerBattingOrder()); + + if (currentInning.needChange()) { + currentInning = currentInning.changeInning(); + saveMatch(match); + clearHistoryAndSave(offenseTeam); + + defenseTeam = findTeam(offenseTeamId); + pitcher = defenseTeam.getPitcher(); + + offenseTeam = findTeam(defenseTeamId); + nextHitter = offenseTeam.getFirstHitter(); + offenseTeam.createTotalScore(currentInning.getInningNumber()); + saveTeam(offenseTeam); + } + + return createApiResponse(match, offenseTeam, nextHitter, pitcher); + } + + private Player updatePitcher(Team defenseTeam, PlayerLogDTO playerLog) { + Player pitcher = defenseTeam.getPitcher(); + pitcher.addPitchCount(playerLog.getHistoryList().size() + 1); + return saveTeam(defenseTeam).getPitcher(); + } + + public Team updateOffenseTeam(PlayerLogDTO playerLog, int inningNumber) { + Team offenseTeam = findOffenseTeam(playerLog); + Player hitter = offenseTeam.findPlayerByName(playerLog.getPlayerName()); + hitter.addHistory(playerLog.getHistoryList()); + hitter.updatePlayerGameInfo(playerLog.getLastAction()); + offenseTeam.setTotalScore(inningNumber, playerLog.getTotalTeamScore()); + return saveTeam(offenseTeam); + } + + private Team findOffenseTeam(PlayerLogDTO playerLog) { + Long offenseTeamId = playerLog.getTeamId(); + return findTeam(offenseTeamId); + } + + public void clearHistoryAndSave(Team offenseTeam) { + offenseTeam.clearAllHistory(); + saveTeam(offenseTeam); + } +} diff --git a/BE/src/main/resources/application.properties b/BE/src/main/resources/application.properties new file mode 100644 index 000000000..019070d47 --- /dev/null +++ b/BE/src/main/resources/application.properties @@ -0,0 +1,6 @@ +spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver +#spring.datasource.url=jdbc:mysql://localhost:3306/baseball?characterEncoding=UTF-8&autoReconnect=true +spring.datasource.url=jdbc:mysql://10.1.1.89:3306/baseball?characterEncoding=UTF-8&autoReconnect=true +spring.datasource.username=team-11 +spring.datasource.password=1234 +spring.datasource.initialization-mode=always diff --git a/BE/src/main/resources/data.sql b/BE/src/main/resources/data.sql new file mode 100644 index 000000000..a406845e9 --- /dev/null +++ b/BE/src/main/resources/data.sql @@ -0,0 +1,183 @@ +use baseball; + +insert into team(name, is_user) values ('Captain', false); +insert into team(name, is_user) values ('Marvel', false); +insert into team(name, is_user) values ('Twins', false); +insert into team(name, is_user) values ('Tigers', false); +insert into team(name, is_user) values ('Rockets', false); +insert into team(name, is_user) values ('Dodgers', false); + +insert into player(name, team) values ('신데렐라', 1); +insert into player(name, team) values ('모아나', 1); +insert into player(name, team) values ('벨', 1); +insert into player(name, team) values ('애리얼', 1); +insert into player(name, team) values ('라푼젤', 1); +insert into player(name, team) values ('뮬란', 1); +insert into player(name, team) values ('자스민', 1); +insert into player(name, team) values ('포카혼타스', 1); +insert into player(name, team) values ('메리다', 1); + +insert into player(name, team) values ('김광진', 2); +insert into player(name, team) values ('이동규', 2); +insert into player(name, team) values ('김진수', 2); +insert into player(name, team) values ('박영권', 2); +insert into player(name, team) values ('추진수', 2); +insert into player(name, team) values ('이용대', 2); +insert into player(name, team) values ('류현진', 2); +insert into player(name, team) values ('최동수', 2); +insert into player(name, team) values ('한양범', 2); + +insert into player(name, team) values ('엘사', 3); +insert into player(name, team) values ('안나', 3); +insert into player(name, team) values ('올라프', 3); +insert into player(name, team) values ('스벤', 3); +insert into player(name, team) values ('크리스토프', 3); +insert into player(name, team) values ('트롤', 3); +insert into player(name, team) values ('얼음괴물', 3); +insert into player(name, team) values ('한스', 3); +insert into player(name, team) values ('스벤당근', 3); + +insert into player(name, team) values ('이승만', 4); +insert into player(name, team) values ('장면', 4); +insert into player(name, team) values ('최규하', 4); +insert into player(name, team) values ('전두환', 4); +insert into player(name, team) values ('노태우', 4); +insert into player(name, team) values ('김영삼', 4); +insert into player(name, team) values ('김대중', 4); +insert into player(name, team) values ('노무현', 4); +insert into player(name, team) values ('이명박', 4); + +insert into player(name, team) values ('버즈', 5); +insert into player(name, team) values ('우디', 5); +insert into player(name, team) values ('제시', 5); +insert into player(name, team) values ('보핍', 5); +insert into player(name, team) values ('포키', 5); +insert into player(name, team) values ('렉스', 5); +insert into player(name, team) values ('햄', 5); +insert into player(name, team) values ('포테이토헤드', 5); +insert into player(name, team) values ('에일리언', 5); + +insert into player(name, team) values ('아이언맨', 6); +insert into player(name, team) values ('캡틴아메리카', 6); +insert into player(name, team) values ('스파이더맨', 6); +insert into player(name, team) values ('헐크', 6); +insert into player(name, team) values ('스칼렛위치', 6); +insert into player(name, team) values ('블랙위도우', 6); +insert into player(name, team) values ('블랙팬서', 6); +insert into player(name, team) values ('토르', 6); +insert into player(name, team) values ('그루트', 6); + + +insert into player_game_info(batting_order, role, pitch_count, plate_appearance, hits, `out`, average, player) +values (1, '투수', 0, 0, 0, 0, 0, 1); +insert into player_game_info(batting_order, role, pitch_count, plate_appearance, hits, `out`, average, player) +values (2, '타자', 0, 0, 0, 0, 0, 2); +insert into player_game_info(batting_order, role, pitch_count, plate_appearance, hits, `out`, average, player) +values (3, '타자', 0, 0, 0, 0, 0, 3); +insert into player_game_info(batting_order, role, pitch_count, plate_appearance, hits, `out`, average, player) +values (4, '타자', 0, 0, 0, 0, 0, 4); +insert into player_game_info(batting_order, role, pitch_count, plate_appearance, hits, `out`, average, player) +values (5, '타자', 0, 0, 0, 0, 0, 5); +insert into player_game_info(batting_order, role, pitch_count, plate_appearance, hits, `out`, average, player) +values (6, '타자', 0, 0, 0, 0, 0, 6); +insert into player_game_info(batting_order, role, pitch_count, plate_appearance, hits, `out`, average, player) +values (7, '타자', 0, 0, 0, 0, 0, 7); +insert into player_game_info(batting_order, role, pitch_count, plate_appearance, hits, `out`, average, player) +values (8, '타자', 0, 0, 0, 0, 0, 8); +insert into player_game_info(batting_order, role, pitch_count, plate_appearance, hits, `out`, average, player) +values (9, '타자', 0, 0, 0, 0, 0, 9); + +insert into player_game_info(batting_order, role, pitch_count, plate_appearance, hits, `out`, average, player) +values (1, '투수', 0, 0, 0, 0, 0, 10); +insert into player_game_info(batting_order, role, pitch_count, plate_appearance, hits, `out`, average, player) +values (2, '타자', 0, 0, 0, 0, 0, 11); +insert into player_game_info(batting_order, role, pitch_count, plate_appearance, hits, `out`, average, player) +values (3, '타자', 0, 0, 0, 0, 0, 12); +insert into player_game_info(batting_order, role, pitch_count, plate_appearance, hits, `out`, average, player) +values (4, '타자', 0, 0, 0, 0, 0, 13); +insert into player_game_info(batting_order, role, pitch_count, plate_appearance, hits, `out`, average, player) +values (5, '타자', 0, 0, 0, 0, 0, 14); +insert into player_game_info(batting_order, role, pitch_count, plate_appearance, hits, `out`, average, player) +values (6, '타자', 0, 0, 0, 0, 0, 15); +insert into player_game_info(batting_order, role, pitch_count, plate_appearance, hits, `out`, average, player) +values (7, '타자', 0, 0, 0, 0, 0, 16); +insert into player_game_info(batting_order, role, pitch_count, plate_appearance, hits, `out`, average, player) +values (8, '타자', 0, 0, 0, 0, 0, 17); +insert into player_game_info(batting_order, role, pitch_count, plate_appearance, hits, `out`, average, player) +values (9, '타자', 0, 0, 0, 0, 0, 18); + +insert into player_game_info(batting_order, role, pitch_count, plate_appearance, hits, `out`, average, player) +values (1, '투수', 0, 0, 0, 0, 0, 19); +insert into player_game_info(batting_order, role, pitch_count, plate_appearance, hits, `out`, average, player) +values (2, '타자', 0, 0, 0, 0, 0, 20); +insert into player_game_info(batting_order, role, pitch_count, plate_appearance, hits, `out`, average, player) +values (3, '타자', 0, 0, 0, 0, 0, 21); +insert into player_game_info(batting_order, role, pitch_count, plate_appearance, hits, `out`, average, player) +values (4, '타자', 0, 0, 0, 0, 0, 22); +insert into player_game_info(batting_order, role, pitch_count, plate_appearance, hits, `out`, average, player) +values (5, '타자', 0, 0, 0, 0, 0, 23); +insert into player_game_info(batting_order, role, pitch_count, plate_appearance, hits, `out`, average, player) +values (6, '타자', 0, 0, 0, 0, 0, 24); +insert into player_game_info(batting_order, role, pitch_count, plate_appearance, hits, `out`, average, player) +values (7, '타자', 0, 0, 0, 0, 0, 25); +insert into player_game_info(batting_order, role, pitch_count, plate_appearance, hits, `out`, average, player) +values (8, '타자', 0, 0, 0, 0, 0, 26); +insert into player_game_info(batting_order, role, pitch_count, plate_appearance, hits, `out`, average, player) +values (9, '타자', 0, 0, 0, 0, 0, 27); + +insert into player_game_info(batting_order, role, pitch_count, plate_appearance, hits, `out`, average, player) +values (1, '투수', 0, 0, 0, 0, 0, 28); +insert into player_game_info(batting_order, role, pitch_count, plate_appearance, hits, `out`, average, player) +values (2, '타자', 0, 0, 0, 0, 0, 29); +insert into player_game_info(batting_order, role, pitch_count, plate_appearance, hits, `out`, average, player) +values (3, '타자', 0, 0, 0, 0, 0, 30); +insert into player_game_info(batting_order, role, pitch_count, plate_appearance, hits, `out`, average, player) +values (4, '타자', 0, 0, 0, 0, 0, 31); +insert into player_game_info(batting_order, role, pitch_count, plate_appearance, hits, `out`, average, player) +values (5, '타자', 0, 0, 0, 0, 0, 32); +insert into player_game_info(batting_order, role, pitch_count, plate_appearance, hits, `out`, average, player) +values (6, '타자', 0, 0, 0, 0, 0, 33); +insert into player_game_info(batting_order, role, pitch_count, plate_appearance, hits, `out`, average, player) +values (7, '타자', 0, 0, 0, 0, 0, 34); +insert into player_game_info(batting_order, role, pitch_count, plate_appearance, hits, `out`, average, player) +values (8, '타자', 0, 0, 0, 0, 0, 35); +insert into player_game_info(batting_order, role, pitch_count, plate_appearance, hits, `out`, average, player) +values (9, '타자', 0, 0, 0, 0, 0, 36); + +insert into player_game_info(batting_order, role, pitch_count, plate_appearance, hits, `out`, average, player) +values (1, '투수', 0, 0, 0, 0, 0, 37); +insert into player_game_info(batting_order, role, pitch_count, plate_appearance, hits, `out`, average, player) +values (2, '타자', 0, 0, 0, 0, 0, 38); +insert into player_game_info(batting_order, role, pitch_count, plate_appearance, hits, `out`, average, player) +values (3, '타자', 0, 0, 0, 0, 0, 39); +insert into player_game_info(batting_order, role, pitch_count, plate_appearance, hits, `out`, average, player) +values (4, '타자', 0, 0, 0, 0, 0, 40); +insert into player_game_info(batting_order, role, pitch_count, plate_appearance, hits, `out`, average, player) +values (5, '타자', 0, 0, 0, 0, 0, 41); +insert into player_game_info(batting_order, role, pitch_count, plate_appearance, hits, `out`, average, player) +values (6, '타자', 0, 0, 0, 0, 0, 42); +insert into player_game_info(batting_order, role, pitch_count, plate_appearance, hits, `out`, average, player) +values (7, '타자', 0, 0, 0, 0, 0, 43); +insert into player_game_info(batting_order, role, pitch_count, plate_appearance, hits, `out`, average, player) +values (8, '타자', 0, 0, 0, 0, 0, 44); +insert into player_game_info(batting_order, role, pitch_count, plate_appearance, hits, `out`, average, player) +values (9, '타자', 0, 0, 0, 0, 0, 45); + +insert into player_game_info(batting_order, role, pitch_count, plate_appearance, hits, `out`, average, player) +values (1, '투수', 0, 0, 0, 0, 0, 46); +insert into player_game_info(batting_order, role, pitch_count, plate_appearance, hits, `out`, average, player) +values (2, '타자', 0, 0, 0, 0, 0, 47); +insert into player_game_info(batting_order, role, pitch_count, plate_appearance, hits, `out`, average, player) +values (3, '타자', 0, 0, 0, 0, 0, 48); +insert into player_game_info(batting_order, role, pitch_count, plate_appearance, hits, `out`, average, player) +values (4, '타자', 0, 0, 0, 0, 0, 49); +insert into player_game_info(batting_order, role, pitch_count, plate_appearance, hits, `out`, average, player) +values (5, '타자', 0, 0, 0, 0, 0, 50); +insert into player_game_info(batting_order, role, pitch_count, plate_appearance, hits, `out`, average, player) +values (6, '타자', 0, 0, 0, 0, 0, 51); +insert into player_game_info(batting_order, role, pitch_count, plate_appearance, hits, `out`, average, player) +values (7, '타자', 0, 0, 0, 0, 0, 52); +insert into player_game_info(batting_order, role, pitch_count, plate_appearance, hits, `out`, average, player) +values (8, '타자', 0, 0, 0, 0, 0, 53); +insert into player_game_info(batting_order, role, pitch_count, plate_appearance, hits, `out`, average, player) +values (9, '타자', 0, 0, 0, 0, 0, 54); diff --git a/BE/src/main/resources/schema.sql b/BE/src/main/resources/schema.sql new file mode 100644 index 000000000..631809596 --- /dev/null +++ b/BE/src/main/resources/schema.sql @@ -0,0 +1,75 @@ +drop table if exists team; +create table team +( + id int auto_increment primary key, + name varchar(64) unique not null, + is_user boolean +); + +drop table if exists team_game_score; +create table team_game_score +( + id int auto_increment primary key, + inning_number int, + score int, + team bigint(20) references team (id), + team_key int +); + +drop table if exists player; +create table player +( + id bigint(20) auto_increment primary key, + name varchar(50), + last_action varchar(50), + team bigint(20) references team (id), + team_key int +); + +drop table if exists player_game_info; +create table player_game_info +( + id bigint(20) auto_increment primary key, + batting_order int, + role varchar(20), + pitch_count int, + plate_appearance int, + hits int, + `out` int, + average bigint(20), + player bigint(20) references player (id) +); + +drop table if exists history; +create table history +( + id bigint(20) auto_increment primary key, + action_name varchar(30), + strike int, + ball int, + `out` int, + team bigint(20) references team (id), + team_key int, + player bigint(20) references player (id), + player_key int +); + +drop table if exists `match`; +create table `match` +( + id bigint(20) auto_increment primary key, + my_team_id bigint(20), + counter_team_id bigint(20), + is_home boolean +); + + +drop table if exists inning; +create table inning +( + `out` int, + inning_number int, + role varchar(50), + cycle varchar(50), + `match` bigint(20) primary key references `match` (id) +) diff --git a/BE/src/test/java/codesquad/baseball/BaseballApplicationTests.java b/BE/src/test/java/codesquad/baseball/BaseballApplicationTests.java new file mode 100644 index 000000000..85fdccb7d --- /dev/null +++ b/BE/src/test/java/codesquad/baseball/BaseballApplicationTests.java @@ -0,0 +1,13 @@ +package codesquad.baseball; + +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.context.SpringBootTest; + +@SpringBootTest +class BaseballApplicationTests { + + @Test + void contextLoads() { + } + +}