Skip to content

Commit 54fa87a

Browse files
Merge pull request #652 from softwaremagico/650-undraws-no-sync
650-undraws-no-sync
2 parents 43b0a5d + 533569d commit 54fa87a

File tree

13 files changed

+152
-61
lines changed

13 files changed

+152
-61
lines changed

backend/kendo-tournament-core/src/main/java/com/softwaremagico/kt/core/controller/DuelController.java

Lines changed: 30 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,6 @@
3030
import com.softwaremagico.kt.core.converters.models.DuelConverterRequest;
3131
import com.softwaremagico.kt.core.converters.models.FightConverterRequest;
3232
import com.softwaremagico.kt.core.converters.models.TournamentConverterRequest;
33-
import com.softwaremagico.kt.core.exceptions.FightNotFoundException;
3433
import com.softwaremagico.kt.core.exceptions.ParticipantNotFoundException;
3534
import com.softwaremagico.kt.core.exceptions.TournamentNotFoundException;
3635
import com.softwaremagico.kt.core.exceptions.ValidateBadRequestException;
@@ -68,6 +67,7 @@ public class DuelController extends BasicInsertableController<Duel, DuelDTO, Due
6867

6968
private final Set<ShiaijoFinishedListener> shiaijoFinishedListeners = new HashSet<>();
7069
private final Set<FightUpdatedListener> fightsUpdatedListeners = new HashSet<>();
70+
private final Set<UntieUpdatedListener> untiesUpdatedListeners = new HashSet<>();
7171

