Merge branch 'dev-comp' into dev
All checks were successful
Deploy Production Server / if_merged (pull_request) Successful in 10m20s
All checks were successful
Deploy Production Server / if_merged (pull_request) Successful in 10m20s
This commit is contained in:
@@ -0,0 +1,42 @@
|
||||
package fr.titionfire.ffsaf.data.model;
|
||||
|
||||
import io.quarkus.runtime.annotations.RegisterForReflection;
|
||||
import jakarta.persistence.*;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.Setter;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@RegisterForReflection
|
||||
|
||||
@Entity
|
||||
@Table(name = "cardboard")
|
||||
public class CardboardModel {
|
||||
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
Long id;
|
||||
|
||||
@ManyToOne(fetch = FetchType.LAZY)
|
||||
@JoinColumn(name = "comb", referencedColumnName = "id")
|
||||
MembreModel comb;
|
||||
|
||||
@ManyToOne(fetch = FetchType.LAZY)
|
||||
@JoinColumn(name = "guest_comb", referencedColumnName = "id")
|
||||
CompetitionGuestModel guestComb;
|
||||
|
||||
@ManyToOne(fetch = FetchType.LAZY)
|
||||
@JoinColumn(name = "match", referencedColumnName = "id")
|
||||
MatchModel match;
|
||||
|
||||
@ManyToOne(fetch = FetchType.LAZY)
|
||||
@JoinColumn(name = "compet", referencedColumnName = "id")
|
||||
CompetitionModel compet;
|
||||
|
||||
int red;
|
||||
int yellow;
|
||||
}
|
||||
@@ -42,4 +42,6 @@ public class CategoryModel {
|
||||
List<TreeModel> tree;
|
||||
|
||||
Integer type;
|
||||
|
||||
String liceName = "1";
|
||||
}
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
package fr.titionfire.ffsaf.data.model;
|
||||
|
||||
import fr.titionfire.ffsaf.utils.Categorie;
|
||||
import fr.titionfire.ffsaf.utils.Genre;
|
||||
import io.quarkus.runtime.annotations.RegisterForReflection;
|
||||
import jakarta.persistence.*;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.Setter;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@RegisterForReflection
|
||||
|
||||
@Entity
|
||||
@Table(name = "competition_guest")
|
||||
public class CompetitionGuestModel {
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
Long id;
|
||||
|
||||
@ManyToOne(fetch = FetchType.LAZY)
|
||||
@JoinColumn(name = "competition", referencedColumnName = "id")
|
||||
CompetitionModel competition;
|
||||
|
||||
String lname = "";
|
||||
String fname = "";
|
||||
|
||||
Categorie categorie = null;
|
||||
|
||||
String club = null;
|
||||
|
||||
Genre genre = null;
|
||||
|
||||
String country = "fr";
|
||||
|
||||
Integer weight = null;
|
||||
|
||||
public CompetitionGuestModel(String s) {
|
||||
this.fname = s.substring(0, s.indexOf(" "));
|
||||
this.lname = s.substring(s.indexOf(" ") + 1);
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return fname + " " + lname;
|
||||
}
|
||||
}
|
||||
@@ -55,10 +55,18 @@ public class CompetitionModel {
|
||||
@OneToMany(mappedBy = "competition", fetch = FetchType.LAZY, cascade = CascadeType.ALL)
|
||||
List<RegisterModel> insc;
|
||||
|
||||
@OneToMany(mappedBy = "competition", fetch = FetchType.LAZY, cascade = CascadeType.ALL)
|
||||
List<CompetitionGuestModel> guests = new ArrayList<>();
|
||||
|
||||
|
||||
List<Long> banMembre = new ArrayList<>();
|
||||
|
||||
String owner;
|
||||
|
||||
List<String> admin = new ArrayList<>();
|
||||
@Column(name = "table_")
|
||||
List<String> table = new ArrayList<>();
|
||||
|
||||
String data1;
|
||||
String data2;
|
||||
String data3;
|
||||
|
||||
@@ -7,6 +7,7 @@ import jakarta.persistence.*;
|
||||
import lombok.*;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
@Getter
|
||||
@@ -32,13 +33,17 @@ public class MatchModel {
|
||||
@JoinColumn(name = "c1", referencedColumnName = "id")
|
||||
MembreModel c1_id = null;
|
||||
|
||||
String c1_str = null;
|
||||
@ManyToOne(fetch = FetchType.EAGER)
|
||||
@JoinColumn(name = "c1_guest", referencedColumnName = "id")
|
||||
CompetitionGuestModel c1_guest = null;
|
||||
|
||||
@ManyToOne(fetch = FetchType.EAGER)
|
||||
@JoinColumn(name = "c2", referencedColumnName = "id")
|
||||
MembreModel c2_id = null;
|
||||
|
||||
String c2_str = null;
|
||||
@ManyToOne(fetch = FetchType.EAGER)
|
||||
@JoinColumn(name = "c2_guest", referencedColumnName = "id")
|
||||
CompetitionGuestModel c2_guest = null;
|
||||
|
||||
@ManyToOne(fetch = FetchType.EAGER)
|
||||
@JoinColumn(name = "id_category", referencedColumnName = "id")
|
||||
@@ -48,9 +53,45 @@ public class MatchModel {
|
||||
|
||||
boolean isEnd = true;
|
||||
|
||||
Date date = null;
|
||||
|
||||
@ElementCollection(fetch = FetchType.EAGER)
|
||||
@CollectionTable(name = "score", joinColumns = @JoinColumn(name = "id_match"))
|
||||
List<ScoreEmbeddable> scores = new ArrayList<>();
|
||||
|
||||
char poule = 'A';
|
||||
|
||||
@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
|
||||
@JoinColumn(name = "match", referencedColumnName = "id")
|
||||
List<CardboardModel> cardboard = new ArrayList<>();
|
||||
|
||||
public String getC1Name() {
|
||||
if (c1_id != null)
|
||||
return c1_id.fname + " " + c1_id.lname;
|
||||
if (c1_guest != null)
|
||||
return c1_guest.fname + " " + c1_guest.lname;
|
||||
return "";
|
||||
}
|
||||
|
||||
public String getC2Name() {
|
||||
if (c2_id != null)
|
||||
return c2_id.fname + " " + c2_id.lname;
|
||||
if (c2_guest != null)
|
||||
return c2_guest.fname + " " + c2_guest.lname;
|
||||
return "";
|
||||
}
|
||||
|
||||
public int win() {
|
||||
int sum = 0;
|
||||
for (ScoreEmbeddable score : this.getScores()) {
|
||||
if (score.getS1() == -1000 || score.getS2() == -1000)
|
||||
continue;
|
||||
|
||||
if (score.getS1() > score.getS2())
|
||||
sum++;
|
||||
else if (score.getS1() < score.getS2())
|
||||
sum--;
|
||||
}
|
||||
return sum;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -56,4 +56,14 @@ public class RegisterModel {
|
||||
this.categorie = categorie;
|
||||
this.club = club;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return membre.fname + " " + membre.lname;
|
||||
}
|
||||
|
||||
public ClubModel getClub2() {
|
||||
if (club == null)
|
||||
return membre.club;
|
||||
return club;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,6 +7,9 @@ import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.Setter;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
@AllArgsConstructor
|
||||
@@ -36,4 +39,20 @@ public class TreeModel {
|
||||
@ManyToOne(fetch = FetchType.EAGER, cascade = CascadeType.PERSIST)
|
||||
@JoinColumn(referencedColumnName = "id")
|
||||
TreeModel right;
|
||||
|
||||
public List<TreeModel> flat() {
|
||||
List<TreeModel> out = new ArrayList<>();
|
||||
this.flat(out);
|
||||
return out;
|
||||
}
|
||||
|
||||
private void flat(List<TreeModel> out) {
|
||||
out.add(this);
|
||||
|
||||
if (this.right != null)
|
||||
this.right.flat(out);
|
||||
|
||||
if (this.left != null)
|
||||
this.left.flat(out);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
package fr.titionfire.ffsaf.data.repository;
|
||||
|
||||
import fr.titionfire.ffsaf.data.model.CardboardModel;
|
||||
import io.quarkus.hibernate.reactive.panache.PanacheRepositoryBase;
|
||||
import jakarta.enterprise.context.ApplicationScoped;
|
||||
|
||||
@ApplicationScoped
|
||||
public class CardboardRepository implements PanacheRepositoryBase<CardboardModel, Long> {
|
||||
}
|
||||
@@ -1,9 +1,19 @@
|
||||
package fr.titionfire.ffsaf.data.repository;
|
||||
|
||||
import fr.titionfire.ffsaf.data.model.CategoryModel;
|
||||
import fr.titionfire.ffsaf.utils.CompetitionSystem;
|
||||
import io.quarkus.hibernate.reactive.panache.Panache;
|
||||
import io.quarkus.hibernate.reactive.panache.PanacheRepositoryBase;
|
||||
import io.smallrye.mutiny.Uni;
|
||||
import jakarta.enterprise.context.ApplicationScoped;
|
||||
|
||||
@ApplicationScoped
|
||||
public class CategoryRepository implements PanacheRepositoryBase<CategoryModel, Long> {
|
||||
|
||||
public Uni<CategoryModel> create(CategoryModel categoryModel) {
|
||||
categoryModel.setSystem(CompetitionSystem.INTERNAL);
|
||||
return Panache.withTransaction(() -> this.persist(categoryModel)
|
||||
.invoke(categoryModel1 -> categoryModel1.setSystemId(categoryModel1.getId())))
|
||||
.chain(this::persist);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
package fr.titionfire.ffsaf.data.repository;
|
||||
|
||||
import fr.titionfire.ffsaf.data.model.CompetitionGuestModel;
|
||||
import io.quarkus.hibernate.reactive.panache.PanacheRepositoryBase;
|
||||
import jakarta.enterprise.context.ApplicationScoped;
|
||||
|
||||
@ApplicationScoped
|
||||
public class CompetitionGuestRepository implements PanacheRepositoryBase<CompetitionGuestModel, Long> {
|
||||
}
|
||||
@@ -1,9 +1,30 @@
|
||||
package fr.titionfire.ffsaf.data.repository;
|
||||
|
||||
import fr.titionfire.ffsaf.data.model.MatchModel;
|
||||
import fr.titionfire.ffsaf.utils.CompetitionSystem;
|
||||
import io.quarkus.hibernate.reactive.panache.Panache;
|
||||
import io.quarkus.hibernate.reactive.panache.PanacheRepositoryBase;
|
||||
import io.smallrye.mutiny.Uni;
|
||||
import jakarta.enterprise.context.ApplicationScoped;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@ApplicationScoped
|
||||
public class MatchRepository implements PanacheRepositoryBase<MatchModel, Long> {
|
||||
|
||||
public Uni<MatchModel> create(MatchModel matchModel) {
|
||||
matchModel.setSystem(CompetitionSystem.INTERNAL);
|
||||
return Panache.withTransaction(() -> this.persistAndFlush(matchModel)
|
||||
.invoke(matchModel1 -> matchModel1.setSystemId(matchModel1.getId())))
|
||||
.chain(this::persist);
|
||||
}
|
||||
|
||||
public Uni<Void> create(List<MatchModel> matchModel) {
|
||||
matchModel.forEach(model -> model.setSystem(CompetitionSystem.INTERNAL));
|
||||
return Panache.withTransaction(() -> this.persist(matchModel)
|
||||
.call(__ -> this.flush())
|
||||
.invoke(__ -> matchModel.forEach(model -> model.setSystemId(model.getId())))
|
||||
.map(__ -> matchModel))
|
||||
.chain(this::persist);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,8 +2,22 @@ package fr.titionfire.ffsaf.data.repository;
|
||||
|
||||
import fr.titionfire.ffsaf.data.model.TreeModel;
|
||||
import io.quarkus.hibernate.reactive.panache.PanacheRepositoryBase;
|
||||
import io.quarkus.hibernate.reactive.panache.common.WithTransaction;
|
||||
import io.smallrye.mutiny.Uni;
|
||||
import jakarta.enterprise.context.ApplicationScoped;
|
||||
|
||||
@ApplicationScoped
|
||||
public class TreeRepository implements PanacheRepositoryBase<TreeModel, Long> {
|
||||
|
||||
@WithTransaction
|
||||
public Uni<Boolean> deleteTree(TreeModel entity) {
|
||||
Uni<Boolean> uni = Uni.createFrom().item(false);
|
||||
if (entity == null)
|
||||
return uni;
|
||||
if (entity.getLeft() != null)
|
||||
uni = uni.chain(__ -> this.deleteTree(entity.getLeft()));
|
||||
if (entity.getRight() != null)
|
||||
uni = uni.chain(__ -> this.deleteTree(entity.getRight()));
|
||||
return uni.chain(__ -> this.deleteById(entity.getId()));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
package fr.titionfire.ffsaf.domain.entity;
|
||||
|
||||
import fr.titionfire.ffsaf.data.model.CardboardModel;
|
||||
import io.quarkus.runtime.annotations.RegisterForReflection;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@RegisterForReflection
|
||||
public class CardboardEntity {
|
||||
long comb_id;
|
||||
long match_id;
|
||||
long compet_id;
|
||||
|
||||
int red;
|
||||
int yellow;
|
||||
|
||||
public static CardboardEntity fromModel(CardboardModel model) {
|
||||
return new CardboardEntity(
|
||||
model.getComb() != null ? model.getComb().getId() : model.getGuestComb().getId() * -1,
|
||||
model.getMatch().getId(),
|
||||
model.getCompet().getId(),
|
||||
model.getRed(), model.getYellow());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
package fr.titionfire.ffsaf.domain.entity;
|
||||
|
||||
import fr.titionfire.ffsaf.data.model.CompetitionGuestModel;
|
||||
import fr.titionfire.ffsaf.data.model.MembreModel;
|
||||
import fr.titionfire.ffsaf.data.model.RegisterModel;
|
||||
import fr.titionfire.ffsaf.utils.Categorie;
|
||||
import fr.titionfire.ffsaf.utils.Genre;
|
||||
import io.quarkus.runtime.annotations.RegisterForReflection;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@RegisterForReflection
|
||||
public class CombEntity {
|
||||
private long id;
|
||||
private String lname;
|
||||
private String fname;
|
||||
Categorie categorie;
|
||||
String club_uuid;
|
||||
String club_str;
|
||||
Genre genre;
|
||||
String country;
|
||||
int overCategory;
|
||||
Integer weight;
|
||||
|
||||
public static CombEntity fromModel(MembreModel model) {
|
||||
if (model == null)
|
||||
return null;
|
||||
|
||||
return new CombEntity(model.getId(), model.getLname(), model.getFname(), model.getCategorie(),
|
||||
model.getClub() == null ? null : model.getClub().getClubId(),
|
||||
model.getClub() == null ? "Sans club" : model.getClub().getName(), model.getGenre(), model.getCountry(),
|
||||
0, null);
|
||||
}
|
||||
|
||||
|
||||
public static CombEntity fromModel(CompetitionGuestModel model) {
|
||||
if (model == null)
|
||||
return null;
|
||||
|
||||
return new CombEntity(model.getId() * -1, model.getLname(), model.getFname(), model.getCategorie(), null,
|
||||
model.getClub(), model.getGenre(), model.getCountry(), 0, model.getWeight());
|
||||
}
|
||||
|
||||
public static CombEntity fromModel(RegisterModel registerModel) {
|
||||
if (registerModel == null || registerModel.getMembre() == null)
|
||||
return null;
|
||||
MembreModel model = registerModel.getMembre();
|
||||
|
||||
return new CombEntity(model.getId(), model.getLname(), model.getFname(), registerModel.getCategorie(),
|
||||
registerModel.getClub2() == null ? null : registerModel.getClub2().getClubId(),
|
||||
registerModel.getClub2() == null ? "Sans club" : registerModel.getClub2().getName(), model.getGenre(),
|
||||
model.getCountry(), registerModel.getOverCategory(), registerModel.getWeight());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
package fr.titionfire.ffsaf.domain.entity;
|
||||
|
||||
import fr.titionfire.ffsaf.data.model.MatchModel;
|
||||
import fr.titionfire.ffsaf.utils.ScoreEmbeddable;
|
||||
import io.quarkus.runtime.annotations.RegisterForReflection;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@RegisterForReflection
|
||||
public class MatchEntity {
|
||||
private long id;
|
||||
private CombEntity c1;
|
||||
private CombEntity c2;
|
||||
private long categorie_ord = 0;
|
||||
private boolean isEnd;
|
||||
private long categorie;
|
||||
private Date date;
|
||||
private List<ScoreEmbeddable> scores;
|
||||
private char poule;
|
||||
private List<CardboardEntity> cardboard;
|
||||
|
||||
public static MatchEntity fromModel(MatchModel model) {
|
||||
if (model == null)
|
||||
return null;
|
||||
return new MatchEntity(model.getId(),
|
||||
(model.getC1_id() == null) ? CombEntity.fromModel(model.getC1_guest()) : CombEntity.fromModel(
|
||||
model.getC1_id()),
|
||||
(model.getC2_id() == null) ? CombEntity.fromModel(model.getC2_guest()) : CombEntity.fromModel(
|
||||
model.getC2_id()),
|
||||
model.getCategory_ord(), model.isEnd(), model.getCategory().getId(), model.getDate(),
|
||||
model.getScores(),
|
||||
model.getPoule(),
|
||||
(model.getCardboard() == null) ? new ArrayList<>() : model.getCardboard().stream()
|
||||
.map(CardboardEntity::fromModel).toList());
|
||||
}
|
||||
|
||||
public int win() {
|
||||
int sum = 0;
|
||||
for (ScoreEmbeddable score : scores) {
|
||||
if (score.getS1() == -1000 || score.getS2() == -1000)
|
||||
continue;
|
||||
|
||||
if (score.getS1() > score.getS2())
|
||||
sum++;
|
||||
else if (score.getS1() < score.getS2())
|
||||
sum--;
|
||||
}
|
||||
return sum;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
package fr.titionfire.ffsaf.domain.entity;
|
||||
|
||||
import fr.titionfire.ffsaf.data.model.TreeModel;
|
||||
import io.quarkus.runtime.annotations.RegisterForReflection;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@RegisterForReflection
|
||||
public class TreeEntity {
|
||||
private Long id;
|
||||
private Long categorie;
|
||||
private Integer level;
|
||||
private MatchEntity match;
|
||||
private TreeEntity left;
|
||||
private TreeEntity right;
|
||||
private TreeEntity associatedNode;
|
||||
|
||||
public static TreeEntity fromModel(TreeModel model) {
|
||||
if (model == null)
|
||||
return null;
|
||||
|
||||
return new TreeEntity(model.getId(), model.getCategory(), model.getLevel(), MatchEntity.fromModel(model.getMatch()), fromModel(model.getLeft()),
|
||||
fromModel(model.getRight()), null);
|
||||
}
|
||||
|
||||
public TreeEntity getMatchNode(Long matchId) {
|
||||
if (this.match != null && this.match.getId() == matchId) {
|
||||
return this;
|
||||
} else {
|
||||
if (this.left != null) {
|
||||
TreeEntity left = this.left.getMatchNode(matchId);
|
||||
if (left != null) {
|
||||
return left;
|
||||
}
|
||||
}
|
||||
if (this.right != null) {
|
||||
TreeEntity right = this.right.getMatchNode(matchId);
|
||||
if (right != null) {
|
||||
return right;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static TreeEntity getParent(TreeEntity current, TreeEntity target) {
|
||||
if (current == null) {
|
||||
return null;
|
||||
} else if (current.equals(target)) {
|
||||
return null;
|
||||
} else if (target.equals(current.left) || target.equals(current.right)) {
|
||||
return current;
|
||||
} else {
|
||||
TreeEntity left = getParent(current.left, target);
|
||||
if (left != null)
|
||||
return left;
|
||||
return getParent(current.right, target);
|
||||
}
|
||||
}
|
||||
|
||||
public static void setAssociated(TreeEntity current, TreeEntity next) {
|
||||
if (current == null || next == null) {
|
||||
return;
|
||||
}
|
||||
current.setAssociatedNode(next);
|
||||
setAssociated(current.getLeft(), next.getLeft());
|
||||
setAssociated(current.getRight(), next.getRight());
|
||||
}
|
||||
}
|
||||
@@ -1,9 +1,6 @@
|
||||
package fr.titionfire.ffsaf.domain.service;
|
||||
|
||||
import fr.titionfire.ffsaf.data.model.MatchModel;
|
||||
import fr.titionfire.ffsaf.data.model.MembreModel;
|
||||
import fr.titionfire.ffsaf.data.model.CategoryModel;
|
||||
import fr.titionfire.ffsaf.data.model.TreeModel;
|
||||
import fr.titionfire.ffsaf.data.model.*;
|
||||
import fr.titionfire.ffsaf.data.repository.*;
|
||||
import fr.titionfire.ffsaf.rest.data.CategoryData;
|
||||
import fr.titionfire.ffsaf.rest.data.CategoryFullData;
|
||||
@@ -45,10 +42,13 @@ public class CategoryService {
|
||||
@Inject
|
||||
CompetPermService permService;
|
||||
|
||||
@Inject
|
||||
CompetitionGuestRepository competitionGuestRepository;
|
||||
|
||||
public Uni<CategoryData> getByIdAdmin(SecurityCtx securityCtx, CompetitionSystem system, Long id) {
|
||||
return repository.find("systemId = ?1 AND system = ?2", id, system)
|
||||
.firstResult()
|
||||
.onItem().ifNull().failWith(() -> new RuntimeException("Poule not found"))
|
||||
.onItem().ifNull().failWith(() -> new RuntimeException("Category not found"))
|
||||
.call(data -> permService.hasAdminViewPerm(securityCtx, data.getCompet()))
|
||||
.map(CategoryData::fromModel);
|
||||
}
|
||||
@@ -171,6 +171,15 @@ public class CategoryService {
|
||||
.invoke(o2 -> o2.forEach(m -> o.membres.put(m.getId(), m)))
|
||||
)
|
||||
)
|
||||
.call(o -> Mutiny.fetch(o.category.getCompet().getGuests())
|
||||
.invoke(o2 -> o2.forEach(m -> o.guest.put(m.getFname() + " " + m.getLname(), m)))
|
||||
.map(o2 -> data.getMatches().stream().flatMap(m -> Stream.of(m.getC1_str(), m.getC2_str())
|
||||
.filter(Objects::nonNull)).distinct().filter(s -> !o.guest.containsKey(s)).map(
|
||||
CompetitionGuestModel::new).toList())
|
||||
.call(o3 -> o3.isEmpty() ? Uni.createFrom().nullItem() :
|
||||
Uni.join().all(o3.stream().map(o4 -> competitionGuestRepository.persist(o4)).toList())
|
||||
.andFailFast())
|
||||
.invoke(o2 -> o2.forEach(m -> o.guest.put(m.getFname() + " " + m.getLname(), m))))
|
||||
.invoke(in -> {
|
||||
ArrayList<TreeModel> node = new ArrayList<>();
|
||||
for (TreeModel treeModel : in.category.getTree())
|
||||
@@ -214,8 +223,8 @@ public class CategoryService {
|
||||
}
|
||||
mm.setCategory(in.category);
|
||||
mm.setCategory_ord(m.getCategory_ord());
|
||||
mm.setC1_str(m.getC1_str());
|
||||
mm.setC2_str(m.getC2_str());
|
||||
mm.setC1_guest(in.guest.getOrDefault(m.getC1_str(), null));
|
||||
mm.setC2_guest(in.guest.getOrDefault(m.getC2_str(), null));
|
||||
mm.setC1_id(in.membres.getOrDefault(m.getC1_id(), null));
|
||||
mm.setC2_id(in.membres.getOrDefault(m.getC2_id(), null));
|
||||
mm.setEnd(m.isEnd());
|
||||
@@ -238,6 +247,7 @@ public class CategoryService {
|
||||
private static class WorkData {
|
||||
CategoryModel category;
|
||||
HashMap<Long, MembreModel> membres = new HashMap<>();
|
||||
HashMap<String, CompetitionGuestModel> guest = new HashMap<>();
|
||||
List<MatchModel> match = new ArrayList<>();
|
||||
List<Long> toRmMatch;
|
||||
List<TreeModel> unlinkNode;
|
||||
@@ -246,7 +256,7 @@ public class CategoryService {
|
||||
|
||||
public Uni<?> delete(SecurityCtx securityCtx, CompetitionSystem system, Long id) {
|
||||
return repository.find("systemId = ?1 AND system = ?2", id, system).firstResult()
|
||||
.onItem().ifNull().failWith(() -> new RuntimeException("Poule not found"))
|
||||
.onItem().ifNull().failWith(() -> new RuntimeException("Category not found"))
|
||||
.call(o -> permService.hasEditPerm(securityCtx, o.getCompet()))
|
||||
.call(o -> Mutiny.fetch(o.getTree())
|
||||
.call(o2 -> o2.isEmpty() ? Uni.createFrom().nullItem() :
|
||||
@@ -260,7 +270,7 @@ public class CategoryService {
|
||||
Panache.withTransaction(() -> treeRepository.delete("id IN ?1", in)))
|
||||
)
|
||||
)
|
||||
.call(o -> matchRepository.delete("poule.id = ?1", o.getId()))
|
||||
.call(o -> matchRepository.delete("category.id = ?1", o.getId()))
|
||||
.chain(model -> Panache.withTransaction(() -> repository.delete("id", model.getId())));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -56,7 +56,7 @@ public class CompetPermService {
|
||||
CompletableFuture<SimpleCompet> f = new CompletableFuture<>();
|
||||
SReqCompet.getConfig(serverCustom.clients, id, f);
|
||||
try {
|
||||
return f.get(1500, TimeUnit.MILLISECONDS);
|
||||
return f.get(500, TimeUnit.MILLISECONDS);
|
||||
} catch (InterruptedException | ExecutionException | TimeoutException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
@@ -71,7 +71,8 @@ public class CompetPermService {
|
||||
.chain(competitionModels -> {
|
||||
CompletableFuture<HashMap<String, String>> f = new CompletableFuture<>();
|
||||
SReqCompet.getAllHaveAccess(serverCustom.clients, securityCtx.getSubject(), f);
|
||||
return Uni.createFrom().future(f, Duration.ofMillis(1500))
|
||||
return Uni.createFrom().future(f, Duration.ofMillis(500))
|
||||
.onFailure().recoverWithItem(new HashMap<>())
|
||||
.map(map_ -> {
|
||||
HashMap<Long, String> map = new HashMap<>();
|
||||
map_.forEach((key, value) -> map.put(Long.parseLong(key), value));
|
||||
@@ -89,7 +90,7 @@ public class CompetPermService {
|
||||
.onFailure().call(throwable -> cacheAccess.invalidate(securityCtx.getSubject()));
|
||||
|
||||
Uni<HashMap<Long, String>> none = cacheNoneAccess.getAsync(securityCtx.getSubject(),
|
||||
k -> competitionRepository.list("system = ?1", CompetitionSystem.NONE)
|
||||
k -> competitionRepository.list("system = ?1", CompetitionSystem.INTERNAL)
|
||||
.map(competitionModels -> {
|
||||
HashMap<Long, String> map = new HashMap<>();
|
||||
for (CompetitionModel model : competitionModels) {
|
||||
@@ -184,7 +185,7 @@ public class CompetPermService {
|
||||
if (!securityCtx.isInClubGroup(o.getClub().getId())) // Only membre club pass here
|
||||
throw new DForbiddenException();
|
||||
|
||||
if (o.getSystem() == CompetitionSystem.NONE)
|
||||
if (o.getSystem() == CompetitionSystem.INTERNAL)
|
||||
if (securityCtx.roleHas("club_president") || securityCtx.roleHas("club_respo_intra")
|
||||
|| securityCtx.roleHas("club_secretaire") || securityCtx.roleHas("club_tresorier"))
|
||||
return Uni.createFrom().nullItem();
|
||||
@@ -219,13 +220,58 @@ public class CompetPermService {
|
||||
if (o.getSystem() == CompetitionSystem.SAFCA)
|
||||
return hasSafcaEditPerm(securityCtx, o.getId());
|
||||
|
||||
if (!securityCtx.isInClubGroup(o.getClub().getId())) // Only membre club pass here
|
||||
throw new DForbiddenException();
|
||||
|
||||
if (o.getSystem() == CompetitionSystem.NONE)
|
||||
if (securityCtx.isClubAdmin())
|
||||
if (o.getSystem() == CompetitionSystem.INTERNAL) {
|
||||
if (securityCtx.isInClubGroup(o.getClub().getId()) && securityCtx.isClubAdmin())
|
||||
return Uni.createFrom().nullItem();
|
||||
|
||||
if (o.getAdmin().contains(securityCtx.getSubject()))
|
||||
return Uni.createFrom().nullItem();
|
||||
|
||||
throw new DForbiddenException();
|
||||
}
|
||||
|
||||
throw new DForbiddenException();
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return {@link fr.titionfire.ffsaf.data.model.CompetitionModel} if securityCtx has edit perm
|
||||
*/
|
||||
public Uni<CompetitionModel> hasTablePerm(SecurityCtx securityCtx, CompetitionModel competitionModel) {
|
||||
return hasTablePerm(securityCtx, Uni.createFrom().item(competitionModel));
|
||||
}
|
||||
|
||||
/**
|
||||
* @return {@link fr.titionfire.ffsaf.data.model.CompetitionModel} if securityCtx has edit perm
|
||||
*/
|
||||
public Uni<CompetitionModel> hasTablePerm(SecurityCtx securityCtx, long id) {
|
||||
return hasTablePerm(securityCtx, competitionRepository.findById(id));
|
||||
}
|
||||
|
||||
/**
|
||||
* @return {@link fr.titionfire.ffsaf.data.model.CompetitionModel} if securityCtx has edit perm
|
||||
*/
|
||||
public Uni<CompetitionModel> hasTablePerm(SecurityCtx securityCtx, Uni<CompetitionModel> in) {
|
||||
return in.call(Unchecked.function(o -> {
|
||||
if (securityCtx.getSubject().equals(o.getOwner()) || securityCtx.roleHas("federation_admin"))
|
||||
return Uni.createFrom().nullItem();
|
||||
|
||||
if (o.getSystem() == CompetitionSystem.SAFCA)
|
||||
return hasSafcaTablePerm(securityCtx, o.getId());
|
||||
|
||||
if (o.getSystem() == CompetitionSystem.INTERNAL) {
|
||||
if (securityCtx.isInClubGroup(o.getClub().getId()) && securityCtx.isClubAdmin())
|
||||
return Uni.createFrom().nullItem();
|
||||
|
||||
if (o.getAdmin().contains(securityCtx.getSubject()))
|
||||
return Uni.createFrom().nullItem();
|
||||
if (o.getTable().contains(securityCtx.getSubject()))
|
||||
return Uni.createFrom().nullItem();
|
||||
|
||||
throw new DForbiddenException();
|
||||
}
|
||||
|
||||
throw new DForbiddenException();
|
||||
})
|
||||
);
|
||||
@@ -236,8 +282,8 @@ public class CompetPermService {
|
||||
Uni.createFrom().nullItem()
|
||||
:
|
||||
getSafcaConfig(id).chain(Unchecked.function(o -> {
|
||||
if (!o.admin().contains(UUID.fromString(securityCtx.getSubject())) && !o.table()
|
||||
.contains(UUID.fromString(securityCtx.getSubject())))
|
||||
if (!o.admin().contains(UUID.fromString(securityCtx.getSubject()))
|
||||
&& !o.table().contains(UUID.fromString(securityCtx.getSubject())))
|
||||
throw new DForbiddenException();
|
||||
return Uni.createFrom().nullItem();
|
||||
}));
|
||||
@@ -253,4 +299,16 @@ public class CompetPermService {
|
||||
return Uni.createFrom().nullItem();
|
||||
}));
|
||||
}
|
||||
|
||||
private Uni<?> hasSafcaTablePerm(SecurityCtx securityCtx, long id) {
|
||||
return securityCtx.roleHas("safca_super_admin") ?
|
||||
Uni.createFrom().nullItem()
|
||||
:
|
||||
getSafcaConfig(id).chain(Unchecked.function(o -> {
|
||||
if (!o.admin().contains(UUID.fromString(securityCtx.getSubject()))
|
||||
&& !o.table().contains(UUID.fromString(securityCtx.getSubject())))
|
||||
throw new DForbiddenException();
|
||||
return Uni.createFrom().nullItem();
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +1,6 @@
|
||||
package fr.titionfire.ffsaf.domain.service;
|
||||
|
||||
import fr.titionfire.ffsaf.data.model.CompetitionModel;
|
||||
import fr.titionfire.ffsaf.data.model.HelloAssoRegisterModel;
|
||||
import fr.titionfire.ffsaf.data.model.MembreModel;
|
||||
import fr.titionfire.ffsaf.data.model.RegisterModel;
|
||||
import fr.titionfire.ffsaf.data.model.*;
|
||||
import fr.titionfire.ffsaf.data.repository.*;
|
||||
import fr.titionfire.ffsaf.net2.ServerCustom;
|
||||
import fr.titionfire.ffsaf.net2.data.SimpleCompet;
|
||||
@@ -16,10 +13,9 @@ import fr.titionfire.ffsaf.rest.data.SimpleCompetData;
|
||||
import fr.titionfire.ffsaf.rest.data.SimpleRegisterComb;
|
||||
import fr.titionfire.ffsaf.rest.exception.DBadRequestException;
|
||||
import fr.titionfire.ffsaf.rest.exception.DForbiddenException;
|
||||
import fr.titionfire.ffsaf.utils.CompetitionSystem;
|
||||
import fr.titionfire.ffsaf.utils.RegisterMode;
|
||||
import fr.titionfire.ffsaf.utils.SecurityCtx;
|
||||
import fr.titionfire.ffsaf.utils.Utils;
|
||||
import fr.titionfire.ffsaf.rest.exception.DNotFoundException;
|
||||
import fr.titionfire.ffsaf.utils.*;
|
||||
import fr.titionfire.ffsaf.ws.send.SRegister;
|
||||
import io.quarkus.cache.Cache;
|
||||
import io.quarkus.cache.CacheName;
|
||||
import io.quarkus.hibernate.reactive.panache.Panache;
|
||||
@@ -64,6 +60,9 @@ public class CompetitionService {
|
||||
@Inject
|
||||
CombRepository combRepository;
|
||||
|
||||
@Inject
|
||||
CompetitionGuestRepository competitionGuestRepository;
|
||||
|
||||
@Inject
|
||||
ServerCustom serverCustom;
|
||||
|
||||
@@ -83,6 +82,9 @@ public class CompetitionService {
|
||||
@Inject
|
||||
Vertx vertx;
|
||||
|
||||
@Inject
|
||||
SRegister sRegister;
|
||||
|
||||
@Inject
|
||||
@CacheName("safca-config")
|
||||
Cache cache;
|
||||
@@ -103,12 +105,13 @@ public class CompetitionService {
|
||||
if (id == 0) {
|
||||
return Uni.createFrom()
|
||||
.item(new CompetitionData(null, "", "", "", "", new Date(), new Date(),
|
||||
CompetitionSystem.NONE, RegisterMode.FREE, new Date(), new Date(), true,
|
||||
CompetitionSystem.INTERNAL, RegisterMode.FREE, new Date(), new Date(), true,
|
||||
null, "", "", null, true, "", "", "", ""));
|
||||
}
|
||||
return permService.hasAdminViewPerm(securityCtx, id)
|
||||
.chain(competitionModel -> Mutiny.fetch(competitionModel.getInsc())
|
||||
.map(insc -> CompetitionData.fromModel(competitionModel).addInsc(insc)))
|
||||
.chain(insc -> Mutiny.fetch(competitionModel.getGuests())
|
||||
.map(guest -> CompetitionData.fromModel(competitionModel).addInsc(insc, guest))))
|
||||
.chain(data ->
|
||||
vertx.getOrCreateContext().executeBlocking(() -> {
|
||||
keycloakService.getUser(UUID.fromString(data.getOwner()))
|
||||
@@ -159,6 +162,14 @@ public class CompetitionService {
|
||||
.map(pouleModels -> pouleModels.stream().map(CompetitionData::fromModel).toList());
|
||||
}
|
||||
|
||||
public Uni<List<CompetitionData>> getAllSystemTable(SecurityCtx securityCtx,
|
||||
CompetitionSystem system) {
|
||||
return repository.list("system = ?1", system)
|
||||
.chain(l -> Uni.join().all(l.stream().map(cm -> permService.hasTablePerm(securityCtx, cm)).toList())
|
||||
.andCollectFailures())
|
||||
.map(l -> l.stream().filter(Objects::nonNull).map(CompetitionData::fromModel).toList());
|
||||
}
|
||||
|
||||
public Uni<CompetitionData> addOrUpdate(SecurityCtx securityCtx, CompetitionData data) {
|
||||
if (data.getId() == null) {
|
||||
return combRepository.find("userId = ?1", securityCtx.getSubject()).firstResult()
|
||||
@@ -175,6 +186,7 @@ public class CompetitionService {
|
||||
model.setSystem(data.getSystem());
|
||||
model.setClub(clubModel);
|
||||
model.setInsc(new ArrayList<>());
|
||||
model.setGuests(new ArrayList<>());
|
||||
model.setUuid(UUID.randomUUID().toString());
|
||||
model.setOwner(securityCtx.getSubject());
|
||||
|
||||
@@ -184,7 +196,7 @@ public class CompetitionService {
|
||||
}).map(CompetitionData::fromModel)
|
||||
.call(c -> (c.getSystem() == CompetitionSystem.SAFCA) ? cacheAccess.invalidate(
|
||||
securityCtx.getSubject()) : Uni.createFrom().nullItem())
|
||||
.call(c -> (c.getSystem() == CompetitionSystem.NONE) ? cacheNoneAccess.invalidate(
|
||||
.call(c -> (c.getSystem() == CompetitionSystem.INTERNAL) ? cacheNoneAccess.invalidate(
|
||||
securityCtx.getSubject()) : Uni.createFrom().nullItem());
|
||||
} else {
|
||||
return permService.hasEditPerm(securityCtx, data.getId())
|
||||
@@ -208,7 +220,7 @@ public class CompetitionService {
|
||||
}).map(CompetitionData::fromModel)
|
||||
.call(c -> (c.getSystem() == CompetitionSystem.SAFCA) ? cacheAccess.invalidate(
|
||||
securityCtx.getSubject()) : Uni.createFrom().nullItem())
|
||||
.call(c -> (c.getSystem() == CompetitionSystem.NONE) ? cacheNoneAccess.invalidate(
|
||||
.call(c -> (c.getSystem() == CompetitionSystem.INTERNAL) ? cacheNoneAccess.invalidate(
|
||||
securityCtx.getSubject()) : Uni.createFrom().nullItem());
|
||||
}
|
||||
}
|
||||
@@ -235,11 +247,18 @@ public class CompetitionService {
|
||||
public Uni<List<SimpleRegisterComb>> getRegister(SecurityCtx securityCtx, Long id, String source) {
|
||||
if ("admin".equals(source))
|
||||
return permService.hasEditPerm(securityCtx, id)
|
||||
.chain(c -> Mutiny.fetch(c.getInsc()))
|
||||
.onItem().transformToMulti(Multi.createFrom()::iterable)
|
||||
.onItem().call(combModel -> Mutiny.fetch(combModel.getMembre().getLicences()))
|
||||
.map(combModel -> SimpleRegisterComb.fromModel(combModel, combModel.getMembre().getLicences()))
|
||||
.collect().asList();
|
||||
.chain(c -> {
|
||||
Uni<List<SimpleRegisterComb>> uni = Mutiny.fetch(c.getInsc())
|
||||
.onItem().transformToMulti(Multi.createFrom()::iterable)
|
||||
.onItem().call(combModel -> Mutiny.fetch(combModel.getMembre().getLicences()))
|
||||
.map(cm -> SimpleRegisterComb.fromModel(cm, cm.getMembre().getLicences()))
|
||||
.collect().asList();
|
||||
return uni
|
||||
.call(l -> Mutiny.fetch(c.getGuests())
|
||||
.map(guest -> guest.stream().map(SimpleRegisterComb::fromModel).toList())
|
||||
.invoke(l::addAll));
|
||||
});
|
||||
|
||||
if ("club".equals(source))
|
||||
return Uni.createFrom().nullItem()
|
||||
.invoke(Unchecked.consumer(__ -> {
|
||||
@@ -262,17 +281,44 @@ public class CompetitionService {
|
||||
public Uni<SimpleRegisterComb> addRegisterComb(SecurityCtx securityCtx, Long id, RegisterRequestData data,
|
||||
String source) {
|
||||
if ("admin".equals(source))
|
||||
return permService.hasEditPerm(securityCtx, id)
|
||||
.chain(c -> findComb(data.getLicence(), data.getFname(), data.getLname())
|
||||
.call(combModel -> {
|
||||
if (c.getBanMembre() == null)
|
||||
c.setBanMembre(new ArrayList<>());
|
||||
c.getBanMembre().remove(combModel.getId());
|
||||
return Panache.withTransaction(() -> repository.persist(c));
|
||||
})
|
||||
.chain(combModel -> updateRegister(data, c, combModel, true)))
|
||||
.chain(r -> Mutiny.fetch(r.getMembre().getLicences())
|
||||
.map(licences -> SimpleRegisterComb.fromModel(r, licences)));
|
||||
if (data.getLicence() != -1) { // not a guest
|
||||
return permService.hasEditPerm(securityCtx, id)
|
||||
.chain(c -> findComb(data.getLicence(), data.getFname(), data.getLname())
|
||||
.call(combModel -> Mutiny.fetch(combModel.getLicences()))
|
||||
.call(combModel -> {
|
||||
if (c.getBanMembre() == null)
|
||||
c.setBanMembre(new ArrayList<>());
|
||||
c.getBanMembre().remove(combModel.getId());
|
||||
return Panache.withTransaction(() -> repository.persist(c));
|
||||
})
|
||||
.chain(combModel -> updateRegister(data, c, combModel, true)))
|
||||
.map(r -> SimpleRegisterComb.fromModel(r, r.getMembre().getLicences()));
|
||||
} else {
|
||||
return permService.hasEditPerm(securityCtx, id)
|
||||
.chain(c -> competitionGuestRepository.findById(data.getId() * -1)
|
||||
.map(g -> {
|
||||
if (g != null)
|
||||
return g;
|
||||
CompetitionGuestModel model = new CompetitionGuestModel();
|
||||
model.setCompetition(c);
|
||||
return model;
|
||||
}))
|
||||
.chain(model -> {
|
||||
model.setFname(data.getFname());
|
||||
model.setLname(data.getLname());
|
||||
model.setGenre(data.getGenre());
|
||||
model.setClub(data.getClub());
|
||||
model.setCountry(data.getCountry());
|
||||
model.setWeight(data.getWeight());
|
||||
model.setCategorie(data.getCategorie());
|
||||
|
||||
return Panache.withTransaction(() -> competitionGuestRepository.persist(model))
|
||||
.call(r -> model.getCompetition().getSystem() == CompetitionSystem.INTERNAL ?
|
||||
sRegister.sendRegister(model.getCompetition().getUuid(),
|
||||
r) : Uni.createFrom().voidItem());
|
||||
})
|
||||
.map(SimpleRegisterComb::fromModel);
|
||||
}
|
||||
if ("club".equals(source))
|
||||
return repository.findById(id)
|
||||
.invoke(Unchecked.consumer(cm -> {
|
||||
@@ -283,6 +329,7 @@ public class CompetitionService {
|
||||
throw new DBadRequestException("Inscription fermée");
|
||||
}))
|
||||
.chain(c -> findComb(data.getLicence(), data.getFname(), data.getLname())
|
||||
.call(combModel -> Mutiny.fetch(combModel.getLicences()))
|
||||
.invoke(Unchecked.consumer(model -> {
|
||||
if (!securityCtx.isInClubGroup(model.getClub().getId()))
|
||||
throw new DForbiddenException();
|
||||
@@ -291,8 +338,7 @@ public class CompetitionService {
|
||||
"Vous n'avez pas le droit d'inscrire ce membre (par décision de l'administrateur de la compétition)");
|
||||
}))
|
||||
.chain(combModel -> updateRegister(data, c, combModel, false)))
|
||||
.chain(r -> Mutiny.fetch(r.getMembre().getLicences())
|
||||
.map(licences -> SimpleRegisterComb.fromModel(r, licences)));
|
||||
.map(r -> SimpleRegisterComb.fromModel(r, r.getMembre().getLicences()));
|
||||
|
||||
return repository.findById(id)
|
||||
.invoke(Unchecked.consumer(cm -> {
|
||||
@@ -347,15 +393,18 @@ public class CompetitionService {
|
||||
SReqRegister.sendIfNeed(serverCustom.clients,
|
||||
new CompetitionData.SimpleRegister(r.getMembre().getId(),
|
||||
r.getOverCategory(), r.getWeight(), r.getCategorie(),
|
||||
(r.getClub() == null) ? null : r.getClub().getId()), c.getId());
|
||||
(r.getClub() == null) ? null : r.getClub().getId(),
|
||||
(r.getClub() == null) ? null : r.getClub().getName()), c.getId());
|
||||
}
|
||||
return r;
|
||||
}))
|
||||
.chain(r -> Panache.withTransaction(() -> registerRepository.persist(r)));
|
||||
.chain(r -> Panache.withTransaction(() -> registerRepository.persist(r)))
|
||||
.call(r -> c.getSystem() == CompetitionSystem.INTERNAL ?
|
||||
sRegister.sendRegister(c.getUuid(), r) : Uni.createFrom().voidItem());
|
||||
}
|
||||
|
||||
private Uni<MembreModel> findComb(Long licence, String fname, String lname) {
|
||||
if (licence != null && licence != 0) {
|
||||
if (licence != null && licence > 0) {
|
||||
return combRepository.find("licence = ?1", licence).firstResult()
|
||||
.invoke(Unchecked.consumer(combModel -> {
|
||||
if (combModel == null)
|
||||
@@ -398,30 +447,45 @@ public class CompetitionService {
|
||||
if (new Date().before(cm.getStartRegister()) || new Date().after(cm.getEndRegister()))
|
||||
throw new DBadRequestException("Inscription fermée");
|
||||
}))
|
||||
.call(cm -> membreService.getByAccountId(securityCtx.getSubject())
|
||||
.call(cm -> membreService.getById(combId)
|
||||
.invoke(Unchecked.consumer(model -> {
|
||||
if (model == null)
|
||||
throw new DNotFoundException("Membre " + combId + " n'existe pas");
|
||||
if (!securityCtx.isInClubGroup(model.getClub().getId()))
|
||||
throw new DForbiddenException();
|
||||
})))
|
||||
.chain(c -> deleteRegister(combId, c, false));
|
||||
|
||||
return repository.findById(id)
|
||||
.invoke(Unchecked.consumer(cm -> {
|
||||
if (cm.getRegisterMode() != RegisterMode.FREE)
|
||||
throw new DForbiddenException();
|
||||
if (new Date().before(cm.getStartRegister()) || new Date().after(cm.getEndRegister()))
|
||||
throw new DBadRequestException("Inscription fermée");
|
||||
}))
|
||||
.call(cm -> membreService.getByAccountId(securityCtx.getSubject())
|
||||
.invoke(Unchecked.consumer(model -> {
|
||||
if (cm.getRegisterMode() != RegisterMode.FREE || !Objects.equals(model.getId(), combId))
|
||||
throw new DForbiddenException();
|
||||
if (new Date().before(cm.getStartRegister()) || new Date().after(cm.getEndRegister()))
|
||||
throw new DBadRequestException("Inscription fermée");
|
||||
})))
|
||||
.chain(c -> deleteRegister(combId, c, false));
|
||||
}
|
||||
|
||||
private Uni<Void> deleteRegister(Long combId, CompetitionModel c, boolean admin) {
|
||||
if (admin && combId < 0) {
|
||||
return competitionGuestRepository.find("competition = ?1 AND id = ?2", c, combId * -1).firstResult()
|
||||
.onFailure().transform(t -> new DBadRequestException("Combattant non inscrit"))
|
||||
.call(Unchecked.function(
|
||||
model -> Panache.withTransaction(() -> competitionGuestRepository.delete(model))
|
||||
.call(r -> c.getSystem() == CompetitionSystem.INTERNAL ?
|
||||
sRegister.sendRegisterRemove(c.getUuid(), combId) : Uni.createFrom()
|
||||
.voidItem())))
|
||||
.replaceWithVoid();
|
||||
}
|
||||
return registerRepository.find("competition = ?1 AND membre.id = ?2", c, combId).firstResult()
|
||||
.onFailure().transform(t -> new DBadRequestException("Combattant non inscrit"))
|
||||
.call(Unchecked.function(registerModel -> {
|
||||
if (!admin && registerModel.isLockEdit())
|
||||
throw new DForbiddenException("Modification bloquée par l'administrateur de la compétition");
|
||||
return Panache.withTransaction(() -> registerRepository.delete(registerModel));
|
||||
return Panache.withTransaction(() -> registerRepository.delete(registerModel))
|
||||
.call(r -> c.getSystem() == CompetitionSystem.INTERNAL ?
|
||||
sRegister.sendRegisterRemove(c.getUuid(), combId) : Uni.createFrom().voidItem());
|
||||
}))
|
||||
.replaceWithVoid();
|
||||
}
|
||||
@@ -440,6 +504,10 @@ public class CompetitionService {
|
||||
.andCollectFailures()))
|
||||
.call(competitionModel -> Panache.withTransaction(
|
||||
() -> categoryRepository.delete("compet = ?1", competitionModel)))
|
||||
.call(competitionModel -> Panache.withTransaction(
|
||||
() -> registerRepository.delete("competition = ?1", competitionModel)))
|
||||
.call(competitionModel -> Panache.withTransaction(
|
||||
() -> competitionGuestRepository.delete("competition = ?1", competitionModel)))
|
||||
.chain(model -> Panache.withTransaction(() -> repository.delete("id", model.getId())))
|
||||
.invoke(o -> SReqCompet.rmCompet(serverCustom.clients, id))
|
||||
.call(__ -> cache.invalidate(id));
|
||||
@@ -528,8 +596,13 @@ public class CompetitionService {
|
||||
continue;
|
||||
|
||||
uni = uni.call(__ -> Panache.withTransaction(
|
||||
() -> registerRepository.delete("competition = ?1 AND membre = ?2",
|
||||
reg.getCompetition(), reg.getMembre())));
|
||||
() -> registerRepository.delete("competition = ?1 AND membre = ?2",
|
||||
reg.getCompetition(), reg.getMembre())))
|
||||
.call(r -> reg.getCompetition().getSystem() == CompetitionSystem.INTERNAL ?
|
||||
sRegister.sendRegisterRemove(reg.getCompetition().getUuid(),
|
||||
reg.getMembre().getId()) : Uni.createFrom().voidItem()).onFailure()
|
||||
.recoverWithNull()
|
||||
;
|
||||
}
|
||||
|
||||
return uni;
|
||||
@@ -541,7 +614,8 @@ public class CompetitionService {
|
||||
public Uni<Response> registerHelloAsso(NotificationData data) {
|
||||
String organizationSlug = data.getOrganizationSlug();
|
||||
String formSlug = data.getFormSlug();
|
||||
RegisterRequestData req = new RegisterRequestData(null, "", "", null, 0, false);
|
||||
RegisterRequestData req = new RegisterRequestData(null, "", "", null, 0, false, null, Categorie.CADET, Genre.NA,
|
||||
null, "fr");
|
||||
|
||||
return repository.find("data1 = ?1 AND data2 = ?2", organizationSlug, formSlug).firstResult()
|
||||
.onFailure().recoverWithNull()
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
package fr.titionfire.ffsaf.domain.service;
|
||||
|
||||
import fr.titionfire.ffsaf.data.model.CompetitionGuestModel;
|
||||
import fr.titionfire.ffsaf.data.model.MatchModel;
|
||||
import fr.titionfire.ffsaf.data.repository.CombRepository;
|
||||
import fr.titionfire.ffsaf.data.repository.MatchRepository;
|
||||
import fr.titionfire.ffsaf.data.repository.CategoryRepository;
|
||||
import fr.titionfire.ffsaf.data.repository.CombRepository;
|
||||
import fr.titionfire.ffsaf.data.repository.CompetitionGuestRepository;
|
||||
import fr.titionfire.ffsaf.data.repository.MatchRepository;
|
||||
import fr.titionfire.ffsaf.rest.data.MatchData;
|
||||
import fr.titionfire.ffsaf.rest.exception.DNotFoundException;
|
||||
import fr.titionfire.ffsaf.utils.CompetitionSystem;
|
||||
@@ -33,6 +35,9 @@ public class MatchService {
|
||||
@Inject
|
||||
CompetPermService permService;
|
||||
|
||||
@Inject
|
||||
CompetitionGuestRepository competitionGuestRepository;
|
||||
|
||||
public Uni<MatchData> getByIdAdmin(SecurityCtx securityCtx, CompetitionSystem system, Long id) {
|
||||
return repository.find("systemId = ?1 AND system = ?2", id, system).firstResult()
|
||||
.onItem().ifNull().failWith(() -> new DNotFoundException("Match not found"))
|
||||
@@ -75,8 +80,6 @@ public class MatchService {
|
||||
}
|
||||
)
|
||||
.chain(o -> {
|
||||
o.setC1_str(data.getC1_str());
|
||||
o.setC2_str(data.getC2_str());
|
||||
o.setCategory_ord(data.getCategory_ord());
|
||||
o.getScores().clear();
|
||||
o.getScores().addAll(data.getScores());
|
||||
@@ -88,6 +91,20 @@ public class MatchService {
|
||||
.chain(() -> (data.getC1_id() == null) ?
|
||||
Uni.createFrom().nullItem() : combRepository.findById(data.getC2_id()))
|
||||
.invoke(o::setC2_id)
|
||||
.chain(() -> (data.getC1_str() == null) ?
|
||||
Uni.createFrom()
|
||||
.item((CompetitionGuestModel) null) : competitionGuestRepository.find(
|
||||
"fname = ?1 AND lname = ?2",
|
||||
data.getC1_str().substring(0, data.getC1_str().indexOf(" ")),
|
||||
data.getC1_str().substring(data.getC1_str().indexOf(" ") + 1)).firstResult())
|
||||
.invoke(o::setC1_guest)
|
||||
.chain(() -> (data.getC2_str() == null) ?
|
||||
Uni.createFrom()
|
||||
.item((CompetitionGuestModel) null) : competitionGuestRepository.find(
|
||||
"fname = ?1 AND lname = ?2",
|
||||
data.getC2_str().substring(0, data.getC2_str().indexOf(" ")),
|
||||
data.getC2_str().substring(data.getC2_str().indexOf(" ") + 1)).firstResult())
|
||||
.invoke(o::setC2_guest)
|
||||
.chain(() -> Panache.withTransaction(() -> repository.persist(o)));
|
||||
})
|
||||
.map(MatchData::fromModel);
|
||||
|
||||
@@ -0,0 +1,400 @@
|
||||
package fr.titionfire.ffsaf.domain.service;
|
||||
|
||||
import fr.titionfire.ffsaf.data.model.*;
|
||||
import fr.titionfire.ffsaf.data.repository.CategoryRepository;
|
||||
import fr.titionfire.ffsaf.data.repository.CompetitionRepository;
|
||||
import fr.titionfire.ffsaf.data.repository.MatchRepository;
|
||||
import fr.titionfire.ffsaf.data.repository.RegisterRepository;
|
||||
import fr.titionfire.ffsaf.rest.data.ResultCategoryData;
|
||||
import fr.titionfire.ffsaf.rest.exception.DForbiddenException;
|
||||
import fr.titionfire.ffsaf.utils.*;
|
||||
import io.quarkus.hibernate.reactive.panache.common.WithSession;
|
||||
import io.quarkus.runtime.annotations.RegisterForReflection;
|
||||
import io.smallrye.mutiny.Multi;
|
||||
import io.smallrye.mutiny.Uni;
|
||||
import io.smallrye.mutiny.unchecked.Unchecked;
|
||||
import jakarta.enterprise.context.ApplicationScoped;
|
||||
import jakarta.inject.Inject;
|
||||
import lombok.Builder;
|
||||
import org.hibernate.reactive.mutiny.Mutiny;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
@WithSession
|
||||
@ApplicationScoped
|
||||
public class ResultService {
|
||||
|
||||
@Inject
|
||||
CompetitionRepository compRepository;
|
||||
|
||||
@Inject
|
||||
RegisterRepository registerRepository;
|
||||
|
||||
@Inject
|
||||
MembreService membreService;
|
||||
|
||||
@Inject
|
||||
CategoryRepository categoryRepository;
|
||||
|
||||
@Inject
|
||||
MatchRepository matchRepository;
|
||||
|
||||
private static final ResourceBundle BUNDLE = ResourceBundle.getBundle("lang.String");
|
||||
|
||||
public Uni<List<Object[]>> getList(SecurityCtx securityCtx) {
|
||||
return membreService.getByAccountId(securityCtx.getSubject())
|
||||
.chain(m -> registerRepository.list("membre = ?1", m))
|
||||
.onItem().transformToMulti(Multi.createFrom()::iterable)
|
||||
.onItem().call(r -> Mutiny.fetch(r.getCompetition()))
|
||||
.onItem().transform(r -> new Object[]{r.getCompetition().getUuid(), r.getCompetition().getName(),
|
||||
r.getCompetition().getDate()})
|
||||
.collect().asList();
|
||||
}
|
||||
|
||||
public Uni<List<ResultCategoryData>> getCategory(String uuid, SecurityCtx securityCtx) {
|
||||
return hasAccess(uuid, securityCtx)
|
||||
.chain(m -> categoryRepository.list("compet.uuid = ?1", uuid)
|
||||
.chain(cats -> matchRepository.list("(c1_id = ?1 OR c2_id = ?1 OR True) AND category IN ?2", //TODO rm OR True
|
||||
m.getMembre(), cats)))
|
||||
.map(matchModels -> {
|
||||
HashMap<Long, List<MatchModel>> map = new HashMap<>();
|
||||
for (MatchModel matchModel : matchModels) {
|
||||
if (!map.containsKey(matchModel.getCategory().getId()))
|
||||
map.put(matchModel.getCategory().getId(), new ArrayList<>());
|
||||
map.get(matchModel.getCategory().getId()).add(matchModel);
|
||||
}
|
||||
|
||||
return map.values();
|
||||
})
|
||||
.onItem()
|
||||
.transformToMulti(Multi.createFrom()::iterable)
|
||||
.onItem().call(list -> Mutiny.fetch(list.get(0).getCategory().getTree()))
|
||||
.onItem().transform(this::getData)
|
||||
.collect().asList();
|
||||
|
||||
}
|
||||
|
||||
private ResultCategoryData getData(List<MatchModel> matchModels) {
|
||||
ResultCategoryData out = new ResultCategoryData();
|
||||
|
||||
CategoryModel categoryModel = matchModels.get(0).getCategory();
|
||||
out.setName(categoryModel.getName());
|
||||
out.setType(categoryModel.getType());
|
||||
|
||||
getArray2(matchModels, out);
|
||||
getTree(categoryModel.getTree(), out);
|
||||
return out;
|
||||
}
|
||||
|
||||
private void getArray2(List<MatchModel> matchModels_, ResultCategoryData out) {
|
||||
List<MatchModel> matchModels = matchModels_.stream().filter(o -> o.getCategory_ord() >= 0).toList();
|
||||
|
||||
HashMap<Character, List<MatchModel>> matchMap = new HashMap<>();
|
||||
for (MatchModel model : matchModels) {
|
||||
char g = model.getPoule();
|
||||
if (!matchMap.containsKey(g))
|
||||
matchMap.put(g, new ArrayList<>());
|
||||
matchMap.get(g).add(model);
|
||||
}
|
||||
|
||||
matchMap.forEach((c, matchEntities) -> {
|
||||
List<ResultCategoryData.PouleArrayData> matchs = matchEntities.stream()
|
||||
.sorted(Comparator.comparing(MatchModel::getCategory_ord))
|
||||
.map(ResultCategoryData.PouleArrayData::fromModel)
|
||||
.toList();
|
||||
|
||||
List<ResultCategoryData.RankArray> rankArray = matchEntities.stream()
|
||||
.flatMap(m -> Stream.of(m.getC1Name(), m.getC2Name()))
|
||||
.distinct()
|
||||
.map(combName -> {
|
||||
AtomicInteger w = new AtomicInteger(0);
|
||||
AtomicInteger pointMake = new AtomicInteger(0);
|
||||
AtomicInteger pointTake = new AtomicInteger(0);
|
||||
|
||||
matchEntities.stream()
|
||||
.filter(m -> m.isEnd() && (m.getC1Name().equals(combName) || m.getC2Name()
|
||||
.equals(combName)))
|
||||
.forEach(matchModel -> {
|
||||
int win = matchModel.win();
|
||||
if ((matchModel.getC1Name()
|
||||
.equals(combName) && win > 0) || matchModel.getC2Name()
|
||||
.equals(combName) && win < 0)
|
||||
w.getAndIncrement();
|
||||
|
||||
for (ScoreEmbeddable score : matchModel.getScores()) {
|
||||
if (score.getS1() <= -900 || score.getS2() <= -900)
|
||||
continue;
|
||||
if (matchModel.getC1Name().equals(combName)) {
|
||||
pointMake.addAndGet(score.getS1());
|
||||
pointTake.addAndGet(score.getS2());
|
||||
} else {
|
||||
pointMake.addAndGet(score.getS2());
|
||||
pointTake.addAndGet(score.getS1());
|
||||
}
|
||||
}
|
||||
});
|
||||
float pointRate = (pointTake.get() == 0) ? pointMake.get() : (float) pointMake.get() / pointTake.get();
|
||||
|
||||
return new ResultCategoryData.RankArray(0, combName, w.get(),
|
||||
pointMake.get(), pointTake.get(), pointRate);
|
||||
})
|
||||
.sorted(Comparator
|
||||
.comparing(ResultCategoryData.RankArray::getWin)
|
||||
.thenComparing(ResultCategoryData.RankArray::getPointRate).reversed())
|
||||
.toList();
|
||||
out.getMatchs().put(c, matchs);
|
||||
|
||||
int lastWin = -1;
|
||||
float pointRate = 0;
|
||||
int rank = 0;
|
||||
for (ResultCategoryData.RankArray rankArray1 : rankArray) {
|
||||
if (rankArray1.getWin() != lastWin || pointRate != rankArray1.getPointRate()) {
|
||||
lastWin = rankArray1.getWin();
|
||||
pointRate = rankArray1.getPointRate();
|
||||
rank++;
|
||||
}
|
||||
rankArray1.setRank(rank);
|
||||
}
|
||||
out.getRankArray().put(c, rankArray);
|
||||
});
|
||||
}
|
||||
|
||||
private static void convertTree(TreeModel src, TreeNode<ResultCategoryData.TreeData> dst) {
|
||||
dst.setData(ResultCategoryData.TreeData.from(src.getMatch()));
|
||||
if (src.getLeft() != null) {
|
||||
dst.setLeft(new TreeNode<>());
|
||||
convertTree(src.getLeft(), dst.getLeft());
|
||||
}
|
||||
if (src.getRight() != null) {
|
||||
dst.setRight(new TreeNode<>());
|
||||
convertTree(src.getRight(), dst.getRight());
|
||||
}
|
||||
}
|
||||
|
||||
private void getTree(List<TreeModel> treeModels, ResultCategoryData out) {
|
||||
ArrayList<TreeNode<ResultCategoryData.TreeData>> trees = new ArrayList<>();
|
||||
treeModels.stream().filter(t -> t.getLevel() != 0).forEach(treeModel -> {
|
||||
TreeNode<ResultCategoryData.TreeData> root = new TreeNode<>();
|
||||
convertTree(treeModel, root);
|
||||
trees.add(root);
|
||||
});
|
||||
out.setTrees(trees);
|
||||
}
|
||||
|
||||
public Uni<CombsArrayData> getAllCombArray(String uuid, SecurityCtx securityCtx) {
|
||||
return hasAccess(uuid, securityCtx)
|
||||
.chain(cm_register -> registerRepository.list("competition.uuid = ?1", uuid)
|
||||
.chain(registers -> matchRepository.list("category.compet.uuid = ?1", uuid)
|
||||
.map(matchModels -> new Pair<>(registers, matchModels)))
|
||||
.map(pair -> {
|
||||
List<RegisterModel> registers = pair.getKey();
|
||||
List<MatchModel> matchModels = pair.getValue();
|
||||
|
||||
CombsArrayData.CombsArrayDataBuilder builder = CombsArrayData.builder();
|
||||
|
||||
List<CombsArrayData.CombsData> combs = matchModels.stream()
|
||||
.flatMap(m -> Stream.of(m.getC1Name(), m.getC2Name()))
|
||||
.filter(Objects::nonNull)
|
||||
.distinct()
|
||||
.map(combName -> {
|
||||
var builder2 = CombsArrayData.CombsData.builder();
|
||||
AtomicInteger w = new AtomicInteger(0);
|
||||
AtomicInteger l = new AtomicInteger(0);
|
||||
AtomicInteger pointMake = new AtomicInteger();
|
||||
AtomicInteger pointTake = new AtomicInteger();
|
||||
|
||||
matchModels.stream()
|
||||
.filter(m -> m.isEnd() && (m.getC1Name().equals(combName)
|
||||
|| m.getC2Name().equals(combName)))
|
||||
.forEach(matchModel -> {
|
||||
int win = matchModel.win();
|
||||
if ((combName.equals(matchModel.getC1Name()) && win > 0) ||
|
||||
combName.equals(matchModel.getC2Name()) && win < 0) {
|
||||
w.getAndIncrement();
|
||||
} else {
|
||||
l.getAndIncrement();
|
||||
}
|
||||
|
||||
matchModel.getScores().stream()
|
||||
.filter(s -> s.getS1() > -900 && s.getS2() > -900)
|
||||
.forEach(score -> {
|
||||
if (combName.equals(matchModel.getC1Name())) {
|
||||
pointMake.addAndGet(score.getS1());
|
||||
pointTake.addAndGet(score.getS2());
|
||||
} else {
|
||||
pointMake.addAndGet(score.getS2());
|
||||
pointTake.addAndGet(score.getS1());
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
Categorie categorie = null;
|
||||
ClubModel club = null;
|
||||
|
||||
Optional<RegisterModel> register = registers.stream()
|
||||
.filter(r -> r.getName().equals(combName)).findFirst();
|
||||
if (register.isPresent()) {
|
||||
categorie = register.get().getCategorie();
|
||||
club = register.get().getClub2();
|
||||
}
|
||||
|
||||
builder2.cat((categorie == null) ? "---" : categorie.getName(BUNDLE));
|
||||
builder2.name(combName);
|
||||
builder2.w(w.get());
|
||||
builder2.l(l.get());
|
||||
builder2.ratioVictoire((l.get() == 0) ? w.get() : (float) w.get() / l.get());
|
||||
builder2.club((club == null) ? BUNDLE.getString("no.licence") : club.getName());
|
||||
builder2.pointMake(pointMake.get());
|
||||
builder2.pointTake(pointTake.get());
|
||||
builder2.ratioPoint(
|
||||
(pointTake.get() == 0) ? pointMake.get() : (float) pointMake.get() / pointTake.get());
|
||||
|
||||
return builder2.build();
|
||||
})
|
||||
.sorted(Comparator.comparing(CombsArrayData.CombsData::name))
|
||||
.toList();
|
||||
|
||||
builder.nb_insc(combs.size());
|
||||
builder.tt_match((int) matchModels.stream().filter(MatchModel::isEnd).count());
|
||||
builder.point(combs.stream().mapToInt(CombsArrayData.CombsData::pointMake).sum());
|
||||
builder.combs(combs);
|
||||
|
||||
return builder.build();
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@Builder
|
||||
@RegisterForReflection
|
||||
public static record CombsArrayData(int nb_insc, int tt_match, long point, List<CombsData> combs) {
|
||||
@Builder
|
||||
@RegisterForReflection
|
||||
public static record CombsData(String cat, String club, String name, int w, int l, float ratioVictoire,
|
||||
float ratioPoint, int pointMake, int pointTake) {
|
||||
}
|
||||
}
|
||||
|
||||
public Uni<ClubArrayData> getClubArray(String uuid, SecurityCtx securityCtx) {
|
||||
ClubArrayData.ClubArrayDataBuilder builder = ClubArrayData.builder();
|
||||
|
||||
return hasAccess(uuid, securityCtx)
|
||||
.invoke(cm_register -> builder.name(cm_register.getClub2().getName()))
|
||||
.chain(cm_register -> registerRepository.list("competition.uuid = ?1 AND membre.club = ?2", uuid,
|
||||
cm_register.getClub2())
|
||||
.chain(registers -> matchRepository.list("category.compet.uuid = ?1", uuid)
|
||||
.map(matchModels -> new Pair<>(registers, matchModels)))
|
||||
.map(pair -> {
|
||||
List<RegisterModel> registers = pair.getKey();
|
||||
List<MatchModel> matchModels = pair.getValue();
|
||||
|
||||
builder.nb_insc(registers.size());
|
||||
|
||||
AtomicInteger tt_win = new AtomicInteger(0);
|
||||
AtomicInteger tt_match = new AtomicInteger(0);
|
||||
|
||||
List<ClubArrayData.CombData> combData = registers.stream()
|
||||
.map(register -> {
|
||||
|
||||
var builder2 = ClubArrayData.CombData.builder();
|
||||
AtomicInteger w = new AtomicInteger(0);
|
||||
AtomicInteger l = new AtomicInteger(0);
|
||||
AtomicInteger pointMake = new AtomicInteger();
|
||||
AtomicInteger pointTake = new AtomicInteger();
|
||||
|
||||
matchModels.stream()
|
||||
.filter(m -> m.isEnd() && (register.getMembre().equals(m.getC1_id())
|
||||
|| register.getMembre().equals(m.getC2_id())))
|
||||
.forEach(matchModel -> {
|
||||
int win = matchModel.win();
|
||||
if ((register.getMembre()
|
||||
.equals(matchModel.getC1_id()) && win > 0) ||
|
||||
register.getMembre()
|
||||
.equals(matchModel.getC2_id()) && win < 0) {
|
||||
w.getAndIncrement();
|
||||
} else {
|
||||
l.getAndIncrement();
|
||||
}
|
||||
|
||||
matchModel.getScores().stream()
|
||||
.filter(s -> s.getS1() > -900 && s.getS2() > -900)
|
||||
.forEach(score -> {
|
||||
if (register.getMembre()
|
||||
.equals(matchModel.getC1_id())) {
|
||||
pointMake.addAndGet(score.getS1());
|
||||
pointTake.addAndGet(score.getS2());
|
||||
} else {
|
||||
pointMake.addAndGet(score.getS2());
|
||||
pointTake.addAndGet(score.getS1());
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
Categorie categorie = register.getCategorie();
|
||||
if (categorie == null)
|
||||
categorie = register.getMembre().getCategorie();
|
||||
|
||||
builder2.cat((categorie == null) ? "---" : categorie.getName(BUNDLE));
|
||||
builder2.name(register.getName());
|
||||
builder2.w(w.get());
|
||||
builder2.l(l.get());
|
||||
builder2.ratioVictoire((l.get() == 0) ? w.get() : (float) w.get() / l.get());
|
||||
builder2.pointMake(pointMake.get());
|
||||
builder2.pointTake(pointTake.get());
|
||||
builder2.ratioPoint(
|
||||
(pointTake.get() == 0) ? pointMake.get() : (float) pointMake.get() / pointTake.get());
|
||||
|
||||
tt_win.addAndGet(w.get());
|
||||
tt_match.addAndGet(w.get() + l.get());
|
||||
|
||||
return builder2.build();
|
||||
})
|
||||
.sorted(Comparator.comparing(ClubArrayData.CombData::name))
|
||||
.toList();
|
||||
|
||||
builder.nb_match(tt_match.get());
|
||||
builder.match_w(tt_win.get());
|
||||
builder.ratioVictoire((float) combData.stream().filter(c -> c.l + c.w != 0)
|
||||
.mapToDouble(ClubArrayData.CombData::ratioVictoire).average().orElse(0L));
|
||||
builder.pointMake(combData.stream().mapToInt(ClubArrayData.CombData::pointMake).sum());
|
||||
builder.pointTake(combData.stream().mapToInt(ClubArrayData.CombData::pointTake).sum());
|
||||
builder.ratioPoint((float) combData.stream().filter(c -> c.l + c.w != 0)
|
||||
.mapToDouble(ClubArrayData.CombData::ratioPoint).average().orElse(0L));
|
||||
builder.combs(combData);
|
||||
|
||||
return builder.build();
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
@Builder
|
||||
@RegisterForReflection
|
||||
public static record ClubArrayData(String name, int nb_insc, int nb_match, int match_w, float ratioVictoire,
|
||||
float ratioPoint, int pointMake, int pointTake, List<CombData> combs) {
|
||||
@Builder
|
||||
@RegisterForReflection
|
||||
public static record CombData(String cat, String name, int w, int l, float ratioVictoire,
|
||||
float ratioPoint, int pointMake, int pointTake) {
|
||||
}
|
||||
}
|
||||
|
||||
private Uni<RegisterModel> hasAccess(String uuid, SecurityCtx securityCtx) {
|
||||
return registerRepository.find("membre.userId = ?1 AND competition.uuid = ?2", securityCtx.getSubject(), uuid)
|
||||
.firstResult()
|
||||
.invoke(Unchecked.consumer(o -> {
|
||||
if (o == null)
|
||||
throw new DForbiddenException("Access denied");
|
||||
}));
|
||||
}
|
||||
|
||||
private Uni<RegisterModel> hasAccess(Long compId, SecurityCtx securityCtx) {
|
||||
return registerRepository.find("membre.userId = ?1 AND competition.id = ?2", securityCtx.getSubject(), compId)
|
||||
.firstResult()
|
||||
.invoke(Unchecked.consumer(o -> {
|
||||
if (o == null)
|
||||
throw new DForbiddenException("Access denied");
|
||||
}));
|
||||
}
|
||||
}
|
||||
@@ -186,6 +186,6 @@ public class AffiliationRequestEndpoints {
|
||||
public Uni<Response> getStatus(
|
||||
@Parameter(description = "L'identifiant de la demande d'affiliation") @PathParam("id") long id) throws URISyntaxException {
|
||||
return Utils.getMediaFile(id, media, "aff_request/status", "affiliation_request_" + id,
|
||||
Uni.createFrom().nullItem());
|
||||
Uni.createFrom().nullItem(), false);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -335,7 +335,7 @@ public class ClubEndpoints {
|
||||
@Parameter(description = "Identifiant long (clubId) de club") @PathParam("clubId") String clubId) {
|
||||
return clubService.getByClubId(clubId).chain(Unchecked.function(clubModel -> {
|
||||
try {
|
||||
return Utils.getMediaFile((clubModel != null) ? clubModel.getId() : -1, media, "ppClub",
|
||||
return Utils.getMediaFileNoDefault((clubModel != null) ? clubModel.getId() : -1, media, "ppClub",
|
||||
Uni.createFrom().nullItem());
|
||||
} catch (URISyntaxException e) {
|
||||
throw new InternalError();
|
||||
@@ -358,7 +358,7 @@ public class ClubEndpoints {
|
||||
return clubService.getById(id).onItem().invoke(checkPerm).chain(Unchecked.function(clubModel -> {
|
||||
try {
|
||||
return Utils.getMediaFile(clubModel.getId(), media, "clubStatus",
|
||||
"statue-" + clubModel.getName(), Uni.createFrom().nullItem());
|
||||
"statue-" + clubModel.getName(), Uni.createFrom().nullItem(), false);
|
||||
} catch (URISyntaxException e) {
|
||||
throw new InternalError();
|
||||
}
|
||||
|
||||
@@ -47,4 +47,12 @@ public class CompetitionAdminEndpoints {
|
||||
public Uni<List<CompetitionData>> getAllSystemAdmin(@PathParam("system") CompetitionSystem system) {
|
||||
return service.getAllSystemAdmin(securityCtx, system);
|
||||
}
|
||||
|
||||
@GET
|
||||
@Path("all/{system}/table")
|
||||
@Authenticated
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
public Uni<List<CompetitionData>> getAllSystemTable(@PathParam("system") CompetitionSystem system) {
|
||||
return service.getAllSystemTable(securityCtx, system);
|
||||
}
|
||||
}
|
||||
|
||||
48
src/main/java/fr/titionfire/ffsaf/rest/ResultEndpoints.java
Normal file
48
src/main/java/fr/titionfire/ffsaf/rest/ResultEndpoints.java
Normal file
@@ -0,0 +1,48 @@
|
||||
package fr.titionfire.ffsaf.rest;
|
||||
|
||||
import fr.titionfire.ffsaf.domain.service.ResultService;
|
||||
import fr.titionfire.ffsaf.rest.data.ResultCategoryData;
|
||||
import fr.titionfire.ffsaf.utils.SecurityCtx;
|
||||
import io.quarkus.security.Authenticated;
|
||||
import io.smallrye.mutiny.Uni;
|
||||
import jakarta.inject.Inject;
|
||||
import jakarta.ws.rs.GET;
|
||||
import jakarta.ws.rs.Path;
|
||||
import jakarta.ws.rs.PathParam;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Authenticated
|
||||
@Path("api/result")
|
||||
public class ResultEndpoints {
|
||||
|
||||
@Inject
|
||||
ResultService resultService;
|
||||
|
||||
@Inject
|
||||
SecurityCtx securityCtx;
|
||||
|
||||
@GET
|
||||
@Path("list")
|
||||
public Uni<List<Object[]>> getList() {
|
||||
return resultService.getList(securityCtx);
|
||||
}
|
||||
|
||||
@GET
|
||||
@Path("{uuid}")
|
||||
public Uni<List<ResultCategoryData>> getCategory(@PathParam("uuid") String uuid) {
|
||||
return resultService.getCategory(uuid, securityCtx);
|
||||
}
|
||||
|
||||
@GET
|
||||
@Path("{uuid}/club")
|
||||
public Uni<ResultService.ClubArrayData> getClub(@PathParam("uuid") String uuid) {
|
||||
return resultService.getClubArray(uuid, securityCtx);
|
||||
}
|
||||
|
||||
@GET
|
||||
@Path("{uuid}/comb")
|
||||
public Uni<ResultService.CombsArrayData> getComb(@PathParam("uuid") String uuid) {
|
||||
return resultService.getAllCombArray(uuid, securityCtx);
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
package fr.titionfire.ffsaf.rest.data;
|
||||
|
||||
import fr.titionfire.ffsaf.data.model.CompetitionGuestModel;
|
||||
import fr.titionfire.ffsaf.data.model.CompetitionModel;
|
||||
import fr.titionfire.ffsaf.data.model.RegisterModel;
|
||||
import fr.titionfire.ffsaf.utils.Categorie;
|
||||
@@ -11,6 +12,7 @@ import lombok.Data;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@@ -57,9 +59,9 @@ public class CompetitionData {
|
||||
model.getAdresse(), "", model.getDate(), model.getTodate(), null,
|
||||
model.getRegisterMode(), model.getStartRegister(), model.getEndRegister(), model.isPublicVisible(),
|
||||
null, model.getClub().getName(), "", null, false,
|
||||
"","", "","");
|
||||
"", "", "", "");
|
||||
|
||||
if (model.getRegisterMode() == RegisterMode.HELLOASSO){
|
||||
if (model.getRegisterMode() == RegisterMode.HELLOASSO) {
|
||||
out.setData1(model.getData1());
|
||||
out.setData2(model.getData2());
|
||||
}
|
||||
@@ -67,10 +69,15 @@ public class CompetitionData {
|
||||
return out;
|
||||
}
|
||||
|
||||
public CompetitionData addInsc(List<RegisterModel> insc) {
|
||||
this.registers = insc.stream()
|
||||
.map(i -> new SimpleRegister(i.getMembre().getId(), i.getOverCategory(), i.getWeight(),
|
||||
i.getCategorie(), (i.getClub() == null) ? null : i.getClub().getId())).toList();
|
||||
public CompetitionData addInsc(List<RegisterModel> insc, List<CompetitionGuestModel> guests) {
|
||||
this.registers = Stream.concat(
|
||||
insc.stream()
|
||||
.map(i -> new SimpleRegister(i.getMembre().getId(), i.getOverCategory(), i.getWeight(),
|
||||
i.getCategorie(), (i.getClub() == null) ? null : i.getClub().getId(),
|
||||
(i.getClub() == null) ? null : i.getClub().getName())),
|
||||
guests.stream()
|
||||
.map(i -> new SimpleRegister(i.getId() * -1, 0, i.getWeight(),
|
||||
i.getCategorie(), null, i.getClub()))).toList();
|
||||
return this;
|
||||
}
|
||||
|
||||
@@ -83,5 +90,6 @@ public class CompetitionData {
|
||||
Integer weight;
|
||||
Categorie categorie;
|
||||
Long club;
|
||||
String club_str;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,8 +28,10 @@ public class MatchData {
|
||||
return null;
|
||||
|
||||
return new MatchData(model.getSystemId(),
|
||||
(model.getC1_id() == null) ? null : model.getC1_id().getId(), model.getC1_str(),
|
||||
(model.getC2_id() == null) ? null : model.getC2_id().getId(), model.getC2_str(),
|
||||
(model.getC1_id() == null) ? null : model.getC1_id().getId(),
|
||||
(model.getC1_guest() == null) ? null : model.getC1_guest().getName(),
|
||||
(model.getC2_id() == null) ? null : model.getC2_id().getId(),
|
||||
(model.getC2_guest() == null) ? null : model.getC2_guest().getName(),
|
||||
model.getCategory().getId(), model.getCategory_ord(), model.isEnd(), model.getPoule(),
|
||||
model.getScores());
|
||||
}
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
package fr.titionfire.ffsaf.rest.data;
|
||||
|
||||
import fr.titionfire.ffsaf.utils.Categorie;
|
||||
import fr.titionfire.ffsaf.utils.Genre;
|
||||
import io.quarkus.runtime.annotations.RegisterForReflection;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
@@ -17,4 +19,11 @@ public class RegisterRequestData {
|
||||
private Integer weight;
|
||||
private int overCategory;
|
||||
private boolean lockEdit = false;
|
||||
|
||||
// for guest registration only
|
||||
private Long id = null;
|
||||
private Categorie categorie = Categorie.CADET;
|
||||
private Genre genre = Genre.NA;
|
||||
private String club = null;
|
||||
private String country = null;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
package fr.titionfire.ffsaf.rest.data;
|
||||
|
||||
import fr.titionfire.ffsaf.data.model.MatchModel;
|
||||
import fr.titionfire.ffsaf.utils.ScoreEmbeddable;
|
||||
import fr.titionfire.ffsaf.utils.TreeNode;
|
||||
import io.quarkus.runtime.annotations.RegisterForReflection;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@RegisterForReflection
|
||||
public class ResultCategoryData {
|
||||
int type;
|
||||
String name;
|
||||
HashMap<Character, List<PouleArrayData>> matchs = new HashMap<>();
|
||||
HashMap<Character, List<RankArray>> rankArray = new HashMap<>();
|
||||
ArrayList<TreeNode<TreeData>> trees;
|
||||
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@RegisterForReflection
|
||||
public static class RankArray {
|
||||
int rank;
|
||||
String name;
|
||||
int win;
|
||||
int pointMake;
|
||||
int pointTake;
|
||||
float pointRate;
|
||||
}
|
||||
|
||||
@RegisterForReflection
|
||||
public record PouleArrayData(String red, boolean red_w, List<Integer[]> score, boolean blue_w, String blue, boolean end) {
|
||||
public static PouleArrayData fromModel(MatchModel matchModel) {
|
||||
return new PouleArrayData(
|
||||
matchModel.getC1Name(),
|
||||
matchModel.isEnd() && matchModel.win() > 0,
|
||||
matchModel.isEnd() ?
|
||||
matchModel.getScores().stream().map(s -> new Integer[]{s.getS1(), s.getS2()}).toList()
|
||||
: new ArrayList<>(),
|
||||
matchModel.isEnd() && matchModel.win() < 0,
|
||||
matchModel.getC2Name(),
|
||||
matchModel.isEnd());
|
||||
}
|
||||
}
|
||||
|
||||
@RegisterForReflection
|
||||
public static record TreeData(long id, String c1FullName, String c2FullName, List<ScoreEmbeddable> scores,
|
||||
boolean end) {
|
||||
public static TreeData from(MatchModel match) {
|
||||
return new TreeData(match.getId(), match.getC1Name(), match.getC2Name(), match.getScores(), match.isEnd());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,9 +1,12 @@
|
||||
package fr.titionfire.ffsaf.rest.data;
|
||||
|
||||
import fr.titionfire.ffsaf.data.model.CompetitionGuestModel;
|
||||
import fr.titionfire.ffsaf.data.model.LicenceModel;
|
||||
import fr.titionfire.ffsaf.data.model.MembreModel;
|
||||
import fr.titionfire.ffsaf.data.model.RegisterModel;
|
||||
import fr.titionfire.ffsaf.net2.data.SimpleClubModel;
|
||||
import fr.titionfire.ffsaf.utils.Categorie;
|
||||
import fr.titionfire.ffsaf.utils.Genre;
|
||||
import fr.titionfire.ffsaf.utils.Utils;
|
||||
import io.quarkus.runtime.annotations.RegisterForReflection;
|
||||
import lombok.AllArgsConstructor;
|
||||
@@ -18,8 +21,9 @@ public class SimpleRegisterComb {
|
||||
private long id;
|
||||
private String fname;
|
||||
private String lname;
|
||||
private String genre;
|
||||
private String categorie;
|
||||
private Genre genre;
|
||||
private String country;
|
||||
private Categorie categorie;
|
||||
private SimpleClubModel club;
|
||||
private Integer licence;
|
||||
private Integer weight;
|
||||
@@ -30,11 +34,18 @@ public class SimpleRegisterComb {
|
||||
public static SimpleRegisterComb fromModel(RegisterModel register, List<LicenceModel> licences) {
|
||||
MembreModel membreModel = register.getMembre();
|
||||
return new SimpleRegisterComb(membreModel.getId(), membreModel.getFname(), membreModel.getLname(),
|
||||
membreModel.getGenre().name(),
|
||||
(register.getCategorie() == null) ? "Catégorie inconnue" : register.getCategorie().getName(),
|
||||
membreModel.getGenre(), membreModel.getCountry(),
|
||||
(register.getCategorie() == null) ? null : register.getCategorie(),
|
||||
SimpleClubModel.fromModel(register.getClub()), membreModel.getLicence(), register.getWeight(),
|
||||
register.getOverCategory(),
|
||||
licences.stream().anyMatch(l -> l.isValidate() && l.getSaison() == Utils.getSaison()),
|
||||
register.isLockEdit());
|
||||
}
|
||||
|
||||
public static SimpleRegisterComb fromModel(CompetitionGuestModel guest) {
|
||||
return new SimpleRegisterComb(guest.getId() * -1, guest.getFname(), guest.getLname(),
|
||||
guest.getGenre(), guest.getCountry(), guest.getCategorie(),
|
||||
new SimpleClubModel(null, guest.getClub(), "fr", null),
|
||||
null, guest.getWeight(), 0, false, false);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
package fr.titionfire.ffsaf.utils;
|
||||
|
||||
public enum CompetitionSystem {
|
||||
SAFCA, NONE
|
||||
SAFCA, INTERNAL
|
||||
}
|
||||
|
||||
35
src/main/java/fr/titionfire/ffsaf/utils/TreeNode.java
Normal file
35
src/main/java/fr/titionfire/ffsaf/utils/TreeNode.java
Normal file
@@ -0,0 +1,35 @@
|
||||
package fr.titionfire.ffsaf.utils;
|
||||
|
||||
import io.quarkus.runtime.annotations.RegisterForReflection;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.Setter;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@RegisterForReflection
|
||||
public class TreeNode<T> {
|
||||
private T data;
|
||||
private TreeNode<T> left;
|
||||
private TreeNode<T> right;
|
||||
|
||||
public TreeNode(T data) {
|
||||
this(data, null, null);
|
||||
}
|
||||
|
||||
public int death() {
|
||||
int dg = 0;
|
||||
int dd = 0;
|
||||
|
||||
if (this.right != null)
|
||||
dg = this.right.death();
|
||||
|
||||
if (this.left != null)
|
||||
dg = this.left.death();
|
||||
|
||||
return 1 + Math.max(dg, dd);
|
||||
}
|
||||
}
|
||||
@@ -150,11 +150,16 @@ public class Utils {
|
||||
|
||||
public static Uni<Response> getMediaFile(long id, String media, String dirname,
|
||||
Uni<?> uniBase) throws URISyntaxException {
|
||||
return getMediaFile(id, media, dirname, null, uniBase);
|
||||
return getMediaFile(id, media, dirname, null, uniBase, true);
|
||||
}
|
||||
|
||||
public static Uni<Response> getMediaFileNoDefault(long id, String media, String dirname,
|
||||
Uni<?> uniBase) throws URISyntaxException {
|
||||
return getMediaFile(id, media, dirname, null, uniBase, false);
|
||||
}
|
||||
|
||||
public static Uni<Response> getMediaFile(long id, String media, String dirname, String out_filename,
|
||||
Uni<?> uniBase) throws URISyntaxException {
|
||||
Uni<?> uniBase, boolean default_) throws URISyntaxException {
|
||||
Future<Pair<File, byte[]>> future = CompletableFuture.supplyAsync(() -> {
|
||||
FilenameFilter filter = (directory, filename) -> filename.startsWith(id + ".");
|
||||
File[] files = new File(media, dirname).listFiles(filter);
|
||||
@@ -182,19 +187,25 @@ public class Utils {
|
||||
return uniBase.chain(__ -> Uni.createFrom().future(future)
|
||||
.chain(filePair -> {
|
||||
if (filePair == null) {
|
||||
return Uni.createFrom().future(future2).map(data -> {
|
||||
if (data == null)
|
||||
return Response.noContent().build();
|
||||
if (default_) {
|
||||
return Uni.createFrom().future(future2).map(data -> {
|
||||
if (data == null)
|
||||
return Response.noContent().build();
|
||||
|
||||
String mimeType = "image/apng";
|
||||
Response.ResponseBuilder resp = Response.ok(data);
|
||||
resp.type(MediaType.APPLICATION_OCTET_STREAM);
|
||||
resp.header(HttpHeaders.CONTENT_LENGTH, data.length);
|
||||
resp.header(HttpHeaders.CONTENT_TYPE, mimeType);
|
||||
resp.header(HttpHeaders.CONTENT_DISPOSITION,
|
||||
"inline; " + ((out_filename == null) ? "" : "filename=\"" + out_filename + "\""));
|
||||
return resp.build();
|
||||
});
|
||||
String mimeType = "image/apng";
|
||||
Response.ResponseBuilder resp = Response.ok(data);
|
||||
resp.type(MediaType.APPLICATION_OCTET_STREAM);
|
||||
resp.header(HttpHeaders.CONTENT_LENGTH, data.length);
|
||||
resp.header(HttpHeaders.CONTENT_TYPE, mimeType);
|
||||
resp.header(HttpHeaders.CONTENT_DISPOSITION,
|
||||
"inline; " + ((out_filename == null) ? "" : "filename=\"" + out_filename + "\""));
|
||||
return resp.build();
|
||||
});
|
||||
} else {
|
||||
Response.ResponseBuilder resp = Response.status(404);
|
||||
resp.header(HttpHeaders.CACHE_CONTROL, "max-age=600");
|
||||
return Uni.createFrom().item(resp.build());
|
||||
}
|
||||
} else {
|
||||
return Uni.createFrom().item(() -> {
|
||||
String mimeType = URLConnection.guessContentTypeFromName(filePair.getKey().getName());
|
||||
|
||||
207
src/main/java/fr/titionfire/ffsaf/ws/CompetitionWS.java
Normal file
207
src/main/java/fr/titionfire/ffsaf/ws/CompetitionWS.java
Normal file
@@ -0,0 +1,207 @@
|
||||
package fr.titionfire.ffsaf.ws;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import fr.titionfire.ffsaf.data.repository.CompetitionRepository;
|
||||
import fr.titionfire.ffsaf.domain.service.CompetPermService;
|
||||
import fr.titionfire.ffsaf.net2.MessageType;
|
||||
import fr.titionfire.ffsaf.utils.SecurityCtx;
|
||||
import fr.titionfire.ffsaf.ws.data.WelcomeInfo;
|
||||
import fr.titionfire.ffsaf.ws.recv.*;
|
||||
import fr.titionfire.ffsaf.ws.send.JsonUni;
|
||||
import io.quarkus.hibernate.reactive.panache.common.WithSession;
|
||||
import io.quarkus.security.Authenticated;
|
||||
import io.quarkus.websockets.next.*;
|
||||
import io.smallrye.mutiny.Multi;
|
||||
import io.smallrye.mutiny.Uni;
|
||||
import io.smallrye.mutiny.unchecked.Unchecked;
|
||||
import jakarta.annotation.PostConstruct;
|
||||
import jakarta.inject.Inject;
|
||||
import jakarta.ws.rs.ForbiddenException;
|
||||
import org.jboss.logging.Logger;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.*;
|
||||
|
||||
import static fr.titionfire.ffsaf.net2.Client_Thread.MAPPER;
|
||||
|
||||
@Authenticated
|
||||
@WebSocket(path = "api/ws/competition/{uuid}")
|
||||
public class CompetitionWS {
|
||||
private static final Logger LOGGER = Logger.getLogger(CompetitionWS.class);
|
||||
|
||||
private static final HashMap<WebSocketConnection, HashMap<UUID, JsonUni<?>>> waitingResponse = new HashMap<>();
|
||||
|
||||
@Inject
|
||||
RMatch rMatch;
|
||||
|
||||
@Inject
|
||||
RCategorie rCategorie;
|
||||
|
||||
@Inject
|
||||
RRegister rRegister;
|
||||
|
||||
@Inject
|
||||
RCardboard rCardboard;
|
||||
|
||||
@Inject
|
||||
SecurityCtx securityCtx;
|
||||
|
||||
@Inject
|
||||
CompetPermService competPermService;
|
||||
|
||||
@Inject
|
||||
CompetitionRepository competitionRepository;
|
||||
|
||||
HashMap<Method, Object> wsMethods = new HashMap<>();
|
||||
|
||||
public void getWSReceiverMethods(Class<?> clazz, Object object) {
|
||||
for (Method method : clazz.getDeclaredMethods()) {
|
||||
if (method.isAnnotationPresent(WSReceiver.class)) {
|
||||
if (method.getParameterCount() <= 1) {
|
||||
LOGGER.warnf("@WSReceiver has no parameters for method %s", method.getName());
|
||||
continue;
|
||||
}
|
||||
if (!method.getReturnType().equals(Uni.class)) {
|
||||
LOGGER.warnf("@WSReceiver has returned unexpected type %s", method.getReturnType());
|
||||
continue;
|
||||
}
|
||||
// method.setAccessible(true);
|
||||
wsMethods.put(method, object);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@PostConstruct
|
||||
void init() {
|
||||
getWSReceiverMethods(RMatch.class, rMatch);
|
||||
getWSReceiverMethods(RCategorie.class, rCategorie);
|
||||
getWSReceiverMethods(RRegister.class, rRegister);
|
||||
getWSReceiverMethods(RCardboard.class, rCardboard);
|
||||
}
|
||||
|
||||
@OnOpen
|
||||
@WithSession
|
||||
Uni<MessageOut> open(WebSocketConnection connection) {
|
||||
LOGGER.infof("Opening CompetitionWS for %s", connection.pathParam("uuid"));
|
||||
LOGGER.debugf("Active connections: %d", connection.getOpenConnections().size());
|
||||
|
||||
return competitionRepository.find("uuid", connection.pathParam("uuid")).firstResult()
|
||||
.invoke(Unchecked.consumer(cm -> {
|
||||
if (cm == null)
|
||||
throw new ForbiddenException();
|
||||
}))
|
||||
.call(cm -> competPermService.hasEditPerm(securityCtx, cm).map(__ -> PermLevel.ADMIN)
|
||||
.onFailure()
|
||||
.recoverWithUni(competPermService.hasTablePerm(securityCtx, cm).map(__ -> PermLevel.TABLE))
|
||||
.onFailure()
|
||||
.recoverWithUni(competPermService.hasViewPerm(securityCtx, cm).map(__ -> PermLevel.VIEW))
|
||||
.invoke(prem -> connection.userData().put(UserData.TypedKey.forString("prem"), prem.toString()))
|
||||
.invoke(prem -> LOGGER.infof("Connection permission: %s", prem))
|
||||
.onFailure().transform(t -> new ForbiddenException()))
|
||||
.invoke(__ -> {
|
||||
connection.userData().put(UserData.TypedKey.forString("subject"), securityCtx.getSubject());
|
||||
waitingResponse.put(connection, new HashMap<>());
|
||||
})
|
||||
.map(cm -> {
|
||||
WelcomeInfo welcomeInfo = new WelcomeInfo();
|
||||
|
||||
welcomeInfo.setName(cm.getName());
|
||||
welcomeInfo.setPerm(connection.userData().get(UserData.TypedKey.forString("prem")));
|
||||
|
||||
return new MessageOut(UUID.randomUUID(), "welcomeInfo", MessageType.NOTIFY, welcomeInfo);
|
||||
});
|
||||
}
|
||||
|
||||
@OnClose
|
||||
void close(WebSocketConnection connection) {
|
||||
LOGGER.infof("Closing CompetitionWS for %s ", connection.pathParam("uuid"));
|
||||
LOGGER.debugf("Active connections: %d", connection.getOpenConnections().size());
|
||||
|
||||
waitingResponse.remove(connection);
|
||||
}
|
||||
|
||||
private MessageOut makeReply(MessageIn message, Object data) {
|
||||
return new MessageOut(message.uuid(), message.code(), MessageType.REPLY, data);
|
||||
}
|
||||
|
||||
private MessageOut makeError(MessageIn message, Object data) {
|
||||
return new MessageOut(message.uuid(), message.code(), MessageType.ERROR, data);
|
||||
}
|
||||
|
||||
@OnTextMessage
|
||||
Multi<MessageOut> processAsync(WebSocketConnection connection, MessageIn message) {
|
||||
System.out.println(message);
|
||||
if (message.type() == MessageType.REPLY || message.type() == MessageType.ERROR) {
|
||||
try {
|
||||
JsonUni<?> jsonUni = waitingResponse.get(connection).get(message.uuid());
|
||||
if (jsonUni == null) {
|
||||
LOGGER.debugf("No JsonUni found for %s", message.uuid());
|
||||
if (message.type() == MessageType.ERROR)
|
||||
LOGGER.errorf("request %s make error %s", message.uuid(), message.data());
|
||||
return null;
|
||||
}
|
||||
waitingResponse.get(connection).remove(message.uuid());
|
||||
|
||||
if (message.type() == MessageType.ERROR)
|
||||
return jsonUni.castAndError(message.data()).onFailure()
|
||||
.invoke(t -> LOGGER.error(t.getMessage(), t))
|
||||
.replaceWith((MessageOut) null).toMulti().filter(__ -> false);
|
||||
|
||||
return jsonUni.castAndChain(message.data()).onFailure()
|
||||
.invoke(t -> LOGGER.error(t.getMessage(), t))
|
||||
.replaceWith((MessageOut) null).toMulti().filter(__ -> false);
|
||||
} catch (JsonProcessingException e) {
|
||||
LOGGER.warn(e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
for (Map.Entry<Method, Object> entry : wsMethods.entrySet()) {
|
||||
Method method = entry.getKey();
|
||||
WSReceiver wsReceiver = method.getAnnotation(WSReceiver.class);
|
||||
PermLevel perm = PermLevel.valueOf(connection.userData().get(UserData.TypedKey.forString("prem")));
|
||||
if (wsReceiver.code().equalsIgnoreCase(message.code())) {
|
||||
if (wsReceiver.permission().ordinal() > perm.ordinal())
|
||||
return Uni.createFrom().item(makeError(message, "Permission denied")).toMulti();
|
||||
return ((Uni<?>) method.invoke(entry.getValue(), connection,
|
||||
MAPPER.treeToValue(message.data(), method.getParameterTypes()[1])))
|
||||
.map(o -> makeReply(message, o))
|
||||
.onFailure()
|
||||
.recoverWithItem(t -> {
|
||||
LOGGER.error(t.getMessage(), t);
|
||||
return makeError(message, t.getMessage());
|
||||
}).toMulti()
|
||||
.filter(__ -> message.type() == MessageType.REQUEST);
|
||||
}
|
||||
}
|
||||
return Uni.createFrom().item(makeError(message, "No receiver method found")).toMulti();
|
||||
} catch (IllegalAccessException | InvocationTargetException | JsonProcessingException e) {
|
||||
LOGGER.warn(e.getMessage(), e);
|
||||
return Uni.createFrom().item(makeError(message, e.getMessage())).toMulti();
|
||||
}
|
||||
|
||||
// return Uni.createFrom().item(new Message<>(message.uuid(), message.code(), MessageType.REPLY, "ko"));
|
||||
}
|
||||
|
||||
public static Uni<Void> sendNotifyToOtherEditor(WebSocketConnection connection, String code, Object data) {
|
||||
String uuid = connection.pathParam("uuid");
|
||||
|
||||
List<Uni<Void>> queue = new ArrayList<>();
|
||||
queue.add(Uni.createFrom().voidItem()); // For avoid empty queue
|
||||
|
||||
connection.getOpenConnections().forEach(c -> {
|
||||
if (uuid.equals(c.pathParam("uuid"))) {
|
||||
queue.add(c.sendText(new MessageOut(UUID.randomUUID(), code, MessageType.NOTIFY, data)));
|
||||
}
|
||||
});
|
||||
|
||||
return Uni.join().all(queue).andCollectFailures().onFailure().recoverWithNull().replaceWithVoid();
|
||||
}
|
||||
|
||||
@OnError
|
||||
Uni<Void> error(WebSocketConnection connection, ForbiddenException t) {
|
||||
return connection.close(CloseReason.INTERNAL_SERVER_ERROR);
|
||||
//return "forbidden: " + securityCtx.getSubject();
|
||||
}
|
||||
}
|
||||
12
src/main/java/fr/titionfire/ffsaf/ws/MessageIn.java
Normal file
12
src/main/java/fr/titionfire/ffsaf/ws/MessageIn.java
Normal file
@@ -0,0 +1,12 @@
|
||||
package fr.titionfire.ffsaf.ws;
|
||||
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import fr.titionfire.ffsaf.net2.MessageType;
|
||||
import io.quarkus.runtime.annotations.RegisterForReflection;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
@RegisterForReflection
|
||||
public record MessageIn (UUID uuid, String code, MessageType type, JsonNode data){
|
||||
|
||||
}
|
||||
11
src/main/java/fr/titionfire/ffsaf/ws/MessageOut.java
Normal file
11
src/main/java/fr/titionfire/ffsaf/ws/MessageOut.java
Normal file
@@ -0,0 +1,11 @@
|
||||
package fr.titionfire.ffsaf.ws;
|
||||
|
||||
import fr.titionfire.ffsaf.net2.MessageType;
|
||||
import io.quarkus.runtime.annotations.RegisterForReflection;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
@RegisterForReflection
|
||||
public record MessageOut(UUID uuid, String code, MessageType type, Object data){
|
||||
|
||||
}
|
||||
8
src/main/java/fr/titionfire/ffsaf/ws/PermLevel.java
Normal file
8
src/main/java/fr/titionfire/ffsaf/ws/PermLevel.java
Normal file
@@ -0,0 +1,8 @@
|
||||
package fr.titionfire.ffsaf.ws;
|
||||
|
||||
public enum PermLevel {
|
||||
NONE,
|
||||
VIEW,
|
||||
TABLE,
|
||||
ADMIN,
|
||||
}
|
||||
11
src/main/java/fr/titionfire/ffsaf/ws/data/WelcomeInfo.java
Normal file
11
src/main/java/fr/titionfire/ffsaf/ws/data/WelcomeInfo.java
Normal file
@@ -0,0 +1,11 @@
|
||||
package fr.titionfire.ffsaf.ws.data;
|
||||
|
||||
import io.quarkus.runtime.annotations.RegisterForReflection;
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
@RegisterForReflection
|
||||
public class WelcomeInfo {
|
||||
private String name;
|
||||
private String perm;
|
||||
}
|
||||
128
src/main/java/fr/titionfire/ffsaf/ws/recv/RCardboard.java
Normal file
128
src/main/java/fr/titionfire/ffsaf/ws/recv/RCardboard.java
Normal file
@@ -0,0 +1,128 @@
|
||||
package fr.titionfire.ffsaf.ws.recv;
|
||||
|
||||
import fr.titionfire.ffsaf.data.model.CardboardModel;
|
||||
import fr.titionfire.ffsaf.data.model.MatchModel;
|
||||
import fr.titionfire.ffsaf.data.repository.CardboardRepository;
|
||||
import fr.titionfire.ffsaf.data.repository.MatchRepository;
|
||||
import fr.titionfire.ffsaf.domain.entity.CardboardEntity;
|
||||
import fr.titionfire.ffsaf.rest.exception.DForbiddenException;
|
||||
import fr.titionfire.ffsaf.rest.exception.DNotFoundException;
|
||||
import fr.titionfire.ffsaf.ws.PermLevel;
|
||||
import fr.titionfire.ffsaf.ws.send.SSCardboard;
|
||||
import io.quarkus.hibernate.reactive.panache.Panache;
|
||||
import io.quarkus.hibernate.reactive.panache.common.WithSession;
|
||||
import io.quarkus.runtime.annotations.RegisterForReflection;
|
||||
import io.quarkus.websockets.next.WebSocketConnection;
|
||||
import io.smallrye.mutiny.Uni;
|
||||
import io.smallrye.mutiny.unchecked.Unchecked;
|
||||
import jakarta.enterprise.context.ApplicationScoped;
|
||||
import jakarta.inject.Inject;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
@WithSession
|
||||
@ApplicationScoped
|
||||
@RegisterForReflection
|
||||
public class RCardboard {
|
||||
|
||||
@Inject
|
||||
MatchRepository matchRepository;
|
||||
|
||||
@Inject
|
||||
CardboardRepository cardboardRepository;
|
||||
|
||||
private Uni<MatchModel> getById(long id, WebSocketConnection connection) {
|
||||
return matchRepository.findById(id)
|
||||
.invoke(Unchecked.consumer(o -> {
|
||||
if (o == null)
|
||||
throw new DNotFoundException("Matche non trouver");
|
||||
if (!o.getCategory().getCompet().getUuid().equals(connection.pathParam("uuid")))
|
||||
throw new DForbiddenException("Permission denied");
|
||||
}));
|
||||
}
|
||||
|
||||
@WSReceiver(code = "sendCardboardChange", permission = PermLevel.TABLE)
|
||||
public Uni<Void> sendCardboardChange(WebSocketConnection connection, SendCardboard card) {
|
||||
return getById(card.matchId, connection)
|
||||
.chain(matchModel -> cardboardRepository.find("(comb.id = ?1 OR guestComb.id = ?2) AND match.id = ?3",
|
||||
card.combId, card.combId * -1, card.matchId).firstResult()
|
||||
.chain(model -> {
|
||||
if (model != null) {
|
||||
model.setRed(model.getRed() + card.red);
|
||||
model.setYellow(model.getYellow() + card.yellow);
|
||||
return Panache.withTransaction(() -> cardboardRepository.persist(model));
|
||||
}
|
||||
CardboardModel cardboardModel = new CardboardModel();
|
||||
|
||||
cardboardModel.setCompet(matchModel.getCategory().getCompet());
|
||||
cardboardModel.setMatch(matchModel);
|
||||
cardboardModel.setRed(card.red);
|
||||
cardboardModel.setYellow(card.yellow);
|
||||
cardboardModel.setComb(null);
|
||||
cardboardModel.setGuestComb(null);
|
||||
|
||||
if (card.combId >= 0) {
|
||||
if (matchModel.getC1_id() != null && matchModel.getC1_id().getId() == card.combId)
|
||||
cardboardModel.setComb(matchModel.getC1_id());
|
||||
if (matchModel.getC2_id() != null && matchModel.getC2_id().getId() == card.combId)
|
||||
cardboardModel.setComb(matchModel.getC2_id());
|
||||
} else {
|
||||
if (matchModel.getC1_guest() != null && matchModel.getC1_guest()
|
||||
.getId() == card.combId * -1)
|
||||
cardboardModel.setGuestComb(matchModel.getC1_guest());
|
||||
if (matchModel.getC2_guest() != null && matchModel.getC2_guest()
|
||||
.getId() == card.combId * -1)
|
||||
cardboardModel.setGuestComb(matchModel.getC2_guest());
|
||||
}
|
||||
|
||||
if (cardboardModel.getComb() == null && cardboardModel.getGuestComb() == null)
|
||||
return Uni.createFrom().nullItem();
|
||||
return Panache.withTransaction(() -> cardboardRepository.persist(cardboardModel));
|
||||
}))
|
||||
.call(model -> SSCardboard.sendCardboard(connection, CardboardEntity.fromModel(model)))
|
||||
.replaceWithVoid();
|
||||
}
|
||||
|
||||
@WSReceiver(code = "getCardboardWithoutThis", permission = PermLevel.VIEW)
|
||||
public Uni<CardboardAllMatch> getCardboardWithoutThis(WebSocketConnection connection, Long matchId) {
|
||||
return getById(matchId, connection)
|
||||
.chain(matchModel -> cardboardRepository.list("compet = ?1 AND match != ?2", matchModel.getCategory().getCompet(), matchModel)
|
||||
.map(models -> {
|
||||
CardboardAllMatch out = new CardboardAllMatch();
|
||||
|
||||
models.stream().filter(c -> (matchModel.getC1_id() != null
|
||||
&& Objects.equals(c.getComb(), matchModel.getC1_id()))
|
||||
|| (matchModel.getC1_guest() != null
|
||||
&& Objects.equals(c.getGuestComb(), matchModel.getC1_guest())))
|
||||
.forEach(c -> {
|
||||
out.c1_yellow += c.getYellow();
|
||||
out.c1_red += c.getRed();
|
||||
});
|
||||
|
||||
models.stream().filter(c -> (matchModel.getC2_id() != null
|
||||
&& Objects.equals(c.getComb(), matchModel.getC2_id()))
|
||||
|| (matchModel.getC2_guest() != null
|
||||
&& Objects.equals(c.getGuestComb(), matchModel.getC2_guest())))
|
||||
.forEach(c -> {
|
||||
out.c2_yellow += c.getYellow();
|
||||
out.c2_red += c.getRed();
|
||||
});
|
||||
|
||||
return out;
|
||||
}));
|
||||
}
|
||||
|
||||
@RegisterForReflection
|
||||
public record SendCardboard(long matchId, long combId, int yellow, int red) {
|
||||
}
|
||||
|
||||
@Data
|
||||
@RegisterForReflection
|
||||
public static class CardboardAllMatch {
|
||||
int c1_yellow = 0;
|
||||
int c1_red = 0;
|
||||
int c2_yellow = 0;
|
||||
int c2_red = 0;
|
||||
}
|
||||
}
|
||||
229
src/main/java/fr/titionfire/ffsaf/ws/recv/RCategorie.java
Normal file
229
src/main/java/fr/titionfire/ffsaf/ws/recv/RCategorie.java
Normal file
@@ -0,0 +1,229 @@
|
||||
package fr.titionfire.ffsaf.ws.recv;
|
||||
|
||||
import fr.titionfire.ffsaf.data.model.CategoryModel;
|
||||
import fr.titionfire.ffsaf.data.model.MatchModel;
|
||||
import fr.titionfire.ffsaf.data.model.TreeModel;
|
||||
import fr.titionfire.ffsaf.data.repository.CategoryRepository;
|
||||
import fr.titionfire.ffsaf.data.repository.CompetitionRepository;
|
||||
import fr.titionfire.ffsaf.data.repository.MatchRepository;
|
||||
import fr.titionfire.ffsaf.data.repository.TreeRepository;
|
||||
import fr.titionfire.ffsaf.domain.entity.MatchEntity;
|
||||
import fr.titionfire.ffsaf.domain.entity.TreeEntity;
|
||||
import fr.titionfire.ffsaf.rest.exception.DForbiddenException;
|
||||
import fr.titionfire.ffsaf.rest.exception.DNotFoundException;
|
||||
import fr.titionfire.ffsaf.utils.TreeNode;
|
||||
import fr.titionfire.ffsaf.ws.PermLevel;
|
||||
import fr.titionfire.ffsaf.ws.send.SSCategorie;
|
||||
import io.quarkus.hibernate.reactive.panache.Panache;
|
||||
import io.quarkus.hibernate.reactive.panache.common.WithSession;
|
||||
import io.quarkus.runtime.annotations.RegisterForReflection;
|
||||
import io.quarkus.websockets.next.WebSocketConnection;
|
||||
import io.smallrye.mutiny.Uni;
|
||||
import io.smallrye.mutiny.unchecked.Unchecked;
|
||||
import jakarta.enterprise.context.ApplicationScoped;
|
||||
import jakarta.inject.Inject;
|
||||
import lombok.Data;
|
||||
import org.hibernate.reactive.mutiny.Mutiny;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@WithSession
|
||||
@ApplicationScoped
|
||||
@RegisterForReflection
|
||||
public class RCategorie {
|
||||
//private static final Logger LOGGER = Logger.getLogger(RCategorie.class);
|
||||
|
||||
@Inject
|
||||
CategoryRepository categoryRepository;
|
||||
|
||||
@Inject
|
||||
CompetitionRepository competitionRepository;
|
||||
|
||||
@Inject
|
||||
MatchRepository matchRepository;
|
||||
|
||||
@Inject
|
||||
TreeRepository treeRepository;
|
||||
|
||||
private Uni<CategoryModel> getById(long id, WebSocketConnection connection) {
|
||||
return categoryRepository.findById(id)
|
||||
.invoke(Unchecked.consumer(o -> {
|
||||
if (o == null)
|
||||
throw new DNotFoundException("Catégorie non trouver");
|
||||
if (!o.getCompet().getUuid().equals(connection.pathParam("uuid")))
|
||||
throw new DForbiddenException("Permission denied");
|
||||
}));
|
||||
}
|
||||
|
||||
@WSReceiver(code = "getAllCategory", permission = PermLevel.VIEW)
|
||||
public Uni<List<JustCategorie>> getAllCategory(WebSocketConnection connection, Object o) {
|
||||
return categoryRepository.list("compet.uuid", connection.pathParam("uuid"))
|
||||
.map(category -> category.stream().map(JustCategorie::from).toList());
|
||||
}
|
||||
|
||||
@WSReceiver(code = "getFullCategory", permission = PermLevel.VIEW)
|
||||
public Uni<FullCategory> getFullCategory(WebSocketConnection connection, Long id) {
|
||||
FullCategory fullCategory = new FullCategory();
|
||||
|
||||
return getById(id, connection)
|
||||
.invoke(cat -> {
|
||||
fullCategory.setId(cat.getId());
|
||||
fullCategory.setName(cat.getName());
|
||||
fullCategory.setLiceName(cat.getLiceName());
|
||||
fullCategory.setType(cat.getType());
|
||||
})
|
||||
.call(cat -> Mutiny.fetch(cat.getMatchs())
|
||||
.map(matchModels -> matchModels.stream().filter(o -> o.getCategory_ord() >= 0)
|
||||
.map(MatchEntity::fromModel).toList())
|
||||
.invoke(fullCategory::setMatches))
|
||||
.call(cat -> treeRepository.list("category = ?1 AND level != 0", cat.getId())
|
||||
.map(treeModels -> treeModels.stream().map(TreeEntity::fromModel).toList())
|
||||
.invoke(fullCategory::setTrees))
|
||||
.map(__ -> fullCategory);
|
||||
}
|
||||
|
||||
@WSReceiver(code = "createCategory", permission = PermLevel.ADMIN)
|
||||
public Uni<Long> createCategory(WebSocketConnection connection, JustCategorie categorie) {
|
||||
return competitionRepository.find("uuid", connection.pathParam("uuid")).firstResult()
|
||||
.chain(cm -> {
|
||||
CategoryModel categoryModel = new CategoryModel();
|
||||
categoryModel.setName(categorie.name);
|
||||
categoryModel.setCompet(cm);
|
||||
categoryModel.setMatchs(new ArrayList<>());
|
||||
categoryModel.setTree(new ArrayList<>());
|
||||
categoryModel.setType(categorie.type);
|
||||
categoryModel.setLiceName(categorie.liceName);
|
||||
|
||||
return categoryRepository.create(categoryModel);
|
||||
})
|
||||
.call(cat -> SSCategorie.sendAddCategory(connection, cat))
|
||||
.map(CategoryModel::getId);
|
||||
}
|
||||
|
||||
@WSReceiver(code = "updateCategory", permission = PermLevel.ADMIN)
|
||||
public Uni<Void> updateCategory(WebSocketConnection connection, JustCategorie categorie) {
|
||||
return getById(categorie.id, connection)
|
||||
.chain(cat -> {
|
||||
cat.setName(categorie.name);
|
||||
cat.setLiceName(categorie.liceName);
|
||||
cat.setType(categorie.type);
|
||||
return Panache.withTransaction(() -> categoryRepository.persist(cat));
|
||||
})
|
||||
.call(cat -> {
|
||||
Uni<Long> uni = Uni.createFrom().nullItem();
|
||||
if ((categorie.type() & 1) == 0)
|
||||
uni = uni.chain(__ -> matchRepository.delete("category = ?1 AND category_ord >= 0", cat));
|
||||
if ((categorie.type() & 2) == 0) {
|
||||
uni = uni.chain(__ -> treeRepository.delete("category = ?1", cat.getId()))
|
||||
.chain(__ -> matchRepository.delete("category = ?1 AND category_ord = -42", cat));
|
||||
}
|
||||
return uni;
|
||||
})
|
||||
.call(cat -> SSCategorie.sendCategory(connection, cat))
|
||||
.replaceWithVoid();
|
||||
}
|
||||
|
||||
private Uni<TreeModel> getOrCreateTreeNode(Long id, Long categorieId, int level) {
|
||||
if (id == null) {
|
||||
TreeModel treeModel = new TreeModel();
|
||||
treeModel.setCategory(categorieId);
|
||||
treeModel.setLevel(level);
|
||||
|
||||
return Panache.withTransaction(() -> treeRepository.persistAndFlush(treeModel));
|
||||
} else {
|
||||
return Panache.withTransaction(
|
||||
() -> treeRepository.find("match.id = ?1", id).firstResult()
|
||||
.invoke(t -> t.setLevel(level))
|
||||
.chain(t -> treeRepository.persist(t)));
|
||||
}
|
||||
}
|
||||
|
||||
private Uni<Void> updateNode(TreeNode<Long> current, TreeModel currentTreeModel, CategoryModel category) {
|
||||
return Uni.createFrom().item(currentTreeModel)
|
||||
.chain(t -> {
|
||||
if (current.getData() != null)
|
||||
return Uni.createFrom().item(t);
|
||||
|
||||
MatchModel matchModel = new MatchModel();
|
||||
matchModel.setCategory(category);
|
||||
matchModel.setCategory_ord(-42);
|
||||
matchModel.setEnd(false);
|
||||
|
||||
return matchRepository.create(matchModel).onItem()
|
||||
.invoke(t::setMatch)
|
||||
.chain(__ -> treeRepository.persistAndFlush(t));
|
||||
})
|
||||
.call(t -> {
|
||||
if (current.getLeft() == null)
|
||||
return Uni.createFrom().item(t);
|
||||
|
||||
return getOrCreateTreeNode(current.getLeft().getData(), category.getId(), 0)
|
||||
.invoke(t::setLeft)
|
||||
.call(treeModel -> updateNode(current.getLeft(), treeModel, category));
|
||||
})
|
||||
.call(t -> {
|
||||
if (current.getRight() == null)
|
||||
return Uni.createFrom().item(t);
|
||||
|
||||
return getOrCreateTreeNode(current.getRight().getData(), category.getId(), 0)
|
||||
.invoke(t::setRight)
|
||||
.call(treeModel -> updateNode(current.getRight(), treeModel, category));
|
||||
})
|
||||
.chain(t -> treeRepository.persist(t))
|
||||
.replaceWithVoid();
|
||||
}
|
||||
|
||||
|
||||
@WSReceiver(code = "updateTrees", permission = PermLevel.ADMIN)
|
||||
public Uni<Void> updateTrees(WebSocketConnection connection, TreeUpdate data) {
|
||||
return getById(data.categoryId, connection)
|
||||
.call(cat -> treeRepository.update("level = -1, left = NULL, right = NULL WHERE category = ?1",
|
||||
cat.getId()))
|
||||
.call(cat -> {
|
||||
Uni<?> uni = Uni.createFrom().voidItem();
|
||||
|
||||
for (int i = 0; i < data.trees().size(); i++) {
|
||||
TreeNode<Long> current = data.trees().get(i);
|
||||
|
||||
int finalI = i;
|
||||
uni = uni.chain(() -> getOrCreateTreeNode(current.getData(), cat.getId(), finalI + 1)
|
||||
.call(treeModel -> updateNode(current, treeModel, cat)));
|
||||
|
||||
}
|
||||
Uni<?> finalUni = uni;
|
||||
return Panache.withTransaction(() -> finalUni);
|
||||
})
|
||||
.call(cat -> treeRepository.list("category = ?1 AND level = -1", cat.getId())
|
||||
.map(l -> l.stream().map(o -> o.getMatch().getId()).toList())
|
||||
.call(__ -> treeRepository.delete("category = ?1 AND level = -1", cat.getId()))
|
||||
.call(ids -> matchRepository.delete("id IN ?1", ids)))
|
||||
.call(__ -> treeRepository.flush())
|
||||
.call(cat -> treeRepository.list("category = ?1 AND level != 0", cat.getId())
|
||||
.map(treeModels -> treeModels.stream().map(TreeEntity::fromModel).toList())
|
||||
.chain(trees -> SSCategorie.sendTreeCategory(connection, trees)))
|
||||
.replaceWithVoid();
|
||||
}
|
||||
|
||||
@RegisterForReflection
|
||||
public record JustCategorie(long id, String name, int type, String liceName) {
|
||||
public static JustCategorie from(CategoryModel m) {
|
||||
return new JustCategorie(m.getId(), m.getName(), m.getType(), m.getLiceName());
|
||||
}
|
||||
}
|
||||
|
||||
@RegisterForReflection
|
||||
public record TreeUpdate(long categoryId, List<TreeNode<Long>> trees) {
|
||||
}
|
||||
|
||||
@Data
|
||||
@RegisterForReflection
|
||||
public static class FullCategory {
|
||||
long id;
|
||||
String name;
|
||||
int type;
|
||||
String liceName;
|
||||
List<TreeEntity> trees = null;
|
||||
List<MatchEntity> matches;
|
||||
}
|
||||
}
|
||||
346
src/main/java/fr/titionfire/ffsaf/ws/recv/RMatch.java
Normal file
346
src/main/java/fr/titionfire/ffsaf/ws/recv/RMatch.java
Normal file
@@ -0,0 +1,346 @@
|
||||
package fr.titionfire.ffsaf.ws.recv;
|
||||
|
||||
import fr.titionfire.ffsaf.data.model.*;
|
||||
import fr.titionfire.ffsaf.data.repository.*;
|
||||
import fr.titionfire.ffsaf.domain.entity.MatchEntity;
|
||||
import fr.titionfire.ffsaf.domain.entity.TreeEntity;
|
||||
import fr.titionfire.ffsaf.rest.exception.DForbiddenException;
|
||||
import fr.titionfire.ffsaf.rest.exception.DNotFoundException;
|
||||
import fr.titionfire.ffsaf.utils.ScoreEmbeddable;
|
||||
import fr.titionfire.ffsaf.ws.PermLevel;
|
||||
import fr.titionfire.ffsaf.ws.send.SSMatch;
|
||||
import io.quarkus.hibernate.reactive.panache.Panache;
|
||||
import io.quarkus.hibernate.reactive.panache.common.WithSession;
|
||||
import io.quarkus.panache.common.Sort;
|
||||
import io.quarkus.runtime.annotations.RegisterForReflection;
|
||||
import io.quarkus.websockets.next.WebSocketConnection;
|
||||
import io.smallrye.mutiny.Uni;
|
||||
import io.smallrye.mutiny.unchecked.Unchecked;
|
||||
import jakarta.enterprise.context.ApplicationScoped;
|
||||
import jakarta.inject.Inject;
|
||||
import org.jboss.logging.Logger;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
@WithSession
|
||||
@ApplicationScoped
|
||||
@RegisterForReflection
|
||||
public class RMatch {
|
||||
private static final Logger LOGGER = Logger.getLogger(RMatch.class);
|
||||
|
||||
@Inject
|
||||
MatchRepository matchRepository;
|
||||
|
||||
@Inject
|
||||
CombRepository combRepository;
|
||||
|
||||
@Inject
|
||||
CategoryRepository categoryRepository;
|
||||
|
||||
@Inject
|
||||
TreeRepository treeRepository;
|
||||
|
||||
@Inject
|
||||
CompetitionGuestRepository competitionGuestRepository;
|
||||
|
||||
private Uni<MatchModel> getById(long id, WebSocketConnection connection) {
|
||||
return matchRepository.findById(id)
|
||||
.invoke(Unchecked.consumer(o -> {
|
||||
if (o == null)
|
||||
throw new DNotFoundException("Matche non trouver");
|
||||
if (!o.getCategory().getCompet().getUuid().equals(connection.pathParam("uuid")))
|
||||
throw new DForbiddenException("Permission denied");
|
||||
}));
|
||||
}
|
||||
|
||||
private Uni<MatchModel> creatMatch(CategoryModel categoryModel, AddMatch m) {
|
||||
return Uni.createFrom().item(() -> {
|
||||
MatchModel matchModel = new MatchModel();
|
||||
|
||||
matchModel.setCategory(categoryModel);
|
||||
matchModel.setCategory_ord(m.categorie_ord);
|
||||
matchModel.setEnd(false);
|
||||
matchModel.setPoule(m.poule);
|
||||
|
||||
return matchModel;
|
||||
})
|
||||
.call(mm -> m.c1() >= 0 ?
|
||||
combRepository.findById(m.c1()).invoke(mm::setC1_id) :
|
||||
competitionGuestRepository.findById(m.c1() * -1).invoke(mm::setC1_guest))
|
||||
.call(mm -> m.c2() >= 0 ?
|
||||
combRepository.findById(m.c2()).invoke(mm::setC2_id) :
|
||||
competitionGuestRepository.findById(m.c2() * -1).invoke(mm::setC2_guest));
|
||||
}
|
||||
|
||||
@WSReceiver(code = "addMatch", permission = PermLevel.ADMIN)
|
||||
public Uni<Void> addMatch(WebSocketConnection connection, AddMatch m) {
|
||||
return categoryRepository.findById(m.categorie)
|
||||
.invoke(Unchecked.consumer(o -> {
|
||||
if (o == null)
|
||||
throw new DNotFoundException("Catégorie non trouver");
|
||||
if (!o.getCompet().getUuid().equals(connection.pathParam("uuid")))
|
||||
throw new DForbiddenException("Permission denied");
|
||||
}))
|
||||
.chain(categoryModel -> creatMatch(categoryModel, m))
|
||||
.chain(mm -> Panache.withTransaction(() -> matchRepository.create(mm)))
|
||||
.call(mm -> SSMatch.sendMatch(connection, MatchEntity.fromModel(mm)))
|
||||
.replaceWithVoid();
|
||||
}
|
||||
|
||||
@WSReceiver(code = "updateMatchComb", permission = PermLevel.ADMIN)
|
||||
public Uni<Void> updateMatchComb(WebSocketConnection connection, MatchComb match) {
|
||||
return getById(match.id(), connection)
|
||||
.call(mm -> match.c1() != null ?
|
||||
match.c1() >= 0 ?
|
||||
combRepository.findById(match.c1()).invoke(model -> {
|
||||
mm.setC1_id(model);
|
||||
mm.setC1_guest(null);
|
||||
}) :
|
||||
competitionGuestRepository.findById(match.c1() * -1).invoke(model -> {
|
||||
mm.setC1_id(null);
|
||||
mm.setC1_guest(model);
|
||||
|
||||
}) :
|
||||
Uni.createFrom().nullItem().invoke(__ -> {
|
||||
mm.setC1_id(null);
|
||||
mm.setC1_guest(null);
|
||||
}))
|
||||
.call(mm -> match.c2() != null ?
|
||||
match.c2() >= 0 ?
|
||||
combRepository.findById(match.c2()).invoke(model -> {
|
||||
mm.setC2_id(model);
|
||||
mm.setC2_guest(null);
|
||||
}) :
|
||||
competitionGuestRepository.findById(match.c2() * -1).invoke(model -> {
|
||||
mm.setC2_id(null);
|
||||
mm.setC2_guest(model);
|
||||
}) :
|
||||
Uni.createFrom().nullItem().invoke(__ -> {
|
||||
mm.setC2_id(null);
|
||||
mm.setC2_guest(null);
|
||||
}))
|
||||
.chain(mm -> Panache.withTransaction(() -> matchRepository.persist(mm)))
|
||||
.call(mm -> SSMatch.sendMatch(connection, MatchEntity.fromModel(mm)))
|
||||
.replaceWithVoid();
|
||||
}
|
||||
|
||||
@WSReceiver(code = "updateMatchOrder", permission = PermLevel.ADMIN)
|
||||
public Uni<Void> updateMatchComb(WebSocketConnection connection, MatchOrder order) {
|
||||
return getById(order.id(), connection)
|
||||
.call(m -> matchRepository.update(
|
||||
"category_ord = category_ord + 1 WHERE category_ord >= ?1 AND category_ord < ?2", order.pos,
|
||||
m.getCategory_ord()))
|
||||
.call(m -> matchRepository.update(
|
||||
"category_ord = category_ord - 1 WHERE category_ord <= ?1 AND category_ord > ?2", order.pos,
|
||||
m.getCategory_ord()))
|
||||
.invoke(m -> m.setCategory_ord(order.pos))
|
||||
.call(m -> Panache.withTransaction(() -> matchRepository.persist(m)))
|
||||
.call(mm -> SSMatch.sendMatchOrder(connection, order))
|
||||
.replaceWithVoid();
|
||||
}
|
||||
|
||||
@WSReceiver(code = "updateMatchScore", permission = PermLevel.TABLE)
|
||||
public Uni<Void> updateMatchScore(WebSocketConnection connection, MatchScore score) {
|
||||
return getById(score.matchId(), connection)
|
||||
.chain(matchModel -> {
|
||||
int old_win = matchModel.win();
|
||||
Optional<ScoreEmbeddable> optional = matchModel.getScores().stream()
|
||||
.filter(s -> s.getN_round() == score.n_round()).findAny();
|
||||
boolean b = score.s1() != -1000 || score.s2() != -1000;
|
||||
if (optional.isPresent()) {
|
||||
if (b) {
|
||||
optional.get().setS1(score.s1());
|
||||
optional.get().setS2(score.s2());
|
||||
} else {
|
||||
matchModel.getScores().remove(optional.get());
|
||||
}
|
||||
} else if (b) {
|
||||
matchModel.getScores().add(new ScoreEmbeddable(score.n_round(), score.s1(), score.s2()));
|
||||
}
|
||||
|
||||
return Panache.withTransaction(() -> matchRepository.persist(matchModel))
|
||||
.call(mm -> {
|
||||
if (mm.isEnd() && mm.win() != old_win && mm.getCategory_ord() == -42) {
|
||||
return updateEndAndTree(mm, new ArrayList<>())
|
||||
.call(l -> SSMatch.sendMatch(connection, l));
|
||||
}
|
||||
return Uni.createFrom().nullItem();
|
||||
});
|
||||
})
|
||||
.call(mm -> SSMatch.sendMatch(connection, MatchEntity.fromModel(mm)))
|
||||
.replaceWithVoid();
|
||||
}
|
||||
|
||||
@WSReceiver(code = "updateMatchEnd", permission = PermLevel.TABLE)
|
||||
public Uni<Void> updateMatchEnd(WebSocketConnection connection, MatchEnd matchEnd) {
|
||||
List<MatchEntity> toSend = new ArrayList<>();
|
||||
|
||||
return getById(matchEnd.matchId(), connection)
|
||||
.chain(mm -> {
|
||||
if (mm.getCategory_ord() == -42 && mm.win() == 0) { // Tournois
|
||||
mm.setDate(null);
|
||||
mm.setEnd(false);
|
||||
} else {
|
||||
mm.setDate((matchEnd.end) ? new Date() : null);
|
||||
mm.setEnd(matchEnd.end);
|
||||
}
|
||||
return Panache.withTransaction(() -> matchRepository.persist(mm));
|
||||
})
|
||||
.invoke(mm -> toSend.add(MatchEntity.fromModel(mm)))
|
||||
.chain(mm -> updateEndAndTree(mm, toSend))
|
||||
.call(__ -> SSMatch.sendMatch(connection, toSend))
|
||||
.replaceWithVoid();
|
||||
}
|
||||
|
||||
private Uni<List<MatchEntity>> updateEndAndTree(MatchModel mm, List<MatchEntity> toSend) {
|
||||
return (mm.getCategory_ord() != -42) ?
|
||||
Uni.createFrom().item(toSend) :
|
||||
treeRepository.list("category = ?1 AND level != 0", Sort.ascending("level"), mm.getCategory().getId())
|
||||
.chain(treeModels -> {
|
||||
List<TreeModel> node = treeModels.stream().flatMap(t -> t.flat().stream()).toList();
|
||||
List<TreeEntity> trees = treeModels.stream().map(TreeEntity::fromModel).toList();
|
||||
for (int i = 0; i < trees.size() - 1; i++) {
|
||||
TreeEntity.setAssociated(trees.get(i), trees.get(i + 1));
|
||||
}
|
||||
|
||||
TreeEntity root = trees.stream()
|
||||
.filter(t -> t.getMatchNode(mm.getId()) != null)
|
||||
.findFirst()
|
||||
.orElseThrow();
|
||||
|
||||
TreeEntity currentNode = root.getMatchNode(mm.getId());
|
||||
if (currentNode == null) {
|
||||
LOGGER.error(
|
||||
"currentNode is empty for " + mm.getId() + " in " + mm.getCategory().getId());
|
||||
return Uni.createFrom().voidItem();
|
||||
}
|
||||
|
||||
TreeEntity parent = TreeEntity.getParent(root, currentNode);
|
||||
if (parent == null) {
|
||||
LOGGER.error("parent is empty for " + mm.getId() + " in " + mm.getCategory().getId());
|
||||
return Uni.createFrom().voidItem();
|
||||
}
|
||||
|
||||
int w = mm.win();
|
||||
MembreModel toSetWin = null;
|
||||
MembreModel toSetLose = null;
|
||||
CompetitionGuestModel toSetWinGuest = null;
|
||||
CompetitionGuestModel toSetLoseGuest = null;
|
||||
|
||||
if (mm.isEnd() && w != 0) {
|
||||
toSetWin = (w > 0) ? mm.getC1_id() : mm.getC2_id();
|
||||
toSetLose = (w > 0) ? mm.getC2_id() : mm.getC1_id();
|
||||
toSetWinGuest = (w > 0) ? mm.getC1_guest() : mm.getC2_guest();
|
||||
toSetLoseGuest = (w > 0) ? mm.getC2_guest() : mm.getC1_guest();
|
||||
}
|
||||
|
||||
MatchModel modelWin = node.stream()
|
||||
.filter(n -> Objects.equals(n.getId(), parent.getId()))
|
||||
.findAny()
|
||||
.map(TreeModel::getMatch)
|
||||
.orElseThrow();
|
||||
|
||||
MatchModel modelLose = (parent.getAssociatedNode() == null) ? null : node.stream()
|
||||
.filter(n -> Objects.equals(n.getId(), parent.getAssociatedNode().getId()))
|
||||
.findAny()
|
||||
.map(TreeModel::getMatch)
|
||||
.orElseThrow();
|
||||
|
||||
if (currentNode.equals(parent.getLeft())) {
|
||||
modelWin.setC1_id(toSetWin);
|
||||
modelWin.setC1_guest(toSetWinGuest);
|
||||
if (modelLose != null) {
|
||||
modelLose.setC1_id(toSetLose);
|
||||
modelLose.setC1_guest(toSetLoseGuest);
|
||||
}
|
||||
} else if (currentNode.equals(parent.getRight())) {
|
||||
modelWin.setC2_id(toSetWin);
|
||||
modelWin.setC2_guest(toSetWinGuest);
|
||||
if (modelLose != null) {
|
||||
modelLose.setC2_id(toSetLose);
|
||||
modelLose.setC2_guest(toSetLoseGuest);
|
||||
}
|
||||
}
|
||||
|
||||
return Panache.withTransaction(() -> matchRepository.persist(modelWin)
|
||||
.invoke(mm2 -> toSend.add(MatchEntity.fromModel(mm2)))
|
||||
.call(__ -> modelLose == null ? Uni.createFrom().nullItem() :
|
||||
matchRepository.persist(modelLose)
|
||||
.invoke(mm2 -> toSend.add(MatchEntity.fromModel(mm2)))
|
||||
)
|
||||
.replaceWithVoid());
|
||||
})
|
||||
.map(__ -> toSend);
|
||||
}
|
||||
|
||||
@WSReceiver(code = "deleteMatch", permission = PermLevel.ADMIN)
|
||||
public Uni<Void> deleteMatch(WebSocketConnection connection, Long idMatch) {
|
||||
return getById(idMatch, connection)
|
||||
.chain(matchModel -> Panache.withTransaction(() -> matchRepository.delete(matchModel)))
|
||||
.call(__ -> SSMatch.sendDeleteMatch(connection, idMatch))
|
||||
.replaceWithVoid();
|
||||
}
|
||||
|
||||
@WSReceiver(code = "recalculateMatch", permission = PermLevel.ADMIN)
|
||||
public Uni<Void> recalculateMatch(WebSocketConnection connection, RecalculateMatch data) {
|
||||
ArrayList<MatchEntity> matches = new ArrayList<>();
|
||||
return categoryRepository.findById(data.categorie)
|
||||
.invoke(Unchecked.consumer(o -> {
|
||||
if (o == null)
|
||||
throw new DNotFoundException("Catégorie non trouver");
|
||||
if (!o.getCompet().getUuid().equals(connection.pathParam("uuid")))
|
||||
throw new DForbiddenException("Permission denied");
|
||||
}))
|
||||
.call(cm -> matchRepository.delete("id IN ?1 AND category = ?2", data.matchesToRemove, cm)
|
||||
.call(__ -> SSMatch.sendDeleteMatch(connection, data.matchesToRemove)))
|
||||
.call(cm -> matchRepository.list("id IN ?1 AND category = ?2",
|
||||
Stream.concat(data.matchOrderToUpdate.keySet().stream(),
|
||||
data.matchPouleToUpdate.keySet().stream())
|
||||
.distinct().toList(), cm)
|
||||
.invoke(matchModels -> matchModels.forEach(model -> {
|
||||
if (data.matchPouleToUpdate.containsKey(model.getId()))
|
||||
model.setPoule(data.matchPouleToUpdate.get(model.getId()));
|
||||
if (data.matchOrderToUpdate.containsKey(model.getId()))
|
||||
model.setCategory_ord(data.matchOrderToUpdate.get(model.getId()));
|
||||
}))
|
||||
.call(mm -> Panache.withTransaction(() -> matchRepository.persist(mm)))
|
||||
.invoke(mm -> matches.addAll(mm.stream().map(MatchEntity::fromModel).toList()))
|
||||
)
|
||||
.chain(categoryModel -> {
|
||||
Uni<List<MatchModel>> uni = Uni.createFrom().item(new ArrayList<>());
|
||||
for (AddMatch match : data.newMatch)
|
||||
uni = uni.call(l -> creatMatch(categoryModel, match).invoke(l::add));
|
||||
return uni;
|
||||
}
|
||||
)
|
||||
.chain(mm -> Panache.withTransaction(() -> matchRepository.create(mm))
|
||||
.invoke(__ -> matches.addAll(mm.stream().map(MatchEntity::fromModel).toList())))
|
||||
.call(__ -> SSMatch.sendMatch(connection, matches))
|
||||
.replaceWithVoid();
|
||||
}
|
||||
|
||||
@RegisterForReflection
|
||||
public record MatchComb(long id, Long c1, Long c2) {
|
||||
}
|
||||
|
||||
@RegisterForReflection
|
||||
public record MatchScore(long matchId, int n_round, int s1, int s2) {
|
||||
}
|
||||
|
||||
@RegisterForReflection
|
||||
public record MatchEnd(long matchId, boolean end) {
|
||||
}
|
||||
|
||||
@RegisterForReflection
|
||||
public record MatchOrder(long id, long pos) {
|
||||
}
|
||||
|
||||
@RegisterForReflection
|
||||
public record AddMatch(long categorie, long categorie_ord, char poule, long c1, long c2) {
|
||||
}
|
||||
|
||||
public record RecalculateMatch(long categorie, List<AddMatch> newMatch, HashMap<Long, Integer> matchOrderToUpdate,
|
||||
HashMap<Long, Character> matchPouleToUpdate, List<Long> matchesToRemove) {
|
||||
}
|
||||
}
|
||||
37
src/main/java/fr/titionfire/ffsaf/ws/recv/RRegister.java
Normal file
37
src/main/java/fr/titionfire/ffsaf/ws/recv/RRegister.java
Normal file
@@ -0,0 +1,37 @@
|
||||
package fr.titionfire.ffsaf.ws.recv;
|
||||
|
||||
import fr.titionfire.ffsaf.data.repository.CompetitionRepository;
|
||||
import fr.titionfire.ffsaf.domain.entity.CombEntity;
|
||||
import fr.titionfire.ffsaf.ws.PermLevel;
|
||||
import io.quarkus.hibernate.reactive.panache.common.WithSession;
|
||||
import io.quarkus.runtime.annotations.RegisterForReflection;
|
||||
import io.quarkus.websockets.next.WebSocketConnection;
|
||||
import io.smallrye.mutiny.Uni;
|
||||
import jakarta.enterprise.context.ApplicationScoped;
|
||||
import jakarta.inject.Inject;
|
||||
import org.hibernate.reactive.mutiny.Mutiny;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@WithSession
|
||||
@ApplicationScoped
|
||||
@RegisterForReflection
|
||||
public class RRegister {
|
||||
|
||||
@Inject
|
||||
CompetitionRepository competitionRepository;
|
||||
|
||||
@WSReceiver(code = "getRegister", permission = PermLevel.TABLE)
|
||||
public Uni<List<CombEntity>> getRegister(WebSocketConnection connection, Object o) {
|
||||
return competitionRepository.find("uuid", connection.pathParam("uuid")).firstResult()
|
||||
.call(cm -> Mutiny.fetch(cm.getInsc()))
|
||||
.call(cm -> Mutiny.fetch(cm.getGuests()))
|
||||
.map(cm -> {
|
||||
ArrayList<CombEntity> combEntities = new ArrayList<>();
|
||||
combEntities.addAll(cm.getInsc().stream().map(CombEntity::fromModel).toList());
|
||||
combEntities.addAll(cm.getGuests().stream().map(CombEntity::fromModel).toList());
|
||||
return combEntities;
|
||||
});
|
||||
}
|
||||
}
|
||||
17
src/main/java/fr/titionfire/ffsaf/ws/recv/WSReceiver.java
Normal file
17
src/main/java/fr/titionfire/ffsaf/ws/recv/WSReceiver.java
Normal file
@@ -0,0 +1,17 @@
|
||||
package fr.titionfire.ffsaf.ws.recv;
|
||||
|
||||
import fr.titionfire.ffsaf.ws.PermLevel;
|
||||
import io.quarkus.runtime.annotations.RegisterForReflection;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
|
||||
@RegisterForReflection
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface WSReceiver {
|
||||
|
||||
String code();
|
||||
|
||||
PermLevel permission() default PermLevel.VIEW;
|
||||
|
||||
}
|
||||
33
src/main/java/fr/titionfire/ffsaf/ws/send/JsonUni.java
Normal file
33
src/main/java/fr/titionfire/ffsaf/ws/send/JsonUni.java
Normal file
@@ -0,0 +1,33 @@
|
||||
package fr.titionfire.ffsaf.ws.send;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import io.quarkus.runtime.annotations.RegisterForReflection;
|
||||
import io.smallrye.mutiny.Uni;
|
||||
import io.smallrye.mutiny.unchecked.Unchecked;
|
||||
|
||||
import java.util.function.Function;
|
||||
|
||||
import static fr.titionfire.ffsaf.net2.Client_Thread.MAPPER;
|
||||
|
||||
@RegisterForReflection
|
||||
public class JsonUni<T> {
|
||||
|
||||
private final Class<T> clazz;
|
||||
private final Function<? super T, Uni<?>> mapper;
|
||||
|
||||
public JsonUni(Class<T> clazz, Function<? super T, Uni<?>> mapper) {
|
||||
this.clazz = clazz;
|
||||
this.mapper = mapper;
|
||||
}
|
||||
|
||||
public Uni<?> castAndChain(JsonNode message) throws JsonProcessingException {
|
||||
return Uni.createFrom().item(MAPPER.treeToValue(message, clazz)).chain(mapper);
|
||||
}
|
||||
|
||||
public Uni<?> castAndError(JsonNode message) throws JsonProcessingException {
|
||||
return Uni.createFrom().item((T) null).invoke(Unchecked.consumer(__ -> {
|
||||
throw new WSClientError(MAPPER.treeToValue(message, String.class));
|
||||
})).chain(mapper);
|
||||
}
|
||||
}
|
||||
53
src/main/java/fr/titionfire/ffsaf/ws/send/SRegister.java
Normal file
53
src/main/java/fr/titionfire/ffsaf/ws/send/SRegister.java
Normal file
@@ -0,0 +1,53 @@
|
||||
package fr.titionfire.ffsaf.ws.send;
|
||||
|
||||
import fr.titionfire.ffsaf.data.model.CompetitionGuestModel;
|
||||
import fr.titionfire.ffsaf.data.model.RegisterModel;
|
||||
import fr.titionfire.ffsaf.domain.entity.CombEntity;
|
||||
import fr.titionfire.ffsaf.net2.MessageType;
|
||||
import fr.titionfire.ffsaf.ws.CompetitionWS;
|
||||
import fr.titionfire.ffsaf.ws.MessageOut;
|
||||
import fr.titionfire.ffsaf.ws.PermLevel;
|
||||
import io.quarkus.runtime.annotations.RegisterForReflection;
|
||||
import io.quarkus.websockets.next.OpenConnections;
|
||||
import io.quarkus.websockets.next.UserData;
|
||||
import io.smallrye.mutiny.Uni;
|
||||
import jakarta.enterprise.context.ApplicationScoped;
|
||||
import jakarta.inject.Inject;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
@ApplicationScoped
|
||||
@RegisterForReflection
|
||||
public class SRegister {
|
||||
|
||||
@SuppressWarnings("CdiInjectionPointsInspection")
|
||||
@Inject
|
||||
OpenConnections connections;
|
||||
|
||||
public Uni<Void> sendRegister(String uuid, RegisterModel registerModel) {
|
||||
return send(uuid, "sendRegister", CombEntity.fromModel(registerModel));
|
||||
}
|
||||
|
||||
public Uni<Void> sendRegister(String uuid, CompetitionGuestModel model) {
|
||||
return send(uuid, "sendRegister", CombEntity.fromModel(model));
|
||||
}
|
||||
|
||||
public Uni<Void> sendRegisterRemove(String uuid, Long combId) {
|
||||
return send(uuid, "sendRegisterRemove", combId);
|
||||
}
|
||||
|
||||
public Uni<Void> send(String uuid, String code, Object data) {
|
||||
List<Uni<Void>> queue = connections.findByEndpointId(CompetitionWS.class.getCanonicalName()).stream()
|
||||
.filter(c -> c.pathParam("uuid").equals(uuid) && PermLevel.valueOf(
|
||||
c.userData().get(UserData.TypedKey.forString("prem"))).ordinal() >= PermLevel.TABLE.ordinal())
|
||||
.map(c -> c.sendText(
|
||||
new MessageOut(UUID.randomUUID(), code, MessageType.NOTIFY, data)))
|
||||
.toList();
|
||||
|
||||
if (queue.isEmpty())
|
||||
return Uni.createFrom().voidItem();
|
||||
return Uni.join().all(queue).andCollectFailures().replaceWithVoid();
|
||||
}
|
||||
|
||||
}
|
||||
13
src/main/java/fr/titionfire/ffsaf/ws/send/SSCardboard.java
Normal file
13
src/main/java/fr/titionfire/ffsaf/ws/send/SSCardboard.java
Normal file
@@ -0,0 +1,13 @@
|
||||
package fr.titionfire.ffsaf.ws.send;
|
||||
|
||||
import fr.titionfire.ffsaf.domain.entity.CardboardEntity;
|
||||
import fr.titionfire.ffsaf.ws.CompetitionWS;
|
||||
import io.quarkus.websockets.next.WebSocketConnection;
|
||||
import io.smallrye.mutiny.Uni;
|
||||
|
||||
public class SSCardboard {
|
||||
|
||||
public static Uni<Void> sendCardboard(WebSocketConnection connection, CardboardEntity cardboardEntity) {
|
||||
return CompetitionWS.sendNotifyToOtherEditor(connection, "sendCardboard", cardboardEntity);
|
||||
}
|
||||
}
|
||||
33
src/main/java/fr/titionfire/ffsaf/ws/send/SSCategorie.java
Normal file
33
src/main/java/fr/titionfire/ffsaf/ws/send/SSCategorie.java
Normal file
@@ -0,0 +1,33 @@
|
||||
package fr.titionfire.ffsaf.ws.send;
|
||||
|
||||
import fr.titionfire.ffsaf.data.model.CategoryModel;
|
||||
import fr.titionfire.ffsaf.domain.entity.TreeEntity;
|
||||
import fr.titionfire.ffsaf.ws.CompetitionWS;
|
||||
import fr.titionfire.ffsaf.ws.recv.RCategorie;
|
||||
import io.quarkus.websockets.next.WebSocketConnection;
|
||||
import io.smallrye.mutiny.Uni;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class SSCategorie {
|
||||
|
||||
public static Uni<Void> sendAddCategory(WebSocketConnection connection, CategoryModel category) {
|
||||
return SSCategorie.sendAddCategory(connection, RCategorie.JustCategorie.from(category));
|
||||
}
|
||||
|
||||
public static Uni<Void> sendAddCategory(WebSocketConnection connection, RCategorie.JustCategorie justCategorie) {
|
||||
return CompetitionWS.sendNotifyToOtherEditor(connection, "sendAddCategory", justCategorie);
|
||||
}
|
||||
|
||||
public static Uni<Void> sendCategory(WebSocketConnection connection, CategoryModel category) {
|
||||
return SSCategorie.sendCategory(connection, RCategorie.JustCategorie.from(category));
|
||||
}
|
||||
|
||||
public static Uni<Void> sendCategory(WebSocketConnection connection, RCategorie.JustCategorie justCategorie) {
|
||||
return CompetitionWS.sendNotifyToOtherEditor(connection, "sendCategory", justCategorie);
|
||||
}
|
||||
|
||||
public static Uni<Void> sendTreeCategory(WebSocketConnection connection, List<TreeEntity> treeEntities) {
|
||||
return CompetitionWS.sendNotifyToOtherEditor(connection, "sendTreeCategory", treeEntities);
|
||||
}
|
||||
}
|
||||
32
src/main/java/fr/titionfire/ffsaf/ws/send/SSMatch.java
Normal file
32
src/main/java/fr/titionfire/ffsaf/ws/send/SSMatch.java
Normal file
@@ -0,0 +1,32 @@
|
||||
package fr.titionfire.ffsaf.ws.send;
|
||||
|
||||
import fr.titionfire.ffsaf.domain.entity.MatchEntity;
|
||||
import fr.titionfire.ffsaf.ws.CompetitionWS;
|
||||
import fr.titionfire.ffsaf.ws.recv.RMatch;
|
||||
import io.quarkus.websockets.next.WebSocketConnection;
|
||||
import io.smallrye.mutiny.Uni;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class SSMatch {
|
||||
|
||||
public static Uni<Void> sendMatch(WebSocketConnection connection, MatchEntity matchEntity) {
|
||||
return SSMatch.sendMatch(connection, List.of(matchEntity));
|
||||
}
|
||||
|
||||
public static Uni<Void> sendMatch(WebSocketConnection connection, List<MatchEntity> matchEntities) {
|
||||
return CompetitionWS.sendNotifyToOtherEditor(connection, "sendMatch", matchEntities);
|
||||
}
|
||||
|
||||
public static Uni<Void> sendMatchOrder(WebSocketConnection connection, RMatch.MatchOrder matchOrder) {
|
||||
return CompetitionWS.sendNotifyToOtherEditor(connection, "sendMatchOrder", matchOrder);
|
||||
}
|
||||
|
||||
public static Uni<Void> sendDeleteMatch(WebSocketConnection connection, Long l) {
|
||||
return SSMatch.sendDeleteMatch(connection, List.of(l));
|
||||
}
|
||||
|
||||
public static Uni<Void> sendDeleteMatch(WebSocketConnection connection, List<Long> longs) {
|
||||
return CompetitionWS.sendNotifyToOtherEditor(connection, "sendDeleteMatch", longs);
|
||||
}
|
||||
}
|
||||
13
src/main/java/fr/titionfire/ffsaf/ws/send/WSClientError.java
Normal file
13
src/main/java/fr/titionfire/ffsaf/ws/send/WSClientError.java
Normal file
@@ -0,0 +1,13 @@
|
||||
package fr.titionfire.ffsaf.ws.send;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.Serial;
|
||||
|
||||
public class WSClientError extends IOException {
|
||||
@Serial
|
||||
private static final long serialVersionUID = -3790479241838684450L;
|
||||
|
||||
public WSClientError(String message) {
|
||||
super(message);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user