I think that the relevant code is mostly in the mciatextension.js script. Specifically, the following code:
//These are the 6 orders of the first two blocks
//All the other blocks are determined by these two.
var blockSeqs4 = [
{f1:1, n1:2, f2:3},
{f1:1, n1:3, f2:2},
{f1:2, n1:1, f2:3},
{f1:2, n1:3, f2:1},
{f1:3, n1:1, f2:2},
{f1:3, n1:2, f2:1}
];...
function getBlockSequence(inID)
{
var blockSeq = [];
var seq = blockSeqs4[inID-1];
//All the blocks are derived from the first two blocks.
blockSeq.push({focalCat:seq.f1, nonFocalCat:seq.n1});//Block 2
blockSeq.push({focalCat:seq.f1, nonFocalCat:seq.n1});//Block 3 (1st critical)
blockSeq.push({focalCat:seq.f2, nonFocalCat:seq.f1});//Block 4 (2nd critical)
blockSeq.push({focalCat:seq.n1, nonFocalCat:seq.f1});//Block 5 (3rd critical = opposite of 1st)
blockSeq.push({focalCat:seq.f2, nonFocalCat:seq.n1});//Block 5 (4th critical = two last focals)
blockSeq.push({focalCat:seq.f1, nonFocalCat:seq.f2});//Block 6 (5th critical = opposite of 2nd)
blockSeq.push({focalCat:seq.n1, nonFocalCat:seq.f2});//Block 7 (6th critical = opposite of 4th)
return (blockSeq);
}...
//Set the category order: the sequence of focal categories.
//The constraint is that each category appears as focal only
//after all the others appeared (exhausted)
var blockSequence;
if (piCurrent.blockSequenceID>0)
{//select the block sequence from a list of all the sequences.
blockSequence = getBlockSequence(piCurrent.blockSequenceID);
}
else if (piCurrent.blockSequence)
{
blockSequence = piCurrent.blockSequence;
}
In mciat.js, the following line is relevant:
blockSequenceID : Math.round(Math.random() * 5),
This is what I think is going on in that code:
1 The parameter blockSequenceID is set to a number between 1 to 5 (this might be due to a coding mistake because I think that it should have been between 1 to 6, so perhaps the code should have been Math.round(Math.random() * 6)].
2 The extension uses the value of blockSequenceID to determine which of the six possible orders to use, as defined in the variable blockSeqs4.
2a Each of the six orders is defined by the first focal category (f1), the first non-focal category (n1) and the second focal category (f2).
2b As shown in the getBlockSequence function, those details are all that the code needs in order to determine which category would be the focal category and which would be the non-focal category in each of the blocks of the task.
2c If I understand the code of that function correctly, after the practice block, the same focal and non-focal categories appear in two consecutive blocks, which probably means that Block 2 is also considered a practice block. Only afterwards, all six contrasts appear, one block after the other.
So, if you want four categories, I guess you need one general practice block, and then 4*3 contrast blocks, with the first one appearing twice at the beginning, once as a practice block and once as the first critical block. I am guessing that's why you wrote that it would require 14 blocks.
I recommend first to change the code to define 14 blocks, without thinking about the randomization. For example, in the getBlockSequence function:
blockSeq.push({focalCat:1, nonFocalCat:2});//Block 2
blockSeq.push({focalCat:1, nonFocalCat:2});//Block 3 (1st critical)
blockSeq.push({focalCat:3, nonFocalCat:1});
blockSeq.push({focalCat:4, nonFocalCat:2});
blockSeq.push({focalCat:2, nonFocalCat:3});
blockSeq.push({focalCat:1, nonFocalCat:4});
blockSeq.push({focalCat:4, nonFocalCat:3});//Opposites
blockSeq.push({focalCat:2, nonFocalCat:1});
blockSeq.push({focalCat:1, nonFocalCat:3});
blockSeq.push({focalCat:1, nonFocalCat:4});
blockSeq.push({focalCat:3, nonFocalCat:2});
blockSeq.push({focalCat:4, nonFocalCat:1});
blockSeq.push({focalCat:3, nonFocalCat:4});
Then, run to make sure that it shows you 14 blocks with four categories. That would mean that we probably understand correctly how the code works.
Next, you can think about how you want to randomize the order and what the rules you want to use in order to build the block sequence. Use those rules to change the code such that it would be relevant for 4 rather than 3 categories.
*There is probably also a way to support a variable number of categories, but it would require some more thinking.
I hope that helps, but let me know if you need more information.
Yoav