How to set Xaxis and Yaxis using data class using kotlin in MpAndroid bar chart - kotlin

Halo i am trying to create barchart using MPAndroid Library but icant how to use it when i send json from php
echo json_encode($output);
and the output contain 2 data that is hari and total_jual
$rowdata[]=array('hari'=>$row['hari'],
'total_jual'=>$row['total_jual']);
in android studio i am using volley to catch jason
for(i in 0 until arr.length()){
val obj = arr.getJSONObject(i)
dataListPenjualan.add(
ClassPenjualan(
obj.getString("hari").toString(),
obj.getString("total_jual").toString()
)
)
val entries = ArrayList<BarEntry>()
val barDataSet = BarDataSet(entries, "Cells")
val labels = ArrayList<String>()
labels.add(dataListPenjualan[i].hari)
//barDataSet.setColors(ColorTemplate.COLORFUL_COLORS)
barDataSet.color = resources.getColor(R.color.black)
chartPemasukan.animateY(5000)
}
the data i catch using volley i send it into class
this is my class
data class ClassPenjualan (val hari:String,
val totalPenjualan:String)
how can i create barchart using data i catch from php. I already try to search but many explanation is in java.
this is what i try
val entries = ArrayList<BarEntry>()
entries.add(BarEntry(dataListPenjualan[i].hari.toFloat(), i))
val barDataSet = BarDataSet(entries, "Cells")
val labels = ArrayList<String>()
labels.add(dataListPenjualan[i].hari)
val data = BarData(labels, barDataSet)
chartPemasukan.data = data // set the data and list of lables into chart
chartPemasukan.setDescription("Set Bar Chart Description") // set the description
//barDataSet.setColors(ColorTemplate.COLORFUL_COLORS)
barDataSet.color = resources.getColor(R.color.black)
chartPemasukan.animateY(5000)

Your code entries.add(BarEntry(dataListPenjualan[i].hari.toFloat(), i)) is wrong.
just try entries.add(BarEntry(i,dataListPenjualan[i].hari.toFloat()))
below code is my demo
val values = ArrayList<BarEntry>()
var i = 0
while (i < xValueCount) {
val yValue = (Math.random() * (100)).toFloat()
values.add(BarEntry(i.toFloat(), yValue))
i++
}
val set1: BarDataSet
if (chart.data != null &&
chart.data.dataSetCount > 0) {
set1 = chart.data.getDataSetByIndex(0) as BarDataSet
set1.values = values
chart.data.notifyDataChanged()
chart.notifyDataSetChanged()
} else {
set1 = BarDataSet(values, "speed")
//绘制图标
set1.setDrawIcons(false)
//绘制数值
set1.setDrawValues(false)
set1.color = ContextCompat.getColor(mContext, getBarHighColorByDataType(false))
set1.highLightColor = ContextCompat.getColor(mContext, getBarHighColorByDataType(true))
set1.highLightAlpha = 255
val dataSets = ArrayList<IBarDataSet>()
dataSets.add(set1)
val data = BarData(dataSets)
data.setValueTextSize(10f)
//barWith = 柱宽度/(柱宽度+旁边一处空白宽度)
data.barWidth = when (dataType) {
0 -> 0.37f
1 -> 0.52f
2 -> 0.3f
else -> 0.43f
}
chart.data = data
}

Related

MPhiljay Barchart in android

In Barchart show x values from column belongs to one label more than 2 two but should be one.
viewModel.reportMounthData.observe(this, Observer { reportModelList->
val barChart = binding.idBarChartMounth
barChart.setScaleEnabled(false)
val entries: ArrayList<BarEntry> = ArrayList()
var i=0
reportModelList.forEach { reportModel->
entries.add(BarEntry(reportModel.YigilganBonus.toFloat(), i))
i++
}
val bardataset = BarDataSet(entries, "Oylik maoshlar miqdori")
val labels = ArrayList<String>()
reportModelList.sortedBy { it.oy }.forEach { reportModel ->
labels.add(mounthSalary(reportModel.oy))
}
val data = BarData(labels, bardataset)
barChart.data = data // set the data and list of labels into chart
barChart.setDescription("\uD83D\uDEE0 Oylik maosh statistikasi") // set the description
// bardataset.setColors(ColorTemplate.COLORFUL_COLORS)
barChart.animateY(2500)
})
enter image description here
it works perfectly until the values ​​reach 6. If there are more than 6, a defect may occur naturally. they said that the main reason for this is that it will not fit on the screen

