I am trying to get hotels to the length of the route, using REST request
The request has a parameter compressedRoute, but the conversion algorithm in Java script language.
Is there such an algorithm in Java or Kotlin? Maybe such a request is in the SDK, but I do not see it?
points to take from route.routeElements.geometry.allPoints?
I managed to compress the route. The problem was in the error of the example on JS.
First you need to go through to limit the number of points in the route, I set 120. If you do more, 414 errors may occur
fun execute(route: Route, categoryName: String, radiusInMeters: Int): Single<List<ItemPlaceByCorridor>> {
val allPointList = route.routeGeometry
val pointList = ArrayList<GeoCoordinate>()
for ((index, elem) in allPointList.withIndex()) {
if (index % (allPointList.size / POINTS_IN_ROUTE) == 0 || (index == 0) || (index == allPointList.lastIndex)) {
pointList.add(elem)
}
}
var routeStr = hereEncodePolyline(pointList)
routeStr += ";w=$radiusInMeters"
return mHereMapsApi.getPlacesByCorridor(categoryName, routeStr)
.map { response -> response.results.listItems }
}
Algorithm transferred from JS to Kotlin
private fun hereEncodePolyline(positions: List<GeoCoordinate>): String {
var lastLat = 0.0
var lastLon = 0.0
var result = ""
for (i in 1..positions.lastIndex) {
val elem = positions[i]
result += hereEncodeFloat(elem.latitude - lastLat)
result += hereEncodeFloat(elem.longitude - lastLon)
lastLat = elem.latitude
lastLon = elem.longitude
}
return result
}
private fun hereEncodeFloat(value: Double): String {
val chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_"
var result = ""
// convert to fixed point
var fixedPoint = Math.round(value * 100000)
// make room on the lowest bit
fixedPoint = fixedPoint shl (1)
// flip bits of negative numbers and ensure that the last bit is set
// (should actually always be the case, but for readability it is ok to do it explicitly)
if (fixedPoint < 0) {
fixedPoint = (fixedPoint.inv()) or 0x01
}
// var-length encode the number in chunks of 5 bits starting with the least significant
// to the most significant
while (fixedPoint > 0x1F) {
result += (chars[((fixedPoint and 0x1F) or 0x20).toInt()]).toString()
fixedPoint = fixedPoint shr (5)
}
result += (chars[fixedPoint.toInt()])
return result
}
Related
I made a stat calculator and I need to store 10 user inputted values to be stored in an array where I can get the average and lowest number. How do I go about getting the values on the array to get the maximum and minimum values?
var values = ArrayList<Int>()
var count = 0
var arrCount = 0
addButt.setOnClickListener {
values.add(statNum.text.toString().toInt())
count++
arrCount++
var i = 0
statNum.setText("")
statArray.text = ""
for (i in 0..arrCount - 1) {
statArray.text = statArray.text as String + values[i] + ","
}
}
avgBut.setOnClickListener{
val statArray = doubleArrayOf(4.0, 7.0, 11.0, 12.0, 9.0)
var sum = 0.0
for (num in statArray) {
sum += num
}
val average = sum / statArray.size
finalAnswer.text = average.toString()
}
minmaxBut.setOnClickListener{
fun findMin(list: List<Int?>): Int? {
return list.sortedWith(compareBy { it }).first()
}
fun findMax(list: List<Int?>): Int? {
return list.sortedWith(compareBy { it }).last()
}
fun main() {
val list = listOf(10, 4, 2, 7, 6, 9)
val min = findMin(list)
finalAnswer.text = "Min Vale = $min"
val max = findMax(list)
println(max) // 10
}
It's very easy to get min, max and average number in the arraylist. I did not understand your code clearly but i will share how you can do these. After you may use that on your array:
val list = arrayListOf<Int>(1,2,3,4,5,6,7,8,9,10)
Log.e("min", list.min().toString())
Log.e("max", list.max().toString())
Log.e("average", list.average().toString())
This will give you below output in logcat:
E/min: 1
E/max: 10
E/average: 5.5
I'm creating a function that rounds large numbers over 1,000 and then returns a string of that rounded number. For example, "2374293" would return as "2.37m"
However, I dont want any extra zeros at the end of decimals like "25.00" or "100.50".
For Example:
What I want:
Input -> Output
"11000" -> "11k"
"11400" -> "11.4k"
What I get:
Input -> Output
"11000" -> "11.00k"
"11400" -> "11.40k"
How would I remove these zeros and decimal point(if it's a whole number) when needed?
Here is my code currently:
private fun roundBigNumb(numb: Long): String {
val newNumb = numb.toDouble()
return when {
numb in 1000..999994 -> {
BigDecimal(newNumb/1000).setScale(2, RoundingMode.HALF_EVEN).toString()+"k"
}
numb in 999995..999999 -> {
"999.99k"
}
numb in 1000000..999994999 -> {
BigDecimal(newNumb/1000000).setScale(2, RoundingMode.HALF_EVEN).toString()+"m"
}
numb in 999995000..999999999 -> {
"999.99m"
}
numb in 1000000000..999994999999 -> {
BigDecimal(newNumb/1000000000).setScale(2, RoundingMode.HALF_EVEN).toString()+"b"
}
numb in 999995000000..999999999999 -> {
"999.99b"
}
numb in 1000000000000..999994999999999 -> {
BigDecimal(newNumb/1000000000000).setScale(2, RoundingMode.HALF_EVEN).toString()+"t"
}
numb in 999995000000000..999999999999999 -> {
"999.99t"
}
numb >= 1000000000000000 -> "∞"
else -> numb.toString()
}
}
import java.math.BigDecimal
import java.math.RoundingMode.HALF_EVEN
fun roundBigNumber(number: Long): String {
fun calc(divisor: Long) = BigDecimal(number.toDouble() / divisor)
.setScale(2, HALF_EVEN)
.toString()
.dropLastWhile { it == '0' }
.dropLastWhile { it == '.' }
return when {
number in 1000..999994 -> calc(1000) + "k"
number in 999995..999999 -> "999.99k"
number in 1000000..999994999 -> calc(1000000) + "m"
number in 999995000..999999999 -> "999.99m"
number in 1000000000..999994999999 -> calc(1000000000) + "b"
number in 999995000000..999999999999 -> "999.99b"
number in 1000000000000..999994999999999 -> calc(1000000000000) + "t"
number in 999995000000000..999999999999999 -> "999.99t"
number >= 1000000000000000 -> "∞"
else -> number.toString()
}
}
Once you have converted the number to a string with up to 2 decimal places (as you are doing), you can use dropLastWhile to drop trailing zeros and decimal places.
Here is an example
fun prettyFormat(input: Double): String {
if( input == 0.0 ) return "0"
val prefix = if( input < 0 ) "-" else ""
val num = abs(input)
// figure out what group of suffixes we are in and scale the number
val pow = floor(log10(num)/3).roundToInt()
val base = num / 10.0.pow(pow * 3)
// Using consistent rounding behavior, always rounding down since you want
// 999999999 to show as 999.99M and not 1B
val roundedDown = floor(base*100)/100.0
// Convert the number to a string with up to 2 decimal places
var baseStr = BigDecimal(roundedDown).setScale(2, RoundingMode.HALF_EVEN).toString()
// Drop trailing zeros, then drop any trailing '.' if present
baseStr = baseStr.dropLastWhile { it == '0' }.dropLastWhile { it == '.' }
val suffixes = listOf("","k","M","B","T")
return when {
pow < suffixes.size -> "$prefix$baseStr${suffixes[pow]}"
else -> "${prefix}infty"
}
}
This produces
11411.0 = 11.41k
11000.0 = 11k
9.99996E8 = 999.99M
12.4 = 12.4
0.0 = 0
-11400.0 = -11.4k
If you don't care about zero or negative numbers it can be simplified a bit.
I've a byte. What I want to do is access bit position to retrieve boolean (0 or 1). How can I do that in Kotlin?
fun getBit(b: Byte, bitNumber: Int): Boolean {
val shift: Int = 7 - bitNumber
val bitMask = (1 shl shift).toByte()
val masked = (b and bitMask)
return masked.toInt() != 0
}
This for some reason return incorrect value of false when it should return true
Your algorithm seems OK, I think you just made an off by one error (although you didn't say if you are counting from 0 or 1). If I change it to
val shift: Int = 8 - bitNumber
It seems to work fine for me:
fun getBit(b: Byte, bitNumber: Int): Boolean {
require(bitNumber in 1..8)
val shift: Int = 8 - bitNumber
val bitMask = (1 shl shift).toByte()
val masked = (b and bitMask)
return masked.toInt() != 0
}
fun main() {
println(getBit(0b10000000.toByte(), 1))
println(getBit(0b10000000.toByte(), 2))
println(getBit(0b01000000, 2))
}
Output:
true
false
true
Note: you can avoid the experimental Byte.and() by using Int.and() instead:
val bitMask = (0b1 shl shift)
val masked = (b.toInt() and bitMask)
return masked != 0
I have an encryption key and i want to convert this given string into a byte array, in order to do file decryption process.
Exemple :
val string = "0123456789012345678901234567890123456789012345678901234567890123"
// what i want to have is something like this :
val result = byteArrayOf(0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x00,0x01,0x02,0x03)
voila :
private fun hexStringToByteArray(s: String): ByteArray? {
val len = s.length
val data = ByteArray(len / 2)
var i = 0
while (i < len) {
data[i / 2] = ((Character.digit(s[i], 16) shl 4) +
Character.digit(s[i + 1], 16)).toByte()
i += 2
}
return data
}
from here https://stackoverflow.com/a/18714790/5015227
I try to do an android application and I'm trying to use Google map Direction API to draw line between 2 marker and when I try to decode the polyline point in the JSON I have from goole server I have a bunch of marker set near to the position 0.0,0.0 like in my screenshoot bellow
my polyline decode function is
private fun decodePoly(polylineArrayList: ArrayList<String>): List<LatLng> {
val poly = ArrayList<LatLng>()
var index = 0
for (i in 0 until polylineArrayList.size-1) {
val encoded = polylineArrayList[i]
val len = encoded.length
var lat = 0
var lng = 0
while (index < len -1) {
var b: Int
var shift = 0
var result = 0
do {
b = encoded[index++].toInt() - 63
result = result or (b and 0x1f shl shift)
shift += 5
} while (b >= 0x20 )
val dlat = if (result and 1 != 0) (result shr 1).inv() else result shr 1
lat += dlat
shift = 0
result = 0
do {
b = encoded[index++].toInt() - 63
result = result or (b and 0x1f shl shift)
shift += 5
} while (b >= 0x20 )
val dlng = if (result and 1 != 0) (result shr 1).inv() else result shr 1
lng += dlng
val p = LatLng(lat.toDouble() / 1E5,
lng.toDouble() / 1E5)
poly.add(p)
}
}
return poly
}
here is the code where i draw the line (i do in in the on success from my asynck task
private val options = PolylineOptions()
private val latLongB = LatLngBounds.Builder()
override fun onSuccess(googleDirectionData: GoogleDirectionData?) {
val polylineArrayList = ArrayList<String>()
for (route in googleDirectionData?.routes!!) {
for (leg in route.legs) {
for (step in leg.steps)
polylineArrayList.add(step.polyline.points)
}
}
val polypts = decodePoly(polylineArrayList)
for (point in polypts) {
options.add(point)
latLongB.include(point)
}
val caisseMarker = LatLng(caisse.wsg84[0], caisse.wsg84[1])
options.add(caisseMarker)
latLongB.include(caisseMarker)
val bounds = latLongB.build()
// add polyline to the map
map.addPolyline(options)
// show map with route centered
map.moveCamera(CameraUpdateFactory.newLatLngBounds(bounds, 100))
}
bunch of marker near 0.0,0.0
did someone know how to fix this in order
to no longer have a marker to position 0.0,0.0?
If you want boost your performance, you should use pre built libraries.
Have a look at
https://github.com/jd-alexander/Google-Directions-Android
https://github.com/bkhezry/MapDrawingTools
https://github.com/akexorcist/Android-GoogleDirectionLibrary
Simple syntax
GoogleDirection.withServerKey("YOUR_SERVER_API_KEY")
.from(new LatLng(41.8838111, -87.6657851))
.and(new LatLng(41.8766061, -87.6556908))
.and(new LatLng(41.8909056, -87.6467561))
.to(new LatLng(41.9007082, -87.6488802))
.transportMode(TransportMode.DRIVING)
.execute(new DirectionCallback() {
#Override
public void onDirectionSuccess(Direction direction, String rawBody) {
if(direction.isOK()) {
// Do something
} else {
// Do something
}
}
#Override
public void onDirectionFailure(Throwable t) {
// Do something
}
});
yes thanx but I'm not realy in search of performance it's just a project for an internship in order to learn kotlin so I don't realy need to boost performance