Add plot like/dislikes

This commit is contained in:
Sauilitired 2019-04-01 17:39:28 +02:00
parent 0f8b7cd588
commit 6323fb0041
No known key found for this signature in database
GPG key ID: C0207FF7EA146678
11 changed files with 251 additions and 39 deletions

View file

@ -0,0 +1,14 @@
package com.github.intellectualsites.plotsquared.plot.commands;
import com.github.intellectualsites.plotsquared.commands.CommandDeclaration;
import com.github.intellectualsites.plotsquared.plot.object.PlotPlayer;
@CommandDeclaration(command = "dislike", permission = "plots.dislike", description = "Dislike the plot",
usage = "/plot dislike [next|purge]", category = CommandCategory.INFO, requiredType = RequiredType.PLAYER)
public class Dislike extends SubCommand {
@Override public boolean onCommand(PlotPlayer player, String[] args) {
return Like.handleLike(player, args, false);
}
}

View file

@ -2,6 +2,7 @@ package com.github.intellectualsites.plotsquared.plot.commands;
import com.github.intellectualsites.plotsquared.commands.CommandDeclaration;
import com.github.intellectualsites.plotsquared.plot.config.Captions;
import com.github.intellectualsites.plotsquared.plot.config.Settings;
import com.github.intellectualsites.plotsquared.plot.database.DBFunc;
import com.github.intellectualsites.plotsquared.plot.flag.Flags;
import com.github.intellectualsites.plotsquared.plot.object.*;
@ -32,6 +33,7 @@ import java.util.UUID;
case "seen":
case "owner":
case "rating":
case "likes":
plot = MainUtil.getPlotFromString(player, null, false);
break;
default:
@ -130,7 +132,7 @@ import java.util.UUID;
if (info == null) {
MainUtil.sendMessage(player,
"&6Categories&7: &amembers&7, &aalias&7, &abiome&7, &aseen&7, &adenied&7, &aflags&7, &aid&7, &asize&7, &atrusted&7, "
+ "&aowner&7, &arating");
+ "&aowner&7, " + (Settings.Ratings.USE_LIKES ? " &alikes" : " &arating"));
return false;
}
full = true;
@ -169,6 +171,8 @@ import java.util.UUID;
return Captions.PLOT_INFO_OWNER.s();
case "rating":
return Captions.PLOT_INFO_RATING.s();
case "likes":
return Captions.PLOT_INFO_LIKES.s();
case "seen":
return Captions.PLOT_INFO_SEEN.s();
default:

View file