Merge properties of a list to another based on properties objects

I got 2 lists with x objects inside , for example:
data class Model(
var token: String = "",
var id: String = "",
var name: String = "",
var image: Int = 0,
)
array is initialized and filled, the other list has x objects also that contains the objects of the first list but with different values in their properties!
what I want to do is to change the properties of the first array by the second one if they got the same object.name
var arr1 = ArrayList<Model>() // locale
var arr2 = ArrayList<Model>() // from db
the first array I got for example
[Model(name = "David", token = "" , image = 0)]
the second array I got
[Model(name = "David", token = "1asd5asdd851", image = 1)]
How do I make the first array take the missing token?
I tried with .filter{} and with .map{}. groupBy {} for hours because Name is the only properties that are the same but I'm more and more confused.
We can first group the second array by name using associateBy() and then iterate over first array and reassign properties:
val arr2ByName = arr2.associateBy { it.name }
arr1.forEach { item1 ->
arr2ByName[item1.name]?.let { item2 ->
item1.token = item2.token
item1.image = item2.image
}
}
Alternatively, if you don't need to modify items in arr1, but create another array and you can use items from both arr1 and arr2, then it will be much easier:
val arr3 = arr1.map { arr2ByName[it.name] ?: it }
One possible way would be to use fold() as follows:
fun main(args: Array<String>) {
val arr1 = listOf(Model(name = "David", token = "" , image = 0))
val arr2 = listOf(Model(name = "David", token = "1asd5asdd851", image = 1))
val mergedModels = arr2.fold(arr1) { localModels, dbModel ->
localModels.map { localModel ->
if (localModel.name == dbModel.name) localModel.copy(token = dbModel.token, image = dbModel.image)
else localModel
}
}
println(mergedModels)
}
If you want to reuse arr1 variable then you can do the following (but I would still use the previous option):
fun main(args: Array<String>) {
var arr1 = listOf(Model(name = "David", token = "" , image = 0))
val arr2 = listOf(Model(name = "David", token = "1asd5asdd851", image = 1))
arr1 = arr2.fold(arr1) { localModels, dbModel ->
localModels.map { localModel ->
if (localModel.name == dbModel.name) localModel.copy(token = dbModel.token, image = dbModel.image)
else localModel
}
}
println(arr1)
}

Read a sequence of numbers of undefined size & print the largest number & position of its first occurrence

I need to read a sequence of numbers of undefined size & prints the largest number & the position of its first occurrence
Can anyone help with this code:
import java.util.Scanner
fun main() {
val scan = Scanner(System.`in`)
val num = scan.nextInt()
var max = Int.MIN_VALUE
var pos = 0
var i = 1
do {
if (max < num) {
max = num
pos = i
}
i++
} while (scan.hasNext())
print("$max $pos")
}
You just need to read a new number in each iteration:
import java.util.Scanner
fun main() {
val scan = Scanner(System.`in`)
var max = Int.MIN_VALUE
var pos = 0
var i = 1
while (scan.hasNext()) {
// Read a new number here
val num = scan.nextInt()
if (max < num) {
max = num
pos = i
}
i++
}
print("$max $pos")
}
My solution to this task
This is a simple task, it can be solved in a simple way without using a “java.util.Scanner”. You just need to read a new number in each iteration.
fun main() {
var pos = 0
var max = 0
var count = 1
while (true) {
val input = readlnOrNull()
if (input == null) break
val num = input.toInt()
if (pos == 0 || num > max) {
max = num
pos = count
}
count++
}
print("$max $pos")
}

