<?php
namespace App\Entity;
use ApiPlatform\Core\Annotation\ApiFilter;
use ApiPlatform\Core\Annotation\ApiResource;
use ApiPlatform\Core\Bridge\Doctrine\Orm\Filter\OrderFilter;
use ApiPlatform\Core\Bridge\Doctrine\Orm\Filter\SearchFilter;
use ApiPlatform\Core\Serializer\Filter\PropertyFilter;
use App\Repository\TeamplayUserRecapRepository;
use Doctrine\ORM\Mapping as ORM;
use Gedmo\Mapping\Annotation as Gedmo;
use Symfony\Component\Serializer\Annotation\Groups;
use Symfony\Component\Validator\Constraints as Assert;
/**
* Snapshot des performances d'un utilisateur à la fin d'un Teamplay
*
* @ORM\Entity(repositoryClass=TeamplayUserRecapRepository::class)
* @ORM\Table(
* name="teamplay_user_recap",
* uniqueConstraints={
* @ORM\UniqueConstraint(name="unique_user_teamplay_recap", columns={"user_id", "teamplay_id"})
* },
* indexes={
* @ORM\Index(name="idx_user_recap", columns={"user_id"}),
* @ORM\Index(name="idx_teamplay_recap", columns={"teamplay_id"}),
* @ORM\Index(name="idx_team_recap", columns={"team_id"}),
* @ORM\Index(name="idx_recap_created", columns={"created_at"})
* }
* )
* @ApiResource(
* normalizationContext={"groups"={"teamplay_recap:read"}},
* denormalizationContext={"groups"={"teamplay_recap:write"}},
* itemOperations={
* "get"={"security"="is_granted('ROLE_USER')"},
* "delete"={"security"="is_granted('ROLE_ADMIN')"}
* },
* collectionOperations={
* "get"={"security"="is_granted('ROLE_USER')"},
* "post"={"security"="is_granted('ROLE_ADMIN')"},
* "get_user_history"={
* "method"="GET",
* "path"="/users/{id}/teamplay-history",
* "controller"="App\Controller\Api\TeamplayRecapController::getUserHistory",
* "security"="is_granted('ROLE_USER')",
* "read"=false,
* "pagination_enabled"=true,
* "defaults"={"_api_receive"=false}
* }
* }
* )
* @ApiFilter(SearchFilter::class, properties={
* "user": "exact",
* "teamplay": "exact",
* "team": "exact",
* "company": "exact"
* })
* @ApiFilter(OrderFilter::class, properties={"id", "createdAt", "teamplayStartDate", "teamplayEndDate", "totalPoints", "userRank"})
* @ApiFilter(PropertyFilter::class, arguments={"parameterName"="fields", "overrideDefaultProperties"=true})
*/
class TeamplayUserRecap
{
/**
* @ORM\Id
* @ORM\GeneratedValue
* @ORM\Column(type="integer")
* @Groups({"teamplay_recap:read"})
*/
private $id;
// ═══════════════════════════════════════════════════════════════
// RELATIONS
// ═══════════════════════════════════════════════════════════════
/**
* @ORM\ManyToOne(targetEntity=User::class)
* @ORM\JoinColumn(nullable=false, onDelete="CASCADE")
* @Assert\NotNull
* @Groups({"teamplay_recap:read", "teamplay_recap:write"})
*/
private $user;
/**
* @ORM\ManyToOne(targetEntity=Teamplay::class)
* @ORM\JoinColumn(nullable=false, onDelete="CASCADE")
* @Assert\NotNull
* @Groups({"teamplay_recap:read", "teamplay_recap:write"})
*/
private $teamplay;
/**
* @ORM\ManyToOne(targetEntity=Team::class)
* @ORM\JoinColumn(nullable=true, onDelete="SET NULL")
* @Groups({"teamplay_recap:read", "teamplay_recap:write"})
*/
private $team;
/**
* @ORM\ManyToOne(targetEntity=Company::class)
* @ORM\JoinColumn(nullable=true, onDelete="SET NULL")
* @Groups({"teamplay_recap:read", "teamplay_recap:write"})
*/
private $company;
// ═══════════════════════════════════════════════════════════════
// INFORMATIONS TEAMPLAY (SNAPSHOT)
// ═══════════════════════════════════════════════════════════════
/**
* @ORM\Column(type="string", length=255)
* @Groups({"teamplay_recap:read", "teamplay_recap:write"})
*/
private $teamplayName;
/**
* @ORM\Column(type="text", nullable=true)
* @Groups({"teamplay_recap:read", "teamplay_recap:write"})
*/
private $teamplayDescription;
/**
* @ORM\ManyToOne(targetEntity=MediaObject::class)
* @Groups({"teamplay_recap:read", "teamplay_recap:write"})
*/
private $teamplayPicture;
/**
* @ORM\Column(type="datetime")
* @Groups({"teamplay_recap:read", "teamplay_recap:write"})
*/
private $teamplayStartDate;
/**
* @ORM\Column(type="datetime")
* @Groups({"teamplay_recap:read", "teamplay_recap:write"})
*/
private $teamplayEndDate;
/**
* @ORM\Column(type="integer")
* @Groups({"teamplay_recap:read", "teamplay_recap:write"})
*/
private $teamplayDuration;
// ═══════════════════════════════════════════════════════════════
// PERFORMANCES UTILISATEUR
// ═══════════════════════════════════════════════════════════════
/**
* @ORM\Column(type="integer", options={"default": 0})
* @Groups({"teamplay_recap:read", "teamplay_recap:write"})
*/
private $totalPoints = 0;
/**
* @ORM\Column(type="integer", nullable=true)
* @Groups({"teamplay_recap:read", "teamplay_recap:write"})
*/
private $userRank;
/**
* @ORM\Column(type="integer", nullable=true)
* @Groups({"teamplay_recap:read", "teamplay_recap:write"})
*/
private $globalRank;
/**
* @ORM\Column(type="integer", options={"default": 0})
* @Groups({"teamplay_recap:read", "teamplay_recap:write"})
*/
private $totalParticipants = 0;
// ═══════════════════════════════════════════════════════════════
// STATISTIQUES ACTIVITÉS UTILISATEUR
// ═══════════════════════════════════════════════════════════════
/**
* @ORM\Column(type="bigint", options={"default": 0})
* @Groups({"teamplay_recap:read", "teamplay_recap:write"})
*/
private $totalSteps = 0;
/**
* @ORM\Column(type="decimal", precision=12, scale=2, options={"default": 0})
* @Groups({"teamplay_recap:read", "teamplay_recap:write"})
*/
private $totalBikeDistance = 0;
/**
* @ORM\Column(type="decimal", precision=12, scale=2, options={"default": 0})
* @Groups({"teamplay_recap:read", "teamplay_recap:write"})
*/
private $totalRunDistance = 0;
/**
* @ORM\Column(type="integer", options={"default": 0})
* @Groups({"teamplay_recap:read", "teamplay_recap:write"})
*/
private $totalKinestexReps = 0;
/**
* @ORM\Column(type="integer", options={"default": 0})
* @Groups({"teamplay_recap:read", "teamplay_recap:write"})
*/
private $totalKinestexDuration = 0;
/**
* @ORM\Column(type="integer", options={"default": 0})
* @Groups({"teamplay_recap:read", "teamplay_recap:write"})
*/
private $totalKinestexSessions = 0;
/**
* @ORM\Column(type="integer", options={"default": 0})
* @Groups({"teamplay_recap:read", "teamplay_recap:write"})
*/
private $totalQuizCorrect = 0;
/**
* @ORM\Column(type="integer", options={"default": 0})
* @Groups({"teamplay_recap:read", "teamplay_recap:write"})
*/
private $totalQuizQuestions = 0;
/**
* @ORM\Column(type="integer", options={"default": 0})
* @Groups({"teamplay_recap:read", "teamplay_recap:write"})
*/
private $totalVideosWatched = 0;
// ═══════════════════════════════════════════════════════════════
// INFORMATIONS ÉQUIPE (SNAPSHOT)
// ═══════════════════════════════════════════════════════════════
/**
* @ORM\Column(type="string", length=255, nullable=true)
* @Groups({"teamplay_recap:read", "teamplay_recap:write"})
*/
private $teamName;
/**
* @ORM\ManyToOne(targetEntity=MediaObject::class)
* @Groups({"teamplay_recap:read", "teamplay_recap:write"})
*/
private $teamPicture;
/**
* @ORM\Column(type="integer", options={"default": 0})
* @Groups({"teamplay_recap:read", "teamplay_recap:write"})
*/
private $teamPoints = 0;
/**
* @ORM\Column(type="integer", nullable=true)
* @Groups({"teamplay_recap:read", "teamplay_recap:write"})
*/
private $teamRank;
/**
* @ORM\Column(type="integer", options={"default": 0})
* @Groups({"teamplay_recap:read", "teamplay_recap:write"})
*/
private $totalTeams = 0;
/**
* @ORM\Column(type="integer", options={"default": 0})
* @Groups({"teamplay_recap:read", "teamplay_recap:write"})
*/
private $teamMembersCount = 0;
// ═══════════════════════════════════════════════════════════════
// STATISTIQUES ÉQUIPE
// ═══════════════════════════════════════════════════════════════
/**
* @ORM\Column(type="bigint", options={"default": 0})
* @Groups({"teamplay_recap:read", "teamplay_recap:write"})
*/
private $teamTotalSteps = 0;
/**
* @ORM\Column(type="decimal", precision=12, scale=2, options={"default": 0})
* @Groups({"teamplay_recap:read", "teamplay_recap:write"})
*/
private $teamTotalBikeDistance = 0;
/**
* @ORM\Column(type="decimal", precision=12, scale=2, options={"default": 0})
* @Groups({"teamplay_recap:read", "teamplay_recap:write"})
*/
private $teamTotalRunDistance = 0;
/**
* @ORM\Column(type="integer", options={"default": 0})
* @Groups({"teamplay_recap:read", "teamplay_recap:write"})
*/
private $teamTotalQuizCorrect = 0;
/**
* @ORM\Column(type="integer", options={"default": 0})
* @Groups({"teamplay_recap:read", "teamplay_recap:write"})
*/
private $teamTotalVideosWatched = 0;
/**
* @ORM\Column(type="integer", options={"default": 0})
* @Groups({"teamplay_recap:read", "teamplay_recap:write"})
*/
private $teamTotalKinestexSessions = 0;
// ═══════════════════════════════════════════════════════════════
// RÉSUMÉ DES TYPES DE CHALLENGES PRÉSENTS (NOUVEAU)
// ═══════════════════════════════════════════════════════════════
/**
* Tableau récapitulatif des types d'activités présents dans le Teamplay
* (quiz, bike, run, step, kinestex, video, etc.) + détail des exos Kinestex
*
* @ORM\Column(type="json", nullable=true)
* @Groups({"teamplay_recap:read", "teamplay_recap:write"})
*/
private $challengeTypesSummary = [];
// ═══════════════════════════════════════════════════════════════
// DÉTAILS CHALLENGES COMPLÉTÉS
// ═══════════════════════════════════════════════════════════════
/**
* @ORM\Column(type="json", nullable=true)
* @Groups({"teamplay_recap:read", "teamplay_recap:write"})
*/
private $challengesData = [];
/**
* @ORM\Column(type="integer", options={"default": 0})
* @Groups({"teamplay_recap:read", "teamplay_recap:write"})
*/
private $challengesCompletedCount = 0;
/**
* @ORM\Column(type="integer", options={"default": 0})
* @Groups({"teamplay_recap:read", "teamplay_recap:write"})
*/
private $challengesTotalCount = 0;
// ═══════════════════════════════════════════════════════════════
// MÉTADONNÉES
// ═══════════════════════════════════════════════════════════════
/**
* @ORM\Column(type="datetime", options={"default": "CURRENT_TIMESTAMP"})
* @Gedmo\Timestampable(on="create")
* @Groups({"teamplay_recap:read"})
*/
private $createdAt;
/**
* @ORM\Column(type="datetime", nullable=true)
* @Gedmo\Timestampable(on="update")
* @Groups({"teamplay_recap:read"})
*/
private $updatedAt;
/**
* @ORM\Column(type="boolean", options={"default": true})
* @Groups({"teamplay_recap:read", "teamplay_recap:write"})
*/
private $autoGenerated = true;
/**
* @ORM\Column(type="json", nullable=true)
* @Groups({"teamplay_recap:read", "teamplay_recap:write"})
*/
private $extraData = [];
// ═══════════════════════════════════════════════════════════════
// GETTERS & SETTERS
// ═══════════════════════════════════════════════════════════════
public function getId(): ?int
{
return $this->id;
}
public function getUser(): ?User
{
return $this->user;
}
public function setUser(?User $user): self
{
$this->user = $user;
return $this;
}
public function getTeamplay(): ?Teamplay
{
return $this->teamplay;
}
public function setTeamplay(?Teamplay $teamplay): self
{
$this->teamplay = $teamplay;
return $this;
}
public function getTeam(): ?Team
{
return $this->team;
}
public function setTeam(?Team $team): self
{
$this->team = $team;
return $this;
}
public function getCompany(): ?Company
{
return $this->company;
}
public function setCompany(?Company $company): self
{
$this->company = $company;
return $this;
}
public function getTeamplayName(): ?string
{
return $this->teamplayName;
}
public function setTeamplayName(string $teamplayName): self
{
$this->teamplayName = $teamplayName;
return $this;
}
public function getTeamplayDescription(): ?string
{
return $this->teamplayDescription;
}
public function setTeamplayDescription(?string $teamplayDescription): self
{
$this->teamplayDescription = $teamplayDescription;
return $this;
}
public function getTeamplayPicture(): ?MediaObject
{
return $this->teamplayPicture;
}
public function setTeamplayPicture(?MediaObject $teamplayPicture): self
{
$this->teamplayPicture = $teamplayPicture;
return $this;
}
public function getTeamplayStartDate(): ?\DateTimeInterface
{
return $this->teamplayStartDate;
}
public function setTeamplayStartDate(\DateTimeInterface $teamplayStartDate): self
{
$this->teamplayStartDate = $teamplayStartDate;
return $this;
}
public function getTeamplayEndDate(): ?\DateTimeInterface
{
return $this->teamplayEndDate;
}
public function setTeamplayEndDate(\DateTimeInterface $teamplayEndDate): self
{
$this->teamplayEndDate = $teamplayEndDate;
return $this;
}
public function getTeamplayDuration(): ?int
{
return $this->teamplayDuration;
}
public function setTeamplayDuration(int $teamplayDuration): self
{
$this->teamplayDuration = $teamplayDuration;
return $this;
}
public function getTotalPoints(): int
{
return $this->totalPoints;
}
public function setTotalPoints(int $totalPoints): self
{
$this->totalPoints = $totalPoints;
return $this;
}
public function getUserRank(): ?int
{
return $this->userRank;
}
public function setUserRank(?int $userRank): self
{
$this->userRank = $userRank;
return $this;
}
public function getGlobalRank(): ?int
{
return $this->globalRank;
}
public function setGlobalRank(?int $globalRank): self
{
$this->globalRank = $globalRank;
return $this;
}
public function getTotalParticipants(): int
{
return $this->totalParticipants;
}
public function setTotalParticipants(int $totalParticipants): self
{
$this->totalParticipants = $totalParticipants;
return $this;
}
public function getTotalSteps(): int
{
return $this->totalSteps;
}
public function setTotalSteps(int $totalSteps): self
{
$this->totalSteps = $totalSteps;
return $this;
}
public function getTotalBikeDistance(): float
{
return (float) $this->totalBikeDistance;
}
public function setTotalBikeDistance(float $totalBikeDistance): self
{
$this->totalBikeDistance = $totalBikeDistance;
return $this;
}
/**
* @Groups({"teamplay_recap:read"})
*/
public function getTotalBikeDistanceKm(): float
{
return round($this->getTotalBikeDistance() / 1000, 2);
}
public function getTotalRunDistance(): float
{
return (float) $this->totalRunDistance;
}
public function setTotalRunDistance(float $totalRunDistance): self
{
$this->totalRunDistance = $totalRunDistance;
return $this;
}
/**
* @Groups({"teamplay_recap:read"})
*/
public function getTotalRunDistanceKm(): float
{
return round($this->getTotalRunDistance() / 1000, 2);
}
public function getTotalKinestexReps(): int
{
return $this->totalKinestexReps;
}
public function setTotalKinestexReps(int $totalKinestexReps): self
{
$this->totalKinestexReps = $totalKinestexReps;
return $this;
}
public function getTotalKinestexDuration(): int
{
return $this->totalKinestexDuration;
}
public function setTotalKinestexDuration(int $totalKinestexDuration): self
{
$this->totalKinestexDuration = $totalKinestexDuration;
return $this;
}
public function getTotalKinestexSessions(): int
{
return $this->totalKinestexSessions;
}
public function setTotalKinestexSessions(int $totalKinestexSessions): self
{
$this->totalKinestexSessions = $totalKinestexSessions;
return $this;
}
public function getTotalQuizCorrect(): int
{
return $this->totalQuizCorrect;
}
public function setTotalQuizCorrect(int $totalQuizCorrect): self
{
$this->totalQuizCorrect = $totalQuizCorrect;
return $this;
}
public function getTotalQuizQuestions(): int
{
return $this->totalQuizQuestions;
}
public function setTotalQuizQuestions(int $totalQuizQuestions): self
{
$this->totalQuizQuestions = $totalQuizQuestions;
return $this;
}
public function getTotalVideosWatched(): int
{
return $this->totalVideosWatched;
}
public function setTotalVideosWatched(int $totalVideosWatched): self
{
$this->totalVideosWatched = $totalVideosWatched;
return $this;
}
public function getTeamName(): ?string
{
return $this->teamName;
}
public function setTeamName(?string $teamName): self
{
$this->teamName = $teamName;
return $this;
}
public function getTeamPicture(): ?MediaObject
{
return $this->teamPicture;
}
public function setTeamPicture(?MediaObject $teamPicture): self
{
$this->teamPicture = $teamPicture;
return $this;
}
public function getTeamPoints(): int
{
return $this->teamPoints;
}
public function setTeamPoints(int $teamPoints): self
{
$this->teamPoints = $teamPoints;
return $this;
}
public function getTeamRank(): ?int
{
return $this->teamRank;
}
public function setTeamRank(?int $teamRank): self
{
$this->teamRank = $teamRank;
return $this;
}
public function getTotalTeams(): int
{
return $this->totalTeams;
}
public function setTotalTeams(int $totalTeams): self
{
$this->totalTeams = $totalTeams;
return $this;
}
public function getTeamMembersCount(): int
{
return $this->teamMembersCount;
}
public function setTeamMembersCount(int $teamMembersCount): self
{
$this->teamMembersCount = $teamMembersCount;
return $this;
}
public function getTeamTotalSteps(): int
{
return $this->teamTotalSteps;
}
public function setTeamTotalSteps(int $teamTotalSteps): self
{
$this->teamTotalSteps = $teamTotalSteps;
return $this;
}
public function getTeamTotalBikeDistance(): float
{
return (float) $this->teamTotalBikeDistance;
}
public function setTeamTotalBikeDistance(float $teamTotalBikeDistance): self
{
$this->teamTotalBikeDistance = $teamTotalBikeDistance;
return $this;
}
public function getTeamTotalRunDistance(): float
{
return (float) $this->teamTotalRunDistance;
}
public function setTeamTotalRunDistance(float $teamTotalRunDistance): self
{
$this->teamTotalRunDistance = $teamTotalRunDistance;
return $this;
}
public function getTeamTotalQuizCorrect(): int
{
return $this->teamTotalQuizCorrect;
}
public function setTeamTotalQuizCorrect(int $teamTotalQuizCorrect): self
{
$this->teamTotalQuizCorrect = $teamTotalQuizCorrect;
return $this;
}
public function getTeamTotalVideosWatched(): int
{
return $this->teamTotalVideosWatched;
}
public function setTeamTotalVideosWatched(int $teamTotalVideosWatched): self
{
$this->teamTotalVideosWatched = $teamTotalVideosWatched;
return $this;
}
public function getTeamTotalKinestexSessions(): int
{
return $this->teamTotalKinestexSessions;
}
public function setTeamTotalKinestexSessions(int $teamTotalKinestexSessions): self
{
$this->teamTotalKinestexSessions = $teamTotalKinestexSessions;
return $this;
}
public function getChallengeTypesSummary(): ?array
{
return $this->challengeTypesSummary;
}
public function setChallengeTypesSummary(?array $challengeTypesSummary): self
{
$this->challengeTypesSummary = $challengeTypesSummary;
return $this;
}
public function getChallengesData(): ?array
{
return $this->challengesData;
}
public function setChallengesData(?array $challengesData): self
{
$this->challengesData = $challengesData;
return $this;
}
public function getChallengesCompletedCount(): int
{
return $this->challengesCompletedCount;
}
public function setChallengesCompletedCount(int $challengesCompletedCount): self
{
$this->challengesCompletedCount = $challengesCompletedCount;
return $this;
}
public function getChallengesTotalCount(): int
{
return $this->challengesTotalCount;
}
public function setChallengesTotalCount(int $challengesTotalCount): self
{
$this->challengesTotalCount = $challengesTotalCount;
return $this;
}
/**
* @Groups({"teamplay_recap:read"})
*/
public function getCompletionRate(): float
{
if ($this->challengesTotalCount === 0) {
return 0;
}
return round(($this->challengesCompletedCount / $this->challengesTotalCount) * 100, 2);
}
public function getCreatedAt(): ?\DateTimeInterface
{
return $this->createdAt;
}
public function setCreatedAt(\DateTimeInterface $createdAt): self
{
$this->createdAt = $createdAt;
return $this;
}
public function getUpdatedAt(): ?\DateTimeInterface
{
return $this->updatedAt;
}
public function setUpdatedAt(?\DateTimeInterface $updatedAt): self
{
$this->updatedAt = $updatedAt;
return $this;
}
public function isAutoGenerated(): bool
{
return $this->autoGenerated;
}
public function setAutoGenerated(bool $autoGenerated): self
{
$this->autoGenerated = $autoGenerated;
return $this;
}
public function getExtraData(): ?array
{
return $this->extraData;
}
public function setExtraData(?array $extraData): self
{
$this->extraData = $extraData;
return $this;
}
/**
* URL directe de l'image du teamplay
* @Groups({"teamplay_recap:read"})
*/
public function getTeamplayPictureUrl(): ?string
{
return $this->teamplayPicture ? $this->teamplayPicture->getContentUrl() : null;
}
/**
* URL directe de l'image de l'équipe
* @Groups({"teamplay_recap:read"})
*/
public function getTeamPictureUrl(): ?string
{
return $this->teamPicture ? $this->teamPicture->getContentUrl() : null;
}
/**
* URL directe de l'avatar de l'utilisateur
* @Groups({"teamplay_recap:read"})
*/
public function getUserPictureUrl(): ?string
{
if ($this->user && $this->user->getClient() && $this->user->getClient()->getAvatar()) {
return $this->user->getClient()->getAvatar()->getContentUrl();
}
return null;
}
}