Skip to content

Instantly share code, notes, and snippets.

View kiwiandroiddev's full-sized avatar

Matt Clarke kiwiandroiddev

  • Auckland, New Zealand
View GitHub Profile
@kiwiandroiddev
kiwiandroiddev / RxScreenCaptureSource.kt
Created December 15, 2020 00:33
Returns an Observable stream of screen grabs using java.awt.Robot. Uses multiple threads to get a somewhat reasonable FPS as per https://github.com/bahusvel/JavaScreenCapture
fun getScreenCaptureSource(
screenRectangle: Rectangle,
numThreads: Int = 6,
fpsPerThread: Int = 8,
robot: Robot = Robot()
): Observable<BufferedImage> {
val periodPerThreadMs: Long = 1000 / fpsPerThread.toLong()
val perThreadOffsetMs: Long = periodPerThreadMs / numThreads
val sources = (0 until numThreads).map { i ->
@kiwiandroiddev
kiwiandroiddev / normalize.kt
Created October 15, 2020 04:28
Kotlin function to remove duplicate consecutive elements in a list, up to maxN duplicate consecutive elements
/**
* Removes duplicate consecutive elements in a list, up to maxN duplicate consecutive elements
* per group.
* Ex. where maxN = 2:
* [0, 0, 1, 2, 2, 4, 4, 4, 4] => [0, 1, 2, 4, 4]
*/
fun <T> List<T>.normalize(maxN: Int): List<T> {
var nextIndexToConsider = 0
return windowed(size = maxN, step = 1, partialWindows = true)
@kiwiandroiddev
kiwiandroiddev / loadOpenCvImage.kt
Created April 5, 2020 01:46
Decode an Android test resource image as an OpenCV Mat
/**
* Uses OpenCV to decode an image that is an android test resource i.e.
* a file from `src/androidTest/resources`.
* Note that the resulting Mat will be empty if there was a problem loading the file.
*/
private fun loadOpenCvImage(testResourceFilename: String): Mat {
val bytes: ByteArray = javaClass.classLoader!!.getResource(testResourceFilename).readBytes()
val matOfByte = MatOfByte().apply { fromList(bytes.toList()) }
return Imgcodecs.imdecode(matOfByte, CV_LOAD_IMAGE_COLOR)
}
@kiwiandroiddev
kiwiandroiddev / BigEndianBits.kt
Created February 28, 2020 22:56
Kotlin function to convert a list of bits (booleans) with big-endian ordering to an integer
/**
* Converts a list of bits (booleans) with big-endian ordering to its corresponding
* integer.
*/
fun List<Boolean>.bigEndianBitsToInt(): Int {
return reversed().foldIndexed(initial = 0) { bitNo: Int, output: Int, bit: Boolean ->
output or (bit.toInt() shl bitNo)
}
}
@kiwiandroiddev
kiwiandroiddev / CartesianProduct.kt
Created August 23, 2019 01:58
Kotlin function to return the cartesian product of two collections
/**
* E.g.
* cartesianProduct(listOf(1, 2, 3), listOf(true, false)) returns
* [(1, true), (1, false), (2, true), (2, false), (3, true), (3, false)]
*/
fun <T, U> cartesianProduct(c1: Collection<T>, c2: Collection<U>): List<Pair<T, U>> {
return c1.flatMap { lhsElem -> c2.map { rhsElem -> lhsElem to rhsElem } }
}
@kiwiandroiddev
kiwiandroiddev / StringFindAllInstances.kt
Created July 11, 2019 00:16
Kotlin extension function on String to find all instances of given substring within. Results are in the form of a list of index pairs.
/**
* Find all instances of given substring in this string.
* Results are in the form of a list of index pairs (start and end index of that particular match).
*/
fun String.findAllInstancesOf(
subString: String,
startIndex: Int = 0
): List<Pair<Int, Int>> {
val index = this.indexOf(subString, startIndex)
if (index == -1) return emptyList()
@kiwiandroiddev
kiwiandroiddev / rxFilterWithBiPredicate.kt
Created February 4, 2019 06:15
Allows a stream to be filtered with a predicate that evaluates the latest and previous items.
/**
* Filters items emitted by an observable by only emitting those that satisfy the specified
* predicate based on the latest and previous items emitted.
* Note that this will always filter out the first item of the stream since in this case there
* is as of yet no previous item to compare it to.
*
* @param bipredicate
* a function that evaluates the current and previous item emitted by the source ObservableSource, returning {@code true}
* if it passes the filter
* @return an Observable that emits only those items emitted by the source ObservableSource that the filter
@kiwiandroiddev
kiwiandroiddev / rxThrottleMatchingItems.kt
Last active October 19, 2018 07:44
Selectively throttles items in an observable stream
fun <T> Observable<T>.throttleMatchingItems(
windowDuration: Long,
unit: TimeUnit,
predicate: (T) -> Boolean
): Observable<T> {
return this.compose { stream ->
val throttledItems = stream
.filter(predicate)
.throttleFirst(windowDuration, unit)
val allOtherItems = stream.filter { !predicate(it) }
@kiwiandroiddev
kiwiandroiddev / RxWebSocketAdapter.kt
Created October 12, 2018 06:52
Converts OkHttp's callback interface for WebSockets into an RxJava Observable of events
import io.reactivex.Observable
import okhttp3.*
import okio.ByteString
fun OkHttpClient.newWebSocketObservable(serverUrl: String): Observable<WebSocketEvent> {
val request = Request.Builder().url(serverUrl).build()
return newWebSocketObservable(request)
}
fun OkHttpClient.newWebSocketObservable(request: Request): Observable<WebSocketEvent> {
fun <T1, T2, R> asyncZip(source1: Single<T1>,
source2: Single<T2>,
zipper: (T1, T2) -> Single<R>): Single<R> =
Single.zip(
source1, source2,
io.reactivex.functions.BiFunction<T1, T2, Single<R>> { t1, t2 -> zipper(t1, t2) }
).flatMap { it }