Рефакторинг, платный боевой пропуск и задания вызова

This commit is contained in:
2025-05-19 17:48:07 +03:00
parent 9f1b7f3513
commit 4e00239a70
4 changed files with 131 additions and 20 deletions

2
.idea/misc.xml generated
View File

@ -4,7 +4,7 @@
<component name="FrameworkDetectionExcludesConfiguration"> <component name="FrameworkDetectionExcludesConfiguration">
<file type="web" url="file://$PROJECT_DIR$" /> <file type="web" url="file://$PROJECT_DIR$" />
</component> </component>
<component name="ProjectRootManager" version="2" languageLevel="JDK_21" default="true" project-jdk-name="21" project-jdk-type="JavaSDK"> <component name="ProjectRootManager" version="2" languageLevel="JDK_23" project-jdk-name="24" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/out" /> <output url="file://$PROJECT_DIR$/out" />
</component> </component>
</project> </project>

2
.idea/vcs.xml generated
View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<project version="4"> <project version="4">
<component name="VcsDirectoryMappings"> <component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$" vcs="Git" /> <mapping directory="" vcs="Git" />
</component> </component>
</project> </project>

View File

@ -4,10 +4,10 @@ import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll import androidx.compose.foundation.verticalScroll
import androidx.compose.material3.MaterialTheme import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.OutlinedTextField
import androidx.compose.material3.Surface import androidx.compose.material3.Surface
import androidx.compose.material3.Text import androidx.compose.material3.Text
import androidx.compose.material3.darkColorScheme import androidx.compose.material3.darkColorScheme
@ -17,18 +17,27 @@ import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.text.SpanStyle
import androidx.compose.ui.text.buildAnnotatedString
import androidx.compose.ui.text.withStyle
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.compose.ui.window.Window import androidx.compose.ui.window.Window
import androidx.compose.ui.window.application import androidx.compose.ui.window.application
import utils.DecimalField
import utils.SliderCard import utils.SliderCard
import utils.SwitchCard
import utils.VSpace import utils.VSpace
import utils.parseInt
import kotlin.math.ceil import kotlin.math.ceil
const val BATTLE_PASS_WEEKS = 13
const val BATTLE_PASS_DAYS = BATTLE_PASS_WEEKS * 7
const val BATTLE_PASS_MAX_LEVEL = 115 const val BATTLE_PASS_MAX_LEVEL = 115
const val DAILY_TASKS_XP = 450 const val DAILY_TASKS_XP = 450
const val WEEKLY_REWARD_XP = 2250 const val WEEKLY_REWARD_XP = 2250
const val WEEKLY_TASKS_XP = 1550 const val WEEKLY_TASKS_XP = 1550
const val CHALLENGE_TASKS_XP = 1000
const val CHALLENGE_TASKS_FREE_NUMBER = 20
const val CHALLENGE_TASKS_PAID_NUMBER = 36
@Composable @Composable
@Preview @Preview
@ -46,18 +55,24 @@ fun App() {
var daysLeft by remember { mutableStateOf(0) } var daysLeft by remember { mutableStateOf(0) }
val weeksLeft = ceil(daysLeft.toFloat() / 7).toInt() val weeksLeft = ceil(daysLeft.toFloat() / 7).toInt()
var currentLevel by remember { mutableStateOf(0) } var currentLevel by remember { mutableStateOf(0) }
var paidBattlePass by remember { mutableStateOf(false) }
var dailyTasksDays by remember { mutableStateOf(0) } var dailyTasksDays by remember { mutableStateOf(0) }
var weeklyRewardWeeks by remember { mutableStateOf(0) } var weeklyRewardWeeks by remember { mutableStateOf(0) }
var weeklyTasksWeeks by remember { mutableStateOf(0) } var weeklyTasksWeeks by remember { mutableStateOf(0) }
var challengeTasksNumber by remember { mutableStateOf(0) }
val xp = ( val xp = (
DAILY_TASKS_XP * dailyTasksDays DAILY_TASKS_XP * dailyTasksDays
+ WEEKLY_REWARD_XP * weeklyRewardWeeks + WEEKLY_REWARD_XP * weeklyRewardWeeks
+ WEEKLY_TASKS_XP * weeklyTasksWeeks + WEEKLY_TASKS_XP * weeklyTasksWeeks
+ challengeTasksNumber / 3 * CHALLENGE_TASKS_XP
) )
Column { Column(
modifier = Modifier
.width(384.dp),
) {
Text( Text(
text = "Исходные значения", text = "Исходные значения",
style = MaterialTheme.typography.headlineSmall, style = MaterialTheme.typography.headlineSmall,
@ -65,32 +80,50 @@ fun App() {
VSpace(16) VSpace(16)
OutlinedTextField( DecimalField(
value = daysLeft.toString(), value = daysLeft,
onValueChange = { onValueChange = {
daysLeft = parseInt(it) daysLeft = it
},
label = {
Text("Дней до завершения события")
}, },
label = "Дней до завершения события",
) )
VSpace(8) VSpace(8)
OutlinedTextField( DecimalField(
value = currentLevel.toString(), value = currentLevel,
onValueChange = { onValueChange = {
currentLevel = parseInt(it) currentLevel = it
}, },
label = { label = "Текущий уровень",
Text("Текущий уровень") )
VSpace(16)
SwitchCard(
checked = paidBattlePass,
onCheckedChange = {
paidBattlePass = it
}, },
label = "Платный боевой пропуск",
description = "Вычисления будут выполняться из расчета, что боевой пропуск уже приобретен",
) )
VSpace(32) VSpace(32)
Text( Text(
text = "${currentLevel + xp.toFloat() / 1000}/$BATTLE_PASS_MAX_LEVEL", text = buildAnnotatedString {
append((currentLevel + xp.toFloat() / 1000).toString())
withStyle(
style = SpanStyle(
fontSize = MaterialTheme.typography.bodyLarge.fontSize,
),
) {
append("/$BATTLE_PASS_MAX_LEVEL")
}
},
style = MaterialTheme.typography.displaySmall, style = MaterialTheme.typography.displaySmall,
) )
} }
@ -143,6 +176,20 @@ fun App() {
}, },
valueRange = 0..weeksLeft, valueRange = 0..weeksLeft,
) )
// TODO: место для заданий недели
SliderCard(
name = "Задания вызова",
value = challengeTasksNumber,
onValueChange = {
challengeTasksNumber = it
},
valueRange = 0..when (paidBattlePass) {
true -> ceil(CHALLENGE_TASKS_PAID_NUMBER.toFloat() / BATTLE_PASS_DAYS * daysLeft).toInt()
false -> ceil(CHALLENGE_TASKS_FREE_NUMBER.toFloat() / BATTLE_PASS_DAYS * daysLeft).toInt()
},
)
} }
} }
} }

