From 0cd937cd3b51eb1ece47b4cf41ae40104fa205c2 Mon Sep 17 00:00:00 2001 From: "vivien.dufour" Date: Tue, 19 Dec 2023 09:44:03 +0100 Subject: [PATCH] can put the ball on the court if we want --- front/components/editor/CourtPlayer.tsx | 9 +- front/tactic/Player.ts | 12 +-- front/views/Editor.tsx | 137 +++++++++++++++++------- 3 files changed, 109 insertions(+), 49 deletions(-) diff --git a/front/components/editor/CourtPlayer.tsx b/front/components/editor/CourtPlayer.tsx index 8f4f659..045d5d0 100644 --- a/front/components/editor/CourtPlayer.tsx +++ b/front/components/editor/CourtPlayer.tsx @@ -1,6 +1,5 @@ import {RefObject, useRef} from "react" import "../../style/player.css" -import RemoveIcon from "../../assets/icon/remove.svg?react" import {BallPiece} from "./BallPiece" import Draggable from "react-draggable" import {PlayerPiece} from "./PlayerPiece" @@ -69,11 +68,9 @@ export default function CourtPlayer({ if (e.key == "Delete") onRemove() }}>
- - {hasBall && ( onBallDrop(ballPiece.current!.getBoundingClientRect())}> + {hasBall && ( onBallDrop(ballPiece.current!.getBoundingClientRect())} + position={{x:0, y: 0}}>
diff --git a/front/tactic/Player.ts b/front/tactic/Player.ts index 553b85e..a025daf 100644 --- a/front/tactic/Player.ts +++ b/front/tactic/Player.ts @@ -1,26 +1,26 @@ import { Team } from "./Team" export interface Player { - id: string + readonly id: string /** * the player's team * */ - team: Team + readonly team: Team /** * player's role * */ - role: string + readonly role: string /** * Percentage of the player's position to the bottom (0 means top, 1 means bottom, 0.5 means middle) */ - bottomRatio: number + readonly bottomRatio: number /** * Percentage of the player's position to the right (0 means left, 1 means right, 0.5 means middle) */ - rightRatio: number + readonly rightRatio: number - hasBall: boolean + readonly hasBall: boolean } diff --git a/front/views/Editor.tsx b/front/views/Editor.tsx index 9032595..100b2d7 100644 --- a/front/views/Editor.tsx +++ b/front/views/Editor.tsx @@ -23,6 +23,7 @@ import SavingState, { } from "../components/editor/SavingState" import {CourtObject} from "../tactic/CourtObjects"; +import {Simulate} from "react-dom/test-utils"; const ERROR_STYLE: CSSProperties = { @@ -126,11 +127,12 @@ function EditorView({ const [opponents, setOpponents] = useState( getRackPlayers(Team.Opponents, content.players), ) - const [objects, setObjects] = useState([{key: "ball"}]) + + const [objects, setObjects] = useState(isBallOnCourt(content) ? [] : [{key: "ball"}]) const courtDivContentRef = useRef(null) - + const canDetach = (bounds: DOMRect) => { const courtBounds = courtDivContentRef.current!.getBoundingClientRect() @@ -143,6 +145,8 @@ function EditorView({ ) } + + const onPieceDetach = (ref: HTMLDivElement, element: RackedPlayer) => { const refBounds = ref.getBoundingClientRect() const courtBounds = courtDivContentRef.current!.getBoundingClientRect() @@ -167,7 +171,6 @@ function EditorView({ }) } - const onObjectDetach = (ref: HTMLDivElement, rackedObject: RackedCourtObject) => { const refBounds = ref.getBoundingClientRect() const courtBounds = courtDivContentRef.current!.getBoundingClientRect() @@ -176,60 +179,110 @@ function EditorView({ let courtObject: CourtObject - switch (rackedObject.key) { case "ball": - courtObject = { - type: "ball", - rightRatio: x, - bottomRatio: y + const ballObj = content.objects.findIndex(o => o.type == "ball") + const playerCollidedIdx = getPlayerCollided(refBounds, content.players) + if(playerCollidedIdx != -1) { + onBallDropOnPlayer(playerCollidedIdx) + setContent((content) => { + return{ + ...content, + objects : content.objects.toSpliced(ballObj, 1) + } + }) + return + } + else { + courtObject = { + type: "ball", + rightRatio: x, + bottomRatio: y + } } break + default: throw new Error("unknown court object ", rackedObject.key) } - setContent((content) => - ({ + setContent((content) => { + return ({ ...content, objects: [ ...content.objects, courtObject, ] }) - ) + }) } - const onBallDrop = (ballBounds: DOMRect) => { - let ballAssigned = false + const getPlayerCollided = (bounds: DOMRect, players: Player[]): number | -1 => { + for (let i = 0; i < players.length; i++) { + const player = players[i] + const playerBounds = document.getElementById(player.id)!.getBoundingClientRect() + const doesOverlap = !( + bounds.top > playerBounds.bottom || + bounds.right < playerBounds.left || + bounds.bottom < playerBounds.top || + bounds.left > playerBounds.right + ) + if(doesOverlap) { + return i + } + } + return -1 + } - setContent(content => { - const players = content.players.map(player => { - if (ballAssigned) { - return {...player, hasBall: false} - } - const playerBounds = document - .getElementById(player.id)! - .getBoundingClientRect() - const doesOverlap = !( - ballBounds.top > playerBounds.bottom || - ballBounds.right < playerBounds.left || - ballBounds.bottom < playerBounds.top || - ballBounds.left > playerBounds.right - ) - if (doesOverlap) { - ballAssigned = true + + const onBallDropOnPlayer = (playerCollidedIdx : number) => { + setContent((content) => { + const ballObj = content.objects.findIndex(o => o.type == "ball") + let player = content.players.at(playerCollidedIdx) as Player + return { + ...content, + players: content.players.toSpliced(playerCollidedIdx, 1, {...player, hasBall: true}), + objects : content.objects.toSpliced(ballObj, 1) + } + }) + } + + const onBallDrop = (refBounds: DOMRect) => { + const playerCollidedIdx = getPlayerCollided(refBounds, content.players) + if(playerCollidedIdx != -1) { + setContent((content) => { + return { + ...content, + players: content.players.map((player) => ({...player, hasBall: false})), } - return { ...player, hasBall: doesOverlap } }) + onBallDropOnPlayer(playerCollidedIdx) + return + } - let objects = content.objects - if (ballAssigned) { - const ballPieceIdx = content.objects.findIndex(obj => obj.type === "ball") - objects = objects.toSpliced(ballPieceIdx, 1) - } + if(content.objects.findIndex(o => o.type == "ball") != -1) { + return + } + + const courtBounds = courtDivContentRef.current!.getBoundingClientRect() + const {x, y} = calculateRatio(refBounds, courtBounds) + let courtObject: CourtObject + + courtObject = { + type: "ball", + rightRatio: x, + bottomRatio: y + } - return {...content, objects, players} + setContent((content) => { + return { + ...content, + players: content.players.map((player) => ({...player, hasBall: false})), + objects: [ + ...content.objects, + courtObject, + ] + } }) } @@ -323,6 +376,9 @@ function EditorView({ player, false, ), + objects: [ + ...content.objects, + ] })) let setter switch (player.team) { @@ -333,7 +389,7 @@ function EditorView({ setter = setAllies } if (player.hasBall) { - /// add an instance of RackedBall back to the rack (objects) + setObjects([{key: "ball"}]) } setter((players) => [ ...players, @@ -352,6 +408,13 @@ function EditorView({ ) } +function isBallOnCourt(content : TacticContent) { + if(content.players.findIndex(p => p.hasBall) != -1) { + return true + } + return content.objects.findIndex(o => o.type == "ball") != -1 +} + function renderCourtObject(courtObject: RackedCourtObject) { if (courtObject.key == "ball") { return