7272
public interface ShiaijoFinishedListener {
7373
void finished(TournamentDTO tournament, Integer shiaijo);
@@ -77,6 +77,10 @@ public interface FightUpdatedListener {
7777
void finished(TournamentDTO tournament, FightDTO fight, DuelDTO duel, String actor, String session);
7878
}
7979

80+
public interface UntieUpdatedListener {
81+
void finished(TournamentDTO tournament, DuelDTO duel, String actor, String session);
82+
}
83+
8084
@Autowired
8185
public DuelController(DuelProvider provider,
8286
DuelConverter converter,
@@ -100,6 +104,10 @@ public void addFightUpdatedListener(FightUpdatedListener listener) {
100104
fightsUpdatedListeners.add(listener);
101105
}
102106

107+
public void addUntieUpdatedListener(UntieUpdatedListener listener) {
108+
untiesUpdatedListeners.add(listener);
109+
}
110+
103111
@Override
104112
protected DuelConverterRequest createConverterRequest(Duel entity) {
105113
return new DuelConverterRequest(entity);
@@ -127,27 +135,34 @@ public DuelDTO update(DuelDTO duel, String username, String session) {
127135
} finally {
128136
new Thread(() -> {
129137
//If a shiaijo has finished, send a message to all computers.
130-
final Fight fight = fightProvider.findByDuels(reverse(duel)).orElseThrow(() ->
131-
new FightNotFoundException(this.getClass(), "No fight found for duel '" + duel + "'"));
138+
final Fight fight = fightProvider.findByDuels(reverse(duel)).orElse(null);
132139

133-
final FightDTO fightDTO = fightConverter.convert(new FightConverterRequest(fight));
134140

135-
final Tournament tournament = tournamentProvider.get(fight.getTournament().getId()).orElseThrow(()
141+
final Tournament tournament = tournamentProvider.get(duel.getTournament().getId()).orElseThrow(()
136142
-> new TournamentNotFoundException(this.getClass(), "No tournament found for duel '" + duel + "'."));
137143

138144
final TournamentDTO tournamentDTO = tournamentConverter.convert(new TournamentConverterRequest(tournament));
139145

140-
//Fight is updated, refresh screens.
141-
fightsUpdatedListeners.forEach(fightUpdatedListener ->
142-
fightUpdatedListener.finished(tournamentDTO, fightDTO, duel, username, session));
143-
144-
if (tournament.getShiaijos() > 1) {
145-
final List<Fight> fightsOfShiaijo = fightProvider.findByTournamentAndShiaijo(tournament, fight.getShiaijo());
146-
final long fightsNotOver = fightsOfShiaijo.stream().filter(fightOfShiaijo -> !fightOfShiaijo.isOver()).count();
147-
if (fightsNotOver == 0) {
148-
shiaijoFinishedListeners.forEach(shiaijoFinishedListener
149-
-> shiaijoFinishedListener.finished(tournamentDTO, fight.getShiaijo()));
146+
//Standard fight.
147+
if (fight != null) {
148+
final FightDTO fightDTO = fightConverter.convert(new FightConverterRequest(fight));
149+
150+
//Fight is updated, refresh screens.
151+
fightsUpdatedListeners.forEach(fightUpdatedListener ->
152+
fightUpdatedListener.finished(tournamentDTO, fightDTO, duel, username, session));
153+
154+
if (tournament.getShiaijos() > 1) {
155+
final List<Fight> fightsOfShiaijo = fightProvider.findByTournamentAndShiaijo(tournament, fight.getShiaijo());
156+
final long fightsNotOver = fightsOfShiaijo.stream().filter(fightOfShiaijo -> !fightOfShiaijo.isOver()).count();
157+
if (fightsNotOver == 0) {
158+
shiaijoFinishedListeners.forEach(shiaijoFinishedListener
159+
-> shiaijoFinishedListener.finished(tournamentDTO, fight.getShiaijo()));
160+
}
150161
}
162+
} else {
163+
//It is an untie duel!
164+
untiesUpdatedListeners.forEach(untieUpdatedListener ->
165+
untieUpdatedListener.finished(tournamentDTO, duel, username, session));
151166
}
152167
}).start();
153168
}

backend/kendo-tournament-core/src/main/java/com/softwaremagico/kt/core/controller/GroupController.java

Lines changed: 33 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -38,11 +38,11 @@
3838
import com.softwaremagico.kt.core.providers.DuelProvider;
3939
import com.softwaremagico.kt.core.providers.FightProvider;
4040
import com.softwaremagico.kt.core.providers.GroupProvider;
41-
import com.softwaremagico.kt.core.providers.TournamentExtraPropertyProvider;
4241
import com.softwaremagico.kt.core.providers.TournamentProvider;
4342
import com.softwaremagico.kt.core.tournaments.TournamentHandlerSelector;
4443
import com.softwaremagico.kt.logger.ExceptionType;
4544
import com.softwaremagico.kt.persistence.entities.Group;
45+
import com.softwaremagico.kt.persistence.entities.Tournament;
4646
import com.softwaremagico.kt.persistence.repositories.GroupRepository;
4747
import jakarta.transaction.Transactional;
4848
import org.springframework.beans.factory.annotation.Autowired;
@@ -64,21 +64,24 @@ public class GroupController extends BasicInsertableController<Group, GroupDTO,
6464
private final DuelConverter duelConverter;
6565
private final TeamConverter teamConverter;
6666
private final TournamentHandlerSelector tournamentHandlerSelector;
67-
private final TournamentExtraPropertyProvider tournamentExtraPropertyProvider;
68-
67+
private final Set<UntieUpdatedListener> untiesUpdatedListeners = new HashSet<>();
6968
private final Set<GroupsUpdatedListener> groupsUpdatedListeners = new HashSet<>();
7069

7170

7271
public interface GroupsUpdatedListener {
7372
void updated(TournamentDTO tournament, String actor, String session);
7473
}
7574

75+
public interface UntieUpdatedListener {
76+
void finished(TournamentDTO tournament, DuelDTO duel, String actor, String session);
77+
}
78+
7679

7780
@Autowired
7881
public GroupController(GroupProvider provider, GroupConverter converter, TournamentConverter tournamentConverter,
7982
TournamentProvider tournamentProvider, FightProvider fightProvider, FightConverter fightConverter,
8083
DuelProvider duelProvider, DuelConverter duelConverter, TeamConverter teamConverter,
81-
TournamentHandlerSelector tournamentHandlerSelector, TournamentExtraPropertyProvider tournamentExtraPropertyProvider) {
84+
TournamentHandlerSelector tournamentHandlerSelector) {
8285
super(provider, converter);
8386
this.tournamentConverter = tournamentConverter;
8487
this.tournamentProvider = tournamentProvider;
@@ -88,14 +91,17 @@ public GroupController(GroupProvider provider, GroupConverter converter, Tournam
8891
this.duelConverter = duelConverter;
8992
this.teamConverter = teamConverter;
9093
this.tournamentHandlerSelector = tournamentHandlerSelector;
91-
this.tournamentExtraPropertyProvider = tournamentExtraPropertyProvider;
9294
}
9395

9496

9597
public void addGroupUpdatedListeners(GroupsUpdatedListener listener) {
9698
groupsUpdatedListeners.add(listener);
9799
}
98100

101+
public void addUntieUpdatedListener(UntieUpdatedListener listener) {
102+
untiesUpdatedListeners.add(listener);
103+
}
104+
99105

100106
@Override
101107
protected GroupConverterRequest createConverterRequest(Group group) {
@@ -203,6 +209,9 @@ public GroupDTO update(GroupDTO groupDTO, String username, String session) {
203209
groupsUpdatedListeners.forEach(groupsUpdatedListener ->
204210
groupsUpdatedListener.updated(groupDTO.getTournament(), username, session))
205211
).start();
212+
if (!unties.isEmpty()) {
213+
sendUntieChangeMessageThroughWebsocket(unties, username, session);
214+
}
206215
}
207216
}
208217

@@ -289,15 +298,32 @@ public GroupDTO setTeams(List<TeamDTO> teams, String username, String session) {
289298
}
290299

291300

292-
public GroupDTO addUnties(Integer groupId, List<DuelDTO> duelDTOS, String username) {
301+
public GroupDTO addUnties(Integer groupId, List<DuelDTO> duelDTOS, String username, String session) {
293302
final GroupDTO groupDTO = get(groupId);
294303
duelDTOS.forEach(duelDTO -> {
295304
duelDTO.setCreatedBy(username);
296305
duelDTO.setTournament(groupDTO.getTournament());
297306
});
298307
groupDTO.getUnties().addAll(duelDTOS);
299308
groupDTO.setUpdatedBy(username);
300-
return convert(getProvider().save(reverse(groupDTO)));
309+
try {
310+
return convert(getProvider().save(reverse(groupDTO)));
311+
} finally {
312+
//Send update information to all devices.
313+
sendUntieChangeMessageThroughWebsocket(duelDTOS, username, session);
314+
}
315+
}
316+
317+
private void sendUntieChangeMessageThroughWebsocket(List<DuelDTO> duelDTOS, String username, String session) {
318+
new Thread(() -> {
319+
for (DuelDTO duelDTO : duelDTOS) {
320+
final Tournament tournament = tournamentProvider.get(duelDTO.getTournament().getId()).orElseThrow(()
321+
-> new TournamentNotFoundException(this.getClass(), "No tournament found for duel '" + duelDTO + "'."));
322+
final TournamentDTO tournamentDTO = tournamentConverter.convert(new TournamentConverterRequest(tournament));
323+
untiesUpdatedListeners.forEach(untieUpdatedListener ->
324+
untieUpdatedListener.finished(tournamentDTO, duelDTO, username, session));
325+
}
326+
}).start();
301327
}
302328

303329

backend/kendo-tournament-rest/src/main/java/com/softwaremagico/kt/rest/services/GroupServices.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -168,9 +168,10 @@ public GroupDTO updateTeam(@RequestBody List<TeamDTO> teamsDto,
168168
@PutMapping(value = "/{groupId}/unties", produces = MediaType.APPLICATION_JSON_VALUE)
169169
public GroupDTO addUnties(@Parameter(description = "Id of the group to update", required = true) @PathVariable("groupId") Integer groupId,
170170
@RequestBody List<DuelDTO> duelDTOs,
171+
@RequestHeader(value = AuthApi.SESSION_HEADER, required = false) String session,
171172
Authentication authentication,
172173
HttpServletRequest request) {
173-
return getController().addUnties(groupId, duelDTOs, authentication.getName());
174+
return getController().addUnties(groupId, duelDTOs, authentication.getName(), session);
174175
}
175176

176177
@PreAuthorize("hasAnyAuthority(@securityService.viewerPrivilege, @securityService.editorPrivilege, @securityService.adminPrivilege)")

backend/kendo-tournament-rest/src/main/java/com/softwaremagico/kt/websockets/WebSocketController.java

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,10 +23,12 @@
2323

2424
import com.fasterxml.jackson.core.JsonProcessingException;
2525
import com.fasterxml.jackson.databind.ObjectMapper;
26+
import com.softwaremagico.kt.core.controller.models.DuelDTO;
2627
import com.softwaremagico.kt.core.controller.models.ElementDTO;
2728
import com.softwaremagico.kt.core.controller.models.FightDTO;
2829
import com.softwaremagico.kt.core.controller.models.TournamentDTO;
2930
import com.softwaremagico.kt.logger.WebsocketsLogger;
31+
import com.softwaremagico.kt.persistence.entities.Duel;
3032
import com.softwaremagico.kt.persistence.entities.Fight;
3133
import com.softwaremagico.kt.persistence.entities.Group;
3234
import com.softwaremagico.kt.websockets.models.MessageContent;
@@ -45,6 +47,7 @@
4547
public class WebSocketController {
4648

4749
public static final String FIGHTS_MAPPING = "/fights";
50+
public static final String UNTIES_MAPPING = "/unties";
4851
public static final String GROUPS_MAPPING = "/groups";
4952
public static final String CREATING_MAPPING = "/creates";
5053
public static final String UPDATING_MAPPING = "/updates";
@@ -142,6 +145,21 @@ public void fightsCreated(@Payload List<FightDTO> fights, String actor, String s
142145
}
143146
}
144147

148+
/**
149+
* Sends a duelDTO to {@value com.softwaremagico.kt.websockets.WebSocketConfiguration#SOCKET_SEND_PREFIX} + {@value #UNTIES_MAPPING}.
150+
*
151+
* @param duelDTO the duelDTO to send.
152+
*/
153+
public void untieUpdated(@Payload DuelDTO duelDTO, String actor, String session) {
154+
try {
155+
WebsocketsLogger.debug(this.getClass(), "Sending duelDTO '{}'.", duelDTO);
156+
this.messagingTemplate.convertAndSend(WebSocketConfiguration.SOCKET_SEND_PREFIX + UNTIES_MAPPING,
157+
new MessageContent(Duel.class.getSimpleName(), toJson(duelDTO), MessageContentType.UPDATED, actor, session));
158+
} catch (Exception e) {
159+
WebsocketsLogger.errorMessage(this.getClass(), e);
160+
}
161+
}
162+
145163
/**
146164
* Advise that the groups of a tournament has been updated {@value com.softwaremagico.kt.websockets.WebSocketConfiguration#SOCKET_SEND_PREFIX}
147165
* + {@value #GROUPS_MAPPING}.

backend/kendo-tournament-rest/src/main/java/com/softwaremagico/kt/websockets/WebsocketFights.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,8 @@ public WebsocketFights(DuelController duelController, FightController fightContr
3333
//Refresh screens when a duel is updated.
3434
duelController.addFightUpdatedListener(((tournament, fight, duel, actor, session) ->
3535
webSocketController.fightUpdated(fight, actor, session)));
36+
duelController.addUntieUpdatedListener(((tournament, duel, actor, session) ->
37+
webSocketController.untieUpdated(duel, actor, session)));
3638
fightController.addFightsAddedListeners((webSocketController::fightsCreated));
3739

3840
}

backend/kendo-tournament-rest/src/main/java/com/softwaremagico/kt/websockets/WebsocketGroups.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,8 @@ public WebsocketGroups(GroupController groupController, WebSocketController webS
3131

3232
//Refresh screens when a group is updated.
3333
groupController.addGroupUpdatedListeners(webSocketController::groupsUpdated);
34-
34+
groupController.addUntieUpdatedListener((tournament, duel, actor, session)
35+
-> webSocketController.untieUpdated(duel, actor, session));
3536
}
3637

3738
}

frontend/src/app/components/untie-fight/untie-fight.component.html

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
(click)="selectDuel(duel)"
88
(keydown)="selectDuel(duel)"
99
[selected]="selected" [swapTeams]="swapTeams"
10+
[projectMode]="projectMode"
1011
class="duel"></duel>
1112
</div>
1213
<div [class.red-ribbon]="swapColors" [class.white-ribbon]="!swapColors" class="right-team ribbon-icon">

frontend/src/app/components/untie-fight/untie-fight.component.scss

Lines changed: 30 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11

22
.untie-container {
33
display: flex;
4-
padding-bottom: 10px;
4+
padding-bottom: 2vh
55
}
66

77
.untie {
8-
border-width: 2px;
8+
border-width: 2px 0 2px 0;
99
border-color: #011d4a;
1010
border-style: solid;
1111
padding: 5px;
@@ -20,35 +20,49 @@
2020
transform: rotate(180deg);
2121
text-align: center;
2222
padding: 20px;
23-
border-width: 2px;
24-
border-color: white;
2523
border-style: solid;
26-
color: red;
27-
background-color: #011d4a;
24+
//background-color: var(--ribbon-background);
25+
text-transform: uppercase;
26+
border-width: 2px 2px 2px 0;
27+
border-color: var(--fight-border-color);
28+
line-height: 25px;
29+
max-width: 56px;
30+
overflow: clip;
2831
}
2932

3033
.right-team {
3134
writing-mode: vertical-rl;
3235
text-align: center;
3336
padding: 20px;
34-
border-width: 2px;
35-
border-color: white;
3637
border-style: solid;
37-
color: white;
38-
text-shadow: -1px -1px 0 #000, 1px -1px 0 #000, -1px 1px 0 #000, 1px 1px 0 #000;
39-
background-color: #011d4a;
38+
//text-shadow: -1px -1px 0 #000, 1px -1px 0 #000, -1px 1px 0 #000, 1px 1px 0 #000;
39+
//background-color: var(--ribbon-background);
40+
text-transform: uppercase;
41+
border-width: 2px 2px 2px 0;
42+
border-color: var(--fight-border-color);
43+
line-height: 25px;
44+
max-width: 56px;
45+
overflow: clip;
4046
}
4147

4248
.red-ribbon {
43-
color: red;
49+
color: var(--ribbon-background);
50+
//To be below the timer
51+
z-index: -1;
52+
background-color: var(--red-team-color);
53+
border-width: 2px 0 2px 2px;
4454
}
4555

4656
.ribbon-icon {
4757
transform: rotate(0deg);
4858
}
4959

5060
.white-ribbon {
51-
color: white;
61+
color: var(--ribbon-background);
62+
//To be below the timer
63+
z-index: -1;
64+
background-color: var(--white-team-color);
65+
border-width: 2px 2px 2px 0;
5266
}
5367

5468
.duel {
@@ -73,7 +87,8 @@
7387
border-width: 1px;
7488
border-color: #777;
7589
border-style: solid;
76-
box-shadow: 0 5px 10px 0 rgba(0, 18, 57, 0.5);
90+
box-shadow: 0 5px 10px 0 var(--shadow);
7791
transition: transform .2s; /* Animation */
78-
background: white;
92+
//Transform causes problem with the timer component z-index.
93+
//transform: scale(1.03);
7994
}

frontend/src/app/components/untie-fight/untie-fight.component.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,9 @@ export class UntieFightComponent extends KendoComponent implements OnInit {
2626
@Input()
2727
swapTeams: boolean;
2828

29+
@Input()
30+
projectMode: boolean;
31+
2932
@Output() onSelectedDuel: EventEmitter<any> = new EventEmitter();
3033

3134
constructor(private duelChangedService: DuelChangedService) {

frontend/src/app/models/tournament-score.model.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ export class TournamentScore extends Element {
88

99
constructor() {
1010
super();
11-
this.scoreType = ScoreType.INTERNATIONAL;
11+
this.scoreType = ScoreType.EUROPEAN;
1212
this.pointsByVictory = 1;
1313
this.pointsByDraw = 0;
1414
}

0 commit comments

Comments
 (0)