diff --git a/src/components/editor/BasketCourt.tsx b/src/components/editor/BasketCourt.tsx
index 4cab8cf..25b53b5 100644
--- a/src/components/editor/BasketCourt.tsx
+++ b/src/components/editor/BasketCourt.tsx
@@ -1,8 +1,14 @@
-import {ReactElement, ReactNode, RefObject, useLayoutEffect, useState} from "react"
-import {Action} from "../../model/tactic/Action"
+import {
+ ReactElement,
+ ReactNode,
+ RefObject,
+ useLayoutEffect,
+ useState,
+} from "react"
+import { Action } from "../../model/tactic/Action"
-import {CourtAction} from "./CourtAction.tsx"
-import {ComponentId, TacticComponent} from "../../model/tactic/Tactic"
+import { CourtAction } from "./CourtAction.tsx"
+import { ComponentId, TacticComponent } from "../../model/tactic/Tactic"
export interface BasketCourtProps {
components: TacticComponent[]
@@ -21,21 +27,20 @@ export interface ActionPreview extends Action {
}
export function BasketCourt({
- components,
- previewAction,
+ components,
+ previewAction,
- renderComponent,
- renderActions,
-
- courtImage,
- courtRef,
- }: BasketCourtProps) {
+ renderComponent,
+ renderActions,
+ courtImage,
+ courtRef,
+}: BasketCourtProps) {
const [forceEmptyComponents, setForceEmptyComponents] = useState(true)
useLayoutEffect(() => {
setForceEmptyComponents(false)
- }, [setForceEmptyComponents]);
+ }, [setForceEmptyComponents])
const usedComponents = forceEmptyComponents ? [] : components
@@ -43,7 +48,7 @@ export function BasketCourt({
+ style={{ position: "relative" }}>
{courtImage}
{usedComponents.map(renderComponent)}
@@ -56,10 +61,8 @@ export function BasketCourt({
origin={previewAction.origin}
isInvalid={previewAction.isInvalid}
//do nothing on interacted, not really possible as it's a preview arrow
- onActionDeleted={() => {
- }}
- onActionChanges={() => {
- }}
+ onActionDeleted={() => {}}
+ onActionChanges={() => {}}
/>
)}
diff --git a/src/components/editor/CourtBall.tsx b/src/components/editor/CourtBall.tsx
index e368598..c9c48dc 100644
--- a/src/components/editor/CourtBall.tsx
+++ b/src/components/editor/CourtBall.tsx
@@ -1,8 +1,8 @@
-import {useRef} from "react"
+import { useRef } from "react"
import Draggable from "react-draggable"
-import {BallPiece} from "./BallPiece"
-import {NULL_POS} from "../../geo/Pos"
-import {Ball} from "../../model/tactic/CourtObjects"
+import { BallPiece } from "./BallPiece"
+import { NULL_POS } from "../../geo/Pos"
+import { Ball } from "../../model/tactic/CourtObjects"
export interface CourtBallProps {
onPosValidated: (rect: DOMRect) => void
@@ -10,10 +10,10 @@ export interface CourtBallProps {
ball: Ball
}
-export function CourtBall({onPosValidated, ball, onRemove}: CourtBallProps) {
+export function CourtBall({ onPosValidated, ball, onRemove }: CourtBallProps) {
const pieceRef = useRef(null)
- const {x, y} = ball.pos
+ const { x, y } = ball.pos
return (
-
+
)
diff --git a/src/components/editor/CourtPlayer.tsx b/src/components/editor/CourtPlayer.tsx
index 2f8e5cb..6b8e8dd 100644
--- a/src/components/editor/CourtPlayer.tsx
+++ b/src/components/editor/CourtPlayer.tsx
@@ -1,9 +1,9 @@
-import React, {ReactNode, RefObject, useCallback, useRef} from "react"
+import React, { ReactNode, RefObject, useCallback, useRef } from "react"
import "../../style/player.css"
import Draggable from "react-draggable"
-import {PlayerPiece} from "./PlayerPiece"
-import {BallState, PlayerInfo} from "../../model/tactic/Player"
-import {NULL_POS, Pos, ratioWithinBase} from "../../geo/Pos"
+import { PlayerPiece } from "./PlayerPiece"
+import { BallState, PlayerInfo } from "../../model/tactic/Player"
+import { NULL_POS, Pos, ratioWithinBase } from "../../geo/Pos"
export interface CourtPlayerProps {
playerInfo: PlayerInfo
@@ -23,16 +23,16 @@ export const PLAYER_RADIUS_PIXELS = 20
* A player that is placed on the court, which can be selected, and moved in the associated bounds
* */
export default function CourtPlayer({
- playerInfo,
- className,
+ playerInfo,
+ className,
- onPositionValidated,
- onRemove,
- courtRef,
- availableActions,
- }: CourtPlayerProps) {
+ onPositionValidated,
+ onRemove,
+ courtRef,
+ availableActions,
+}: CourtPlayerProps) {
const usesBall = playerInfo.ballState != BallState.NONE
- const {x, y} = playerInfo.pos
+ const { x, y } = playerInfo.pos
const pieceRef = useRef(null)
return (
@@ -47,8 +47,11 @@ export default function CourtPlayer({
const pos = ratioWithinBase(pieceBounds, parentBounds)
-
- if (Math.abs(pos.x - x) >= MOVE_AREA_SENSIBILITY || Math.abs(pos.y - y) >= MOVE_AREA_SENSIBILITY) onPositionValidated(pos)
+ if (
+ Math.abs(pos.x - x) >= MOVE_AREA_SENSIBILITY ||
+ Math.abs(pos.y - y) >= MOVE_AREA_SENSIBILITY
+ )
+ onPositionValidated(pos)
}, [courtRef, onPositionValidated, x, y])}>
c.id == pathItem.originPlayerId)! as Player
}
-export function getPlayerNextTo(player: PlayerLike, n: number, components: TacticComponent[]): PlayerLike | undefined {
- const playerOrigin = player.type === "player" ? player : getOrigin(player, components)
+export function getPlayerNextTo(
+ player: PlayerLike,
+ n: number,
+ components: TacticComponent[],
+): PlayerLike | undefined {
+ const playerOrigin =
+ player.type === "player" ? player : getOrigin(player, components)
const pathItems = playerOrigin.path?.items!
// add one as there is a shifting because a Player is never at the head of its own path
@@ -24,20 +49,24 @@ export function getPlayerNextTo(player: PlayerLike, n: number, components: Tacti
const targetIdx = idx + n
// remove the screen phantom
- const result = targetIdx == 0 ? playerOrigin : getComponent
(pathItems[targetIdx - 1], components)
+ const result =
+ targetIdx == 0
+ ? playerOrigin
+ : getComponent(pathItems[targetIdx - 1], components)
return result
}
//FIXME this function can be a bottleneck if the phantom's position is
// following another phantom and / or the origin of the phantom is another
-export function computePhantomPositioning(phantom: PlayerPhantom,
- content: TacticContent,
- area: DOMRect): Pos {
+export function computePhantomPositioning(
+ phantom: PlayerPhantom,
+ content: TacticContent,
+ area: DOMRect,
+): Pos {
const positioning = phantom.pos
// If the position is already known and fixed, return the pos
- if (positioning.type === "fixed")
- return positioning
+ if (positioning.type === "fixed") return positioning
// If the position is to determine (positioning.type = "follows"), determine the phantom's pos
// by calculating it from the referent position, and the action that targets the referent.
@@ -46,44 +75,56 @@ export function computePhantomPositioning(phantom: PlayerPhantom,
// Get the referent from the components
const referent: PlayerLike = getComponent(positioning.attach, components)
- const referentPos = referent.type === "player"
- ? referent.pos
- : computePhantomPositioning(referent, content, area)
+ const referentPos =
+ referent.type === "player"
+ ? referent.pos
+ : computePhantomPositioning(referent, content, area)
// Get the origin
const origin = getOrigin(phantom, components)
const originPathItems = origin.path!.items
const phantomIdx = originPathItems.indexOf(phantom.id)
- const playerBeforePhantom: PlayerLike = phantomIdx == 0 ? origin : getComponent(originPathItems[phantomIdx - 1], components)
- const action = playerBeforePhantom.actions.find(a => a.target === positioning.attach)!
+ const playerBeforePhantom: PlayerLike =
+ phantomIdx == 0
+ ? origin
+ : getComponent(originPathItems[phantomIdx - 1], components)
+ const action = playerBeforePhantom.actions.find(
+ (a) => a.target === positioning.attach,
+ )!
const segments = action.segments
const lastSegment = segments[segments.length - 1]
const lastSegmentStart = segments[segments.length - 2]?.next
- const pivotPoint = lastSegment.controlPoint ?? (lastSegmentStart
- ? typeof lastSegmentStart === "string"
- ? document.getElementById(lastSegmentStart)!.getBoundingClientRect()
- : lastSegmentStart
- : playerBeforePhantom.type === "phantom"
- ? computePhantomPositioning(playerBeforePhantom, content, area)
- : playerBeforePhantom.pos)
-
+ const pivotPoint =
+ lastSegment.controlPoint ??
+ (lastSegmentStart
+ ? typeof lastSegmentStart === "string"
+ ? document
+ .getElementById(lastSegmentStart)!
+ .getBoundingClientRect()
+ : lastSegmentStart
+ : playerBeforePhantom.type === "phantom"
+ ? computePhantomPositioning(playerBeforePhantom, content, area)
+ : playerBeforePhantom.pos)
const segment = posWithinBase(relativeTo(referentPos, pivotPoint), area)
const segmentLength = norm(segment)
const phantomDistanceFromReferent = PLAYER_RADIUS_PIXELS //TODO Place this in constants
const segmentProjection = minus(area, {
x: (segment.x / segmentLength) * phantomDistanceFromReferent,
- y: (segment.y / segmentLength) * phantomDistanceFromReferent
+ y: (segment.y / segmentLength) * phantomDistanceFromReferent,
})
const segmentProjectionRatio: Pos = ratioWithinBase(segmentProjection, area)
return add(referentPos, segmentProjectionRatio)
}
-export function getComponent(id: string, components: TacticComponent[]): T {
- return components.find(c => c.id === id)! as T
+export function getComponent(
+ id: string,
+ components: TacticComponent[],
+): T {
+ return components.find((c) => c.id === id)! as T
}
export function areInSamePath(a: PlayerLike, b: PlayerLike) {
@@ -141,13 +182,18 @@ export function clearPlayerPath(
)
}
-function removeAllPhantomsAttached(to: ComponentId, content: TacticContent): TacticContent {
+function removeAllPhantomsAttached(
+ to: ComponentId,
+ content: TacticContent,
+): TacticContent {
let i = 0
while (i < content.components.length) {
const component = content.components[i]
if (component.type === "phantom") {
-
- if (component.pos.type === "follows" && component.pos.attach === to) {
+ if (
+ component.pos.type === "follows" &&
+ component.pos.attach === to
+ ) {
content = removePlayer(component, content)
continue
}
@@ -165,16 +211,24 @@ export function removePlayer(
content = removeAllPhantomsAttached(player.id, content)
if (player.type === "phantom") {
-
const pos = player.pos
// if the phantom was attached to another player, remove the action that symbolizes the attachment
if (pos.type === "follows") {
- const playerBefore = getPlayerNextTo(player, -1, content.components)!
- const actionIdx = playerBefore.actions.findIndex(a => a.target === pos.attach)
- content = updateComponent({
- ...playerBefore,
- actions: playerBefore.actions.toSpliced(actionIdx, 1)
- }, content)
+ const playerBefore = getPlayerNextTo(
+ player,
+ -1,
+ content.components,
+ )!
+ const actionIdx = playerBefore.actions.findIndex(
+ (a) => a.target === pos.attach,
+ )
+ content = updateComponent(
+ {
+ ...playerBefore,
+ actions: playerBefore.actions.toSpliced(actionIdx, 1),
+ },
+ content,
+ )
}
const origin = getOrigin(player, content.components)
@@ -229,9 +283,9 @@ export function truncatePlayerPath(
truncateStartIdx == 0
? null
: {
- ...path,
- items: path.items.toSpliced(truncateStartIdx),
- },
+ ...path,
+ items: path.items.toSpliced(truncateStartIdx),
+ },
},
content,
)
diff --git a/src/editor/TacticContentDomains.ts b/src/editor/TacticContentDomains.ts
index a8d02d3..1f3a9cc 100644
--- a/src/editor/TacticContentDomains.ts
+++ b/src/editor/TacticContentDomains.ts
@@ -1,11 +1,26 @@
-import {Pos, ratioWithinBase} from "../geo/Pos"
-import {BallState, Player, PlayerInfo, PlayerLike, PlayerTeam,} from "../model/tactic/Player"
-import {Ball, BALL_ID, BALL_TYPE, CourtObject,} from "../model/tactic/CourtObjects"
-import {ComponentId, TacticComponent, TacticContent,} from "../model/tactic/Tactic"
-import {overlaps} from "../geo/Box"
-import {RackedCourtObject, RackedPlayer} from "./RackedItems"
-import {changePlayerBallState, getComponent, getOrigin} from "./PlayerDomains"
-import {ActionKind} from "../model/tactic/Action.ts";
+import { Pos, ratioWithinBase } from "../geo/Pos"
+import {
+ BallState,
+ Player,
+ PlayerInfo,
+ PlayerLike,
+ PlayerTeam,
+} from "../model/tactic/Player"
+import {
+ Ball,
+ BALL_ID,
+ BALL_TYPE,
+ CourtObject,
+} from "../model/tactic/CourtObjects"
+import {
+ ComponentId,
+ TacticComponent,
+ TacticContent,
+} from "../model/tactic/Tactic"
+import { overlaps } from "../geo/Box"
+import { RackedCourtObject, RackedPlayer } from "./RackedItems"
+import { changePlayerBallState, getComponent, getOrigin } from "./PlayerDomains"
+import { ActionKind } from "../model/tactic/Action.ts"
export function placePlayerAt(
refBounds: DOMRect,
@@ -167,20 +182,37 @@ export function moveComponent(
const originPathItems = origin.path!.items
const phantomIdx = originPathItems.indexOf(component.id)
- const playerBeforePhantom: PlayerLike = phantomIdx == 0 ? origin : getComponent(originPathItems[phantomIdx - 1], content.components)
+ const playerBeforePhantom: PlayerLike =
+ phantomIdx == 0
+ ? origin
+ : getComponent(
+ originPathItems[phantomIdx - 1],
+ content.components,
+ )
// detach the action from the screen target and transform it to a regular move action to the phantom.
- content = updateComponent({
- ...playerBeforePhantom,
- actions: playerBeforePhantom.actions.map(a => a.target === referent ? {
- ...a,
- segments: a.segments.toSpliced(a.segments.length - 2, 1, {
- ...a.segments[a.segments.length - 1],
- next: component.id,
- }),
- target: component.id,
- type: ActionKind.MOVE
- } : a),
- }, content)
+ content = updateComponent(
+ {
+ ...playerBeforePhantom,
+ actions: playerBeforePhantom.actions.map((a) =>
+ a.target === referent
+ ? {
+ ...a,
+ segments: a.segments.toSpliced(
+ a.segments.length - 2,
+ 1,
+ {
+ ...a.segments[a.segments.length - 1],
+ next: component.id,
+ },
+ ),
+ target: component.id,
+ type: ActionKind.MOVE,
+ }
+ : a,
+ ),
+ },
+ content,
+ )
}
content = updateComponent(
@@ -188,10 +220,10 @@ export function moveComponent(
...component,
pos: isPhantom
? {
- type: "fixed",
- ...newPos
- }
- : newPos
+ type: "fixed",
+ ...newPos,
+ }
+ : newPos,
},
content,
)
@@ -253,5 +285,5 @@ export function getRackPlayers(
c.type == "player" && c.team == team && c.role == role,
) == -1,
)
- .map((key) => ({team, key}))
+ .map((key) => ({ team, key }))
}
diff --git a/src/model/tactic/Player.ts b/src/model/tactic/Player.ts
index ab4d116..a22eaee 100644
--- a/src/model/tactic/Player.ts
+++ b/src/model/tactic/Player.ts
@@ -34,7 +34,7 @@ export interface PlayerInfo {
*/
readonly ballState: BallState
- readonly pos: Pos,
+ readonly pos: Pos
}
export enum BallState {
@@ -61,24 +61,26 @@ export interface MovementPath {
/**
* The position of the phantom is known and fixed
*/
-export type FixedPhantomPositioning = ({ type: "fixed" } & Pos)
+export type FixedPhantomPositioning = { type: "fixed" } & Pos
/**
* The position of the phantom is constrained to a given component.
* The actual position of the phantom is to determine given its environment.
*/
-export type FollowsPhantomPositioning = { type: "follows", attach: ComponentId }
+export type FollowsPhantomPositioning = { type: "follows"; attach: ComponentId }
/**
* Defines the different kind of positioning a phantom can have
*/
-export type PhantomPositioning = FixedPhantomPositioning | FollowsPhantomPositioning
-
+export type PhantomPositioning =
+ | FixedPhantomPositioning
+ | FollowsPhantomPositioning
/**
* A player phantom is a kind of component that represents the future state of a player
* according to the court's step information
*/
-export interface PlayerPhantom extends Component<"phantom", PhantomPositioning> {
+export interface PlayerPhantom
+ extends Component<"phantom", PhantomPositioning> {
readonly originPlayerId: ComponentId
readonly ballState: BallState
diff --git a/src/model/tactic/Tactic.ts b/src/model/tactic/Tactic.ts
index b22473f..0ad312c 100644
--- a/src/model/tactic/Tactic.ts
+++ b/src/model/tactic/Tactic.ts
@@ -28,7 +28,7 @@ export interface Component {
*/
readonly id: ComponentId
- readonly pos: Positioning,
+ readonly pos: Positioning
readonly actions: Action[]
}
diff --git a/src/pages/Editor.tsx b/src/pages/Editor.tsx
index cc51abb..83c4dac 100644
--- a/src/pages/Editor.tsx
+++ b/src/pages/Editor.tsx
@@ -403,7 +403,11 @@ function EditorView({
id: component.id,
team: origin.team,
role: origin.role,
- pos: computePhantomPositioning(component, content, courtBounds()),
+ pos: computePhantomPositioning(
+ component,
+ content,
+ courtBounds(),
+ ),
ballState: component.ballState,
}
} else {
diff --git a/src/pages/HomePage.tsx b/src/pages/HomePage.tsx
index 2a6bb64..faba0d7 100644
--- a/src/pages/HomePage.tsx
+++ b/src/pages/HomePage.tsx
@@ -57,10 +57,10 @@ export default function HomePage() {
}
function Home({
- lastTactics,
- allTactics,
- teams,
- }: {
+ lastTactics,
+ allTactics,
+ teams,
+}: {
lastTactics: Tactic[]
allTactics: Tactic[]
teams: Team[]
@@ -77,10 +77,10 @@ function Home({
}
function Body({
- lastTactics,
- allTactics,
- teams,
- }: {
+ lastTactics,
+ allTactics,
+ teams,
+}: {
lastTactics: Tactic[]
allTactics: Tactic[]
teams: Team[]
@@ -100,10 +100,10 @@ function Body({
}
function SideMenu({
- width,
- lastTactics,
- teams,
- }: {
+ width,
+ lastTactics,
+ teams,
+}: {
width: number
lastTactics: Tactic[]
teams: Team[]
@@ -123,9 +123,9 @@ function SideMenu({
}
function PersonalSpace({
- width,
- allTactics,
- }: {
+ width,
+ allTactics,
+}: {
width: number
allTactics: Tactic[]
}) {
@@ -198,17 +198,15 @@ function TableData({ allTactics }: { allTactics: Tactic[] }) {
function BodyPersonalSpace({ allTactics }: { allTactics: Tactic[] }) {
return (
- {
- allTactics.length == 0
- ?
Aucune tactique créée !
- :
-
-
+ {allTactics.length == 0 ? (
+ Aucune tactique créée !
+ ) : (
+
- }
-
+
+
+ )}
)
}