View File

@ -1,14 +1,21 @@
package utils package utils
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.width
import androidx.compose.material3.MaterialTheme import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.OutlinedCard import androidx.compose.material3.OutlinedCard
import androidx.compose.material3.OutlinedTextField
import androidx.compose.material3.Slider import androidx.compose.material3.Slider
import androidx.compose.material3.Switch
import androidx.compose.material3.Text import androidx.compose.material3.Text
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
@ -21,9 +28,66 @@ fun VSpace(
) )
} }
fun parseInt( @Composable
value: String, fun DecimalField(
) = value.toIntOrNull() ?: 0 value: Int,
onValueChange: (Int) -> Unit,
label: String,
) {
OutlinedTextField(
value = value.toString(),
onValueChange = {
onValueChange(it.toIntOrNull() ?: 0)
},
modifier = Modifier
.fillMaxWidth(),
label = {
Text(label)
},
)
}
@Composable
fun SwitchCard(
checked: Boolean,
onCheckedChange: (Boolean) -> Unit,
label: String,
description: String? = null,
) {
OutlinedCard {
Column(
modifier = Modifier
.padding(
horizontal = 16.dp,
vertical = 12.dp,
),
verticalArrangement = Arrangement.spacedBy(4.dp),
) {
Row(
modifier = Modifier
.fillMaxWidth(),
horizontalArrangement = Arrangement.SpaceBetween,
verticalAlignment = Alignment.CenterVertically,
) {
Text(
text = label,
style = MaterialTheme.typography.titleLarge,
)
Spacer(Modifier.width(16.dp))
Switch(
checked = checked,
onCheckedChange = onCheckedChange,
)
}
description?.let {
Text(
text = it,
style = MaterialTheme.typography.bodyMedium,
)
}
}
}
}
@Composable @Composable
fun SliderCard( fun SliderCard(