Open
Description
When adding a fixture, the UI should have good defaults:
- Fixture Type: last one in that field (if not submitted) or fixture type last added
- DMX Mode: last one with which this fixture was added
- Name: Fixture Type Name (Numbering with space if multiple Qty, but not in text field, only in preview)
- Quantity: 1
- FID: highest FID + 1
- Universe/Address: lowest free with enough space for selected above
A first draft for the API is still in hackmd, but we may still want to decide whether HTTP or WS is the better approach here.
Also, Form validation for adding fixtures needs to be added and we should report errors from the server to the user.
Kotlin Algorithm for Finding Free Address
When adding new fixtures, the client needs to assign their DMX Addresses. By default it makes sense to put these in the "next free gap" of the approriate size. I wrote an algorithm in Kotlin to find these gaps:
/**
* Finds the first gap in [inputList] at or after [target]. The minimum size of the gap can be specified by [gapSize].
*
* [inputList] does not have to be sorted.
*/
fun nextGap(inputList: List<Int>, target: Int, gapSize: Int = 1): Int {
val list = inputList.sorted()
var firstCandidate = list.binarySearch(target)
if (firstCandidate < 0) {
// negative returned index means the targetFid does not exist in Patch yet
firstCandidate = -firstCandidate-1
}
var last: Int = target-1
var current: Int
for (i in firstCandidate..list.lastIndex) {
current = list[i]
if (current > last + gapSize) {
return last + 1
}
last = current
}
return last + 1
}
Note this algorithm does not consider the upper limit of 512 on DMX Addresses, so that needs to be added in an outer layer.
The associated unit test:
@Test
fun testFindGapAtOrAfter() {
val exampleArray = arrayOf(10,11,12,20,21,23)
exampleArray.shuffle(kotlin.random.Random(42))
val exampleList = exampleArray.asList()
// gapSize 1
assertEquals(1, nextGap(exampleList, 1))
assertEquals(3, nextGap(exampleList, 3))
assertEquals(13, nextGap(exampleList, 10))
assertEquals(13, nextGap(exampleList, 12))
assertEquals(19, nextGap(exampleList, 19))
assertEquals(22, nextGap(exampleList, 20))
assertEquals(22, nextGap(exampleList, 21))
assertEquals(22, nextGap(exampleList, 22))
assertEquals(24, nextGap(exampleList, 23))
assertEquals(24, nextGap(exampleList, 24))
// bigger gapSize
assertEquals(1, nextGap(exampleList, 1, 9))
assertEquals(24, nextGap(exampleList, 1, 10))
assertEquals(13, nextGap(exampleList, 12, 7))
assertEquals(24, nextGap(exampleList, 12, 8))
assertEquals(18, nextGap(exampleList, 18, 2))
assertEquals(24, nextGap(exampleList, 18, 3))
assertEquals(24, nextGap(exampleList, 23, 9))
assertEquals(24, nextGap(exampleList, 24, 9))
}
Activity