Skip to content

Commit

Permalink
Merge pull request #200 from softeerbootcamp4th/fix/#199-faster-alg
Browse files Browse the repository at this point in the history
fix/#199-faster-alg
  • Loading branch information
wjddn2165 authored Aug 21, 2024
2 parents 9c9f82b + b9d2b07 commit c89d782
Show file tree
Hide file tree
Showing 3 changed files with 37 additions and 27 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,8 @@ public class LotteryParticipants extends BaseEntity {
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;

@OneToOne // mappedBy 이용하면 둘 다 저장 안해도 됨
@OneToOne(fetch = FetchType.LAZY) // mappedBy 이용하면 둘 다 저장 안해도 됨
@JoinColumn(name = "base_user_id")
//todo: 왜이런지 알아보기
@JsonBackReference
@JsonIgnore
private BaseUser baseUser;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import org.springframework.data.jpa.repository.Query;
import org.springframework.stereotype.Repository;

import java.util.List;
import java.util.Optional;

@Repository
Expand All @@ -20,5 +21,8 @@ public interface LotteryParticipantsRepository extends JpaRepository<LotteryPart

@Query("SELECT COUNT(p) FROM LotteryParticipants p WHERE p.baseUser.id LIKE :id%")
long countByBaseUser_Id(@Param("id") String id);

@Query("SELECT lp.id, lp.appliedCount From LotteryParticipants lp")
List<Object[]> findIdAndAppliedCounts();
}

Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,6 @@ public Admin verifyAdmin(AdminRequestDto adminRequestDto) {
// 어드민 생성
public ResponseDto postAdmin(AdminRequestDto adminRequestDto) {
String adminId = adminRequestDto.getAdminId();
//Todo: 비밀번호 암호화 필요
String password = adminRequestDto.getPassword();

Admin admin = adminRepository.findById(adminId).orElse(null);
Expand Down Expand Up @@ -338,41 +337,49 @@ public ResponseDto pickLotteryEventWinners() {

int winnerCount = lotteryEvent.getWinnerCount();

List<LotteryParticipants> lotteryParticipants = lotteryParticipantsRepository.findAll();
List<Object[]> lotteryParticipants = lotteryParticipantsRepository.findIdAndAppliedCounts();

if(winnerCount >= lotteryParticipants.size()){
for (LotteryParticipants lotteryParticipant : lotteryParticipants) {
lotteryWinnerRepository.save(new LotteryWinners(lotteryParticipant));
if (winnerCount >= lotteryParticipants.size()) {
for (Object[] lotteryParticipant : lotteryParticipants) {
lotteryWinnerRepository.save(new LotteryWinners(
lotteryParticipantsRepository.findById((Long) lotteryParticipant[0]).get()
));
}
return new ResponseDto("추첨이 완료되었습니다.");
}
Set<LotteryParticipants> lotteryEventWinners = new HashSet<>();

int totalWeight;
Random random = new Random();
while (lotteryEventWinners.size() < winnerCount) {
totalWeight = 0;
for (LotteryParticipants lotteryParticipant : lotteryParticipants) {
totalWeight += lotteryParticipant.getAppliedCount();
}
int appliedCount;
List<Long> appliedParticipants = new ArrayList<>();

int randomValue = random.nextInt(totalWeight) + 1;

int cumulativeSum = 0;
for (LotteryParticipants lotteryParticipant : lotteryParticipants) {
cumulativeSum += lotteryParticipant.getAppliedCount();
if (randomValue <= cumulativeSum) {
lotteryEventWinners.add(lotteryParticipant);
lotteryParticipants.remove(lotteryParticipant);
break;
}
for (Object[] lotteryParticipant : lotteryParticipants) {
appliedCount = (int) lotteryParticipant[1];
for (int i = 0; i < appliedCount; i++) {
appliedParticipants.add((long) lotteryParticipant[0]);
}
}

for (LotteryParticipants lotteryEventWinner : lotteryEventWinners) {
lotteryWinnerRepository.save(new LotteryWinners(lotteryEventWinner));
// Fisher-Yates Shuffle Algorithm
Random random = new Random();
for (int i = appliedParticipants.size() - 1; i > 0; i--) {
int j = random.nextInt(i + 1);
Long temp = appliedParticipants.get(i);
appliedParticipants.set(i, appliedParticipants.get(j));
appliedParticipants.set(j, temp);
}

Set<Long> lotteryEventWinners = new HashSet<>();
while (lotteryEventWinners.size() < winnerCount) {
Long winnerId = appliedParticipants.remove(0);
if (lotteryEventWinners.contains(winnerId)) continue;
lotteryEventWinners.add(winnerId);
}

List<LotteryWinners> winnersToSave = lotteryEventWinners.stream()
.map(winnerId -> new LotteryWinners(lotteryParticipantsRepository.findById(winnerId).get()))
.collect(Collectors.toList());

lotteryWinnerRepository.saveAll(winnersToSave);

return new ResponseDto("추첨이 완료되었습니다.");
}

Expand Down

0 comments on commit c89d782

Please sign in to comment.