1
mirror of https://github.com/carm-outsource/TimeReward.git synced 2026-06-04 15:28:16 +08:00

fix(time): 尝试修复在线时间计算错误的问题

This commit is contained in:
2025-07-10 19:17:07 +08:00
parent cc451cd1f4
commit 8a8c23bd7e
5 changed files with 76 additions and 30 deletions
@@ -1,9 +1,11 @@
package cc.carm.plugin.timereward.data; package cc.carm.plugin.timereward.data;
import cc.carm.plugin.timereward.Main;
import cc.carm.plugin.timereward.util.DateTimeUtils; import cc.carm.plugin.timereward.util.DateTimeUtils;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import java.time.Duration; import java.time.Duration;
import java.time.LocalDate;
import java.time.LocalDateTime; import java.time.LocalDateTime;
import java.util.Arrays; import java.util.Arrays;
import java.util.function.BiFunction; import java.util.function.BiFunction;
@@ -18,16 +20,25 @@ public enum IntervalType {
DAILY( DAILY(
1, Duration.ofDays(1), time -> !DateTimeUtils.sameDay(time.toLocalDate()), 1, Duration.ofDays(1), time -> !DateTimeUtils.sameDay(time.toLocalDate()),
(timeRecord, join) -> { (record, join) -> {
LocalDateTime now = LocalDateTime.now(); LocalDateTime now = LocalDateTime.now();
if (!now.toLocalDate().isEqual(join.toLocalDate())) { LocalDate today = LocalDate.now();
// 加入的时间和现在的时间不在同一天 if (DateTimeUtils.sameDay(join.toLocalDate(), today)) {
return Duration.between(DateTimeUtils.todayStartTime(), now); // 如果加入的时间和今天的日期相同
if (DateTimeUtils.sameDay(record.getDate(), today)) {
// 如果上一次记录的日期和今天的日期相同
// 则从加入的时间开始计算到现在的时间,并加上当天的游玩时间
return Duration.between(join, now).plus(record.getDailyTime());
} else {
// 如果上一次记录的日期和今天的日期不同
// 则从加入的时间开始计算到现在的时间
return Duration.between(join, now);
}
} else {
// 如果加入的时间和今天的日期不同
// 则从今天的0点开始计算到现在的时间
return Duration.between(today.atTime(0, 0, 0), now);
} }
if (now.toLocalDate().isEqual(timeRecord.getDate())) { // 和记录还在同一天
return Duration.between(join, now).plus(timeRecord.getDailyTime());
}
return Duration.between(join, now); // 加入的时间和现在的时间在同一天
} }
), ),
WEEKLY( WEEKLY(
@@ -35,13 +46,15 @@ public enum IntervalType {
time -> !DateTimeUtils.sameWeek(time), time -> !DateTimeUtils.sameWeek(time),
(r, join) -> { (r, join) -> {
LocalDateTime now = LocalDateTime.now(); LocalDateTime now = LocalDateTime.now();
if (!DateTimeUtils.sameWeek(join, now)) { if (DateTimeUtils.sameWeek(join.toLocalDate(), now)) {
if (DateTimeUtils.sameWeek(r.getDate(), now.toLocalDate())) {
return Duration.between(join, now).plus(r.getWeeklyTime());
} else {
return Duration.between(join, now);
}
} else {
return Duration.between(DateTimeUtils.currentWeekStartTime(), now); return Duration.between(DateTimeUtils.currentWeekStartTime(), now);
} }
if (DateTimeUtils.sameWeek(r.getDate(), now)) {
return Duration.between(join, now).plus(r.getWeeklyTime());
}
return Duration.between(join, now);
} }
), ),
@@ -50,13 +63,15 @@ public enum IntervalType {
time -> !DateTimeUtils.sameMonth(time.toLocalDate()), time -> !DateTimeUtils.sameMonth(time.toLocalDate()),
(r, join) -> { (r, join) -> {
LocalDateTime now = LocalDateTime.now(); LocalDateTime now = LocalDateTime.now();
if (!DateTimeUtils.sameMonth(join.toLocalDate(), now.toLocalDate())) { if (DateTimeUtils.sameMonth(join.toLocalDate(), now.toLocalDate())) {
if (DateTimeUtils.sameMonth(r.getDate(), now.toLocalDate())) {
return Duration.between(join, now).plus(r.getMonthlyTime());
} else {
return Duration.between(join, now);
}
} else {
return Duration.between(DateTimeUtils.currentMonthStartTime(), now); return Duration.between(DateTimeUtils.currentMonthStartTime(), now);
} }
if (DateTimeUtils.sameMonth(r.getDate(), now.toLocalDate())) {
return Duration.between(join, now).plus(r.getMonthlyTime());
}
return Duration.between(join, now);
} }
); );
@@ -82,22 +97,19 @@ public enum IntervalType {
return maxDuration; return maxDuration;
} }
public @NotNull BiFunction<TimeRecord, LocalDateTime, Duration> calculator() {
return calculator;
}
public @NotNull Predicate<LocalDateTime> changePredicator() {
return periodChangePredicate;
}
public Duration calculate(@NotNull TimeRecord timeRecord, @NotNull LocalDateTime joinTime) { public Duration calculate(@NotNull TimeRecord timeRecord, @NotNull LocalDateTime joinTime) {
Duration result = calculator.apply(timeRecord, joinTime); Duration result = calculator.apply(timeRecord, joinTime);
// 如果超过最大值,则返回最大值 // 如果超过最大值,则返回最大值
return result.compareTo(maxDuration) > 0 ? maxDuration : result; if (result.compareTo(maxDuration) > 0) {
Main.debugging("在线时间超过最大值,类型: " + this.name() + ", 计算结果: " + result + " 加入时间 " + joinTime + " 时间记录" + timeRecord);
return maxDuration;
}
return result;
} }
public boolean isPeriodChanged(@NotNull LocalDateTime claimedDate) { public boolean isPeriodChanged(@NotNull LocalDateTime claimedDate) {
return changePredicator().test(claimedDate); return periodChangePredicate.test(claimedDate);
} }
public static IntervalType parse(String input) { public static IntervalType parse(String input) {
@@ -38,15 +38,18 @@ public class UserManager extends UserDataManager<UUID, UserRewardData> {
MySQLStorage storage = Main.getStorage(); MySQLStorage storage = Main.getStorage();
@Nullable UserRewardData current = loadData(data.getUserUUID()); // 考虑读取时间差,优先利用数据库的当前数据计算 // 考虑读取时间差,优先利用数据库的当前数据计算
TimeRecord oldRecord = current == null ? data.getTimeRecord() : current.getTimeRecord(); @Nullable TimeRecord inDatabase = storage.loadTimeRecord(data.getUserUUID());
TimeRecord oldRecord = inDatabase == null ? data.getTimeRecord() : inDatabase;
Main.debugging("用户 " + data.getUserUUID() + " 的旧记录: " + oldRecord);
// 只需要保存游玩时间数据,领取数据已经实时保存了 // 只需要保存游玩时间数据,领取数据已经实时保存了
Duration daily = IntervalType.DAILY.calculate(oldRecord, data.getJoinTime()); Duration daily = IntervalType.DAILY.calculate(oldRecord, data.getJoinTime());
Duration weekly = IntervalType.WEEKLY.calculate(oldRecord, data.getJoinTime()); Duration weekly = IntervalType.WEEKLY.calculate(oldRecord, data.getJoinTime());
Duration monthly = IntervalType.MONTHLY.calculate(oldRecord, data.getJoinTime()); Duration monthly = IntervalType.MONTHLY.calculate(oldRecord, data.getJoinTime());
Duration total = IntervalType.TOTAL.calculate(oldRecord, data.getJoinTime()); Duration total = IntervalType.TOTAL.calculate(oldRecord, data.getJoinTime());
TimeRecord newRecord = new TimeRecord(LocalDate.now(), daily, weekly, monthly, total); TimeRecord newRecord = new TimeRecord(LocalDate.now(), daily, weekly, monthly, total);
Main.debugging("用户 " + data.getUserUUID() + " 的新记录: " + newRecord);
storage.savePlayTime(data.getUserUUID(), newRecord); storage.savePlayTime(data.getUserUUID(), newRecord);
} }
@@ -76,6 +76,13 @@ public class MySQLStorage {
long monthly = rs.getLong("monthly_time"); long monthly = rs.getLong("monthly_time");
long total = rs.getLong("total_time"); long total = rs.getLong("total_time");
Main.debugging("成功从数据库中加载用户在线时间记录: " + uuid + " -> {",
" - DAILY = " + daily,
" - WEEKLY = " + weekly,
" - MONTHLY = " + monthly,
" - TOTAL = " + total,
"}");
return new TimeRecord(date, daily, weekly, monthly, total); return new TimeRecord(date, daily, weekly, monthly, total);
}, TimeRecord.empty()); }, TimeRecord.empty());
} }
@@ -18,7 +18,9 @@ public class DateTimeUtils {
} }
public static boolean sameDay(LocalDate a, LocalDate b) { public static boolean sameDay(LocalDate a, LocalDate b) {
return a.getDayOfYear() == b.getDayOfYear() && a.getYear() == b.getYear(); return a.getYear() == b.getYear() &&
a.getMonth() == b.getMonth() &&
a.getDayOfMonth() == b.getDayOfMonth();
} }
public static boolean sameWeek(Temporal a) { public static boolean sameWeek(Temporal a) {
@@ -0,0 +1,22 @@
package cc.carm.plugin.tests;
import cc.carm.plugin.timereward.data.IntervalType;
import cc.carm.plugin.timereward.data.TimeRecord;
import org.junit.Test;
import java.time.LocalDate;
import java.time.LocalDateTime;
public class IntervalTest {
@Test
public void test() {
System.out.println(IntervalType.DAILY.calculate(
new TimeRecord(LocalDate.now(), 100, 200, 300, 400),
LocalDateTime.now()
).getSeconds());
}
}