diff --git a/FencerJudgeBack/build.gradle.kts b/FencerJudgeBack/build.gradle.kts index e72e48d..f64df6d 100644 --- a/FencerJudgeBack/build.gradle.kts +++ b/FencerJudgeBack/build.gradle.kts @@ -33,7 +33,7 @@ dependencies { implementation("org.springframework.boot:spring-boot-starter-websocket") // SECURITY - implementation("org.springframework.boot:spring-boot-starter-security") +// implementation("org.springframework.boot:spring-boot-starter-security") // H2 Database runtimeOnly("com.h2database:h2") diff --git a/FencerJudgeBack/src/main/kotlin/fr/teamflash/fencerjudgeback/config/ConfigSecurity.kt b/FencerJudgeBack/src/main/kotlin/fr/teamflash/fencerjudgeback/config/ConfigSecurity.kt deleted file mode 100644 index 373883d..0000000 --- a/FencerJudgeBack/src/main/kotlin/fr/teamflash/fencerjudgeback/config/ConfigSecurity.kt +++ /dev/null @@ -1,56 +0,0 @@ -package fr.teamflash.fencerjudgeback.config - -import org.springframework.beans.factory.annotation.Autowired -import org.springframework.context.annotation.Bean -import org.springframework.context.annotation.Configuration -import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder -import org.springframework.security.config.annotation.web.builders.HttpSecurity -import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity -import org.springframework.security.core.userdetails.User -import org.springframework.security.core.userdetails.UserDetailsService -import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder -import org.springframework.security.provisioning.InMemoryUserDetailsManager -import org.springframework.security.web.SecurityFilterChain - -@Configuration -@EnableWebSecurity -class SecurityConfig { - - @Autowired - open fun configureGlobal(auth: AuthenticationManagerBuilder) { - val encoder = BCryptPasswordEncoder() - - //Créer des utilisateurs fixes - auth.inMemoryAuthentication() - .passwordEncoder(encoder) - .withUser("aaa") - .password(encoder.encode("bbb")) - .roles("USER") - .and() - .withUser("Admin") - .password(encoder.encode("Admin")) - .roles("ADMIN") - } - - @Bean - open fun securityFilterChain(http: HttpSecurity): SecurityFilterChain { - http.authorizeHttpRequests { authorize -> - authorize.requestMatchers("/ws/*").authenticated() - .anyRequest().permitAll() - } - .httpBasic { } - .formLogin { } - .csrf { it.disable() } - return http.build() - } - - @Bean - fun userDetailsService(): UserDetailsService { - val user = User.withUsername("user") - .password("{noop}password") // {noop} = pas de hash pour dev - .roles("USER") - .build() - - return InMemoryUserDetailsManager(user) - } -} diff --git a/FencerJudgeBack/src/main/kotlin/fr/teamflash/fencerjudgeback/config/WebSocketConfig.kt b/FencerJudgeBack/src/main/kotlin/fr/teamflash/fencerjudgeback/config/MatchWebSocketConfig.kt similarity index 85% rename from FencerJudgeBack/src/main/kotlin/fr/teamflash/fencerjudgeback/config/WebSocketConfig.kt rename to FencerJudgeBack/src/main/kotlin/fr/teamflash/fencerjudgeback/config/MatchWebSocketConfig.kt index ec13cd2..6fc3650 100644 --- a/FencerJudgeBack/src/main/kotlin/fr/teamflash/fencerjudgeback/config/WebSocketConfig.kt +++ b/FencerJudgeBack/src/main/kotlin/fr/teamflash/fencerjudgeback/config/MatchWebSocketConfig.kt @@ -5,7 +5,6 @@ import org.springframework.messaging.simp.config.MessageBrokerRegistry import org.springframework.web.socket.config.annotation.EnableWebSocketMessageBroker import org.springframework.web.socket.config.annotation.StompEndpointRegistry import org.springframework.web.socket.config.annotation.WebSocketMessageBrokerConfigurer -import org.springframework.web.socket.server.support.HttpSessionHandshakeInterceptor const val CHANNEL_MATCH_NAME: String = "/ws/topic/match" @@ -19,13 +18,12 @@ open class MatchWebSocketConfig : WebSocketMessageBrokerConfigurer { registry.enableSimpleBroker(CHANNEL_MATCH_NAME) // Prefix for messages FROM client TO server - registry.setApplicationDestinationPrefixes("/ws") + registry.setApplicationDestinationPrefixes("/ws/matches") } override fun registerStompEndpoints(registry: StompEndpointRegistry) { // Register the "/ws" endpoint, enabling SockJS fallback options registry.addEndpoint("/ws/matches-app") - .addInterceptors(HttpSessionHandshakeInterceptor()) .setAllowedOriginPatterns("*") // Allow connections from any origin (adjust for production) .withSockJS() } diff --git a/FencerJudgeBack/src/main/kotlin/fr/teamflash/fencerjudgeback/config/PlayerWebSocketConfig.kt b/FencerJudgeBack/src/main/kotlin/fr/teamflash/fencerjudgeback/config/PlayerWebSocketConfig.kt new file mode 100644 index 0000000..012e601 --- /dev/null +++ b/FencerJudgeBack/src/main/kotlin/fr/teamflash/fencerjudgeback/config/PlayerWebSocketConfig.kt @@ -0,0 +1,30 @@ +package fr.teamflash.fencerjudgeback.config + +import org.springframework.context.annotation.Configuration +import org.springframework.messaging.simp.config.MessageBrokerRegistry +import org.springframework.web.socket.config.annotation.EnableWebSocketMessageBroker +import org.springframework.web.socket.config.annotation.StompEndpointRegistry +import org.springframework.web.socket.config.annotation.WebSocketMessageBrokerConfigurer + +const val CHANNEL_PLAYER_NAME: String = "/ws/topic/match" + +@Configuration +@EnableWebSocketMessageBroker +open class PlayerWebSocketConfig : WebSocketMessageBrokerConfigurer { + + override fun configureMessageBroker(registry: MessageBrokerRegistry) { + // Enable a simple memory-based message broker to send messages to clients + // Prefix for messages FROM server TO client + registry.enableSimpleBroker(CHANNEL_PLAYER_NAME) + + // Prefix for messages FROM client TO server + registry.setApplicationDestinationPrefixes("/ws") + } + + override fun registerStompEndpoints(registry: StompEndpointRegistry) { + // Register the "/ws" endpoint, enabling SockJS fallback options + registry.addEndpoint("/ws/players-app") + .setAllowedOriginPatterns("*") // Allow connections from any origin (adjust for production) + .withSockJS() + } +} \ No newline at end of file diff --git a/FencerJudgeBack/src/main/kotlin/fr/teamflash/fencerjudgeback/config/RefereeWebSocketConfig.kt b/FencerJudgeBack/src/main/kotlin/fr/teamflash/fencerjudgeback/config/RefereeWebSocketConfig.kt new file mode 100644 index 0000000..9d4cf59 --- /dev/null +++ b/FencerJudgeBack/src/main/kotlin/fr/teamflash/fencerjudgeback/config/RefereeWebSocketConfig.kt @@ -0,0 +1,30 @@ +package fr.teamflash.fencerjudgeback.config + +import org.springframework.context.annotation.Configuration +import org.springframework.messaging.simp.config.MessageBrokerRegistry +import org.springframework.web.socket.config.annotation.EnableWebSocketMessageBroker +import org.springframework.web.socket.config.annotation.StompEndpointRegistry +import org.springframework.web.socket.config.annotation.WebSocketMessageBrokerConfigurer + +const val CHANNEL_REFEREE_NAME: String = "/ws/topic/referee" + +@Configuration +@EnableWebSocketMessageBroker +open class RefereeWebSocketConfig : WebSocketMessageBrokerConfigurer { + + override fun configureMessageBroker(registry: MessageBrokerRegistry) { + // Enable a simple memory-based message broker to send messages to clients + // Prefix for messages FROM server TO client + registry.enableSimpleBroker(CHANNEL_REFEREE_NAME) + + // Prefix for messages FROM client TO server + registry.setApplicationDestinationPrefixes("/ws") + } + + override fun registerStompEndpoints(registry: StompEndpointRegistry) { + // Register the "/ws" endpoint, enabling SockJS fallback options + registry.addEndpoint("/ws/referees-app") + .setAllowedOriginPatterns("*") // Allow connections from any origin (adjust for production) + .withSockJS() + } +} \ No newline at end of file diff --git a/FencerJudgeBack/src/main/kotlin/fr/teamflash/fencerjudgeback/entities/MatchBean.kt b/FencerJudgeBack/src/main/kotlin/fr/teamflash/fencerjudgeback/entities/MatchBean.kt index f37c7fd..87ccf3e 100644 --- a/FencerJudgeBack/src/main/kotlin/fr/teamflash/fencerjudgeback/entities/MatchBean.kt +++ b/FencerJudgeBack/src/main/kotlin/fr/teamflash/fencerjudgeback/entities/MatchBean.kt @@ -6,14 +6,7 @@ import jakarta.persistence.GenerationType import jakarta.persistence.Id import jakarta.persistence.SequenceGenerator import jakarta.persistence.Table -import jakarta.validation.constraints.* -import java.util.Date - -enum class MatchState { - ONGOING, - OVER, - NOT_STARTED -} +import jakarta.validation.constraints.* @Entity @Table(name="matches") @@ -35,6 +28,6 @@ data class MatchBean( var score1:Int=0, @field:Min(value = 0, message = "Score must be at least 0") var score2:Int=0, - val date: Date?=null, - val state: MatchState?=null + val date: String?=null, + val state:String?=null ) diff --git a/FencerJudgeBack/src/main/kotlin/fr/teamflash/fencerjudgeback/entities/RefereeBean.kt b/FencerJudgeBack/src/main/kotlin/fr/teamflash/fencerjudgeback/entities/RefereeBean.kt index cb2570a..4756fee 100644 --- a/FencerJudgeBack/src/main/kotlin/fr/teamflash/fencerjudgeback/entities/RefereeBean.kt +++ b/FencerJudgeBack/src/main/kotlin/fr/teamflash/fencerjudgeback/entities/RefereeBean.kt @@ -7,13 +7,6 @@ import jakarta.persistence.Id import jakarta.persistence.SequenceGenerator import jakarta.persistence.Table -enum class RefereeLevel { - DEPARTMENTAL, - REGIONAL, - NATIONAL, - INTERNATIONAL -} - @Entity @Table(name="referees") data class RefereeBean( @@ -23,5 +16,5 @@ data class RefereeBean( val id:Long?=null, val name:String?=null, val firstName:String?=null, - val level:RefereeLevel?=null + val qualification:String?=null ) \ No newline at end of file diff --git a/FencerJudgeBack/src/main/kotlin/fr/teamflash/fencerjudgeback/restControllers/MainController.kt b/FencerJudgeBack/src/main/kotlin/fr/teamflash/fencerjudgeback/restControllers/MainController.kt deleted file mode 100644 index 5dbfd7a..0000000 --- a/FencerJudgeBack/src/main/kotlin/fr/teamflash/fencerjudgeback/restControllers/MainController.kt +++ /dev/null @@ -1,12 +0,0 @@ -package fr.teamflash.fencerjudgeback.restControllers - -import org.springframework.web.bind.annotation.GetMapping -import org.springframework.web.bind.annotation.RestController - -@RestController -class MainController { - @GetMapping("/") - fun main() { - return print("Hello") - } -} \ No newline at end of file diff --git a/FencerJudgeBack/src/main/kotlin/fr/teamflash/fencerjudgeback/restControllers/MatchRestController.kt b/FencerJudgeBack/src/main/kotlin/fr/teamflash/fencerjudgeback/restControllers/MatchRestController.kt index ab2e7de..0957c00 100644 --- a/FencerJudgeBack/src/main/kotlin/fr/teamflash/fencerjudgeback/restControllers/MatchRestController.kt +++ b/FencerJudgeBack/src/main/kotlin/fr/teamflash/fencerjudgeback/restControllers/MatchRestController.kt @@ -1,21 +1,14 @@ package fr.teamflash.fencerjudgeback.restControllers import fr.teamflash.fencerjudgeback.entities.MatchBean -import fr.teamflash.fencerjudgeback.entities.MatchState import fr.teamflash.fencerjudgeback.services.MatchService import org.springframework.http.ResponseEntity import org.springframework.web.bind.annotation.* -import java.util.Date @RestController -@CrossOrigin(origins = ["*"]) @RequestMapping("/matches") class MatchRestController(private val matchService: MatchService) { - companion object { - const val URL_ORIGIN: String = "http://localhost:*" - } - // Lister tous les matchs @GetMapping("/") fun getAll(): ResponseEntity?> { @@ -24,7 +17,7 @@ class MatchRestController(private val matchService: MatchService) { // Lister tous les matchs à partir d'une certaine date @GetMapping("/date/{date}") - fun getAllFromDate(@PathVariable date: Date): ResponseEntity?> { + fun getAllFromDate(@PathVariable date:String): ResponseEntity?> { return ResponseEntity.ok(matchService.getAll().filter { it.date == date }) } @@ -49,19 +42,19 @@ class MatchRestController(private val matchService: MatchService) { // Lister les matchs en cours @GetMapping("/active") fun getAllActive(): ResponseEntity?> { - return ResponseEntity.ok(matchService.getAll().filter { it.state == MatchState.ONGOING }) + return ResponseEntity.ok(matchService.getAll().filter { it.state == "ACTIVE" }) } // Lister les matchs terminés @GetMapping("/over") fun getAllFinished(): ResponseEntity?> { - return ResponseEntity.ok(matchService.getAll().filter { it.state == MatchState.OVER }) + return ResponseEntity.ok(matchService.getAll().filter { it.state == "FINISHED" }) } // Lister les matchs non commencés @GetMapping("/not-started") fun getAllNotStarted(): ResponseEntity?> { - return ResponseEntity.ok(matchService.getAll().filter { it.state == MatchState.NOT_STARTED }) + return ResponseEntity.ok(matchService.getAll().filter { it.state == "NOT STARTED" }) } // Afficher un match par id @@ -73,6 +66,7 @@ class MatchRestController(private val matchService: MatchService) { // Ajouter un match @PostMapping("/create-match") fun createMatch(@RequestBody match: MatchBean): ResponseEntity { +// return ResponseEntity.status(HttpStatus.CREATED).body(matchService.createMatch(match)) return ResponseEntity.ok(matchService.createMatch(match)) } diff --git a/FencerJudgeBack/src/main/kotlin/fr/teamflash/fencerjudgeback/restControllers/PlayerRestController.kt b/FencerJudgeBack/src/main/kotlin/fr/teamflash/fencerjudgeback/restControllers/PlayerRestController.kt index 628282a..699c557 100644 --- a/FencerJudgeBack/src/main/kotlin/fr/teamflash/fencerjudgeback/restControllers/PlayerRestController.kt +++ b/FencerJudgeBack/src/main/kotlin/fr/teamflash/fencerjudgeback/restControllers/PlayerRestController.kt @@ -3,7 +3,6 @@ package fr.teamflash.fencerjudgeback.restControllers import fr.teamflash.fencerjudgeback.entities.PlayerBean import fr.teamflash.fencerjudgeback.services.PlayerService import org.springframework.http.ResponseEntity -import org.springframework.web.bind.annotation.CrossOrigin import org.springframework.web.bind.annotation.DeleteMapping import org.springframework.web.bind.annotation.GetMapping import org.springframework.web.bind.annotation.PathVariable @@ -14,7 +13,6 @@ import org.springframework.web.bind.annotation.RequestMapping import org.springframework.web.bind.annotation.RestController @RestController -@CrossOrigin(origins = ["*"]) @RequestMapping("/players") class PlayerRestController(private val playerService: PlayerService) { diff --git a/FencerJudgeBack/src/main/kotlin/fr/teamflash/fencerjudgeback/restControllers/RefereeRestController.kt b/FencerJudgeBack/src/main/kotlin/fr/teamflash/fencerjudgeback/restControllers/RefereeRestController.kt index 42ca424..e26e90f 100644 --- a/FencerJudgeBack/src/main/kotlin/fr/teamflash/fencerjudgeback/restControllers/RefereeRestController.kt +++ b/FencerJudgeBack/src/main/kotlin/fr/teamflash/fencerjudgeback/restControllers/RefereeRestController.kt @@ -1,11 +1,8 @@ package fr.teamflash.fencerjudgeback.restControllers -import fr.teamflash.fencerjudgeback.entities.MatchState import fr.teamflash.fencerjudgeback.entities.RefereeBean -import fr.teamflash.fencerjudgeback.entities.RefereeLevel import fr.teamflash.fencerjudgeback.services.RefereeService import org.springframework.http.ResponseEntity -import org.springframework.web.bind.annotation.CrossOrigin import org.springframework.web.bind.annotation.DeleteMapping import org.springframework.web.bind.annotation.GetMapping import org.springframework.web.bind.annotation.PathVariable @@ -16,7 +13,6 @@ import org.springframework.web.bind.annotation.RequestMapping import org.springframework.web.bind.annotation.RestController @RestController -@CrossOrigin(origins = ["*"]) @RequestMapping("/referees") class RefereeRestController(private val refereeService: RefereeService) { @@ -44,10 +40,10 @@ class RefereeRestController(private val refereeService: RefereeService) { return ResponseEntity.ok(refereeService.getByFirstName(firstName)) } - // Afficher un ou plusieurs arbitre(s) par niveau - @GetMapping("/level/{level}") - fun getByQualification(@PathVariable level: RefereeLevel): ResponseEntity?> { - return ResponseEntity.ok(refereeService.getByLevel(level)) + // Afficher un ou plusieurs arbitre(s) par qualification + @GetMapping("/qualification/{qualification}") + fun getByQualification(@PathVariable qualification:String): ResponseEntity?> { + return ResponseEntity.ok(refereeService.getByQualification(qualification)) } // Ajouter un arbitre diff --git a/FencerJudgeBack/src/main/kotlin/fr/teamflash/fencerjudgeback/services/RefereeService.kt b/FencerJudgeBack/src/main/kotlin/fr/teamflash/fencerjudgeback/services/RefereeService.kt index c3491ed..218a1cb 100644 --- a/FencerJudgeBack/src/main/kotlin/fr/teamflash/fencerjudgeback/services/RefereeService.kt +++ b/FencerJudgeBack/src/main/kotlin/fr/teamflash/fencerjudgeback/services/RefereeService.kt @@ -1,8 +1,6 @@ package fr.teamflash.fencerjudgeback.services -import fr.teamflash.fencerjudgeback.entities.MatchState import fr.teamflash.fencerjudgeback.entities.RefereeBean -import fr.teamflash.fencerjudgeback.entities.RefereeLevel import fr.teamflash.fencerjudgeback.repositories.RefereeRepository import fr.teamflash.fencerjudgeback.websocket.controllers.RefereeWebSocketController import fr.teamflash.fencerjudgeback.websocket.models.RefereeUpdateMessage @@ -44,10 +42,10 @@ class RefereeService( return refereeRepository.findAll().filter{ it.firstName == firstName } } - // Obtenir un ou plusieurs arbitre(s) par niveau - fun getByLevel(level: RefereeLevel): List? { - println("RefereeService.getByLevel : $level") - return refereeRepository.findAll().filter{ it.level == level } + // Obtenir un ou plusieurs arbitre(s) par qualification + fun getByQualification(qualification:String): List? { + println("RefereeService.getRefereeByQualification : $qualification") + return refereeRepository.findAll().filter{ it.qualification == qualification } } // Ajouter un arbitre (admin) diff --git a/FencerJudgeBack/src/main/kotlin/fr/teamflash/fencerjudgeback/websocket/controllers/RefereeWebSocketController.kt b/FencerJudgeBack/src/main/kotlin/fr/teamflash/fencerjudgeback/websocket/controllers/RefereeWebSocketController.kt index 792fdc1..6064fda 100644 --- a/FencerJudgeBack/src/main/kotlin/fr/teamflash/fencerjudgeback/websocket/controllers/RefereeWebSocketController.kt +++ b/FencerJudgeBack/src/main/kotlin/fr/teamflash/fencerjudgeback/websocket/controllers/RefereeWebSocketController.kt @@ -30,7 +30,7 @@ class RefereeWebSocketController( id = refereeUpdateMessage.refereeId, name = refereeUpdateMessage.name, firstName = refereeUpdateMessage.firstName, - level = refereeUpdateMessage.level + qualification = refereeUpdateMessage.qualification ) // Update the referee in the database diff --git a/FencerJudgeBack/src/main/kotlin/fr/teamflash/fencerjudgeback/websocket/models/MatchUpdateMessage.kt b/FencerJudgeBack/src/main/kotlin/fr/teamflash/fencerjudgeback/websocket/models/MatchUpdateMessage.kt index f30aef3..028845f 100644 --- a/FencerJudgeBack/src/main/kotlin/fr/teamflash/fencerjudgeback/websocket/models/MatchUpdateMessage.kt +++ b/FencerJudgeBack/src/main/kotlin/fr/teamflash/fencerjudgeback/websocket/models/MatchUpdateMessage.kt @@ -1,7 +1,6 @@ package fr.teamflash.fencerjudgeback.websocket.models import fr.teamflash.fencerjudgeback.entities.MatchBean -import java.util.* /** * Message model for match updates sent through WebSocket @@ -13,7 +12,7 @@ data class MatchUpdateMessage( val refereeId: Long?, val score1: Int, val score2: Int, - val date: Date?, + val date: String?, val type: UpdateType = UpdateType.SCORE_UPDATE ) { enum class UpdateType { diff --git a/FencerJudgeBack/src/main/kotlin/fr/teamflash/fencerjudgeback/websocket/models/RefereeUpdateMessage.kt b/FencerJudgeBack/src/main/kotlin/fr/teamflash/fencerjudgeback/websocket/models/RefereeUpdateMessage.kt index 12f0fdd..cb9c1be 100644 --- a/FencerJudgeBack/src/main/kotlin/fr/teamflash/fencerjudgeback/websocket/models/RefereeUpdateMessage.kt +++ b/FencerJudgeBack/src/main/kotlin/fr/teamflash/fencerjudgeback/websocket/models/RefereeUpdateMessage.kt @@ -1,7 +1,6 @@ package fr.teamflash.fencerjudgeback.websocket.models import fr.teamflash.fencerjudgeback.entities.RefereeBean -import fr.teamflash.fencerjudgeback.entities.RefereeLevel /** * Message model for referee updates sent through WebSocket @@ -10,7 +9,7 @@ data class RefereeUpdateMessage( val refereeId: Long, val name: String?, val firstName: String?, - val level: RefereeLevel?, + val qualification: String?, val type: UpdateType = UpdateType.REFEREE_UPDATE ) { enum class UpdateType { @@ -28,7 +27,7 @@ data class RefereeUpdateMessage( refereeId = refereeBean.id ?: 0, name = refereeBean.name, firstName = refereeBean.firstName, - level = refereeBean.level, + qualification = refereeBean.qualification, type = type ) } diff --git a/FencerJudgeBack/src/main/resources/static/testMatchWebSocketHTML.html b/FencerJudgeBack/src/main/resources/static/testMatchWebSocketHTML.html index 950f7b6..05c5007 100644 --- a/FencerJudgeBack/src/main/resources/static/testMatchWebSocketHTML.html +++ b/FencerJudgeBack/src/main/resources/static/testMatchWebSocketHTML.html @@ -71,7 +71,7 @@ date: document.getElementById("matchDate").value }; - stompClient.send("/ws/add", {}, JSON.stringify(match)); + stompClient.send("/ws/matches/add", {}, JSON.stringify(match)); displayMessage(match) } diff --git a/FencerJudgeBack/src/main/resources/static/testPlusOrMinusWebSocketHTML.html b/FencerJudgeBack/src/main/resources/static/testPlusOrMinusWebSocketHTML.html index 8fd04a8..05219fd 100644 --- a/FencerJudgeBack/src/main/resources/static/testPlusOrMinusWebSocketHTML.html +++ b/FencerJudgeBack/src/main/resources/static/testPlusOrMinusWebSocketHTML.html @@ -63,15 +63,15 @@ function sendMatch() { const match = { id: 1, - player1ID: parseInt(document.getElementById("player1Id").value), - player2ID: parseInt(document.getElementById("player2Id").value), - refereeID: parseInt(document.getElementById("refereeId").value), + player1Id: parseInt(document.getElementById("player1Id").value), + player2Id: parseInt(document.getElementById("player2Id").value), + refereeId: parseInt(document.getElementById("refereeId").value), score1: parseInt(document.getElementById("score1").value), score2: parseInt(document.getElementById("score2").value), date: document.getElementById("matchDate").value }; - stompClient.send("/ws/plusPoint", {}, JSON.stringify({ + stompClient.send("/ws/matches/addPoint", {}, JSON.stringify({ match: match, playerId: match.player1Id })); diff --git a/FencerJudgeFront/src/app/app.module.ts b/FencerJudgeFront/src/app/app.module.ts index de9e710..4490d31 100644 --- a/FencerJudgeFront/src/app/app.module.ts +++ b/FencerJudgeFront/src/app/app.module.ts @@ -1,7 +1,6 @@ import { NgModule } from '@angular/core'; import { BrowserModule } from '@angular/platform-browser'; import { FormsModule } from '@angular/forms'; -import { HttpClientModule } from '@angular/common/http'; import { AppRoutingModule } from './app-routing.module'; import { AppComponent } from './app.component'; @@ -30,7 +29,7 @@ import { MatchesDelComponent } from './components/match/matches-del/matches-del. SponsortComponent, MatchesDelComponent, ], - imports: [BrowserModule, AppRoutingModule, FormsModule, HttpClientModule], + imports: [BrowserModule, AppRoutingModule, FormsModule], providers: [], bootstrap: [AppComponent], }) diff --git a/FencerJudgeFront/src/app/components/essentials/footer/footer.component.css b/FencerJudgeFront/src/app/components/essentials/footer/footer.component.css index 93884ad..a76370e 100644 --- a/FencerJudgeFront/src/app/components/essentials/footer/footer.component.css +++ b/FencerJudgeFront/src/app/components/essentials/footer/footer.component.css @@ -1,52 +1,21 @@ -footer { - color: white; - background-color: var(--h-f-bg); - padding: 2rem; -} -.socialmedias { - display: flex; - justify-content: end; - align-items: center; -} - -.socialmedias a { - background-color: white; - text-decoration: none; - margin-left: 1rem; - height: 40px; - width: 40px; - border-radius: 50%; - display: flex; - align-items: center; - justify-content: center; - padding: .6rem; - transition: background-color .4s ease-in-out; -} - -.socialmedias a:hover { - background-color: var(--primary-color); +.footer-gris { + background-color: #2c2c2c; /* Gris foncé personnalisé */ } .flag-bar { - height: 6px; - /* épaisseur du trait */ - width: 100%; - /* toute la largeur */ - background: linear-gradient(to right, - #0055a4 0%, - /* bleu */ - #0055a4 33.33%, - /* 1/3 */ - #fff 33.33%, - /* blanc */ - #fff 66.66%, - /* 2/3 */ - #ef4135 66.66%, - /* rouge */ - #ef4135 100%); + height: 6px; /* épaisseur du trait */ + width: 100%; /* toute la largeur */ + background: linear-gradient( + to right, + #0055a4 0%, /* bleu */ + #0055a4 33.33%, /* 1/3 */ + #fff 33.33%, /* blanc */ + #fff 66.66%, /* 2/3 */ + #ef4135 66.66%, /* rouge */ + #ef4135 100% + ); margin-bottom: 8px; - border-radius: 3px; - /* optionnel, pour arrondir les bords */ - box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1); + border-radius: 3px; /* optionnel, pour arrondir les bords */ + box-shadow: 0 1px 3px rgba(0,0,0,0.1); } \ No newline at end of file diff --git a/FencerJudgeFront/src/app/components/essentials/footer/footer.component.html b/FencerJudgeFront/src/app/components/essentials/footer/footer.component.html index 68e8789..9ec5e22 100644 --- a/FencerJudgeFront/src/app/components/essentials/footer/footer.component.html +++ b/FencerJudgeFront/src/app/components/essentials/footer/footer.component.html @@ -1,16 +1,43 @@ -
+
- FencerJudge + FencerJudge FencerJudge
-
+
Suivez-nous - - - - + + + +
@@ -18,4 +45,4 @@
-
\ No newline at end of file +
diff --git a/FencerJudgeFront/src/app/components/essentials/header/header.component.css b/FencerJudgeFront/src/app/components/essentials/header/header.component.css index d7282b5..9df8f3d 100644 --- a/FencerJudgeFront/src/app/components/essentials/header/header.component.css +++ b/FencerJudgeFront/src/app/components/essentials/header/header.component.css @@ -1,7 +1,3 @@ -nav { - background-color: var(--h-f-bg); -} - .navbar { box-shadow: 0 2px 6px rgba(0, 0, 0, 0.1); } @@ -11,7 +7,6 @@ nav { font-size: 1.4rem; display: flex; align-items: center; - color: white; } .navbar-brand img { @@ -20,13 +15,11 @@ nav { } .nav-link { - text-transform: uppercase; - font-weight: 600; - color: white; transition: color 0.3s ease; } .nav-link:hover, .active-link { color: #ffcc00 !important; + font-weight: 600; } diff --git a/FencerJudgeFront/src/app/components/essentials/header/header.component.html b/FencerJudgeFront/src/app/components/essentials/header/header.component.html index d427b35..c8ae8e8 100644 --- a/FencerJudgeFront/src/app/components/essentials/header/header.component.html +++ b/FencerJudgeFront/src/app/components/essentials/header/header.component.html @@ -1,28 +1,52 @@ - diff --git a/FencerJudgeFront/src/app/components/home/home.component.css b/FencerJudgeFront/src/app/components/home/home.component.css index a09e6de..6fc2a77 100644 --- a/FencerJudgeFront/src/app/components/home/home.component.css +++ b/FencerJudgeFront/src/app/components/home/home.component.css @@ -1,740 +1,627 @@ .match-card { - background: linear-gradient(135deg, #1a1a2e 0%, #16213e 100%); - border: 2px solid var(--primary-color); - padding: 24px; - box-shadow: 0 8px 32px rgba(0, 0, 0, 0.4), - inset 0 1px 0 rgba(255, 255, 255, 0.1); - position: relative; - overflow: hidden; - transition: all 0.3s ease; - height: 90vh; - width: 100%; - display: flex; - flex-direction: column; - justify-content: space-between; + background: linear-gradient(135deg, #1a1a2e 0%, #16213e 100%); + border: 2px solid #daa520; + padding: 24px; + box-shadow: 0 8px 32px rgba(0, 0, 0, 0.4), + inset 0 1px 0 rgba(255, 255, 255, 0.1); + position: relative; + overflow: hidden; + transition: all 0.3s ease; + height: 80vh; + width: 100%; } .match-card::before { - content: ""; - position: absolute; - top: 0; - left: 0; - right: 0; - height: 2px; - background: linear-gradient(90deg, #daa520, var(--primary-color), #daa520); - background-size: 200% 100%; - animation: gradientShift 15s ease infinite; + content: ""; + position: absolute; + top: 0; + left: 0; + right: 0; + height: 2px; + background: linear-gradient(90deg, #daa520, #ffd700, #daa520); + background-size: 200% 100%; + animation: gradientShift 15s ease infinite; } @keyframes gradientShift { - 0% { - background-position: 0% 50%; - } + 0% { + background-position: 0% 50%; + } - 50% { - background-position: 100% 50%; - } + 50% { + background-position: 100% 50%; + } - 100% { - background-position: 0% 50%; - } + 100% { + background-position: 0% 50%; + } } .match-card { - transform: translateY(-4px); - box-shadow: 0 12px 48px rgba(218, 165, 32, 0.2), 0 8px 32px rgba(0, 0, 0, 0.4); + transform: translateY(-4px); + box-shadow: 0 12px 48px rgba(218, 165, 32, 0.2), 0 8px 32px rgba(0, 0, 0, 0.4); } .match-background { - position: absolute; - top: 0; - left: 0; - width: 100%; - height: 100%; - z-index: -1; + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + z-index: -1; } .background-image { - width: 100%; - height: 100%; - object-fit: cover; - filter: grayscale(30%) brightness(0.4) contrast(1.2); - transition: all 0.5s ease; + width: 100%; + height: 100%; + object-fit: cover; + filter: grayscale(30%) brightness(0.4) contrast(1.2); + transition: all 0.5s ease; } .match-card:hover .background-image { - filter: grayscale(10%) brightness(0.3) contrast(1.4); - transform: scale(1.05); + filter: grayscale(10%) brightness(0.3) contrast(1.4); + transform: scale(1.05); } .image-overlay { - position: absolute; - top: 0; - left: 0; - width: 100%; - height: 100%; - background: linear-gradient(135deg, - rgba(26, 26, 46, 0.85) 0%, - rgba(0, 0, 0, 0.7) 50%, - rgba(22, 33, 62, 0.85) 100%); + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + background: linear-gradient( + 135deg, + rgba(26, 26, 46, 0.85) 0%, + rgba(0, 0, 0, 0.7) 50%, + rgba(22, 33, 62, 0.85) 100% + ); } /* Header */ .match-header { - display: flex; - justify-content: space-between; - align-items: center; - margin-bottom: 20px; + display: flex; + justify-content: space-between; + align-items: center; + margin-bottom: 20px; } .match-weapon { - display: flex; - align-items: center; - gap: 8px; - color: #daa520; - font-weight: 600; + display: flex; + align-items: center; + gap: 8px; + color: #daa520; + font-weight: 600; } .weapon-type { - font-size: 14px; - text-transform: uppercase; - letter-spacing: 1px; + font-size: 14px; + text-transform: uppercase; + letter-spacing: 1px; } /* Status */ .match-status { - display: flex; - align-items: center; - gap: 8px; - padding: 6px 12px; - border-radius: 20px; - font-size: 12px; - font-weight: 600; - text-transform: uppercase; - letter-spacing: 0.5px; + display: flex; + align-items: center; + gap: 8px; + padding: 6px 12px; + border-radius: 20px; + font-size: 12px; + font-weight: 600; + text-transform: uppercase; + letter-spacing: 0.5px; } .status-warning { - background: rgba(34, 197, 94, 0.2); - color: #22c55e; - border: 1px solid #22c55e; + background: rgba(34, 197, 94, 0.2); + color: #22c55e; + border: 1px solid #22c55e; } .status-success { - background: rgba(239, 68, 68, 0.2); - color: #ef4444; - border: 1px solid #ef4444; + background: rgba(239, 68, 68, 0.2); + color: #ef4444; + border: 1px solid #ef4444; } .status-secondary { - background: rgba(59, 130, 246, 0.2); - color: #3b82f6; - border: 1px solid #3b82f6; + background: rgba(59, 130, 246, 0.2); + color: #3b82f6; + border: 1px solid #3b82f6; } .status-dot { - width: 8px; - height: 8px; - border-radius: 50%; - background: currentColor; - animation: pulse 2s infinite; + width: 8px; + height: 8px; + border-radius: 50%; + background: currentColor; + animation: pulse 2s infinite; } @keyframes pulse { - - 0%, - 100% { - opacity: 1; - } - - 50% { - opacity: 0.5; - } + 0%, + 100% { + opacity: 1; + } + 50% { + opacity: 0.5; + } } /* Versus Section */ .match-versus { - display: flex; - align-items: center; - justify-content: space-between; - margin: 24px 0; - position: relative; + display: flex; + align-items: center; + justify-content: space-between; + margin: 24px 0; + position: relative; } .fencer { - flex: 1; - text-align: center; - color: white; + flex: 1; + text-align: center; + color: white; } .fencer-name { - font-size: 18px; - font-weight: 700; - margin-bottom: 4px; - color: #daa520; + font-size: 18px; + font-weight: 700; + margin-bottom: 4px; + color: #daa520; } .fencer-club { - font-size: 12px; - color: #9ca3af; - margin-bottom: 8px; + font-size: 12px; + color: #9ca3af; + margin-bottom: 8px; } .score { - font-size: 32px; - font-weight: 900; - color: white; - text-shadow: 0 2px 4px rgba(0, 0, 0, 0.5); + font-size: 32px; + font-weight: 900; + color: white; + text-shadow: 0 2px 4px rgba(0, 0, 0, 0.5); } .vs-divider { - display: flex; - flex-direction: column; - align-items: center; - gap: 4px; - margin: 0 20px; + display: flex; + flex-direction: column; + align-items: center; + gap: 4px; + margin: 0 20px; } .vs-text { - font-size: 14px; - font-weight: 700; - color: #6b7280; - letter-spacing: 2px; + font-size: 14px; + font-weight: 700; + color: #6b7280; + letter-spacing: 2px; } .crossed-swords { - font-size: 20px; - opacity: 0.7; + font-size: 20px; + opacity: 0.7; } /* Details */ .match-details { - display: flex; - flex-direction: column; - gap: 12px; - margin-top: 20px; - padding-top: 20px; - border-top: 1px solid rgba(255, 255, 255, 0.1); + display: flex; + flex-direction: column; + gap: 12px; + margin-top: 20px; + padding-top: 20px; + border-top: 1px solid rgba(255, 255, 255, 0.1); } .detail-item { - display: flex; - align-items: center; - gap: 12px; - font-size: 14px; + display: flex; + align-items: center; + gap: 12px; + font-size: 14px; } .detail-item .icon { - font-size: 16px; - width: 20px; - text-align: center; + font-size: 16px; + width: 20px; + text-align: center; } .detail-item .label { - color: #9ca3af; - font-weight: 500; - min-width: 60px; + color: #9ca3af; + font-weight: 500; + min-width: 60px; } .detail-item .value { - color: white; - font-weight: 600; + color: white; + font-weight: 600; } /* Responsive */ @media (max-width: 768px) { - .match-card { - padding: 16px; - } + .match-card { + padding: 16px; + } - .match-versus { - flex-direction: column; - gap: 16px; - } + .match-versus { + flex-direction: column; + gap: 16px; + } - .vs-divider { - transform: rotate(90deg); - margin: 0; - } + .vs-divider { + transform: rotate(90deg); + margin: 0; + } - .fencer { - width: 100%; - } + .fencer { + width: 100%; + } } .combat-arena { - margin-top: 24px; - background: linear-gradient(135deg, - rgba(220, 38, 38, 0.1) 0%, - rgba(0, 0, 0, 0.8) 50%, - rgba(255, 215, 0, 0.1) 100%); - border: 2px solid; - border-image: linear-gradient(45deg, #dc2626, var(--primary-color), #dc2626) 1; - border-radius: var(--border-radius); - padding: 20px; - position: relative; - overflow: hidden; + margin-top: 24px; + background: linear-gradient( + 135deg, + rgba(220, 38, 38, 0.1) 0%, + rgba(0, 0, 0, 0.8) 50%, + rgba(255, 215, 0, 0.1) 100% + ); + border: 2px solid; + border-image: linear-gradient(45deg, #dc2626, #ffd700, #dc2626) 1; + border-radius: 12px; + padding: 20px; + position: relative; + overflow: hidden; } .combat-arena::before { - content: ""; - position: absolute; - top: -50%; - left: -50%; - width: 200%; - height: 200%; - background: repeating-conic-gradient(from 0deg at 50% 50%, - transparent 0deg 2deg, - rgba(220, 38, 38, 0.05) 2deg 4deg); - animation: rotate 20s linear infinite; - pointer-events: none; + content: ""; + position: absolute; + top: -50%; + left: -50%; + width: 200%; + height: 200%; + background: repeating-conic-gradient( + from 0deg at 50% 50%, + transparent 0deg 2deg, + rgba(220, 38, 38, 0.05) 2deg 4deg + ); + animation: rotate 20s linear infinite; + pointer-events: none; } @keyframes rotate { - 0% { - transform: rotate(0deg); - } - - 100% { - transform: rotate(360deg); - } + 0% { + transform: rotate(0deg); + } + 100% { + transform: rotate(360deg); + } } /* Header Arena */ .arena-header { - display: flex; - align-items: center; - justify-content: center; - gap: 12px; - margin-bottom: 20px; - position: relative; + display: flex; + align-items: center; + justify-content: center; + gap: 12px; + margin-bottom: 20px; + position: relative; } .arena-title { - font-family: "Orbitron", monospace; - font-size: 16px; - font-weight: 900; - color: var(--primary-color); - letter-spacing: 3px; - text-shadow: 0 0 10px var(--primary-color), 0 0 20px var(--primary-color), 0 0 30px var(--primary-color); - animation: titleGlow 2s ease-in-out infinite alternate; + font-family: "Orbitron", monospace; + font-size: 16px; + font-weight: 900; + color: #ffd700; + letter-spacing: 3px; + text-shadow: 0 0 10px #ffd700, 0 0 20px #ffd700, 0 0 30px #ffd700; + animation: titleGlow 2s ease-in-out infinite alternate; } @keyframes titleGlow { - from { - text-shadow: 0 0 10px var(--primary-color), 0 0 20px var(--primary-color), 0 0 30px var(--primary-color); - } - - to { - text-shadow: 0 0 20px var(--primary-color), 0 0 30px var(--primary-color), 0 0 40px var(--primary-color); - } + from { + text-shadow: 0 0 10px #ffd700, 0 0 20px #ffd700, 0 0 30px #ffd700; + } + to { + text-shadow: 0 0 20px #ffd700, 0 0 30px #ffd700, 0 0 40px #ffd700; + } } .arena-pulse { - width: 10px; - height: 10px; - background: #dc2626; - border-radius: 50%; - position: relative; - animation: pulse-danger 1s infinite; + width: 10px; + height: 10px; + background: #dc2626; + border-radius: 50%; + position: relative; + animation: pulse-danger 1s infinite; } .arena-pulse::before { - content: ""; - position: absolute; - top: -5px; - left: -5px; - right: -5px; - bottom: -5px; - background: #dc2626; - border-radius: 50%; - opacity: 0.3; - animation: pulse-ring 1s infinite; + content: ""; + position: absolute; + top: -5px; + left: -5px; + right: -5px; + bottom: -5px; + background: #dc2626; + border-radius: 50%; + opacity: 0.3; + animation: pulse-ring 1s infinite; } @keyframes pulse-danger { - - 0%, - 100% { - transform: scale(1); - } - - 50% { - transform: scale(1.2); - } + 0%, + 100% { + transform: scale(1); + } + 50% { + transform: scale(1.2); + } } @keyframes pulse-ring { - 0% { - transform: scale(0.8); - opacity: 0.8; - } - - 100% { - transform: scale(2); - opacity: 0; - } + 0% { + transform: scale(0.8); + opacity: 0.8; + } + 100% { + transform: scale(2); + opacity: 0; + } } /* Combat Grid */ .combat-grid { - display: grid; - grid-template-columns: 1fr; - gap: 16px; + display: grid; + grid-template-columns: 1fr; + gap: 16px; } .combat-stat { - display: flex; - align-items: center; - gap: 16px; - padding: 16px; - background: linear-gradient(90deg, - rgba(0, 0, 0, 0.8) 0%, - rgba(26, 26, 46, 0.9) 50%, - rgba(0, 0, 0, 0.8) 100%); - border: 1px solid var(--primary-color); - border-radius: var(--border-radius); - position: relative; - transition: all 0.3s ease; - cursor: pointer; + display: flex; + align-items: center; + gap: 16px; + padding: 16px; + background: linear-gradient( + 90deg, + rgba(0, 0, 0, 0.8) 0%, + rgba(26, 26, 46, 0.9) 50%, + rgba(0, 0, 0, 0.8) 100% + ); + border: 1px solid rgba(255, 215, 0, 0.3); + border-radius: 8px; + position: relative; + transition: all 0.3s ease; + cursor: pointer; } .combat-stat:hover { - transform: translateX(8px); - border-color: var(--primary-color); - box-shadow: 0 4px 20px var(--primary-color), - inset 0 1px 0 rgba(255, 215, 0, 0.1); + transform: translateX(8px); + border-color: #ffd700; + box-shadow: 0 4px 20px rgba(255, 215, 0, 0.3), + inset 0 1px 0 rgba(255, 215, 0, 0.1); } /* Icons animés */ .stat-icon { - position: relative; - display: flex; - align-items: center; - justify-content: center; - width: 48px; - height: 48px; - font-size: 24px; + position: relative; + display: flex; + align-items: center; + justify-content: center; + width: 48px; + height: 48px; + font-size: 24px; } .location-radar { - position: absolute; - width: 40px; - height: 40px; - border: 2px solid #10b981; - border-radius: 50%; - border-top-color: transparent; - animation: radar-spin 2s linear infinite; + position: absolute; + width: 40px; + height: 40px; + border: 2px solid #10b981; + border-radius: 50%; + border-top-color: transparent; + animation: radar-spin 2s linear infinite; } .referee-badge { - position: absolute; - width: 35px; - height: 35px; - background: linear-gradient(45deg, var(--primary-color), #ffed4a); - clip-path: polygon(50% 0%, - 61% 35%, - 98% 35%, - 68% 57%, - 79% 91%, - 50% 70%, - 21% 91%, - 32% 57%, - 2% 35%, - 39% 35%); - animation: badge-pulse 3s ease-in-out infinite; + position: absolute; + width: 35px; + height: 35px; + background: linear-gradient(45deg, #ffd700, #ffed4a); + clip-path: polygon( + 50% 0%, + 61% 35%, + 98% 35%, + 68% 57%, + 79% 91%, + 50% 70%, + 21% 91%, + 32% 57%, + 2% 35%, + 39% 35% + ); + animation: badge-pulse 3s ease-in-out infinite; } .time-ring { - position: absolute; - width: 36px; - height: 36px; - border: 3px solid #dc2626; - border-radius: 50%; - border-left-color: transparent; - animation: time-tick 1s linear infinite; + position: absolute; + width: 36px; + height: 36px; + border: 3px solid #dc2626; + border-radius: 50%; + border-left-color: transparent; + animation: time-tick 1s linear infinite; } @keyframes radar-spin { - 0% { - transform: rotate(0deg); - } - - 100% { - transform: rotate(360deg); - } + 0% { + transform: rotate(0deg); + } + 100% { + transform: rotate(360deg); + } } @keyframes badge-pulse { - - 0%, - 100% { - transform: scale(1) rotate(0deg); - } - - 50% { - transform: scale(1.1) rotate(5deg); - } + 0%, + 100% { + transform: scale(1) rotate(0deg); + } + 50% { + transform: scale(1.1) rotate(5deg); + } } @keyframes time-tick { - 0% { - transform: rotate(0deg); - } - - 100% { - transform: rotate(360deg); - } + 0% { + transform: rotate(0deg); + } + 100% { + transform: rotate(360deg); + } } /* Content */ .stat-content { - flex: 1; - display: flex; - flex-direction: column; - gap: 2px; + flex: 1; + display: flex; + flex-direction: column; + gap: 2px; } .stat-label { - font-family: "Orbitron", monospace; - font-size: 10px; - font-weight: 700; - color: #6b7280; - letter-spacing: 1px; - text-transform: uppercase; + font-family: "Orbitron", monospace; + font-size: 10px; + font-weight: 700; + color: #6b7280; + letter-spacing: 1px; + text-transform: uppercase; } .stat-value { - font-size: 16px; - font-weight: 700; - color: white; - text-shadow: 0 1px 2px rgba(0, 0, 0, 0.5); + font-size: 16px; + font-weight: 700; + color: #ffffff; + text-shadow: 0 1px 2px rgba(0, 0, 0, 0.5); } .stat-sub { - font-size: 11px; - color: #9ca3af; - font-weight: 500; + font-size: 11px; + color: #9ca3af; + font-weight: 500; } /* Glows spécifiques */ .venue .stat-value { - color: #10b981; + color: #10b981; } - .referee .stat-value { - color: var(--primary-color); + color: #ffd700; } - .timing .stat-value { - color: #dc2626; + color: #dc2626; } .stat-glow { - position: absolute; - top: 0; - left: 0; - right: 0; - bottom: 0; - border-radius: 8px; - opacity: 0; - transition: opacity 0.3s ease; - pointer-events: none; + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; + border-radius: 8px; + opacity: 0; + transition: opacity 0.3s ease; + pointer-events: none; } .combat-stat:hover .stat-glow { - opacity: 1; + opacity: 1; } .venue-glow { - box-shadow: inset 0 0 20px rgba(16, 185, 129, 0.2); + box-shadow: inset 0 0 20px rgba(16, 185, 129, 0.2); } - .referee-glow { - box-shadow: inset 0 0 20px rgba(255, 215, 0, 0.2); + box-shadow: inset 0 0 20px rgba(255, 215, 0, 0.2); } - .timing-glow { - box-shadow: inset 0 0 20px rgba(220, 38, 38, 0.2); + box-shadow: inset 0 0 20px rgba(220, 38, 38, 0.2); } /* Responsive */ @media (min-width: 768px) { - .combat-grid { - grid-template-columns: repeat(3, 1fr); - } + .combat-grid { + grid-template-columns: repeat(3, 1fr); + } - .combat-stat { - flex-direction: column; - text-align: center; - gap: 12px; - } - - .combat-stat:hover { - transform: translateY(-4px); - } -} - -/* Section Weapons */ -.section-header { - text-align: center; - margin-bottom: 3rem; - position: relative; -} - -.section-title { - font-size: 2.5rem; - font-weight: 300; - letter-spacing: 2px; - color: #333; - margin: 0; - position: relative; - display: inline-block; -} - -.section-title::after { - content: ''; - position: absolute; - bottom: -10px; - left: 50%; - transform: translateX(-50%); - width: 60px; - height: 2px; - background: var(--gradient-color); -} - -.weapons-container, -.diplomes-container { - display: flex; - flex-wrap: wrap; - gap: 20px; - justify-content: center; - padding: 20px; -} - -/* Card Weapon */ -.weapon-card, -.diplomes-card { - position: relative; - background-size: cover; - background-position: center; - border-radius: var(--border-radius); - box-shadow: 0 4px 12px rgba(0, 0, 0, 0.2); - width: 400px; - height: 500px; - color: white; - text-align: center; - overflow-y: auto; - overflow-x: hidden; - display: flex; + .combat-stat { flex-direction: column; - padding: 20px; - aspect-ratio: 16/9; - transition: box-shadow 0.3s ease; - /* Transition douce pour l'effet de lift */ + text-align: center; + gap: 12px; + } + + .combat-stat:hover { + transform: translateY(-4px); + } } -.weapon-card:hover, -.diplomes-card:hover { - background-image: none !important; - box-shadow: - 0 8px 25px rgba(0, 0, 0, 0.3), - 0 0 20px rgba(212, 175, 55, 0.3), - inset 0 1px 0 rgba(255, 255, 255, 0.1); - transform: translateY(-2px); - /* Léger lift au hover */ - border: 2px solid var(--primary-color); - background: var(--card-gradient) !important; +.weapons-container { + display: flex; + flex-wrap: wrap; + gap: 20px; + justify-content: center; + padding: 20px; } -.weapon-card:before, -.diplomes-card:before { - content: ''; - position: absolute; - inset: 0; - background-image: inherit; - background-size: cover; - background-position: center; - filter: var(--blur-effect); - opacity: .6; - z-index: 1; - transition: var(--transition-smooth); - /* Courbe plus fluide */ +.weapon-card { + position: relative; + background-size: cover; + background-position: center; + border-radius: 12px; + box-shadow: 0 4px 12px rgba(0,0,0,0.2); + max-width: 300px; + height: 400px; + color: white; + text-align: center; + overflow: hidden; + display: flex; + flex-direction: column; + justify-content: flex-end; + padding: 20px; + background-color: #000; +} +.weapon-card::before { + content: ''; + position: absolute; + inset: 0; + background-image: inherit; + background-size: cover; + background-position: center; + filter: blur(10px) brightness(1.1); + opacity: 0.7; + z-index: 1; +} +.weapon-card * { + position: relative; + z-index: 2; + text-shadow: 0 2px 4px rgba(0, 0, 0, 0.8); } -.weapon-card:hover:before, -.diplomes-card:hover:before { - transform: scale(1.2); - /* Zoom uniquement sur l'image */ - filter: var(--blur-hover); - /* Moins de blur + plus lumineux au hover */ - opacity: .8; - /* Plus visible au hover */ - background-image: none; +.weapon-card img { + width: 100%; + height: auto; + border-radius: 10px; + margin-bottom: 15px; } -.weapon-card:hover:before, -.diplomes-card:hover:before { - animation: metalShine 2s ease-in-out infinite alternate; -} - -@keyframes metalShine { - 0% { - filter: brightness(1.1) contrast(1.2); - } - - 100% { - filter: brightness(1.3) contrast(1.4) saturate(1.1); - } -} - -.weapon-card *, -.diplomes-card * { - position: relative; - z-index: 2; - text-shadow: 0 2px 4px rgba(0, 0, 0, 0.8); +.weapon-card h2 { + margin-bottom: 10px; + font-size: 1.4em; } .weapon-card p { - color: white; - font-size: 0.95em; -} - -.diplomes-card h2, -.weapon-card h2 { - position: absolute; - opacity: 1; - transition: opacity 0.3s ease, transform 0.3s ease; - bottom: 50%; - left: 50%; - transform: translate(-50%, 50%); - /* Centrage parfait */ - margin: auto 0; - text-transform: uppercase; - font-size: 1.4em; -} - -.diplomes-card:hover h2, -.weapon-card:hover h2 { - opacity: 0; - transform: translate(-50%, 30%); - /* Glisse vers le haut en disparaissant */ -} - -.diplomes-card p, -.weapon-card p, -.weapon-card ul li, -.diplomes-card ul li { - text-align: start; - opacity: 0; - transform: translateY(-100%); - transition: opacity transform .6s ease-in-out; -} - -.diplomes-card:hover p, -.weapon-card:hover p, -.weapon-card:hover ul li, -.diplomes-card:hover ul li { - opacity: 1; - transform: translateY(0); + color: #ffffff; + font-size: 0.95em; } \ No newline at end of file diff --git a/FencerJudgeFront/src/app/components/home/home.component.html b/FencerJudgeFront/src/app/components/home/home.component.html index aaf0494..7242cb1 100644 --- a/FencerJudgeFront/src/app/components/home/home.component.html +++ b/FencerJudgeFront/src/app/components/home/home.component.html @@ -1,277 +1,137 @@
-
- Escrime -
+
+ Escrime +
+
+ +
+
+ ⚔️ + {{ latestMatch.weapon }} +
+
+ + {{ getMatchStateLabel(latestMatch.state) }} +
+
+ +
+
+
+ {{ player1?.name }} {{ player1?.firstName }} +
+
{{ player1?.club }}
+
{{ latestMatch.score1 }}
-
-
- ⚔️ - {{ latestMatch.weapon }} -
-
- - {{ getMatchStateLabel(latestMatch.state) }} -
+
+ VS +
⚔️
-
-
-
- {{ player1?.name }} {{ player1?.firstName }} -
-
{{ player1?.club }}
-
{{ latestMatch.score1 }}
-
+
+
+ {{ player2?.name }} {{ player2?.firstName }} +
+
{{ player2?.club }}
+
{{ latestMatch.score2 }}
+
+
-
- VS -
⚔️
-
- -
-
- {{ player2?.name }} {{ player2?.firstName }} -
-
{{ player2?.club }}
-
{{ latestMatch.score2 }}
-
+
+
+ ARENA COMBAT +
-
-
- ARENA COMBAT -
+
+
+
+
+ 🏛️
- -
-
-
-
- 🏛️ -
-
- BATTLEFIELD - {{ latestMatch.city }} - {{ latestMatch.country }} -
-
-
- -
-
-
- ⚖️ -
-
- COMBAT JUDGE - {{ referee?.name }} {{ referee?.firstName }} - OFFICIAL REFEREE -
-
-
- -
-
-
- -
-
- COMBAT START - {{ getTimeUntilMatch() }} - LIVE BATTLE -
-
-
-
-
- 🎯 -
-
- FUN FACT - - Saviez-vous que l'escrime est l'un des sports les plus anciens aux - Jeux Olympiques ? - - Inspiration et tradition au rendez-vous -
-
+
+ BATTLEFIELD + {{ latestMatch.city }} + {{ latestMatch.country }}
+
+
+ +
+
+
+ ⚖️ +
+
+ COMBAT JUDGE + {{ referee?.name }} {{ referee?.firstName }} + OFFICIAL REFEREE +
+
+
+ +
+
+
+ +
+
+ COMBAT START + {{ getTimeUntilMatch() }} + LIVE BATTLE +
+
+
+
+
+ 🎯 +
+
+ FUN FACT + + Saviez-vous que l'escrime est l'un des sports les plus anciens aux + Jeux Olympiques ? + + Inspiration et tradition au rendez-vous +
+
+
+
+
+
+

Épée

+

Tout le corps est cible valable. Pas de priorité.

+
+ +
+

Fleuret

+

Cible : torse. La priorité s'applique.

+
+ +
+

Sabre

+

Cible : haut du corps. Priorité en cas de touche simultanée.

+
+ +
+

Sabre Laser

+

Arme moderne d’escrime sportive, inspirée de la science-fiction. Lame lumineuse, règles proches du sabre classique. Discipline visuelle et dynamique.

-
-
-

Les Armes

-
+
-
-
-

Épée

-
    -
  • - Le but de l’épée est de toucher le premier son adversaire avec la pointe de la lame. - La priorité ne s’applique pas comme au fleuret, - c’est-à-dire que les deux épéistes peuvent toucher simultanément : le point leur sera accordé. -
  • -
  • - Toutes les parties du corps comptent, des pieds jusqu’au masque. - C’est le premier qui touche l’autre qui marque le point. -
  • -
  • - Les touches ne sont accordées que si elles sont portées avec la pointe de la lame. - Les touches doivent être portées à l’adversaire avec une pression suffisante. -
  • -
-
-
-

Fleuret

-
    -
  • - Les touches sont comptabilisées par un système électrique qui détecte les touches sur la veste des escrimeurs. -
  • -
  • - Pour marquer un point, la touche doit être portée sur la partie valable du corps de l’adversaire, qui est délimitée par les règles de l’escrime. - La zone valable est le tronc, ce qui exclut les membres et la tête. -
  • -
  • - Les touches simultanées ne sont pas prises en compte, c’est-à-dire que si les deux escrimeurs touchent leur adversaire en même temps, - l’arbitre dira lequel des deux avait la « priorité » pour pouvoir attribuer le point. -
  • -
-
- -
-

Sabre

-
    -
  • - Le sabre est une arme qui permet des touches rapides et dynamiques. - Les touches sont marquées avec le tranchant et le bout de la lame. -
  • -
  • - Les touches sont valides sur tout le haut du corps, au-dessus de la ceinture jusqu’à la tête. - Les touches sont déterminées par des capteurs électriques sur la cuirasse et le masque de l’escrimeur. -
  • -
  • - Si les deux tireurs touchent en même temps, c’est l’attaquant qui a la priorité du point, sauf si l’adversaire parade et riposte. - Cette règle est quasiment identique à celle du fleuret. -
  • -
-
- -
-

Sabre Laser

-

Les combats au sabre laser suivent généralement des règles similaires à celles de l’escrime artistique. - La pratique du sabre laser se décline en trois disciplines complémentaires : -

-
    -
  • - Combat sportif : Les escrimeurs s’affrontent en duel réglementé dans une arène. - Ils doivent toucher l’adversaire avec leur sabre laser pour accumuler des points en un temps donné. - Le combat sportif exige de la stratégie, de la rapidité et une maîtrise technique. -
  • -
  • - Combat chorégraphié : Cette discipline se pratique à deux ou en groupe. - Les participants exécutent ensemble un combat sous forme de mise en scène préalablement répétée, souvent accompagnée d’une musique appropriée. - Le sens du spectacle prime, et les mouvements doivent être précis et spectaculaires. -
  • -
  • - Kata : Inspiré des arts martiaux, le kata consiste à reproduire un enchaînement de mouvements codifiés seul ou face à un adversaire imaginaire. - Il vise à progresser techniquement et exige rigueur, précision et patience. -
  • -
-
- -
- - -
-
-

Les diplômes d'arbitrage

-
- -
-
-

départemental

-

Ce diplôme est décemé par la CAI ou la CRA dont - dépend l'arbitre :

-
    -
  • - Âge minimum : 14 ans. -
  • -
  • - Ouvre droit à arbitrer toutes les compétitions - organisées dans le cadre du comité interdépartemental - et/ou du comité régional dont dépend l'arbitre (sous - réserve de l'avis de la CRA dont dépend l'arbitre). -
  • -
  • - Titulaire d'un carton BLANC qui permet d'arrêter un - match à n'importe quel moment pour demander une - assistance du DT et/ou de l'organisateur de la - compétition. Le rôle pédagogique du DT et/ou de - l'organisateur est primordial dans l'accompagnement - des jeunes arbitres. -
  • -
-
- -
-

régional

-

Ce diplôme est décerné par la CRA dont dépend - l'arbitre :

-
    -
  • - Âge minimum : 16 ans -
  • -
  • - Il ouvre droit à arbitrer toutes les compétitions - organisées dans le cadre du Comité régional, -
  • -
  • - Les circuits nationaux, -
  • -
  • - La Fête des Jeunes, -
  • -
  • - Des dérogations ponctuelles peuvent faire l'objet d'une - circulaire. -
  • -
-
- -
-

national

-

Ce diplôme est décerné par la CNA (Commission - Nationale Arbitrage) :

-
    -
  • • Âge minimum : 18 ans
  • -
  • Il ouvre droit à arbitrer toutes les compétitions - organisées dans le cadre du Comité régional,
  • -
  • Les circuits nationaux,
  • -
  • La Fête des Jeunes, les championnats de France M17, - M20, Séniors et Vétérans sur convocation de la CNN
  • -
  • Les circuits européens M17 et U23 organisés sur le - territoire français et à l'étranger.
  • -
-
- -
-

international

-

Ce diplôme est décerné par la Fédération - Internationale d'Escrime (FIE).

-
    -
  • Âge minimum : 20 ans
  • -
  • Il ouvre droit à arbitrer toutes les compétitions. Les - arbitres qui figurent sur la liste restreinte de la FIE - doivent arbitrer des compétitions nationales séniors et - être la référence de notre corps arbitral.
  • -
-
- -
-
- - \ No newline at end of file + diff --git a/FencerJudgeFront/src/app/components/match/matches-id/matches-id.component.html b/FencerJudgeFront/src/app/components/match/matches-id/matches-id.component.html index 6ce2a75..2f926a0 100644 --- a/FencerJudgeFront/src/app/components/match/matches-id/matches-id.component.html +++ b/FencerJudgeFront/src/app/components/match/matches-id/matches-id.component.html @@ -29,7 +29,7 @@
diff --git a/FencerJudgeFront/src/app/interfaces/matches.ts b/FencerJudgeFront/src/app/interfaces/matches.ts index 1437a58..26c6767 100644 --- a/FencerJudgeFront/src/app/interfaces/matches.ts +++ b/FencerJudgeFront/src/app/interfaces/matches.ts @@ -1,7 +1,7 @@ export enum MatchState { - ONGOING = 0, - OVER = 1, - NOT_STARTED = 2, + ONGOING = 1, + OVER = 2, + NOT_STARTED = 3, } export interface Matches { diff --git a/FencerJudgeFront/src/app/services/matches/matches.service.ts b/FencerJudgeFront/src/app/services/matches/matches.service.ts index bbffd36..5a80f75 100644 --- a/FencerJudgeFront/src/app/services/matches/matches.service.ts +++ b/FencerJudgeFront/src/app/services/matches/matches.service.ts @@ -1,5 +1,5 @@ import { Injectable } from '@angular/core'; -import { Observable, of } from 'rxjs'; +import { Observable, Subject, BehaviorSubject, of } from 'rxjs'; import { Matches, MatchState } from '@interfaces/matches'; @Injectable({ providedIn: 'root' }) @@ -45,41 +45,85 @@ export class MatchesService { state: MatchState.NOT_STARTED, }, ]; + private socket?: WebSocket; + private matchUpdates$ = new Subject(); + private allMatches: Matches[] = []; private nextMatchId = Math.max(...this.matches.map((m) => m.id)) + 1; constructor() { - console.log('[MatchesService] Initial matches loaded:', this.matches); + this.connectToMatchUpdatesWebSocket(); + } + + private connectToMatchUpdatesWebSocket(): void { + const wsUrl = 'http://localhost:8080/ws/matches-app'; + this.socket = new WebSocket(wsUrl); + + this.socket.onopen = () => { + console.log('[WebSocket] ✅ Connecté à', wsUrl); + }; + + this.socket.onmessage = (event) => { + try { + const data = JSON.parse(event.data) as Matches[]; + console.log('[WebSocket] 📥 Données reçues :', data); + this.matchUpdates$.next(data); + } catch (e) { + console.error('[WebSocket] ❌ Erreur de parsing JSON', e); + } + }; + + this.socket.onerror = (err) => { + console.error('[WebSocket] ❌ Erreur :', err); + }; + + this.socket.onclose = () => { + console.warn('[WebSocket] 🔌 Fermeture de la connexion'); + }; + } + + private sendMatchesToWebSocket(): void { + if (this.socket && this.socket.readyState === WebSocket.OPEN) { + const dataToSend = JSON.stringify(this.matches); + this.socket.send(dataToSend); + console.log('[WebSocket] 📤 Données envoyées :', dataToSend); + } else { + console.warn("[WebSocket] ⚠️ Le WebSocket n'est pas encore ouvert."); + } + } + + public sendCurrentMatches(): void { + this.sendMatchesToWebSocket(); } getMatches(): Observable { - console.log('[MatchesService] Fetching all matches'); - return of(this.matches); + return this.matchUpdates$.asObservable(); } getMatchById(id: number): Observable { - const match = this.matches.find((m) => m.id === id); - console.log(`[MatchesService] Fetching match ID: ${id}`, match); - return of(match); - } - - // Préparation future pour WebSocket - connectToMatchUpdatesWebSocket(): void { - console.log( - '[MatchesService] WebSocket connection placeholder initialized' - ); - // ici tu pourrais plus tard faire : this.socket = new WebSocket('ws://...') etc. + const match = this.allMatches.find((m) => m.id === id); + console.log(`[MatchesService] Match ID ${id} récupéré :`, match); + return new BehaviorSubject(match).asObservable(); } updateMatch(id: number, updatedData: Partial): void { - const match = this.matches.find((m) => m.id === id); - if (match) { - Object.assign(match, updatedData); - console.log(`[MatchesService] Match ${id} mis à jour :`, match); + const matchIndex = this.allMatches.findIndex((m) => m.id === id); + if (matchIndex !== -1) { + const updatedMatch = { ...this.allMatches[matchIndex], ...updatedData }; + this.allMatches[matchIndex] = updatedMatch; + this.matchUpdates$.next([...this.allMatches]); // émettre un nouveau tableau + console.log( + `[MatchesService] Match ${id} mis à jour localement :`, + updatedMatch + ); } else { - console.warn(`[MatchesService] Match ${id} introuvable`); + console.warn(`[MatchesService] Match ${id} non trouvé pour mise à jour`); } } + ngOnDestroy(): void { + this.socket?.close(); + } + create(match: Omit): Observable { const newMatch: Matches = { ...match, diff --git a/FencerJudgeFront/src/app/templates/sponsort/sponsort.component.html b/FencerJudgeFront/src/app/templates/sponsort/sponsort.component.html index dd13b28..89ce529 100644 --- a/FencerJudgeFront/src/app/templates/sponsort/sponsort.component.html +++ b/FencerJudgeFront/src/app/templates/sponsort/sponsort.component.html @@ -20,25 +20,4 @@ src="https://www.prieur-sports.us/assets/images/prieur-sport-fencing-equipment.png" />
-
- - - - - - - -
diff --git a/FencerJudgeFront/src/assets/departements.jpg b/FencerJudgeFront/src/assets/departements.jpg deleted file mode 100644 index 787fc6b..0000000 Binary files a/FencerJudgeFront/src/assets/departements.jpg and /dev/null differ diff --git a/FencerJudgeFront/src/assets/international.jpg b/FencerJudgeFront/src/assets/international.jpg deleted file mode 100644 index 3447190..0000000 Binary files a/FencerJudgeFront/src/assets/international.jpg and /dev/null differ diff --git a/FencerJudgeFront/src/assets/nationnal.jpg b/FencerJudgeFront/src/assets/nationnal.jpg deleted file mode 100644 index a9ed1a7..0000000 Binary files a/FencerJudgeFront/src/assets/nationnal.jpg and /dev/null differ diff --git a/FencerJudgeFront/src/assets/region.png b/FencerJudgeFront/src/assets/region.png deleted file mode 100644 index 3c6daa9..0000000 Binary files a/FencerJudgeFront/src/assets/region.png and /dev/null differ diff --git a/FencerJudgeFront/src/styles.css b/FencerJudgeFront/src/styles.css index 5374057..c44aac6 100644 --- a/FencerJudgeFront/src/styles.css +++ b/FencerJudgeFront/src/styles.css @@ -2,32 +2,3 @@ .bg-primary-custom { background-color: #414141; } - -/* Colors */ -:root { - --primary-color: rgba(212, 175, 55, 0.6); - --gradient-color: linear-gradient(90deg, #d4af37, var(--primary-color)); - --card-gradient: linear-gradient(45deg, transparent 30%, rgba(255, 255, 255, 0.1) 50%, transparent 70%), - linear-gradient(135deg, - rgba(64, 64, 64, 0.95) 0%, - rgba(32, 32, 32, 0.98) 50%, - rgba(16, 16, 16, 0.95) 100%); - --h-f-bg: #2c2c2c; -} - -/* Filters */ -:root { - --blur-effect: blur(10px) brightness(1.1) contrast(1.1); - --blur-hover: blur(8px) brightness(1.3); -} - -/* Transitions */ -:root { - --transition-smooth: all 0.6s cubic-bezier(0.4, 0, 0.2, 1); - --transition-quick: all 0.3s ease; -} - -/* Borders */ -:root { - --border-radius: 12px; -} \ No newline at end of file diff --git a/db.lock.db b/db.lock.db new file mode 100644 index 0000000..072e750 --- /dev/null +++ b/db.lock.db @@ -0,0 +1,6 @@ +#FileLock +#Mon Jun 02 17:40:34 CEST 2025 +hostName=ExostFlash +id=197313393c88a931fa21bf5ce1281b7253870b00683 +method=file +server=192.167.2.100\:54366 diff --git a/db.mv.db b/db.mv.db index 13d536b..f4f797b 100644 Binary files a/db.mv.db and b/db.mv.db differ diff --git a/db.trace.db b/db.trace.db deleted file mode 100644 index 016cc9c..0000000 --- a/db.trace.db +++ /dev/null @@ -1,48 +0,0 @@ -2025-06-03 09:54:12.514185+02:00 database: close -org.h2.message.DbException: IO Exception: "Closing" -IO Exception: "Closing" [90028-232] - at org.h2.message.DbException.get(DbException.java:212) - at org.h2.mvstore.db.Store.close(Store.java:374) - at org.h2.engine.Database.closeOpenFilesAndUnlock(Database.java:1292) - at org.h2.engine.Database.closeImpl(Database.java:1254) - at org.h2.engine.Database.close(Database.java:1173) - at org.h2.engine.Database.onShutdown(Database.java:1158) - at org.h2.engine.OnExitDatabaseCloser.onShutdown(OnExitDatabaseCloser.java:85) - at org.h2.engine.OnExitDatabaseCloser.run(OnExitDatabaseCloser.java:114) -Caused by: org.h2.jdbc.JdbcSQLNonTransientException: IO Exception: "Closing" -IO Exception: "Closing" [90028-232] - at org.h2.message.DbException.getJdbcSQLException(DbException.java:566) - at org.h2.message.DbException.getJdbcSQLException(DbException.java:489) - ... 8 more -Caused by: org.h2.mvstore.MVStoreException: Reading from file sun.nio.ch.FileChannelImpl@1baeb921 failed at 15775 (length -1), read 0, remaining 24 [2.3.232/1] - at org.h2.mvstore.DataUtils.newMVStoreException(DataUtils.java:996) - at org.h2.mvstore.DataUtils.readFully(DataUtils.java:455) - at org.h2.mvstore.FileStore.readFully(FileStore.java:721) - at org.h2.mvstore.SingleFileStore.readFully(SingleFileStore.java:60) - at org.h2.mvstore.SingleFileStore.readFully(SingleFileStore.java:28) - at org.h2.mvstore.SFChunk.readFully(SFChunk.java:35) - at org.h2.mvstore.Chunk.readToC(Chunk.java:496) - at org.h2.mvstore.FileStore.getToC(FileStore.java:2070) - at org.h2.mvstore.FileStore.rewriteChunks(FileStore.java:1913) - at org.h2.mvstore.FileStore.compactRewrite(FileStore.java:1901) - at org.h2.mvstore.FileStore.rewriteChunks(FileStore.java:1862) - at org.h2.mvstore.FileStore.lambda$compact$0(FileStore.java:879) - at org.h2.mvstore.MVStore.tryExecuteUnderStoreLock(MVStore.java:937) - at org.h2.mvstore.FileStore.compact(FileStore.java:879) - at org.h2.mvstore.RandomAccessStore.compactStore(RandomAccessStore.java:441) - at org.h2.mvstore.FileStore.compactStore(FileStore.java:890) - at org.h2.mvstore.FileStore.stop(FileStore.java:275) - at org.h2.mvstore.MVStore.closeStore(MVStore.java:693) - at org.h2.mvstore.MVStore.close(MVStore.java:643) - at org.h2.mvstore.db.Store.close(Store.java:364) - ... 6 more -Caused by: java.io.IOException: Le périphérique n’est pas prêt - at java.base/sun.nio.ch.FileDispatcherImpl.pread0(Native Method) - at java.base/sun.nio.ch.FileDispatcherImpl.pread(FileDispatcherImpl.java:67) - at java.base/sun.nio.ch.IOUtil.readIntoNativeBuffer(IOUtil.java:338) - at java.base/sun.nio.ch.IOUtil.read(IOUtil.java:306) - at java.base/sun.nio.ch.IOUtil.read(IOUtil.java:283) - at java.base/sun.nio.ch.FileChannelImpl.readInternal(FileChannelImpl.java:984) - at java.base/sun.nio.ch.FileChannelImpl.read(FileChannelImpl.java:964) - at org.h2.mvstore.DataUtils.readFully(DataUtils.java:441) - ... 24 more