@@ -5,8 +5,12 @@ import android.content.DialogInterface
55import android.os.Bundle
66import android.view.LayoutInflater
77import android.view.View
8+ import android.view.animation.AnimationUtils
89import androidx.appcompat.app.AppCompatDialogFragment
10+ import androidx.core.widget.doAfterTextChanged
911import com.google.android.material.dialog.MaterialAlertDialogBuilder
12+ import com.google.android.material.textfield.TextInputEditText
13+ import dev.lucasnlm.antimine.R
1014import dev.lucasnlm.antimine.core.models.Difficulty
1115import dev.lucasnlm.antimine.custom.viewmodel.CreateGameViewModel
1216import dev.lucasnlm.antimine.custom.viewmodel.CustomEvent
@@ -47,12 +51,68 @@ class CustomLevelDialogFragment : AppCompatDialogFragment() {
4751 mapHeight.setText(state.height.toString())
4852 mapMines.setText(state.mines.toString())
4953 seed.setText(" " )
54+
55+ mapWidth.checkLimit(MIN_WIDTH , MAX_WIDTH )
56+ mapHeight.checkLimit(MIN_HEIGHT , MAX_HEIGHT )
57+ mapMines.checkProportionOnChange()
5058 }
5159 }
5260
5361 return binding.root
5462 }
5563
64+ private fun TextInputEditText.checkProportion () {
65+ val width = binding.mapWidth.text.toString().toIntOrNull()
66+ val height = binding.mapHeight.text.toString().toIntOrNull()
67+ val current = text.toString().toIntOrNull()
68+ error =
69+ if (current != null && width != null && height != null ) {
70+ val minMines = (width * height * 0.5 - MIN_SAFE_AREA ).toInt().coerceAtLeast(1 )
71+ if (current <= minMines) {
72+ null
73+ } else {
74+ val maxProportion = width * height * 0.75
75+ if (current >= maxProportion) {
76+ getString(i18n.string.proportion_too_high)
77+ } else {
78+ null
79+ }
80+ }
81+ } else {
82+ null
83+ }
84+ }
85+
86+ private fun TextInputEditText.checkProportionOnChange () {
87+ doAfterTextChanged {
88+ checkProportion()
89+ }
90+ }
91+
92+ private fun TextInputEditText.checkLimit (
93+ min : Int ,
94+ max : Int ,
95+ ) {
96+ doAfterTextChanged {
97+ if (it?.isNotBlank() == true ) {
98+ val current = text.toString().toIntOrNull()
99+ if (current != null ) {
100+ if (current > max) {
101+ error = getString(i18n.string.value_limit_max, max)
102+ } else if (current < min) {
103+ error = getString(i18n.string.value_limit_min, min)
104+ }
105+ } else {
106+ error = null
107+ }
108+ } else {
109+ error = null
110+ }
111+
112+ binding.mapMines.checkProportion()
113+ }
114+ }
115+
56116 override fun onCreateDialog (savedInstanceState : Bundle ? ): Dialog {
57117 return MaterialAlertDialogBuilder (requireContext()).apply {
58118 setTitle(i18n.string.new_game)
@@ -67,6 +127,56 @@ class CustomLevelDialogFragment : AppCompatDialogFragment() {
67127 }.create()
68128 }
69129
130+ private fun checkLimitFeedbacks (): Boolean {
131+ val wantedWidth = binding.mapWidth.text.toString().toIntOrNull()
132+ var allValid = true
133+ if (wantedWidth == null ) {
134+ binding.mapWidth.startAnimation(AnimationUtils .loadAnimation(context, R .anim.fast_shake))
135+ allValid = false
136+ } else if (wantedWidth >= MAX_WIDTH ) {
137+ binding.mapWidth.setText(MAX_WIDTH .toString())
138+ binding.mapWidth.startAnimation(AnimationUtils .loadAnimation(context, R .anim.fast_shake))
139+ allValid = false
140+ } else if (wantedWidth <= MIN_WIDTH ) {
141+ binding.mapWidth.setText(MIN_WIDTH .toString())
142+ binding.mapWidth.startAnimation(AnimationUtils .loadAnimation(context, R .anim.fast_shake))
143+ allValid = false
144+ }
145+
146+ val wantedHeight = binding.mapHeight.text.toString().toIntOrNull()
147+ if (wantedHeight == null ) {
148+ binding.mapHeight.startAnimation(AnimationUtils .loadAnimation(context, R .anim.fast_shake))
149+ allValid = false
150+ } else if (wantedHeight >= MAX_HEIGHT ) {
151+ binding.mapHeight.setText(MAX_HEIGHT .toString())
152+ binding.mapHeight.startAnimation(AnimationUtils .loadAnimation(context, R .anim.fast_shake))
153+ allValid = false
154+ } else if (wantedHeight <= MIN_HEIGHT ) {
155+ binding.mapHeight.setText(MIN_HEIGHT .toString())
156+ binding.mapHeight.startAnimation(AnimationUtils .loadAnimation(context, R .anim.fast_shake))
157+ allValid = false
158+ }
159+
160+ if (allValid && wantedWidth != null && wantedHeight != null ) {
161+ val wantedMines = binding.mapMines.text.toString().toIntOrNull()
162+ val maxMines = wantedWidth * wantedHeight - MIN_SAFE_AREA
163+ if (wantedMines == null ) {
164+ binding.mapMines.startAnimation(AnimationUtils .loadAnimation(context, R .anim.fast_shake))
165+ allValid = false
166+ } else if (wantedMines >= maxMines) {
167+ binding.mapMines.setText((wantedWidth * wantedHeight - MIN_SAFE_AREA ).toString())
168+ binding.mapMines.startAnimation(AnimationUtils .loadAnimation(context, R .anim.fast_shake))
169+ allValid = false
170+ } else if (wantedMines <= MIN_MINES ) {
171+ binding.mapMines.setText(MIN_MINES .toString())
172+ binding.mapMines.startAnimation(AnimationUtils .loadAnimation(context, R .anim.fast_shake))
173+ allValid = false
174+ }
175+ }
176+
177+ return allValid
178+ }
179+
70180 override fun onDismiss (dialog : DialogInterface ) {
71181 if (activity is DialogInterface .OnDismissListener ) {
72182 (activity as DialogInterface .OnDismissListener ).onDismiss(dialog)
@@ -79,8 +189,8 @@ class CustomLevelDialogFragment : AppCompatDialogFragment() {
79189 const val MIN_HEIGHT = 5
80190 const val MIN_MINES = 3
81191 const val MIN_SAFE_AREA = 9
82- const val MAX_WIDTH = 50
83- const val MAX_HEIGHT = 50
192+ const val MAX_WIDTH = 100
193+ const val MAX_HEIGHT = 100
84194
85195 private fun filterInput (
86196 target : String ,
0 commit comments