룰렛 변경

- 확률 수동 설정
- 여러개의 룰렛이 켜져있을 때 선택하여 돌리기
- 후원 히스토리에 룰렛 히스토리
This commit is contained in:
Yu Sung
2024-05-11 02:56:52 +09:00
parent 57abeea432
commit cab719c774
21 changed files with 339 additions and 265 deletions

View File

@@ -9,11 +9,10 @@ import SwiftUI
class RouletteOption: ObservableObject {
var title: String
var weight: Int
var percentage: String = "50.00"
var percentage: String = ""
init(title: String, weight: Int) {
init(title: String, percentage: String) {
self.title = title
self.weight = weight
self.percentage = percentage
}
}

View File

@@ -12,10 +12,7 @@ struct RouletteSettingsOptionView: View {
@ObservedObject var option: RouletteOption
let index: Int
let onClickPlus: () -> Void
let onClickDelete: () -> Void
let onClickSubstract: () -> Void
var body: some View {
VStack(spacing: 6.7) {
@@ -47,19 +44,28 @@ struct RouletteSettingsOptionView: View {
.background(Color(hex: "222222"))
.cornerRadius(6.7)
Text("\(option.percentage)%")
HStack(spacing: 0) {
TextField("0.00", text: $option.percentage)
.autocapitalization(.none)
.disableAutocorrection(true)
.font(.custom(Font.medium.rawValue, size: 13.3))
.foregroundColor(Color(hex: "eeeeee"))
.padding(.horizontal, 13.3)
.padding(.vertical, 16.7)
.background(Color(hex: "222222"))
.cornerRadius(6.7)
Image("btn_minus_round_rect")
.onTapGesture { onClickSubstract() }
Image("btn_plus_round_rect")
.onTapGesture { onClickPlus() }
.keyboardType(.decimalPad)
.onChange(of: option.percentage) { newValue in
if newValue.count > 5 {
option.percentage = String(newValue.prefix(5))
}
}
Text("%")
.font(.custom(Font.medium.rawValue, size: 13.3))
.foregroundColor(Color(hex: "eeeeee"))
}
.padding(.horizontal, 13.3)
.padding(.vertical, 16.7)
.frame(maxWidth: 85)
.background(Color(hex: "222222"))
.cornerRadius(6.7)
}
}
}
@@ -68,11 +74,9 @@ struct RouletteSettingsOptionView: View {
struct RouletteSettingsOptionView_Previews: PreviewProvider {
static var previews: some View {
RouletteSettingsOptionView(
option: RouletteOption(title: "옵션1", weight: 1),
option: RouletteOption(title: "옵션1", percentage: ""),
index: 2,
onClickPlus: {},
onClickDelete: {},
onClickSubstract: {}
onClickDelete: {}
)
}
}

View File

@@ -128,9 +128,7 @@ struct RouletteSettingsView: View {
RouletteSettingsOptionView(
option: viewModel.options[index],
index: index,
onClickPlus: { viewModel.plusWeight(index: index) },
onClickDelete: { viewModel.deleteOption(index: index) },
onClickSubstract: { viewModel.subtractWeight(index: index) }
onClickDelete: { viewModel.deleteOption(index: index) }
)
}
}
@@ -190,7 +188,7 @@ struct RouletteSettingsView: View {
isShowing: $viewModel.isShowPreview,
title: "룰렛 미리보기",
onClickSpin: nil,
preview: preview
previewList: [preview]
)
}
}

View File

