Timelock weiter gebastelt
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
#Fri Mar 20 15:47:06 CET 2026
|
||||
#Sat Mar 21 08:14:24 CET 2026
|
||||
display=\:0
|
||||
host=Mario-Linux
|
||||
process-id=112524
|
||||
process-id=23243
|
||||
user=mario
|
||||
|
||||
4997
.metadata/.log
4997
.metadata/.log
File diff suppressed because it is too large
Load Diff
@@ -1,24 +1,7 @@
|
||||
[ {
|
||||
"version" : "9.5.0-20260320031124+0000",
|
||||
"buildTime" : "20260320031124+0000",
|
||||
"commitId" : "97faa73152fb6d4ea37edf6b3f7590dcbce8b952",
|
||||
"current" : false,
|
||||
"snapshot" : true,
|
||||
"nightly" : false,
|
||||
"releaseNightly" : true,
|
||||
"activeRc" : false,
|
||||
"rcFor" : "",
|
||||
"milestoneFor" : "",
|
||||
"broken" : false,
|
||||
"downloadUrl" : "https://services.gradle.org/distributions-snapshots/gradle-9.5.0-20260320031124+0000-bin.zip",
|
||||
"checksumUrl" : "https://services.gradle.org/distributions-snapshots/gradle-9.5.0-20260320031124+0000-bin.zip.sha256",
|
||||
"checksum" : "d28982b60bd15c7f3e13032152fc384f30465713b9c439bd3e159ad758461393",
|
||||
"wrapperChecksumUrl" : "https://services.gradle.org/distributions-snapshots/gradle-9.5.0-20260320031124+0000-wrapper.jar.sha256",
|
||||
"wrapperChecksum" : "f307680272dffdb8e636f1169adfbf693513005c80aa06e8d381f20390a06e6a"
|
||||
}, {
|
||||
"version" : "9.6.0-20260319194115+0000",
|
||||
"buildTime" : "20260319194115+0000",
|
||||
"commitId" : "eaac62111b6cbb05984176b52e4be56d5249ebf8",
|
||||
"version" : "9.6.0-20260321035213+0000",
|
||||
"buildTime" : "20260321035213+0000",
|
||||
"commitId" : "cc9b7c946cf24a57b2119d39f1a33cf5493ea930",
|
||||
"current" : false,
|
||||
"snapshot" : true,
|
||||
"nightly" : true,
|
||||
@@ -27,10 +10,27 @@
|
||||
"rcFor" : "",
|
||||
"milestoneFor" : "",
|
||||
"broken" : false,
|
||||
"downloadUrl" : "https://services.gradle.org/distributions-snapshots/gradle-9.6.0-20260319194115+0000-bin.zip",
|
||||
"checksumUrl" : "https://services.gradle.org/distributions-snapshots/gradle-9.6.0-20260319194115+0000-bin.zip.sha256",
|
||||
"checksum" : "a72c6e0f1a5ecc7d81768c65a5bdcd8f0af37ba5b05c83df4c45d08b8ce79fce",
|
||||
"wrapperChecksumUrl" : "https://services.gradle.org/distributions-snapshots/gradle-9.6.0-20260319194115+0000-wrapper.jar.sha256",
|
||||
"downloadUrl" : "https://services.gradle.org/distributions-snapshots/gradle-9.6.0-20260321035213+0000-bin.zip",
|
||||
"checksumUrl" : "https://services.gradle.org/distributions-snapshots/gradle-9.6.0-20260321035213+0000-bin.zip.sha256",
|
||||
"checksum" : "e533696ad1e80c2878ed39c18b5252ac7e0bad6394ead2b93663656cd6591059",
|
||||
"wrapperChecksumUrl" : "https://services.gradle.org/distributions-snapshots/gradle-9.6.0-20260321035213+0000-wrapper.jar.sha256",
|
||||
"wrapperChecksum" : "f307680272dffdb8e636f1169adfbf693513005c80aa06e8d381f20390a06e6a"
|
||||
}, {
|
||||
"version" : "9.5.0-20260321014114+0000",
|
||||
"buildTime" : "20260321014114+0000",
|
||||
"commitId" : "e7d13113f033cc35f5b8c7e0eeb88906259a1410",
|
||||
"current" : false,
|
||||
"snapshot" : true,
|
||||
"nightly" : false,
|
||||
"releaseNightly" : true,
|
||||
"activeRc" : false,
|
||||
"rcFor" : "",
|
||||
"milestoneFor" : "",
|
||||
"broken" : false,
|
||||
"downloadUrl" : "https://services.gradle.org/distributions-snapshots/gradle-9.5.0-20260321014114+0000-bin.zip",
|
||||
"checksumUrl" : "https://services.gradle.org/distributions-snapshots/gradle-9.5.0-20260321014114+0000-bin.zip.sha256",
|
||||
"checksum" : "eeb50f4468d73f74a68fe62a16d371ccc7c54088d7d2f672adb12c4bce4104d5",
|
||||
"wrapperChecksumUrl" : "https://services.gradle.org/distributions-snapshots/gradle-9.5.0-20260321014114+0000-wrapper.jar.sha256",
|
||||
"wrapperChecksum" : "f307680272dffdb8e636f1169adfbf693513005c80aa06e8d381f20390a06e6a"
|
||||
}, {
|
||||
"version" : "9.4.1",
|
||||
|
||||
File diff suppressed because one or more lines are too long
Binary file not shown.
Binary file not shown.
File diff suppressed because one or more lines are too long
Binary file not shown.
Binary file not shown.
@@ -4,14 +4,13 @@ INDEX VERSION 1.134+/home/mario/Workspaces/xxx-thegame/.metadata/.plugins/org.ec
|
||||
176453541.index
|
||||
677104696.index
|
||||
341080888.index
|
||||
4134502745.index
|
||||
774576701.index
|
||||
4134502745.index
|
||||
41199409.index
|
||||
2217896880.index
|
||||
134995224.index
|
||||
4025319337.index
|
||||
900586112.index
|
||||
9341915.index
|
||||
2929476459.index
|
||||
2065500052.index
|
||||
3051047092.index
|
||||
@@ -28,8 +27,8 @@ INDEX VERSION 1.134+/home/mario/Workspaces/xxx-thegame/.metadata/.plugins/org.ec
|
||||
2032345814.index
|
||||
3839581777.index
|
||||
2466743981.index
|
||||
673436610.index
|
||||
13999064.index
|
||||
673436610.index
|
||||
3972616808.index
|
||||
1914043487.index
|
||||
3154281632.index
|
||||
@@ -45,10 +44,10 @@ INDEX VERSION 1.134+/home/mario/Workspaces/xxx-thegame/.metadata/.plugins/org.ec
|
||||
4020783879.index
|
||||
2900482015.index
|
||||
3059431983.index
|
||||
13156219.index
|
||||
833027591.index
|
||||
4088356365.index
|
||||
13156219.index
|
||||
37241354.index
|
||||
4088356365.index
|
||||
1295630681.index
|
||||
2701419231.index
|
||||
3939420913.index
|
||||
@@ -56,8 +55,8 @@ INDEX VERSION 1.134+/home/mario/Workspaces/xxx-thegame/.metadata/.plugins/org.ec
|
||||
1318022262.index
|
||||
773718761.index
|
||||
2311226047.index
|
||||
1865797976.index
|
||||
3539841425.index
|
||||
1865797976.index
|
||||
2455962971.index
|
||||
2576972120.index
|
||||
2389383899.index
|
||||
|
||||
@@ -12,11 +12,17 @@
|
||||
<fullyQualifiedTypeName name="de.oaa.xxx.games.chastity.cardlock.GreenCard"/>
|
||||
<fullyQualifiedTypeName name="java.util.Random"/>
|
||||
<fullyQualifiedTypeName name="de.oaa.xxx.games.chastity.CardLockService"/>
|
||||
<fullyQualifiedTypeName name="jakarta.persistence.Column"/>
|
||||
<fullyQualifiedTypeName name="java.time.LocalDateTime"/>
|
||||
<fullyQualifiedTypeName name="de.oaa.xxx.games.chastity.history.LockHistoryRepository"/>
|
||||
<fullyQualifiedTypeName name="lombok.Getter"/>
|
||||
<fullyQualifiedTypeName name="lombok.Setter"/>
|
||||
<fullyQualifiedTypeName name="de.oaa.xxx.games.chastity.cardlock.Test"/>
|
||||
<fullyQualifiedTypeName name="de.oaa.xxx.games.chastity.KeyholderCardLock"/>
|
||||
<fullyQualifiedTypeName name="lombok.Getter"/>
|
||||
<fullyQualifiedTypeName name="lombok.Setter"/>
|
||||
<fullyQualifiedTypeName name="de.oaa.xxx.games.chastity.timelock.TimeLockService"/>
|
||||
<fullyQualifiedTypeName name="jakarta.persistence.Column"/>
|
||||
<fullyQualifiedTypeName name="java.time.temporal.ChronoUnit"/>
|
||||
<fullyQualifiedTypeName name="java.time.LocalDateTime"/>
|
||||
<fullyQualifiedTypeName name="de.oaa.xxx.games.chastity.AbstractLockService"/>
|
||||
<fullyQualifiedTypeName name="de.oaa.xxx.games.chastity.timelock.TimeLockEntity"/>
|
||||
<fullyQualifiedTypeName name="de.oaa.xxx.games.chastity.timelock.TimeLockRepository"/>
|
||||
<fullyQualifiedTypeName name="de.oaa.xxx.games.chastity.verification.VerificationVoteRepository"/>
|
||||
</qualifiedTypeNameHistroy>
|
||||
|
||||
@@ -28,6 +28,8 @@
|
||||
<item key="updateTextualMatches" value="false"/>
|
||||
<item key="updateQualifiedNames" value="false"/>
|
||||
<item key="patterns" value="*"/>
|
||||
<item key="updateSimilarElements" value="false"/>
|
||||
<item key="updateSimilarElementsMatchStrategy" value="1"/>
|
||||
</section>
|
||||
<section name="org.eclipse.jdt.internal.ui.dialogs.OpenTypeSelectionDialog2">
|
||||
<item key="ShowStatusLine" value="true"/>
|
||||
@@ -81,4 +83,11 @@
|
||||
<section name="NewPackageWizardPage">
|
||||
<item key="create_package_info_java" value="false"/>
|
||||
</section>
|
||||
<section name="NewEnumCreationWizard.dialogBounds">
|
||||
<item key="DIALOG_X_ORIGIN" value="20"/>
|
||||
<item key="DIALOG_Y_ORIGIN" value="20"/>
|
||||
<item key="DIALOG_WIDTH" value="631"/>
|
||||
<item key="DIALOG_HEIGHT" value="577"/>
|
||||
<item key="DIALOG_FONT_NAME" value="1|Ubuntu Sans|11.0|0|GTK|1|"/>
|
||||
</section>
|
||||
</section>
|
||||
|
||||
@@ -31,3 +31,7 @@
|
||||
2026-03-20 10:34:17,517 [Worker-5: Loading available Gradle versions] INFO o.e.b.c.i.u.g.PublishedGradleVersions - Gradle version information cache is up-to-date. Trying to read.
|
||||
2026-03-20 12:08:01,037 [Worker-1: Loading available Gradle versions] INFO o.e.b.c.i.u.g.PublishedGradleVersions - Gradle version information cache is up-to-date. Trying to read.
|
||||
2026-03-20 15:47:08,644 [Worker-1: Loading available Gradle versions] INFO o.e.b.c.i.u.g.PublishedGradleVersions - Gradle version information cache is up-to-date. Trying to read.
|
||||
2026-03-20 16:26:08,485 [Worker-7: Loading available Gradle versions] INFO o.e.b.c.i.u.g.PublishedGradleVersions - Gradle version information cache is up-to-date. Trying to read.
|
||||
2026-03-21 08:03:15,921 [Worker-1: Loading available Gradle versions] INFO o.e.b.c.i.u.g.PublishedGradleVersions - Gradle version information cache is out-of-date. Trying to update.
|
||||
2026-03-21 08:10:51,183 [Worker-1: Loading available Gradle versions] INFO o.e.b.c.i.u.g.PublishedGradleVersions - Gradle version information cache is up-to-date. Trying to read.
|
||||
2026-03-21 08:14:27,502 [Worker-8: Loading available Gradle versions] INFO o.e.b.c.i.u.g.PublishedGradleVersions - Gradle version information cache is up-to-date. Trying to read.
|
||||
|
||||
@@ -6,4 +6,5 @@
|
||||
<workingSet aggregate="true" factoryID="org.eclipse.ui.internal.WorkingSetFactory" id="1772786688998_3" label="Window Working Set" name="Aggregate for window 1772786688997"/>
|
||||
<workingSet aggregate="true" factoryID="org.eclipse.ui.internal.WorkingSetFactory" id="1772792014092_4" label="Window Working Set" name="Aggregate for window 1772792014092"/>
|
||||
<workingSet aggregate="true" factoryID="org.eclipse.ui.internal.WorkingSetFactory" id="1773603878078_5" label="Window Working Set" name="Aggregate for window 1773600542055"/>
|
||||
<workingSet aggregate="true" factoryID="org.eclipse.ui.internal.WorkingSetFactory" id="1774020460693_6" label="Window Working Set" name="Aggregate for window 1774020460693"/>
|
||||
</workingSetManager>
|
||||
@@ -1,3 +1,3 @@
|
||||
#Fri Mar 20 15:47:06 CET 2026
|
||||
#Sat Mar 21 08:14:24 CET 2026
|
||||
org.eclipse.core.runtime=2
|
||||
org.eclipse.platform=4.39.0.v20260226-0420
|
||||
|
||||
BIN
bilder/card_cum.png
Normal file
BIN
bilder/card_cum.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 299 KiB |
BIN
bilder/card_cum_caged.png
Normal file
BIN
bilder/card_cum_caged.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 301 KiB |
@@ -8,6 +8,8 @@ Verknüpfung der Spiele, wenn das Finish eines aus dem Bereich Chastity ist, wir
|
||||
|
||||
Wenn ein Lock für einen User existiert, wird er ohne entsprechend Penis/Vagina zu dem Spiel erstellt.
|
||||
|
||||
TODO: Im Time Lock, wenn im Spinning Wheel tasks drin sind, dürfen keine sonst keine Tasks gefordert sein und umgekehrt
|
||||
|
||||
Ich kann Spieler einladen zu spielen, dann kriegt die Person eine E-Mail und muss bestätigen, dass es diese PErson ist, sie wird dann ins spiel übernommen
|
||||
-- Falls fall mit Chastity auftritt wird die Spielpartnerin als Keyholder eingetragen, diese Person darf entscheiden, was für ein Lock das wird.
|
||||
|
||||
|
||||
@@ -138,8 +138,8 @@ public class BdsmGameService {
|
||||
newLock.setTestLock(false);
|
||||
newLock.setTaskCardMode(template.getTaskCardMode());
|
||||
|
||||
int codeLines = template.getUnlockCodeLines() != null ? template.getUnlockCodeLines() : 5;
|
||||
newLock.setUnlockCodeLines(codeLines);
|
||||
int codeLines = template.getUnlockCodeLength() != null ? template.getUnlockCodeLength() : 5;
|
||||
newLock.setUnlockCodeLength(codeLines);
|
||||
StringBuilder codeBuilder = new StringBuilder();
|
||||
java.util.Random rng = new java.util.Random();
|
||||
for (int i = 0; i < codeLines; i++) codeBuilder.append(rng.nextInt(10));
|
||||
|
||||
@@ -1,45 +0,0 @@
|
||||
package de.oaa.xxx.games.chastity;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.temporal.ChronoUnit;
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import de.oaa.xxx.games.chastity.cardlock.CardEnum;
|
||||
import de.oaa.xxx.games.chastity.cardlock.CardLockEntity;
|
||||
import de.oaa.xxx.games.chastity.tasks.Task;
|
||||
|
||||
public class KeyholderCardLock {
|
||||
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(KeyholderCardLock.class);
|
||||
|
||||
private CardLockEntity lock;
|
||||
|
||||
public void addCards(List<CardEnum> cards) {
|
||||
lock.getAvailableCards().addAll(cards);
|
||||
}
|
||||
|
||||
public void freeze() {
|
||||
var multiplier = lock.getPickEveryMinute() * new Random().nextDouble(1.0, 4.0);
|
||||
LocalDateTime frozenTill = LocalDateTime.now().plus((long) multiplier, ChronoUnit.MINUTES);
|
||||
lock.setFrozenUntill(frozenTill);
|
||||
LOGGER.debug("Frozen by keyholder until {}", lock.getFrozenUntill());
|
||||
}
|
||||
|
||||
public void freeze(LocalDateTime until) {
|
||||
lock.setFrozenUntill(until);
|
||||
LOGGER.debug("Frozen by keyholder until {}", lock.getFrozenUntill());
|
||||
}
|
||||
|
||||
public void task() {
|
||||
}
|
||||
|
||||
public void task(Task task) {
|
||||
}
|
||||
|
||||
public void penalty() {
|
||||
}
|
||||
}
|
||||
@@ -1,6 +0,0 @@
|
||||
package de.oaa.xxx.games.chastity;
|
||||
|
||||
public enum LockType {
|
||||
|
||||
CARD, TIMED;
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
package de.oaa.xxx.games.chastity;
|
||||
|
||||
public class ProcessLock {
|
||||
|
||||
public void oeffnen() {
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,5 +0,0 @@
|
||||
package de.oaa.xxx.games.chastity;
|
||||
|
||||
public class ProcessTimedLock extends ProcessLock {
|
||||
|
||||
}
|
||||
@@ -1,5 +0,0 @@
|
||||
package de.oaa.xxx.games.chastity;
|
||||
|
||||
public class Timer {
|
||||
|
||||
}
|
||||
@@ -43,6 +43,21 @@ public enum CardEnum {
|
||||
public Card get() {
|
||||
return new DoubleUpCard();
|
||||
}
|
||||
},
|
||||
CUM {
|
||||
@Override
|
||||
public Card get() {
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
}
|
||||
|
||||
},
|
||||
CUM_IN_CAGE {
|
||||
@Override
|
||||
public Card get() {
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -36,18 +36,26 @@ import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import de.oaa.xxx.games.chastity.CodeCreator;
|
||||
import de.oaa.xxx.games.chastity.KeyholderInvitationEntity;
|
||||
import de.oaa.xxx.games.chastity.KeyholderInvitationRepository;
|
||||
import de.oaa.xxx.games.chastity.LockeeInvitationEntity;
|
||||
import de.oaa.xxx.games.chastity.LockeeInvitationRepository;
|
||||
import de.oaa.xxx.games.chastity.common.CodeCreator;
|
||||
import de.oaa.xxx.games.chastity.keyholder.KeyholderInvitationEntity;
|
||||
import de.oaa.xxx.games.chastity.keyholder.KeyholderInvitationRepository;
|
||||
import de.oaa.xxx.games.chastity.keyholder.KeyholderNotificationRepository;
|
||||
import de.oaa.xxx.games.chastity.keyholder.KeyholderTaskChoiceEntity;
|
||||
import de.oaa.xxx.games.chastity.keyholder.KeyholderTaskChoiceRepository;
|
||||
import de.oaa.xxx.games.chastity.lockee.LockeeInvitationEntity;
|
||||
import de.oaa.xxx.games.chastity.lockee.LockeeInvitationRepository;
|
||||
import de.oaa.xxx.games.chastity.tasks.AssignedTaskEntity;
|
||||
import de.oaa.xxx.games.chastity.tasks.AssignedTaskRepository;
|
||||
import de.oaa.xxx.games.chastity.tasks.Task;
|
||||
import de.oaa.xxx.games.chastity.unlock.TempOpeningReason;
|
||||
import de.oaa.xxx.games.chastity.unlock.UnlockCodeHistoryRepository;
|
||||
import de.oaa.xxx.games.chastity.unlock.UnlockCodeHistoryService;
|
||||
import de.oaa.xxx.games.chastity.verification.VerificationEntity;
|
||||
import de.oaa.xxx.games.chastity.verification.VerificationRepository;
|
||||
import de.oaa.xxx.games.chastity.verification.VerificationVoteEntity;
|
||||
import de.oaa.xxx.games.chastity.verification.VerificationVoteRepository;
|
||||
import de.oaa.xxx.games.chastity.vote.CommunityTaskVoteEntity;
|
||||
import de.oaa.xxx.games.chastity.vote.CommunityTaskVoteRepository;
|
||||
import de.oaa.xxx.social.SystemMessageService;
|
||||
import de.oaa.xxx.user.UserRepository;
|
||||
|
||||
@@ -60,7 +68,7 @@ public class CardLockController {
|
||||
private final KeyholderInvitationRepository invitationRepository;
|
||||
private final VerificationRepository verificationRepository;
|
||||
private final VerificationVoteRepository verificationVoteRepository;
|
||||
private final HygieneViolationRepository hygieneViolationRepository;
|
||||
private final KeyholderNotificationRepository keyholderNotificationRepository;
|
||||
private final LockeeInvitationRepository lockeeInvitationRepository;
|
||||
private final AssignedTaskRepository assignedTaskRepository;
|
||||
private final KeyholderTaskChoiceRepository keyholderTaskChoiceRepository;
|
||||
@@ -76,7 +84,7 @@ public class CardLockController {
|
||||
public CardLockController(CardlockRepository cardlockRepository, UserRepository userRepository,
|
||||
KeyholderInvitationRepository invitationRepository, VerificationRepository verificationRepository,
|
||||
VerificationVoteRepository verificationVoteRepository,
|
||||
HygieneViolationRepository hygieneViolationRepository,
|
||||
KeyholderNotificationRepository keyholderNotificationRepository,
|
||||
LockeeInvitationRepository lockeeInvitationRepository, AssignedTaskRepository assignedTaskRepository,
|
||||
KeyholderTaskChoiceRepository keyholderTaskChoiceRepository,
|
||||
CommunityTaskVoteRepository communityTaskVoteRepository,
|
||||
@@ -88,7 +96,7 @@ public class CardLockController {
|
||||
this.invitationRepository = invitationRepository;
|
||||
this.verificationRepository = verificationRepository;
|
||||
this.verificationVoteRepository = verificationVoteRepository;
|
||||
this.hygieneViolationRepository = hygieneViolationRepository;
|
||||
this.keyholderNotificationRepository = keyholderNotificationRepository;
|
||||
this.lockeeInvitationRepository = lockeeInvitationRepository;
|
||||
this.assignedTaskRepository = assignedTaskRepository;
|
||||
this.keyholderTaskChoiceRepository = keyholderTaskChoiceRepository;
|
||||
@@ -197,7 +205,7 @@ public class CardLockController {
|
||||
lock.setRequiresVerification(req.requiresVerification());
|
||||
lock.setTestLock(req.testLock());
|
||||
lock.setTaskCardMode(req.taskCardMode() != null ? req.taskCardMode() : "RANDOM");
|
||||
lock.setUnlockCodeLines(codeLines);
|
||||
lock.setUnlockCodeLength(codeLines);
|
||||
lock.setUnlockCode(unlockCode);
|
||||
|
||||
LocalDateTime now = LocalDateTime.now();
|
||||
@@ -322,11 +330,7 @@ public class CardLockController {
|
||||
if (!l.getLockee().equals(myId))
|
||||
return ResponseEntity.status(403).build();
|
||||
|
||||
l.setHygineOpeningtime(LocalDateTime.now());
|
||||
cardlockRepository.save(l);
|
||||
|
||||
unlockCodeHistoryService.save(myId, l.getLockId(), l.getName(), l.getUnlockCode(), "HYGIENE_OPEN");
|
||||
|
||||
cardLockServiceFactory.create(l).startHygieneOpening();
|
||||
return ResponseEntity.ok(Map.of("unlockCode", l.getUnlockCode(), "durationMinutes",
|
||||
l.getHygineOpeningDurationMinutes() != null ? l.getHygineOpeningDurationMinutes() : 30));
|
||||
}
|
||||
@@ -346,46 +350,8 @@ public class CardLockController {
|
||||
if (!l.getLockee().equals(myId))
|
||||
return ResponseEntity.status(403).build();
|
||||
|
||||
LocalDateTime now = LocalDateTime.now();
|
||||
|
||||
// Overtime berechnen
|
||||
if (l.getHygineOpeningtime() != null && l.getHygineOpeningDurationMinutes() != null) {
|
||||
LocalDateTime dueTime = l.getHygineOpeningtime().plusMinutes(l.getHygineOpeningDurationMinutes());
|
||||
if (now.isAfter(dueTime)) {
|
||||
long overtimeMinutes = ChronoUnit.MINUTES.between(dueTime, now);
|
||||
if (l.getKeyholder() == null) {
|
||||
// Self-Lock: 4-fache Überschreitungszeit einfrieren
|
||||
if (l.getFrozenUntill() != null) {
|
||||
l.setFrozenUntill(l.getFrozenUntill().plusMinutes(overtimeMinutes * 4));
|
||||
} else {
|
||||
l.setFrozenUntill(now.plusMinutes(overtimeMinutes * 4));
|
||||
}
|
||||
} else {
|
||||
// Keyholder vorhanden: Verletzung protokollieren
|
||||
HygieneViolationEntity violation = new HygieneViolationEntity();
|
||||
violation.setLockId(lockId);
|
||||
violation.setLockeeId(myId);
|
||||
violation.setKeyholderUserId(l.getKeyholder());
|
||||
violation.setViolationTime(now);
|
||||
violation.setOvertimeMinutes(overtimeMinutes);
|
||||
hygieneViolationRepository.save(violation);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Nächsten Öffnungszeitpunkt setzen
|
||||
l.setLastHygineOpening(LocalDateTime.now());
|
||||
l.setHygineOpeningtime(null);
|
||||
|
||||
// Neuen Entsperrcode generieren
|
||||
int codeLines = l.getUnlockCodeLines() != null ? l.getUnlockCodeLines() : 5;
|
||||
String newCode = generateUnlockCode(codeLines);
|
||||
l.setUnlockCode(newCode);
|
||||
cardlockRepository.save(l);
|
||||
|
||||
unlockCodeHistoryService.save(myId, l.getLockId(), l.getName(), newCode, "HYGIENE_CLOSE");
|
||||
|
||||
return ResponseEntity.ok(Map.of("newUnlockCode", newCode));
|
||||
String code = cardLockServiceFactory.create(l).endHygieneOpening();
|
||||
return ResponseEntity.ok(Map.of("newUnlockCode", code));
|
||||
}
|
||||
|
||||
@PostMapping("/cardlock/{lockId}/task/complete")
|
||||
@@ -496,9 +462,9 @@ public class CardLockController {
|
||||
result.put("hygieneEnabled", hygieneEnabled);
|
||||
result.put("hygieneOpeningDue", hygieneOpeningDue);
|
||||
result.put("hygieneSecondsRemaining", hygieneSecondsRemaining);
|
||||
result.put("hygieneOpeningActive", l.getHygineOpeningtime() != null);
|
||||
result.put("hygieneOpeningActive", l.getTempOpeningTime() != null && TempOpeningReason.HYGIENE == l.getTempOpeningReason());
|
||||
result.put("hygieneOpeningStarted",
|
||||
l.getHygineOpeningtime() != null ? l.getHygineOpeningtime().toString() : null);
|
||||
l.getTempOpeningTime() != null ? l.getTempOpeningTime().toString() : null);
|
||||
result.put("hygieneDurationMinutes",
|
||||
l.getHygineOpeningDurationMinutes() != null ? l.getHygineOpeningDurationMinutes() : 0);
|
||||
result.put("hasKeyholder", l.getKeyholder() != null);
|
||||
@@ -973,7 +939,7 @@ public class CardLockController {
|
||||
}
|
||||
}
|
||||
|
||||
var recentViolations = hygieneViolationRepository.findByLockId(lockId).stream()
|
||||
var notification = keyholderNotificationRepository.findByLockId(lockId).stream()
|
||||
.sorted((a, b) -> b.getViolationTime().compareTo(a.getViolationTime())).limit(5)
|
||||
.map(v -> Map.of("time", v.getViolationTime().toString(), "overtimeMinutes", v.getOvertimeMinutes()))
|
||||
.toList();
|
||||
@@ -998,7 +964,7 @@ public class CardLockController {
|
||||
result.put("hygieneEnabled", hygieneEnabled);
|
||||
result.put("hygieneOpeningDue", hygieneOpeningDue);
|
||||
result.put("hygieneSecondsRemaining", hygieneSecondsRemaining);
|
||||
result.put("hygieneOpeningActive", l.getHygineOpeningtime() != null);
|
||||
result.put("hygieneOpeningActive", l.getTempOpeningTime() != null && TempOpeningReason.HYGIENE == l.getTempOpeningReason());
|
||||
result.put("requiresVerification", l.isRequiresVerification());
|
||||
result.put("verificationDue", verificationDue);
|
||||
result.put("verificationDoneToday", verificationDoneToday);
|
||||
@@ -1007,7 +973,7 @@ public class CardLockController {
|
||||
result.put("verificationImage", verificationImage);
|
||||
result.put("verificationUpvotes", verificationUpvotes);
|
||||
result.put("verificationDownvotes", verificationDownvotes);
|
||||
result.put("hygieneViolations", recentViolations);
|
||||
result.put("hygieneViolations", notification);
|
||||
result.put("hasTasks", l.getTasks() != null && !l.getTasks().isEmpty());
|
||||
if (l.getTasks() != null) {
|
||||
var taskList = l.getTasks().stream().map(t -> {
|
||||
@@ -1589,6 +1555,8 @@ public class CardLockController {
|
||||
case FREEZE -> "Freeze";
|
||||
case RESET -> "Reset";
|
||||
case DOUBLE_UP -> "Double Up";
|
||||
case CUM -> "Kommen";
|
||||
case CUM_IN_CAGE -> "Kommen im Käfig";
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@ import java.util.UUID;
|
||||
|
||||
import de.oaa.xxx.games.chastity.tasks.Task;
|
||||
import de.oaa.xxx.games.chastity.tasks.TaskListConverter;
|
||||
import de.oaa.xxx.games.chastity.unlock.TempOpeningReason;
|
||||
import jakarta.persistence.Column;
|
||||
import jakarta.persistence.Convert;
|
||||
import jakarta.persistence.Entity;
|
||||
@@ -60,7 +61,7 @@ public class CardLockEntity {
|
||||
@Column
|
||||
private boolean testLock;
|
||||
@Column
|
||||
private Integer unlockCodeLines;
|
||||
private Integer unlockCodeLength;
|
||||
|
||||
// State
|
||||
@Column
|
||||
@@ -75,7 +76,11 @@ public class CardLockEntity {
|
||||
@Column
|
||||
private LocalDateTime lastHygineOpening;
|
||||
@Column
|
||||
private LocalDateTime hygineOpeningtime; // If null, not while hygine opening
|
||||
private LocalDateTime tempOpeningTime; // If null, not while hygine opening
|
||||
@Column
|
||||
private Integer tempOpeningDuration;
|
||||
@Column
|
||||
private TempOpeningReason tempOpeningReason;
|
||||
@Column
|
||||
private LocalDateTime unlockTime;
|
||||
@Column
|
||||
|
||||
@@ -11,33 +11,41 @@ import java.util.stream.Collectors;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import de.oaa.xxx.games.chastity.ProcessLock;
|
||||
import de.oaa.xxx.games.chastity.common.AbstractLockService;
|
||||
import de.oaa.xxx.games.chastity.common.CodeCreator;
|
||||
import de.oaa.xxx.games.chastity.keyholder.KeyholderNotificationEntity;
|
||||
import de.oaa.xxx.games.chastity.keyholder.KeyholderNotificationRepository;
|
||||
import de.oaa.xxx.games.chastity.tasks.Task;
|
||||
import de.oaa.xxx.games.chastity.unlock.TempOpeningReason;
|
||||
import de.oaa.xxx.games.chastity.unlock.UnlockCodeHistoryService;
|
||||
import de.oaa.xxx.games.chastity.verification.VerificationRepository;
|
||||
import de.oaa.xxx.games.chastity.verification.VerificationVoteRepository;
|
||||
import de.oaa.xxx.games.history.GameHistoryEntity;
|
||||
import de.oaa.xxx.games.history.GameHistoryRepository;
|
||||
import de.oaa.xxx.games.chastity.tasks.Task;
|
||||
import de.oaa.xxx.games.chastity.verification.VerificationEntity;
|
||||
import de.oaa.xxx.games.chastity.verification.VerificationRepository;
|
||||
import de.oaa.xxx.games.chastity.verification.VerificationVoteEntity;
|
||||
import de.oaa.xxx.games.chastity.verification.VerificationVoteRepository;
|
||||
import de.oaa.xxx.user.UserRepository;
|
||||
|
||||
public class CardLockService extends ProcessLock {
|
||||
public class CardLockService extends AbstractLockService {
|
||||
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(CardLockService.class);
|
||||
private final CardLockEntity lock;
|
||||
private VerificationRepository verificationRepository;
|
||||
private VerificationVoteRepository verificationVoteRepository;
|
||||
private CardLockRepository cardLockRepository;
|
||||
private VerificationRepository verificationRepository;
|
||||
private GameHistoryRepository gameHistoryRepository;
|
||||
private UserRepository userRepository;
|
||||
private UnlockCodeHistoryService unlockCodeHistoryService;
|
||||
private KeyholderNotificationRepository keyholderNotificationRepository;
|
||||
|
||||
public CardLockService(CardLockEntity lock, VerificationRepository verificationRepository, VerificationVoteRepository verificationVoteRepository, CardLockRepository cardLockRepository, GameHistoryRepository gameHistoryRepository, UserRepository userRepository) {
|
||||
this.lock = lock;
|
||||
this.verificationRepository = verificationRepository;
|
||||
this.verificationVoteRepository = verificationVoteRepository;
|
||||
public CardLockService(CardLockEntity lock, VerificationRepository verificationRepository,
|
||||
VerificationVoteRepository verificationVoteRepository, CardLockRepository cardLockRepository,
|
||||
GameHistoryRepository gameHistoryRepository, UserRepository userRepository, KeyholderNotificationRepository keyholderNotificationRepository,UnlockCodeHistoryService unlockCodeHistoryService) {
|
||||
super(verificationVoteRepository);
|
||||
this.lock = lock;
|
||||
this.cardLockRepository = cardLockRepository;
|
||||
this.verificationRepository = verificationRepository;
|
||||
this.gameHistoryRepository = gameHistoryRepository;
|
||||
this.userRepository = userRepository;
|
||||
this.keyholderNotificationRepository = keyholderNotificationRepository;
|
||||
this.unlockCodeHistoryService = unlockCodeHistoryService;
|
||||
}
|
||||
|
||||
public CardDTO getNextCard() {
|
||||
@@ -165,19 +173,6 @@ public class CardLockService extends ProcessLock {
|
||||
lock.getAvailableCards().add(CardEnum.GREEN);
|
||||
cardLockRepository.save(lock);
|
||||
}
|
||||
|
||||
|
||||
private boolean isValid(VerificationEntity entity) {
|
||||
int count = 0;
|
||||
for (VerificationVoteEntity vote : verificationVoteRepository.findAllByVerificationId(entity.getVerficationId())) {
|
||||
if (vote.isUpvote()) {
|
||||
count++;
|
||||
} else {
|
||||
count--;
|
||||
}
|
||||
}
|
||||
return count >= 0;
|
||||
}
|
||||
|
||||
public String freeze() {
|
||||
var multiplier = lock.getPickEveryMinute() * new Random().nextDouble(1.0, 4.0);
|
||||
@@ -244,4 +239,94 @@ public class CardLockService extends ProcessLock {
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
public void startHygieneOpening() {
|
||||
tempOperning(TempOpeningReason.HYGIENE, lock.getHygineOpeningDurationMinutes());
|
||||
}
|
||||
|
||||
private Long calcOvertime() {
|
||||
LocalDateTime now = LocalDateTime.now();
|
||||
Long overtime = null;
|
||||
if (lock.getTempOpeningTime() != null && lock.getTempOpeningDuration() != null) {
|
||||
LocalDateTime dueTime = lock.getTempOpeningTime().plusMinutes(lock.getTempOpeningDuration());
|
||||
if (LocalDateTime.now().isAfter(dueTime)) {
|
||||
overtime = ChronoUnit.MINUTES.between(dueTime, now);
|
||||
}
|
||||
}
|
||||
return overtime;
|
||||
}
|
||||
|
||||
public String endHygieneOpening() {
|
||||
LocalDateTime now = LocalDateTime.now();
|
||||
|
||||
Long overtime = calcOvertime();
|
||||
if (overtime != null) {
|
||||
if (lock.getKeyholder() != null) {
|
||||
reportKeyholder(overtime);
|
||||
}
|
||||
freezeForOvertime(overtime);
|
||||
|
||||
}
|
||||
lock.setLastHygineOpening(now);
|
||||
lock.setTempOpeningDuration(null);
|
||||
lock.setTempOpeningTime(null);
|
||||
|
||||
var code = CodeCreator.createAlphanumericCode(lock.getUnlockCodeLength());
|
||||
lock.setUnlockCode(code);
|
||||
cardLockRepository.save(lock);
|
||||
return code;
|
||||
}
|
||||
|
||||
private void reportKeyholder(Long overtime) {
|
||||
KeyholderNotificationEntity notification = new KeyholderNotificationEntity();
|
||||
notification.setLockId(lock.getLockId());
|
||||
notification.setLockeeId(lock.getLockee());
|
||||
notification.setKeyholderUserId(lock.getKeyholder());
|
||||
notification.setViolationTime(LocalDateTime.now());
|
||||
notification.setOvertimeMinutes(overtime);
|
||||
keyholderNotificationRepository.save(notification);
|
||||
}
|
||||
|
||||
private void freezeForOvertime(Long overtime) {
|
||||
if (lock.getFrozenUntill() != null) {
|
||||
lock.setFrozenUntill(lock.getFrozenUntill().plusMinutes(overtime * 4));
|
||||
} else {
|
||||
lock.setFrozenUntill(LocalDateTime.now().plusMinutes(overtime * 4));
|
||||
}
|
||||
}
|
||||
|
||||
private void tempOperning(TempOpeningReason reason, Integer duration) {
|
||||
assert duration != null;
|
||||
lock.setTempOpeningReason(reason);
|
||||
lock.setTempOpeningTime(LocalDateTime.now());;
|
||||
lock.setTempOpeningDuration(duration);
|
||||
cardLockRepository.save(lock);
|
||||
unlockCodeHistoryService.save(lock.getLockee(), lock.getLockId(), lock.getName(), lock.getUnlockCode(), reason.toString());
|
||||
}
|
||||
|
||||
public String cum(boolean tempUnlock) {
|
||||
if (tempUnlock) {
|
||||
tempOperning(TempOpeningReason.CARD, 0); // Je länger man braucht, desto länger wird gefreezed
|
||||
}
|
||||
return lock.getUnlockCode();
|
||||
}
|
||||
|
||||
public String endCumming() {
|
||||
Long overtime = calcOvertime();
|
||||
if (overtime != null) {
|
||||
if (lock.getKeyholder() == null) {
|
||||
freezeForOvertime(overtime);
|
||||
} else {
|
||||
reportKeyholder(overtime);
|
||||
}
|
||||
}
|
||||
lock.setTempOpeningDuration(null);
|
||||
lock.setTempOpeningTime(null);
|
||||
lock.setTempOpeningReason(null);
|
||||
|
||||
var code = CodeCreator.createAlphanumericCode(lock.getUnlockCodeLength());
|
||||
lock.setUnlockCode(code);
|
||||
cardLockRepository.save(lock);
|
||||
return code;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
package de.oaa.xxx.games.chastity.cardlock;
|
||||
|
||||
import de.oaa.xxx.games.history.GameHistoryRepository;
|
||||
import de.oaa.xxx.games.chastity.keyholder.KeyholderNotificationRepository;
|
||||
import de.oaa.xxx.games.chastity.unlock.UnlockCodeHistoryService;
|
||||
import de.oaa.xxx.games.chastity.verification.VerificationRepository;
|
||||
import de.oaa.xxx.games.chastity.verification.VerificationVoteRepository;
|
||||
import de.oaa.xxx.user.UserRepository;
|
||||
@@ -20,18 +22,24 @@ public class CardLockServiceFactory {
|
||||
private final VerificationVoteRepository verificationVoteRepository;
|
||||
private final CardLockRepository cardLockRepository;
|
||||
private final GameHistoryRepository gameHistoryRepository;
|
||||
private final UserRepository userRepository;
|
||||
private final UserRepository userRepository;
|
||||
private KeyholderNotificationRepository keyholderNotificationRepository;
|
||||
private final UnlockCodeHistoryService unlockCodeHistoryService;
|
||||
|
||||
public CardLockServiceFactory(VerificationRepository verificationRepository,
|
||||
VerificationVoteRepository verificationVoteRepository,
|
||||
CardLockRepository cardLockRepository,
|
||||
GameHistoryRepository gameHistoryRepository,
|
||||
UserRepository userRepository) {
|
||||
UserRepository userRepository,
|
||||
KeyholderNotificationRepository keyholderNotificationRepository,
|
||||
UnlockCodeHistoryService unlockCodeHistoryService) {
|
||||
this.verificationRepository = verificationRepository;
|
||||
this.verificationVoteRepository = verificationVoteRepository;
|
||||
this.cardLockRepository = cardLockRepository;
|
||||
this.gameHistoryRepository = gameHistoryRepository;
|
||||
this.userRepository = userRepository;
|
||||
this.keyholderNotificationRepository = keyholderNotificationRepository;
|
||||
this.unlockCodeHistoryService = unlockCodeHistoryService;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -44,7 +52,9 @@ public class CardLockServiceFactory {
|
||||
verificationVoteRepository,
|
||||
cardLockRepository,
|
||||
gameHistoryRepository,
|
||||
userRepository
|
||||
userRepository,
|
||||
keyholderNotificationRepository,
|
||||
unlockCodeHistoryService
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
package de.oaa.xxx.games.chastity.cardlock;
|
||||
|
||||
public class CumCard implements Card {
|
||||
|
||||
@Override
|
||||
public CardDTO processCard(CardLockService lock) {
|
||||
return new CardDTO(CardEnum.CUM, lock.cum(true));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
package de.oaa.xxx.games.chastity.cardlock;
|
||||
|
||||
public class CumInCageCard implements Card {
|
||||
|
||||
@Override
|
||||
public CardDTO processCard(CardLockService lock) {
|
||||
return new CardDTO(CardEnum.CUM_IN_CAGE, lock.cum(false));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
package de.oaa.xxx.games.chastity.cardlock;
|
||||
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
public interface HygieneViolationRepository extends JpaRepository<HygieneViolationEntity, UUID> {
|
||||
List<HygieneViolationEntity> findByKeyholderUserIdAndNotifiedKeyholderFalse(UUID keyholderUserId);
|
||||
List<HygieneViolationEntity> findByLockId(UUID lockId);
|
||||
}
|
||||
@@ -1,8 +1,12 @@
|
||||
package de.oaa.xxx.games.chastity.cardlock;
|
||||
|
||||
import de.oaa.xxx.games.chastity.keyholder.KeyholderTaskChoiceRepository;
|
||||
import de.oaa.xxx.games.chastity.tasks.AssignedTaskEntity;
|
||||
import de.oaa.xxx.games.chastity.tasks.AssignedTaskRepository;
|
||||
import de.oaa.xxx.games.chastity.tasks.Task;
|
||||
import de.oaa.xxx.games.chastity.vote.CommunityTaskVoteEntryEntity;
|
||||
import de.oaa.xxx.games.chastity.vote.CommunityTaskVoteEntryRepository;
|
||||
import de.oaa.xxx.games.chastity.vote.CommunityTaskVoteRepository;
|
||||
import de.oaa.xxx.social.SystemMessageService;
|
||||
import de.oaa.xxx.user.UserRepository;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
|
||||
@@ -16,6 +16,8 @@ import org.springframework.transaction.annotation.Transactional;
|
||||
import de.oaa.xxx.games.chastity.tasks.AssignedTaskEntity;
|
||||
import de.oaa.xxx.games.chastity.tasks.AssignedTaskRepository;
|
||||
import de.oaa.xxx.games.chastity.tasks.Task;
|
||||
import de.oaa.xxx.games.chastity.vote.CommunityTaskVoteEntryRepository;
|
||||
import de.oaa.xxx.games.chastity.vote.CommunityTaskVoteRepository;
|
||||
import de.oaa.xxx.social.SystemMessageService;
|
||||
|
||||
@Component
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
package de.oaa.xxx.games.chastity.common;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import de.oaa.xxx.games.chastity.verification.VerificationEntity;
|
||||
import de.oaa.xxx.games.chastity.verification.VerificationVoteEntity;
|
||||
import de.oaa.xxx.games.chastity.verification.VerificationVoteRepository;
|
||||
|
||||
public abstract class AbstractLockService {
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(AbstractLockService.class);
|
||||
private final VerificationVoteRepository verificationVoteRepository;
|
||||
|
||||
public AbstractLockService(VerificationVoteRepository verificationVoteRepository) {
|
||||
this.verificationVoteRepository = verificationVoteRepository;
|
||||
}
|
||||
|
||||
protected boolean isValid(VerificationEntity entity) {
|
||||
LOGGER.trace("isValid");
|
||||
int count = 0;
|
||||
for (VerificationVoteEntity vote : verificationVoteRepository.findAllByVerificationId(entity.getVerficationId())) {
|
||||
if (vote.isUpvote()) {
|
||||
count++;
|
||||
} else {
|
||||
count--;
|
||||
}
|
||||
}
|
||||
return count >= 0;
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package de.oaa.xxx.games.chastity;
|
||||
package de.oaa.xxx.games.chastity.common;
|
||||
|
||||
import java.util.Random;
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
package de.oaa.xxx.games.chastity.common;
|
||||
|
||||
public enum LockType {
|
||||
|
||||
CARD, TIMED;
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
package de.oaa.xxx.games.chastity.common;
|
||||
|
||||
public enum PenaltyType {
|
||||
|
||||
ADD, FREEZE, PILLORY;
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package de.oaa.xxx.games.chastity;
|
||||
package de.oaa.xxx.games.chastity.keyholder;
|
||||
|
||||
import jakarta.persistence.*;
|
||||
import lombok.Getter;
|
||||
@@ -1,4 +1,4 @@
|
||||
package de.oaa.xxx.games.chastity;
|
||||
package de.oaa.xxx.games.chastity.keyholder;
|
||||
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
@@ -1,4 +1,4 @@
|
||||
package de.oaa.xxx.games.chastity.cardlock;
|
||||
package de.oaa.xxx.games.chastity.keyholder;
|
||||
|
||||
import jakarta.persistence.*;
|
||||
import lombok.Getter;
|
||||
@@ -7,11 +7,13 @@ import lombok.Setter;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.UUID;
|
||||
|
||||
import de.oaa.xxx.games.chastity.unlock.TempOpeningReason;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
@Entity
|
||||
@Table(name = "hygiene_violation")
|
||||
public class HygieneViolationEntity {
|
||||
@Table(name = "keyholder_notification")
|
||||
public class KeyholderNotificationEntity {
|
||||
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.UUID)
|
||||
@@ -34,4 +36,7 @@ public class HygieneViolationEntity {
|
||||
|
||||
@Column(nullable = false)
|
||||
private boolean notifiedKeyholder = false;
|
||||
|
||||
@Column(nullable = false)
|
||||
private TempOpeningReason openingReason;
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
package de.oaa.xxx.games.chastity.keyholder;
|
||||
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
public interface KeyholderNotificationRepository extends JpaRepository<KeyholderNotificationEntity, UUID> {
|
||||
List<KeyholderNotificationEntity> findByKeyholderUserIdAndNotifiedKeyholderFalse(UUID keyholderUserId);
|
||||
List<KeyholderNotificationEntity> findByLockId(UUID lockId);
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package de.oaa.xxx.games.chastity.cardlock;
|
||||
package de.oaa.xxx.games.chastity.keyholder;
|
||||
|
||||
import jakarta.persistence.*;
|
||||
import lombok.Getter;
|
||||
@@ -1,4 +1,4 @@
|
||||
package de.oaa.xxx.games.chastity.cardlock;
|
||||
package de.oaa.xxx.games.chastity.keyholder;
|
||||
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import java.util.List;
|
||||
@@ -0,0 +1,16 @@
|
||||
package de.oaa.xxx.games.chastity.lockcontroll;
|
||||
|
||||
public abstract class LockControl {
|
||||
|
||||
protected final LockControlCallback callback;
|
||||
|
||||
public LockControl(LockControlCallback callback) {
|
||||
this.callback = callback;
|
||||
}
|
||||
|
||||
public abstract boolean init();
|
||||
|
||||
public abstract boolean unlock();
|
||||
|
||||
public abstract boolean lock();
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
package de.oaa.xxx.games.chastity.lockcontroll;
|
||||
|
||||
public interface LockControlCallback {
|
||||
|
||||
void setUnlockCode(String code);
|
||||
|
||||
int getUnlockcodeLenght();
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
package de.oaa.xxx.games.chastity.lockcontroll;
|
||||
|
||||
public enum LockControllType {
|
||||
|
||||
TTLOCK, UNLOCK_CODE, TRUST;
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package de.oaa.xxx.games.chastity.lockcontroll;
|
||||
|
||||
class NoInteractionCallback implements LockControlCallback {
|
||||
|
||||
@Override
|
||||
public void setUnlockCode(String code) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getUnlockcodeLenght() {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
package de.oaa.xxx.games.chastity.lockcontroll;
|
||||
|
||||
public class TTLockControl extends LockControl {
|
||||
|
||||
public TTLockControl() {
|
||||
super(new NoInteractionCallback());
|
||||
}
|
||||
|
||||
private static final String BASE_URL = "https://euapi.ttlock.com/";
|
||||
|
||||
@Override
|
||||
public boolean init() {
|
||||
// TODO Auto-generated method stub
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean unlock() {
|
||||
// TODO Auto-generated method stub
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean lock() {
|
||||
// TODO Auto-generated method stub
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package de.oaa.xxx.games.chastity.lockcontroll;
|
||||
|
||||
public class TrustLockControl extends LockControl {
|
||||
|
||||
public TrustLockControl() {
|
||||
super(new NoInteractionCallback());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean init() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean unlock() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean lock() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
package de.oaa.xxx.games.chastity.lockcontroll;
|
||||
|
||||
import de.oaa.xxx.games.chastity.common.CodeCreator;
|
||||
|
||||
public class UnlockcodeLockControl extends LockControl {
|
||||
|
||||
public UnlockcodeLockControl(LockControlCallback callback) {
|
||||
super(callback);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean init() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean unlock() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean lock() {
|
||||
var code = CodeCreator.createAlphanumericCode(callback.getUnlockcodeLenght());
|
||||
callback.setUnlockCode(code);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package de.oaa.xxx.games.chastity;
|
||||
package de.oaa.xxx.games.chastity.lockee;
|
||||
|
||||
import java.security.Principal;
|
||||
import java.security.SecureRandom;
|
||||
@@ -220,7 +220,7 @@ public class LockeeInvitationController {
|
||||
LocalDateTime now = LocalDateTime.now();
|
||||
lock.setStartTime(now);
|
||||
lock.setUnlockCode(unlockCode);
|
||||
lock.setUnlockCodeLines(codeLines);
|
||||
lock.setUnlockCodeLength(codeLines);
|
||||
lock.setAvailableCards(new ArrayList<>(lock.getInitialCards()));
|
||||
lock.setOpenPicks(0);
|
||||
lock.setNextCardIn(now.plusMinutes(lock.getPickEveryMinute()));
|
||||
@@ -1,4 +1,4 @@
|
||||
package de.oaa.xxx.games.chastity;
|
||||
package de.oaa.xxx.games.chastity.lockee;
|
||||
|
||||
import jakarta.persistence.*;
|
||||
import lombok.Getter;
|
||||
@@ -1,4 +1,4 @@
|
||||
package de.oaa.xxx.games.chastity;
|
||||
package de.oaa.xxx.games.chastity.lockee;
|
||||
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
package de.oaa.xxx.games.chastity.pillory;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.UUID;
|
||||
|
||||
import jakarta.persistence.Column;
|
||||
import jakarta.persistence.Entity;
|
||||
import jakarta.persistence.GeneratedValue;
|
||||
import jakarta.persistence.GenerationType;
|
||||
import jakarta.persistence.Id;
|
||||
import jakarta.persistence.Table;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
@Entity
|
||||
@Table(name = "pillory")
|
||||
public class PilloryEntity {
|
||||
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.UUID)
|
||||
@Column
|
||||
@Setter(lombok.AccessLevel.NONE)
|
||||
private UUID pilloryId;
|
||||
@Column(nullable = false)
|
||||
private UUID lockId;
|
||||
@Column(nullable = false)
|
||||
private UUID lockeeUserId;
|
||||
@Column(nullable = false)
|
||||
private LocalDateTime createdAt;
|
||||
@Column
|
||||
private PilloryReason reason;
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package de.oaa.xxx.games.chastity.pillory;
|
||||
|
||||
public enum PilloryReason {
|
||||
|
||||
HYGIENE_OPENING_EXEEDED,
|
||||
KEYHOLDER_DESCESSION;
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package de.oaa.xxx.games.chastity.pillory;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
|
||||
public interface PilloryRepository extends JpaRepository<PilloryEntity, UUID> {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
package de.oaa.xxx.games.chastity.spinningwheel;
|
||||
|
||||
import de.oaa.xxx.games.chastity.timelock.TimeLockService;
|
||||
|
||||
public enum EntryType {
|
||||
|
||||
ADD_TIME {
|
||||
@Override
|
||||
public void apply(TimeLockService service, Integer intVal, String stringVal) {
|
||||
service.addTime(intVal);
|
||||
}
|
||||
},
|
||||
REMOVE_TIME {
|
||||
@Override
|
||||
public void apply(TimeLockService service, Integer intVal, String stringVal) {
|
||||
service.removeTime(intVal);
|
||||
}
|
||||
},
|
||||
FREEZE_TIME {
|
||||
@Override
|
||||
public void apply(TimeLockService service, Integer intVal, String stringVal) {
|
||||
service.freeze(intVal);
|
||||
}
|
||||
},
|
||||
FREEZE {
|
||||
@Override
|
||||
public void apply(TimeLockService service, Integer intVal, String stringVal) {
|
||||
service.freeze();
|
||||
}
|
||||
},
|
||||
UNFREEZE {
|
||||
@Override
|
||||
public void apply(TimeLockService service, Integer intVal, String stringVal) {
|
||||
service.unfreeze();
|
||||
}
|
||||
},
|
||||
TASK {
|
||||
@Override
|
||||
public void apply(TimeLockService service, Integer intVal, String stringVal) {
|
||||
service.task();
|
||||
}
|
||||
},
|
||||
TEXT {
|
||||
@Override
|
||||
public void apply(TimeLockService service, Integer intVal, String stringVal) {
|
||||
service.text(intVal, stringVal);
|
||||
}
|
||||
};
|
||||
|
||||
public abstract void apply(TimeLockService service, Integer intVal, String stringVal);
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
package de.oaa.xxx.games.chastity.spinningwheel;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import com.fasterxml.jackson.core.type.TypeReference;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
|
||||
import jakarta.persistence.AttributeConverter;
|
||||
import jakarta.persistence.Converter;
|
||||
|
||||
@Converter
|
||||
public class SpinningWheelConverter implements AttributeConverter<List<SpinningWheelEntry>, String> {
|
||||
|
||||
private static final ObjectMapper mapper = new ObjectMapper();
|
||||
|
||||
@Override
|
||||
public String convertToDatabaseColumn(List<SpinningWheelEntry> list) {
|
||||
if (list == null || list.isEmpty())
|
||||
return null;
|
||||
try {
|
||||
return mapper.writeValueAsString(list);
|
||||
} catch (Exception e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<SpinningWheelEntry> convertToEntityAttribute(String json) {
|
||||
if (json == null || json.isBlank())
|
||||
return new ArrayList<>();
|
||||
try {
|
||||
return new ArrayList<>(mapper.readValue(json, new TypeReference<List<SpinningWheelEntry>>() {
|
||||
}));
|
||||
} catch (Exception e) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package de.oaa.xxx.games.chastity.spinningwheel;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
public class SpinningWheelEntity {
|
||||
|
||||
private UUID wheelId;
|
||||
private String name;
|
||||
private List<SpinningWheelEntity> entries;
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
package de.oaa.xxx.games.chastity.spinningwheel;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.Setter;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class SpinningWheelEntry {
|
||||
|
||||
private EntryType type;
|
||||
private Integer intVal;
|
||||
private String stringVal;
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package de.oaa.xxx.games.chastity.spinningwheel;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
public class SpinningWheelEntryEntity {
|
||||
|
||||
private UUID entryId;
|
||||
private EntryType type;
|
||||
private Integer intVal;
|
||||
private String stringVal;
|
||||
|
||||
public SpinningWheelEntry toSpinningWheelEntry() {
|
||||
return new SpinningWheelEntry(type, intVal, stringVal);
|
||||
}
|
||||
}
|
||||
@@ -45,6 +45,9 @@ public class AssignedTaskEntity {
|
||||
/** Wie viele rote Karten hinzufügen bei Ablehnung / Ablauf (null = keine). */
|
||||
@Column
|
||||
private Integer penaltyRedCards;
|
||||
|
||||
@Column
|
||||
private Integer penaltyAddTime;
|
||||
|
||||
/** PENDING | ACCEPTED | DECLINED | EXPIRED */
|
||||
@Column(nullable = false)
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
package de.oaa.xxx.games.chastity.tasks;
|
||||
|
||||
public enum TaskMode {
|
||||
RANDOM, KEYHOLDER, COMMUNITY;
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package de.oaa.xxx.games.chastity.timelock;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
import de.oaa.xxx.games.chastity.lockcontroll.LockControllType;
|
||||
|
||||
public record TimeLockAdditionalSettings(LockControllType controllType, UUID lockee, UUID keyholder, boolean testlock, Integer unlockCodeLength) {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,117 @@
|
||||
package de.oaa.xxx.games.chastity.timelock;
|
||||
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
import de.oaa.xxx.games.chastity.common.PenaltyType;
|
||||
import de.oaa.xxx.games.chastity.spinningwheel.SpinningWheelConverter;
|
||||
import de.oaa.xxx.games.chastity.spinningwheel.SpinningWheelEntry;
|
||||
import de.oaa.xxx.games.chastity.tasks.Task;
|
||||
import de.oaa.xxx.games.chastity.tasks.TaskListConverter;
|
||||
import de.oaa.xxx.games.chastity.tasks.TaskMode;
|
||||
import de.oaa.xxx.games.chastity.unlock.TempOpeningReason;
|
||||
import jakarta.persistence.Column;
|
||||
import jakarta.persistence.Convert;
|
||||
import jakarta.persistence.Entity;
|
||||
import jakarta.persistence.GeneratedValue;
|
||||
import jakarta.persistence.GenerationType;
|
||||
import jakarta.persistence.Id;
|
||||
import jakarta.persistence.Table;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
@Entity
|
||||
@Table(name = "time_lock")
|
||||
public class TimeLockEntity {
|
||||
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.UUID)
|
||||
@Column
|
||||
private UUID lockId;
|
||||
@Column
|
||||
private String name;
|
||||
// Settings
|
||||
@Column(nullable = false)
|
||||
private UUID lockee;
|
||||
@Column
|
||||
private UUID keyholder;
|
||||
@Column
|
||||
private LocalDateTime startTime;
|
||||
@Column
|
||||
private LocalDateTime unlockTime;
|
||||
@Column
|
||||
private boolean endTimeVisible;
|
||||
@Convert(converter = TaskListConverter.class)
|
||||
@Column(columnDefinition = "TEXT")
|
||||
private List<Task> tasks;
|
||||
@Column
|
||||
private Integer taskEveryMinutes;
|
||||
@Column
|
||||
private Integer minTasksPerDay;
|
||||
@Convert(converter = SpinningWheelConverter.class)
|
||||
@Column(columnDefinition = "TEXT")
|
||||
private List<SpinningWheelEntry> spinningWheelEntries;
|
||||
@Column
|
||||
private Integer hygineOpeningDurationMinutes;
|
||||
@Column
|
||||
private Integer hygineOpeningEveryMinites;
|
||||
@Column
|
||||
private boolean requiresVerification;
|
||||
@Column
|
||||
private boolean testLock;
|
||||
@Column
|
||||
private Integer unlockCodeLength;
|
||||
@Column(nullable = false)
|
||||
private TaskMode taskMode = TaskMode.RANDOM;
|
||||
@Column
|
||||
private Integer spinsEveryMinutes;
|
||||
@Column
|
||||
private Integer minSpinsPerDay;
|
||||
@Column
|
||||
private PenaltyType penaltyType;
|
||||
@Column
|
||||
private Integer penaltyValue;
|
||||
|
||||
@Column
|
||||
private LocalDateTime lastHygineOpening;
|
||||
@Column
|
||||
private LocalDateTime tempOpeningTime; // If null, not while hygine opening
|
||||
@Column
|
||||
private Integer tempOpeningDuration;
|
||||
@Column
|
||||
private TempOpeningReason tempOpeningReason;
|
||||
@Column
|
||||
private LocalDateTime frozenFrom;
|
||||
@Column
|
||||
private LocalDateTime frozenUntil;
|
||||
@Column
|
||||
private String currentTask;
|
||||
@Column(columnDefinition = "TEXT")
|
||||
private String currentTaskDescription;
|
||||
@Column
|
||||
private LocalDateTime taskUntil;
|
||||
@Column
|
||||
private String unlockCode;
|
||||
/** Keyholder hat Unlock angefordert – nächste Aktion der Lockee zeigt grüne Karte */
|
||||
@Column(nullable = false)
|
||||
private boolean keyholderRequestedUnlock = false;
|
||||
/** Lockee hat Notfall-Entsperrung angefordert */
|
||||
@Column
|
||||
private java.time.LocalDateTime emergencyUnlockRequestedAt;
|
||||
/** true = System hat automatisch entsperrt (Keyholderin nicht reagiert) */
|
||||
@Column(nullable = false)
|
||||
private boolean emergencyAutoUnlocked = false;
|
||||
@Column
|
||||
private List<LocalDateTime> taskTimes;
|
||||
@Column
|
||||
private List<LocalDateTime> spinningWheelTimes;
|
||||
@Column
|
||||
private LocalDate lastCheck;
|
||||
|
||||
public TaskMode getTaskMode() { return taskMode != null ? taskMode : TaskMode.RANDOM; }
|
||||
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package de.oaa.xxx.games.chastity.timelock;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
|
||||
public interface TimeLockRepository extends JpaRepository<TimeLockEntity, UUID> {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,381 @@
|
||||
package de.oaa.xxx.games.chastity.timelock;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.temporal.ChronoUnit;
|
||||
import java.util.Random;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import de.oaa.xxx.games.chastity.common.AbstractLockService;
|
||||
import de.oaa.xxx.games.chastity.common.CodeCreator;
|
||||
import de.oaa.xxx.games.chastity.keyholder.KeyholderNotificationEntity;
|
||||
import de.oaa.xxx.games.chastity.keyholder.KeyholderNotificationRepository;
|
||||
import de.oaa.xxx.games.chastity.lockcontroll.LockControl;
|
||||
import de.oaa.xxx.games.chastity.lockcontroll.LockControlCallback;
|
||||
import de.oaa.xxx.games.chastity.lockcontroll.TTLockControl;
|
||||
import de.oaa.xxx.games.chastity.lockcontroll.TrustLockControl;
|
||||
import de.oaa.xxx.games.chastity.lockcontroll.UnlockcodeLockControl;
|
||||
import de.oaa.xxx.games.chastity.spinningwheel.SpinningWheelEntry;
|
||||
import de.oaa.xxx.games.chastity.tasks.Task;
|
||||
import de.oaa.xxx.games.chastity.tasks.TaskMode;
|
||||
import de.oaa.xxx.games.chastity.unlock.TempOpeningReason;
|
||||
import de.oaa.xxx.games.chastity.unlock.UnlockCodeHistoryService;
|
||||
import de.oaa.xxx.games.chastity.verification.VerificationRepository;
|
||||
import de.oaa.xxx.games.chastity.verification.VerificationVoteRepository;
|
||||
import de.oaa.xxx.games.history.GameHistoryEntity;
|
||||
import de.oaa.xxx.games.history.GameHistoryRepository;
|
||||
import de.oaa.xxx.user.UserRepository;
|
||||
|
||||
public class TimeLockService extends AbstractLockService implements LockControlCallback {
|
||||
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(TimeLockService.class);
|
||||
private final TimeLockEntity lock;
|
||||
private final TimeLockRepository timeLockRepository;
|
||||
private final VerificationRepository verificationRepository;
|
||||
private final GameHistoryRepository gameHistoryRepository;
|
||||
private final UserRepository userRepository;
|
||||
private final KeyholderNotificationRepository keyholderNotificationRepository;
|
||||
private final UnlockCodeHistoryService unlockCodeHistoryService;
|
||||
|
||||
private LockControl lockControl;
|
||||
|
||||
public TimeLockService(TimeLockEntity lock, VerificationRepository verificationRepository,
|
||||
VerificationVoteRepository verificationVoteRepository,
|
||||
TimeLockRepository timeLockRepository,
|
||||
GameHistoryRepository gameHistoryRepository,
|
||||
UserRepository userRepository,
|
||||
KeyholderNotificationRepository keyholderNotificationRepository,
|
||||
UnlockCodeHistoryService unlockCodeHistoryService) {
|
||||
super(verificationVoteRepository);
|
||||
this.lock = lock;
|
||||
this.timeLockRepository = timeLockRepository;
|
||||
this.verificationRepository = verificationRepository;
|
||||
this.gameHistoryRepository = gameHistoryRepository;
|
||||
this.userRepository = userRepository;
|
||||
this.keyholderNotificationRepository = keyholderNotificationRepository;
|
||||
this.unlockCodeHistoryService = unlockCodeHistoryService;
|
||||
}
|
||||
|
||||
public void init(TimeLockTemplate template, TimeLockAdditionalSettings settings) {
|
||||
switch (settings.controllType()) {
|
||||
case TTLOCK -> lockControl = new TTLockControl();
|
||||
case TRUST -> lockControl = new TrustLockControl();
|
||||
case UNLOCK_CODE -> lockControl = new UnlockcodeLockControl(this);
|
||||
}
|
||||
|
||||
lock.setLockee(UUID.randomUUID());
|
||||
lock.setName(template.name());
|
||||
lock.setLockee(settings.lockee());
|
||||
lock.setKeyholder(settings.keyholder());
|
||||
lock.setRequiresVerification(template.requiresVerification());
|
||||
lock.setTestLock(settings.testlock());
|
||||
lock.setUnlockCodeLength(settings.unlockCodeLength());
|
||||
|
||||
lock.setStartTime(LocalDateTime.now());
|
||||
Integer unlockTimeMinutes = template.maxTimeInMinutes();
|
||||
if (template.minTimeInMinutes() != null) {
|
||||
unlockTimeMinutes = new Random().nextInt(template.minTimeInMinutes(), template.maxTimeInMinutes());
|
||||
}
|
||||
lock.setUnlockTime(LocalDateTime.now().plusMinutes(unlockTimeMinutes));
|
||||
lock.setEndTimeVisible(template.endTimeVisible());
|
||||
|
||||
lock.setTasks(template.tasks());
|
||||
lock.setTaskEveryMinutes(template.taskEveryMinutes());
|
||||
lock.setMinTasksPerDay(template.minTasksPerDay());
|
||||
|
||||
lock.setSpinningWheelEntries(template.spinningWheelEntries());
|
||||
lock.setSpinsEveryMinutes(template.spinsEveryMinutes());
|
||||
lock.setMinSpinsPerDay(template.minSpinsPerDay());
|
||||
|
||||
lock.setHygineOpeningDurationMinutes(template.hygineOpeningDurationMinutes());
|
||||
lock.setHygineOpeningEveryMinites(template.hygineOpeningEveryMinites());
|
||||
|
||||
lock.setTaskMode(template.taskMode());
|
||||
|
||||
lockControl.lock();
|
||||
}
|
||||
|
||||
public SpinningWheelEntry spinWheel() {
|
||||
if (TempOpeningReason.HYGIENE != lock.getTempOpeningReason() ) {
|
||||
var entries = lock.getSpinningWheelEntries();
|
||||
var entry = entries.get(new Random().nextInt(entries.size()));
|
||||
entry.getType().apply(this, entry.getIntVal(), entry.getStringVal());
|
||||
return entry;
|
||||
}
|
||||
// Nicht während der Hyhiene Öffnung
|
||||
return null;
|
||||
}
|
||||
|
||||
public void addTime(Integer intVal) {
|
||||
LOGGER.debug("Lock addTime: %s minutes", intVal);
|
||||
lock.setUnlockTime(lock.getUnlockTime().plusMinutes(intVal));
|
||||
}
|
||||
|
||||
public void removeTime(Integer intVal) {
|
||||
LOGGER.debug("Lock removeTime: %s minutes", intVal);
|
||||
lock.setUnlockTime(lock.getUnlockTime().minusMinutes(intVal));
|
||||
}
|
||||
|
||||
public void freeze(Integer intVal) {
|
||||
LOGGER.debug("Lock frozen for %s minutes", intVal);
|
||||
lock.setFrozenFrom(LocalDateTime.now());
|
||||
lock.setFrozenUntil(LocalDateTime.now().plusMinutes(intVal));
|
||||
}
|
||||
|
||||
public void freeze() {
|
||||
LOGGER.debug("Lock frozen");
|
||||
lock.setFrozenFrom(LocalDateTime.now());
|
||||
}
|
||||
|
||||
public void unfreeze() {
|
||||
if (lock.getFrozenFrom() != null) {
|
||||
var unfreeTime = lock.getFrozenUntil() != null ? lock.getFrozenUntil() : LocalDateTime.now();
|
||||
var diff = ChronoUnit.MINUTES.between(lock.getFrozenFrom(), unfreeTime);
|
||||
LOGGER.debug("Lock unfrozen - adding %s minutes to the lock", diff);
|
||||
lock.setUnlockTime(lock.getUnlockTime().plusMinutes(diff));
|
||||
} else {
|
||||
LOGGER.debug("Lock not frozen - ignore Call");
|
||||
}
|
||||
}
|
||||
|
||||
public void task() {
|
||||
if (TempOpeningReason.HYGIENE != lock.getTempOpeningReason() ) {
|
||||
switch (lock.getTaskMode()) {
|
||||
case TaskMode.RANDOM -> applyRandomTask();
|
||||
case TaskMode.KEYHOLDER -> startKeyHolderVote();
|
||||
case TaskMode.COMMUNITY -> startCommunityVode();
|
||||
}
|
||||
}
|
||||
// Nicht während der Hyhiene Öffnung
|
||||
}
|
||||
|
||||
private void startKeyHolderVote() {
|
||||
// Keyholder Vote starten
|
||||
}
|
||||
|
||||
private void startCommunityVode() {
|
||||
// Community Vote starten
|
||||
}
|
||||
|
||||
public void applyRandomTask() {
|
||||
LOGGER.debug("Apply random task");
|
||||
var tasks = lock.getTasks();
|
||||
if (!tasks.isEmpty()) {
|
||||
task(tasks.get(new Random().nextInt(tasks.size())));
|
||||
}
|
||||
}
|
||||
|
||||
public void task(Task task) {
|
||||
LOGGER.debug("Apply task {}", task);
|
||||
lock.setCurrentTask(task.resolveTitle());
|
||||
lock.setCurrentTaskDescription(task.getDescription());
|
||||
if (task.getMinutes() != null && task.getMinutes() > 0) {
|
||||
lock.setTaskUntil(LocalDateTime.now().plusMinutes(task.getMinutes()));
|
||||
}
|
||||
}
|
||||
|
||||
public void text(Integer intVal, String stringVal) {
|
||||
LOGGER.debug("Apply text {}", stringVal);
|
||||
lock.setCurrentTask(stringVal);
|
||||
if (intVal != null && intVal > 0) {
|
||||
lock.setTaskUntil(LocalDateTime.now().plusMinutes(intVal));
|
||||
}
|
||||
}
|
||||
|
||||
public String clearTask() {
|
||||
LOGGER.debug("Clear task");
|
||||
lock.setCurrentTask(null);
|
||||
lock.setCurrentTaskDescription(null);
|
||||
lock.setTaskUntil(null);
|
||||
return "";
|
||||
}
|
||||
|
||||
public void testUnfreeze() {
|
||||
if (lock.getFrozenUntil().isAfter(LocalDateTime.now())) {
|
||||
unfreeze();
|
||||
}
|
||||
}
|
||||
|
||||
public void unlock(String unlockCode) {
|
||||
lockControl.unlock();
|
||||
this.lock.setUnlockTime(LocalDateTime.now());
|
||||
boolean valid = true;
|
||||
if (lock.isEmergencyAutoUnlocked()) {
|
||||
valid = false;
|
||||
LOGGER.debug("Lock invalid - Emergency Auto-Unlock (1h timer)");
|
||||
}
|
||||
if (lock.isTestLock()) {
|
||||
valid = false;
|
||||
} else if (Duration.between(lock.getStartTime(), lock.getUnlockTime()).toHours() > 24) {
|
||||
Set<LocalDate> verifications = verificationRepository.findByLockId(this.lock.getLockId()).stream()
|
||||
.filter(verification -> isValid(verification))
|
||||
.map(verification -> verification.getVerificationTime().toLocalDate()).collect(Collectors.toSet());
|
||||
|
||||
LocalDate current = this.lock.getStartTime().toLocalDate();
|
||||
LocalDate last = this.lock.getUnlockTime().toLocalDate().minusDays(1);
|
||||
|
||||
while (!current.isAfter(last)) {
|
||||
if (!verifications.contains(current)) {
|
||||
valid = false;
|
||||
LOGGER.debug("Lock invalid - no daily verification on %s", current.toString());
|
||||
break;
|
||||
}
|
||||
current = current.plusDays(1);
|
||||
}
|
||||
}
|
||||
|
||||
lock.setUnlockTime(LocalDateTime.now());
|
||||
LOGGER.debug("Unlocked at {}", lock.getUnlockTime());
|
||||
timeLockRepository.save(lock);
|
||||
|
||||
if (valid) {
|
||||
long durationMinutes = Duration.between(lock.getStartTime(), lock.getUnlockTime()).toMinutes();
|
||||
|
||||
// Gemeinsamer History-Eintrag mit Teilnehmerliste
|
||||
GameHistoryEntity entry = new GameHistoryEntity();
|
||||
entry.setGameType(de.oaa.xxx.games.history.GameType.CARDLOCK);
|
||||
entry.setGameName(lock.getName());
|
||||
entry.setStartTime(lock.getStartTime());
|
||||
entry.setEndTime(lock.getUnlockTime());
|
||||
entry.setDurationMinutes(durationMinutes);
|
||||
entry.addParticipant(lock.getLockee(), de.oaa.xxx.games.history.GameRole.LOCKEE);
|
||||
if (lock.getKeyholder() != null) {
|
||||
entry.addParticipant(lock.getKeyholder(), de.oaa.xxx.games.history.GameRole.KEYHOLDER);
|
||||
}
|
||||
gameHistoryRepository.save(entry);
|
||||
|
||||
int minutes = (int) durationMinutes;
|
||||
userRepository.findById(lock.getLockee()).ifPresent(u -> {
|
||||
u.setLockeeXp(u.getLockeeXp() + minutes);
|
||||
userRepository.save(u);
|
||||
});
|
||||
if (lock.getKeyholder() != null) {
|
||||
userRepository.findById(lock.getKeyholder()).ifPresent(u -> {
|
||||
u.setKeyholderXp(u.getKeyholderXp() + minutes);
|
||||
userRepository.save(u);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void applyPenalty() {
|
||||
if (lock.getPenaltyType() != null) {
|
||||
switch (lock.getPenaltyType()) {
|
||||
case ADD -> addTime(lock.getPenaltyValue());
|
||||
case FREEZE -> freeze();
|
||||
case PILLORY -> pillory();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void check() {
|
||||
LocalDate today = LocalDate.now();
|
||||
if (!lock.getStartTime().toLocalDate().equals(today)) {
|
||||
if (lock.getLastCheck() != null || today.isAfter(lock.getLastCheck())) {
|
||||
LOGGER.info("Check the day before for violations");
|
||||
LocalDate yesterday = today.minusDays(1);
|
||||
boolean violation = false;
|
||||
if (lock.getMinTasksPerDay() != null) {
|
||||
if (lock.getMinTasksPerDay() > lock.getTaskTimes().stream().map(LocalDateTime::toLocalDate)
|
||||
.filter(yesterday::equals).count()) {
|
||||
violation = true;
|
||||
}
|
||||
}
|
||||
if (lock.getMinSpinsPerDay() != null) {
|
||||
if (lock.getMinSpinsPerDay() > lock.getSpinningWheelTimes().stream().map(LocalDateTime::toLocalDate)
|
||||
.filter(yesterday::equals).count()) {
|
||||
violation = true;
|
||||
}
|
||||
}
|
||||
if (violation) {
|
||||
applyPenalty();
|
||||
}
|
||||
lock.setLastCheck(today);
|
||||
timeLockRepository.save(lock);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void pillory() {
|
||||
// TODO an den Pranger stellen
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setUnlockCode(String code) {
|
||||
lock.setUnlockCode(code);
|
||||
timeLockRepository.save(lock);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getUnlockcodeLenght() {
|
||||
return lock.getUnlockCodeLength();
|
||||
}
|
||||
|
||||
|
||||
public void startHygieneOpening() {
|
||||
tempOperning(TempOpeningReason.HYGIENE, lock.getHygineOpeningDurationMinutes());
|
||||
}
|
||||
|
||||
private Long calcOvertime() {
|
||||
LocalDateTime now = LocalDateTime.now();
|
||||
Long overtime = null;
|
||||
if (lock.getTempOpeningTime() != null && lock.getTempOpeningDuration() != null) {
|
||||
LocalDateTime dueTime = lock.getTempOpeningTime().plusMinutes(lock.getTempOpeningDuration());
|
||||
if (LocalDateTime.now().isAfter(dueTime)) {
|
||||
overtime = ChronoUnit.MINUTES.between(dueTime, now);
|
||||
}
|
||||
}
|
||||
return overtime;
|
||||
}
|
||||
|
||||
public String endHygieneOpening() {
|
||||
lockControl.lock();
|
||||
LocalDateTime now = LocalDateTime.now();
|
||||
|
||||
Long overtime = calcOvertime();
|
||||
if (overtime != null) {
|
||||
if (lock.getKeyholder() != null) {
|
||||
reportKeyholder(overtime);
|
||||
}
|
||||
addOvertime(overtime);
|
||||
}
|
||||
lock.setLastHygineOpening(now);
|
||||
lock.setTempOpeningDuration(null);
|
||||
lock.setTempOpeningTime(null);
|
||||
|
||||
var code = CodeCreator.createAlphanumericCode(lock.getUnlockCodeLength());
|
||||
lock.setUnlockCode(code);
|
||||
timeLockRepository.save(lock);
|
||||
return code;
|
||||
}
|
||||
|
||||
private void reportKeyholder(Long overtime) {
|
||||
KeyholderNotificationEntity notification = new KeyholderNotificationEntity();
|
||||
notification.setLockId(lock.getLockId());
|
||||
notification.setLockeeId(lock.getLockee());
|
||||
notification.setKeyholderUserId(lock.getKeyholder());
|
||||
notification.setViolationTime(LocalDateTime.now());
|
||||
notification.setOvertimeMinutes(overtime);
|
||||
keyholderNotificationRepository.save(notification);
|
||||
}
|
||||
|
||||
private void addOvertime(Long overtime) {
|
||||
lock.setUnlockTime(lock.getUnlockTime().plusMinutes(overtime * 4));
|
||||
}
|
||||
|
||||
private void tempOperning(TempOpeningReason reason, Integer duration) {
|
||||
assert duration != null;
|
||||
lockControl.unlock();
|
||||
lock.setTempOpeningReason(reason);
|
||||
lock.setTempOpeningTime(LocalDateTime.now());;
|
||||
lock.setTempOpeningDuration(duration);
|
||||
timeLockRepository.save(lock);
|
||||
unlockCodeHistoryService.save(lock.getLockee(), lock.getLockId(), lock.getName(), lock.getUnlockCode(), reason.toString());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
package de.oaa.xxx.games.chastity.timelock;
|
||||
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import de.oaa.xxx.games.chastity.keyholder.KeyholderNotificationRepository;
|
||||
import de.oaa.xxx.games.chastity.unlock.UnlockCodeHistoryService;
|
||||
import de.oaa.xxx.games.chastity.verification.VerificationRepository;
|
||||
import de.oaa.xxx.games.chastity.verification.VerificationVoteRepository;
|
||||
import de.oaa.xxx.games.history.GameHistoryRepository;
|
||||
import de.oaa.xxx.user.UserRepository;
|
||||
@Service
|
||||
public class TimeLockServiceFactory {
|
||||
|
||||
|
||||
private final VerificationRepository verificationRepository;
|
||||
private final VerificationVoteRepository verificationVoteRepository;
|
||||
private final TimeLockRepository timeLockRepository;
|
||||
private final GameHistoryRepository gameHistoryRepository;
|
||||
private final UserRepository userRepository;
|
||||
private KeyholderNotificationRepository keyholderNotificationRepository;
|
||||
private final UnlockCodeHistoryService unlockCodeHistoryService;
|
||||
|
||||
public TimeLockServiceFactory(VerificationRepository verificationRepository,
|
||||
VerificationVoteRepository verificationVoteRepository,
|
||||
TimeLockRepository timeLockRepository,
|
||||
GameHistoryRepository gameHistoryRepository,
|
||||
UserRepository userRepository,
|
||||
KeyholderNotificationRepository keyholderNotificationRepository,
|
||||
UnlockCodeHistoryService unlockCodeHistoryService) {
|
||||
this.verificationRepository = verificationRepository;
|
||||
this.verificationVoteRepository = verificationVoteRepository;
|
||||
this.timeLockRepository = timeLockRepository;
|
||||
this.gameHistoryRepository = gameHistoryRepository;
|
||||
this.userRepository = userRepository;
|
||||
this.keyholderNotificationRepository = keyholderNotificationRepository;
|
||||
this.unlockCodeHistoryService = unlockCodeHistoryService;
|
||||
}
|
||||
|
||||
/**
|
||||
* Erstellt eine neue CardLockService-Instanz für das gegebene Lock.
|
||||
*/
|
||||
public TimeLockService create(TimeLockEntity lock) {
|
||||
return new TimeLockService(
|
||||
lock,
|
||||
verificationRepository,
|
||||
verificationVoteRepository,
|
||||
timeLockRepository,
|
||||
gameHistoryRepository,
|
||||
userRepository,
|
||||
keyholderNotificationRepository,
|
||||
unlockCodeHistoryService
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package de.oaa.xxx.games.chastity.timelock;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
import de.oaa.xxx.games.chastity.common.PenaltyType;
|
||||
import de.oaa.xxx.games.chastity.spinningwheel.SpinningWheelEntry;
|
||||
import de.oaa.xxx.games.chastity.tasks.Task;
|
||||
import de.oaa.xxx.games.chastity.tasks.TaskMode;
|
||||
|
||||
public record TimeLockTemplate(UUID templateId, UUID owner, String name, Integer minTimeInMinutes,
|
||||
Integer maxTimeInMinutes, boolean endTimeVisible, Integer hygineOpeningDurationMinutes,
|
||||
Integer hygineOpeningEveryMinites, List<Task> tasks, Integer taskEveryMinutes, Integer minTasksPerDay,
|
||||
List<SpinningWheelEntry> spinningWheelEntries, Integer spinsEveryMinutes, Integer minSpinsPerDay,
|
||||
boolean requiresVerification, TaskMode taskMode, PenaltyType penaltyType, Integer penaltyValue) {
|
||||
}
|
||||
@@ -0,0 +1,107 @@
|
||||
package de.oaa.xxx.games.chastity.timelock;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
import de.oaa.xxx.games.chastity.common.PenaltyType;
|
||||
import de.oaa.xxx.games.chastity.spinningwheel.SpinningWheelConverter;
|
||||
import de.oaa.xxx.games.chastity.spinningwheel.SpinningWheelEntry;
|
||||
import de.oaa.xxx.games.chastity.tasks.Task;
|
||||
import de.oaa.xxx.games.chastity.tasks.TaskListConverter;
|
||||
import de.oaa.xxx.games.chastity.tasks.TaskMode;
|
||||
import jakarta.persistence.Column;
|
||||
import jakarta.persistence.Convert;
|
||||
import jakarta.persistence.Entity;
|
||||
import jakarta.persistence.GeneratedValue;
|
||||
import jakarta.persistence.GenerationType;
|
||||
import jakarta.persistence.Id;
|
||||
import jakarta.persistence.Table;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
@Entity
|
||||
@Table(name = "timelock_template")
|
||||
public class TimeLockTemplateEntity {
|
||||
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.UUID)
|
||||
@Column
|
||||
private UUID templateId;
|
||||
@Column(nullable = false)
|
||||
private UUID owner;
|
||||
@Column
|
||||
private String name;
|
||||
@Column
|
||||
private Integer minTimeInMinutes;
|
||||
@Column
|
||||
private Integer maxTimeInMinutes;
|
||||
@Column
|
||||
private boolean endTimeVisible;
|
||||
@Column
|
||||
private Integer hygineOpeningDurationMinutes;
|
||||
@Column
|
||||
private Integer hygineOpeningEveryMinites;
|
||||
|
||||
@Convert(converter = TaskListConverter.class)
|
||||
@Column(columnDefinition = "TEXT")
|
||||
private List<Task> tasks;
|
||||
@Column
|
||||
private Integer taskEveryMinutes;
|
||||
@Column
|
||||
private Integer minTasksPerDay;
|
||||
|
||||
@Convert(converter = SpinningWheelConverter.class)
|
||||
@Column(columnDefinition = "TEXT")
|
||||
private List<SpinningWheelEntry> spinningWheelEntries;
|
||||
@Column
|
||||
private Integer spinsEveryMinutes;
|
||||
@Column
|
||||
private Integer minSpinsPerDay;
|
||||
|
||||
@Column
|
||||
private boolean requiresVerification;
|
||||
@Column(nullable = false)
|
||||
private TaskMode taskMode = TaskMode.RANDOM;
|
||||
@Column
|
||||
private PenaltyType penaltyType;
|
||||
@Column
|
||||
private Integer penaltyValue;
|
||||
|
||||
public TaskMode getTaskCardMode() {
|
||||
return taskMode != null ? taskMode : TaskMode.RANDOM;
|
||||
}
|
||||
|
||||
public TimeLockTemplate toTimeLockTemplate() {
|
||||
return new TimeLockTemplate(templateId, owner, name, minTimeInMinutes, maxTimeInMinutes, endTimeVisible,
|
||||
hygineOpeningDurationMinutes, hygineOpeningEveryMinites, tasks, taskEveryMinutes, minTasksPerDay,
|
||||
spinningWheelEntries, spinsEveryMinutes, minSpinsPerDay, requiresVerification, taskMode, penaltyType,
|
||||
penaltyValue);
|
||||
}
|
||||
|
||||
public static TimeLockTemplateEntity fromTemplate(TimeLockTemplate template) {
|
||||
if (template != null) {
|
||||
TimeLockTemplateEntity entity = new TimeLockTemplateEntity();
|
||||
entity.setOwner(template.owner());
|
||||
entity.setName(template.name());
|
||||
entity.setMinTimeInMinutes(template.minTimeInMinutes());
|
||||
entity.setMaxTimeInMinutes(template.maxTimeInMinutes());
|
||||
entity.setEndTimeVisible(template.endTimeVisible());
|
||||
entity.setHygineOpeningDurationMinutes(template.hygineOpeningDurationMinutes());
|
||||
entity.setHygineOpeningEveryMinites(template.hygineOpeningEveryMinites());
|
||||
entity.setTasks(template.tasks());
|
||||
entity.setTaskEveryMinutes(template.taskEveryMinutes());
|
||||
entity.setMinTasksPerDay(template.minTasksPerDay());
|
||||
entity.setSpinningWheelEntries(template.spinningWheelEntries());
|
||||
entity.setSpinsEveryMinutes(template.spinsEveryMinutes());
|
||||
entity.setMinSpinsPerDay(template.minSpinsPerDay());
|
||||
entity.setRequiresVerification(template.requiresVerification());
|
||||
entity.setTaskMode(template.taskMode() != null ? template.taskMode() : TaskMode.RANDOM);
|
||||
entity.setPenaltyType(template.penaltyType());
|
||||
entity.setPenaltyValue(template.penaltyValue());
|
||||
return entity;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,92 @@
|
||||
package de.oaa.xxx.games.chastity.timelock;
|
||||
|
||||
import static de.oaa.xxx.util.ValidationResult.ERROR;
|
||||
import static de.oaa.xxx.util.ValidationResult.OK;
|
||||
import static de.oaa.xxx.util.ValidationResult.WARNING;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
import de.oaa.xxx.games.chastity.spinningwheel.EntryType;
|
||||
import de.oaa.xxx.games.chastity.tasks.TaskMode;
|
||||
import de.oaa.xxx.util.ValidationResult;
|
||||
|
||||
public class TimeLockTemplateService {
|
||||
|
||||
private TimelockTemplateRepository timelockTemplateRepository;
|
||||
|
||||
public TimeLockTemplateService(TimelockTemplateRepository timelockTemplateRepository) {
|
||||
this.timelockTemplateRepository = timelockTemplateRepository;
|
||||
}
|
||||
|
||||
public List<TimeLockTemplate> all(UUID ownderId) {
|
||||
return timelockTemplateRepository.findByOwner(ownderId).stream().map(template -> template.toTimeLockTemplate()).toList();
|
||||
}
|
||||
|
||||
public boolean safe(TimeLockTemplate template) {
|
||||
var result = validate(template);
|
||||
if (ValidationResult.OK == result || ValidationResult.WARNING == result) {
|
||||
timelockTemplateRepository.save(TimeLockTemplateEntity.fromTemplate(template));
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public ValidationResult validate(TimeLockTemplate template) {
|
||||
if (template == null) {
|
||||
return ERROR;
|
||||
}
|
||||
if (template.owner() == null ||
|
||||
template.name() == null ||
|
||||
template.maxTimeInMinutes() == null) {
|
||||
return ERROR;
|
||||
}
|
||||
if (template.taskEveryMinutes() != null) {
|
||||
if (template.tasks() == null || template.tasks().isEmpty()) {
|
||||
return ERROR;
|
||||
}
|
||||
if (template.spinningWheelEntries() != null && !template.spinningWheelEntries().isEmpty()
|
||||
&& template.spinningWheelEntries().stream().anyMatch(entry -> EntryType.TASK == entry.getType())) {
|
||||
return ERROR;
|
||||
}
|
||||
if (template.minTasksPerDay() != null) {
|
||||
int minTime = getMinimumTime(template);
|
||||
if (minTime > (24*60)) {
|
||||
return ERROR;
|
||||
} else if (minTime > (12*60)) {
|
||||
return WARNING;
|
||||
}
|
||||
}
|
||||
} else if (template.minTasksPerDay() != null) {
|
||||
return ERROR;
|
||||
}
|
||||
if (template.spinsEveryMinutes() != null) {
|
||||
if (template.spinningWheelEntries() == null || template.spinningWheelEntries().isEmpty()) {
|
||||
return ERROR;
|
||||
}
|
||||
if (template.minSpinsPerDay() != null) {
|
||||
int minTime = template.spinsEveryMinutes() * template.minSpinsPerDay();
|
||||
if (minTime > (24*60)) {
|
||||
return ERROR;
|
||||
} else if (minTime > (12*60)) {
|
||||
return WARNING;
|
||||
}
|
||||
}
|
||||
} else if (template.minSpinsPerDay() != null) {
|
||||
return ERROR;
|
||||
}
|
||||
if (template.hygineOpeningEveryMinites() != null && template.hygineOpeningDurationMinutes() == null) {
|
||||
return ERROR;
|
||||
}
|
||||
return OK;
|
||||
}
|
||||
|
||||
private Integer getMinimumTime(TimeLockTemplate template) {
|
||||
int votetime = 0;
|
||||
if (TaskMode.COMMUNITY == template.taskMode() || TaskMode.KEYHOLDER == template.taskMode()) {
|
||||
votetime = 60 * template.minTasksPerDay();
|
||||
}
|
||||
int waittime = template.taskEveryMinutes() * template.minTasksPerDay();
|
||||
return votetime + waittime;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
package de.oaa.xxx.games.chastity.timelock;
|
||||
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
public interface TimelockTemplateRepository extends JpaRepository<TimeLockTemplateEntity, UUID> {
|
||||
List<TimeLockTemplateEntity> findByOwner(UUID owner);
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
package de.oaa.xxx.games.chastity.unlock;
|
||||
|
||||
public enum TempOpeningReason {
|
||||
HYGIENE, CARD, TASK;
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package de.oaa.xxx.games.chastity.cardlock;
|
||||
package de.oaa.xxx.games.chastity.unlock;
|
||||
|
||||
import jakarta.persistence.*;
|
||||
import lombok.Getter;
|
||||
@@ -1,4 +1,4 @@
|
||||
package de.oaa.xxx.games.chastity.cardlock;
|
||||
package de.oaa.xxx.games.chastity.unlock;
|
||||
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
@@ -1,4 +1,4 @@
|
||||
package de.oaa.xxx.games.chastity.cardlock;
|
||||
package de.oaa.xxx.games.chastity.unlock;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
@@ -23,7 +23,7 @@ import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import de.oaa.xxx.games.chastity.CodeCreator;
|
||||
import de.oaa.xxx.games.chastity.common.CodeCreator;
|
||||
import de.oaa.xxx.user.UserRepository;
|
||||
|
||||
@RestController
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package de.oaa.xxx.games.chastity.cardlock;
|
||||
package de.oaa.xxx.games.chastity.vote;
|
||||
|
||||
import jakarta.persistence.*;
|
||||
import lombok.Getter;
|
||||
@@ -1,4 +1,4 @@
|
||||
package de.oaa.xxx.games.chastity.cardlock;
|
||||
package de.oaa.xxx.games.chastity.vote;
|
||||
|
||||
import jakarta.persistence.*;
|
||||
import lombok.Getter;
|
||||
@@ -1,4 +1,4 @@
|
||||
package de.oaa.xxx.games.chastity.cardlock;
|
||||
package de.oaa.xxx.games.chastity.vote;
|
||||
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import java.util.List;
|
||||
@@ -1,4 +1,4 @@
|
||||
package de.oaa.xxx.games.chastity.cardlock;
|
||||
package de.oaa.xxx.games.chastity.vote;
|
||||
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import java.time.LocalDateTime;
|
||||
@@ -0,0 +1,5 @@
|
||||
package de.oaa.xxx.util;
|
||||
|
||||
public enum ValidationResult {
|
||||
OK, INFO, WARNING, ERROR;
|
||||
}
|
||||
@@ -0,0 +1,150 @@
|
||||
package de.oaa.xxx.games.chastity.timelock;
|
||||
|
||||
import de.oaa.xxx.games.chastity.spinningwheel.EntryType;
|
||||
import de.oaa.xxx.games.chastity.spinningwheel.SpinningWheelEntry;
|
||||
import de.oaa.xxx.games.chastity.tasks.Task;
|
||||
import de.oaa.xxx.games.chastity.tasks.TaskMode;
|
||||
import de.oaa.xxx.util.ValidationResult;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.mockito.Mockito;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
class TimeLockTemplateServiceTest {
|
||||
|
||||
private final TimeLockTemplateService service = new TimeLockTemplateService(null);
|
||||
|
||||
/**
|
||||
* Zentrale Factory-Methode für den Test.
|
||||
* Erzeugt immer ein frisches Record-Objekt.
|
||||
*/
|
||||
private TimeLockTemplate createTemplate(
|
||||
UUID owner, String name, Integer maxTime,
|
||||
Integer taskEvery, Integer minTasks, List<Task> tasks,
|
||||
Integer spinsEvery, Integer minSpins, List<SpinningWheelEntry> entries,
|
||||
Integer hygEvery, Integer hygDuration) {
|
||||
return createTemplate(owner, name, maxTime, taskEvery, minTasks, tasks, spinsEvery, minSpins, entries, hygEvery, hygDuration, TaskMode.RANDOM);
|
||||
}
|
||||
|
||||
private TimeLockTemplate createTemplate(
|
||||
UUID owner, String name, Integer maxTime,
|
||||
Integer taskEvery, Integer minTasks, List<Task> tasks,
|
||||
Integer spinsEvery, Integer minSpins, List<SpinningWheelEntry> entries,
|
||||
Integer hygEvery, Integer hygDuration, TaskMode taskMode) {
|
||||
|
||||
return new TimeLockTemplate(null,
|
||||
owner,
|
||||
name,
|
||||
0, // minTimeInMinutes
|
||||
maxTime,
|
||||
true, // endTimeVisible
|
||||
hygDuration,
|
||||
hygEvery,
|
||||
tasks,
|
||||
taskEvery,
|
||||
minTasks,
|
||||
entries,
|
||||
spinsEvery,
|
||||
minSpins,
|
||||
false, // requiresVerification
|
||||
taskMode,
|
||||
null, // penaltyType
|
||||
null // penaltyValue
|
||||
);
|
||||
}
|
||||
|
||||
// Hilfsmethode für ein schnelles Standard-Template
|
||||
private TimeLockTemplate validBase() {
|
||||
return createTemplate(UUID.randomUUID(), "Standard", 60, null, null, null, null, null, null, null, null);
|
||||
}
|
||||
|
||||
@Test
|
||||
void validate_OK_Minimal() {
|
||||
assertThat(service.validate(validBase())).isEqualTo(ValidationResult.OK);
|
||||
}
|
||||
|
||||
@Test
|
||||
void validate_ERROR_MissingMandatoryFields() {
|
||||
assertThat(service.validate(createTemplate(null, "Name", 10, null, null, null, null, null, null, null, null))).isEqualTo(ValidationResult.ERROR);
|
||||
assertThat(service.validate(createTemplate(UUID.randomUUID(), null, 10, null, null, null, null, null, null, null, null))).isEqualTo(ValidationResult.ERROR);
|
||||
assertThat(service.validate(createTemplate(UUID.randomUUID(), "Name", null, null, null, null, null, null, null, null, null))).isEqualTo(ValidationResult.ERROR);
|
||||
}
|
||||
|
||||
@Test
|
||||
void validate_ERROR_TasksButNoList() {
|
||||
// Intervall gesetzt, aber Liste ist null oder leer
|
||||
TimeLockTemplate tNull = createTemplate(UUID.randomUUID(), "T", 60, 10, null, null, null, null, null, null, null);
|
||||
TimeLockTemplate tEmpty = createTemplate(UUID.randomUUID(), "T", 60, 10, null, Collections.emptyList(), null, null, null, null, null);
|
||||
|
||||
assertThat(service.validate(tNull)).isEqualTo(ValidationResult.ERROR);
|
||||
assertThat(service.validate(tEmpty)).isEqualTo(ValidationResult.ERROR);
|
||||
}
|
||||
|
||||
@Test
|
||||
void validate_ERROR_SpinningWheelTaskConflict() {
|
||||
SpinningWheelEntry taskEntry = new SpinningWheelEntry();
|
||||
taskEntry.setType(EntryType.TASK);
|
||||
|
||||
TimeLockTemplate t = createTemplate(UUID.randomUUID(), "T", 60, 10, null, List.of(new Task()), null, null, List.of(taskEntry), null, null);
|
||||
|
||||
assertThat(service.validate(t)).isEqualTo(ValidationResult.ERROR);
|
||||
}
|
||||
|
||||
@Test
|
||||
void validate_WARNING_TaskTimeLimitReached() {
|
||||
// 120 Min Intervall * 7 Tasks = 840 Min (> 12h)
|
||||
TimeLockTemplate t = createTemplate(UUID.randomUUID(), "T", 60, 120, 7, List.of(new Task()), null, null, null, null, null);
|
||||
|
||||
assertThat(service.validate(t)).isEqualTo(ValidationResult.WARNING);
|
||||
}
|
||||
|
||||
@Test
|
||||
void validate_ERROR_MinTasksWithoutInterval() {
|
||||
TimeLockTemplate t = createTemplate(UUID.randomUUID(), "T", 60, null, 5, null, null, null, null, null, null);
|
||||
assertThat(service.validate(t)).isEqualTo(ValidationResult.ERROR);
|
||||
}
|
||||
|
||||
@Test
|
||||
void validate_ERROR_SpinsButNoEntries() {
|
||||
TimeLockTemplate t = createTemplate(UUID.randomUUID(), "T", 60, null, null, null, 30, 2, null, null, null);
|
||||
assertThat(service.validate(t)).isEqualTo(ValidationResult.ERROR);
|
||||
}
|
||||
|
||||
@Test
|
||||
void validate_WARNING_SpinTimeLimitReached() {
|
||||
// 200 Min Intervall * 4 Spins = 800 Min (> 12h)
|
||||
TimeLockTemplate t = createTemplate(UUID.randomUUID(), "T", 60, null, null, null, 200, 4, List.of(new SpinningWheelEntry()), null, null);
|
||||
|
||||
assertThat(service.validate(t)).isEqualTo(ValidationResult.WARNING);
|
||||
}
|
||||
|
||||
@Test
|
||||
void validate_ERROR_HygieneIncomplete() {
|
||||
// Intervall gesetzt, aber Dauer fehlt
|
||||
TimeLockTemplate t = createTemplate(UUID.randomUUID(), "T", 60, null, null, null, null, null, null, 60, null);
|
||||
assertThat(service.validate(t)).isEqualTo(ValidationResult.ERROR);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void validate_communityVotes() {
|
||||
TimeLockTemplate t = createTemplate(UUID.randomUUID(), "T", 60, 60, 6, List.of(new Task()), null, null, null, null, null,TaskMode.RANDOM);
|
||||
assertThat(service.validate(t)).isEqualTo(ValidationResult.OK);
|
||||
|
||||
t = createTemplate(UUID.randomUUID(), "T", 60, 60, 7, List.of(new Task()), null, null, null, null, null,TaskMode.COMMUNITY);
|
||||
assertThat(service.validate(t)).isEqualTo(ValidationResult.WARNING);
|
||||
|
||||
t = createTemplate(UUID.randomUUID(), "T", 60, 60, 12, List.of(new Task()), null, null, null, null, null,TaskMode.COMMUNITY);
|
||||
assertThat(service.validate(t)).isEqualTo(ValidationResult.WARNING);
|
||||
}
|
||||
|
||||
public void testErrorOnTasksAndTaskInWheel() {
|
||||
SpinningWheelEntry entry = Mockito.mock(SpinningWheelEntry.class);
|
||||
Mockito.when(entry.getType()).thenReturn(EntryType.TASK);
|
||||
TimeLockTemplate t = createTemplate(UUID.randomUUID(), "T", 60, 60, 6, List.of(new Task()), null, null, List.of(), null, null);
|
||||
assertThat(service.validate(t)).isEqualTo(ValidationResult.ERROR);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user