- Java 11
- Gradle
- SpringBoot
- Spring Web
- Spring Data JPA
- Lombok
- Mapstruct
- H2 in-memory DB
- PostgreSQL
- Docker
- Docker compose
- Flyway
- Spring Boot Test
- JUnit
- Mockito
- MockMvc
- Swagger API
- Application support H2 in-memory DB and Postgres DB, H2 in-memory DB is being used by default.
- DB data is pre-populated by Flyway, SQL scripts can be found here
There are multiple ways to run application
- the default application.yaml will run profile h2, you can change it
- How to install gradle: https://gradle.org/install/
- Run the command to build the whole project: gradle clean build
- start the application with H2 in-mem DB: java -jar ./build/libs/sport-depth-chart-0.0.1-SNAPSHOT.jar --spring.profiles.active=h2
- Run the command to build the whole project: gradle clean build
- with docker-compose.yaml, so you can only docker-compose up todos-postgres
- start the application with Postgres DB: java -jar ./build/libs/sport-depth-chart-0.0.1-SNAPSHOT.jar --spring.profiles.active=postgres
- Run the command to build the whole project: gradle clean build
- run docker-compose up, then application and postgres DB are both up and running.
-
For the scale of the solution, I design the sport and team table, which means we can have more sports and more teams for different sports.
-
From the requirements, it mentioned "A player can be listed on the Depth Chart for multiple positions", so we can use a link table "player_position" to represent this many to many relationships (usually use one to many relationships on both player and position tables).
-
For more sports and teams, player and position table's PK both use increment id (BIGSERIAL).
-
I found a tricky thing in position. From the depth chart, the TE position appears two times, so I create a column "real_position_name" in position table. In that way, we can insert data by position_name with "TE1", "TE2", and show the real position name with column "real_position_name".
- for more sports, teams, so all the API needs the sportId, teamId, I assumed frontend already have these ids in UI.
- In my folloing explanations, a "depth list" actually the player_postion table data, it represents the depth chart data in particular position ex: "LWR-(#13, Evans, Mike),(#1, Darden, Jaelon),(#10, Miller, Scott)"
in DB, after join table(player, position, player_position), data looks like this:
There are 2 cases in addPlayerToDepthChart() case 1: adding a player without a position_depth, case 2: adding a player with a position_depth
For both case 1, case 2, avoid the player existing in this position's depth list call removePlayerFromDepthChart() first, so all the players will shift to the right depth
- case 1: adding a player without a position_depth
- call removePlayerFromDepthChart() first
- find current max depth
- add this player with position_depth with current max depth + 1
- case 2: adding a player with a position_depth
- For consecutive depth, check the position_depth is too big? because I hope each player's position_depth in this depth list is consecutive.
- call removePlayerFromDepthChart() first
- shift other players' depth + 1 (if other players' depth is bigger than or equal to input position_depth)
- add this player to a particular position_depth
- shift other players' depth - 1 (if other players' depth is bigger than removed player's depth)
- remove this player in this depth list
- find this player's position depth in this position
- find backups (other players' position depth is bigger)
Output the depth chart
if you start the application successful, the Swagger API is here:
http://localhost:8080/swagger-ui/index.html?configUrl=/v3/api-docs/swagger-config
For convenience, you can directly call this API without input (I have hard code with sportId is 1 (NFL)), you also can find some names to use in other API.
the response shows the depth chart
{
"sportId": 1,
"teamId": 1,
"positionName": "TE1",
"playerName": "Smith, Donovan"
}
After execution:
In depth chart, the first position of TE has "Smith, Donovan" at the last
{
"sportId": 1,
"teamId": 1,
"positionName": "LWR",
"playerName": "Smith, Donovan",
"positionDepth": 2
}
After execution:
In depth chart, "Smith, Donovan" in position "LWR" and positionDepth is 2
{
"sportId": 1,
"teamId": 1,
"positionName": "LWR",
"playerName": "Smith, Donovan"
}
In depth chart, "Smith, Donovan" in position "LWR" has gone.