@ -0,0 +1,143 @@
package com.github.intellectualsites.plotsquared.plot.commands;
import com.github.intellectualsites.plotsquared.commands.CommandDeclaration;
import com.github.intellectualsites.plotsquared.plot.PlotSquared;
import com.github.intellectualsites.plotsquared.plot.config.Captions;
import com.github.intellectualsites.plotsquared.plot.config.Settings;
import com.github.intellectualsites.plotsquared.plot.database.DBFunc;
import com.github.intellectualsites.plotsquared.plot.flag.Flags;
import com.github.intellectualsites.plotsquared.plot.object.Plot;
import com.github.intellectualsites.plotsquared.plot.object.PlotPlayer;
import com.github.intellectualsites.plotsquared.plot.object.Rating;
import com.github.intellectualsites.plotsquared.plot.util.EventUtil;
import com.github.intellectualsites.plotsquared.plot.util.MainUtil;
import com.github.intellectualsites.plotsquared.plot.util.Permissions;
import com.github.intellectualsites.plotsquared.plot.util.TaskManager;
import java.util.*;
@CommandDeclaration(command = "like", permission = "plots.like", description = "Like the plot",
usage = "/plot like [next|purge]", category = CommandCategory.INFO, requiredType = RequiredType.PLAYER)
public class Like extends SubCommand {
@Override public boolean onCommand(PlotPlayer player, String[] args) {
return handleLike(player, args, true);
}
protected static boolean handleLike(final PlotPlayer player, String[] args, final boolean like) {
final UUID uuid = player.getUUID();
if (args.length == 1) {
switch (args[0].toLowerCase()) {
case "next": {
final List<Plot> plots = new ArrayList<>(PlotSquared.get().getBasePlots());
plots.sort((p1, p2) -> {
double v1 = getLikesPercentage(p1);
double v2 = getLikesPercentage(p2);
if (v1 == v2) {
return -0;
}
return v2 > v1 ? 1 : -1;
});
for (final Plot plot : plots) {
if ((!Settings.Done.REQUIRED_FOR_RATINGS || plot.hasFlag(Flags.DONE))
&& plot.isBasePlot() && (!plot.getLikes().containsKey(uuid))) {
plot.teleportPlayer(player);
MainUtil.sendMessage(player, Captions.RATE_THIS);
return true;
}
}
MainUtil.sendMessage(player, Captions.FOUND_NO_PLOTS);
return true;
}
case "purge": {
final Plot plot = player.getCurrentPlot();
if (plot == null) {
return !sendMessage(player, Captions.NOT_IN_PLOT);
}
if (!Permissions
.hasPermission(player, Captions.PERMISSION_ADMIN_COMMAND_RATE, true)) {
return false;
}
plot.clearRatings();
Captions.RATINGS_PURGED.send(player);
return true;
}
}
}
final Plot plot = player.getCurrentPlot();
if (plot == null) {
return !sendMessage(player, Captions.NOT_IN_PLOT);
}
if (!plot.hasOwner()) {
sendMessage(player, Captions.RATING_NOT_OWNED);
return false;
}
if (plot.isOwner(player.getUUID())) {
sendMessage(player, Captions.RATING_NOT_YOUR_OWN);
return false;
}
if (Settings.Done.REQUIRED_FOR_RATINGS && !plot.hasFlag(Flags.DONE)) {
sendMessage(player, Captions.RATING_NOT_DONE);
return false;
}
final Runnable run = () -> {
final Boolean oldRating = plot.getLikes().get(uuid);
if (oldRating != null) {
sendMessage(player, Captions.RATING_ALREADY_EXISTS, plot.getId().toString());
return;
}
final int rating;
if (like) {
rating = 10;
} else {
rating = 1;
}
plot.addRating(uuid, new Rating(rating));
final Rating result = EventUtil.manager.callRating(player, plot, new Rating(rating));
if (result != null) {
plot.addRating(uuid, result);
sendMessage(player, like ? Captions.RATING_LIKED : Captions.RATING_DISLIKED,
plot.getId().toString());
}
};
if (plot.getSettings().ratings == null) {
if (!Settings.Enabled_Components.RATING_CACHE) {
TaskManager.runTaskAsync(() -> {
plot.getSettings().ratings = DBFunc.getRatings(plot);
run.run();
});
return true;
}
plot.getSettings().ratings = new HashMap<>();
}
run.run();
return true;
}
/**
* Get the likes to dislike ratio of a plot as a percentage (in decimal form)
*
* @return likes to dislike ratio, returns zero if the plot has no likes
*/
public static double getLikesPercentage(final Plot plot) {
if (!plot.hasRatings()) {
return 0;
}
final Collection<Boolean> reactions = plot.getLikes().values();
double numLikes = 0, numDislikes = 0;
for (final boolean reaction : reactions) {
if (reaction) {
numLikes += 1;
} else {
numDislikes += 1;
}
}
if (numLikes == 0 && numDislikes == 0) {
return 0D;
} else if (numDislikes == 0) {
return 1.0D;
}
return numLikes / (numLikes + numDislikes);
}
}

View file

