Skip to content

Commit 3a73ef3

Browse files
committed
monthly QOTW leaderboard
1 parent 1c3360a commit 3a73ef3

File tree

7 files changed

+67
-119
lines changed

7 files changed

+67
-119
lines changed

src/main/java/net/javadiscord/javabot/systems/qotw/QOTWPointsService.java

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@
1212
import org.springframework.stereotype.Service;
1313
import org.springframework.transaction.annotation.Transactional;
1414

15+
import java.time.LocalDate;
16+
import java.time.YearMonth;
1517
import java.util.List;
1618
import java.util.Optional;
1719

@@ -33,14 +35,13 @@ public class QOTWPointsService {
3335
@Transactional
3436
public QOTWAccount getOrCreateAccount(long userId) throws DataAccessException {
3537
QOTWAccount account;
36-
Optional<QOTWAccount> optional = pointsRepository.getByUserId(userId);
38+
Optional<QOTWAccount> optional = pointsRepository.getByUserId(userId, getCurrentMonth());
3739
if (optional.isPresent()) {
3840
account = optional.get();
3941
} else {
4042
account = new QOTWAccount();
4143
account.setUserId(userId);
4244
account.setPoints(0);
43-
pointsRepository.insert(account);
4445
}
4546
return account;
4647
}
@@ -53,7 +54,7 @@ public QOTWAccount getOrCreateAccount(long userId) throws DataAccessException {
5354
*/
5455
public int getQOTWRank(long userId) {
5556
try{
56-
List<QOTWAccount> accounts = pointsRepository.sortByPoints();
57+
List<QOTWAccount> accounts = pointsRepository.sortByPoints(getCurrentMonth());
5758
return accounts.stream()
5859
.map(QOTWAccount::getUserId)
5960
.toList()
@@ -88,7 +89,7 @@ public long getPoints(long userId) {
8889
*/
8990
public List<Pair<QOTWAccount, Member>> getTopMembers(int n, Guild guild) {
9091
try {
91-
List<QOTWAccount> accounts = pointsRepository.sortByPoints();
92+
List<QOTWAccount> accounts = pointsRepository.sortByPoints(getCurrentMonth());
9293
return accounts.stream()
9394
.map(s -> new Pair<>(s, guild.getMemberById(s.getUserId())))
9495
.filter(p->p.first().getPoints() > 0)
@@ -110,7 +111,7 @@ public List<Pair<QOTWAccount, Member>> getTopMembers(int n, Guild guild) {
110111
*/
111112
public List<QOTWAccount> getTopAccounts(int amount, int page) {
112113
try {
113-
return pointsRepository.getTopAccounts(page, amount);
114+
return pointsRepository.getTopAccounts(getCurrentMonth(), page, amount);
114115
} catch (DataAccessException e) {
115116
ExceptionLogger.capture(e, getClass().getSimpleName());
116117
return List.of();
@@ -125,16 +126,17 @@ public List<QOTWAccount> getTopAccounts(int amount, int page) {
125126
*/
126127
public long increment(long userId) {
127128
try {
128-
QOTWAccount account = getOrCreateAccount(userId);
129-
account.setPoints(account.getPoints() + 1);
130-
if (pointsRepository.update(account)) {
131-
return account.getPoints();
132-
} else {
133-
return 0;
134-
}
129+
LocalDate date=LocalDate.now();
130+
int points = pointsRepository.getPointsAtDate(userId, date)+1;
131+
pointsRepository.setPointsAtDate(userId, date, points);
132+
return pointsRepository.getByUserId(userId, getCurrentMonth()).map(QOTWAccount::getPoints).orElse(0L);
135133
} catch (DataAccessException e) {
136134
ExceptionLogger.capture(e, getClass().getSimpleName());
137135
return 0;
138136
}
139137
}
138+
139+
public static LocalDate getCurrentMonth() {
140+
return YearMonth.from(LocalDate.now()).atDay(1);
141+
}
140142
}

src/main/java/net/javadiscord/javabot/systems/qotw/commands/QOTWAdminCommand.java

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
import net.dv8tion.jda.api.interactions.commands.build.Commands;
55
import net.dv8tion.jda.api.interactions.commands.build.SubcommandGroupData;
66
import net.javadiscord.javabot.systems.qotw.commands.qotw_points.IncrementPointsSubcommand;
7-
import net.javadiscord.javabot.systems.qotw.commands.qotw_points.SetPointsSubcommand;
87
import net.javadiscord.javabot.systems.qotw.commands.questions_queue.AddQuestionSubcommand;
98
import net.javadiscord.javabot.systems.qotw.commands.questions_queue.ListQuestionsSubcommand;
109
import net.javadiscord.javabot.systems.qotw.commands.questions_queue.RemoveQuestionSubcommand;
@@ -23,18 +22,17 @@ public class QOTWAdminCommand extends SlashCommand {
2322
* @param addQuestionSubcommand /qotw-admin questions-queue add
2423
* @param removeQuestionSubcommand /qotw-admin questions-queue remove
2524
* @param incrementPointsSubcommand /qotw-admin account increment
26-
* @param setPointsSubcommand /qotw-admin account set
2725
* @param reviewSubcommand /qotw-admin submissions review
2826
*/
29-
public QOTWAdminCommand(ListQuestionsSubcommand listQuestionsSubcommand, AddQuestionSubcommand addQuestionSubcommand, RemoveQuestionSubcommand removeQuestionSubcommand, IncrementPointsSubcommand incrementPointsSubcommand, SetPointsSubcommand setPointsSubcommand, QOTWReviewSubcommand reviewSubcommand) {
27+
public QOTWAdminCommand(ListQuestionsSubcommand listQuestionsSubcommand, AddQuestionSubcommand addQuestionSubcommand, RemoveQuestionSubcommand removeQuestionSubcommand, IncrementPointsSubcommand incrementPointsSubcommand, QOTWReviewSubcommand reviewSubcommand) {
3028
setCommandData(Commands.slash("qotw-admin", "Administrative tools for managing the Question of the Week.")
3129
.setDefaultPermissions(DefaultMemberPermissions.DISABLED)
3230
.setGuildOnly(true)
3331
);
3432
addSubcommands(reviewSubcommand);
3533
addSubcommandGroups(
3634
SubcommandGroup.of(new SubcommandGroupData("questions-queue", "Commands for interacting with the set of QOTW questions that are in queue."), listQuestionsSubcommand, addQuestionSubcommand, removeQuestionSubcommand),
37-
SubcommandGroup.of(new SubcommandGroupData("account", "Commands for interaction with Users Question of the Week points."), incrementPointsSubcommand, setPointsSubcommand),
35+
SubcommandGroup.of(new SubcommandGroupData("account", "Commands for interaction with Users Question of the Week points."), incrementPointsSubcommand),
3836
SubcommandGroup.of(new SubcommandGroupData("submissions", "Commands for managing QOTW Submissions."), reviewSubcommand)
3937
);
4038
}

src/main/java/net/javadiscord/javabot/systems/qotw/commands/qotw_points/SetPointsSubcommand.java

Lines changed: 0 additions & 69 deletions
This file was deleted.

src/main/java/net/javadiscord/javabot/systems/qotw/dao/QuestionPointsRepository.java

Lines changed: 46 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -2,89 +2,102 @@
22

33
import java.sql.ResultSet;
44
import java.sql.SQLException;
5+
import java.time.LocalDate;
56
import java.util.List;
67
import java.util.Optional;
78

8-
import org.jetbrains.annotations.NotNull;
99
import org.springframework.dao.DataAccessException;
1010
import org.springframework.dao.EmptyResultDataAccessException;
1111
import org.springframework.jdbc.core.JdbcTemplate;
1212
import org.springframework.stereotype.Repository;
1313

1414
import lombok.RequiredArgsConstructor;
15-
import lombok.extern.slf4j.Slf4j;
1615
import net.javadiscord.javabot.systems.qotw.model.QOTWAccount;
1716

1817
/**
1918
* Dao class that represents the QOTW_POINTS SQL Table.
2019
*/
21-
@Slf4j
2220
@RequiredArgsConstructor
2321
@Repository
2422
public class QuestionPointsRepository {
2523
private final JdbcTemplate jdbcTemplate;
2624

2725
/**
28-
* Inserts a new {@link QOTWAccount} if none exists.
26+
* Returns a {@link QOTWAccount} based on the given user Id.
2927
*
30-
* @param account The account to insert.
28+
* @param userId The discord Id of the user.
29+
* @param startDate The earliest date where points are counted
30+
* @return The {@link QOTWAccount} object.
3131
* @throws DataAccessException If an error occurs.
3232
*/
33-
public void insert(QOTWAccount account) throws DataAccessException {
34-
int rows = jdbcTemplate.update("INSERT INTO qotw_points (user_id, points) VALUES (?, ?)",
35-
account.getUserId(),account.getPoints());
36-
if (rows == 0) throw new DataAccessException("User was not inserted.") {};
37-
log.info("Inserted new QOTW-Account: {}", account);
33+
public Optional<QOTWAccount> getByUserId(long userId, LocalDate startDate) throws DataAccessException {
34+
try {
35+
return Optional.of(jdbcTemplate.queryForObject("SELECT SUM(points) AS points FROM qotw_points WHERE user_id = ? AND obtained_at >= ?",
36+
(rs, row)->{
37+
QOTWAccount acc=new QOTWAccount();
38+
acc.setUserId(userId);
39+
acc.setPoints(rs.getLong(1));
40+
return acc;
41+
},
42+
userId, startDate));
43+
}catch (EmptyResultDataAccessException e) {
44+
return Optional.empty();
45+
}
3846
}
3947

4048
/**
41-
* Returns a {@link QOTWAccount} based on the given user Id.
49+
* Gets the number points given to a user at a certain date.
4250
*
43-
* @param userId The discord Id of the user.
44-
* @return The {@link QOTWAccount} object.
45-
* @throws DataAccessException If an error occurs.
51+
* @param userId the ID of the user
52+
* @param date the date where the points are given to that user
53+
* @return the number of points the user obtained at the given date
4654
*/
47-
public Optional<QOTWAccount> getByUserId(long userId) throws DataAccessException {
55+
public int getPointsAtDate(long userId, LocalDate date) {
4856
try {
49-
return Optional.of(jdbcTemplate.queryForObject("SELECT * FROM qotw_points WHERE user_id = ?", (rs, row)->this.read(rs),userId));
57+
return jdbcTemplate.queryForObject("SELECT SUM(points) FROM qotw_points WHERE user_id = ? AND obtained_at >= ?",
58+
(rs, row) -> rs.getInt(1),
59+
userId, date);
5060
}catch (EmptyResultDataAccessException e) {
51-
return Optional.empty();
61+
return 0;
5262
}
5363
}
5464

5565
/**
56-
* Updates a single QOTW Account.
66+
* Sets the points of a user at a certain date.
5767
*
58-
* @param account The updated QOTW Account.
59-
* @return Whether the update affected rows.
60-
* @throws DataAccessException If an error occurs.
68+
* @param userId the id of the user to set to points of
69+
* @param date the date when the points should be marked as set
70+
* @param points the (new) number of points the user got at that date
71+
* @return {@code true} if a change was made, else {@code false}
6172
*/
62-
public boolean update(@NotNull QOTWAccount account) throws DataAccessException {
63-
return jdbcTemplate.update("UPDATE qotw_points SET points = ? WHERE user_id = ?",
64-
account.getPoints(), account.getUserId()) > 0;
73+
public boolean setPointsAtDate(long userId, LocalDate date, long points) {
74+
return jdbcTemplate.update("MERGE INTO qotw_points (user_id,obtained_at,points) KEY(user_id,obtained_at) VALUES (?,?,?)",
75+
userId, date, points) > 0;
6576
}
6677

6778
/**
6879
* Gets all {@link QOTWAccount} and sorts them by their points.
6980
*
81+
* @param startDate the minimum date points are considered
7082
* @return A {@link List} that contains all {@link QOTWAccount}s sorted by their points.
7183
* @throws DataAccessException If an error occurs.
7284
*/
73-
public List<QOTWAccount> sortByPoints() throws DataAccessException {
74-
return jdbcTemplate.query("SELECT * FROM qotw_points ORDER BY points DESC", (rs, row)->this.read(rs));
85+
public List<QOTWAccount> sortByPoints(LocalDate startDate) throws DataAccessException {
86+
return jdbcTemplate.query("SELECT user_id, SUM(points) FROM qotw_points WHERE obtained_at >= ? GROUP BY user_id ORDER BY SUM(points) DESC", (rs, row)->this.read(rs), startDate);
7587
}
7688

7789
/**
7890
* Gets a specified amount of {@link QOTWAccount}s.
7991
*
80-
* @param page The page.
81-
* @param size The amount of {@link QOTWAccount}s to return.
92+
* @param startDate the minimum date points are considered
93+
* @param page The page.
94+
* @param size The amount of {@link QOTWAccount}s to return.
8295
* @return A {@link List} containing the specified amount of {@link QOTWAccount}s.
8396
* @throws DataAccessException If an error occurs.
8497
*/
85-
public List<QOTWAccount> getTopAccounts(int page, int size) throws DataAccessException {
86-
return jdbcTemplate.query("SELECT * FROM qotw_points WHERE points > 0 ORDER BY points DESC LIMIT ? OFFSET ?", (rs,row)->this.read(rs),
87-
size, Math.max(0, (page * size) - size));
98+
public List<QOTWAccount> getTopAccounts(LocalDate startDate, int page, int size) throws DataAccessException {
99+
return jdbcTemplate.query("SELECT user_id, SUM(points) FROM qotw_points WHERE startDate >= ? AND points > 0 GROUP BY user_id ORDER BY SUM(points) DESC LIMIT ? OFFSET ?", (rs,row)->this.read(rs),
100+
startDate, size, Math.max(0, (page * size) - size));
88101
}
89102

90103
/**
@@ -96,8 +109,8 @@ public List<QOTWAccount> getTopAccounts(int page, int size) throws DataAccessExc
96109
*/
97110
private QOTWAccount read(ResultSet rs) throws SQLException {
98111
QOTWAccount account = new QOTWAccount();
99-
account.setUserId(rs.getLong("user_id"));
100-
account.setPoints(rs.getLong("points"));
112+
account.setUserId(rs.getLong(1));
113+
account.setPoints(rs.getLong(2));
101114
return account;
102115
}
103116
}

src/main/java/net/javadiscord/javabot/systems/user_commands/leaderboard/QOTWLeaderboardSubcommand.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -197,7 +197,7 @@ private void drawUserCard(@NotNull Graphics2D g2d, @NotNull Member member, QOTWP
197197
*/
198198
private @NotNull String getCacheName() {
199199
try {
200-
List<QOTWAccount> accounts = qotwPointsRepository.sortByPoints()
200+
List<QOTWAccount> accounts = qotwPointsRepository.sortByPoints(QOTWPointsService.getCurrentMonth())
201201
.stream()
202202
.limit(DISPLAY_COUNT)
203203
.toList();
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
ALTER TABLE qotw_points ADD obtained_at DATE NOT NULL DEFAULT CURRENT_TIMESTAMP(0);
2+
ALTER TABLE qotw_points DROP PRIMARY KEY;
3+
ALTER TABLE qotw_points ADD PRIMARY KEY (user_id, obtained_at);

src/main/resources/database/schema.sql

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ CREATE TABLE qotw_question
5050
CREATE TABLE qotw_points
5151
(
5252
user_id BIGINT PRIMARY KEY,
53+
obtained_at DATE PRIMARY KEY DEFAULT CURRENT_TIMESTAMP(0),
5354
points BIGINT NOT NULL DEFAULT 0
5455
);
5556

0 commit comments

Comments
 (0)