Code · LLD machine coding · PhonePe prep
Hackathon Platform (machine coding round)
Design a coding-contest platform.
Question
Design a coding-contest platform.
- Add problems to a question library: description, tags, difficulty, score.
- Contestants register with a name and department.
- Fetch problems filtered by difficulty or tag and sorted by score, extensible to new filters and sorts.
- A contestant solves a problem (with the time taken); list the problems a contestant has solved.
- For a problem: how many users solved it and the average time taken.
- Scoring is pluggable: a fixed score, or a score adjusted by solve time.
- Return the current leader.
- Top N most-solved problems for a tag.
- Extension: after a solve, recommend 5 problems with similar tags.
Design: repositories + services, Strategy for scoring and recommendations, Predicate / Comparator for filters,
custom exceptions, unit tests in src/test. Run HackathonPlatformDemo; it prints each requirement in order.
entities/Contestant.java 22 lines GitHub ↗
package com.practice.phonepe.interview.entities;
import java.util.UUID;
public class Contestant {
private final String id;
private final String name;
private final String department;
//add a field to store createdat
public Contestant(String name, String department) {
this.id = UUID.randomUUID().toString();
this.name = name;
this.department = department;
}
public String getId() {
return id;
}
public String getName() {
return name;
}
public String getDepartment() {
return department;
}
} entities/Difficulty.java 4 lines GitHub ↗
package com.practice.phonepe.interview.entities;
public enum Difficulty {
EASY, MEDIUM, HARD
} entities/Problem.java 32 lines GitHub ↗
package com.practice.phonepe.interview.entities;
import java.util.Set;
import java.util.UUID;
public class Problem {
private final String id;
private final String description;
private final Set<String> tags;
private final Difficulty difficulty;
private final int baseScore;
public Problem(String description, Set<String> tags, Difficulty difficulty, int baseScore) {
this.id = UUID.randomUUID().toString();
this.description = description;
this.tags = tags;
this.difficulty = difficulty;
this.baseScore = baseScore;
}
public String getId() {
return id;
}
public String getDescription() {
return description;
}
public Set<String> getTags() {
return tags;
}
public Difficulty getDifficulty() {
return difficulty;
}
public int getBaseScore() {
return baseScore;
}
} entities/Submission.java 33 lines GitHub ↗
package com.practice.phonepe.interview.entities;
import java.time.Instant;
public class Submission {
private final String contestantId;
private final String problemId;
private final int timeTakenSeconds;
private final int scoreAwarded;
private final Instant solvedAt;
// scoreAwarded is captured at solve time rather than recomputed later, so a contestant's
// total score stays correct even if the scoring strategy is swapped mid-contest.
public Submission(String contestantId, String problemId, int timeTakenSeconds, int scoreAwarded) {
this.contestantId = contestantId;
this.problemId = problemId;
this.timeTakenSeconds = timeTakenSeconds;
this.scoreAwarded = scoreAwarded;
this.solvedAt = Instant.now();
}
public String getContestantId() {
return contestantId;
}
public String getProblemId() {
return problemId;
}
public int getTimeTakenSeconds() {
return timeTakenSeconds;
}
public int getScoreAwarded() {
return scoreAwarded;
}
public Instant getSolvedAt() {
return solvedAt;
}
} exception/AlreadySolvedException.java 6 lines GitHub ↗
package com.practice.phonepe.interview.exception;
public class AlreadySolvedException extends RuntimeException {
public AlreadySolvedException(String message) {
super(message);
}
} exception/EntityNotFoundException.java 6 lines GitHub ↗
package com.practice.phonepe.interview.exception;
public class EntityNotFoundException extends RuntimeException {
public EntityNotFoundException(String message) {
super(message);
}
} repository/ContestantRepository.java 9 lines GitHub ↗
package com.practice.phonepe.interview.repository;
import com.practice.phonepe.interview.entities.Contestant;
import java.util.List;
import java.util.Optional;
public interface ContestantRepository {
void save(Contestant contestant);
Optional<Contestant> findById(String contestantId);
List<Contestant> findAll();
} repository/InMemoryContestantRepository.java 22 lines GitHub ↗
package com.practice.phonepe.interview.repository;
import com.practice.phonepe.interview.entities.Contestant;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
public class InMemoryContestantRepository implements ContestantRepository {
private final Map<String, Contestant> contestantsById = new LinkedHashMap<>();
@Override
public void save(Contestant contestant) {
contestantsById.put(contestant.getId(), contestant);
}
@Override
public Optional<Contestant> findById(String contestantId) {
return Optional.ofNullable(contestantsById.get(contestantId));
}
@Override
public List<Contestant> findAll() {
return new ArrayList<>(contestantsById.values());
}
} repository/InMemoryProblemRepository.java 22 lines GitHub ↗
package com.practice.phonepe.interview.repository;
import com.practice.phonepe.interview.entities.Problem;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
public class InMemoryProblemRepository implements ProblemRepository {
private final Map<String, Problem> problemsById = new LinkedHashMap<>();
@Override
public void save(Problem problem) {
problemsById.put(problem.getId(), problem);
}
@Override
public Optional<Problem> findById(String problemId) {
return Optional.ofNullable(problemsById.get(problemId));
}
@Override
public List<Problem> findAll() {
return new ArrayList<>(problemsById.values());
}
} repository/InMemorySubmissionRepository.java 28 lines GitHub ↗
package com.practice.phonepe.interview.repository;
import com.practice.phonepe.interview.entities.Submission;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
public class InMemorySubmissionRepository implements SubmissionRepository {
private final List<Submission> submissions = new ArrayList<>();
@Override
public void save(Submission submission) {
submissions.add(submission);
}
@Override
public List<Submission> findByContestant(String contestantId) {
return submissions.stream()
.filter(submission -> submission.getContestantId().equals(contestantId))
.collect(Collectors.toList());
}
@Override
public List<Submission> findByProblem(String problemId) {
return submissions.stream()
.filter(submission -> submission.getProblemId().equals(problemId))
.collect(Collectors.toList());
}
@Override
public List<Submission> findAll() {
return new ArrayList<>(submissions);
}
} repository/ProblemRepository.java 9 lines GitHub ↗
package com.practice.phonepe.interview.repository;
import com.practice.phonepe.interview.entities.Problem;
import java.util.List;
import java.util.Optional;
public interface ProblemRepository {
void save(Problem problem);
Optional<Problem> findById(String problemId);
List<Problem> findAll();
} repository/SubmissionRepository.java 9 lines GitHub ↗
package com.practice.phonepe.interview.repository;
import com.practice.phonepe.interview.entities.Submission;
import java.util.List;
public interface SubmissionRepository {
void save(Submission submission);
List<Submission> findByContestant(String contestantId);
List<Submission> findByProblem(String problemId);
List<Submission> findAll();
} service/ContestantService.java 37 lines GitHub ↗
package com.practice.phonepe.interview.service;
import com.practice.phonepe.interview.entities.Contestant;
import com.practice.phonepe.interview.entities.Problem;
import com.practice.phonepe.interview.exception.EntityNotFoundException;
import com.practice.phonepe.interview.repository.ContestantRepository;
import com.practice.phonepe.interview.repository.ProblemRepository;
import com.practice.phonepe.interview.repository.SubmissionRepository;
import java.util.List;
import java.util.stream.Collectors;
public class ContestantService {
private final ContestantRepository contestantRepository;
private final SubmissionRepository submissionRepository;
private final ProblemRepository problemRepository;
public ContestantService(ContestantRepository contestantRepository,
SubmissionRepository submissionRepository,
ProblemRepository problemRepository) {
this.contestantRepository = contestantRepository;
this.submissionRepository = submissionRepository;
this.problemRepository = problemRepository;
}
public Contestant addContestant(String name, String department) {
Contestant contestant = new Contestant(name, department);
contestantRepository.save(contestant);
return contestant;
}
public List<Problem> fetchSolvedProblems(String contestantId) {
requireContestant(contestantId);
return submissionRepository.findByContestant(contestantId).stream()
.map(submission -> problemRepository.findById(submission.getProblemId())
.orElseThrow(() -> new EntityNotFoundException("Problem not found: " + submission.getProblemId())))
.collect(Collectors.toList());
}
private Contestant requireContestant(String contestantId) {
return contestantRepository.findById(contestantId)
.orElseThrow(() -> new EntityNotFoundException("Contestant not found: " + contestantId));
}
} service/ContestService.java 86 lines GitHub ↗
package com.practice.phonepe.interview.service;
import com.practice.phonepe.interview.entities.Contestant;
import com.practice.phonepe.interview.entities.Problem;
import com.practice.phonepe.interview.entities.Submission;
import com.practice.phonepe.interview.exception.AlreadySolvedException;
import com.practice.phonepe.interview.exception.EntityNotFoundException;
import com.practice.phonepe.interview.repository.ContestantRepository;
import com.practice.phonepe.interview.repository.ProblemRepository;
import com.practice.phonepe.interview.repository.SubmissionRepository;
import com.practice.phonepe.interview.strategy.RecommendationStrategy;
import com.practice.phonepe.interview.strategy.ScoringStrategy;
import java.security.KeyPair;
import java.util.*;
import java.util.stream.Collectors;
class Pair {
int key;
Contestant contestant;
public Pair(int key , Contestant contestant) {
this.key = key;
this.contestant = contestant;
}
}
public class ContestService {
private static final int RECOMMENDATION_COUNT = 5;
private final ContestantRepository contestantRepository;
private final ProblemRepository problemRepository;
private final SubmissionRepository submissionRepository;
private final ScoringStrategy scoringStrategy;
private final RecommendationStrategy recommendationStrategy;
private final PriorityQueue<Pair> leaderBoard;
public ContestService(ContestantRepository contestantRepository,
ProblemRepository problemRepository,
SubmissionRepository submissionRepository,
ScoringStrategy scoringStrategy,
RecommendationStrategy recommendationStrategy) {
this.contestantRepository = contestantRepository;
this.problemRepository = problemRepository;
this.submissionRepository = submissionRepository;
this.scoringStrategy = scoringStrategy;
this.recommendationStrategy = recommendationStrategy;
this.leaderBoard = new PriorityQueue<>();
}
public SolveResult solve(String contestantId, String problemId, int timeTakenSeconds) {
Contestant contestant = contestantRepository.findById(contestantId)
.orElseThrow(() -> new EntityNotFoundException("Contestant not found: " + contestantId));
Problem problem = problemRepository.findById(problemId)
.orElseThrow(() -> new EntityNotFoundException("Problem not found: " + problemId));
Set<String> solvedProblemIds = submissionRepository.findByContestant(contestantId).stream()
.map(Submission::getProblemId)
.collect(Collectors.toSet());
if (solvedProblemIds.contains(problemId)) {
throw new AlreadySolvedException(contestant.getName() + " has already solved this problem");
}
int scoreAwarded = scoringStrategy.calculateScore(problem, timeTakenSeconds);
submissionRepository.save(new Submission(contestantId, problemId, timeTakenSeconds, scoreAwarded));
//
Pair pair = new Pair(scoreAwarded, contestant);
leaderBoard.add(pair);
List<Problem> candidates = problemRepository.findAll().stream()
.filter(candidate -> !candidate.getId().equals(problemId))
.filter(candidate -> !solvedProblemIds.contains(candidate.getId()))
.collect(Collectors.toList());
List<Problem> recommendations = recommendationStrategy.recommend(problem, candidates, RECOMMENDATION_COUNT);
// M - contestant , N - problem
// O(log(M)) + O(N)
return new SolveResult(scoreAwarded, recommendations);
}
public Optional<Contestant> getLeader() {
if (submissionRepository.findAll().isEmpty()) {
return Optional.empty();
}
Map<String, Integer> totalScoreByContestant = submissionRepository.findAll().stream()
.collect(Collectors.groupingBy(Submission::getContestantId, Collectors.summingInt(Submission::getScoreAwarded)));
// Assumption: ties broken by earliest-registered contestant
Contestant leader = null;
int bestScore = Integer.MIN_VALUE;
for (Contestant contestant : contestantRepository.findAll()) {
int score = totalScoreByContestant.getOrDefault(contestant.getId(), 0);
if (score > bestScore) {
bestScore = score;
leader = contestant;
}
}
return Optional.ofNullable(leader);
}
} service/ProblemService.java 48 lines GitHub ↗
package com.practice.phonepe.interview.service;
import com.practice.phonepe.interview.entities.Problem;
import com.practice.phonepe.interview.entities.Submission;
import com.practice.phonepe.interview.exception.EntityNotFoundException;
import com.practice.phonepe.interview.repository.ProblemRepository;
import com.practice.phonepe.interview.repository.SubmissionRepository;
import java.util.Comparator;
import java.util.List;
import java.util.function.Predicate;
import java.util.stream.Collectors;
public class ProblemService {
private final ProblemRepository problemRepository;
private final SubmissionRepository submissionRepository;
public ProblemService(ProblemRepository problemRepository, SubmissionRepository submissionRepository) {
this.problemRepository = problemRepository;
this.submissionRepository = submissionRepository;
}
public void addProblem(Problem problem) {
problemRepository.save(problem);
}
public List<Problem> fetchProblems(Predicate<Problem> filter, Comparator<Problem> sortBy) {
return problemRepository.findAll().stream()
.filter(filter)
.sorted(sortBy)
.collect(Collectors.toList());
}
public ProblemStats getProblemStats(String problemId) {
requireProblem(problemId);
List<Submission> submissions = submissionRepository.findByProblem(problemId);
double averageTime = submissions.stream()
.mapToInt(Submission::getTimeTakenSeconds)
.average()
.orElse(0);
return new ProblemStats(submissions.size(), averageTime);
}
// "Liked" isn't defined anywhere in the spec beyond solving, so it's treated as solve count.
public List<Problem> getTopNProblems(String tag, int n) {
return problemRepository.findAll().stream()
.filter(problem -> problem.getTags().contains(tag))
.sorted(Comparator.comparingInt((Problem problem) -> submissionRepository.findByProblem(problem.getId()).size()).reversed())
.limit(n)
.collect(Collectors.toList());
}
private Problem requireProblem(String problemId) {
return problemRepository.findById(problemId)
.orElseThrow(() -> new EntityNotFoundException("Problem not found: " + problemId));
}
} service/ProblemStats.java 15 lines GitHub ↗
package com.practice.phonepe.interview.service;
public class ProblemStats {
private final int solveCount;
private final double averageTimeTakenSeconds;
public ProblemStats(int solveCount, double averageTimeTakenSeconds) {
this.solveCount = solveCount;
this.averageTimeTakenSeconds = averageTimeTakenSeconds;
}
public int getSolveCount() {
return solveCount;
}
public double getAverageTimeTakenSeconds() {
return averageTimeTakenSeconds;
}
} service/SolveResult.java 17 lines GitHub ↗
package com.practice.phonepe.interview.service;
import com.practice.phonepe.interview.entities.Problem;
import java.util.List;
public class SolveResult {
private final int scoreAwarded;
private final List<Problem> recommendedProblems;
public SolveResult(int scoreAwarded, List<Problem> recommendedProblems) {
this.scoreAwarded = scoreAwarded;
this.recommendedProblems = recommendedProblems;
}
public int getScoreAwarded() {
return scoreAwarded;
}
public List<Problem> getRecommendedProblems() {
return recommendedProblems;
}
} strategy/FixedScoreStrategy.java 8 lines GitHub ↗
package com.practice.phonepe.interview.strategy;
import com.practice.phonepe.interview.entities.Problem;
public class FixedScoreStrategy implements ScoringStrategy {
@Override
public int calculateScore(Problem problem, int timeTakenSeconds) {
return problem.getBaseScore();
}
} strategy/RecommendationStrategy.java 8 lines GitHub ↗
package com.practice.phonepe.interview.strategy;
import com.practice.phonepe.interview.entities.Problem;
import java.util.List;
public interface RecommendationStrategy {
// candidates is expected to already exclude justSolved and anything the contestant has
// solved, so the strategy only has to rank, not filter.
List<Problem> recommend(Problem justSolved, List<Problem> candidates, int count);
} strategy/ScoringStrategy.java 5 lines GitHub ↗
package com.practice.phonepe.interview.strategy;
import com.practice.phonepe.interview.entities.Problem;
public interface ScoringStrategy {
int calculateScore(Problem problem, int timeTakenSeconds);
} strategy/SimilarTagRecommendationStrategy.java 21 lines GitHub ↗
package com.practice.phonepe.interview.strategy;
import com.practice.phonepe.interview.entities.Problem;
import java.util.Comparator;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
public class SimilarTagRecommendationStrategy implements RecommendationStrategy {
@Override
public List<Problem> recommend(Problem justSolved, List<Problem> candidates, int count) {
return candidates.stream()
.sorted(Comparator.comparingInt((Problem candidate) -> sharedTagCount(justSolved, candidate)).reversed())
.limit(count)
.collect(Collectors.toList());
}
private int sharedTagCount(Problem a, Problem b) {
Set<String> shared = new HashSet<>(a.getTags());
shared.retainAll(b.getTags());
return shared.size();
}
} strategy/TimeAdjustedScoreStrategy.java 19 lines GitHub ↗
package com.practice.phonepe.interview.strategy;
import com.practice.phonepe.interview.entities.Problem;
public class TimeAdjustedScoreStrategy implements ScoringStrategy {
private final int fastSolveThresholdSeconds;
public TimeAdjustedScoreStrategy(int fastSolveThresholdSeconds) {
this.fastSolveThresholdSeconds = fastSolveThresholdSeconds;
}
@Override
public int calculateScore(Problem problem, int timeTakenSeconds) {
// Assumption: no exact formula was specified. Full score within the threshold, then a
// 10% penalty per additional threshold interval, floored at half the base score.
if (timeTakenSeconds <= fastSolveThresholdSeconds) {
return problem.getBaseScore();
}
int intervalsLate = (timeTakenSeconds - fastSolveThresholdSeconds) / fastSolveThresholdSeconds;
double penalty = Math.min(0.5, intervalsLate * 0.1);
return (int) Math.round(problem.getBaseScore() * (1 - penalty));
}
} HackathonPlatformDemo.java 155 lines GitHub ↗
package com.practice.phonepe.interview;
import com.practice.phonepe.interview.entities.Contestant;
import com.practice.phonepe.interview.entities.Difficulty;
import com.practice.phonepe.interview.entities.Problem;
import com.practice.phonepe.interview.exception.AlreadySolvedException;
import com.practice.phonepe.interview.exception.EntityNotFoundException;
import com.practice.phonepe.interview.repository.ContestantRepository;
import com.practice.phonepe.interview.repository.InMemoryContestantRepository;
import com.practice.phonepe.interview.repository.InMemoryProblemRepository;
import com.practice.phonepe.interview.repository.InMemorySubmissionRepository;
import com.practice.phonepe.interview.repository.ProblemRepository;
import com.practice.phonepe.interview.repository.SubmissionRepository;
import com.practice.phonepe.interview.service.ContestService;
import com.practice.phonepe.interview.service.ContestantService;
import com.practice.phonepe.interview.service.ProblemService;
import com.practice.phonepe.interview.service.ProblemStats;
import com.practice.phonepe.interview.service.SolveResult;
import com.practice.phonepe.interview.strategy.FixedScoreStrategy;
import com.practice.phonepe.interview.strategy.RecommendationStrategy;
import com.practice.phonepe.interview.strategy.ScoringStrategy;
import com.practice.phonepe.interview.strategy.SimilarTagRecommendationStrategy;
import com.practice.phonepe.interview.strategy.TimeAdjustedScoreStrategy;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Optional;
import java.util.Set;
// Each section below is labelled with the exact requirement it answers, in the same order
// the PDF lists them, so the two can be read side by side.
public class HackathonPlatformDemo {
public static void main(String[] args) {
ProblemRepository problemRepository = new InMemoryProblemRepository();
ContestantRepository contestantRepository = new InMemoryContestantRepository();
SubmissionRepository submissionRepository = new InMemorySubmissionRepository();
ScoringStrategy scoringStrategy = new TimeAdjustedScoreStrategy(300); // 5 min fast-solve threshold
RecommendationStrategy recommendationStrategy = new SimilarTagRecommendationStrategy();
ProblemService problemService = new ProblemService(problemRepository, submissionRepository);
ContestantService contestantService = new ContestantService(contestantRepository, submissionRepository, problemRepository);
ContestService contestService = new ContestService(
contestantRepository, problemRepository, submissionRepository, scoringStrategy, recommendationStrategy);
requirement(1, "add problems to the Questions Library");
Problem twoSum = new Problem("Two Sum", Set.of("array", "hashing"), Difficulty.EASY, 100);
Problem mergeIntervals = new Problem("Merge Intervals", Set.of("array", "sorting"), Difficulty.MEDIUM, 200);
Problem lruCache = new Problem("LRU Cache", Set.of("design", "hashing"), Difficulty.MEDIUM, 250);
Problem wordLadder = new Problem("Word Ladder", Set.of("graph", "bfs"), Difficulty.HARD, 400);
Problem medianOfArrays = new Problem("Median of Two Sorted Arrays", Set.of("array", "binary-search"), Difficulty.HARD, 450);
Problem validParentheses = new Problem("Valid Parentheses", Set.of("stack"), Difficulty.EASY, 80);
List.of(twoSum, mergeIntervals, lruCache, wordLadder, medianOfArrays, validParentheses)
.forEach(problemService::addProblem);
System.out.println(problemRepository.findAll().size() + " problems added");
requirement(2, "contestants register with their name and department");
Contestant aayushi = contestantService.addContestant("Aayushi", "Backend");
Contestant riya = contestantService.addContestant("Riya", "Frontend");
Contestant karan = contestantService.addContestant("Karan", "Backend");
System.out.println(aayushi.getName() + " (" + aayushi.getDepartment() + ") registered");
System.out.println(riya.getName() + " (" + riya.getDepartment() + ") registered");
System.out.println(karan.getName() + " (" + karan.getDepartment() + ") registered");
requirement(3, "a problem carries description, tag(s), difficulty, score");
printProblems(List.of(twoSum));
requirement(4, "filter by difficulty or tag, sort by score (extensible via Predicate/Comparator)");
System.out.println("filter difficulty=EASY, sort by score ascending:");
printProblems(problemService.fetchProblems(
problem -> problem.getDifficulty() == Difficulty.EASY,
Comparator.comparingInt(Problem::getBaseScore)));
System.out.println("filter tag=array, sort by score descending:");
printProblems(problemService.fetchProblems(
problem -> problem.getTags().contains("array"),
Comparator.comparingInt(Problem::getBaseScore).reversed()));
requirement(5, "solve a problem, then list problems solved by that contestant");
List<SolveResult> solves = new ArrayList<>();
solves.add(solveAndPrint(contestService, aayushi, twoSum, 200));
solves.add(solveAndPrint(contestService, aayushi, mergeIntervals, 900));
solves.add(solveAndPrint(contestService, riya, twoSum, 700));
solves.add(solveAndPrint(contestService, karan, lruCache, 300));
solves.add(solveAndPrint(contestService, aayushi, validParentheses, 100));
System.out.println("problems solved by Aayushi:");
printProblems(contestantService.fetchSolvedProblems(aayushi.getId()));
requirement(6, "number of users who solved a problem + average time taken");
ProblemStats twoSumStats = problemService.getProblemStats(twoSum.getId());
System.out.println("Two Sum -> solvedBy=" + twoSumStats.getSolveCount()
+ " users, avgTime=" + twoSumStats.getAverageTimeTakenSeconds() + "s");
requirement(7, "scoring strategy is pluggable: fixed score, or score adjusted by time");
ScoringStrategy fixed = new FixedScoreStrategy();
int slowSolveTime = 900;
System.out.println("Merge Intervals solved in " + slowSolveTime + "s:");
System.out.println(" FixedScoreStrategy -> " + fixed.calculateScore(mergeIntervals, slowSolveTime));
System.out.println(" TimeAdjustedScoreStrategy -> " + scoringStrategy.calculateScore(mergeIntervals, slowSolveTime));
requirement(8, "return the current leader of the contest");
Optional<Contestant> leader = contestService.getLeader();
leader.ifPresent(c -> System.out.println(c.getName() + " (" + c.getDepartment() + ") is leading"));
requirement(9, "top N liked problems of a given tag (\"liked\" = solve count)");
System.out.println("top 10 tagged 'array' (only 3 exist, so all 3 come back):");
printProblems(problemService.getTopNProblems("array", 10));
extension("on solving a problem, return top 5 recommended problems by similar tags");
for (SolveResult solve : solves) {
if (!solve.getRecommendedProblems().isEmpty()) {
System.out.println(" recommended: " + describe(solve.getRecommendedProblems()));
}
}
note("exceptions handled gracefully, errors printed to the console");
try {
contestService.solve("no-such-contestant", twoSum.getId(), 100);
} catch (EntityNotFoundException e) {
System.err.println("ERROR: " + e.getMessage());
}
try {
contestService.solve(aayushi.getId(), "no-such-problem", 100);
} catch (EntityNotFoundException e) {
System.err.println("ERROR: " + e.getMessage());
}
try {
contestService.solve(aayushi.getId(), twoSum.getId(), 150); // already solved above
} catch (AlreadySolvedException e) {
System.err.println("ERROR: " + e.getMessage());
}
}
private static SolveResult solveAndPrint(ContestService contestService, Contestant contestant, Problem problem, int timeTakenSeconds) {
SolveResult result = contestService.solve(contestant.getId(), problem.getId(), timeTakenSeconds);
System.out.println(contestant.getName() + " solved '" + problem.getDescription()
+ "' in " + timeTakenSeconds + "s -> scored " + result.getScoreAwarded());
return result;
}
private static void requirement(int number, String description) {
System.out.println();
System.out.println("=== [Mandatory " + number + "] " + description + " ===");
}
private static void extension(String description) {
System.out.println();
System.out.println("=== [Extension] " + description + " ===");
}
private static void note(String description) {
System.out.println();
System.out.println("=== [" + description + "] ===");
}
private static void printProblems(List<Problem> problems) {
if (problems.isEmpty()) {
System.out.println(" (none)");
return;
}
for (Problem problem : problems) {
System.out.printf(" - %-28s tags=%-24s difficulty=%-6s score=%d%n",
problem.getDescription(), problem.getTags(), problem.getDifficulty(), problem.getBaseScore());
}
}
private static String describe(List<Problem> problems) {
StringBuilder builder = new StringBuilder();
for (Problem problem : problems) {
if (builder.length() > 0) {
builder.append(", ");
}
builder.append(problem.getDescription());
}
return builder.toString();
}
}