@@ -46,47 +46,15 @@ final class RouletteSettingsViewModel: ObservableObject {
private var rouletteId = 0
@Published var rouletteList = [GetNewRouletteResponse]()
func plusWeight(index: Int) {
options[index].weight += 1
recalculatePercentages()
}
func subtractWeight(index: Int) {
if options[index].weight > 1 {
options[index].weight -= 1
recalculatePercentages()
}
}
func addOption() {
if (options.count >= 10) {
return
}
options.append(RouletteOption(title: "", weight: 1))
recalculatePercentages()
options.append(RouletteOption(title: "", percentage: ""))
}
func deleteOption(index: Int) {
options.remove(at: index)
recalculatePercentages()
}
private func recalculatePercentages() {
let options = options
var totalWeight = 0
for option in options {
totalWeight += option.weight
}
guard totalWeight > 0 else { return }
for i in 0..<options.count {
let percent = floor(Double(options[i].weight) / Double(totalWeight) * 10000) / 100
options[i].percentage = String(format: "%.2f", percent)
}
removeAllAndAddOptions(options: options)
}
private func removeAllAndAddOptions(options: [RouletteOption]) {
@@ -143,7 +111,7 @@ final class RouletteSettingsViewModel: ObservableObject {
items.append(RoulettePreviewItem(title: option.title, percent: "\(option.percentage)%"))
}
previewData = RoulettePreview(can: self.can, items: items)
previewData = RoulettePreview(id: 0, can: self.can, items: items)
isLoading = false
isShowPreview = true
}
@@ -152,25 +120,48 @@ final class RouletteSettingsViewModel: ObservableObject {
if !isLoading {
isLoading = true
if rouletteId > 0 {
updateRoulette(onSuccess: onSuccess)
} else {
createRoulette(onSuccess: onSuccess)
if validationOptions() {
if rouletteId > 0 {
updateRoulette(onSuccess: onSuccess)
} else {
createRoulette(onSuccess: onSuccess)
}
}
}
}
private func createRoulette(onSuccess: @escaping (Bool, String) -> Void) {
var items = [RouletteItem]()
private func validationOptions() -> Bool {
var totalPercentage = Float(0)
for option in options {
if option.title.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty {
isLoading = false
errorMessage = "옵션은 빈칸일 수 없습니다."
isShowErrorPopup = true
return
return false
}
items.append(RouletteItem(title: option.title, weight: option.weight))
if let percentage = Float(option.percentage) {
totalPercentage += percentage
}
}
if totalPercentage != Float(100) {
isLoading = false
errorMessage = "확률이 100%가 아닙니다"
isShowErrorPopup = true
return false
}
return true
}
private func createRoulette(onSuccess: @escaping (Bool, String) -> Void) {
var items = [RouletteItem]()
for option in options {
if let percentage = Float(option.percentage) {
items.append(RouletteItem(title: option.title, percentage: percentage))
}
}
let selectedRouletteTitle: String
@@ -227,14 +218,9 @@ final class RouletteSettingsViewModel: ObservableObject {
private func updateRoulette(onSuccess: @escaping (Bool, String) -> Void) {
var items = [RouletteItem]()
for option in options {
if option.title.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty {
isLoading = false
errorMessage = "옵션은 빈칸일 수 없습니다."
isShowErrorPopup = true
return
if let percentage = Float(option.percentage) {
items.append(RouletteItem(title: option.title, percentage: percentage))
}
items.append(RouletteItem(title: option.title, weight: option.weight))
}
let selectedRoulette = rouletteList[selectedRoulette!.rawValue]
@@ -259,24 +245,10 @@ final class RouletteSettingsViewModel: ObservableObject {
selectedRouletteTitle = "룰렛 1"
}
var isAllActive = false
rouletteList
.filter {
$0.id != selectedRoulette.id
}
.forEach {
if $0.isActive {
isAllActive = true
}
}
if isActive {
successMessage = "\(selectedRouletteTitle)로 설정하였습니다."
} else if !isAllActive {
successMessage = "\(selectedRouletteTitle)이 비활성화 되었습니다."
successMessage = "\(selectedRouletteTitle)을 활성화 했습니다."
} else {
successMessage = "\(selectedRouletteTitle)설정했습니다."
successMessage = "\(selectedRouletteTitle)비활성화 했습니다."
}
let request = UpdateRouletteRequest(id: rouletteId, can: can, isActive: isActive, items: items)
@@ -337,10 +309,9 @@ final class RouletteSettingsViewModel: ObservableObject {
self.rouletteId = roulette.id
self.isActive = roulette.isActive
let options = roulette.items.map {
RouletteOption(title: $0.title, weight: $0.weight)
RouletteOption(title: $0.title, percentage: String($0.percentage))
}
removeAllAndAddOptions(options: options)
recalculatePercentages()
} else {
self.canText = ""
self.isActive = false