Skip to content

Commit

Permalink
Implement timeout respecting in challenges completion.
Browse files Browse the repository at this point in the history
Implement timeout in GUI's.

Relates #71
  • Loading branch information
BONNe committed Sep 24, 2021
1 parent 1b01995 commit bb5e861
Show file tree
Hide file tree
Showing 8 changed files with 202 additions and 6 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -251,13 +251,25 @@ public void addChallengeDone(@NonNull String challengeName, int times)
* @param challengeName - unique challenge name
* @param times - the number of times to set
*/
public void setChallengeTimes(@NonNull String challengeName, @NonNull int times)
public void setChallengeTimes(@NonNull String challengeName, int times)
{
challengeStatus.put(challengeName, times);
challengesTimestamp.put(challengeName, System.currentTimeMillis());
}


/**
* Gets last completion time.
*
* @param challengeName the unique id
* @return the last completion time
*/
public long getLastCompletionTime(@NonNull String challengeName)
{
return this.challengesTimestamp.getOrDefault(challengeName, 0L);
}


/**
* Check if a challenge has been done
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1397,6 +1397,43 @@ public boolean isChallengeComplete(UUID user, World world, String challengeID)
}


/**
* This method returns if given user breached timeout for given challenge.
* @param user - User that must be checked.
* @param world - World where challenge operates.
* @param challenge - Challenge that must be checked.
* @return True, if challenge is breached timeout, otherwise - false.
*/
public boolean isBreachingTimeOut(User user, World world, Challenge challenge)
{
if (challenge.getTimeout() <= 0)
{
// Challenge does not have a timeout.
return false;
}

return System.currentTimeMillis() <
this.getLastCompletionDate(user, world, challenge) + challenge.getTimeout();
}


/**
* Gets last completion date for given challenge.
*
* @param user the user
* @param world the world
* @param challenge the challenge
* @return the last completion date
*/
public long getLastCompletionDate(User user, World world, Challenge challenge)
{
String userId = this.getDataUniqueID(user, Util.getWorld(world));
this.addPlayerData(userId);

return this.playerCacheData.get(userId).getLastCompletionTime(challenge.getUniqueId());
}


/**
* This method sets given challenge as completed.
* @param user - Targeted user.
Expand Down
47 changes: 45 additions & 2 deletions src/main/java/world/bentobox/challenges/panel/CommonPanel.java
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
import org.eclipse.jdt.annotation.NonNull;
import org.eclipse.jdt.annotation.Nullable;

import java.time.*;
import java.util.*;
import java.util.stream.Collectors;

Expand Down Expand Up @@ -159,13 +160,17 @@ protected List<String> generateChallengeDescription(Challenge challenge, @Nullab
String requirements = isCompletedAll ? "" : this.generateRequirements(challenge, target);
// Get rewards in single string
String rewards = isCompletedAll ? "" : this.generateRewards(challenge, isCompletedOnce);
// Get coolDown in singe string
String coolDown = isCompletedAll || challenge.getTimeout() <= 0 ? "" :
this.generateCoolDown(challenge, target);

if (!description.replaceAll("(?m)^[ \\t]*\\r?\\n", "").isEmpty())
{
String returnString = this.user.getTranslationOrNothing(reference + "lore",
"[requirements]", requirements,
"[rewards]", rewards,
"[status]", status);
"[status]", status,
"[cooldown]", coolDown);

// remove empty lines from the generated text.
List<String> collect =
Expand All @@ -191,7 +196,8 @@ protected List<String> generateChallengeDescription(Challenge challenge, @Nullab
Constants.PARAMETER_DESCRIPTION, description,
"[requirements]", requirements,
"[rewards]", rewards,
"[status]", status);
"[status]", status,
"[cooldown]", coolDown);

// Remove empty lines and returns as a list.

Expand All @@ -202,6 +208,43 @@ protected List<String> generateChallengeDescription(Challenge challenge, @Nullab
}


/**
* Generate cool down string.
*
* @param challenge the challenge
* @param target the target
* @return the string
*/
private String generateCoolDown(Challenge challenge, @Nullable User target)
{
final String reference = Constants.DESCRIPTIONS + "challenge.cooldown.";

String coolDown;

if (target != null && this.manager.isBreachingTimeOut(target, this.world, challenge))
{
long missing = this.manager.getLastCompletionDate(this.user, this.world, challenge) +
challenge.getTimeout() - System.currentTimeMillis();

coolDown = this.user.getTranslation(reference + "wait-time",
"[time]",
Utils.parseDuration(Duration.ofMillis(missing), this.user));
}
else
{
coolDown = "";
}

String timeout = this.user.getTranslation(reference + "timeout",
"[time]",
Utils.parseDuration(Duration.ofMillis(challenge.getTimeout()), this.user));

return this.user.getTranslation(reference + "lore",
"[timeout]", timeout,
"[wait-time]", coolDown);
}


