Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
import org.patinanetwork.codebloom.common.db.models.potd.POTD;
import org.patinanetwork.codebloom.common.db.models.question.Question;
import org.patinanetwork.codebloom.common.db.models.question.QuestionDifficulty;
import org.patinanetwork.codebloom.common.db.models.question.bank.QuestionBank;
import org.patinanetwork.codebloom.common.db.models.question.topic.LeetcodeTopicEnum;
import org.patinanetwork.codebloom.common.db.models.question.topic.QuestionTopic;
import org.patinanetwork.codebloom.common.db.models.user.User;
Expand All @@ -25,6 +26,7 @@
import org.patinanetwork.codebloom.common.db.repos.leaderboard.LeaderboardRepository;
import org.patinanetwork.codebloom.common.db.repos.potd.POTDRepository;
import org.patinanetwork.codebloom.common.db.repos.question.QuestionRepository;
import org.patinanetwork.codebloom.common.db.repos.question.questionbank.QuestionBankRepository;
import org.patinanetwork.codebloom.common.db.repos.question.topic.QuestionTopicRepository;
import org.patinanetwork.codebloom.common.db.repos.user.UserRepository;
import org.patinanetwork.codebloom.common.db.repos.user.options.UserFilterOptions;
Expand Down Expand Up @@ -53,6 +55,7 @@ public class SubmissionsHandler {
private final QuestionTopicRepository questionTopicRepository;
private final JobRepository jobRepository;
private final Reporter throttledReporter;
private final QuestionBankRepository questionBankRepository;

private boolean isValid(final LocalDateTime createdAt) {
// TODO - Replace EST locked functionality.
Expand All @@ -76,7 +79,8 @@ public SubmissionsHandler(
final UserRepository userRepository,
final QuestionTopicRepository questionTopicRepository,
final ThrottledReporter throttledReporter,
final JobRepository jobRepository) {
final JobRepository jobRepository,
final QuestionBankRepository questionBankRepository) {
this.questionRepository = questionRepository;
this.leetcodeClient = throttledLeetcodeClient;
this.leaderboardRepository = leaderboardRepository;
Expand All @@ -85,6 +89,7 @@ public SubmissionsHandler(
this.questionTopicRepository = questionTopicRepository;
this.jobRepository = jobRepository;
this.throttledReporter = throttledReporter;
this.questionBankRepository = questionBankRepository;
}

public static <T> Predicate<T> distinctByKey(final Function<? super T, ?> keyExtractor) {
Expand All @@ -99,11 +104,29 @@ public ArrayList<AcceptedSubmission> handleSubmissions(

var questionMap = leetcodeSubmissions.parallelStream()
.filter(distinctByKey(LeetcodeSubmission::getTitleSlug))
.map(s -> Pair.of(
s.getTitleSlug(),
fast
? leetcodeClient.findQuestionBySlugFast(s.getTitleSlug())
: leetcodeClient.findQuestionBySlug(s.getTitleSlug())))
.map(s -> {
String slug = s.getTitleSlug();

QuestionBank bankQuestion = questionBankRepository.getQuestionBySlug(slug);

if (bankQuestion == null) {
LeetcodeQuestion question = fast
? leetcodeClient.findQuestionBySlugFast(slug)
: leetcodeClient.findQuestionBySlug(slug);

bankQuestion = QuestionBank.builder()
.questionSlug(question.getTitleSlug())
.questionDifficulty(QuestionDifficulty.valueOf(question.getDifficulty()))
.questionTitle(question.getQuestionTitle())
.questionNumber(question.getQuestionId())
.questionLink("https://leetcode.com/problems/" + question.getTitleSlug())
.description(question.getQuestion())
.acceptanceRate(question.getAcceptanceRate())
.build();
}

return Pair.of(slug, bankQuestion);
})
.collect(Collectors.toMap(p -> p.getLeft(), p -> p.getRight()));

for (LeetcodeSubmission leetcodeSubmission : leetcodeSubmissions) {
Expand All @@ -127,7 +150,7 @@ public ArrayList<AcceptedSubmission> handleSubmissions(
multiplier = potd.getMultiplier();
}

LeetcodeQuestion leetcodeQuestion = questionMap.get(leetcodeSubmission.getTitleSlug());
QuestionBank bankQuestion = questionMap.get(leetcodeSubmission.getTitleSlug());

// If the submission is before the leaderboard started, points awarded = 0
Leaderboard recentLeaderboard = leaderboardRepository.getRecentLeaderboardMetadata();
Expand All @@ -152,9 +175,7 @@ public ArrayList<AcceptedSubmission> handleSubmissions(
points = 0;
} else {
points = ScoreCalculator.calculateScore(
QuestionDifficulty.valueOf(leetcodeQuestion.getDifficulty()),
leetcodeQuestion.getAcceptanceRate(),
multiplier);
bankQuestion.getQuestionDifficulty(), bankQuestion.getAcceptanceRate(), multiplier);
}

// throttledReporter.log(Report.builder()
Expand All @@ -178,36 +199,34 @@ public ArrayList<AcceptedSubmission> handleSubmissions(

Question newQuestion = Question.builder()
.userId(user.getId())
.questionSlug(leetcodeQuestion.getTitleSlug())
.questionDifficulty(QuestionDifficulty.valueOf(leetcodeQuestion.getDifficulty()))
.questionNumber(leetcodeQuestion.getQuestionId())
.questionLink("https://leetcode.com/problems/" + leetcodeQuestion.getTitleSlug())
.questionTitle(leetcodeQuestion.getQuestionTitle())
.description(leetcodeQuestion.getQuestion())
.questionSlug(bankQuestion.getQuestionSlug())
.questionDifficulty(bankQuestion.getQuestionDifficulty())
.questionNumber(bankQuestion.getQuestionNumber())
.questionLink("https://leetcode.com/problems/" + bankQuestion.getQuestionSlug())
.questionTitle(bankQuestion.getQuestionTitle())
.description(bankQuestion.getDescription())
.pointsAwarded(points)
.acceptanceRate(leetcodeQuestion.getAcceptanceRate())
.acceptanceRate(bankQuestion.getAcceptanceRate())
.submittedAt(leetcodeSubmission.getTimestamp())
.submissionId(String.valueOf(leetcodeSubmission.getId()))
.build();

var createdQuestion = questionRepository.createQuestion(newQuestion);

Job newJob = Job.builder()
.questionId(newQuestion.getId())
.status(JobStatus.INCOMPLETE)
.build();

jobRepository.createJob(newJob);

leetcodeQuestion.getTopics().stream()
bankQuestion.getTopics().stream()
.forEach(topic -> questionTopicRepository.createQuestionTopic(QuestionTopic.builder()
.questionId(newQuestion.getId())
.topicSlug(topic.getSlug())
.topic(LeetcodeTopicEnum.fromValue(topic.getSlug()))
.topicSlug(topic.getTopicSlug())
.topic(LeetcodeTopicEnum.fromValue(topic.getTopicSlug()))
.build()));

acceptedSubmissions.add(
new AcceptedSubmission(leetcodeQuestion.getQuestionTitle(), createdQuestion.getId(), points));
new AcceptedSubmission(bankQuestion.getQuestionTitle(), newQuestion.getId(), points));

UserWithScore recentUserMetadata = userRepository.getUserWithScoreByIdAndLeaderboardId(
user.getId(), recentLeaderboard.getId(), UserFilterOptions.DEFAULT);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
package org.patinanetwork.codebloom.common.submissions;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

import java.time.LocalDateTime;
import java.util.List;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.patinanetwork.codebloom.common.db.models.leaderboard.Leaderboard;
import org.patinanetwork.codebloom.common.db.models.question.QuestionDifficulty;
import org.patinanetwork.codebloom.common.db.models.question.bank.QuestionBank;
import org.patinanetwork.codebloom.common.db.models.user.User;
import org.patinanetwork.codebloom.common.db.models.user.UserWithScore;
import org.patinanetwork.codebloom.common.db.repos.job.JobRepository;
import org.patinanetwork.codebloom.common.db.repos.leaderboard.LeaderboardRepository;
import org.patinanetwork.codebloom.common.db.repos.potd.POTDRepository;
import org.patinanetwork.codebloom.common.db.repos.question.QuestionRepository;
import org.patinanetwork.codebloom.common.db.repos.question.questionbank.QuestionBankRepository;
import org.patinanetwork.codebloom.common.db.repos.question.topic.QuestionTopicRepository;
import org.patinanetwork.codebloom.common.db.repos.user.UserRepository;
import org.patinanetwork.codebloom.common.db.repos.user.options.UserFilterOptions;
import org.patinanetwork.codebloom.common.leetcode.models.LeetcodeSubmission;
import org.patinanetwork.codebloom.common.leetcode.throttled.ThrottledLeetcodeClient;
import org.patinanetwork.codebloom.common.reporter.throttled.ThrottledReporter;
import org.patinanetwork.codebloom.common.submissions.object.AcceptedSubmission;

public class SubmissionHandlerTest {
private final QuestionRepository questionRepository = mock(QuestionRepository.class);
private final ThrottledLeetcodeClient leetcodeClient = mock(ThrottledLeetcodeClient.class);
private final LeaderboardRepository leaderboardRepository = mock(LeaderboardRepository.class);
private final POTDRepository potdRepository = mock(POTDRepository.class);
private final UserRepository userRepository = mock(UserRepository.class);
private final QuestionTopicRepository questionTopicRepository = mock(QuestionTopicRepository.class);
private final JobRepository jobRepository = mock(JobRepository.class);
private final ThrottledReporter throttledReporter = mock(ThrottledReporter.class);
private final QuestionBankRepository questionBankRepository = mock(QuestionBankRepository.class);

private SubmissionsHandler submissionsHandler;

@BeforeEach
void setup() {
submissionsHandler = new SubmissionsHandler(
questionRepository,
leetcodeClient,
leaderboardRepository,
potdRepository,
userRepository,
questionTopicRepository,
throttledReporter,
jobRepository,
questionBankRepository);
}

// @Test
// void testHandleSubmission() {
// LeetcodeSubmission mockSub = mock(LeetcodeSubmission.class);
// List<LeetcodeSubmission> mockSubmissions = List.of(mockSub);
// User mockUser = mock(User.class);
// POTD mockPOTD = mock(POTD.class);
// QuestionBank mockBank = QuestionBank.builder()
// .id("bdbba382-1738-11f1-a2ff-4f7d0fe833a2")
// .questionSlug("hello-world")
// .questionDifficulty(QuestionDifficulty.Easy)
// .questionTitle("Hello World")
// .questionNumber(1)
// .questionLink("https://leetcode.com/problems/hello-world")
// .description("Print Hello World to the terminal")
// .acceptanceRate(1.0f)
// .createdAt(OffsetDateTime.now())
// .topics(List.of())
// .build();
// Leaderboard mockLeaderboard = mock(Leaderboard.class);

// when(potdRepository.getCurrentPOTD()).thenReturn(mockPOTD);
// when(mockSubmissions.parallelStream()
// .filter(SubmissionsHandler.distinctByKey(LeetcodeSubmission::getTitleSlug))
// .map(any())
// .collect(any()))
// .thenReturn(Map.of("mockSlug", mockBank));

// when(mockSub.getStatusDisplay()).thenReturn("Accepted");
// when(questionRepository.questionExistsBySubmissionId(String.valueOf(mockSub.getId())))
// .thenReturn(false);
// when(mockPOTD.getCreatedAt()).thenReturn(LocalDateTime.now());
// when(anyMap().get(anyString())).thenReturn(mockBank);
// when(leaderboardRepository.getRecentLeaderboardMetadata()).thenReturn(mockLeaderboard);
// when(mockLeaderboard.getCreatedAt().isAfter(mockSub.getTimestamp())).thenReturn(false);

// when(questionRepository.createQuestion(any(Question.class))).thenReturn(null);
// // when(bankQuestion.get)
// }

@Test
void testHandleSubmissionSuccess() {
LeetcodeSubmission submission =
new LeetcodeSubmission(1, "Hello World", "hello-world", LocalDateTime.now(), "Accepted");

User user = mock(User.class);
when(user.getId()).thenReturn("fb632fce-173e-11f1-8350-6f6b49d02c1c");

when(potdRepository.getCurrentPOTD()).thenReturn(null);

when(questionRepository.questionExistsBySubmissionId("1")).thenReturn(false);

when(questionRepository.getQuestionBySlugAndUserId("hello-world", "fb632fce-173e-11f1-8350-6f6b49d02c1c"))
.thenReturn(null);

Leaderboard leaderboard = mock(Leaderboard.class);
when(leaderboard.getId()).thenReturn("7c572df6-173f-11f1-8331-d3ac52e05366");
when(leaderboard.getCreatedAt()).thenReturn(submission.getTimestamp().minusHours(1));
when(leaderboardRepository.getRecentLeaderboardMetadata()).thenReturn(leaderboard);

UserWithScore userWithScore = mock(UserWithScore.class);
when(userWithScore.getTotalScore()).thenReturn(100);
when(userRepository.getUserWithScoreByIdAndLeaderboardId(
"fb632fce-173e-11f1-8350-6f6b49d02c1c",
"7c572df6-173f-11f1-8331-d3ac52e05366",
UserFilterOptions.DEFAULT))
.thenReturn(userWithScore);

QuestionBank bankQuestion = QuestionBank.builder()
.questionSlug("hello-world")
.questionDifficulty(QuestionDifficulty.Easy)
.questionTitle("Hello World")
.questionNumber(1)
.questionLink("https://leetcode.com/problems/hello-world")
.description("Print Hello World")
.acceptanceRate(1.0f)
.topics(List.of())
.build();

when(questionBankRepository.getQuestionBySlug("hello-world")).thenReturn(bankQuestion);

List<AcceptedSubmission> result = submissionsHandler.handleSubmissions(List.of(submission), user, true);

assertEquals(1, result.size());

verify(jobRepository).createJob(any());
verify(leaderboardRepository)
.updateUserPointsFromLeaderboard(
eq("7c572df6-173f-11f1-8331-d3ac52e05366"),
eq("fb632fce-173e-11f1-8350-6f6b49d02c1c"),
anyInt());
}
}
Loading