/Rex/labTools/task_utilities.c
C | 556 lines | 265 code | 95 blank | 196 comment | 84 complexity | e24e87179a2e7c49281abdfa3f708516 MD5 | raw file
Possible License(s): LGPL-2.0
- /*
- ** TASK_UTILITIES.C
- **
- ** Utility functions to use with pRec/pTask
- ** structures & routines
- */
- #include <stddef.h>
- #include "toys.h"
- #include "task_utilities.h"
- #include "property_list.h"
- /* PUBLIC ROUTINES */
- /* make trials */
- /* PUBLIC ROUTINE: tu_make_trials1D
- **
- */
- void tu_make_trials1D(_PRtask task,
- char *name, int num, int *values, float multiplier)
- {
- register int i;
- /* check args ... be sure to free trials
- ** if none given
- */
- if(num <= 0) {
- pr_task_clear(task);
- return;
- }
- /* add the array of (empty) trials */
- pr_task_add_trials1D(task, num);
- /* For each, add a list with the value
- ** of the given property.
- */
- for(i=0;i<num;i++) {
- task->trials[i]->id = task->id*100+i;
- task->trials[i]->list =
- pl_list_initV("1dtc", 0, 1,
- name, values[i], multiplier,
- NULL);
- }
- }
- /* PUBLIC ROUTINE: tu_make_trials2D
- **
- ** Utility to make a 2D trial set.
- ** Parameter #1 is rows
- ** Parameter #2 is columns
- **
- ** Remember that, as per C conventions, matrix
- ** is stored row by row.
- **
- ** Arguments:
- ** _PRtask ... the task to update
- ** name1 ... string name of paramter #1
- ** n1 ... number of values in paramter #1 array (rows)
- ** v1 ... array of values for paramter #1
- ** m1 ... multiplier for paramter #1
- ** name2 ... string name of paramter #2
- ** n2 ... number of values in paramter #2 array (cols)
- ** v2 ... array of values for paramter #2
- ** m2 ... multiplier for paramter #2
- */
- void tu_make_trials2D(_PRtask task,
- char *name1, int n1, int *v1, float m1,
- char *name2, int n2, int *v2, float m2)
- {
- long dummy = 0;
- register int i, j, k;
- /* check args ... be sure to free trials
- ** if none given
- */
- if(n1 <= 0 && n2 <= 0) {
- pr_task_clear(task);
- return;
- }
- if(n1 <= 0) {
- n1 = 1;
- v1 = &dummy;
- m1 = 1.0;
- }
- if(n2 <= 0) {
- n2 = 1;
- v2 = &dummy;
- m2 = 1.0;
- }
- /* add the array of (empty) trials */
- pr_task_add_trials2D(task, n1, n2);
- /* For each, add a list of 2 properties,
- ** corresponding to the values of the two
- ** variables.
- */
- for(k=0,i=0;i<n1;i++) {
- for(j=0;j<n2;j++,k++) {
- task->trials[k]->id = task->id*100+k;
- task->trials[k]->list =
- pl_list_initV("2dtc", 0, 1,
- name1, v1[i], m1,
- name2, v2[j], m2,
- NULL);
- }
- }
- }
- /* get trials */
- /* PUBLIC ROUTINE: tu_get_block
- **
- ** Gets the next trial from a standard (not randomized) block,
- ** making the block if necessary
- **
- ** Arguments:
- ** task ... See paradgim_rec for details.
- ** num_blocks ... Number of blocks (reps) of the set of trials
- ** that should be used when creating the
- ** pointer array.
- ** reset_flag ... If true, set the pointer back to the beginning
- ** after reaching the end of the array.
- **
- */
- _PRtrial tu_get_block(_PRtask task, int num_blocks, int reset_flag)
- {
- int last_score = task->pmf ? task->pmf->last_score : 0;
- /* Conditionally make a single block...
- ** This will also reset the index to 0
- */
- if(task->trialPs == NULL) {
- pr_task_make_trialP_all(task, num_blocks);
- /* check that it worked */
- if(task->trialPs == NULL)
- return(NULL);
- /* Otherwise increment the pointer and check for
- ** end of the array
- */
- } else if(last_score >= 0 &&
- ++(task->trialPs_index) >= task->trialPs_length) {
- /* end of the line ... check for reset */
- if(reset_flag > 0)
- /* reset pointer back to the beginning of the array */
- task->trialPs_index = 0;
- else
- /* no reset, end of the line */
- return(NULL);
- }
- /* return the current trial */
- return(task->trialPs[task->trialPs_index]);
- }
- /* PUBLIC ROUTINE: tu_get_random
- **
- ** Gets the next trial in a randomized block,
- ** making the block if necessary.
- **
- ** Arguments:
- ** task ... See paradgim_rec for details.
- ** num_blocks ... Number of blocks (reps) of the set of trials
- ** that should be used when creating the
- ** pointer array.
- ** reset_flag ... If true, set the pointer back to the beginning
- ** after reaching the end of the array.
- */
- _PRtrial tu_get_random(_PRtask task, int num_blocks, int reset_flag)
- {
- int last_score = task->pmf ? task->pmf->last_score : 0;
- if(task->trialPs) {
- /* check previous score ... */
- if(last_score < 0) {
- /* swap trial with later trial */
- pr_task_swap_trialP(task);
- /* try to increment the pointer */
- } else if((++(task->trialPs_index)) == task->trialPs_length) {
- /* reached the end, clear pointer array
- ** so next time through it gets re-randomized
- */
- SAFE_FREE(task->trialPs);
- task->trialPs_length = 0;
- }
- } else {
-
- /* force 'reset' first time through */
- reset_flag = 1;
- }
- /* check to make block */
- if(reset_flag && !task->trialPs) {
- /* make the randomized set... the second argument
- ** determines the minimum number of trial
- ** blocks to include in the array -- this
- ** is to make sure that redoing trials
- ** after an nc/brfix doesn't cause
- ** a predictable pattern to accumulate
- ** at the end of the list
- */
- pr_task_make_trialP_allR(task, num_blocks);
- }
- /* check if there is a list of pointers */
- if(!task->trialPs)
- return(NULL);
- /* return pointer to the current trial */
- return(task->trialPs[task->trialPs_index]);
- }
- /* PUBLIC ROUTINE: tu_get_random_altRows
- **
- ** Modified by Long from tu_get_random()
- ** make a superblock by combining randomized blocks by rows.
- ** Gets the next trial in a randomized block,
- ** making the block if necessary.
- **
- ** Arguments:
- ** task ... See paradgim_rec for details.
- ** num_blocks ... Number of blocks (reps) of the set of trials
- ** that should be used when creating the
- ** pointer array.
- ** reset_flag ... If true, set the pointer back to the beginning
- ** after reaching the end of the array.
- */
- _PRtrial tu_get_random_altRows(_PRtask task, int num_blocks, int reset_flag)
- {
- int last_score = task->pmf ? task->pmf->last_score : 0;
- int flagRepeat = pl_list_get_v(task->task_menus->lists[1], "flagRepeat")
;
- if(task->trialPs) {
- /* check previous score ... */
-
- if ( (last_score <= -1) || ( (last_score==0) && flagRepeat ) ) {
-
- /* always repeat fixbreak or no-choice trials , or error-trial with flagRepeat on */
- printf (" repeat trial \n");
- return(task->trialPs[task->trialPs_index]);
- }
-
- if ( (last_score<0) && !flagRepeat ) {
-
- /* swap trial with later trial */
- printf (" swap trial \n");
- pr_task_swap_trialP(task);
-
- /* try to increment the pointer */
- } else if((++(task->trialPs_index)) == task->trialPs_length) {
- /* reached the end, clear pointer array
- ** so next time through it gets re-randomized
- */
- SAFE_FREE(task->trialPs);
- task->trialPs_length = 0;
- }
- } else {
-
- /* force 'reset' first time through */
- reset_flag = 1;
- }
- /* check to make block */
- if(reset_flag && !task->trialPs) {
-
int num_sets = task->trials_rows;
- int num_cols = task->trials_columns;
- int count_per_row = num_cols * num_blocks;
- _PRtrial *finaltrialPs = SAFE_ZALLOC(_PRtrial, num_sets*count_per_row);
- int i, j, k, m, n;
- /*
- ** Long: create a super block with blocks of randomized sets.
- ** Each block contains num_blocks randomized trials.
- */
-
- SAFE_FREE(task->trialPs);
- task->trialPs = SAFE_ZALLOC(_PRtrial, count_per_row);
- task->trialPs_length = count_per_row;
- task->trialPs_index = 0;
-
- n = 0;
- for(m=0; m<num_sets; m++) {
-
- /* fill the array with repeated blocks of pointers
- ** to trials, in order
- */
- k = 0;
- for(i=0;i<num_blocks;i++)
- for(j=0;j<num_cols;j++) {
- task->trialPs[k] = task->trials[j + m*num_cols];
- k++;
- }
- pr_task_randomize_trialP(task);
- for (i=0; i<k; i++) {
- finaltrialPs[n] = task->trialPs[i];
- n++;
- }
- }
-
- SAFE_FREE(task->trialPs);
- task->trialPs = finaltrialPs;
- task->trialPs_length = n;
- task->trialPs_index = 0;
- }
-
- /* check if there is a list of pointers */
- if(!task->trialPs)
- return(NULL);
- /* return pointer to the current trial */
- return(task->trialPs[task->trialPs_index]);
- }
- /* PUBLIC ROUTINE: tu_compute_xyrt
- **
- ** Computes x,y positions of a set of
- ** graphics objects with properties
- ** defined as "TU_XYRT_LIST"
- ** (see task_utilities.h)
- **
- */
- void tu_compute_xyrt(_PLlist list)
- {
- int pi=0;
- register int i=0;
- if(!list || !list->properties_length ||
- !list->values_length)
- return;
- /* find index of property DX_X */
- while(pi<list->properties_length &&
- strcmp(list->properties[pi]->name, DX_X)) pi++;
- if(pi == list->properties_length)
- return;
- /* set each rt */
- for(i=0;i<list->values_length;i++) {
- tu_compute_rtR(list->properties, pi, i);
- /*
- ** printf("obj %d, r = %d, t = %d\n", i,
- ** list->properties[pi+kR]->values_wc[i],
- ** list->properties[pi+kT]->values_wc[i]);
- */
- }
- /* set each xy */
- for(i=0;i<list->values_length;i++) {
- tu_compute_xyR(list->properties, pi, i);
- /*
- ** printf("obj %d, x = %d, y = %d\n", i,
- ** list->properties[pi]->values_wc[i],
- ** list->properties[pi+1]->values_wc[i]);
- */
- }
- }
- #define WVI(ki_,vi_) ps[pi+(ki_)]->values_wc[(vi_)]
- #define WV(ki_) WVI(ki_, vi)
- #define WC_VDV(v_,dv_) WC_V(v_, dv_); WC_DV(v_,dv_)
- #define WC_V(v_,dv_) if(WV(v_) == NULLI) { WV(v_) = 0; }
- #define WC_DV(v_,dv_) if(WV(dv_)>0) { \
- WV(v_) += (TOY_RAND(2*WV(dv_)+1) - WV(dv_)); \
- WV(dv_) = NULLI; }
- void tu_compute_rtR(_PLproperty *ps, int pi, int vi)
- {
- int wrti;
- /*
- ** Check r,t
- */
- WC_VDV(kR, kDR);
- WC_VDV(kT, kDT);
- /*
- ** Get WRT angle ... first get index of wrt object,
- ** then marks as NULLI to avoid inf recurs.
- */
- wrti = WV(kWRT);
- WV(kWRT) = NULLI;
- /* check for no wrt */
- if(wrti == NULLI || wrti == vi || wrti < 0 ||
- wrti >= (*ps)->values_length)
- return;
- /* recursively compute the angle ! */
- tu_compute_rtR(ps, pi, wrti);
- /* add the angle */
- WV(kR) += WVI(kR, wrti);
- }
- void tu_compute_xyR(_PLproperty *ps, int pi, int vi)
- {
- int vertexi, vx, vy;
- /*
- ** Check if x, y are set ...
- */
- if(WV(kX) != NULLI && WV(kY) != NULLI) {
- /* check for dx, dy */
- WC_DV(kX, kDX);
- WC_DV(kY, kDY);
- /* outta */
- return;
- }
- /* r, t should already be set */
- vertexi = WV(kVERTEX);
- WV(kVERTEX) = NULLI;
- /* check for no vertex */
- if(vertexi == NULLI || vertexi == vi || vertexi < 0 ||
- vertexi >= (*ps)->values_length) {
- vx = 0;
- vy = 0;
- } else {
- tu_compute_xyR(ps, pi, vertexi);
- vx = WVI(kX, vertexi);
- vy = WVI(kY, vertexi);
- }
- /* compute x, y from r, t, and
- ** add dx,dy if neccesary.
- */
- WV(kX) = TOY_RT_TO_X(vx, WV(kR), WV(kT));
- WC_DV(kX, kDX);
- WV(kY) = TOY_RT_TO_Y(vy, WV(kR), WV(kT));
- WC_DV(kY, kDY);
- /*
- ** printf("vt=%d,vx=%d,vy=%d,kr=%d,kt=%d,kdx=%d,kdy=%d,kx=%d,ky=%d\n",
- ** vertexi,vx,vy,WV(kR),WV(kT),WV(kDX),WV(kDY),WV(kX),WV(kY));
- */
- }
- /* PUBLIC ROUTINE: tu_compute_dangle
- ** Returns an array containing target angles +/- RAND(dangle)
- ** Added by bss on 04/26/2007
- */
- int *tu_compute_dangle(int angle, int toff, int dangle, int radius, int dangle_limit)
- {
- int *dangled[3];
- int t1, t2;
- int ang_betw_t;
- double d_betw_t;
-
- /* Choose a position for T1 everything else is relative to this */
- if(TOY_RAND(100)<=49) {
- angle+=toff;
- }
- else {
- angle+=(toff+180);
- }
- /* Choose if you are adding or subtracting dangle */
- if(dangle>1) {
- if(TOY_RAND(100)<=49) {
- t1=angle-TOY_RAND(dangle);
- }
- else {
- t1=angle+TOY_RAND(dangle);
- }
-
- if(TOY_RAND(100)<=49) {
- t2=angle+180-TOY_RAND(dangle);
- }
- else {
- t2=angle+180+TOY_RAND(dangle);
- }
- }
- else {
- t1=angle;
- t2=angle+180;
- }
-
- /* Check final angles to make sure that they are not too close */
- ang_betw_t=abs(t2-t1);
- if(ang_betw_t>180) {
- ang_betw_t=360-ang_betw_t; /* Normalize */
- }
-
- d_betw_t=2*(sin(DEG2RAD*((double)ang_betw_t/2)))*((double)radius/10);
-
- if(d_betw_t>dangle_limit) {
- dangled[2]=1;
- }
- else {
- dangled[2]=0;
- }
- dangled[0]=t1;
- dangled[1]=t2;
- return(dangled);
- }
- /* PUBLIC ROUTINE: tu_get_seed
- **
- ** Generate seed for random number generator.
- ** Behavior depends on seed_base:
- ** <0 ... generate random seed
- ** =0 ... use zero as seed
- ** >0 ... generate seed from base, coherence, angle
- */
- int tu_get_seed(int seed_base, int coherence, int angle)
- {
- struct timespec now;
- int seed;
- if (seed_base < 0) {
- clock_gettime(CLOCK_REALTIME, &now);
- seed = now.tv_sec%1000;
- }
- else if (seed_base == 0) {
- seed = 0;
- }
- else {
- seed = seed_base + coherence + angle;
- }
- printf("dot seed = %d\n", seed);
- return (seed);
- }