@ -4,6 +4,7 @@ import com.github.intellectualsites.plotsquared.commands.Command;
import com.github.intellectualsites.plotsquared.commands.CommandCaller;
import com.github.intellectualsites.plotsquared.commands.CommandDeclaration;
import com.github.intellectualsites.plotsquared.plot.config.Captions;
import com.github.intellectualsites.plotsquared.plot.config.Settings;
import com.github.intellectualsites.plotsquared.plot.object.*;
import com.github.intellectualsites.plotsquared.plot.util.CmdConfirm;
import com.github.intellectualsites.plotsquared.plot.util.EconHandler;
@ -68,7 +69,6 @@ public class MainCommand extends Command {
new DebugPaste();
new Unlink();
new Kick();
new Rate();
new DebugClaimTest();
new Inbox();
new Comment();
@ -98,6 +98,14 @@ public class MainCommand extends Command {
new SetHome();
new Cluster();
new DebugImportWorlds();
if (Settings.Ratings.USE_LIKES) {
new Like();
new Dislike();
} else {
new Rate();
}
// Referenced commands
instance.toggle = new Toggle();
instance.help = new Help(instance);

View file

@ -32,7 +32,7 @@ public abstract class SubCommand extends Command {
public abstract boolean onCommand(PlotPlayer player, String[] args);
public boolean sendMessage(PlotPlayer player, Captions message, Object... args) {
public static boolean sendMessage(PlotPlayer player, Captions message, Object... args) {
message.send(player, args);
return true;
}

View file

@ -378,6 +378,9 @@ public enum Captions {
RATING_ALREADY_EXISTS("$2You have already rated plot $2%s", "Ratings"), RATING_APPLIED(
"$4You successfully rated plot $2%s", "Ratings"),
RATING_DISLIKED("$4You successfully disliked plot $2%s", "Ratings"),
RATING_LIKED("$4You successfully liked plot $2%s", "Ratings"),
RATING_NOT_YOUR_OWN("$2You cannot rate your own plot", "Ratings"), RATING_NOT_DONE(
"$2You can only rate finished plots.", "Ratings"),
@ -693,6 +696,8 @@ public enum Captions {
PLOT_INFO_BIOME("$1Biome:$2 %biome%", "Info"), PLOT_INFO_RATING("$1Rating:$2 %rating%", "Info"),
PLOT_INFO_LIKES("$1Like Ratio:$2 %likes%%", "Info"),
PLOT_INFO_OWNER("$1Owner:$2 %owner%", "Info"), PLOT_INFO_ID("$1ID:$2 %id%", "Info"),
PLOT_INFO_ALIAS("$1Alias:$2 %alias%", "Info"), PLOT_INFO_SIZE("$1Size:$2 %size%", "Info"),

View file

@ -315,6 +315,9 @@ public class Settings extends Config {
public static final class Ratings {
@Comment("Replace the rating system with a like system. Will add /plot like/dislike,"
+ " and remove the rating command") public static boolean USE_LIKES = false;
@Comment("Rating categories")
public static List<String> CATEGORIES = new ArrayList<>();
}

View file

@ -1344,7 +1344,7 @@ public class Plot {
}
/**
* Clear the ratings for this plot
* Clear the ratings/likes for this plot
*/
public void clearRatings() {
Plot base = this.getBasePlot(false);
@ -1355,6 +1355,15 @@ public class Plot {
}
}
public Map<UUID, Boolean> getLikes() {
final Map<UUID, Boolean> map = new HashMap<>();
final Map<UUID, Rating> ratings = this.getRatings();
ratings.forEach((uuid, rating) -> {
map.put(uuid, rating.getLike());
});
return map;
}
/**
* Gets the ratings associated with a plot<br>
* - The rating object may contain multiple categories

View file

@ -9,6 +9,9 @@ import java.util.Map.Entry;
import java.util.stream.IntStream;
public class Rating {
private static final String LIKE_INTERNAL = "__LIKES__";
/**
* This is a map of the rating category to the rating value
*/
@ -17,22 +20,27 @@ public class Rating {
private boolean changed;
public Rating(int value) {
this.initial = value;
this.ratingMap = new HashMap<>();
if (Settings.Ratings.CATEGORIES != null && Settings.Ratings.CATEGORIES.size() > 1) {
if (value < 10) {
for (String ratingCategory : Settings.Ratings.CATEGORIES) {
this.ratingMap.put(ratingCategory, value);
}
this.changed = true;
return;
}
for (String ratingCategory : Settings.Ratings.CATEGORIES) {
this.ratingMap.put(ratingCategory, value % 10 - 1);
value = value / 10;
}
if (Settings.Ratings.USE_LIKES) {
this.initial = value == 10 ? 10 : 1;
this.ratingMap.put(LIKE_INTERNAL, this.initial == 10 ? 10 : 1);
} else {
this.ratingMap.put(null, value);
this.initial = value;
if (Settings.Ratings.CATEGORIES != null && Settings.Ratings.CATEGORIES.size() > 1) {
if (value < 10) {
for (String ratingCategory : Settings.Ratings.CATEGORIES) {
this.ratingMap.put(ratingCategory, value);
}
this.changed = true;
return;
}
for (String ratingCategory : Settings.Ratings.CATEGORIES) {
this.ratingMap.put(ratingCategory, value % 10 - 1);
value = value / 10;
}
} else {
this.ratingMap.put(null, value);
}
}
}
@ -44,10 +52,18 @@ public class Rating {
}
public double getAverageRating() {
if (Settings.Ratings.USE_LIKES) {
return getLike() ? 10 : 1;
}
double total = this.ratingMap.entrySet().stream().mapToDouble(Entry::getValue).sum();
return total / this.ratingMap.size();
}
public boolean getLike() {
final Integer rating = this.getRating(LIKE_INTERNAL);
return rating != null && rating == 10;
}
public Integer getRating(String category) {
return this.ratingMap.get(category);
}
@ -64,6 +80,9 @@ public class Rating {
if (!this.changed) {
return this.initial;
}
if (Settings.Ratings.USE_LIKES) {
return this.ratingMap.get(LIKE_INTERNAL);
}
if (Settings.Ratings.CATEGORIES != null && Settings.Ratings.CATEGORIES.size() > 1) {
return IntStream.range(0, Settings.Ratings.CATEGORIES.size()).map(
i -> (int) ((i + 1) * Math

View file

@ -2,6 +2,7 @@ package com.github.intellectualsites.plotsquared.plot.util;
import com.github.intellectualsites.plotsquared.commands.CommandCaller;
import com.github.intellectualsites.plotsquared.plot.PlotSquared;
import com.github.intellectualsites.plotsquared.plot.commands.Like;
import com.github.intellectualsites.plotsquared.plot.config.Captions;
import com.github.intellectualsites.plotsquared.plot.config.Settings;
import com.github.intellectualsites.plotsquared.plot.database.DBFunc;
@ -776,25 +777,29 @@ public class MainUtil {
if (info.contains("%rating%")) {
final String newInfo = info;
TaskManager.runTaskAsync(() -> {
int max = 10;
if (Settings.Ratings.CATEGORIES != null && !Settings.Ratings.CATEGORIES.isEmpty()) {
max = 8;
}
String info1;
if (full && Settings.Ratings.CATEGORIES != null
&& Settings.Ratings.CATEGORIES.size() > 1) {
double[] ratings = MainUtil.getAverageRatings(plot);
String rating = "";
String prefix = "";
for (int i = 0; i < ratings.length; i++) {
rating += prefix + Settings.Ratings.CATEGORIES.get(i) + '=' + String
.format("%.1f", ratings[i]);
prefix = ",";
}
info1 = newInfo.replaceAll("%rating%", rating);
if (Settings.Ratings.USE_LIKES) {
info1 = newInfo.replaceAll("%rating%", String.format("%.0f%%", Like.getLikesPercentage(plot) * 100D));
} else {
info1 = newInfo.replaceAll("%rating%",
String.format("%.1f", plot.getAverageRating()) + '/' + max);
int max = 10;
if (Settings.Ratings.CATEGORIES != null && !Settings.Ratings.CATEGORIES.isEmpty()) {
max = 8;
}
if (full && Settings.Ratings.CATEGORIES != null
&& Settings.Ratings.CATEGORIES.size() > 1) {
double[] ratings = MainUtil.getAverageRatings(plot);
String rating = "";
String prefix = "";
for (int i = 0; i < ratings.length; i++) {
rating += prefix + Settings.Ratings.CATEGORIES.get(i) + '=' + String
.format("%.1f", ratings[i]);
prefix = ",";
}
info1 = newInfo.replaceAll("%rating%", rating);
} else {
info1 = newInfo.replaceAll("%rating%",
String.format("%.1f", plot.getAverageRating()) + '/' + max);
}
}
whenDone.run(info1);
});

View file

@ -245,10 +245,12 @@ public class StringMan {
}
public static boolean isEqual(String a, String b) {
return (a == b) || ((a != null) && (b != null) && (a.length() == b.length()) && (
a.hashCode() == b.hashCode()) && a.equals(b));
// return a.equals(b) || b != null && a.length() == b.length() && a.hashCode() == b.hashCode()
// && a.equals(b);
if ((a == null && b != null) || (a != null && b == null)) {
return false;
} else if (a == null /* implies that b is null */) {
return false;
}
return a.equals(b);
}
public static boolean isEqualIgnoreCase(String a, String b) {