This function will randomize categories and make sure that some do not sit next to each other.
Metadata(en-US, Question, Label) q1loop "blah" loop { _1 "_1", _2 "_2", _3 "_3", _4 "_4", _5 "_5", _6 "_6", _7 "_7", _8 "_8", _9 "_9" } fields - ( q1 "" categorical [1..1] { _1 "_1", _2 "_2", _3 "_3", _4 "_4", _5 "_5" }; ) expand; End Metadata
And in the routing
Routing(Web) Dim i q1loop.Categories.Order = OrderConstants.oCustom For i = 1 to 20 ' test 20 times q1loop.Categories.Filter = RanNotTogether(q1loop,{_3,_4,_5},Null) q1loop[..].q1.Response.Initial = {_1} q1loop.Ask() Next '! Returns a category list of all categories in question.categories where none of the categories in notTogether are next to one another Caution should be taken to ensure that there is enough room to allow for the notTogether codes to be separated by at least one other code For example, a question with 9 items having 5 items that can't be together is not possible. ARGS: question - question whose categories are used notTogether - category list of categories that cannot appear together seed - if not Null, then used as the random seed RETURNS: category list randomized so that none of the notTogether categories are next to each other EXAMPLE: q10loop.Categories.Order = OrderConstants.oCustom q10loop.Categories.Filter = RanNotTogether,q10loop,{coke,pepsi,rccola},Null) !' Function RanNotTogether(question,notTogether,seed) Dim randomCodes,notTogetherCodes Dim randomCodeList,randomCode,codeCount Dim FinalArray[],strFilter ' Make array large enough for all categories ReDim(FinalArray,question.Categories.Count) ' Initialize array to blanks For codeCount = LBound(FinalArray) to UBound(FinalArray) FinalArray[codeCount] = "" Next ' Codes allowed to be together randomCodes = SelectRange(question.Categories - notTogether) ' Codes not allowed to be together notTogetherCodes = SelectRange(notTogether) codeCount = 0 ' Place codes not allowed to be next to each other If ( seed is not null ) Then SetRandomSeed(seed) randomCodeList = ransequence(0,UBound(FinalArray),1) For Each randomCode in randomCodeList Select Case ( randomCode ) Case 0 ' Can't have any to right If FinalArray[randomCode + 1] = "" Then FinalArray[randomCode] = notTogetherCodes[codeCount] codeCount = codeCount + 1 End If Case UBound(FinalArray) ' Can't have any to left If FinalArray[randomCode - 1] = "" Then FinalArray[randomCode] = notTogetherCodes[codeCount] codeCount = codeCount + 1 End If Case Else ' Can't have any to right or left If FinalArray[randomCode + 1] = "" And FinalArray[randomCode - 1] = "" Then FinalArray[randomCode] = notTogetherCodes[codeCount] codeCount = codeCount + 1 End If End Select ' If placed all those that can't be together, then get out of loop if ( codeCount > UBound(notTogetherCodes) ) Then Exit For Next ' Add the remaining codes codeCount = 0 For Each randomCode in randomCodeList ' If haven't used this position, then put in the next remaining code If FinalArray[randomCode] = "" Then FinalArray[randomCode] = randomCodes[codeCount] codeCount = codeCount + 1 End If Next ' convert to a categorical list and return strFilter = "" For codeCount = LBound(FinalArray) to UBound(FinalArray) strFilter = strFilter + question.Categories[CCategorical(FinalArray[codeCount])].Name + "," Next RanNotTogether = CCategorical("{" + Left(strFilter,Len(strFilter)-1) + "}") End Function End Routing