/**
* This method generate requirements description for given challenge.
* @param challenge Challenge which requirements must be generated.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -303,6 +303,12 @@ private PanelItem createChallengeButton(ItemTemplateRecord template, @NonNull Ch
this.createChallengeButton(template, challenge).getItem());
}
}
else if (challenge.isRepeatable() && challenge.getTimeout() > 0)
{
// Update timeout after clicking.
panel.getInventory().setItem(i,
this.createChallengeButton(template, challenge).getItem());
}
break;
case "COMPLETE_MAX":
if (challenge.isRepeatable())
Expand All @@ -328,6 +334,12 @@ private PanelItem createChallengeButton(ItemTemplateRecord template, @NonNull Ch
this.createChallengeButton(template, challenge).getItem());
}
}
else if (challenge.getTimeout() > 0)
{
// Update timeout after clicking.
panel.getInventory().setItem(i,
this.createChallengeButton(template, challenge).getItem());
}
}
break;
case "MULTIPLE_PANEL":
Expand Down
20 changes: 17 additions & 3 deletions src/main/java/world/bentobox/challenges/tasks/TryToComplete.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@


import com.google.common.collect.UnmodifiableIterator;
import java.time.*;
import java.time.temporal.ChronoUnit;
import java.util.Arrays;
import java.util.Collections;
import java.util.EnumMap;
Expand Down Expand Up @@ -228,7 +230,8 @@ public static boolean complete(ChallengesAddon addon,
int maxTimes)
{
return new TryToComplete(addon, user, challenge, world, topLabel, permissionPrefix).
build(maxTimes).meetsRequirements;
build(maxTimes).
meetsRequirements;
}


Expand Down Expand Up @@ -713,6 +716,17 @@ else if (!this.challenge.isRepeatable() && this.manager.isChallengeComplete(this
Utils.sendMessage(this.user, this.user.getTranslation("challenges.errors.not-repeatable"));
result = EMPTY_RESULT;
}
// Check if timeout is not broken
else if (this.manager.isBreachingTimeOut(this.user, this.world, this.challenge))
{
long missing = this.manager.getLastCompletionDate(this.user, this.world, challenge) +
this.challenge.getTimeout() - System.currentTimeMillis();

Utils.sendMessage(this.user, this.user.getTranslation("challenges.errors.timeout",
"[timeout]", Utils.parseDuration(Duration.ofMillis(this.challenge.getTimeout()), this.user),
"[wait-time]", Utils.parseDuration(Duration.ofMillis(missing), this.user)));
result = EMPTY_RESULT;
}
// Check environment
else if (!this.challenge.getEnvironment().isEmpty() &&
!this.challenge.getEnvironment().contains(this.user.getWorld().getEnvironment()))
Expand Down Expand Up @@ -776,7 +790,7 @@ private boolean checkPermissions()
*/
private int getAvailableCompletionTimes(int vantedTimes)
{
if (!this.challenge.isRepeatable())
if (!this.challenge.isRepeatable() || this.challenge.getTimeout() > 0)
{
// Challenge is not repeatable
vantedTimes = 1;
Expand Down Expand Up @@ -1513,7 +1527,7 @@ private OtherRequirements getOtherRequirements()
*
* @author tastybento
*/
class ChallengeResult
static class ChallengeResult
{
/**
* This method sets that challenge meets all requirements at least once.
Expand Down
40 changes: 40 additions & 0 deletions src/main/java/world/bentobox/challenges/utils/Utils.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package world.bentobox.challenges.utils;


import java.time.Duration;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
Expand Down Expand Up @@ -878,4 +879,43 @@ public static String prettifyObject(ItemStack item, @Nullable BookMeta bookMeta,
"[type]", prettifyObject(itemType, user),
"[meta]", meta);
}


/**
* This method parses duration to a readable format.
* @param duration that needs to be parsed.
* @return parsed duration string.
*/
public static String parseDuration(Duration duration, User user)
{
final String reference = Constants.DESCRIPTIONS + "challenge.cooldown.";

String returnString = "";

if (duration.toDays() > 0)
{
returnString += user.getTranslationOrNothing(reference + "in-days",
Constants.PARAMETER_NUMBER, String.valueOf(duration.toDays()));
}

if (duration.toHoursPart() > 0)
{
returnString += user.getTranslationOrNothing(reference + "in-hours",
Constants.PARAMETER_NUMBER, String.valueOf(duration.toHoursPart()));
}

if (duration.toMinutesPart() > 0)
{
returnString += user.getTranslationOrNothing(reference + "in-minutes",
Constants.PARAMETER_NUMBER, String.valueOf(duration.toMinutesPart()));
}

if (duration.toSecondsPart() > 0 || returnString.isBlank())
{
returnString += user.getTranslationOrNothing(reference + "in-seconds",
Constants.PARAMETER_NUMBER, String.valueOf(duration.toSecondsPart()));
}

return returnString;
}
}
19 changes: 19 additions & 0 deletions src/main/resources/locales/en-US.yml
Original file line number Diff line number Diff line change
Expand Up @@ -829,6 +829,7 @@ challenges:
lore: |-
[description]
[status]
[cooldown]
[requirements]
[rewards]
# Contains a text generated inside [status] lore
Expand All @@ -841,6 +842,23 @@ challenges:
completed-times-of: "&2 Completed &7&l [number] &r&2 out of &7&l [max] &r&2 times"
# Status message that indicates that max completion count reached for repeatable challenge
completed-times-reached: "&2&l Completed all &7 [max] &2 times"
# Contains a text generated inside [cooldown] lore
cooldown:
lore: |-
[timeout]
[wait-time]
# Text message that shows challenges timeout.
timeout: "&7&l Cool down: &r&7 [time]"
# Text message that shows challenges wait time if it is larger than 0.
wait-time: "&c&l Available after: &r&c [time]"
# Text message that replaces days if number > 1
in-days: "[number] d, "
# Text message that replaces hours if number > 1
in-hours: "[number] h, "
# Text message that replaces minutes if number > 1
in-minutes: "[number] min, "
# Text message that replaces seconds if number > 1
in-seconds: "[number] s"
# Contains a text generated inside [requirements] lore
requirements:
lore: |-
Expand Down Expand Up @@ -1156,6 +1174,7 @@ challenges:
invalid-challenge: "&c Challenge [challenge] contains invalid data. It will not be loaded from database!"
no-library-entries: "&c Cannot find any library entries. Nothing to show."
not-hooked: "&c Challenges Addon could not find any GameMode."
timeout: "&c This challenge requires to wait [timeout] between completions. You must wait [wait-time] till complete it again."
# # Showcase for manual material translation
# materials:
# # Names should be lowercase.
Expand Down
19 changes: 19 additions & 0 deletions src/main/resources/locales/lv.yml
Original file line number Diff line number Diff line change
Expand Up @@ -849,6 +849,7 @@ challenges:
lore: |-
[description]
[status]
[cooldown]
[requirements]
[rewards]
# Contains a text generated inside [status] lore
Expand All @@ -861,6 +862,23 @@ challenges:
completed-times-of: "&2 Izpildīts &7&l [number] &r&2 no &7&l [max] &r&2 reizēm"
# Status message that indicates that max completion count reached for repeatable challenge
completed-times-reached: "&2&l Izpildīts visas &7 [max] &2 reizes"
# Contains a text generated inside [cooldown] lore
cooldown:
lore: |-
[timeout]
[wait-time]
# Text message that shows challenges timeout.
timeout: "&7&l Taimauts: &r&7 [time]"
# Text message that shows challenges wait time if it is larger than 0.
wait-time: "&c&l Jānogaida: &r&c [time]"
# Text message that replaces days if number > 1
in-days: "[number] d, "
# Text message that replaces hours if number > 1
in-hours: "[number] h, "
# Text message that replaces minutes if number > 1
in-minutes: "[number] min, "
# Text message that replaces seconds if number > 1
in-seconds: "[number] s"
# Contains a text generated inside [requirements] lore
requirements:
lore: |-
Expand Down Expand Up @@ -1180,6 +1198,7 @@ challenges:
invalid-challenge: "&c Uzdevums [challenge] satur nekorektus datus. Tas var tikt ielādēts nekorekti!"
no-library-entries: "&c Nevar atrast bibliotēkas ierakstus. Nav ko rādīt."
not-hooked: "&c Uzdevumu Papildinājumam neizdevās atrast Spēles Režīmu."
timeout: "&c Šim uzdevumam ir uzstādīts [timeout] taimauts starp izpildēm. Tev vēl ir jāgaida [wait-time], lai varētu pildīt uzdevumu."
# # Showcase for manual material translation
# materials:
# # Names should be lowercase.
Expand Down

0 comments on commit bb5e861

Please sign in to comment.