Move to new server
This commit is contained in:
5
Dockerfile
Executable file
5
Dockerfile
Executable file
@@ -0,0 +1,5 @@
|
|||||||
|
FROM eclipse-temurin:21
|
||||||
|
|
||||||
|
COPY target/swiss*.jar swiss-backend.jar
|
||||||
|
|
||||||
|
ENTRYPOINT ["java", "-jar", "swiss-backend.jar"]
|
||||||
63
Jenkinsfile
vendored
Normal file
63
Jenkinsfile
vendored
Normal file
@@ -0,0 +1,63 @@
|
|||||||
|
// This Jenkinsfile defines a declarative pipeline
|
||||||
|
pipeline {
|
||||||
|
|
||||||
|
options {
|
||||||
|
disableConcurrentBuilds()
|
||||||
|
}
|
||||||
|
agent any
|
||||||
|
|
||||||
|
/*
|
||||||
|
agent {
|
||||||
|
docker {
|
||||||
|
image 'maven:3.9.3-eclipse-temurin-21'
|
||||||
|
args '-v $HOME/.m2:/root/.m2'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
// Defines the sequence of stages that will be executed
|
||||||
|
stages {
|
||||||
|
// This stage checks out the source code from the SCM (Source Code Management) system
|
||||||
|
stage('Checkout') {
|
||||||
|
steps {
|
||||||
|
// This command checks out the source code from the SCM into the Jenkins workspace
|
||||||
|
checkout scm
|
||||||
|
}
|
||||||
|
}
|
||||||
|
stage('Build') {
|
||||||
|
steps {
|
||||||
|
sh 'mvn -B clean package'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
stage('Docker Build') {
|
||||||
|
steps {
|
||||||
|
sh 'docker build -t upquark/swiss-backend:latest -t upquark/swiss-backend:${BUILD_NUMBER} .'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
stage('Push the Docker Image to DockerHUb') {
|
||||||
|
steps {
|
||||||
|
script {
|
||||||
|
withCredentials([string(credentialsId: 'c7783e4f-2f79-482f-885f-dfb39f8c02d3', variable: 'docker_hub')]) {
|
||||||
|
sh 'docker login -u upquark -p ${docker_hub}'
|
||||||
|
}
|
||||||
|
sh 'docker push upquark/swiss-backend:latest'
|
||||||
|
sh 'docker push upquark/swiss-backend:${BUILD_NUMBER}'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
stage('Deploy to Kubernetes') {
|
||||||
|
steps {
|
||||||
|
script {
|
||||||
|
kubeconfig(credentialsId: 'k3s-kubeconfig') {
|
||||||
|
sh 'cat k8s/deployment.yaml | sed "s/latest/$BUILD_NUMBER/g" | kubectl apply -n swiss -f -'
|
||||||
|
sh 'kubectl apply -f k8s/service.yaml -n swiss'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
7
TODO
Normal file
7
TODO
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
https://stackoverflow.com/questions/76220171/kubernetes-continuous-deploy-plugin-not-found-in-jenkins
|
||||||
|
https://dev.to/amailath/secure-your-spring-boot-and-angular-application-with-jwt-authentication-a-comprehensive-guide-3o64
|
||||||
|
https://bootify.io/spring-security/rest-api-spring-security-with-jwt.html
|
||||||
|
|
||||||
|
https://access.crunchydata.com/documentation/postgres-operator/latest/tutorials/cluster-management/update-cluster
|
||||||
|
|
||||||
|
Token refresh
|
||||||
1
docker-build.sh
Executable file
1
docker-build.sh
Executable file
@@ -0,0 +1 @@
|
|||||||
|
docker build -t swiss-backend:latest .
|
||||||
1
docker-run.sh
Executable file
1
docker-run.sh
Executable file
@@ -0,0 +1 @@
|
|||||||
|
docker run -p 8080:8080 -e SPRING_PROFILES_ACTIVE=local swiss-backend:latest
|
||||||
38
k8s/deployment.yaml
Normal file
38
k8s/deployment.yaml
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: swiss-backend
|
||||||
|
spec:
|
||||||
|
replicas: 1
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
app: swiss-backend
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: swiss-backend
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- name: swiss-backend
|
||||||
|
image: upquark/swiss-backend:latest
|
||||||
|
imagePullPolicy: Always
|
||||||
|
ports:
|
||||||
|
- containerPort: 8080
|
||||||
|
env:
|
||||||
|
# - name: SPRING_PROFILES_ACTIVE
|
||||||
|
# value: local
|
||||||
|
- name: DB_URL
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
key: host
|
||||||
|
name: pg-pguser-swiss-user
|
||||||
|
- name: DB_USERNAME
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
key: user
|
||||||
|
name: pg-pguser-swiss-user
|
||||||
|
- name: DB_PASSWORD
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
key: password
|
||||||
|
name: pg-pguser-swiss-user
|
||||||
27
k8s/external-postgres-service.yaml
Normal file
27
k8s/external-postgres-service.yaml
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
annotations:
|
||||||
|
kubectl.kubernetes.io/last-applied-configuration: |
|
||||||
|
{"apiVersion":"v1","kind":"Service","metadata":{"annotations":{},"name":"external-postgres-svc","namespace":"swiss"},"spec":{"ports":[{"port":5432,"protocol":"TCP","targetPort":5432}]}}
|
||||||
|
creationTimestamp: "2024-09-20T11:29:41Z"
|
||||||
|
name: external-postgres-svc
|
||||||
|
namespace: swiss
|
||||||
|
resourceVersion: "82759"
|
||||||
|
uid: d6fbb75a-9526-4524-a044-df93c0682fd8
|
||||||
|
spec:
|
||||||
|
clusterIP: 10.43.15.101
|
||||||
|
clusterIPs:
|
||||||
|
- 10.43.15.101
|
||||||
|
internalTrafficPolicy: Cluster
|
||||||
|
ipFamilies:
|
||||||
|
- IPv4
|
||||||
|
ipFamilyPolicy: SingleStack
|
||||||
|
ports:
|
||||||
|
- port: 5432
|
||||||
|
protocol: TCP
|
||||||
|
targetPort: 5432
|
||||||
|
sessionAffinity: None
|
||||||
|
type: ClusterIP
|
||||||
|
status:
|
||||||
|
loadBalancer: {}
|
||||||
26
k8s/renovate-cronjob.yaml
Normal file
26
k8s/renovate-cronjob.yaml
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
apiVersion: batch/v1
|
||||||
|
kind: CronJob
|
||||||
|
metadata:
|
||||||
|
name: renovate
|
||||||
|
spec:
|
||||||
|
schedule: '@hourly'
|
||||||
|
concurrencyPolicy: Forbid
|
||||||
|
jobTemplate:
|
||||||
|
spec:
|
||||||
|
template:
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- name: renovate
|
||||||
|
# Update this to the latest available and then enable Renovate on
|
||||||
|
# the manifest
|
||||||
|
image: renovate/renovate:38.80.0
|
||||||
|
args:
|
||||||
|
- user/repo
|
||||||
|
# Environment Variables
|
||||||
|
env:
|
||||||
|
- name: LOG_LEVEL
|
||||||
|
value: debug
|
||||||
|
envFrom:
|
||||||
|
- secretRef:
|
||||||
|
name: renovate-env
|
||||||
|
restartPolicy: Never
|
||||||
13
k8s/renovate-secret.yaml
Normal file
13
k8s/renovate-secret.yaml
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
apiVersion: v1
|
||||||
|
kind: Secret
|
||||||
|
metadata:
|
||||||
|
name: renovate-env
|
||||||
|
type: Opaque
|
||||||
|
stringData:
|
||||||
|
# GITHUB_COM_TOKEN: 'any-personal-user-token-for-github-com-for-fetching-changelogs'
|
||||||
|
# You can set RENOVATE_AUTODISCOVER to true to run Renovate on all repos you have push access to
|
||||||
|
RENOVATE_AUTODISCOVER: 'false'
|
||||||
|
RENOVATE_ENDPOINT: 'https://git.tenvoorde.org/api/v1'
|
||||||
|
RENOVATE_GIT_AUTHOR: 'Renovate Bot <michel@tenvoorde.org>'
|
||||||
|
RENOVATE_PLATFORM: 'gitea'
|
||||||
|
RENOVATE_TOKEN: 'b9791f9de22856120ba85dd0adeb76178e5cb85f'
|
||||||
12
k8s/service.yaml
Normal file
12
k8s/service.yaml
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: swiss-backend
|
||||||
|
spec:
|
||||||
|
type: NodePort
|
||||||
|
selector:
|
||||||
|
app: swiss-backend
|
||||||
|
ports:
|
||||||
|
- protocol: TCP
|
||||||
|
port: 8080
|
||||||
|
nodePort: 30080
|
||||||
28
keys/keypair.pem
Normal file
28
keys/keypair.pem
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
-----BEGIN PRIVATE KEY-----
|
||||||
|
MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCp5PMrGbzVKQSE
|
||||||
|
LSSkMoJnPUKu0f+ySIRe39qd5r1w07S6TAEqIwBdXwCdwTo8QnggNNxlC3j2pa0J
|
||||||
|
lKI3cNrnNitcs8oI0jQ4LN/HsN/cwp3V+m0sBaEVt9mZK0qSj2mxx+EnHpLF3Z+L
|
||||||
|
7EAGPlezpyGKsJHi1hgAXcbKdLcfC/h3g/TtIvPj7VfR86VGArY2VsZQWFsKvkQa
|
||||||
|
rGVosARQo0b2L/qsqYr9CvCEZ6gSTMS0+xr9Fc9AsYOyuzsw2zHvq8i/L8alK/Tt
|
||||||
|
CJobZK1O0Kedbv5R1gEU+NhGzrdZe1YwCCg5QZCk6j9NXN8tpMIFpeORsxXWxB72
|
||||||
|
Dzc6+/FNAgMBAAECggEAB/mFeYkyfi339o1Y6jUtvlNXkTWtwyxYvExVKnLFgymI
|
||||||
|
0vLU3im472kRchY7Gc+D7H0WuE5+zdMOiYPWznPnbpFyHR6aVeoqBdYDZg/1Hhtr
|
||||||
|
hbsEy1tzSX3xApnP3QvKygvIE4pBmPSTc+Gxyqk7/CSU9DngCy4B/+hm96NdYiFd
|
||||||
|
yI5VByp+DMhk/dtgWFOHZcG4MvrRaLA8ZRnSkCa5QrL+la3lf4M9FJedpo9GvjG6
|
||||||
|
c8M+pgLKMmw4bFDqfDyEpYhJxQaAqEMFaiBuMMDymI6OXpzBG92kflK7VvR4YBym
|
||||||
|
DUhqhmQ4qAe37Wr2vVob+Dsf39IuS+FWDNZSW6lrMQKBgQDnGVBv0Xv3+pb/NmqA
|
||||||
|
1sRJvhMtFaVkIKJuf1qK7SNzU5tCbNAfaJgQQVFNswnjpbS300T1ehNorsDeDi05
|
||||||
|
WqeWdRPY/Qz+19AJ1UiCMUku/SWWN21byUQU4yven6mJ6rgkKbAv4E4VtpcG3q8B
|
||||||
|
W/aIL1KAHvEFJ3rI21QD4A+NvQKBgQC8M1rlXu64kKbw4D5KormMFvjkoROsXwn/
|
||||||
|
eqN0wCN9avD7+LN/MUhqn7S0t0iQJRH+kaOjS6yl1v9JFI8bBLMQ1Uk1Mtpi4Mvl
|
||||||
|
AWtPLUYXxeP+zlS1ueBuDzRsNUGRqYM1MVlr7sko5gOAPQHHaDbNRYSqaskLtRR0
|
||||||
|
/BjItmDC0QKBgGCySOPgxXxnUBMNk9bBBnTMoX111zRkK1MM2rfSrcitrQNIQHVD
|
||||||
|
8Iysp/ZY+cRVK57XOb11DPX6WR0Q1X9wHTtpVZqvl2ZyqsvSgHppYPPWXInUO1/y
|
||||||
|
gRg0TcDjEa9xlQccomoF8uZG9j6boqJw9mDZXC3bxIGhmVC95ROSBzAJAoGBAJHz
|
||||||
|
3dUuV0IpZF4/+e8V3YHIOwPL657tIarQ6Dzd2WglbHhsun+0r62I57KSxaKMLTVY
|
||||||
|
qygzwtPmNZruZ8ETVu+CCUFJi9XM8jNKc3c27Dn5jUSJrWY1ndic0BHvB0e4x3mU
|
||||||
|
KP4sdDLUlvh3145WwtFUzXsAT6RVrWTAMVRPJCFRAoGBAMEW8V36c+XJuD9qDvg3
|
||||||
|
qG3uPaGS1IytkpSAtfSV+hXJ14N57L/oxPTVyrZKDgu0ic3KAHEJG/WN+SQPfaWT
|
||||||
|
zj8YnFFeSISRRo4Y1Q4Rg/Yer5fKVdkvGKPR9lCEhbxEBqZz4qSMUHGak1exjTeW
|
||||||
|
DapsPxEG0wEN8rMoNzYMNuc3
|
||||||
|
-----END PRIVATE KEY-----
|
||||||
185
pom.xml
Executable file
185
pom.xml
Executable file
@@ -0,0 +1,185 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
<parent>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-parent</artifactId>
|
||||||
|
<version>3.3.4</version>
|
||||||
|
<relativePath/> <!-- lookup parent from repository -->
|
||||||
|
</parent>
|
||||||
|
<groupId>nl.connected-it</groupId>
|
||||||
|
<artifactId>swiss-backend</artifactId>
|
||||||
|
<version>0.0.1-SNAPSHOT</version>
|
||||||
|
<name>swiss-backend</name>
|
||||||
|
<description>Swiss Backend</description>
|
||||||
|
<properties>
|
||||||
|
<java.version>21</java.version>
|
||||||
|
<maven.compiler.source>21</maven.compiler.source>
|
||||||
|
<maven.compiler.target>21</maven.compiler.target>
|
||||||
|
<mapstruct.version>1.6.0.RC1</mapstruct.version>
|
||||||
|
</properties>
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-actuator</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-data-jpa</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-security</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.auth0</groupId>
|
||||||
|
<artifactId>java-jwt</artifactId>
|
||||||
|
<version>4.4.0</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.fasterxml.jackson.datatype</groupId>
|
||||||
|
<artifactId>jackson-datatype-hibernate5-jakarta</artifactId>
|
||||||
|
<version>2.17.2</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.h2database</groupId>
|
||||||
|
<artifactId>h2</artifactId>
|
||||||
|
<scope>runtime</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-security</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-web</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-validation</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-devtools</artifactId>
|
||||||
|
<scope>runtime</scope>
|
||||||
|
<optional>true</optional>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.postgresql</groupId>
|
||||||
|
<artifactId>postgresql</artifactId>
|
||||||
|
<scope>runtime</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.flywaydb</groupId>
|
||||||
|
<artifactId>flyway-core</artifactId>
|
||||||
|
<version>10.18.0</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.flywaydb</groupId>
|
||||||
|
<artifactId>flyway-database-postgresql</artifactId>
|
||||||
|
<version>10.18.0</version>
|
||||||
|
<scope>runtime</scope>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-configuration-processor</artifactId>
|
||||||
|
<optional>true</optional>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.projectlombok</groupId>
|
||||||
|
<artifactId>lombok</artifactId>
|
||||||
|
<!-- <optional>true</optional>-->
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-test</artifactId>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.security</groupId>
|
||||||
|
<artifactId>spring-security-test</artifactId>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
<build>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.hibernate.orm.tooling</groupId>
|
||||||
|
<artifactId>hibernate-enhance-maven-plugin</artifactId>
|
||||||
|
<version>${hibernate.version}</version>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<id>enhance</id>
|
||||||
|
<goals>
|
||||||
|
<goal>enhance</goal>
|
||||||
|
</goals>
|
||||||
|
<configuration>
|
||||||
|
<enableLazyInitialization>true</enableLazyInitialization>
|
||||||
|
<enableDirtyTracking>true</enableDirtyTracking>
|
||||||
|
<enableAssociationManagement>true</enableAssociationManagement>
|
||||||
|
</configuration>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.graalvm.buildtools</groupId>
|
||||||
|
<artifactId>native-maven-plugin</artifactId>
|
||||||
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||||
|
<configuration>
|
||||||
|
<excludes>
|
||||||
|
<exclude>
|
||||||
|
<groupId>org.projectlombok</groupId>
|
||||||
|
<artifactId>lombok</artifactId>
|
||||||
|
</exclude>
|
||||||
|
</excludes>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-compiler-plugin</artifactId>
|
||||||
|
<version>3.13.0</version>
|
||||||
|
<configuration>
|
||||||
|
<source>21</source>
|
||||||
|
<target>21</target>
|
||||||
|
<annotationProcessorPaths>
|
||||||
|
<path>
|
||||||
|
<groupId>org.projectlombok</groupId>
|
||||||
|
<artifactId>lombok</artifactId>
|
||||||
|
<version>${lombok.version}</version>
|
||||||
|
</path>
|
||||||
|
<!--
|
||||||
|
<path>
|
||||||
|
<groupId>org.projectlombok</groupId>
|
||||||
|
<artifactId>lombok-mapstruct-binding</artifactId>
|
||||||
|
<version>0.2.0</version>
|
||||||
|
</path>
|
||||||
|
<path>
|
||||||
|
<groupId>org.mapstruct</groupId>
|
||||||
|
<artifactId>mapstruct-processor</artifactId>
|
||||||
|
<version>${mapstruct.version}</version>
|
||||||
|
</path>
|
||||||
|
-->
|
||||||
|
</annotationProcessorPaths>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.flywaydb</groupId>
|
||||||
|
<artifactId>flyway-maven-plugin</artifactId>
|
||||||
|
<version>10.18.0</version>
|
||||||
|
<configuration>
|
||||||
|
<url>jdbc:postgresql://localhost:5432/swiss?currentSchema=swiss</url>
|
||||||
|
<user>postgres</user>
|
||||||
|
<password>postgres</password>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
|
||||||
|
</build>
|
||||||
|
|
||||||
|
</project>
|
||||||
11
renovate.json
Normal file
11
renovate.json
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
{
|
||||||
|
"extends": [
|
||||||
|
"config:base"
|
||||||
|
],
|
||||||
|
"packageRules": [
|
||||||
|
{
|
||||||
|
"updateTypes": ["minor", "patch", "pin", "digest"],
|
||||||
|
"automerge": false
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
15
src/main/java/nl/connectedit/swiss/SwissApplication.java
Executable file
15
src/main/java/nl/connectedit/swiss/SwissApplication.java
Executable file
@@ -0,0 +1,15 @@
|
|||||||
|
package nl.connectedit.swiss;
|
||||||
|
|
||||||
|
import org.springframework.boot.SpringApplication;
|
||||||
|
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||||
|
import org.springframework.transaction.annotation.EnableTransactionManagement;
|
||||||
|
|
||||||
|
@SpringBootApplication
|
||||||
|
@EnableTransactionManagement
|
||||||
|
public class SwissApplication {
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
SpringApplication.run(SwissApplication.class, args);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,46 @@
|
|||||||
|
package nl.connectedit.swiss.authentication;
|
||||||
|
|
||||||
|
import jakarta.validation.Valid;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;
|
||||||
|
import org.springframework.context.annotation.Profile;
|
||||||
|
import org.springframework.http.HttpStatus;
|
||||||
|
import org.springframework.http.ResponseEntity;
|
||||||
|
import org.springframework.security.authentication.AuthenticationManager;
|
||||||
|
import org.springframework.security.authentication.BadCredentialsException;
|
||||||
|
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
||||||
|
import org.springframework.security.core.userdetails.UserDetails;
|
||||||
|
import org.springframework.web.bind.annotation.CrossOrigin;
|
||||||
|
import org.springframework.web.bind.annotation.PostMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestBody;
|
||||||
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
import org.springframework.web.server.ResponseStatusException;
|
||||||
|
|
||||||
|
@RestController
|
||||||
|
@ConditionalOnExpression("${security}")
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
@CrossOrigin
|
||||||
|
public class AuthenticationController {
|
||||||
|
|
||||||
|
private final JwtUserDetailsService jwtUserDetailsService;
|
||||||
|
|
||||||
|
private final AuthenticationManager authenticationManager;
|
||||||
|
|
||||||
|
private final JwtTokenService jwtTokenService;
|
||||||
|
|
||||||
|
@PostMapping("/authenticate")
|
||||||
|
public AuthenticationResponse authenticate(@RequestBody @Valid final AuthenticationRequest authenticationRequest) {
|
||||||
|
try {
|
||||||
|
authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(
|
||||||
|
authenticationRequest.getUsername(), authenticationRequest.getPassword()));
|
||||||
|
} catch (final BadCredentialsException ex) {
|
||||||
|
throw new ResponseStatusException(HttpStatus.UNAUTHORIZED);
|
||||||
|
}
|
||||||
|
|
||||||
|
final UserDetails userDetails = jwtUserDetailsService.loadUserByUsername(authenticationRequest.getUsername());
|
||||||
|
final AuthenticationResponse authenticationResponse = new AuthenticationResponse();
|
||||||
|
authenticationResponse.setAccessToken(jwtTokenService.generateToken(userDetails));
|
||||||
|
authenticationResponse.setUsername(authenticationRequest.getUsername());
|
||||||
|
return authenticationResponse;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
package nl.connectedit.swiss.authentication;
|
||||||
|
|
||||||
|
import jakarta.validation.constraints.NotNull;
|
||||||
|
import jakarta.validation.constraints.Size;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
public class AuthenticationRequest {
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
@Size(max = 255)
|
||||||
|
private String username;
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
@Size(max = 255)
|
||||||
|
private String password;
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
package nl.connectedit.swiss.authentication;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
public class AuthenticationResponse {
|
||||||
|
|
||||||
|
private String accessToken;
|
||||||
|
|
||||||
|
private String username;
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
package nl.connectedit.swiss.authentication;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
public class Client {
|
||||||
|
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
private String hash;
|
||||||
|
}
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
package nl.connectedit.swiss.authentication;
|
||||||
|
|
||||||
|
import org.springframework.stereotype.Repository;
|
||||||
|
import org.springframework.util.DigestUtils;
|
||||||
|
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
|
@Repository
|
||||||
|
public class ClientRepository {
|
||||||
|
|
||||||
|
private static final String hash = "$2a$12$FjsFqFTorg0sXCiSISFS3.xvSCzmAATIcA7wh5w8WtQ7eYZC.H4UW";
|
||||||
|
|
||||||
|
Optional<Client> findByLogin(String username) {
|
||||||
|
if (username.equals("bcholten")) {
|
||||||
|
var client = new Client();
|
||||||
|
client.setId(1L);
|
||||||
|
client.setHash(hash);
|
||||||
|
return Optional.of(client);
|
||||||
|
} else {
|
||||||
|
return Optional.empty();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,57 @@
|
|||||||
|
package nl.connectedit.swiss.authentication;
|
||||||
|
|
||||||
|
import jakarta.servlet.FilterChain;
|
||||||
|
import jakarta.servlet.ServletException;
|
||||||
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
|
import jakarta.servlet.http.HttpServletResponse;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;
|
||||||
|
import org.springframework.context.annotation.Profile;
|
||||||
|
import org.springframework.http.HttpHeaders;
|
||||||
|
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
||||||
|
import org.springframework.security.core.context.SecurityContextHolder;
|
||||||
|
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
import org.springframework.web.filter.OncePerRequestFilter;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
@ConditionalOnExpression("${security}")
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class JwtRequestFilter extends OncePerRequestFilter {
|
||||||
|
|
||||||
|
private final JwtTokenService jwtTokenService;
|
||||||
|
|
||||||
|
private final JwtUserDetailsService jwtUserDetailsService;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void doFilterInternal(final HttpServletRequest request, final HttpServletResponse response,
|
||||||
|
final FilterChain chain) throws IOException, ServletException {
|
||||||
|
// look for Bearer auth header
|
||||||
|
final String header = request.getHeader(HttpHeaders.AUTHORIZATION);
|
||||||
|
if (header == null || !header.startsWith("Bearer ")) {
|
||||||
|
chain.doFilter(request, response);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
final String token = header.substring(7);
|
||||||
|
final String username = jwtTokenService.validateTokenAndGetUsername(token);
|
||||||
|
if (username == null) {
|
||||||
|
// validation failed or token expired
|
||||||
|
chain.doFilter(request, response);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// set user details on spring security context
|
||||||
|
final JwtUserDetails userDetails = jwtUserDetailsService.loadUserByUsername(username);
|
||||||
|
final UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(
|
||||||
|
userDetails, null, userDetails.getAuthorities());
|
||||||
|
authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
|
||||||
|
SecurityContextHolder.getContext().setAuthentication(authentication);
|
||||||
|
|
||||||
|
// continue with authenticated user
|
||||||
|
chain.doFilter(request, response);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,62 @@
|
|||||||
|
package nl.connectedit.swiss.authentication;
|
||||||
|
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import org.springframework.security.authentication.AuthenticationManager;
|
||||||
|
import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration;
|
||||||
|
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||||
|
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
|
||||||
|
import org.springframework.security.config.http.SessionCreationPolicy;
|
||||||
|
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
|
||||||
|
import org.springframework.security.web.SecurityFilterChain;
|
||||||
|
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
|
||||||
|
import org.springframework.web.servlet.config.annotation.CorsRegistry;
|
||||||
|
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
|
||||||
|
|
||||||
|
import static org.springframework.security.config.Customizer.withDefaults;
|
||||||
|
|
||||||
|
@Configuration
|
||||||
|
@ConditionalOnExpression("${security}")
|
||||||
|
@EnableWebSecurity
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class JwtSecurityConfig {
|
||||||
|
|
||||||
|
private final JwtRequestFilter jwtRequestFilter;
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
BCryptPasswordEncoder passwordEncoder() {
|
||||||
|
return new BCryptPasswordEncoder();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public AuthenticationManager authenticationManager(
|
||||||
|
final AuthenticationConfiguration authenticationConfiguration) throws Exception {
|
||||||
|
return authenticationConfiguration.getAuthenticationManager();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public SecurityFilterChain configure(final HttpSecurity http) throws Exception {
|
||||||
|
return http.cors(withDefaults())
|
||||||
|
.csrf((csrf) -> csrf.disable())
|
||||||
|
.authorizeHttpRequests((authorize) -> authorize
|
||||||
|
.requestMatchers("/", "/authenticate", "/testdata").permitAll()
|
||||||
|
.anyRequest().hasAuthority(UserRoles.ROLE_USER))
|
||||||
|
.sessionManagement((session) -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
|
||||||
|
.addFilterBefore(jwtRequestFilter, UsernamePasswordAuthenticationFilter.class)
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public WebMvcConfigurer corsConfigurer() {
|
||||||
|
return new WebMvcConfigurer() {
|
||||||
|
@Override
|
||||||
|
public void addCorsMappings(CorsRegistry registry) {
|
||||||
|
registry.addMapping("/**")
|
||||||
|
.allowedMethods("HEAD", "GET", "PUT", "POST", "DELETE", "PATCH");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,51 @@
|
|||||||
|
package nl.connectedit.swiss.authentication;
|
||||||
|
|
||||||
|
import com.auth0.jwt.JWT;
|
||||||
|
import com.auth0.jwt.JWTVerifier;
|
||||||
|
import com.auth0.jwt.algorithms.Algorithm;
|
||||||
|
import com.auth0.jwt.exceptions.JWTVerificationException;
|
||||||
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;
|
||||||
|
import org.springframework.security.core.userdetails.UserDetails;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import java.security.interfaces.RSAPrivateKey;
|
||||||
|
import java.security.interfaces.RSAPublicKey;
|
||||||
|
import java.time.Duration;
|
||||||
|
import java.time.Instant;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
@ConditionalOnExpression("${security}")
|
||||||
|
public class JwtTokenService {
|
||||||
|
|
||||||
|
private static final Duration JWT_TOKEN_VALIDITY = Duration.ofDays(7);
|
||||||
|
|
||||||
|
private final Algorithm rsa256;
|
||||||
|
private final JWTVerifier verifier;
|
||||||
|
|
||||||
|
public JwtTokenService(@Value("classpath:certs/public.pem") final RSAPublicKey publicKey,
|
||||||
|
@Value("classpath:certs/private.pem") final RSAPrivateKey privateKey) {
|
||||||
|
this.rsa256 = Algorithm.RSA256(publicKey, privateKey);
|
||||||
|
this.verifier = JWT.require(this.rsa256).build();
|
||||||
|
}
|
||||||
|
|
||||||
|
public String generateToken(final UserDetails userDetails) {
|
||||||
|
final Instant now = Instant.now();
|
||||||
|
return JWT.create()
|
||||||
|
.withSubject(userDetails.getUsername())
|
||||||
|
.withIssuer("app")
|
||||||
|
.withIssuedAt(now)
|
||||||
|
.withExpiresAt(now.plusMillis(JWT_TOKEN_VALIDITY.toMillis()))
|
||||||
|
.sign(this.rsa256);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String validateTokenAndGetUsername(final String token) {
|
||||||
|
try {
|
||||||
|
return verifier.verify(token).getSubject();
|
||||||
|
} catch (final JWTVerificationException verificationEx) {
|
||||||
|
// log.warn("token invalid: {}", verificationEx.getMessage());
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
package nl.connectedit.swiss.authentication;
|
||||||
|
|
||||||
|
import org.springframework.security.core.GrantedAuthority;
|
||||||
|
import org.springframework.security.core.userdetails.User;
|
||||||
|
import org.springframework.security.core.userdetails.UserDetails;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
|
||||||
|
public class JwtUserDetails extends User {
|
||||||
|
|
||||||
|
public final Long id;
|
||||||
|
|
||||||
|
public JwtUserDetails(final Long id, final String username, final String hash,
|
||||||
|
final Collection<? extends GrantedAuthority> authorities) {
|
||||||
|
super(username, hash, authorities);
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
package nl.connectedit.swiss.authentication;
|
||||||
|
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import org.springframework.security.core.authority.SimpleGrantedAuthority;
|
||||||
|
import org.springframework.security.core.userdetails.UserDetails;
|
||||||
|
import org.springframework.security.core.userdetails.UserDetailsService;
|
||||||
|
import org.springframework.security.core.userdetails.UsernameNotFoundException;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class JwtUserDetailsService implements UserDetailsService {
|
||||||
|
|
||||||
|
private final ClientRepository clientRepository;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public JwtUserDetails loadUserByUsername(final String username) {
|
||||||
|
final Client client = clientRepository.findByLogin(username).orElseThrow(
|
||||||
|
() -> new UsernameNotFoundException("User " + username + " not found"));
|
||||||
|
final List<SimpleGrantedAuthority> roles = Collections.singletonList(new SimpleGrantedAuthority(UserRoles.ROLE_USER));
|
||||||
|
return new JwtUserDetails(client.getId(), username, client.getHash(), roles);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
package nl.connectedit.swiss.authentication;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public class LoginCredentialsDto {
|
||||||
|
|
||||||
|
private String username;
|
||||||
|
|
||||||
|
private String password;
|
||||||
|
|
||||||
|
private String ipAddres;
|
||||||
|
}
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
package nl.connectedit.swiss.authentication;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public class UserDto {
|
||||||
|
|
||||||
|
private String username;
|
||||||
|
|
||||||
|
private String token;
|
||||||
|
|
||||||
|
private String refreshToken;
|
||||||
|
|
||||||
|
private String ipAddress;
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
package nl.connectedit.swiss.authentication;
|
||||||
|
|
||||||
|
public class UserRoles {
|
||||||
|
|
||||||
|
public static final String USER = "USER";
|
||||||
|
public static final String ROLE_USER = "ROLE_" + USER;
|
||||||
|
|
||||||
|
}
|
||||||
25
src/main/java/nl/connectedit/swiss/config/CorsConfig.java
Normal file
25
src/main/java/nl/connectedit/swiss/config/CorsConfig.java
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
package nl.connectedit.swiss.config;
|
||||||
|
|
||||||
|
import jakarta.servlet.FilterChain;
|
||||||
|
import jakarta.servlet.ServletException;
|
||||||
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
|
import jakarta.servlet.http.HttpServletResponse;
|
||||||
|
import java.io.IOException;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
import org.springframework.web.filter.OncePerRequestFilter;
|
||||||
|
|
||||||
|
//@Component
|
||||||
|
public class CorsConfig extends OncePerRequestFilter {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void doFilterInternal(final HttpServletRequest request, final HttpServletResponse response,
|
||||||
|
final FilterChain filterChain) throws ServletException, IOException {
|
||||||
|
response.addHeader("Access-Control-Allow-Origin", "*");
|
||||||
|
response.addHeader("Access-Control-Allow-Methods", "GET, POST, DELETE, PUT, PATCH, HEAD");
|
||||||
|
response.addHeader("Access-Control-Allow-Headers", "Origin, Accept, X-Requested-With, Content-Type, Access-Control-Request-Method, Access-Control-Request-Headers");
|
||||||
|
response.addHeader("Access-Control-Expose-Headers", "Access-Control-Allow-Origin, Access-Control-Allow-Credentials");
|
||||||
|
response.addHeader("Access-Control-Allow-Credentials", "true");
|
||||||
|
response.addIntHeader("Access-Control-Max-Age", 10);
|
||||||
|
filterChain.doFilter(request, response);
|
||||||
|
}
|
||||||
|
}
|
||||||
14
src/main/java/nl/connectedit/swiss/config/JsonConfig.java
Normal file
14
src/main/java/nl/connectedit/swiss/config/JsonConfig.java
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
package nl.connectedit.swiss.config;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.databind.Module;
|
||||||
|
import com.fasterxml.jackson.datatype.hibernate5.jakarta.Hibernate5JakartaModule;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
|
||||||
|
@Configuration
|
||||||
|
public class JsonConfig {
|
||||||
|
@Bean
|
||||||
|
public Module hibernateModule() {
|
||||||
|
return new Hibernate5JakartaModule();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
package nl.connectedit.swiss.config;
|
||||||
|
|
||||||
|
import jakarta.servlet.DispatcherType;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||||
|
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
|
||||||
|
import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
|
||||||
|
import org.springframework.security.web.SecurityFilterChain;
|
||||||
|
|
||||||
|
//@Configuration
|
||||||
|
//@EnableWebSecurity
|
||||||
|
public class SecurityConfig {
|
||||||
|
|
||||||
|
// @Bean
|
||||||
|
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
|
||||||
|
http
|
||||||
|
.csrf(AbstractHttpConfigurer::disable)
|
||||||
|
.authorizeHttpRequests(auth -> auth.anyRequest().permitAll());
|
||||||
|
// .authorizeHttpRequests(request -> {
|
||||||
|
// request.dispatcherTypeMatchers(DispatcherType.FORWARD).permitAll();
|
||||||
|
// request.requestMatchers("/error").permitAll();
|
||||||
|
// });
|
||||||
|
return http.build();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,53 @@
|
|||||||
|
package nl.connectedit.swiss.controller;
|
||||||
|
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import nl.connectedit.swiss.domain.entity.Player;
|
||||||
|
import nl.connectedit.swiss.dto.PlayerDto;
|
||||||
|
import nl.connectedit.swiss.mapper.PlayerMapper;
|
||||||
|
import nl.connectedit.swiss.service.PlayerService;
|
||||||
|
import org.springframework.http.ResponseEntity;
|
||||||
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@RestController
|
||||||
|
@CrossOrigin
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class PlayerController {
|
||||||
|
|
||||||
|
private final PlayerService playerService;
|
||||||
|
|
||||||
|
private final PlayerMapper playerMapper;
|
||||||
|
|
||||||
|
@GetMapping("/players")
|
||||||
|
public ResponseEntity<List<PlayerDto>> getPlayers() {
|
||||||
|
return ResponseEntity.ok(playerService.findAllPlayers()
|
||||||
|
.stream()
|
||||||
|
.map(playerMapper::toDto)
|
||||||
|
.toList());
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping("/players/{id}")
|
||||||
|
public ResponseEntity<PlayerDto> getPlayer(@PathVariable Long id) {
|
||||||
|
return ResponseEntity.ok(playerMapper.toDto(playerService.findPlayerById(id)));
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostMapping("/players")
|
||||||
|
public ResponseEntity<PlayerDto> createPlayer(@RequestBody PlayerDto playerDto) {
|
||||||
|
Player player;
|
||||||
|
try {
|
||||||
|
player = playerMapper.toEntity(playerDto);
|
||||||
|
} catch (NullPointerException e) {
|
||||||
|
return ResponseEntity.badRequest().build();
|
||||||
|
}
|
||||||
|
return ResponseEntity.ok(playerMapper.toDto(playerService.savePlayer(player)));
|
||||||
|
}
|
||||||
|
|
||||||
|
@PutMapping("/players/{id}")
|
||||||
|
public ResponseEntity<PlayerDto> updatePlayer(@PathVariable("id") Long id, @RequestBody PlayerDto playerDto) {
|
||||||
|
var player = playerMapper.toEntity(playerDto);
|
||||||
|
player.setId(id);
|
||||||
|
return ResponseEntity.ok(playerMapper.toDto(playerService.savePlayer(player)));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,53 @@
|
|||||||
|
package nl.connectedit.swiss.controller;
|
||||||
|
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import nl.connectedit.swiss.domain.TournamentStatus;
|
||||||
|
import nl.connectedit.swiss.dto.TournamentRegistrationDto;
|
||||||
|
import nl.connectedit.swiss.mapper.TournamentPlayerRegistrationMapper;
|
||||||
|
import nl.connectedit.swiss.service.PlayerService;
|
||||||
|
import nl.connectedit.swiss.service.RegistrationService;
|
||||||
|
import nl.connectedit.swiss.service.TournamentService;
|
||||||
|
import org.springframework.http.HttpStatus;
|
||||||
|
import org.springframework.web.bind.annotation.CrossOrigin;
|
||||||
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
|
import org.springframework.web.bind.annotation.PathVariable;
|
||||||
|
import org.springframework.web.bind.annotation.PostMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestBody;
|
||||||
|
import org.springframework.web.bind.annotation.ResponseStatus;
|
||||||
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@RestController
|
||||||
|
@CrossOrigin
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class RegistrationController {
|
||||||
|
|
||||||
|
private final PlayerService playerService;
|
||||||
|
|
||||||
|
private final RegistrationService registrationService;
|
||||||
|
|
||||||
|
private final TournamentService tournamentService;
|
||||||
|
|
||||||
|
private final TournamentPlayerRegistrationMapper tournamentPlayerRegistrationMapper;
|
||||||
|
|
||||||
|
@GetMapping("/players/{playerId}/registrations")
|
||||||
|
public List<TournamentRegistrationDto> getRegistrationsForPlayer(@PathVariable Long playerId) {
|
||||||
|
var player = playerService.findPlayerById(playerId);
|
||||||
|
var tournaments = tournamentService.findAllTournaments();
|
||||||
|
|
||||||
|
return tournamentPlayerRegistrationMapper.mapToDto(tournaments, player);
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostMapping("/players/{playerId}/registrations/{tournamentId}")
|
||||||
|
@ResponseStatus(value = HttpStatus.NO_CONTENT)
|
||||||
|
public TournamentRegistrationDto registerTournamentRegistrations(@PathVariable Long playerId, @PathVariable Long tournamentId, @RequestBody TournamentRegistrationDto tournamentRegistrationDto) {
|
||||||
|
var player = playerService.findPlayerById(playerId);
|
||||||
|
var tournament = tournamentService.findTournamentById(tournamentId);
|
||||||
|
for (var eventRegistration : tournamentRegistrationDto.getEvents()) {
|
||||||
|
registrationService.updateOrAddRegistrations(eventRegistration, tournament, player);
|
||||||
|
}
|
||||||
|
|
||||||
|
return tournamentPlayerRegistrationMapper.mapToTournamentRegistrationDto(tournament, player);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
package nl.connectedit.swiss.controller;
|
||||||
|
|
||||||
|
import org.springframework.http.HttpHeaders;
|
||||||
|
import org.springframework.http.HttpStatus;
|
||||||
|
import org.springframework.http.ResponseEntity;
|
||||||
|
import org.springframework.security.access.AccessDeniedException;
|
||||||
|
import org.springframework.web.bind.annotation.ControllerAdvice;
|
||||||
|
import org.springframework.web.bind.annotation.ExceptionHandler;
|
||||||
|
import org.springframework.web.context.request.WebRequest;
|
||||||
|
import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler;
|
||||||
|
|
||||||
|
//@ControllerAdvice
|
||||||
|
public class RestResponseEntityExceptionHandler
|
||||||
|
extends ResponseEntityExceptionHandler {
|
||||||
|
|
||||||
|
@ExceptionHandler({AccessDeniedException.class})
|
||||||
|
public ResponseEntity<Object> handleAccessDeniedException(
|
||||||
|
Exception ex, WebRequest request) {
|
||||||
|
return new ResponseEntity<Object>(ex.getMessage(), new HttpHeaders(), HttpStatus.FORBIDDEN);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,507 @@
|
|||||||
|
package nl.connectedit.swiss.controller;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
|
import jakarta.annotation.PostConstruct;
|
||||||
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
|
import jakarta.transaction.Transactional;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import lombok.SneakyThrows;
|
||||||
|
import nl.connectedit.swiss.domain.*;
|
||||||
|
import nl.connectedit.swiss.domain.entity.Player;
|
||||||
|
import nl.connectedit.swiss.domain.entity.Registration;
|
||||||
|
import nl.connectedit.swiss.domain.entity.Tournament;
|
||||||
|
import nl.connectedit.swiss.domain.entity.TournamentPlayer;
|
||||||
|
import nl.connectedit.swiss.dto.*;
|
||||||
|
import nl.connectedit.swiss.service.*;
|
||||||
|
import org.springframework.boot.web.client.RestTemplateBuilder;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.http.HttpEntity;
|
||||||
|
import org.springframework.http.HttpHeaders;
|
||||||
|
import org.springframework.http.HttpMethod;
|
||||||
|
import org.springframework.web.bind.annotation.CrossOrigin;
|
||||||
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestHeader;
|
||||||
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
import org.springframework.web.client.RestTemplate;
|
||||||
|
|
||||||
|
import java.net.URI;
|
||||||
|
import java.net.http.HttpClient;
|
||||||
|
import java.net.http.HttpRequest;
|
||||||
|
import java.net.http.HttpResponse;
|
||||||
|
import java.time.LocalDate;
|
||||||
|
import java.time.Month;
|
||||||
|
import java.time.format.DateTimeFormatter;
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.concurrent.ThreadLocalRandom;
|
||||||
|
|
||||||
|
import static nl.connectedit.swiss.domain.PlayerStrength.*;
|
||||||
|
|
||||||
|
@RestController
|
||||||
|
@CrossOrigin
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class TestController {
|
||||||
|
|
||||||
|
private final TournamentService tournamentService;
|
||||||
|
|
||||||
|
private final PlayerService playerService;
|
||||||
|
|
||||||
|
private final TournamentDivideService tournamentDivideService;
|
||||||
|
private final TournamentDrawService tournamentDrawService;
|
||||||
|
private final TournamentPlayService tournamentPlayService;
|
||||||
|
|
||||||
|
private final ObjectMapper objectMapper;
|
||||||
|
private final RestTemplateBuilder restTemplateBuilder;
|
||||||
|
private RestTemplate restTemplate;
|
||||||
|
|
||||||
|
private final PlayerController playerController;
|
||||||
|
|
||||||
|
private String authorizationHeader;
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public RestTemplate restTemplate(RestTemplateBuilder builder) {
|
||||||
|
return builder.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping("/testdata")
|
||||||
|
// @PostConstruct
|
||||||
|
// @Transactional
|
||||||
|
public void init(@RequestHeader(name = "Authorization", required = false) String authorizationHeader) {
|
||||||
|
this.authorizationHeader = authorizationHeader;
|
||||||
|
|
||||||
|
restTemplate = restTemplateBuilder.build();
|
||||||
|
|
||||||
|
var tournament = createTournament();
|
||||||
|
|
||||||
|
getMales().forEach(player -> savePlayer(player, Sex.M));
|
||||||
|
getFemales().forEach(player -> savePlayer(player, Sex.V));
|
||||||
|
|
||||||
|
registerForSingles(tournament);
|
||||||
|
registerForDoubles(tournament);
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("DataFlowIssue")
|
||||||
|
private List<PlayerDto> getPlayers() {
|
||||||
|
var headers = new HttpHeaders();
|
||||||
|
headers.add("Authorization", authorizationHeader);
|
||||||
|
var entity = new HttpEntity<>(headers);
|
||||||
|
|
||||||
|
// return Arrays.asList(restTemplate.getForEntity("http://localhost:8080/players", PlayerDto[].class).getBody());
|
||||||
|
return Arrays.asList(restTemplate.exchange("http://localhost:8080/players", HttpMethod.GET, entity, PlayerDto[].class).getBody());
|
||||||
|
}
|
||||||
|
|
||||||
|
private void registerForSingles(TournamentDto tournament) {
|
||||||
|
var eventIdHE = tournament.getEvents().stream().filter(event -> event.getType().equals("HE")).findFirst().get().getId();
|
||||||
|
var eventIdDE = tournament.getEvents().stream().filter(event -> event.getType().equals("DE")).findFirst().get().getId();
|
||||||
|
|
||||||
|
for (var player : getPlayers()) {
|
||||||
|
var tournamentRegistrationDto = new TournamentRegistrationDto();
|
||||||
|
tournamentRegistrationDto.setId(tournament.getId());
|
||||||
|
var eventRegistrationDto = new EventRegistrationDto();
|
||||||
|
eventRegistrationDto.setId(player.getSex().equals("M") ? eventIdHE : eventIdDE);
|
||||||
|
eventRegistrationDto.setRegistered(true);
|
||||||
|
eventRegistrationDto.setPlayer(player.getId());
|
||||||
|
eventRegistrationDto.setType(player.getSex().equals("M") ? "HE" : "DE");
|
||||||
|
tournamentRegistrationDto.setEvents(List.of(eventRegistrationDto));
|
||||||
|
|
||||||
|
var headers = new HttpHeaders();
|
||||||
|
headers.add("Authorization", authorizationHeader);
|
||||||
|
var entity = new HttpEntity<>(tournamentRegistrationDto, headers);
|
||||||
|
restTemplate.postForObject("http://localhost:8080/players/%d/registrations/%d".formatted(player.getId(), tournament.getId()), entity, TournamentRegistrationDto.class);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void registerForDoubles(TournamentDto tournament) {
|
||||||
|
var males = getPlayers().stream().filter(p -> p.getSex().equals("M")).toArray(PlayerDto[]::new);
|
||||||
|
var females = getPlayers().stream().filter(p -> p.getSex().equals("V")).toArray(PlayerDto[]::new);
|
||||||
|
|
||||||
|
for (int i = 0; i <= 6; i++) {
|
||||||
|
registerForDoubles(tournament, males[i * 2], males[i * 2 + 1]);
|
||||||
|
registerForDoubles(tournament, males[i * 2 + 1], males[i * 2]);
|
||||||
|
}
|
||||||
|
for (int i = 0; i <= 8; i++) {
|
||||||
|
registerForDoubles(tournament, females[i * 2], females[i * 2 + 1]);
|
||||||
|
registerForDoubles(tournament, females[i * 2 + 1], females[i * 2]);
|
||||||
|
}
|
||||||
|
for (int i = 18; i <= 29; i++) {
|
||||||
|
registerForDoubles(tournament, males[i], females[i]);
|
||||||
|
registerForDoubles(tournament, females[i], males[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private void registerForDoubles(TournamentDto tournament, PlayerDto player, PlayerDto partner) {
|
||||||
|
var eventType = player.getSex().equals(partner.getSex()) ? (player.getSex().equals("M") ? "HD" : "DD") : "GD";
|
||||||
|
|
||||||
|
var eventId = tournament.getEvents().stream().filter(event -> event.getType().equals(eventType)).findFirst().get().getId();
|
||||||
|
|
||||||
|
// for (var player : getPlayers()) {
|
||||||
|
var tournamentRegistrationDto = new TournamentRegistrationDto();
|
||||||
|
tournamentRegistrationDto.setId(tournament.getId());
|
||||||
|
var eventRegistrationDto = new EventRegistrationDto();
|
||||||
|
eventRegistrationDto.setId(eventId);
|
||||||
|
eventRegistrationDto.setRegistered(true);
|
||||||
|
eventRegistrationDto.setPlayer(player.getId());
|
||||||
|
eventRegistrationDto.setPartner(partner.getId());
|
||||||
|
eventRegistrationDto.setType(eventType);
|
||||||
|
tournamentRegistrationDto.setEvents(List.of(eventRegistrationDto));
|
||||||
|
|
||||||
|
var headers = new HttpHeaders();
|
||||||
|
headers.add("Authorization", authorizationHeader);
|
||||||
|
var entity = new HttpEntity<>(tournamentRegistrationDto, headers);
|
||||||
|
restTemplate.postForObject("http://localhost:8080/players/%d/registrations/%d".formatted(player.getId(), tournament.getId()), entity, TournamentRegistrationDto.class);
|
||||||
|
// }
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private TournamentDto createTournament() {
|
||||||
|
var headers = new HttpHeaders();
|
||||||
|
headers.add("Authorization", authorizationHeader);
|
||||||
|
var entity = new HttpEntity<>(getTournament(), headers);
|
||||||
|
return restTemplate.postForObject("http://localhost:8080/tournaments", entity, TournamentDto.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
private TournamentDto getTournament() {
|
||||||
|
var tournamentDto = new TournamentDto();
|
||||||
|
tournamentDto.setName("Testtoernooi");
|
||||||
|
tournamentDto.setDate("14-12-2024");
|
||||||
|
tournamentDto.setStatus("UPCOMING");
|
||||||
|
tournamentDto.setMaxEvents(2L);
|
||||||
|
tournamentDto.setCourts(9L);
|
||||||
|
tournamentDto.setCostsPerEvent(List.of(6f, 10f, 0f));
|
||||||
|
return tournamentDto;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void savePlayer(String firstName, Sex sex) {
|
||||||
|
Random random = new Random();
|
||||||
|
|
||||||
|
String[] lastNames = {
|
||||||
|
"Meedendorp", "Holstege", "Goedhart", "Zijlma", "Duursma", "Keizer", "Verschoor",
|
||||||
|
"Mulder", "Koers", "Duindam", "Castelein", "Coemans", "Huijbers", "Kelder",
|
||||||
|
"Stein", "Rakhorst", "Brugman", "Seinen", "Mayer", "Gijsman", "Kingma",
|
||||||
|
"Jansen", "Westerik", "Brehler", "Ebbers", "Lensink", "Lups", "Verboom"
|
||||||
|
};
|
||||||
|
|
||||||
|
String[] clubs = {
|
||||||
|
"BC Holten", "BC Reflex", "ZBC", "WSV Apeldoorn", "BC IJsselstad", "Flits", "ELO United", "BC Kwiek"
|
||||||
|
};
|
||||||
|
|
||||||
|
var playerDto = new PlayerDto();
|
||||||
|
playerDto.setFirstName(firstName);
|
||||||
|
playerDto.setLastName(lastNames[random.nextInt(lastNames.length)]);
|
||||||
|
playerDto.setClub(clubs[random.nextInt(clubs.length)]);
|
||||||
|
playerDto.setSex(sex.name());
|
||||||
|
var birthday = randomDate(LocalDate.of(1950, 1, 1), LocalDate.of(2010, 1, 1)).format(DateTimeFormatter.ofPattern("dd-MM-yyyy"));
|
||||||
|
playerDto.setBirthday(birthday);
|
||||||
|
playerDto.setPhoneNumber("0612345678");
|
||||||
|
playerDto.setEmail("aaaa@bbb.cc");
|
||||||
|
playerDto.setStrength(getRandomStrength().name());
|
||||||
|
|
||||||
|
var headers = new HttpHeaders();
|
||||||
|
headers.add("Authorization", authorizationHeader);
|
||||||
|
var entity = new HttpEntity<>(playerDto, headers);
|
||||||
|
restTemplate.postForObject("http://localhost:8080/players", entity, PlayerDto.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<String> getMales() {
|
||||||
|
return List.of("Michel", "Eric", "Leon", "Luuk", "Jeffrey", "Jason", "Oleg", "Gerjan", "Gerard", "Henk",
|
||||||
|
"Peter", "Gerrit", "Wilco", "Guido", "Sander", "Roy", "Yafiq", "Martijn", "Dick", "Willem", "Layo",
|
||||||
|
"Thomas", "Gerben", "Bert", "Bart", "Nico", "Jan", "Diederik", "Gert", "Dennis", "Pieter");
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<String> getFemales() {
|
||||||
|
return List.of("Amber", "Lisa", "Vanja", "Evelien", "Daphne", "Willemijn", "Miranda", "Inge", "Esmee",
|
||||||
|
"Joanne", "Laura", "Nienke", "Patty", "Rosan", "Vera", "Hedwig", "Lois", "Liedewij", "Gera", "Carolien",
|
||||||
|
"Anne", "Dominique", "Linda", "Esther", "Marilyn", "Ilse", "Emily", "Eva", "Kitty", "Floor", "Tess", "Fenna");
|
||||||
|
}
|
||||||
|
|
||||||
|
private PlayerStrength getRandomStrength() {
|
||||||
|
var random = new Random().nextInt(0, 12);
|
||||||
|
|
||||||
|
return switch(random) {
|
||||||
|
case 0 -> D5;
|
||||||
|
case 1, 2 -> D6;
|
||||||
|
case 3, 4, 5 -> D7;
|
||||||
|
case 6, 7 -> D8;
|
||||||
|
case 8, 9 -> D9;
|
||||||
|
default -> DR;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public static LocalDate randomDate(LocalDate startInclusive, LocalDate endExclusive) {
|
||||||
|
long startEpochDay = startInclusive.toEpochDay();
|
||||||
|
long endEpochDay = endExclusive.toEpochDay();
|
||||||
|
long randomDay = ThreadLocalRandom
|
||||||
|
.current()
|
||||||
|
.nextLong(startEpochDay, endEpochDay);
|
||||||
|
|
||||||
|
return LocalDate.ofEpochDay(randomDay);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
private void deRest() {
|
||||||
|
|
||||||
|
var malePlayers = List.of(
|
||||||
|
savePlayer("Michel", Sex.M),
|
||||||
|
savePlayer("Eric", Sex.M),
|
||||||
|
savePlayer("Leon", Sex.M),
|
||||||
|
savePlayer("Luuk", Sex.M),
|
||||||
|
savePlayer("Jeffrey", Sex.M),
|
||||||
|
savePlayer("Jason", Sex.M),
|
||||||
|
savePlayer("Oleg", Sex.M),
|
||||||
|
savePlayer("Gerjan", Sex.M),
|
||||||
|
savePlayer("Gerard", Sex.M),
|
||||||
|
savePlayer("Henk", Sex.M),
|
||||||
|
savePlayer("Peter", Sex.M),
|
||||||
|
savePlayer("Gerrit", Sex.M),
|
||||||
|
savePlayer("Wilco", Sex.M),
|
||||||
|
savePlayer("Guido", Sex.M),
|
||||||
|
savePlayer("Sander", Sex.M),
|
||||||
|
savePlayer("Roy", Sex.M),
|
||||||
|
|
||||||
|
savePlayer("Yafiq", Sex.M),
|
||||||
|
savePlayer("Martijn", Sex.M),
|
||||||
|
savePlayer("Dick", Sex.M),
|
||||||
|
savePlayer("Willem", Sex.M),
|
||||||
|
savePlayer("Layo", Sex.M),
|
||||||
|
savePlayer("Thomas", Sex.M),
|
||||||
|
savePlayer("Gerben", Sex.M),
|
||||||
|
savePlayer("Bert", Sex.M),
|
||||||
|
savePlayer("Bart", Sex.M),
|
||||||
|
savePlayer("Nico", Sex.M),
|
||||||
|
savePlayer("Jan", Sex.M),
|
||||||
|
savePlayer("Diederik", Sex.M),
|
||||||
|
savePlayer("Gert", Sex.M),
|
||||||
|
savePlayer("Dennis", Sex.M),
|
||||||
|
savePlayer("Pieter", Sex.M)
|
||||||
|
);
|
||||||
|
|
||||||
|
var femalePlayers = List.of(
|
||||||
|
savePlayer("Amber", Sex.V),
|
||||||
|
savePlayer("Lisa", Sex.V),
|
||||||
|
savePlayer("Vanja", Sex.V),
|
||||||
|
savePlayer("Evelien", Sex.V),
|
||||||
|
savePlayer("Daphne", Sex.V),
|
||||||
|
savePlayer("Willemijn", Sex.V),
|
||||||
|
savePlayer("Miranda", Sex.V),
|
||||||
|
savePlayer("Inge", Sex.V),
|
||||||
|
savePlayer("Esmee", Sex.V),
|
||||||
|
savePlayer("Joanne", Sex.V),
|
||||||
|
savePlayer("Laura", Sex.V),
|
||||||
|
savePlayer("Nienke", Sex.V),
|
||||||
|
savePlayer("Patty", Sex.V),
|
||||||
|
savePlayer("Rosan", Sex.V),
|
||||||
|
savePlayer("Vera", Sex.V),
|
||||||
|
savePlayer("Hedwig", Sex.V),
|
||||||
|
|
||||||
|
savePlayer("Lois", Sex.V),
|
||||||
|
savePlayer("Liedewij", Sex.V),
|
||||||
|
savePlayer("Gera", Sex.V),
|
||||||
|
savePlayer("Carolien", Sex.V),
|
||||||
|
savePlayer("Anne", Sex.V),
|
||||||
|
savePlayer("Dominique", Sex.V),
|
||||||
|
savePlayer("Linda", Sex.V),
|
||||||
|
savePlayer("Esther", Sex.V),
|
||||||
|
savePlayer("Marilyn", Sex.V),
|
||||||
|
savePlayer("Ilse", Sex.V),
|
||||||
|
savePlayer("Emily", Sex.V),
|
||||||
|
savePlayer("Eva", Sex.V),
|
||||||
|
savePlayer("Kitty", Sex.V),
|
||||||
|
savePlayer("Floor", Sex.V),
|
||||||
|
savePlayer("Tess", Sex.V),
|
||||||
|
savePlayer("Fenna", Sex.V)
|
||||||
|
);
|
||||||
|
|
||||||
|
malePlayers.forEach(player -> registerForSingles(tournamentId, player));
|
||||||
|
femalePlayers.forEach(player -> registerForSingles(tournamentId, player));
|
||||||
|
|
||||||
|
malePlayers = new ArrayList<>(malePlayers);
|
||||||
|
malePlayers.add(savePlayer("Rolf", Sex.M));
|
||||||
|
|
||||||
|
for (var i = 0; i < 14; i += 2) {
|
||||||
|
registerForDoubles(tournamentId, malePlayers.get(i), malePlayers.get(i + 1));
|
||||||
|
registerForDoubles(tournamentId, malePlayers.get(i + 1), malePlayers.get(i));
|
||||||
|
}
|
||||||
|
for (var i = 0; i < 16; i += 2) {
|
||||||
|
registerForDoubles(tournamentId, femalePlayers.get(i), femalePlayers.get(i + 1));
|
||||||
|
registerForDoubles(tournamentId, femalePlayers.get(i + 1), femalePlayers.get(i));
|
||||||
|
}
|
||||||
|
for (var i = 16; i < malePlayers.size(); i++) {
|
||||||
|
registerForDoubles(tournamentId, malePlayers.get(i), femalePlayers.get(i));
|
||||||
|
registerForDoubles(tournamentId, femalePlayers.get(i), malePlayers.get(i));
|
||||||
|
}
|
||||||
|
|
||||||
|
divideTournament(tournamentId);
|
||||||
|
drawTournament(tournamentId);
|
||||||
|
// startRound(2L, 1L);
|
||||||
|
// playRound(2L, 0, 0);
|
||||||
|
|
||||||
|
startRound(tournamentId, 2L);
|
||||||
|
playRound(tournamentId, 1, 0);
|
||||||
|
|
||||||
|
|
||||||
|
finishRound(tournamentId, 2L);
|
||||||
|
newRound(tournamentId, 2L);
|
||||||
|
|
||||||
|
startRound(tournamentId, 8L);
|
||||||
|
playRound(tournamentId, 1, 1);
|
||||||
|
|
||||||
|
if (1==1) return;
|
||||||
|
|
||||||
|
finishRound(tournamentId, 8L);
|
||||||
|
newRound(tournamentId, 2L);
|
||||||
|
|
||||||
|
startRound(tournamentId, 9L);
|
||||||
|
playRound(tournamentId, 1, 2);
|
||||||
|
finishRound(tournamentId, 9L);
|
||||||
|
newRound(tournamentId, 2L);
|
||||||
|
|
||||||
|
startRound(tournamentId, 10L);
|
||||||
|
playRound(tournamentId, 1, 3);
|
||||||
|
// finishRound(2L, 10L);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private void addToTournament(Long tournamentId, Player player) {
|
||||||
|
var tournament = tournamentService.findTournamentById(tournamentId);
|
||||||
|
TournamentPlayer tournamentPlayer = new TournamentPlayer();
|
||||||
|
tournamentPlayer.setTournament(tournament);
|
||||||
|
tournamentPlayer.setPlayer(player);
|
||||||
|
tournament.getTournamentPlayers().add(tournamentPlayer);
|
||||||
|
tournamentService.saveTournament(tournament);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void divideTournament(Long tournamentId) {
|
||||||
|
var tournament = tournamentService.findTournamentById(tournamentId);
|
||||||
|
tournamentDivideService.divide(tournament);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void drawTournament(Long tournamentId) {
|
||||||
|
var tournament = tournamentService.findTournamentById(tournamentId);
|
||||||
|
tournamentDrawService.draw(tournament);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void playRound(long tournamentId, int group, int round) {
|
||||||
|
var tournament = tournamentService.findTournamentById(tournamentId);
|
||||||
|
for (var match : tournament.getEvents().get(0).getGroups().get(group).getRounds().get(round).getMatches()) {
|
||||||
|
tournamentPlayService.startMatch(tournament, match.getId(), 1L);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (var match : tournament.getEvents().get(0).getGroups().get(group).getRounds().get(round).getMatches()) {
|
||||||
|
tournament = tournamentService.findTournamentById(tournamentId);
|
||||||
|
var resultDto = new ResultDto();
|
||||||
|
resultDto.getGames().add(getRandomGame());
|
||||||
|
resultDto.getGames().add(getRandomGame());
|
||||||
|
resultDto.setMatchId(match.getId());
|
||||||
|
tournamentPlayService.saveResult(tournament, match.getId(), resultDto);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private GameDto getRandomGame() {
|
||||||
|
Random random = new Random();
|
||||||
|
|
||||||
|
var gameDto = new GameDto();
|
||||||
|
gameDto.setScore1(21L);
|
||||||
|
gameDto.setScore2(random.nextLong(19));
|
||||||
|
|
||||||
|
return gameDto;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void finishRound(long tournamentId, long roundId) {
|
||||||
|
var tournament = tournamentService.findTournamentById(tournamentId);
|
||||||
|
tournamentPlayService.finishRound(tournament, roundId);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void newRound(long tournamentId, long groupId) {
|
||||||
|
var tournament = tournamentService.findTournamentById(tournamentId);
|
||||||
|
tournamentPlayService.newRound(tournament, groupId);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void startRound(long tournamentId, long roundId) {
|
||||||
|
var tournament = tournamentService.findTournamentById(tournamentId);
|
||||||
|
tournamentPlayService.startRound(tournament, roundId);
|
||||||
|
}
|
||||||
|
|
||||||
|
// private void saveTournament1() {
|
||||||
|
// var tournament = new Tournament();
|
||||||
|
// tournament.setName("Zwitsers Laddersysteem BC Holten 2023");
|
||||||
|
// tournament.setDate(LocalDate.of(2023, Month.DECEMBER, 12));
|
||||||
|
// tournament.setStatus(TournamentStatus.CLOSED);
|
||||||
|
// tournamentService.saveTournament(tournament);
|
||||||
|
// }
|
||||||
|
|
||||||
|
|
||||||
|
private Long saveTournament() {
|
||||||
|
var tournament = new Tournament();
|
||||||
|
tournament.setName("Testtoernooi");
|
||||||
|
tournament.setDate(LocalDate.of(2024, Month.DECEMBER, 14));
|
||||||
|
tournament.setStatus(TournamentStatus.UPCOMING);
|
||||||
|
tournament.setMaxEvents(2L);
|
||||||
|
tournament.setCourts(9L);
|
||||||
|
tournament.setCostsPerEvent(List.of(6f, 10f));
|
||||||
|
tournamentService.saveTournament(tournament);
|
||||||
|
return tournament.getId();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void registerForSingles(Long tournamentId, Player player) {
|
||||||
|
var tournament = tournamentService.findTournamentById(tournamentId);
|
||||||
|
var registration = new Registration();
|
||||||
|
registration.setPlayer(player);
|
||||||
|
var event = tournament.getEventByType(player.getSex() == Sex.M ? EventType.HE : EventType.DE);
|
||||||
|
registration.setPartner(null);
|
||||||
|
registration.setTournament(tournament);
|
||||||
|
registration.setEvent(event);
|
||||||
|
if (event.getRegistrations() == null) event.setRegistrations(new ArrayList<>());
|
||||||
|
event.getRegistrations().add(registration);
|
||||||
|
// player.getRegistrations().add(registration);
|
||||||
|
tournamentService.saveTournament(tournament);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void registerForDoubles(Long tournamentId, Player player, Player partner) {
|
||||||
|
var tournament = tournamentService.findTournamentById(tournamentId);
|
||||||
|
var registration = new Registration();
|
||||||
|
registration.setPlayer(player);
|
||||||
|
registration.setPartner(partner);
|
||||||
|
var event = tournament.getEventByType(
|
||||||
|
player.getSex() == partner.getSex() ?
|
||||||
|
(player.getSex() == Sex.M ? EventType.HD : EventType.DD) : EventType.GD);
|
||||||
|
registration.setTournament(tournament);
|
||||||
|
registration.setEvent(event);
|
||||||
|
event.getRegistrations().add(registration);
|
||||||
|
// player.getRegistrations().add(registration);
|
||||||
|
tournamentService.saveTournament(tournament);
|
||||||
|
}
|
||||||
|
|
||||||
|
// private Player savePlayer(String firstName, Sex sex) {
|
||||||
|
// Random random = new Random();
|
||||||
|
//
|
||||||
|
// String[] lastNames = {
|
||||||
|
// "Meedendorp", "Holstege", "Goedhart", "Zijlma", "Duursma", "Keizer", "Verschoor",
|
||||||
|
// "Mulder", "Koers", "Duindam", "Castelein", "Coemans", "Huijbers", "Kelder",
|
||||||
|
// "Stein", "Rakhorst", "Brugman", "Seinen", "Mayer", "Gijsman", "Kingma",
|
||||||
|
// "Jansen", "Westerik", "Brehler", "Ebbers", "Lensink", "Lups", "Verboom"
|
||||||
|
// };
|
||||||
|
//
|
||||||
|
// String[] clubs = {
|
||||||
|
// "BC Holten", "BC Reflex", "ZBC", "WSV Apeldoorn", "BC IJsselstad", "Flits", "ELO United", "BC Kwiek"
|
||||||
|
// };
|
||||||
|
//
|
||||||
|
// var player = new Player();
|
||||||
|
// player.setFirstName(firstName);
|
||||||
|
// player.setLastName(lastNames[random.nextInt(lastNames.length)]);
|
||||||
|
// player.setClub(clubs[random.nextInt(clubs.length)]);
|
||||||
|
// player.setSex(sex);
|
||||||
|
// player.setBirthday(randomDate(LocalDate.of(1950, 1, 1), LocalDate.of(2010, 1, 1)));
|
||||||
|
// player.setPhoneNumber("0612345678");
|
||||||
|
// player.setEmail("aaaa@bbb.cc");
|
||||||
|
// player.setStrength(getRandomStrength());
|
||||||
|
//
|
||||||
|
// playerService.savePlayer(player);
|
||||||
|
// return player;
|
||||||
|
// }
|
||||||
|
*/
|
||||||
|
|
||||||
|
}
|
||||||
184
src/main/java/nl/connectedit/swiss/controller/TournamentController.java
Executable file
184
src/main/java/nl/connectedit/swiss/controller/TournamentController.java
Executable file
@@ -0,0 +1,184 @@
|
|||||||
|
package nl.connectedit.swiss.controller;
|
||||||
|
|
||||||
|
import jakarta.transaction.Transactional;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import nl.connectedit.swiss.domain.TournamentStatus;
|
||||||
|
import nl.connectedit.swiss.domain.entity.Tournament;
|
||||||
|
import nl.connectedit.swiss.dto.ResultDto;
|
||||||
|
import nl.connectedit.swiss.dto.TournamentDto;
|
||||||
|
import nl.connectedit.swiss.dto.TournamentValidationDto;
|
||||||
|
import nl.connectedit.swiss.mapper.TournamentMapper;
|
||||||
|
import nl.connectedit.swiss.mapper.TournamentValidationMapper;
|
||||||
|
import nl.connectedit.swiss.service.*;
|
||||||
|
import org.springframework.http.ResponseEntity;
|
||||||
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
@RestController
|
||||||
|
@CrossOrigin
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class TournamentController {
|
||||||
|
|
||||||
|
private final TournamentService tournamentService;
|
||||||
|
|
||||||
|
private final TournamentMapper tournamentMapper;
|
||||||
|
|
||||||
|
private final TournamentValidationService tournamentValidationService;
|
||||||
|
|
||||||
|
private final TournamentValidationMapper tournamentValidationMapper;
|
||||||
|
|
||||||
|
private final TournamentDivideService tournamentDivideService;
|
||||||
|
|
||||||
|
private final TournamentDrawService tournamentDrawService;
|
||||||
|
|
||||||
|
private final TournamentPlayService tournamentPlayService;
|
||||||
|
|
||||||
|
@GetMapping("/tournaments")
|
||||||
|
public ResponseEntity<List<TournamentDto>> getTournaments(@RequestParam(value = "status", required = false) TournamentStatus status) {
|
||||||
|
List<Tournament> tournaments;
|
||||||
|
|
||||||
|
if (Objects.nonNull(status)) {
|
||||||
|
tournaments = tournamentService.findAllTournamentsWithStatus(status);
|
||||||
|
} else {
|
||||||
|
tournaments = tournamentService.findAllTournaments();
|
||||||
|
}
|
||||||
|
|
||||||
|
return ResponseEntity.ok(tournaments
|
||||||
|
.stream()
|
||||||
|
.map(tournamentMapper::toDto)
|
||||||
|
.toList());
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping("/tournaments/{id}")
|
||||||
|
@Transactional
|
||||||
|
public ResponseEntity<TournamentDto> getTournament(@PathVariable Long id) {
|
||||||
|
var tournament = tournamentService.findTournamentById(id);
|
||||||
|
|
||||||
|
if (tournament == null) {
|
||||||
|
return ResponseEntity.notFound().build();
|
||||||
|
}
|
||||||
|
|
||||||
|
return ResponseEntity.ok(tournamentMapper.toDto(tournament));
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostMapping("/tournaments")
|
||||||
|
public ResponseEntity<TournamentDto> createTournament(@RequestBody TournamentDto tournamentDto) {
|
||||||
|
var tournament = tournamentMapper.toEntity(tournamentDto);
|
||||||
|
return ResponseEntity.ok(tournamentMapper.toDto(tournamentService.saveTournament(tournament)));
|
||||||
|
}
|
||||||
|
|
||||||
|
@PutMapping("/tournaments/{id}")
|
||||||
|
public ResponseEntity<TournamentDto> updateTournament(@PathVariable Long id, @RequestBody TournamentDto tournamentDto) {
|
||||||
|
var newTournament = tournamentMapper.toEntity(tournamentDto);
|
||||||
|
var tournament = tournamentService.updateTournament(id, newTournament);
|
||||||
|
|
||||||
|
return ResponseEntity.ok(tournamentMapper.toDto(tournament));
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping("/tournaments/{id}/validate")
|
||||||
|
public ResponseEntity<TournamentValidationDto> validateTournament(@PathVariable Long id) {
|
||||||
|
var tournament = tournamentService.findTournamentById(id);
|
||||||
|
|
||||||
|
var tournamentValidation = tournamentValidationService.validate(tournament);
|
||||||
|
|
||||||
|
return ResponseEntity.ok(tournamentValidationMapper.toDto(tournamentValidation));
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostMapping("/tournaments/{id}/divide")
|
||||||
|
public ResponseEntity<TournamentDto> divideTournamentNew(@PathVariable Long id) {
|
||||||
|
var tournament = tournamentService.findTournamentById(id);
|
||||||
|
|
||||||
|
return ResponseEntity.ok(tournamentMapper.toDto(tournamentDivideService.divide(tournament)));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@PostMapping("/tournaments/{id}/divide/clear")
|
||||||
|
public ResponseEntity<TournamentDto> clearTournamentDivision(@PathVariable Long id) {
|
||||||
|
var tournament = tournamentService.findTournamentById(id);
|
||||||
|
|
||||||
|
return ResponseEntity.ok(tournamentMapper.toDto(tournamentDivideService.clear(tournament)));
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostMapping("/tournaments/{id}/draw")
|
||||||
|
public ResponseEntity<TournamentDto> drawTournament(@PathVariable Long id) {
|
||||||
|
var tournament = tournamentService.findTournamentById(id);
|
||||||
|
|
||||||
|
return ResponseEntity.ok(tournamentMapper.toDto(tournamentDrawService.draw(tournament)));
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostMapping("/tournaments/{id}/draw/clear")
|
||||||
|
public ResponseEntity<TournamentDto> clearTournamentDraw(@PathVariable Long id) {
|
||||||
|
var tournament = tournamentService.findTournamentById(id);
|
||||||
|
|
||||||
|
return ResponseEntity.ok(tournamentMapper.toDto(tournamentDrawService.clear(tournament)));
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostMapping("/tournaments/{tournamentId}/rounds/{roundId}/start")
|
||||||
|
public ResponseEntity<TournamentDto> startRound(@PathVariable Long tournamentId, @PathVariable Long roundId) {
|
||||||
|
var tournament = tournamentService.findTournamentById(tournamentId);
|
||||||
|
|
||||||
|
return ResponseEntity.ok(tournamentMapper.toDto(tournamentPlayService.startRound(tournament, roundId)));
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostMapping("/tournaments/{tournamentId}/rounds/{roundId}/finish")
|
||||||
|
public ResponseEntity<TournamentDto> finishRound(@PathVariable Long tournamentId, @PathVariable Long roundId) {
|
||||||
|
var tournament = tournamentService.findTournamentById(tournamentId);
|
||||||
|
|
||||||
|
return ResponseEntity.ok(tournamentMapper.toDto(tournamentPlayService.finishRound(tournament, roundId)));
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostMapping("/tournaments/{tournamentId}/groups/{groupId}/finish")
|
||||||
|
public ResponseEntity<TournamentDto> finishGroup(@PathVariable Long tournamentId, @PathVariable Long groupId) {
|
||||||
|
var tournament = tournamentService.findTournamentById(tournamentId);
|
||||||
|
|
||||||
|
return ResponseEntity.ok(tournamentMapper.toDto(tournamentPlayService.finishGroup(tournament, groupId)));
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostMapping("/tournaments/{tournamentId}/groups/{groupId}/new")
|
||||||
|
public ResponseEntity<TournamentDto> newRound(@PathVariable Long tournamentId, @PathVariable Long groupId) {
|
||||||
|
var tournament = tournamentService.findTournamentById(tournamentId);
|
||||||
|
|
||||||
|
return ResponseEntity.ok(tournamentMapper.toDto(tournamentPlayService.newRound(tournament, groupId)));
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostMapping("/tournaments/{tournamentId}/matches/{matchId}/start/{court}")
|
||||||
|
public ResponseEntity<TournamentDto> startMatch(@PathVariable Long tournamentId, @PathVariable Long matchId, @PathVariable Long court) {
|
||||||
|
var tournament = tournamentService.findTournamentById(tournamentId);
|
||||||
|
|
||||||
|
return ResponseEntity.ok(tournamentMapper.toDto(tournamentPlayService.startMatch(tournament, matchId, court)));
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostMapping("/tournaments/{tournamentId}/matches/{matchId}/stop")
|
||||||
|
public ResponseEntity<TournamentDto> stopMatch(@PathVariable Long tournamentId, @PathVariable Long matchId) {
|
||||||
|
var tournament = tournamentService.findTournamentById(tournamentId);
|
||||||
|
|
||||||
|
return ResponseEntity.ok(tournamentMapper.toDto(tournamentPlayService.stopMatch(tournament, matchId)));
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostMapping("/tournaments/{tournamentId}/matches/{matchId}")
|
||||||
|
public ResponseEntity<TournamentDto> saveResult(@PathVariable Long tournamentId, @PathVariable Long matchId, @RequestBody ResultDto resultDto) {
|
||||||
|
var tournament = tournamentService.findTournamentById(tournamentId);
|
||||||
|
|
||||||
|
return ResponseEntity.ok(tournamentMapper.toDto(tournamentPlayService.saveResult(tournament, matchId, resultDto)));
|
||||||
|
}
|
||||||
|
|
||||||
|
@PatchMapping("/tournaments/{tournamentId}/players/{playerId}/paid/{paid}")
|
||||||
|
public ResponseEntity<Void> updatePaid(@PathVariable Long tournamentId, @PathVariable Long playerId, @PathVariable Boolean paid) {
|
||||||
|
var tournament = tournamentService.findTournamentById(tournamentId);
|
||||||
|
|
||||||
|
tournamentPlayService.updatePaid(tournament, playerId, paid);
|
||||||
|
|
||||||
|
return ResponseEntity.noContent().build();
|
||||||
|
}
|
||||||
|
|
||||||
|
@PatchMapping("/tournaments/{tournamentId}/players/{playerId}/present/{present}")
|
||||||
|
public ResponseEntity<Void> updatePresent(@PathVariable Long tournamentId, @PathVariable Long playerId, @PathVariable Boolean present) {
|
||||||
|
var tournament = tournamentService.findTournamentById(tournamentId);
|
||||||
|
|
||||||
|
tournamentPlayService.updatePresent(tournament, playerId, present);
|
||||||
|
|
||||||
|
return ResponseEntity.noContent().build();
|
||||||
|
}
|
||||||
|
}
|
||||||
15
src/main/java/nl/connectedit/swiss/domain/EventDivision.java
Normal file
15
src/main/java/nl/connectedit/swiss/domain/EventDivision.java
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
package nl.connectedit.swiss.domain;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
import nl.connectedit.swiss.domain.entity.Group;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public class EventDivision {
|
||||||
|
|
||||||
|
private Long eventId;
|
||||||
|
|
||||||
|
private List<Group> groups = new ArrayList<>();
|
||||||
|
}
|
||||||
20
src/main/java/nl/connectedit/swiss/domain/EventType.java
Normal file
20
src/main/java/nl/connectedit/swiss/domain/EventType.java
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
package nl.connectedit.swiss.domain;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
@Getter
|
||||||
|
public enum EventType {
|
||||||
|
|
||||||
|
HE("Herenenkel", false),
|
||||||
|
DE("Damesenkel", false),
|
||||||
|
HD("Herendubbel", true),
|
||||||
|
DD("Damesdubbel", true),
|
||||||
|
GD("Gemengd dubbel", true);
|
||||||
|
|
||||||
|
private final String text;
|
||||||
|
|
||||||
|
private final boolean isDoublesEvent;
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
package nl.connectedit.swiss.domain;
|
||||||
|
|
||||||
|
import lombok.Builder;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@Builder
|
||||||
|
public class EventValidation {
|
||||||
|
private Long eventId;
|
||||||
|
|
||||||
|
@Builder.Default
|
||||||
|
private List<Validation> validations = new ArrayList<>();
|
||||||
|
}
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
package nl.connectedit.swiss.domain;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public enum PlayerStrength {
|
||||||
|
D5(8),
|
||||||
|
D6(6),
|
||||||
|
D7(4),
|
||||||
|
D8(3),
|
||||||
|
D9(2),
|
||||||
|
DR(1);
|
||||||
|
|
||||||
|
private final int coefficient;
|
||||||
|
}
|
||||||
10
src/main/java/nl/connectedit/swiss/domain/Sex.java
Normal file
10
src/main/java/nl/connectedit/swiss/domain/Sex.java
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
package nl.connectedit.swiss.domain;
|
||||||
|
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public enum Sex {
|
||||||
|
|
||||||
|
M, V
|
||||||
|
|
||||||
|
}
|
||||||
8
src/main/java/nl/connectedit/swiss/domain/Status.java
Normal file
8
src/main/java/nl/connectedit/swiss/domain/Status.java
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
package nl.connectedit.swiss.domain;
|
||||||
|
|
||||||
|
public enum Status {
|
||||||
|
NOT_STARTED,
|
||||||
|
READY_TO_PLAY,
|
||||||
|
IN_PROGRESS,
|
||||||
|
FINISHED
|
||||||
|
}
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
package nl.connectedit.swiss.domain;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public class TournamentDivision {
|
||||||
|
|
||||||
|
private Long tournamentId;
|
||||||
|
|
||||||
|
private boolean divided;
|
||||||
|
|
||||||
|
private List<EventDivision> eventDivisions = new ArrayList<>();
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
package nl.connectedit.swiss.domain;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public enum TournamentStatus {
|
||||||
|
UPCOMING("Nieuw"),
|
||||||
|
DIVIDED("Ingedeeld"),
|
||||||
|
DRAWN("Geloot"),
|
||||||
|
ONGOING("Bezig"),
|
||||||
|
CLOSED("Gesloten");
|
||||||
|
|
||||||
|
private final String text;
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
package nl.connectedit.swiss.domain;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public class TournamentValidation {
|
||||||
|
|
||||||
|
private Long tournamentId;
|
||||||
|
|
||||||
|
private List<Validation> validations;
|
||||||
|
|
||||||
|
private List<EventValidation> eventValidations;
|
||||||
|
|
||||||
|
public boolean hasErrors() {
|
||||||
|
return !validations.isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
19
src/main/java/nl/connectedit/swiss/domain/Validation.java
Normal file
19
src/main/java/nl/connectedit/swiss/domain/Validation.java
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
package nl.connectedit.swiss.domain;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@AllArgsConstructor
|
||||||
|
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||||
|
public class Validation {
|
||||||
|
public enum Severity {
|
||||||
|
INFO, WARN, ERROR
|
||||||
|
}
|
||||||
|
private Severity severity;
|
||||||
|
|
||||||
|
private String message;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
package nl.connectedit.swiss.domain.entity;
|
||||||
|
|
||||||
|
import org.hibernate.proxy.HibernateProxy;
|
||||||
|
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
public abstract class AbstractEntity {
|
||||||
|
|
||||||
|
protected abstract Long getId();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public final boolean equals(Object o) {
|
||||||
|
if (this == o) return true;
|
||||||
|
if (o == null) return false;
|
||||||
|
Class<?> oEffectiveClass = o instanceof HibernateProxy ? ((HibernateProxy) o).getHibernateLazyInitializer().getPersistentClass() : o.getClass();
|
||||||
|
Class<?> thisEffectiveClass = this instanceof HibernateProxy ? ((HibernateProxy) this).getHibernateLazyInitializer().getPersistentClass() : this.getClass();
|
||||||
|
if (thisEffectiveClass != oEffectiveClass) return false;
|
||||||
|
AbstractEntity abstractEntity = (AbstractEntity) o;
|
||||||
|
return getId() != null && Objects.equals(getId(), abstractEntity.getId());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public final int hashCode() {
|
||||||
|
return this instanceof HibernateProxy ? ((HibernateProxy) this).getHibernateLazyInitializer().getPersistentClass().hashCode() : getClass().hashCode();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
62
src/main/java/nl/connectedit/swiss/domain/entity/Event.java
Normal file
62
src/main/java/nl/connectedit/swiss/domain/entity/Event.java
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
package nl.connectedit.swiss.domain.entity;
|
||||||
|
|
||||||
|
import jakarta.persistence.*;
|
||||||
|
import lombok.*;
|
||||||
|
import nl.connectedit.swiss.domain.EventType;
|
||||||
|
import nl.connectedit.swiss.domain.Status;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
@Entity
|
||||||
|
@Table
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
@Builder
|
||||||
|
@AllArgsConstructor
|
||||||
|
public class Event extends AbstractEntity {
|
||||||
|
|
||||||
|
@Id
|
||||||
|
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
@ManyToOne
|
||||||
|
private Tournament tournament;
|
||||||
|
|
||||||
|
@OneToMany(cascade = CascadeType.MERGE, fetch = FetchType.LAZY)
|
||||||
|
// @Builder.Default
|
||||||
|
private List<Registration> registrations;// = new ArrayList<>();
|
||||||
|
|
||||||
|
@Enumerated(EnumType.STRING)
|
||||||
|
private Status status;
|
||||||
|
|
||||||
|
@Enumerated(EnumType.STRING)
|
||||||
|
private EventType type;
|
||||||
|
|
||||||
|
@OneToMany(cascade = CascadeType.MERGE, fetch = FetchType.LAZY)
|
||||||
|
private List<Group> groups;// = new ArrayList<>();
|
||||||
|
|
||||||
|
public static List<Event> getBlankEventSet(Tournament tournament) {
|
||||||
|
return Arrays.stream(EventType.values())
|
||||||
|
.map(type -> Event
|
||||||
|
.builder()
|
||||||
|
.type(type)
|
||||||
|
.status(Status.NOT_STARTED)
|
||||||
|
.tournament(tournament)
|
||||||
|
.build()
|
||||||
|
)
|
||||||
|
.collect(Collectors.toCollection(ArrayList::new));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addRegistration(Registration registration) {
|
||||||
|
this.registrations.add(registration);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return this.getType().getText();
|
||||||
|
}
|
||||||
|
}
|
||||||
26
src/main/java/nl/connectedit/swiss/domain/entity/Game.java
Normal file
26
src/main/java/nl/connectedit/swiss/domain/entity/Game.java
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
package nl.connectedit.swiss.domain.entity;
|
||||||
|
|
||||||
|
import jakarta.persistence.*;
|
||||||
|
import lombok.*;
|
||||||
|
|
||||||
|
@Entity
|
||||||
|
@Table
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
@Builder
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
@AllArgsConstructor
|
||||||
|
public class Game extends AbstractEntity {
|
||||||
|
|
||||||
|
@Id
|
||||||
|
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
@ManyToOne
|
||||||
|
private Match match;
|
||||||
|
|
||||||
|
private Long score1;
|
||||||
|
|
||||||
|
private Long score2;
|
||||||
|
|
||||||
|
}
|
||||||
38
src/main/java/nl/connectedit/swiss/domain/entity/Group.java
Normal file
38
src/main/java/nl/connectedit/swiss/domain/entity/Group.java
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
package nl.connectedit.swiss.domain.entity;
|
||||||
|
|
||||||
|
import jakarta.persistence.*;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
import nl.connectedit.swiss.domain.EventType;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import nl.connectedit.swiss.domain.Status;
|
||||||
|
|
||||||
|
@Entity
|
||||||
|
@Table(name = "eventgroup")
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
public class Group extends AbstractEntity {
|
||||||
|
|
||||||
|
@Id
|
||||||
|
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
@ManyToOne
|
||||||
|
private Event event;
|
||||||
|
|
||||||
|
@Enumerated(EnumType.STRING)
|
||||||
|
private Status status;
|
||||||
|
|
||||||
|
private EventType type;
|
||||||
|
|
||||||
|
@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY)
|
||||||
|
private List<Round> rounds;// = new ArrayList<>();
|
||||||
|
|
||||||
|
@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY)
|
||||||
|
private List<Team> teams;// = new ArrayList<>();
|
||||||
|
|
||||||
|
}
|
||||||
49
src/main/java/nl/connectedit/swiss/domain/entity/Match.java
Normal file
49
src/main/java/nl/connectedit/swiss/domain/entity/Match.java
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
package nl.connectedit.swiss.domain.entity;
|
||||||
|
|
||||||
|
import jakarta.persistence.*;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import lombok.Setter;
|
||||||
|
import nl.connectedit.swiss.domain.EventType;
|
||||||
|
import nl.connectedit.swiss.domain.Status;
|
||||||
|
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Entity
|
||||||
|
@Table
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class Match extends AbstractEntity {
|
||||||
|
|
||||||
|
@Id
|
||||||
|
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
private EventType type;
|
||||||
|
|
||||||
|
private Status status;
|
||||||
|
|
||||||
|
@ManyToOne
|
||||||
|
private Round round;
|
||||||
|
|
||||||
|
@ManyToOne
|
||||||
|
private Team team1;
|
||||||
|
|
||||||
|
@ManyToOne
|
||||||
|
private Team team2;
|
||||||
|
|
||||||
|
private Boolean played;
|
||||||
|
|
||||||
|
private Long court;
|
||||||
|
|
||||||
|
@OneToMany(cascade = CascadeType.MERGE, fetch = FetchType.LAZY)
|
||||||
|
private List<Game> games;// = new ArrayList<>();
|
||||||
|
|
||||||
|
private LocalDateTime startTime;
|
||||||
|
|
||||||
|
private LocalDateTime endTime;
|
||||||
|
|
||||||
|
}
|
||||||
77
src/main/java/nl/connectedit/swiss/domain/entity/Player.java
Normal file
77
src/main/java/nl/connectedit/swiss/domain/entity/Player.java
Normal file
@@ -0,0 +1,77 @@
|
|||||||
|
package nl.connectedit.swiss.domain.entity;
|
||||||
|
|
||||||
|
import jakarta.persistence.*;
|
||||||
|
import jakarta.validation.constraints.NotEmpty;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
import lombok.Setter;
|
||||||
|
import nl.connectedit.swiss.domain.PlayerStrength;
|
||||||
|
import nl.connectedit.swiss.domain.Sex;
|
||||||
|
import org.springframework.format.annotation.DateTimeFormat;
|
||||||
|
|
||||||
|
import java.time.LocalDate;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import static org.springframework.util.StringUtils.hasLength;
|
||||||
|
|
||||||
|
@Entity
|
||||||
|
@Table
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
@NoArgsConstructor
|
||||||
|
public class Player extends AbstractEntity {
|
||||||
|
|
||||||
|
@Id
|
||||||
|
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
@Column(nullable = false)
|
||||||
|
@NotEmpty
|
||||||
|
private String firstName;
|
||||||
|
|
||||||
|
@Column
|
||||||
|
private String middleName;
|
||||||
|
|
||||||
|
@Column(nullable = false)
|
||||||
|
@NotEmpty
|
||||||
|
private String lastName;
|
||||||
|
|
||||||
|
@Column(nullable = false)
|
||||||
|
@Enumerated(EnumType.STRING)
|
||||||
|
private Sex sex;
|
||||||
|
|
||||||
|
@Column(nullable = false)
|
||||||
|
@DateTimeFormat(pattern = "dd-MM-yyyy")
|
||||||
|
private LocalDate birthday;
|
||||||
|
|
||||||
|
@Column(nullable = false)
|
||||||
|
private String phoneNumber;
|
||||||
|
|
||||||
|
@Column(nullable = false)
|
||||||
|
private String email;
|
||||||
|
|
||||||
|
@Column
|
||||||
|
private String club;
|
||||||
|
|
||||||
|
@Column(nullable = false)
|
||||||
|
@Enumerated(EnumType.STRING)
|
||||||
|
private PlayerStrength strength;
|
||||||
|
|
||||||
|
@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY)
|
||||||
|
private List<Registration> registrations;// = new ArrayList<>();
|
||||||
|
|
||||||
|
@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY)
|
||||||
|
private List<Registration> partnerRegistrations;// = new ArrayList<>();
|
||||||
|
|
||||||
|
public String getFullName() {
|
||||||
|
return hasLength(middleName) ?
|
||||||
|
String.join(" ", firstName, middleName, lastName) :
|
||||||
|
String.join(" ", firstName, lastName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return this.getFullName();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
package nl.connectedit.swiss.domain.entity;
|
||||||
|
|
||||||
|
import jakarta.annotation.Nullable;
|
||||||
|
import jakarta.persistence.*;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
@Entity
|
||||||
|
@Table
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class Registration extends AbstractEntity {
|
||||||
|
|
||||||
|
@Id
|
||||||
|
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
@ManyToOne
|
||||||
|
private Event event;
|
||||||
|
|
||||||
|
@ManyToOne
|
||||||
|
private Tournament tournament;
|
||||||
|
|
||||||
|
@ManyToOne
|
||||||
|
@JoinColumn(name = "player_id")
|
||||||
|
private Player player;
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
@ManyToOne
|
||||||
|
@JoinColumn(name = "partner_id")
|
||||||
|
private Player partner;
|
||||||
|
|
||||||
|
}
|
||||||
39
src/main/java/nl/connectedit/swiss/domain/entity/Round.java
Normal file
39
src/main/java/nl/connectedit/swiss/domain/entity/Round.java
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
package nl.connectedit.swiss.domain.entity;
|
||||||
|
|
||||||
|
import jakarta.persistence.*;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import lombok.Setter;
|
||||||
|
import nl.connectedit.swiss.domain.Status;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Entity
|
||||||
|
@Table
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class Round extends AbstractEntity {
|
||||||
|
|
||||||
|
@Id
|
||||||
|
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
@ManyToOne
|
||||||
|
private Group group;
|
||||||
|
|
||||||
|
private Status status;
|
||||||
|
|
||||||
|
@OneToMany(cascade = CascadeType.MERGE, fetch = FetchType.LAZY)
|
||||||
|
private List<Match> matches;// = new ArrayList<>();
|
||||||
|
|
||||||
|
@OneToMany(cascade = CascadeType.MERGE, fetch = FetchType.LAZY)
|
||||||
|
private List<Team> quit;// = new ArrayList<>();
|
||||||
|
|
||||||
|
@ManyToOne
|
||||||
|
private Team drawnOut;
|
||||||
|
|
||||||
|
}
|
||||||
34
src/main/java/nl/connectedit/swiss/domain/entity/Team.java
Normal file
34
src/main/java/nl/connectedit/swiss/domain/entity/Team.java
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
package nl.connectedit.swiss.domain.entity;
|
||||||
|
|
||||||
|
import jakarta.annotation.Nullable;
|
||||||
|
import jakarta.persistence.*;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
@Entity
|
||||||
|
@Table
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class Team extends AbstractEntity {
|
||||||
|
|
||||||
|
@Id
|
||||||
|
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
@ManyToOne
|
||||||
|
private Group group;
|
||||||
|
|
||||||
|
@ManyToOne
|
||||||
|
private Player player1;
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
@ManyToOne
|
||||||
|
private Player player2;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return player2 != null ? player1.toString() + " + " + player2.toString() : player1.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,71 @@
|
|||||||
|
package nl.connectedit.swiss.domain.entity;
|
||||||
|
|
||||||
|
import jakarta.persistence.*;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
import nl.connectedit.swiss.domain.EventType;
|
||||||
|
import nl.connectedit.swiss.domain.TournamentStatus;
|
||||||
|
|
||||||
|
import java.time.LocalDate;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
@Entity
|
||||||
|
@Table
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
public class Tournament extends AbstractEntity {
|
||||||
|
|
||||||
|
public Tournament() {
|
||||||
|
initialize();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Id
|
||||||
|
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
private LocalDate date;
|
||||||
|
|
||||||
|
@Enumerated(EnumType.STRING)
|
||||||
|
private TournamentStatus status;
|
||||||
|
|
||||||
|
@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY)
|
||||||
|
private List<Event> events;// = new ArrayList<>();
|
||||||
|
|
||||||
|
@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY)
|
||||||
|
private List<TournamentPlayer> tournamentPlayers;
|
||||||
|
|
||||||
|
private Long maxEvents;
|
||||||
|
|
||||||
|
@ElementCollection
|
||||||
|
private List<Float> costsPerEvent;
|
||||||
|
|
||||||
|
private Long courts;
|
||||||
|
|
||||||
|
public void initialize() {
|
||||||
|
this.events = new ArrayList<>();
|
||||||
|
this.events.addAll(Event.getBlankEventSet(this));
|
||||||
|
this.status = TournamentStatus.UPCOMING;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Event getEventByType(EventType type) {
|
||||||
|
return events
|
||||||
|
.stream()
|
||||||
|
.filter(event -> event.getType().equals(type))
|
||||||
|
.findFirst()
|
||||||
|
.orElse(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Registration> getRegistrations() {
|
||||||
|
return events
|
||||||
|
.stream()
|
||||||
|
.map(Event::getRegistrations)
|
||||||
|
.flatMap(List::stream)
|
||||||
|
.collect(Collectors.toCollection(ArrayList::new));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
package nl.connectedit.swiss.domain.entity;
|
||||||
|
|
||||||
|
import jakarta.persistence.*;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Entity
|
||||||
|
@Table
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
public class TournamentPlayer extends AbstractEntity {
|
||||||
|
|
||||||
|
@Id
|
||||||
|
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
@ManyToOne
|
||||||
|
private Tournament tournament;
|
||||||
|
|
||||||
|
@ElementCollection
|
||||||
|
private List<String> events;
|
||||||
|
|
||||||
|
@ManyToOne
|
||||||
|
private Player player;
|
||||||
|
|
||||||
|
private boolean paid;
|
||||||
|
|
||||||
|
private boolean present;
|
||||||
|
}
|
||||||
4
src/main/java/nl/connectedit/swiss/dto/AbstractDto.java
Normal file
4
src/main/java/nl/connectedit/swiss/dto/AbstractDto.java
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
package nl.connectedit.swiss.dto;
|
||||||
|
|
||||||
|
public class AbstractDto {
|
||||||
|
}
|
||||||
22
src/main/java/nl/connectedit/swiss/dto/EventDto.java
Normal file
22
src/main/java/nl/connectedit/swiss/dto/EventDto.java
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
package nl.connectedit.swiss.dto;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
public class EventDto extends AbstractDto {
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
private String type;
|
||||||
|
|
||||||
|
private String status;
|
||||||
|
|
||||||
|
private boolean isDoublesEvent;
|
||||||
|
|
||||||
|
private List<RegistrationDto> registrations;
|
||||||
|
|
||||||
|
private List<GroupDto> groups;
|
||||||
|
}
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
package nl.connectedit.swiss.dto;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
public class EventRegistrationDto extends AbstractDto {
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
private String type;
|
||||||
|
|
||||||
|
private boolean isDoublesEvent;
|
||||||
|
|
||||||
|
private boolean registered;
|
||||||
|
|
||||||
|
private Long player;
|
||||||
|
|
||||||
|
private Long partner;
|
||||||
|
}
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
package nl.connectedit.swiss.dto;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public class EventValidationDto {
|
||||||
|
|
||||||
|
private Long eventId;
|
||||||
|
|
||||||
|
private List<ValidationDto> validations;
|
||||||
|
}
|
||||||
13
src/main/java/nl/connectedit/swiss/dto/GameDto.java
Normal file
13
src/main/java/nl/connectedit/swiss/dto/GameDto.java
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
package nl.connectedit.swiss.dto;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
public class GameDto extends AbstractDto {
|
||||||
|
|
||||||
|
private Long score1;
|
||||||
|
|
||||||
|
private Long score2;
|
||||||
|
}
|
||||||
26
src/main/java/nl/connectedit/swiss/dto/GroupDto.java
Normal file
26
src/main/java/nl/connectedit/swiss/dto/GroupDto.java
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
package nl.connectedit.swiss.dto;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
public class GroupDto extends AbstractDto {
|
||||||
|
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
private String type;
|
||||||
|
|
||||||
|
private String status;
|
||||||
|
|
||||||
|
private List<TeamDto> teams;
|
||||||
|
|
||||||
|
private List<RoundDto> rounds;
|
||||||
|
|
||||||
|
private StandingsDto standings;
|
||||||
|
|
||||||
|
}
|
||||||
32
src/main/java/nl/connectedit/swiss/dto/MatchDto.java
Normal file
32
src/main/java/nl/connectedit/swiss/dto/MatchDto.java
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
package nl.connectedit.swiss.dto;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
public class MatchDto extends AbstractDto {
|
||||||
|
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
private String type;
|
||||||
|
|
||||||
|
private String status;
|
||||||
|
|
||||||
|
private TeamDto team1;
|
||||||
|
|
||||||
|
private TeamDto team2;
|
||||||
|
|
||||||
|
private Boolean played;
|
||||||
|
|
||||||
|
private List<GameDto> games;
|
||||||
|
|
||||||
|
private LocalDateTime startTime;
|
||||||
|
|
||||||
|
private LocalDateTime endTime;
|
||||||
|
|
||||||
|
private Long court;
|
||||||
|
}
|
||||||
34
src/main/java/nl/connectedit/swiss/dto/PlayerDto.java
Normal file
34
src/main/java/nl/connectedit/swiss/dto/PlayerDto.java
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
package nl.connectedit.swiss.dto;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
import org.springframework.format.annotation.DateTimeFormat;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
public class PlayerDto extends AbstractDto {
|
||||||
|
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
private String firstName;
|
||||||
|
|
||||||
|
private String middleName;
|
||||||
|
|
||||||
|
private String lastName;
|
||||||
|
|
||||||
|
private String sex;
|
||||||
|
|
||||||
|
@DateTimeFormat(pattern = "dd-MM-yyyy")
|
||||||
|
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "dd-MM-yyyy")
|
||||||
|
private String birthday;
|
||||||
|
|
||||||
|
private String phoneNumber;
|
||||||
|
|
||||||
|
private String email;
|
||||||
|
|
||||||
|
private String club;
|
||||||
|
|
||||||
|
private String strength;
|
||||||
|
|
||||||
|
}
|
||||||
15
src/main/java/nl/connectedit/swiss/dto/RegistrationDto.java
Normal file
15
src/main/java/nl/connectedit/swiss/dto/RegistrationDto.java
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
package nl.connectedit.swiss.dto;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
public class RegistrationDto extends AbstractDto {
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
private PlayerDto player;
|
||||||
|
|
||||||
|
private PlayerDto partner;
|
||||||
|
}
|
||||||
|
|
||||||
15
src/main/java/nl/connectedit/swiss/dto/ResultDto.java
Normal file
15
src/main/java/nl/connectedit/swiss/dto/ResultDto.java
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
package nl.connectedit.swiss.dto;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
public class ResultDto extends AbstractDto {
|
||||||
|
|
||||||
|
private Long matchId;
|
||||||
|
|
||||||
|
private List<GameDto> games = new ArrayList<>();
|
||||||
|
}
|
||||||
26
src/main/java/nl/connectedit/swiss/dto/RoundDto.java
Normal file
26
src/main/java/nl/connectedit/swiss/dto/RoundDto.java
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
package nl.connectedit.swiss.dto;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
public class RoundDto extends AbstractDto {
|
||||||
|
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
private List<MatchDto> matches;
|
||||||
|
|
||||||
|
private String status;
|
||||||
|
|
||||||
|
private List<TeamDto> quit;
|
||||||
|
|
||||||
|
private TeamDto drawnOut;
|
||||||
|
|
||||||
|
private StandingsDto standings;
|
||||||
|
|
||||||
|
}
|
||||||
13
src/main/java/nl/connectedit/swiss/dto/StandingsDto.java
Normal file
13
src/main/java/nl/connectedit/swiss/dto/StandingsDto.java
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
package nl.connectedit.swiss.dto;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
public class StandingsDto {
|
||||||
|
|
||||||
|
private List<StandingsEntryDto> entries = new ArrayList<>();
|
||||||
|
}
|
||||||
69
src/main/java/nl/connectedit/swiss/dto/StandingsEntry.java
Normal file
69
src/main/java/nl/connectedit/swiss/dto/StandingsEntry.java
Normal file
@@ -0,0 +1,69 @@
|
|||||||
|
package nl.connectedit.swiss.dto;
|
||||||
|
|
||||||
|
import java.util.Comparator;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
import lombok.ToString;
|
||||||
|
import nl.connectedit.swiss.domain.entity.Team;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
@ToString
|
||||||
|
public class StandingsEntry {
|
||||||
|
|
||||||
|
public StandingsEntry(Team team) {
|
||||||
|
this.team = team;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Long position;
|
||||||
|
|
||||||
|
private Team team;
|
||||||
|
|
||||||
|
private Long played = 0L;
|
||||||
|
|
||||||
|
private Long won = 0L;
|
||||||
|
|
||||||
|
private Long lost = 0L;
|
||||||
|
|
||||||
|
private Long points = 0L;
|
||||||
|
|
||||||
|
private Long gamesWon = 0L;
|
||||||
|
|
||||||
|
private Long gamesLost = 0L;
|
||||||
|
|
||||||
|
private Long pointsWon = 0L;
|
||||||
|
|
||||||
|
private Long pointsLost = 0L;
|
||||||
|
|
||||||
|
public static int compare(StandingsEntry s1, StandingsEntry s2) {
|
||||||
|
var pointsPerMatchS1 = safeDivide(s1.points, s1.played);
|
||||||
|
var pointsPerMatchS2 = safeDivide(s2.points, s2.played);
|
||||||
|
if (pointsPerMatchS1 > pointsPerMatchS2) {
|
||||||
|
return -1;
|
||||||
|
} else if (pointsPerMatchS1 < pointsPerMatchS2) {
|
||||||
|
return 1;
|
||||||
|
} else {
|
||||||
|
if (s1.played < s2.played) {
|
||||||
|
return -1;
|
||||||
|
} else if (s1.played > s2.played) {
|
||||||
|
return 1;
|
||||||
|
} else {
|
||||||
|
var gamesPerMatchS1 = safeDivide(s1.gamesWon - s1.gamesLost, s1.played);
|
||||||
|
var gamesPerMatchS2 = safeDivide(s2.gamesWon - s2.gamesLost, s2.played);
|
||||||
|
if (gamesPerMatchS1 > gamesPerMatchS2) {
|
||||||
|
return -1;
|
||||||
|
} else if (gamesPerMatchS1 < gamesPerMatchS2) {
|
||||||
|
return 1;
|
||||||
|
} else {
|
||||||
|
var ptsPerMatchS1 = safeDivide(s1.pointsWon - s1.pointsLost, s1.played);
|
||||||
|
var ptsPerMatchS2 = safeDivide(s2.pointsWon - s2.pointsLost, s2.played);
|
||||||
|
return Double.compare(ptsPerMatchS2, ptsPerMatchS1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static double safeDivide(Long a, Long b) {
|
||||||
|
return (a == 0 && b == 0) ? 0 : (double) a / b;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
package nl.connectedit.swiss.dto;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
public class StandingsEntryDto {
|
||||||
|
|
||||||
|
private Long position;
|
||||||
|
|
||||||
|
private TeamDto team;
|
||||||
|
|
||||||
|
private Long played;
|
||||||
|
|
||||||
|
private Long won;
|
||||||
|
|
||||||
|
private Long lost;
|
||||||
|
|
||||||
|
private Long points;
|
||||||
|
|
||||||
|
private Long gamesWon;
|
||||||
|
|
||||||
|
private Long gamesLost;
|
||||||
|
|
||||||
|
private Long pointsWon;
|
||||||
|
|
||||||
|
private Long pointsLost;
|
||||||
|
|
||||||
|
}
|
||||||
13
src/main/java/nl/connectedit/swiss/dto/TeamDto.java
Normal file
13
src/main/java/nl/connectedit/swiss/dto/TeamDto.java
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
package nl.connectedit.swiss.dto;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
public class TeamDto extends AbstractDto {
|
||||||
|
|
||||||
|
private PlayerDto player1;
|
||||||
|
|
||||||
|
private PlayerDto player2;
|
||||||
|
}
|
||||||
32
src/main/java/nl/connectedit/swiss/dto/TournamentDto.java
Normal file
32
src/main/java/nl/connectedit/swiss/dto/TournamentDto.java
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
package nl.connectedit.swiss.dto;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
public class TournamentDto extends AbstractDto {
|
||||||
|
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "dd-MM-yyyy")
|
||||||
|
private String date;
|
||||||
|
|
||||||
|
private String status;
|
||||||
|
|
||||||
|
private List<EventDto> events;
|
||||||
|
|
||||||
|
private List<TournamentPlayerDto> tournamentPlayers;
|
||||||
|
|
||||||
|
private Long maxEvents;
|
||||||
|
|
||||||
|
private List<Float> costsPerEvent;
|
||||||
|
|
||||||
|
private Long courts;
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
package nl.connectedit.swiss.dto;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
public class TournamentPlayerDto extends AbstractDto {
|
||||||
|
|
||||||
|
private Long playerId;
|
||||||
|
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
private List<String> events;
|
||||||
|
|
||||||
|
private Boolean paid;
|
||||||
|
|
||||||
|
private Boolean present;
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
package nl.connectedit.swiss.dto;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
public class TournamentRegistrationDto extends AbstractDto {
|
||||||
|
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
private Boolean editable;
|
||||||
|
|
||||||
|
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "dd-MM-yyyy")
|
||||||
|
private String date;
|
||||||
|
|
||||||
|
private String status;
|
||||||
|
|
||||||
|
private List<EventRegistrationDto> events;
|
||||||
|
}
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
package nl.connectedit.swiss.dto;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
import nl.connectedit.swiss.domain.Validation;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
public class TournamentValidationDto extends AbstractDto {
|
||||||
|
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
private List<Validation> validations;
|
||||||
|
|
||||||
|
private List<EventValidationDto> eventValidations;
|
||||||
|
}
|
||||||
|
|
||||||
11
src/main/java/nl/connectedit/swiss/dto/ValidationDto.java
Normal file
11
src/main/java/nl/connectedit/swiss/dto/ValidationDto.java
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
package nl.connectedit.swiss.dto;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
public class ValidationDto extends AbstractDto {
|
||||||
|
private String severity;
|
||||||
|
private String message;
|
||||||
|
}
|
||||||
8
src/main/java/nl/connectedit/swiss/mapper/DtoMapper.java
Normal file
8
src/main/java/nl/connectedit/swiss/mapper/DtoMapper.java
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
package nl.connectedit.swiss.mapper;
|
||||||
|
|
||||||
|
import nl.connectedit.swiss.domain.entity.AbstractEntity;
|
||||||
|
import nl.connectedit.swiss.dto.AbstractDto;
|
||||||
|
|
||||||
|
public interface DtoMapper<E extends AbstractEntity, D extends AbstractDto> {
|
||||||
|
D toDto(E entity);
|
||||||
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
package nl.connectedit.swiss.mapper;
|
||||||
|
|
||||||
|
import nl.connectedit.swiss.domain.entity.AbstractEntity;
|
||||||
|
import nl.connectedit.swiss.dto.AbstractDto;
|
||||||
|
|
||||||
|
public interface EntityMapper<D extends AbstractDto, E extends AbstractEntity> {
|
||||||
|
E toEntity(D dto);
|
||||||
|
}
|
||||||
66
src/main/java/nl/connectedit/swiss/mapper/EventMapper.java
Normal file
66
src/main/java/nl/connectedit/swiss/mapper/EventMapper.java
Normal file
@@ -0,0 +1,66 @@
|
|||||||
|
package nl.connectedit.swiss.mapper;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import nl.connectedit.swiss.domain.Status;
|
||||||
|
import nl.connectedit.swiss.domain.entity.Event;
|
||||||
|
import nl.connectedit.swiss.domain.EventType;
|
||||||
|
import nl.connectedit.swiss.dto.EventDto;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class EventMapper implements DtoMapper<Event, EventDto>, EntityMapper<EventDto, Event> {
|
||||||
|
|
||||||
|
private final RegistrationMapper registrationMapper;
|
||||||
|
|
||||||
|
private final GroupMapper groupMapper;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Event toEntity(EventDto eventDto) {
|
||||||
|
Event event = new Event();
|
||||||
|
event.setId(eventDto.getId());
|
||||||
|
event.setType(
|
||||||
|
Arrays.stream(EventType.values())
|
||||||
|
.filter(ts -> ts.getText().equals(eventDto.getType()))
|
||||||
|
.findFirst()
|
||||||
|
.orElse(null)
|
||||||
|
);
|
||||||
|
event.setStatus(Status.valueOf(eventDto.getStatus()));
|
||||||
|
event.setRegistrations(
|
||||||
|
eventDto.getRegistrations()
|
||||||
|
.stream()
|
||||||
|
.map(registrationMapper::toEntity)
|
||||||
|
.toList()
|
||||||
|
);
|
||||||
|
|
||||||
|
return event;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public EventDto toDto(Event event) {
|
||||||
|
EventDto eventDto = new EventDto();
|
||||||
|
eventDto.setId(event.getId());
|
||||||
|
eventDto.setType(event.getType().name());
|
||||||
|
eventDto.setStatus(event.getStatus().name());
|
||||||
|
eventDto.setDoublesEvent(event.getType().isDoublesEvent());
|
||||||
|
if (event.getRegistrations() != null) {
|
||||||
|
eventDto.setRegistrations(
|
||||||
|
event.getRegistrations()
|
||||||
|
.stream()
|
||||||
|
.map(registrationMapper::toDto)
|
||||||
|
.toList()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (event.getGroups() != null) {
|
||||||
|
eventDto.setGroups(
|
||||||
|
event.getGroups()
|
||||||
|
.stream()
|
||||||
|
.map(groupMapper::toDto)
|
||||||
|
.toList()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return eventDto;
|
||||||
|
}
|
||||||
|
}
|
||||||
18
src/main/java/nl/connectedit/swiss/mapper/GameMapper.java
Normal file
18
src/main/java/nl/connectedit/swiss/mapper/GameMapper.java
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
package nl.connectedit.swiss.mapper;
|
||||||
|
|
||||||
|
import nl.connectedit.swiss.domain.entity.Game;
|
||||||
|
import nl.connectedit.swiss.dto.GameDto;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
public class GameMapper implements DtoMapper<Game, GameDto> {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public GameDto toDto(Game game) {
|
||||||
|
var gameDto = new GameDto();
|
||||||
|
gameDto.setScore1(game.getScore1());
|
||||||
|
gameDto.setScore2(game.getScore2());
|
||||||
|
|
||||||
|
return gameDto;
|
||||||
|
}
|
||||||
|
}
|
||||||
55
src/main/java/nl/connectedit/swiss/mapper/GroupMapper.java
Normal file
55
src/main/java/nl/connectedit/swiss/mapper/GroupMapper.java
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
package nl.connectedit.swiss.mapper;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import nl.connectedit.swiss.domain.Status;
|
||||||
|
import nl.connectedit.swiss.domain.entity.Group;
|
||||||
|
import nl.connectedit.swiss.domain.entity.Round;
|
||||||
|
import nl.connectedit.swiss.dto.GroupDto;
|
||||||
|
import nl.connectedit.swiss.dto.RoundDto;
|
||||||
|
import nl.connectedit.swiss.service.StandingsService;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class GroupMapper implements DtoMapper<Group, GroupDto> {
|
||||||
|
|
||||||
|
private final TeamMapper teamMapper;
|
||||||
|
|
||||||
|
private final RoundMapper roundMapper;
|
||||||
|
|
||||||
|
private final StandingsService standingsService;
|
||||||
|
|
||||||
|
private final StandingsMapper standingsMapper;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public GroupDto toDto(Group group) {
|
||||||
|
var groupDto = new GroupDto();
|
||||||
|
groupDto.setId(group.getId());
|
||||||
|
groupDto.setName(group.getName());
|
||||||
|
groupDto.setType(group.getType().name());
|
||||||
|
groupDto.setStatus(group.getStatus().name());
|
||||||
|
groupDto.setTeams(
|
||||||
|
group.getTeams()
|
||||||
|
.stream()
|
||||||
|
.map(teamMapper::toDto)
|
||||||
|
.toList());
|
||||||
|
|
||||||
|
var standingsGroup = new ArrayList<Round>();
|
||||||
|
var rounds = new ArrayList<RoundDto>();
|
||||||
|
if (group.getRounds() != null) {
|
||||||
|
for (var round : group.getRounds()) {
|
||||||
|
if (round.getStatus() == Status.FINISHED) {
|
||||||
|
standingsGroup.add(round);
|
||||||
|
}
|
||||||
|
rounds.add(roundMapper.toDto(round, standingsGroup, group.getTeams()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
groupDto.setRounds(rounds);
|
||||||
|
|
||||||
|
var standings = standingsService.getStandings(group.getRounds(), group.getTeams());
|
||||||
|
groupDto.setStandings(standingsMapper.toDto(standings));
|
||||||
|
|
||||||
|
return groupDto;
|
||||||
|
}
|
||||||
|
}
|
||||||
39
src/main/java/nl/connectedit/swiss/mapper/MatchMapper.java
Normal file
39
src/main/java/nl/connectedit/swiss/mapper/MatchMapper.java
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
package nl.connectedit.swiss.mapper;
|
||||||
|
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import nl.connectedit.swiss.domain.entity.Match;
|
||||||
|
import nl.connectedit.swiss.dto.MatchDto;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class MatchMapper implements DtoMapper<Match, MatchDto> {
|
||||||
|
|
||||||
|
private final TeamMapper teamMapper;
|
||||||
|
|
||||||
|
private final GameMapper gameMapper;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public MatchDto toDto(Match match) {
|
||||||
|
var matchDto = new MatchDto();
|
||||||
|
|
||||||
|
matchDto.setId(match.getId());
|
||||||
|
matchDto.setType(match.getType().name());
|
||||||
|
matchDto.setStatus(match.getStatus().name());
|
||||||
|
matchDto.setTeam1(teamMapper.toDto(match.getTeam1()));
|
||||||
|
matchDto.setTeam2(teamMapper.toDto(match.getTeam2()));
|
||||||
|
matchDto.setStartTime(match.getStartTime());
|
||||||
|
matchDto.setEndTime(match.getEndTime());
|
||||||
|
matchDto.setCourt(match.getCourt());
|
||||||
|
|
||||||
|
if (match.getGames() != null) {
|
||||||
|
matchDto.setGames(
|
||||||
|
match.getGames()
|
||||||
|
.stream()
|
||||||
|
.map(gameMapper::toDto)
|
||||||
|
.toList());
|
||||||
|
}
|
||||||
|
|
||||||
|
return matchDto;
|
||||||
|
}
|
||||||
|
}
|
||||||
57
src/main/java/nl/connectedit/swiss/mapper/PlayerMapper.java
Normal file
57
src/main/java/nl/connectedit/swiss/mapper/PlayerMapper.java
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
package nl.connectedit.swiss.mapper;
|
||||||
|
|
||||||
|
import nl.connectedit.swiss.domain.entity.Player;
|
||||||
|
import nl.connectedit.swiss.domain.PlayerStrength;
|
||||||
|
import nl.connectedit.swiss.domain.Sex;
|
||||||
|
import nl.connectedit.swiss.dto.PlayerDto;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import java.time.LocalDate;
|
||||||
|
import java.time.format.DateTimeFormatter;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
public class PlayerMapper implements DtoMapper<Player, PlayerDto>, EntityMapper<PlayerDto, Player> {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Player toEntity(PlayerDto playerDto) {
|
||||||
|
Objects.requireNonNull(playerDto.getFirstName(), "Voornaam is verplicht");
|
||||||
|
Objects.requireNonNull(playerDto.getLastName(), "Achternaam is verplicht");
|
||||||
|
Objects.requireNonNull(playerDto.getSex(), "Geslacht is verplicht");
|
||||||
|
Objects.requireNonNull(playerDto.getPhoneNumber(), "Telefoon is verplicht");
|
||||||
|
Objects.requireNonNull(playerDto.getEmail(), "Emailadres is verplicht");
|
||||||
|
Objects.requireNonNull(playerDto.getBirthday(), "Geboortedatum is verplicht");
|
||||||
|
Objects.requireNonNull(playerDto.getStrength(), "Speelsterkte is verplicht");
|
||||||
|
|
||||||
|
Player player = new Player();
|
||||||
|
player.setId(playerDto.getId());
|
||||||
|
player.setFirstName(playerDto.getFirstName());
|
||||||
|
player.setMiddleName(playerDto.getMiddleName());
|
||||||
|
player.setLastName(playerDto.getLastName());
|
||||||
|
player.setSex(Sex.valueOf(playerDto.getSex()));
|
||||||
|
player.setBirthday(LocalDate.parse(playerDto.getBirthday(), DateTimeFormatter.ofPattern("dd-MM-yyyy")));
|
||||||
|
player.setPhoneNumber(playerDto.getPhoneNumber());
|
||||||
|
player.setEmail(playerDto.getEmail());
|
||||||
|
player.setClub(playerDto.getClub());
|
||||||
|
player.setStrength(PlayerStrength.valueOf(playerDto.getStrength()));
|
||||||
|
|
||||||
|
return player;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PlayerDto toDto(Player player) {
|
||||||
|
PlayerDto playerDto = new PlayerDto();
|
||||||
|
playerDto.setId(player.getId());
|
||||||
|
playerDto.setFirstName(player.getFirstName());
|
||||||
|
playerDto.setMiddleName(player.getMiddleName());
|
||||||
|
playerDto.setLastName(player.getLastName());
|
||||||
|
playerDto.setSex(player.getSex().name());
|
||||||
|
playerDto.setBirthday(player.getBirthday().format(DateTimeFormatter.ofPattern("dd-MM-yyyy")));
|
||||||
|
playerDto.setPhoneNumber(player.getPhoneNumber());
|
||||||
|
playerDto.setEmail(player.getEmail());
|
||||||
|
playerDto.setClub(player.getClub());
|
||||||
|
playerDto.setStrength(player.getStrength().name());
|
||||||
|
|
||||||
|
return playerDto;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
package nl.connectedit.swiss.mapper;
|
||||||
|
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import nl.connectedit.swiss.domain.entity.Registration;
|
||||||
|
import nl.connectedit.swiss.dto.RegistrationDto;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class RegistrationMapper implements DtoMapper<Registration, RegistrationDto>, EntityMapper<RegistrationDto, Registration> {
|
||||||
|
|
||||||
|
private final PlayerMapper playerMapper;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Registration toEntity(RegistrationDto registrationDto) {
|
||||||
|
Registration registration = new Registration();
|
||||||
|
registration.setId(registrationDto.getId());
|
||||||
|
registration.setPlayer(playerMapper.toEntity(registrationDto.getPlayer()));
|
||||||
|
if (registrationDto.getPartner() != null) {
|
||||||
|
registration.setPartner(playerMapper.toEntity(registrationDto.getPartner()));
|
||||||
|
}
|
||||||
|
return registration;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public RegistrationDto toDto(Registration registration) {
|
||||||
|
RegistrationDto registrationDto = new RegistrationDto();
|
||||||
|
registrationDto.setId(registration.getId());
|
||||||
|
// registrationDto.setTournament(registration.getEvent().getTournament().getId());
|
||||||
|
registrationDto.setPlayer(playerMapper.toDto(registration.getPlayer()));
|
||||||
|
if (registration.getPartner() != null) {
|
||||||
|
registrationDto.setPartner(playerMapper.toDto(registration.getPartner()));
|
||||||
|
}
|
||||||
|
return registrationDto;
|
||||||
|
}
|
||||||
|
}
|
||||||
53
src/main/java/nl/connectedit/swiss/mapper/RoundMapper.java
Normal file
53
src/main/java/nl/connectedit/swiss/mapper/RoundMapper.java
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
package nl.connectedit.swiss.mapper;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import nl.connectedit.swiss.domain.entity.Group;
|
||||||
|
import nl.connectedit.swiss.domain.entity.Round;
|
||||||
|
import nl.connectedit.swiss.domain.entity.Team;
|
||||||
|
import nl.connectedit.swiss.dto.RoundDto;
|
||||||
|
import nl.connectedit.swiss.service.StandingsService;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class RoundMapper {
|
||||||
|
|
||||||
|
private final MatchMapper matchMapper;
|
||||||
|
|
||||||
|
private final TeamMapper teamMapper;
|
||||||
|
|
||||||
|
private final StandingsService standingsService;
|
||||||
|
|
||||||
|
private final StandingsMapper standingsMapper;
|
||||||
|
|
||||||
|
public RoundDto toDto(Round round, List<Round> roundsForStandings, List<Team> teamsForStandings) {
|
||||||
|
var roundDto = new RoundDto();
|
||||||
|
roundDto.setId(round.getId());
|
||||||
|
roundDto.setName(round.getName());
|
||||||
|
roundDto.setMatches(
|
||||||
|
round.getMatches()
|
||||||
|
.stream()
|
||||||
|
.map(matchMapper::toDto)
|
||||||
|
.toList());
|
||||||
|
roundDto.setStatus(round.getStatus().name());
|
||||||
|
if (round.getQuit() != null) {
|
||||||
|
roundDto.setQuit(
|
||||||
|
round.getQuit()
|
||||||
|
.stream()
|
||||||
|
.map(teamMapper::toDto)
|
||||||
|
.toList());
|
||||||
|
}
|
||||||
|
if (round.getDrawnOut() != null) {
|
||||||
|
roundDto.setDrawnOut(teamMapper.toDto(round.getDrawnOut()));
|
||||||
|
}
|
||||||
|
|
||||||
|
var standings = standingsService.getStandings(roundsForStandings, teamsForStandings);
|
||||||
|
roundDto.setStandings(standingsMapper.toDto(standings));
|
||||||
|
|
||||||
|
return roundDto;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,42 @@
|
|||||||
|
package nl.connectedit.swiss.mapper;
|
||||||
|
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.List;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import nl.connectedit.swiss.dto.StandingsDto;
|
||||||
|
import nl.connectedit.swiss.dto.StandingsEntry;
|
||||||
|
import nl.connectedit.swiss.dto.StandingsEntryDto;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class StandingsMapper {
|
||||||
|
|
||||||
|
private final TeamMapper teamMapper;
|
||||||
|
|
||||||
|
public StandingsDto toDto(List<StandingsEntry> standings) {
|
||||||
|
var standingsDto = new StandingsDto();
|
||||||
|
Long position = 1L;
|
||||||
|
for (Iterator<StandingsEntry> i = standings.iterator(); i.hasNext(); position++ ) {
|
||||||
|
standingsDto.getEntries().add(toDto(i.next(), position));
|
||||||
|
}
|
||||||
|
|
||||||
|
return standingsDto;
|
||||||
|
}
|
||||||
|
|
||||||
|
private StandingsEntryDto toDto(StandingsEntry standingsEntry, Long position) {
|
||||||
|
var standingsEntryDto = new StandingsEntryDto();
|
||||||
|
standingsEntryDto.setPosition(position);
|
||||||
|
standingsEntryDto.setTeam(teamMapper.toDto(standingsEntry.getTeam()));
|
||||||
|
standingsEntryDto.setPlayed(standingsEntry.getPlayed());
|
||||||
|
standingsEntryDto.setWon(standingsEntry.getWon());
|
||||||
|
standingsEntryDto.setLost(standingsEntry.getLost());
|
||||||
|
standingsEntryDto.setPoints(standingsEntry.getPoints());
|
||||||
|
standingsEntryDto.setGamesWon(standingsEntry.getGamesWon());
|
||||||
|
standingsEntryDto.setGamesLost(standingsEntry.getGamesLost());
|
||||||
|
standingsEntryDto.setPointsWon(standingsEntry.getPointsWon());
|
||||||
|
standingsEntryDto.setPointsLost(standingsEntry.getPointsLost());
|
||||||
|
|
||||||
|
return standingsEntryDto;
|
||||||
|
}
|
||||||
|
}
|
||||||
25
src/main/java/nl/connectedit/swiss/mapper/TeamMapper.java
Normal file
25
src/main/java/nl/connectedit/swiss/mapper/TeamMapper.java
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
package nl.connectedit.swiss.mapper;
|
||||||
|
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import nl.connectedit.swiss.domain.entity.Team;
|
||||||
|
import nl.connectedit.swiss.dto.TeamDto;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class TeamMapper implements DtoMapper<Team, TeamDto> {
|
||||||
|
|
||||||
|
private final PlayerMapper playerMapper;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public TeamDto toDto(Team team) {
|
||||||
|
var teamDto = new TeamDto();
|
||||||
|
teamDto.setPlayer1(playerMapper.toDto(team.getPlayer1()));
|
||||||
|
|
||||||
|
if (team.getPlayer2() != null) {
|
||||||
|
teamDto.setPlayer2(playerMapper.toDto(team.getPlayer2()));
|
||||||
|
}
|
||||||
|
|
||||||
|
return teamDto;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,81 @@
|
|||||||
|
package nl.connectedit.swiss.mapper;
|
||||||
|
|
||||||
|
import java.time.LocalDate;
|
||||||
|
import java.time.format.DateTimeFormatter;
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import nl.connectedit.swiss.domain.entity.Tournament;
|
||||||
|
import nl.connectedit.swiss.domain.TournamentStatus;
|
||||||
|
import nl.connectedit.swiss.domain.entity.TournamentPlayer;
|
||||||
|
import nl.connectedit.swiss.dto.TournamentDto;
|
||||||
|
import nl.connectedit.swiss.dto.TournamentPlayerDto;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class TournamentMapper implements DtoMapper<Tournament, TournamentDto>, EntityMapper<TournamentDto, Tournament> {
|
||||||
|
|
||||||
|
private final EventMapper eventMapper;
|
||||||
|
|
||||||
|
private final TournamentPlayerMapper tournamentPlayerMapper;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Tournament toEntity(TournamentDto tournamentDto) {
|
||||||
|
Tournament tournament = new Tournament();
|
||||||
|
tournament.setId(tournamentDto.getId());
|
||||||
|
tournament.setName(tournamentDto.getName());
|
||||||
|
tournament.setDate(LocalDate.parse(tournamentDto.getDate(), DateTimeFormatter.ofPattern("dd-MM-yyyy")));
|
||||||
|
tournament.setStatus(
|
||||||
|
Arrays.stream(TournamentStatus.values())
|
||||||
|
.filter(ts -> ts.getText().equals(tournamentDto.getStatus()))
|
||||||
|
.findFirst()
|
||||||
|
.orElse(TournamentStatus.UPCOMING)
|
||||||
|
);
|
||||||
|
tournament.setMaxEvents(tournamentDto.getMaxEvents());
|
||||||
|
tournament.setCostsPerEvent(tournamentDto.getCostsPerEvent());
|
||||||
|
tournament.setCourts(tournamentDto.getCourts());
|
||||||
|
|
||||||
|
return tournament;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public TournamentDto toDto(Tournament tournament) {
|
||||||
|
TournamentDto tournamentDto = new TournamentDto();
|
||||||
|
tournamentDto.setId(tournament.getId());
|
||||||
|
tournamentDto.setName(tournament.getName());
|
||||||
|
tournamentDto.setDate(tournament.getDate().format(DateTimeFormatter.ofPattern("dd-MM-yyyy")));
|
||||||
|
tournamentDto.setStatus(tournament.getStatus().name());
|
||||||
|
tournamentDto.setEvents(
|
||||||
|
tournament.getEvents()
|
||||||
|
.stream()
|
||||||
|
.map(eventMapper::toDto)
|
||||||
|
.toList()
|
||||||
|
);
|
||||||
|
|
||||||
|
if (tournament.getTournamentPlayers() != null) {
|
||||||
|
var tournamentPlayers = tournament.getTournamentPlayers();
|
||||||
|
|
||||||
|
tournamentPlayers.sort(Comparator.comparing((TournamentPlayer tournamentPlayer) -> tournamentPlayer.getPlayer().getLastName())
|
||||||
|
.thenComparing((TournamentPlayer tournamentPlayer) -> tournamentPlayer.getPlayer().getFirstName()));
|
||||||
|
|
||||||
|
tournamentDto.setTournamentPlayers(tournamentPlayers
|
||||||
|
.stream()
|
||||||
|
.map(tournamentPlayerMapper::toDto)
|
||||||
|
.toList()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
tournamentDto.setMaxEvents(tournament.getMaxEvents() == null ? 2L : tournament.getMaxEvents());
|
||||||
|
|
||||||
|
if (tournament.getCostsPerEvent() == null || tournament.getCostsPerEvent().isEmpty()) {
|
||||||
|
tournamentDto.setCostsPerEvent(List.of(0f, 0f, 0f));
|
||||||
|
} else {
|
||||||
|
tournamentDto.setCostsPerEvent(tournament.getCostsPerEvent());
|
||||||
|
}
|
||||||
|
|
||||||
|
tournamentDto.setCourts(tournament.getCourts() == null ? 1L : tournament.getCourts());
|
||||||
|
|
||||||
|
return tournamentDto;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
package nl.connectedit.swiss.mapper;
|
||||||
|
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import nl.connectedit.swiss.domain.entity.Team;
|
||||||
|
import nl.connectedit.swiss.domain.entity.TournamentPlayer;
|
||||||
|
import nl.connectedit.swiss.dto.TeamDto;
|
||||||
|
import nl.connectedit.swiss.dto.TournamentPlayerDto;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class TournamentPlayerMapper implements DtoMapper<TournamentPlayer, TournamentPlayerDto> {
|
||||||
|
|
||||||
|
private final PlayerMapper playerMapper;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public TournamentPlayerDto toDto(TournamentPlayer tournamentPlayer) {
|
||||||
|
var tournamentPlayerDto = new TournamentPlayerDto();
|
||||||
|
tournamentPlayerDto.setPlayerId(tournamentPlayer.getPlayer().getId());
|
||||||
|
tournamentPlayerDto.setName(tournamentPlayer.getPlayer().getFullName());
|
||||||
|
tournamentPlayerDto.setEvents(new ArrayList<>(tournamentPlayer.getEvents()));
|
||||||
|
tournamentPlayerDto.setPaid(tournamentPlayer.isPaid());
|
||||||
|
tournamentPlayerDto.setPresent(tournamentPlayer.isPresent());
|
||||||
|
|
||||||
|
return tournamentPlayerDto;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,78 @@
|
|||||||
|
package nl.connectedit.swiss.mapper;
|
||||||
|
|
||||||
|
import java.time.format.DateTimeFormatter;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import nl.connectedit.swiss.domain.TournamentStatus;
|
||||||
|
import nl.connectedit.swiss.domain.entity.Event;
|
||||||
|
import nl.connectedit.swiss.domain.EventType;
|
||||||
|
import nl.connectedit.swiss.domain.entity.Player;
|
||||||
|
import nl.connectedit.swiss.domain.Sex;
|
||||||
|
import nl.connectedit.swiss.domain.entity.Tournament;
|
||||||
|
import nl.connectedit.swiss.dto.EventRegistrationDto;
|
||||||
|
import nl.connectedit.swiss.dto.TournamentRegistrationDto;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class TournamentPlayerRegistrationMapper {
|
||||||
|
|
||||||
|
public List<TournamentRegistrationDto> mapToDto(List<Tournament> tournaments, Player player) {
|
||||||
|
return tournaments.stream()
|
||||||
|
.map(tournament -> this.mapToTournamentRegistrationDto(tournament, player))
|
||||||
|
.toList();
|
||||||
|
}
|
||||||
|
|
||||||
|
public TournamentRegistrationDto mapToTournamentRegistrationDto(Tournament tournament, Player player) {
|
||||||
|
TournamentRegistrationDto tournamentRegistrationDto = new TournamentRegistrationDto();
|
||||||
|
tournamentRegistrationDto.setId(tournament.getId());
|
||||||
|
tournamentRegistrationDto.setName(tournament.getName());
|
||||||
|
tournamentRegistrationDto.setEditable(tournament.getStatus() == TournamentStatus.UPCOMING);
|
||||||
|
tournamentRegistrationDto.setDate(tournament.getDate().format(DateTimeFormatter.ofPattern("dd-MM-yyyy")));
|
||||||
|
tournamentRegistrationDto.setStatus(tournament.getStatus().name());
|
||||||
|
tournamentRegistrationDto.setEvents(
|
||||||
|
tournament.getEvents()
|
||||||
|
.stream()
|
||||||
|
.filter(event -> isRelevant(event, player))
|
||||||
|
.map(event -> this.mapToEventRegistrationDto(event, player))
|
||||||
|
.toList()
|
||||||
|
);
|
||||||
|
|
||||||
|
return tournamentRegistrationDto;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isRelevant(Event event, Player player) {
|
||||||
|
if (player.getSex() == Sex.M) {
|
||||||
|
return switch(event.getType()) {
|
||||||
|
case EventType.HE, EventType.HD, EventType.GD -> true;
|
||||||
|
default -> false;
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
return switch(event.getType()) {
|
||||||
|
case EventType.DE, EventType.DD, EventType.GD -> true;
|
||||||
|
default -> false;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private EventRegistrationDto mapToEventRegistrationDto(Event event, Player player) {
|
||||||
|
EventRegistrationDto eventRegistrationDto = new EventRegistrationDto();
|
||||||
|
eventRegistrationDto.setId(event.getId());
|
||||||
|
eventRegistrationDto.setType(event.getType().name());
|
||||||
|
eventRegistrationDto.setDoublesEvent(event.getType().isDoublesEvent());
|
||||||
|
for (var registration : event.getRegistrations()) {
|
||||||
|
if (registration.getPlayer().getId().equals(player.getId())) {
|
||||||
|
eventRegistrationDto.setRegistered(true);
|
||||||
|
eventRegistrationDto.setPlayer(registration.getPlayer().getId());
|
||||||
|
if (registration.getPartner() != null) {
|
||||||
|
eventRegistrationDto.setPartner(registration.getPartner().getId());
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
eventRegistrationDto.setRegistered(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return eventRegistrationDto;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,45 @@
|
|||||||
|
package nl.connectedit.swiss.mapper;
|
||||||
|
|
||||||
|
import nl.connectedit.swiss.domain.Validation;
|
||||||
|
import nl.connectedit.swiss.domain.EventValidation;
|
||||||
|
import nl.connectedit.swiss.domain.TournamentValidation;
|
||||||
|
import nl.connectedit.swiss.dto.EventValidationDto;
|
||||||
|
import nl.connectedit.swiss.dto.TournamentValidationDto;
|
||||||
|
import nl.connectedit.swiss.dto.ValidationDto;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
public class TournamentValidationMapper {
|
||||||
|
|
||||||
|
public TournamentValidationDto toDto(TournamentValidation tournamentValidation) {
|
||||||
|
var tournamentValidationDto = new TournamentValidationDto();
|
||||||
|
tournamentValidationDto.setId(tournamentValidation.getTournamentId());
|
||||||
|
tournamentValidationDto.setValidations(tournamentValidation.getValidations());
|
||||||
|
tournamentValidationDto.setEventValidations(
|
||||||
|
tournamentValidation.getEventValidations()
|
||||||
|
.stream()
|
||||||
|
.map(this::toEventValidationDto)
|
||||||
|
.toList()
|
||||||
|
);
|
||||||
|
return tournamentValidationDto;
|
||||||
|
}
|
||||||
|
|
||||||
|
private EventValidationDto toEventValidationDto(EventValidation eventValidation) {
|
||||||
|
var eventValidationDto = new EventValidationDto();
|
||||||
|
eventValidationDto.setEventId(eventValidation.getEventId());
|
||||||
|
eventValidationDto.setValidations(
|
||||||
|
eventValidation.getValidations()
|
||||||
|
.stream()
|
||||||
|
.map(this::toValidationDto)
|
||||||
|
.toList()
|
||||||
|
);
|
||||||
|
return eventValidationDto;
|
||||||
|
}
|
||||||
|
|
||||||
|
private ValidationDto toValidationDto(Validation validation) {
|
||||||
|
var validationDto = new ValidationDto();
|
||||||
|
validationDto.setSeverity(validation.getSeverity().name());
|
||||||
|
validationDto.setMessage(validation.getMessage());
|
||||||
|
return validationDto;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
package nl.connectedit.swiss.repository;
|
||||||
|
|
||||||
|
import nl.connectedit.swiss.domain.entity.Player;
|
||||||
|
import org.springframework.data.jpa.repository.JpaRepository;
|
||||||
|
|
||||||
|
public interface PlayerRepository extends JpaRepository<Player, Long> {
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
package nl.connectedit.swiss.repository;
|
||||||
|
|
||||||
|
import nl.connectedit.swiss.domain.entity.Registration;
|
||||||
|
import org.springframework.data.jpa.repository.JpaRepository;
|
||||||
|
import org.springframework.data.jpa.repository.Query;
|
||||||
|
import org.springframework.data.repository.query.Param;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public interface RegistrationRepository extends JpaRepository<Registration, Long> {
|
||||||
|
|
||||||
|
@Query("""
|
||||||
|
select r from Registration r
|
||||||
|
where r.player.id = :playerId
|
||||||
|
""")
|
||||||
|
List<Registration> findRegistrationsForPlayer(@Param("playerId") Long playerId);
|
||||||
|
}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
package nl.connectedit.swiss.repository;
|
||||||
|
|
||||||
|
import nl.connectedit.swiss.domain.entity.Tournament;
|
||||||
|
import nl.connectedit.swiss.domain.TournamentStatus;
|
||||||
|
import org.springframework.data.jpa.repository.JpaRepository;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public interface TournamentRepository extends JpaRepository<Tournament, Long> {
|
||||||
|
|
||||||
|
List<Tournament> findAllByStatus(TournamentStatus status);
|
||||||
|
}
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
package nl.connectedit.swiss.service;
|
||||||
|
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import nl.connectedit.swiss.domain.entity.Player;
|
||||||
|
import nl.connectedit.swiss.repository.PlayerRepository;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class PlayerService {
|
||||||
|
|
||||||
|
private final PlayerRepository playerRepository;
|
||||||
|
|
||||||
|
public Player savePlayer(Player player) {
|
||||||
|
return playerRepository.save(player);
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Player> findAllPlayers() {
|
||||||
|
return playerRepository.findAll();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Player findPlayerById(Long id) {
|
||||||
|
return playerRepository.getReferenceById(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,53 @@
|
|||||||
|
package nl.connectedit.swiss.service;
|
||||||
|
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import nl.connectedit.swiss.domain.entity.Player;
|
||||||
|
import nl.connectedit.swiss.domain.entity.Registration;
|
||||||
|
import nl.connectedit.swiss.domain.entity.Tournament;
|
||||||
|
import nl.connectedit.swiss.dto.EventRegistrationDto;
|
||||||
|
import nl.connectedit.swiss.repository.RegistrationRepository;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class RegistrationService {
|
||||||
|
|
||||||
|
private final TournamentService tournamentService;
|
||||||
|
|
||||||
|
private final PlayerService playerService;
|
||||||
|
|
||||||
|
public void updateOrAddRegistrations(EventRegistrationDto eventRegistration, Tournament tournament, Player player) {
|
||||||
|
var event = tournament.getEvents().stream().filter(e -> e.getId().equals(eventRegistration.getId())).findFirst().orElseThrow();
|
||||||
|
|
||||||
|
if (!eventRegistration.isRegistered()) { // remove any existing registration
|
||||||
|
event.getRegistrations().removeIf(registration -> registration.getPlayer().equals(player));
|
||||||
|
} else {
|
||||||
|
var optionalExistingPlayerRegistration = event.getRegistrations().stream()
|
||||||
|
.filter(registration -> registration.getPlayer().equals(player))
|
||||||
|
.findAny();
|
||||||
|
if (optionalExistingPlayerRegistration.isEmpty()) { // no previous registration for this event
|
||||||
|
var newRegistration = new Registration();
|
||||||
|
newRegistration.setTournament(tournament);
|
||||||
|
newRegistration.setEvent(event);
|
||||||
|
newRegistration.setPlayer(player);
|
||||||
|
if (eventRegistration.getPartner() != null){
|
||||||
|
var partner = playerService.findPlayerById(eventRegistration.getPartner());
|
||||||
|
newRegistration.setPartner(partner);
|
||||||
|
}
|
||||||
|
event.addRegistration(newRegistration);
|
||||||
|
} else { // change existing registration
|
||||||
|
var existingPlayerRegistration = optionalExistingPlayerRegistration.get();
|
||||||
|
if (eventRegistration.getPartner() != null){
|
||||||
|
var partner = playerService.findPlayerById(eventRegistration.getPartner());
|
||||||
|
existingPlayerRegistration.setPartner(partner);
|
||||||
|
} else {
|
||||||
|
existingPlayerRegistration.setPartner(null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
tournamentService.saveTournament(tournament);
|
||||||
|
}
|
||||||
|
}
|
||||||
51
src/main/java/nl/connectedit/swiss/service/ServiceUtil.java
Normal file
51
src/main/java/nl/connectedit/swiss/service/ServiceUtil.java
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
package nl.connectedit.swiss.service;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Objects;
|
||||||
|
import nl.connectedit.swiss.domain.entity.Event;
|
||||||
|
import nl.connectedit.swiss.domain.entity.Group;
|
||||||
|
import nl.connectedit.swiss.domain.entity.Match;
|
||||||
|
import nl.connectedit.swiss.domain.entity.Round;
|
||||||
|
import nl.connectedit.swiss.domain.entity.Tournament;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
public class ServiceUtil {
|
||||||
|
|
||||||
|
static Group getGroup(Tournament tournament, Long groupId) {
|
||||||
|
return tournament.getEvents()
|
||||||
|
.stream()
|
||||||
|
.map(Event::getGroups)
|
||||||
|
.flatMap(Collection::stream)
|
||||||
|
.filter(group -> Objects.equals(group.getId(), groupId))
|
||||||
|
.findAny()
|
||||||
|
.orElseThrow();
|
||||||
|
}
|
||||||
|
|
||||||
|
static Round getRound(Tournament tournament, Long roundId) {
|
||||||
|
return tournament.getEvents()
|
||||||
|
.stream()
|
||||||
|
.map(Event::getGroups)
|
||||||
|
.flatMap(Collection::stream)
|
||||||
|
.map(Group::getRounds)
|
||||||
|
.flatMap(Collection::stream)
|
||||||
|
.filter(round -> Objects.equals(round.getId(), roundId))
|
||||||
|
.findAny()
|
||||||
|
.orElseThrow();
|
||||||
|
}
|
||||||
|
|
||||||
|
static Match getMatch(Tournament tournament, Long matchId) {
|
||||||
|
return tournament.getEvents()
|
||||||
|
.stream()
|
||||||
|
.map(Event::getGroups)
|
||||||
|
.flatMap(Collection::stream)
|
||||||
|
.map(Group::getRounds)
|
||||||
|
.flatMap(Collection::stream)
|
||||||
|
.map(Round::getMatches)
|
||||||
|
.flatMap(Collection::stream)
|
||||||
|
.filter(match -> Objects.equals(match.getId(), matchId))
|
||||||
|
.findAny()
|
||||||
|
.orElseThrow();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
116
src/main/java/nl/connectedit/swiss/service/StandingsService.java
Normal file
116
src/main/java/nl/connectedit/swiss/service/StandingsService.java
Normal file
@@ -0,0 +1,116 @@
|
|||||||
|
package nl.connectedit.swiss.service;
|
||||||
|
|
||||||
|
import nl.connectedit.swiss.domain.entity.Group;
|
||||||
|
import nl.connectedit.swiss.domain.entity.Match;
|
||||||
|
import nl.connectedit.swiss.domain.entity.Round;
|
||||||
|
import nl.connectedit.swiss.domain.entity.Team;
|
||||||
|
import nl.connectedit.swiss.dto.StandingsEntry;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
public class StandingsService {
|
||||||
|
|
||||||
|
public List<StandingsEntry> getStandings(List<Round> rounds, List<Team> teams) {
|
||||||
|
var standings = new ArrayList<StandingsEntry>();
|
||||||
|
teams.forEach(team -> standings.add(new StandingsEntry(team)));
|
||||||
|
if (rounds != null) {
|
||||||
|
for (var round : rounds) {
|
||||||
|
addRoundToStandings(standings, round);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return sortStandings(standings);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void addRoundToStandings(List<StandingsEntry> standings, Round round) {
|
||||||
|
var matches = round.getMatches();
|
||||||
|
|
||||||
|
for (var match : matches) {
|
||||||
|
addMatchToStandingsEntry(standings, match);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void addMatchToStandingsEntry(List<StandingsEntry> standings, Match match) {
|
||||||
|
if (!match.getPlayed()) return;
|
||||||
|
|
||||||
|
var standingTeam1 = getStandingsEntryForTeam(standings, match.getTeam1());
|
||||||
|
var standingTeam2 = getStandingsEntryForTeam(standings, match.getTeam2());
|
||||||
|
|
||||||
|
standingTeam1.setPlayed(standingTeam1.getPlayed() + 1);
|
||||||
|
standingTeam2.setPlayed(standingTeam2.getPlayed() + 1);
|
||||||
|
|
||||||
|
standingTeam1.setPointsWon(standingTeam1.getPointsWon() + match.getGames().get(0).getScore1());
|
||||||
|
standingTeam2.setPointsWon(standingTeam2.getPointsWon() + match.getGames().get(0).getScore2());
|
||||||
|
standingTeam1.setPointsLost(standingTeam1.getPointsLost() + match.getGames().get(0).getScore2());
|
||||||
|
standingTeam2.setPointsLost(standingTeam2.getPointsLost() + match.getGames().get(0).getScore1());
|
||||||
|
|
||||||
|
standingTeam1.setPointsWon(standingTeam1.getPointsWon() + match.getGames().get(1).getScore1());
|
||||||
|
standingTeam2.setPointsWon(standingTeam2.getPointsWon() + match.getGames().get(1).getScore2());
|
||||||
|
standingTeam1.setPointsLost(standingTeam1.getPointsLost() + match.getGames().get(1).getScore2());
|
||||||
|
standingTeam2.setPointsLost(standingTeam2.getPointsLost() + match.getGames().get(1).getScore1());
|
||||||
|
|
||||||
|
if (match.getGames().size() == 3) {
|
||||||
|
standingTeam1.setPointsWon(standingTeam1.getPointsWon() + match.getGames().get(2).getScore1());
|
||||||
|
standingTeam2.setPointsWon(standingTeam2.getPointsWon() + match.getGames().get(2).getScore2());
|
||||||
|
standingTeam1.setPointsLost(standingTeam1.getPointsLost() + match.getGames().get(2).getScore2());
|
||||||
|
standingTeam2.setPointsLost(standingTeam2.getPointsLost() + match.getGames().get(2).getScore1());
|
||||||
|
|
||||||
|
if (match.getGames().get(2).getScore1() > match.getGames().get(2).getScore2()) {
|
||||||
|
standingTeam1.setWon(standingTeam1.getWon() + 1);
|
||||||
|
standingTeam1.setPoints(standingTeam1.getPoints() + 2);
|
||||||
|
standingTeam1.setGamesWon(standingTeam1.getGamesWon() + 2);
|
||||||
|
standingTeam1.setGamesLost(standingTeam1.getGamesLost() + 1);
|
||||||
|
|
||||||
|
standingTeam2.setLost(standingTeam2.getLost() + 1);
|
||||||
|
standingTeam2.setGamesWon(standingTeam2.getGamesWon() + 1);
|
||||||
|
standingTeam2.setGamesLost(standingTeam2.getGamesLost() + 2);
|
||||||
|
} else {
|
||||||
|
standingTeam1.setLost(standingTeam1.getLost() + 1);
|
||||||
|
standingTeam1.setGamesWon(standingTeam1.getGamesWon() + 1);
|
||||||
|
standingTeam1.setGamesLost(standingTeam1.getGamesLost() + 2);
|
||||||
|
|
||||||
|
standingTeam2.setWon(standingTeam2.getWon() + 1);
|
||||||
|
standingTeam2.setPoints(standingTeam2.getPoints() + 2);
|
||||||
|
standingTeam2.setGamesWon(standingTeam2.getGamesWon() + 2);
|
||||||
|
standingTeam2.setGamesLost(standingTeam2.getGamesLost() + 1);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (match.getGames().get(1).getScore1() > match.getGames().get(1).getScore2()) {
|
||||||
|
standingTeam1.setWon(standingTeam1.getWon() + 1);
|
||||||
|
standingTeam1.setPoints(standingTeam1.getPoints() + 2);
|
||||||
|
standingTeam1.setGamesWon(standingTeam1.getGamesWon() + 2);
|
||||||
|
|
||||||
|
standingTeam2.setLost(standingTeam2.getLost() + 1);
|
||||||
|
standingTeam2.setGamesLost(standingTeam2.getGamesLost() + 2);
|
||||||
|
} else {
|
||||||
|
standingTeam1.setLost(standingTeam1.getLost() + 1);
|
||||||
|
standingTeam1.setGamesLost(standingTeam2.getGamesLost() + 2);
|
||||||
|
|
||||||
|
standingTeam2.setWon(standingTeam2.getWon() + 1);
|
||||||
|
standingTeam2.setPoints(standingTeam2.getPoints() + 2);
|
||||||
|
standingTeam2.setGamesWon(standingTeam2.getGamesWon() + 2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private StandingsEntry getStandingsEntryForTeam(List<StandingsEntry> standings, Team team) {
|
||||||
|
return standings.stream().filter(standingsEntry -> Objects.equals(standingsEntry.getTeam(), team)).findAny().orElse(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<StandingsEntry> sortStandings(List<StandingsEntry> standings) {
|
||||||
|
var sortedStandings = standings
|
||||||
|
.stream()
|
||||||
|
.sorted(StandingsEntry::compare)
|
||||||
|
.toList();
|
||||||
|
|
||||||
|
var position = 0L;
|
||||||
|
for (var standing : sortedStandings) {
|
||||||
|
standing.setPosition(++position);
|
||||||
|
}
|
||||||
|
return sortedStandings;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,157 @@
|
|||||||
|
package nl.connectedit.swiss.service;
|
||||||
|
|
||||||
|
import jakarta.transaction.Transactional;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Comparator;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Objects;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import nl.connectedit.swiss.domain.EventType;
|
||||||
|
import nl.connectedit.swiss.domain.Status;
|
||||||
|
import nl.connectedit.swiss.domain.TournamentStatus;
|
||||||
|
import nl.connectedit.swiss.domain.entity.Event;
|
||||||
|
import nl.connectedit.swiss.domain.entity.Group;
|
||||||
|
import nl.connectedit.swiss.domain.entity.Registration;
|
||||||
|
import nl.connectedit.swiss.domain.entity.Team;
|
||||||
|
import nl.connectedit.swiss.domain.entity.Tournament;
|
||||||
|
import nl.connectedit.swiss.repository.TournamentRepository;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class TournamentDivideService {
|
||||||
|
|
||||||
|
private final TournamentValidationService tournamentValidationService;
|
||||||
|
|
||||||
|
private final TournamentRepository tournamentRepository;
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
public Tournament divide(Tournament tournament) {
|
||||||
|
if (tournamentValidationService.validate(tournament).hasErrors()) {
|
||||||
|
return tournament;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (var event : tournament.getEvents()) {
|
||||||
|
if (event.getRegistrations().size() >= 4) {
|
||||||
|
divide(event);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
tournament.setStatus(TournamentStatus.DIVIDED);
|
||||||
|
|
||||||
|
tournamentRepository.save(tournament);
|
||||||
|
|
||||||
|
return tournament;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void divide(Event event) {
|
||||||
|
List<Registration> registrations;
|
||||||
|
if (event.getType().isDoublesEvent()) {
|
||||||
|
registrations = groupRegistrations(event.getRegistrations());
|
||||||
|
} else {
|
||||||
|
registrations = event.getRegistrations();
|
||||||
|
}
|
||||||
|
|
||||||
|
event.setGroups(new ArrayList<>());
|
||||||
|
|
||||||
|
if (registrations.size() <= 16) {
|
||||||
|
var group = getGroup(registrations, event.getType());
|
||||||
|
group.setEvent(event);
|
||||||
|
event.getGroups().add(group);
|
||||||
|
} else {
|
||||||
|
var groups = getGroups(registrations, event.getType());
|
||||||
|
event.getGroups().addAll(groups);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<Registration> groupRegistrations(List<Registration> registrations) {
|
||||||
|
var groupedRegistrations = new ArrayList<Registration>();
|
||||||
|
|
||||||
|
nextRegistration:
|
||||||
|
for (var registration : registrations) {
|
||||||
|
for (var groupedRegistration : groupedRegistrations) {
|
||||||
|
if (Objects.equals(groupedRegistration.getPartner(), registration.getPlayer())) {
|
||||||
|
continue nextRegistration;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
groupedRegistrations.add(registration);
|
||||||
|
}
|
||||||
|
return groupedRegistrations;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Group getGroup(List<Registration> registrations, EventType type) {
|
||||||
|
var group = new Group();
|
||||||
|
group.setName(type.getText());
|
||||||
|
group.setType(type);
|
||||||
|
group.setStatus(Status.IN_PROGRESS);
|
||||||
|
group.setTeams(new ArrayList<>());
|
||||||
|
for (var registration : registrations) {
|
||||||
|
group.getTeams().add(getTeam(registration, group));
|
||||||
|
}
|
||||||
|
|
||||||
|
return group;
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<Group> getGroups(List<Registration> orgRegistrations, EventType type) {
|
||||||
|
var registrations = new ArrayList<>(orgRegistrations);
|
||||||
|
|
||||||
|
var group1 = new Group();
|
||||||
|
group1.setName(type.getText() + " 1");
|
||||||
|
group1.setType(type);
|
||||||
|
group1.setStatus(Status.IN_PROGRESS);
|
||||||
|
group1.setTeams(new ArrayList<>());
|
||||||
|
var group2 = new Group();
|
||||||
|
group2.setName(type.getText() + " 2");
|
||||||
|
group2.setType(type);
|
||||||
|
group2.setStatus(Status.IN_PROGRESS);
|
||||||
|
group2.setTeams(new ArrayList<>());
|
||||||
|
|
||||||
|
var registrationStrengthMap = new HashMap<Registration, Integer>();
|
||||||
|
for (var registration : registrations) {
|
||||||
|
var strength = registration.getPlayer().getStrength().getCoefficient();
|
||||||
|
if (registration.getPartner() != null) {
|
||||||
|
strength += registration.getPartner().getStrength().getCoefficient();
|
||||||
|
}
|
||||||
|
registrationStrengthMap.put(registration, strength);
|
||||||
|
}
|
||||||
|
|
||||||
|
var sortedRegistrations = registrationStrengthMap
|
||||||
|
.entrySet()
|
||||||
|
.stream()
|
||||||
|
.sorted(Map.Entry.comparingByValue(Comparator.reverseOrder()))
|
||||||
|
.map(Map.Entry::getKey)
|
||||||
|
.toList();
|
||||||
|
|
||||||
|
for (Iterator<Registration> i = sortedRegistrations.iterator(); i.hasNext(); ) {
|
||||||
|
group1.getTeams().add(getTeam(i.next(), group1));
|
||||||
|
if (i.hasNext()) {
|
||||||
|
group2.getTeams().add(getTeam(i.next(), group2));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return List.of(group1, group2);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Team getTeam(Registration registration, Group group) {
|
||||||
|
var team = new Team();
|
||||||
|
team.setPlayer1(registration.getPlayer());
|
||||||
|
team.setPlayer2(registration.getPartner());
|
||||||
|
team.setGroup(group);
|
||||||
|
|
||||||
|
return team;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Tournament clear(Tournament tournament) {
|
||||||
|
for (var event : tournament.getEvents()) {
|
||||||
|
event.getGroups().clear();
|
||||||
|
}
|
||||||
|
tournament.setStatus(TournamentStatus.UPCOMING);
|
||||||
|
|
||||||
|
tournamentRepository.save(tournament);
|
||||||
|
|
||||||
|
return tournament;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,183 @@
|
|||||||
|
package nl.connectedit.swiss.service;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import nl.connectedit.swiss.domain.Status;
|
||||||
|
import nl.connectedit.swiss.domain.TournamentStatus;
|
||||||
|
import nl.connectedit.swiss.domain.entity.*;
|
||||||
|
import nl.connectedit.swiss.repository.TournamentRepository;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class TournamentDrawService {
|
||||||
|
|
||||||
|
private final TournamentRepository tournamentRepository;
|
||||||
|
|
||||||
|
public Tournament draw(Tournament tournament) {
|
||||||
|
if (!tournamentIsReadyForDraw(tournament)) return null;
|
||||||
|
|
||||||
|
for (var event : tournament.getEvents()) {
|
||||||
|
for (var group : event.getGroups()) {
|
||||||
|
var round = new Round();
|
||||||
|
round.setName("Ronde 1");
|
||||||
|
round.setGroup(group);
|
||||||
|
round.setMatches(createMatchList(group, round));
|
||||||
|
round.setStatus(Status.NOT_STARTED);
|
||||||
|
group.getRounds().add(round);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
registerTournamentPlayers(tournament);
|
||||||
|
|
||||||
|
tournament.setStatus(TournamentStatus.DRAWN);
|
||||||
|
|
||||||
|
tournamentRepository.save(tournament);
|
||||||
|
|
||||||
|
return tournament;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void registerTournamentPlayers(Tournament tournament) {
|
||||||
|
var players = new HashSet<Player>();
|
||||||
|
for (var event : tournament.getEvents()) {
|
||||||
|
for (var group : event.getGroups()) {
|
||||||
|
for (var team : group.getTeams()) {
|
||||||
|
players.add(team.getPlayer1());
|
||||||
|
if (team.getPlayer2() != null) players.add(team.getPlayer2());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (var player : players) {
|
||||||
|
var tournamentPlayer = new TournamentPlayer();
|
||||||
|
tournamentPlayer.setTournament(tournament);
|
||||||
|
tournamentPlayer.setPlayer(player);
|
||||||
|
tournamentPlayer.setEvents(
|
||||||
|
tournament.getEvents()
|
||||||
|
.stream()
|
||||||
|
.filter(event ->
|
||||||
|
event.getRegistrations()
|
||||||
|
.stream()
|
||||||
|
.anyMatch(r -> r.getPlayer().equals(player)))
|
||||||
|
.map(Event::getType)
|
||||||
|
.map(Enum::name)
|
||||||
|
.toList()
|
||||||
|
);
|
||||||
|
tournament.getTournamentPlayers().add(tournamentPlayer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Tournament clear(Tournament tournament) {
|
||||||
|
if (!tournamentIsDrawn(tournament)) return tournament;
|
||||||
|
|
||||||
|
for (var event : tournament.getEvents()) {
|
||||||
|
for (var group : event.getGroups()) {
|
||||||
|
group.getRounds().clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
tournament.getTournamentPlayers().clear();
|
||||||
|
|
||||||
|
tournament.setStatus(TournamentStatus.DIVIDED);
|
||||||
|
|
||||||
|
tournamentRepository.save(tournament);
|
||||||
|
|
||||||
|
return tournament;
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<Match> createMatchList(Group group, Round round) {
|
||||||
|
List<Match> matches;
|
||||||
|
var drawCounter = 0;
|
||||||
|
do {
|
||||||
|
drawCounter++;
|
||||||
|
matches = new ArrayList<>();
|
||||||
|
var teams = new ArrayList<>(group.getTeams());
|
||||||
|
|
||||||
|
Collections.shuffle(teams);
|
||||||
|
|
||||||
|
for (Iterator<Team> i = teams.iterator(); i.hasNext(); ) {
|
||||||
|
var match = new Match();
|
||||||
|
match.setType(group.getType());
|
||||||
|
match.setStatus(Status.NOT_STARTED);
|
||||||
|
match.setTeam1(i.next());
|
||||||
|
if (i.hasNext()) {
|
||||||
|
match.setTeam2(i.next());
|
||||||
|
} else {
|
||||||
|
round.setDrawnOut(match.getTeam1());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
match.setPlayed(false);
|
||||||
|
match.setRound(round);
|
||||||
|
matches.add(match);
|
||||||
|
}
|
||||||
|
} while (!drawIsValid(matches) || drawCounter == 1000);
|
||||||
|
|
||||||
|
return matches;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean drawIsValid(List<Match> matches) {
|
||||||
|
for (var match : matches) {
|
||||||
|
var clubs = getClubsFromMatch(match);
|
||||||
|
var distinctClubs = new HashSet<>(clubs).size();
|
||||||
|
if (!match.getType().isDoublesEvent()) {
|
||||||
|
if (distinctClubs == 1) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (distinctClubs == 1) {
|
||||||
|
return false;
|
||||||
|
} else if (distinctClubs == 2 && (teamPlayersHaveDifferentClub(match.getTeam1()) ^ teamPlayersHaveDifferentClub(match.getTeam2()))) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<String> getClubsFromMatch(Match match) {
|
||||||
|
var clubs = new ArrayList<String>();
|
||||||
|
|
||||||
|
clubs.add(match.getTeam1().getPlayer1().getClub());
|
||||||
|
if (match.getTeam1().getPlayer2() != null) {
|
||||||
|
clubs.add(match.getTeam1().getPlayer2().getClub());
|
||||||
|
}
|
||||||
|
clubs.add(match.getTeam2().getPlayer1().getClub());
|
||||||
|
if (match.getTeam2().getPlayer2() != null) {
|
||||||
|
clubs.add(match.getTeam2().getPlayer2().getClub());
|
||||||
|
}
|
||||||
|
|
||||||
|
return clubs;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean teamPlayersHaveDifferentClub(Team team) {
|
||||||
|
if (team.getPlayer2() == null) return true;
|
||||||
|
|
||||||
|
return !Objects.equals(team.getPlayer1().getClub(), team.getPlayer2().getClub());
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean tournamentIsReadyForDraw(Tournament tournament) {
|
||||||
|
return tournament.getStatus() == TournamentStatus.DIVIDED &&
|
||||||
|
tournament.getEvents()
|
||||||
|
.stream()
|
||||||
|
.map(Event::getGroups)
|
||||||
|
.flatMap(List::stream)
|
||||||
|
.map(Group::getRounds)
|
||||||
|
.flatMap(List::stream)
|
||||||
|
.toList()
|
||||||
|
.isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean tournamentIsDrawn(Tournament tournament) {
|
||||||
|
if (tournament.getStatus() != TournamentStatus.DRAWN) return false;
|
||||||
|
|
||||||
|
for (var event : tournament.getEvents()) {
|
||||||
|
for (var group : event.getGroups()) {
|
||||||
|
for (var round : group.getRounds()) {
|
||||||
|
if (round.getStatus() != Status.NOT_STARTED) return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user