private List<List<String>> balance_trials(int i,List ballatsqs,	List<List<String>> unbalanced_trials,List<Integer> between_factors,List<List<Integer>> between_factors_list) 
	{
		int n_factors = factors_and_levels.length;
		
		if (i < n_factors)
		//if (i < 2)
		{
			int [][] ballatsq = (int[][]) ballatsqs.get(i);
			//i added (participant+i) instead of just participant bececause i want
			//different randomization for each factor for the same particpant
			
			//int dist = i*factors_and_levels[i].size();
			int level_multiples = 1;
			for (int factor = 0; factor < i; factor++)
			{
				level_multiples*=factors_and_levels[factor].size();
			}
			//System.out.println("level_multiples:"+level_multiples);			
			int index = transpose(participant,level_multiples);
			
			//we choose group order from index rather than participant directly because we want the factors to counterbalance as well
			int []	group_order = ballatsq[index % ballatsq.length]; 

			//Added November 27, 2010 to account randomization
			//is cognitive shift allowed for this factor?
			int isAllowed = independently_counterbalanced[i];
			if (isAllowed != -1)
			{
				//group_order = ballatsq[isAllowed % ballatsq.length];
				List<int[]> latin_square_rows = new ArrayList<int[]>();
				for (int a = 0; a < ballatsq.length;a++)
					latin_square_rows.add(ballatsq[a]);				
				
				//shuffle will be different for different participants
				
				Collections.shuffle(latin_square_rows, versions_set_shuffle);
				group_order = latin_square_rows.get(0); //always pick the first one
				independently_counterbalanced[i] = ++isAllowed;
			}


			//the following doesnt work and it's not needed for this experiment
			//for odd squares do 2n x n

			/*if (ballatsq.length % 2 != 0)
			{
				int [][] oddsq = new int[ballatsq.length * 2][ballatsq.length];
				
				//fill first half
				for (int j = 0; j < ballatsq.length;j++)
					for (int k = 0; k < ballatsq[j].length;k++)
						oddsq[j][k] = ballatsq[j][k];
				//fill the rest
				for (int j = 0; j < ballatsq.length;j++)
					for (int k = 0; k < ballatsq[j].length;k++)
						oddsq[ j+ ballatsq.length][k] = ballatsq[j][ballatsq[j].length - k - 1];

				group_order = oddsq[index % oddsq.length];
				
				//print it
				System.out.println("--------------------------");
				for (int j = 0; j < oddsq.length; j++)
				{
					for (int k = 0; k < oddsq[j].length; k++)
					{
						System.out.print(oddsq[j][k]);
					}
					System.out.println();
					}
				System.out.println("old:"+index % ballatsq.length+",new:"+index % oddsq.length);
			}*/
			
			List<List<String>> [] split = new List[group_order.length];			
			int [] b_factors = new int[group_order.length];			

			for (int j = 0; j < group_order.length; j++)
			{
				List<List<String>> balanced_trials_chunk = new ArrayList<List<String>>();
				
				for (int k = 0; k < unbalanced_trials.size(); k++)
				{
					String str_factor = unbalanced_trials.get(k).get(i);
					
					int pos = group_order[j]-1;				

					if (str_factor.equals(factors_and_levels[i].get(pos)))
					{	
						balanced_trials_chunk.add(unbalanced_trials.get(k));
					}
				}

				split[j] = balanced_trials_chunk; 
				b_factors[j] = group_order[j]-1;
			}
			
			List<List<String>> ret = new ArrayList<List<String>>();
			
			for (int x = 0; x < split.length; x++)
			{
				//for between factors
				List<Integer> b_factors_recurse = new ArrayList<Integer>();
				if (between_factors != null)
					b_factors_recurse.addAll(between_factors);
				b_factors_recurse.add(b_factors[x]);
				
				ret.addAll(balance_trials(i+1,ballatsqs,split[x],b_factors_recurse,between_factors_list));					
			}
			return ret;
			
		}
		else
		{
			between_factors_list.add(between_factors);
			return unbalanced_trials;	
		}
	}