Hello everyone!
I'm in the process of designing a quiz feature, and I'm struggling with designing an algorithm that will choose questions for a quiz. I believe my issue would easily be solved with a while loop, but since this is unavailable in Appian, I need some help designing an alternative solution. I have no code written, so let me describe my issue from a high level.
I have a table containing quiz questions - around 400 rows at the moment. When loading a quiz form, I need to pull randomly chosen 40 questions from this table.
First, I determine the first available question ID. Then, I determine the last available question ID. I save both as integers, 7 and 403.
Then, I get a random integer number, picked from a range between 7 and 403.
And here's where I get stuck: I need to make sure these numbers are unique. Normally I would have an array that I would append with these randomly generated integers on the condition that they are not already in the array, and I would do this until the array item count equals 40. But since I need to specify, somehow, the number of iterations in the for loop, the whole idea breaks apart.
Furthermore, I also need to make sure that these numbers are actually valid primary keys... You might have noticed that the range starts at 7, and this is because the first 6 rows were test values I have filtered out of the Record Type via Source Filter.
Querying the Record Type for all question IDs, and then choosing a random ID from this array is also an option, but it seems like a pretty heavy query. And then I would have to re-query.
I have another idea which might work, but I am not sure if this is the most optimal approach. The interface is using a wizard pattern, so after each question the user will have to click a button to navigate to the next question. I think I could, upon button click, append the ID of the current question to a variable, then get a random ID following the steps above, query for this ID to populate the next step. The hole in this one is that I still need to make sure that the randomly picked integer is actually a valid identifier.
Please, help a brother out!
Discussion posts and replies are publicly visible
Yup, Expressions aren't always that friendly for some things. Some options:
fn!index( fn!union( a!flatten( a!forEach( items: fn!enumerate(403) + 7, expression: a!localVariables( local!outerValue: fv!item, a!forEach( items: fn!enumerate(10), expression: fn!tointeger( local!outerValue + fn!round(fn!rand() * 10, 0) ) ) ) ) ), fn!tointeger({}) ), 10 * fn!enumerate(40) + 1 )
Basically the Expression is operating a loop within a loop. The inner loop is generating the random numbers as integers in batches of 10, each of which is added to the value of the outer loop (which is incrementing from your lower to upper bounds - i.e. 7 to 403).
The result is then flattened (so the lists of lists is made into one list) which is the deduplicated (using the union function).
Lastly, we index into this list every 10th item.
It's crude but seems to work. Others may have better ideas.
It does seem crude but doable. I considered using a process, since you can actually perform a while loop there, but I was not entirely sure how to access the output in the expression, since I am using a Start Form. Thanks for your help!