How do I pull entries from an ArrayList at random in Kotlin? - kotlin

This is my first Kotlin project. I am learning as I go and I have reached a roadblock.
I have an ArrayList of questions that I want to pull into that app in a random order. I've tried assigning the .random to the point where the question is assigned (right now it is set to CurrentPosition-1) but that only randomized the question and didn't pull the correct answers along with the questions.
How do I either bundle the answers to the question or is there a better way to get the questions to shuffle in order? I plan on having 50+ questions but only 10 will show each time the test is taken. I don't want the same 10 questions showing each time the user opens the test.
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_quiz_questions)
mQuestionsList=Constants.getQuestions()
setQuestion()
}
private fun setQuestion(){
val question = mQuestionsList!![mCurrentPosition-1]
defaultOptionsView()
if(mCurrentPosition == mQuestionsList!!.size){
submitBtn.text = "Finish"
}else{
submitBtn.text = "Submit"
}
progressBar.progress = mCurrentPosition
tv_progress.text = "$mCurrentPosition" + "/" + progressBar.max
tv_question.text = question!!.question
test_image.setImageResource(question.image)
tvOptionOne.text = question.optionOne
tvOptionTwo.text = question.optionTwo
tvOptionThree.text = question.optionThree
tvOptionFour.text = question.optionFour
}
private fun defaultOptionsView(){
val options = ArrayList<TextView>()
options.add(0, tvOptionOne)
options.add(1, tvOptionTwo)
options.add(2, tvOptionThree)
options.add(3, tvOptionFour)
Here is my Array
object Constants{
const val TOTAL_QUESTIONS: String = "total_questions"
const val CORRECT_ANSWERS: String = "correct_answers"
fun getQuestions(): ArrayList<Question>{
val questionsList = ArrayList<Question>()
val q1 = Question(
R.drawable.questionmark,
1,
"Who is Regional Manager of\n Dunder Mifflin Scranton?",
"Michael",
"Jim",
"Pam",
"Dwight",
1,
)
I appreciate any help at all. Thank you in advance.

list.shuffled().take(10) And make your mQuestionsList property type List instead of ArrayList since you don’t need to modify it after retrieval. You should also probably make it lateinit or initialize it at its declaration site so you won’t have to make the type nullable and have to resort to !!, which is generally a code smell. So I would declare it as var mQuestionsList: List<Question> = emptyList() and whenever you want new values do mQuestionsList = Constants.getQuestions().shuffled().take(10).

Related

Problem passing a variable from one activity to another (Kotlin / Android)

This is driving me nuts.
I am taking a number of variables and passing them in a bundle to the same activity. All of the variables are passing through just fine - except for one. It is extremely odd to me because there are 7 other variables that are being assigned and passed in the same manner with no problems.
I know that the variable is being set to the proper value. The problem appears to be either when the variable is being passed or when it is being received. Or something I have no idea about...
As I said, I am bundling the variables and then calling the same activity, which then receives the variables. There is another activity that is used to bring this one up - and the variable passing has the same problem with the exact same variable.
Here is where I bundle the variables
var intentNext= Intent(this#PositionActivityLeft, PositionActivityLeft::class.java)
val bundle = Bundle()
bundle.putBoolean("confirmChoices", confirmChoices)
bundle.putString("gameType", gameType)
bundle.putInt("smallBlind", smallBlind)
bundle.putInt("bigBlind", bigBlind)
bundle.putInt("buyIn", buyIn)
bundle.putInt("handsPerHour", handsPerHour)
bundle.putString("venue", venue)
bundle.putString("location", location)
bundle.putString("venueType", venueType)
bundle.putInt("numSession", numSession)
bundle.putInt("numSessionHands", numSessionHands)
bundle.putInt("stackSize", stackSize)
bundle.putInt("numVillains", numVillainsCount)
bundle.putString("heroPosition", heroPosition)
bundle.putString("villain1Position", villain1Position)
bundle.putString("villain2Position", villain2Position)
bundle.putString("villain3Position", villain3Position)
bundle.putString("Villain4Position", villain4Position)
bundle.putString("villain5Position", villain5Position)
bundle.putString("villain6Position", villain6Position)
bundle.putString("villain7Position", villain7Position)
bundle.putString("villain8Position", villain8Position)
intentNext.putExtras(bundle)
startActivity(intentNext)
overridePendingTransition(0,0)
and here is where I read them in:
class PositionActivityLeft : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_position_left)
// other variable declarations
val bundle: Bundle? = intent.extras
val confirmChoices = bundle!!.getBoolean("confirmChoices")
val gameType = bundle.getString("gameType")
val smallBlind = bundle.getInt("smallBlind")
val bigBlind = bundle.getInt("bigBlind")
val buyIn = bundle.getInt("buyIn")
val handsPerHour = bundle.getInt("handPerHour")
val venue = bundle.getString("venue")
val location = bundle.getString("location")
val venueType = bundle.getString("venueType")
val numSession = bundle.getInt("numSession")
val numSessionHands = bundle.getInt("numSessionHands")
val stackSize = bundle.getInt("stackSize")
val numVillains = bundle.getInt("numVillains")
var heroPosition = bundle.getString("heroPosition")
var villain1Position = bundle.getString("villain1Position","_")
var villain2Position = bundle.getString("villain2Position","_")
var villain3Position = bundle.getString("villain3Position","_")
var villain4Position = bundle.getString("villain4Position","_")
var villain5Position = bundle.getString("villain5Position","_")
var villain6Position = bundle.getString("villain6Position","_")
var villain7Position = bundle.getString("villain7Position","_")
var villain8Position = bundle.getString("villain8Position","_")
for all of the villainPosition variables, I have a default value ("_"). All of the variables pass the intended value of the variable except for villain4Position - it always goes to the default.
I have some code that shows me that the variable is being set properly prior to bundling and sending. It is the reading that isn't getting through. I have tried changing the variable name, changing the location of the line (moving it up or down) and it's always the same result.
I had originally set up a mutablelistOf for the villainPosition variable which allowed me to do a number of things with much less code, but the 4th variable in the list (index 3) kept having problems. I thought it might have been in how I was iterating things or something, so I went and modified the program to explicitly callout all 8 variables and work with them individually. And the result was exactly the same - the 4th variable is not passing from one activity to another.
The problem is a typo
The value is stored in the bundle using the key (with an uppercase "V").
"Villain4Position"
while (with a lowercase "v") is the key used to retrieve the value from the bundle.
"villain4Position"
To fix this, you should ensure that the bundle key used to retrieve the value matches the one used to put it. Try changing the key used to retrieve the value for
"villain4Position" to "Villain4Position"

Why am I geting a blank when I run this string funtion in Kotlin?

So I was solving a problem that required me to put unique characters in a string without using a data structure.
fun main(){
val s1 = "fhfnfnfjuw"
val s2 = "Osayuki"
val s3 = "Raymond"
val s4 = "Aseosa"
uniqueChar(s1)
}
fun uniqueChar(s: String){
val updatedString = ""
s.forEach {c ->
if (!updatedString.contains(c)){
updatedString.plus(c)
}
}
println(updatedString)
}
And getting this error
I'm not sure what's going on and why I'm getting a blank. I'm sure it's an easy fix, but I can't see it. Any help is appreciated.
updatedString.plus(c) does not change updatedString. It creates a new string, including the character c. Since you don't do anything with that, the new string goes...nowhere.
Instead, you probably wanted updatedString = updatedString.plus(c) -- or something better with StringBuilder, but that's the closest version to your code.

CharBuffer to string?

How to get the string "hi" from the CharBuffer? toString() does not seem to work.
val a = CharBuffer.allocate(10);
a.put('h');
a.put('i');
val b = a.toString();
Variable states after running the code above:
CharBuffer is pretty low-level and really meant for I/O stuff, so it may seem illogical at first. In your example it actually returned a string containing remaining 8 bytes that you didn't set. To make it return your data you need to invoke flip() like this:
val a = CharBuffer.allocate(10);
a.put('h');
a.put('i');
a.flip()
val b = a.toString();
You can find more in the docs of the Buffer
For more typical use cases it is much easier to use StringBuilder:
val a = StringBuilder()
a.append('h')
a.append('i')
val b = a.toString()
Or even use a Kotlin util that wraps StringBuilder:
val b = buildString {
append('h')
append('i')
}

How to use putextra () in Kotin

I want to send data (number) from "edit text section" of Sub-Activity1 (users input a simple number)and receive in another Sub-activity2, and depending on the number I want to show different sets of text. I am a beginner and I am stuck where in Sub-Activity 2 as it returns error for val str where I want to receive and manipulate the number received from Sub-Activity 1 editText.
Sub-Activity 1 :
<Send & Open Sub-Activity2>
getResult.setOnClickListener {
val intent = Intent(this, subactivity::class.java)
val name: String = editTextID.getText().toString()
intent.putExtra(name:"editTextID",value:"7.0")
startActivity(intent)
This returns no error.
Sub-Activity 2: <Receive & Manipulate the text>
class subactivity2 : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_subactivity2)
val str =intent.getStringExtra("editTextID")
when str == 7.0 {
infoTextView.textview.text= "textIwannaShow"
}
}
Franz might be right about you wanting to pass a Double, but since you're passing it as a String and also naming your val str, I'll assume you do want to pass a string (that just happens to represent a number). In which case you need to compare to a string
if (str == "7.0") {
infoTextView.textview.text = "textIwannaShow"
}
or if you do want a when block
when(str) {
"7.0" -> infoTextView.textview.text = "textIwannaShow"
}
If you actually want to work with numbers you'll have to call toDouble() on your string at some point to convert it to one. toDoubleOrNull would be better if you're taking that number from a text input (in case the user doesn't enter a valid number), but you're not actually using the value taken from the EditText
In your Sub-Activity 2, you are receiving a String not an Integer.
So, you should change your code from this
val str =intent.getStringExtra("editTextID")
To this
val str =intent.getIntExtra("editTextID", 0)
Anyway, in the example you are passing 7.0 which is Double, so you probably need this instead of above code
val str =intent.getDoubleExtra("editTextID", 0.0)

Fixing Some Kotlin Syntax

I just finish built a simple android music app with Java, then I convert the java files to Kotlin with Kotlin plugin for Android Studio.
There are some error, in MainActivity.kt
private fun display() {
val mySongs = findSong(Environment.getExternalStorageDirectory())
items = arrayOf(mySongs.size.toString())
for (i in mySongs.indices) {
items[i] = mySongs[i].name.toString().replace(".mp3", "").replace(".wav", "")
}
val adp = ArrayAdapter(this, android.R.layout.simple_list_item_1, items!!)
listView!!.adapter = adp
listView!!.onItemClickListener = AdapterView.OnItemClickListener { adapterView, view, position, l -> startActivity(Intent(applicationContext, PlayerActivity::class.java).putExtra("pos", position).putExtra("songs", mySongs)) }
}
this line : items[i] = mySongs[i].name.toString().replace(".mp3","").replace(".wav", "")
showing an error: Smart cast to 'Array' is a mutable property that could have been changed by this time.
and on the PlayerActivity.kt
val i = intent
val b = i.extras
mySongs = b.getParcelableArrayList<Parcelable>(mySongs.toString())
position = b.getInt("pos", 0)
val u = Uri.parse(mySongs!![position].toString())
mediaPlayer = MediaPlayer.create(applicationContext, u)
the b.getParcelableArrayList<Parcelable>(mySongs.toString()) has a problem says Type mismatch.
Anyone can help me fix this? Thank You
This line
items = arrayOf(mySongs.size.toString())
creates an array of 1 element containing a string with the size of my songs. ex: ["23"]
You could use this instead: arrayOfNulls(mySongs.size)
For the other question:
mySongs = b.getParcelableArrayList<Parcelable>(mySongs.toString())
should return the same type as (I assume that it was the same code than in main activity because they are in 2 differents files and the context of mySongs is not provided)
val mySongs = findSong(Environment.getExternalStorageDirectory())
mySongs will have be the same type as the result of findSong.
Also you should use var instead of val because val are immutable