NoSuchElementException java.lang.Scanner

I have no idea what the error is, I am having a hard time adapting to this language, any help thank you very much.
Error:
Exception in thread "main" java.util.NoSuchElementException
at java.base/java.util.Scanner.throwFor(Scanner.java:937)
at java.base/java.util.Scanner.next(Scanner.java:1594)
at java.base/java.util.Scanner.nextInt(Scanner.java:2258)
at java.base/java.util.Scanner.nextInt(Scanner.java:2212)
at Packing.<init>(Packing.kt:100)
at PackingKt.main(Packing.kt:7)
at PackingKt.main(Packing.kt)
My code:
import java.io.InputStream
import java.util.Scanner
fun main() {
val input = Scanner(InputStream.nullInputStream())
val packing1 = Packing(input)
val packing2 = Packing(input)
val packing3 = Packing(input)
var total = 0
var min = 0
val combinations = ArrayList<String>()
for(a in 1..3){
for(b in 1..3){
for(c in 1..3){
//here is a piece of code
}
}
combinations.sort()
println("${combinations.get(0)} $min")
}
}
class Packing {
var brownBottles = 0
var greenBottles = 0
var clearBottles = 0
constructor (input : Scanner){
brownBottles = input.nextInt() //this is the line 100
greenBottles = input.nextInt()
clearBottles = input.nextInt()
}
}
The idea is to enter values by console that initialize the variables of my objects.
I would just use
val input = Scanner(System.`in`)
If you enter 9 integers in the console the initialization of the Packing objects should work.
The nullInputStream() makes no sense to me. It's not possible to read from the console with that.
The combinations list is empty so it throws an exception accessing it here
println("${combinations.get(0)} $min")

Kotlin - The caracter literal does not conform expect type Int

I'm struggling with types with my program, I've been asked to do it in JS first and it worked fine but now I can't achieve the result.
Do you think I should make another 'algorithm' ? In advance, thank you for your time.
fun main(){
// the idea is to put numbers in a box
// that cant be larger than 10
val data = "12493419133"
var result = data[0]
var currentBox = Character.getNumericValue(data[0])
var i = 1
while(i < data.length){
val currentArticle = Character.getNumericValue(data[i])
currentBox += currentArticle
println(currentBox)
if(currentBox <= 10){
result += Character.getNumericValue(currentArticle)
}else{
result += '/'
//var resultChar = result.toChar()
// result += '/'
currentBox = Character.getNumericValue(currentArticle)
result += currentArticle
}
i++
}
print(result) //should print 124/9/341/91/33
}
The result is actually of a Char type, and the overload operator function + only accepts Int to increment ASCII value to get new Char.
public operator fun plus(other: Int): Char
In idomatic Kotlin way, you can solve your problem:
fun main() {
val data = "12493419133"
var counter = 0
val result = data.asSequence()
.map(Character::getNumericValue)
.map { c ->
counter += c
if (counter <= 10) c.toString() else "/$c".also{ counter = c }
}
.joinToString("") // terminal operation, will trigger the map functions
println(result)
}
Edit: If the data is too large, you may want to use StringBuilder because it doesn't create string every single time the character is iterated, and instead of using a counter of yourself you can use list.fold()
fun main() {
val data = "12493419133"
val sb = StringBuilder()
data.fold(0) { acc, c ->
val num = Character.getNumericValue(c)
val count = num + acc
val ret = if (count > 10) num.also { sb.append('/') } else count
ret.also { sb.append(c) } // `ret` returned to ^fold, next time will be passed as acc
}
println(sb.toString())
}
If you want a result in List<Char> type:
val data = "12493419133"
val result = mutableListOf<Char>()
var sum = 0
data.asSequence().forEach {
val v = Character.getNumericValue(it)
sum += v
if (sum > 10) {
result.add('/')
sum = v
}
result.add(it)
}
println(result.joinToString(""))