Virtual U.org
Get Personal Training on VU Today
    
Top shadow
 
 register/help
User Name:

Password:

Opsch_gs.cpp Source File
Main Page   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Namespace Members   Compound Members   File Members  

Opsch_gs.cpp

Go to the documentation of this file.
00001 //Filename   : ODEPT_GS.CPP
00002 //Description: functions for generating student records
00003 //owner:                        fred 0616
00004 
00005 #include <OBOX.H>
00006 
00007 #include <OMATH.H>
00008 #include <OINFO.H>
00009 #include <OMISC.H>
00010 #include <ODEPT.H>
00011 #include <ODEPTRES.H>
00012 #include <OSCHLRES.H>
00013 #include <OPSCHOOL.H>
00014 #include <OPEERSCH.H>                             //##### fred 0714 #####//
00015 #include <OSYS.H>
00016 
00017 #include <ALL.H>                                  //for debug_msg
00018 #include <STDIO.H>
00019 
00020 #if(GAME_VERSION>=200)
00021 
00022 #define MAX_TRADITION_COUNT 5
00023 #define MAX_NONTRA_COUNT    5
00024 #define MAX_MASTER_COUNT    3
00025 #define MAX_DOCTOR_COUNT    3
00026 
00027 const RECORD_SEPARATOR_LEN = 2;
00028 static char *RECORD_SEPARATOR = "\r\n";
00029 const FIELD_SEPARATOR_LEN = 1;
00030 static char *FIELD_SEPARATOR = "\t";
00031 
00032 static char *export_num(int value) {
00033     static char num_str[20];
00034     return itoa( value, num_str, 10 );              // 10 is radix
00035 }
00036 
00037 static char *export_num(double value) {
00038     static char num_str[20];
00039     return gcvt( value, 7, num_str );               // a few more more than 7, for negative sign, decimal point and exponent
00040 }
00041 
00042 static char *export_percent(double value) {       // value already multiplied by 100
00043     static char num_str[20];
00044     return gcvt( value*0.01, 7, num_str );          // a few more more than 7, for negative sign, decimal point and exponent
00045 }
00046 
00047 #define WRITE_FIELD_SEPARATOR(f)      f->file_write(FIELD_SEPARATOR, FIELD_SEPARATOR_LEN)
00048 #define WRITE_STR_FIELD(f,s)          { f->file_write(s, strlen(s)); }
00049 #define WRITE_NUM_FIELD(f,n)          { char *s=export_num(n); f->file_write(s, strlen(s)); }
00050 #define WRITE_PERCENT_FIELD(f,n)      { char *s=export_percent(n); f->file_write(s, strlen(s)); }
00051 #define WRITE_RECORD_SEPARATOR(f)     f->file_write(RECORD_SEPARATOR, RECORD_SEPARATOR_LEN)
00052 
00053 //-------- Define struct  ---------//
00054 short NONTRA_COUNT = 0;
00055 short MASTER_COUNT = 0;
00056 short DOCTOR_COUNT = 0;
00057 #endif
00058 
00061 struct StudentStruct {
00062     int stu_recno;
00063     int dept_recno;
00064     char  trimester_tag;
00065 };
00066 
00069 class StuDynArray : public DynArray {
00070 public:
00071     StuDynArray() : DynArray(sizeof(StudentStruct), 200) {};
00072 
00073     void deinit() {
00074         if( size()==0 )
00075             return;
00076 
00077         for( int i=size() ; i>0 ; i-- ) {
00078             //if( !is_deleted(i) )
00079             linkout(i);
00080         }
00081 
00082         zap();                                      // zap the DynArrayB
00083     };
00084 };
00085 
00086 //------- Define static vars -----------//
00087 
00088 static StuDynArray    stuArr[MAX_STUDENT_LEVEL];
00089 
00090 //---------- Begin of function PlayerSchoolgenerate_student -----------//
00092 void PlayerSchool::generate_student() {
00093     // refer to techdoc3.3 section 4.1
00094     generate_student_level_pct();
00095 
00096   // refer to techdoc3.3 section 4.2 & 4.3
00097     generate_student_transition_prob_n_year_in_program();
00098 
00099     // refer to techdoc3.3 section 4.4
00100     generate_student_gender_ethnic();
00101 
00102     // refer to techdoc3.3 section 4.5: talent indices
00103     // refer to techdoc3.3 section 4.6: financial aid
00104     // NOTE: see td3.4 section 2.7 for these two parts; see enrollment model
00105 
00106   // refer to techdoc3.3 section 4.7
00107     generate_student_major_preference();
00108 
00109     // refer to techdoc3.3 section 4.8: elective course preference
00110     // refer to techdoc3.3 section 4.9: courses taken
00111 
00112     // adjust the pct arrays for generate_student_random_get_group_index()
00113     generate_student_adjust_pct_arrays();
00114 
00115     // NOTE.1 980930
00116     // DL students will use the data in HE.GDB.init:Student_Parameters for non-traditional
00117     // undergraduates (SL-2).  The original data for SL-5, non-matriculated students, can
00118     // be abandoned.
00119 
00120     //
00121     //----- randomly get properties for generate student -----//
00122     //
00123     char studentLevel, yearInProgram, genderEthnicGroup, stuSeg, major;
00124     float talentArr[TALENT_VAR_COUNT];
00125     int i, finAid = 0, progressIndex = 50;
00126 
00127     talentArr[0]=talentArr[1]=talentArr[2] = 0.5f;
00128 
00129   //## chea 281099 you can lower the init student no. from below
00130     int stuCount = get_player_expected_student_count();
00131 
00132     //DynArrayB         stuArr(sizeof(Student*), 2000,DEFAULT_REUSE_INTERVAL_DAYS);
00133 
00134     int sl_count=0;
00135 
00136 #ifdef DEBUG
00137     int year1Count[MAX_STUDENT_LEVEL];
00138     memset( year1Count, 0, sizeof(year1Count) );
00139 #endif
00140 
00141     for( i=stuCount; i>0 ; i-- ) {
00142 
00143         //----- find studentLevel -----//
00144 
00145 #if(GAME_VERSION>=200)
00146         studentLevel = generate_student_random_get_group_index
00147             (student_level_pct, MAX_STUDENT_LEVEL-1);   // omit Distance Learning
00148 #else
00149         studentLevel = generate_student_random_get_group_index
00150             (student_level_pct, MAX_STUDENT_LEVEL);
00151 #endif
00152 
00153         if ( studentLevel <= MASTER ) {
00154             yearInProgram = 1 + generate_student_random_get_group_index
00155                 (year_in_program_pct[studentLevel], MAX_GRADUATE_YEARS+1);
00156         }
00157         else if ( studentLevel == DOCTOR ) {
00158             // special case: doctor's major is assigned here
00159             //
00160             err_when(studentLevel-1 != SL_DOCTOR);
00161             // major is dept_recno to department_array
00162             major = 1 + generate_student_random_get_group_index
00163                 (adjusted_student_major_pref[SL_DOCTOR], department_array.department_count);
00164 
00165             yearInProgram = 1 + generate_student_random_get_group_index
00166                 (department_res[department_array[major]->department_id]->doctor_year_in_program_pct, MAX_GRADUATE_YEARS+1);
00167         }
00168         else if ( studentLevel == DISTANCE_LEARN ) {
00169             yearInProgram = 1 + generate_student_random_get_group_index
00170                 // see note.1 above
00171                 (year_in_program_pct[UG_NONTRADITION], MAX_GRADUATE_YEARS+1);
00172         }
00173         else
00174             err_here();                                 // unknown student level
00175 
00176         if(yearInProgram==1)
00177             sl_count++;
00178 
00179         //----- find gender -----//
00180 
00181         genderEthnicGroup = generate_student_random_get_group_index
00182             (student_gender_pct[studentLevel], GENDER_ETHNIC_TYPE_COUNT);
00183 
00184         //----- find major = deptRecno -----//
00185 
00186         if ( yearInProgram > 1 ||
00187              ( !is_ug_group(studentLevel) )  ) {
00188             if ( studentLevel != DOCTOR ) {             // doctor's major is assigned above
00189                 short sl;
00190                 if ( studentLevel == DISTANCE_LEARN )     // for sl5
00191                     sl = SL_UG;
00192                 else if ( studentLevel > UG_TRADITION  )  // for sl2-3
00193                     sl = studentLevel - 1;
00194                 else
00195                     sl = SL_UG;                             // for sl1
00196 
00197                 err_when(MASTER != UG_TRADITION + 2);
00198 
00199                 // major is dept_recno to department_array
00200                 major = 1 + generate_student_random_get_group_index
00201                     // sl: 0107: this should fix the DL student in agricultre dept
00202                     (adjusted_student_major_pref[sl], department_array.department_count);
00203             }
00204         }
00205         else if ( yearInProgram == 1 ) {
00206             // 1st year UG student don't have major
00207             major = 0;                                  // 0 -> UNDECIDED;
00208         }
00209         else
00210             err_here();
00211 
00212         //----------- student segment ------------//
00213 
00214         if ( studentLevel == UG_TRADITION ) {
00215             stuSeg = m.random(STUDENT_SEGMENT_COUNT);   //BUGHERE //TO calc subSeg
00216         }
00217         else {
00218             stuSeg = -1;
00219         }
00220 
00221         //----- add student -----//
00222 
00223         // add old students here and, will add new students (yr1 student) in enrollment
00224 
00225         if ( yearInProgram > 1 ) {
00226             // assign talent here // 990414
00227 
00228             enroll_res.calc_a_talent(talentArr, studentLevel, genderEthnicGroup, stuSeg);
00229 
00230             int stuRecno=0;
00231             if ( major )
00232                 stuRecno = department_array[major]->student_array.add( studentLevel, yearInProgram,
00233                                                                        genderEthnicGroup, stuSeg, major, finAid, talentArr );
00234             else
00235                 err_here();
00236             //department_res.general_dept.student_array.add( studentLevel, yearInProgram,
00237             //  genderEthnicGroup, stuSeg, major, finAid, talentArr );
00238 
00239             // 990413
00240             // init var for course taking init
00241             Student* stuPtr = department_array[major]->student_array[stuRecno];
00242             StudentStruct stuStruct;
00243 
00244             stuStruct.stu_recno = stuRecno;
00245             stuStruct.dept_recno = major;
00246             stuStruct.trimester_tag = -1;
00247 
00248             // remember this sim
00249             stuArr[studentLevel].linkin(&stuStruct);
00250 
00251             //StudentStruct* stuStrPtr = (StudentStruct *) stuArr.get();
00252             //err_when(stuPtr->student_level != studentLevel);
00253             //err_when(stuStrPtr->stu_ptr != stuPtr);
00254             //err_when(stuStrPtr->stu_ptr->student_level != studentLevel);
00255         }
00256 #ifdef DEBUG
00257         else {
00258             ++year1Count[studentLevel];
00259         }
00260 #endif
00261     }
00262 
00263 #if(GAME_VERSION>=200)
00264     if ( sys.debug_session ) {
00265         do {
00266             Department* deptPtr = department_array[m.random(10)+1];
00267 
00268             int stdRecno = m.random(deptPtr->student_array.size())+1;
00269 
00270             Student* stdPtr = deptPtr->student_array[stdRecno];
00271 
00272             if ( stdPtr->audit_flag )
00273                 continue;
00274 
00275             switch ( stdPtr->student_level ) {
00276             case UG_TRADITION:    continue;
00277                 break;
00278             case UG_NONTRADITION: if ( NONTRA_COUNT >= MAX_NONTRA_COUNT )
00279                 continue;
00280             NONTRA_COUNT++;
00281             break;
00282             case MASTER:        if ( MASTER_COUNT >= MAX_MASTER_COUNT )
00283                 continue;
00284             MASTER_COUNT++;
00285             break;
00286             case DOCTOR:        if ( DOCTOR_COUNT >= MAX_DOCTOR_COUNT )
00287                 continue;
00288             DOCTOR_COUNT++;
00289             break;
00290             }
00291 
00292             stdPtr->old_student_recno = stdRecno;
00293 
00294             stdPtr->audit_flag = 1;
00295 
00296             File file;
00297 
00298             char fileName[123];
00299 
00300             switch( stdPtr->student_level ) {
00301             case UG_NONTRADITION: strcpy( fileName, "NONTRADITION" );
00302                 break;
00303             case MASTER:        strcpy( fileName, "MASTER" );
00304                 break;
00305             case DOCTOR:        strcpy( fileName, "DOCTOR" );
00306                 break;
00307             }
00308 
00309             strcat( fileName, m.format(stdPtr->old_student_recno) );
00310             strcat( fileName, ".txt" );
00311 
00312             file.file_create(fileName);
00313 
00314             WRITE_STR_FIELD( (&file), "Cohort" );
00315             WRITE_FIELD_SEPARATOR( (&file) );
00316             WRITE_STR_FIELD( (&file), "Trimester" );
00317             WRITE_FIELD_SEPARATOR( (&file) );
00318             WRITE_STR_FIELD( (&file), "ID" );
00319             WRITE_FIELD_SEPARATOR( (&file) );
00320             WRITE_STR_FIELD( (&file), "Variable" );
00321             WRITE_FIELD_SEPARATOR( (&file) );
00322             WRITE_STR_FIELD( (&file), "Trimester" );
00323             WRITE_RECORD_SEPARATOR( (&file) );
00324 
00325             for ( int i=0; i<4; i++ ) {
00326                 WRITE_NUM_FIELD( (&file), -1 );
00327                 WRITE_FIELD_SEPARATOR( (&file) );
00328                 WRITE_STR_FIELD( (&file), "A" );
00329                 WRITE_FIELD_SEPARATOR( (&file) );
00330                 WRITE_FIELD_SEPARATOR( (&file) );
00331                 WRITE_STR_FIELD( (&file), "S" );
00332                 WRITE_FIELD_SEPARATOR( (&file) );
00333 
00334                 switch (i) {
00335                 case 0: WRITE_STR_FIELD( (&file), "Courses" );
00336                     WRITE_FIELD_SEPARATOR( (&file) );
00337                     WRITE_FIELD_SEPARATOR( (&file) );
00338                     WRITE_NUM_FIELD( (&file), stdPtr->course_per_trimester[0] );
00339                     WRITE_NUM_FIELD( (&file), stdPtr->course_per_trimester[1] );
00340                     WRITE_NUM_FIELD( (&file), stdPtr->course_per_trimester[2] );
00341                     break;
00342 
00343                 case 1: WRITE_STR_FIELD( (&file), "Status" );
00344                     WRITE_FIELD_SEPARATOR( (&file) );
00345                     WRITE_FIELD_SEPARATOR( (&file) );
00346                     if ( stdPtr->department_recno ) {
00347                         WRITE_STR_FIELD( (&file), department_res[department_array[stdPtr->department_recno]->department_id]->name );
00348                     }
00349                     else
00350                         WRITE_STR_FIELD( (&file), "Undec" );
00351                     break;
00352 
00353                 case 2: WRITE_STR_FIELD( (&file), "AcadTalent" );
00354                     WRITE_FIELD_SEPARATOR( (&file) );
00355                     WRITE_NUM_FIELD( (&file), stdPtr->talent_academic );
00356                     break;
00357                 case 3: WRITE_STR_FIELD( (&file), "GenEnth" );
00358                     WRITE_FIELD_SEPARATOR( (&file) );
00359                     WRITE_FIELD_SEPARATOR( (&file) );
00360                     switch( stdPtr->gender_ethnic_group ) {
00361                     case NONMINORITY_MALE:    WRITE_STR_FIELD( (&file), "NM" ); break;
00362                     case NONMINORITY_FEMALE:  WRITE_STR_FIELD( (&file), "NF" ); break;
00363                     case MINORITY_MALE:     WRITE_STR_FIELD( (&file), "MM" ); break;
00364                     case MINORITY_FEMALE:   WRITE_STR_FIELD( (&file), "MF" ); break;
00365                     }
00366                     break;
00367                 }
00368                 WRITE_RECORD_SEPARATOR( (&file) );
00369             }
00370 
00371             file.file_close();
00372         } while ((NONTRA_COUNT != MAX_NONTRA_COUNT ) || (MASTER_COUNT != MAX_MASTER_COUNT) || (DOCTOR_COUNT != MAX_DOCTOR_COUNT));
00373     }
00374 #endif
00375 
00376     //--- initialize previous course selection data for newly generated students. ---//
00377     generate_student_init_course(progressIndex);    // 990412
00378 
00379     for (char sl=0; sl<MAX_STUDENT_LEVEL; sl++)
00380         stuArr[sl].deinit();
00381 
00382 }
00383 
00384 //---------- End of function PlayerSchool::generate_student -----------//
00385 
00386 //---------- Begin of function PlayerSchool::generate_student_level_pct -----------//
00390 
00391 int PlayerSchool::get_player_expected_student_count() {
00392     const int remap[INPUT_OPTION_COUNT] = {         //refer to notes 990114
00393         2000, 6000, 10000
00394     };
00395 
00396     //## BUGHER for newif
00397     err_when(student_count < 0 || student_count >= INPUT_OPTION_COUNT);
00398 
00399     return remap[student_count];
00400     //## BUGHER for newif
00401     return student_count;
00402 }
00403 
00404 #if(GAME_VERSION>=200)
00405 int PlayerSchool::get_player_expected_sponsored_research() {
00406     switch (sponsored_research_intensity) {
00407     case 0:   return 1;
00408     case 5:   return 2;
00409     case 10:    return 4;
00410     default:
00411         err_here();
00412         return 1;
00413     }
00414 }
00415 #endif
00416 
00417 void PlayerSchool::generate_student_level_pct() {
00418     PeerSchool *playerEx = school_res.player_peer_school;
00419     int studentCount=0, i;
00420 
00421     err_when(UG_TRADITION != 0 || UG_NONTRADITION != 1);
00422 
00423     float sl2Multiplier[3] = { 1.5f, 1.0f, 0.5f };
00424     err_when(URBAN != 0);
00425 
00426     int realStuCount = get_player_expected_student_count();
00427 
00428     student_level_pct[UG_TRADITION]   = playerEx->full_time_undergrad;
00429     // 1009 + campus location
00430     student_level_pct[UG_NONTRADITION]  = playerEx->part_time_undergrad * sl2Multiplier[player_school.campus_environment] * player_school.parttime_undergrad_percent / 100;
00431     // player_input
00432     student_level_pct[DISTANCE_LEARN] = (float) ( realStuCount * sl5_student_percent / 100);
00433 
00434     int gradStudCount = realStuCount * graduate_student_percent / 100;
00435 
00436     student_level_pct[DOCTOR] = gradStudCount * player_school.doctoral_program_intensity / 100;
00437     student_level_pct[MASTER] = gradStudCount - student_level_pct[DOCTOR];
00438 
00439     //-----------------------------------------------//
00440 
00441     for (i=0; i<MAX_STUDENT_LEVEL; i++)
00442         studentCount += (int) student_level_pct[i];
00443 
00444     //-----------------------------------------------//
00445 
00446     float scaleFactor = float(realStuCount) / studentCount;
00447 
00448     for (i=0; i<MAX_STUDENT_LEVEL; i++) {
00449         student_level_pct[i]
00450             = (student_level_pct[i] * scaleFactor) / realStuCount;
00451     }
00452 }
00453 
00454 //---------- End of function PlayerSchool::generate_student_level_pct -----------//
00455 
00456 //---------- Begin of function PlayerSchool::generate_student_transition_probabilities -----------//
00466 void PlayerSchool::generate_student_transition_prob_n_year_in_program() {
00467     PeerSchool *playerEx = school_res.player_peer_school;
00468     int yr, sl, i;
00469 
00470     //----- transition probabilities for UG_TRADITION & UG_NONTRADITION & MASTER-----//
00471     // refer to techdoc3.3 section 4.2
00472     //temporarily place the following procedures in this function
00473 
00474     // read these two arrays from dbase
00475     const float dropouts_fraction[MASTER_ARRAY_SIZE][MAX_GRADUATE_YEARS] = {
00476         { 0.29f, 0.19f, 0.26f,  0.16f, 0.07f, 0.02f, 0.01f, 0.00f },
00477         { 0.25f, 0.20f, 0.15f, 0.10f, 0.08f, 0.08f, 0.07f, 0.07f  },
00478         { 0.70f, 0.30f, 0.00f, 0.00f, 0.00f, 0.00f, 0.00f, 0.00f  }
00479 
00480     };
00481 
00482     const float graduates_fraction[MASTER_ARRAY_SIZE][MAX_GRADUATE_YEARS] = {
00483         { 0.00f,  0.00f,  0.06f,  0.53f,  0.31f,  0.08f,  0.02f,  0.00f },
00484         { 0.00f,  0.00f,  0.00f,  0.00f,  0.00f,  0.10f,  0.30f,  0.50f },
00485         { 0.95f,  0.05f,  0.00f,  0.00f,  0.00f,  0.00f,  0.00f,  0.00f }
00486     };
00487 
00488     err_when(UG_TRADITION!=0);
00489     err_when(MASTER!=2);
00490 
00491     // step 1
00492     //
00493     float fractionWhoGradOnTime[UG_NONTRADITION+1];
00494     float gradAnytimePct[MASTER_ARRAY_SIZE];
00495 
00496     memset(fractionWhoGradOnTime, 0, sizeof(fractionWhoGradOnTime));
00497 
00498     for (i=0; i<MAX_GRADUATE_YEARS; i++)
00499         fractionWhoGradOnTime[UG_TRADITION] += graduates_fraction[UG_TRADITION][i];
00500 
00501     for (i=0; i<MAX_GRADUATE_YEARS; i++)
00502         fractionWhoGradOnTime[UG_NONTRADITION] += graduates_fraction[UG_NONTRADITION][i];
00503 
00504     for (sl= 0; sl<=UG_NONTRADITION; sl++) {
00505         gradAnytimePct[sl]
00506             = playerEx->target_grad_rate_sl[sl] / 100.0f
00507             + ( 1-playerEx->target_grad_rate_sl[sl] / 100.0f )
00508             * ( 1-fractionWhoGradOnTime[sl] );
00509     }
00510     // special case for MASTER
00511     gradAnytimePct[MASTER] = playerEx->target_grad_rate_sl[MASTER] / 100.0f;
00512 
00513     // step 2
00514     //
00515     float fractionSurvivors[MAX_GRADUATE_YEARS+1], popDivisor[MASTER_ARRAY_SIZE];
00516     float gradTransProb[MASTER_ARRAY_SIZE][MAX_GRADUATE_YEARS];
00517 
00518     for (sl=0; sl<MASTER_ARRAY_SIZE; sl++) {
00519         for (yr=0; yr<MAX_GRADUATE_YEARS; yr++) {
00520             if ( yr > 0 ) {
00521                 fractionSurvivors[yr]  = fractionSurvivors[yr-1] * (1.0f - gradTransProb[sl][yr-1]    - dropout_trans_prob[sl][yr-1]);
00522                 popDivisor[sl] += fractionSurvivors[yr];
00523             }
00524             else {
00525                 fractionSurvivors[yr] = 1.0f;
00526                 popDivisor[sl] = fractionSurvivors[yr];
00527             }
00528 
00529 #if(GAME_VERSION>=200)
00530             // BUG FIX if divided by zero
00531             dropout_trans_prob[sl][yr] = math.safe_divide( dropouts_fraction[sl][yr] * ( 1.0f - gradAnytimePct[sl] ), fractionSurvivors[yr] );
00532 
00533             gradTransProb[sl][yr] = math.safe_divide( graduates_fraction[sl][yr] * gradAnytimePct[sl], fractionSurvivors[yr] );
00534 #else
00535             dropout_trans_prob[sl][yr] = dropouts_fraction[sl][yr] * ( 1.0f - gradAnytimePct[sl] ) / fractionSurvivors[yr];
00536 
00537             gradTransProb[sl][yr] = graduates_fraction[sl][yr] * gradAnytimePct[sl] / fractionSurvivors[yr];
00538 #endif
00539         }
00540 
00541         //----- calc year_in_program_pct -----//
00542         fractionSurvivors[yr]  = fractionSurvivors[yr-1] * (1.0f - gradTransProb[sl][yr-1] - dropout_trans_prob[sl][yr-1]);
00543         popDivisor[sl] += fractionSurvivors[yr];
00544 
00545         for (yr=0; yr<MAX_GRADUATE_YEARS+1; yr++) {
00546 #if(GAME_VERSION>=200)
00547             year_in_program_pct[sl][yr] = math.safe_divide( fractionSurvivors[yr], popDivisor[sl] );
00548 #else
00549             year_in_program_pct[sl][yr] = fractionSurvivors[yr] / popDivisor[sl];
00550 #endif
00551             //## chea 120200 just checking
00552             if(year_in_program_pct[sl][yr]<=0)
00553                 year_in_program_pct[sl][yr]=0;
00554         }
00555     }
00556 
00557     memcpy(grad_trans_prob, gradTransProb, sizeof(gradTransProb));
00558 
00559     //----- transition probabilities for DOCTOR -----//
00560     // calculated for each department;
00561     // see DepartmentInfo::generate_student_transition_prob_n_year_in_program_doctor()
00562     short deptCount = department_res.department_count;
00563     for( i=1 ; i<=deptCount ; i++ ) {
00564         DepartmentInfo *deptInfo = department_res[i];
00565         deptInfo->generate_student_transition_prob_n_year_in_program_doctor();
00566     }
00567 
00568     //----- transition probabilities for SL-5 are not necessary -----//
00569 }
00570 
00571 //---------- End of function PlayerSchool::generate_student_transition_probabilities -----------//
00572 
00573 //-------- Begin of function PlayerSchool::generate_student_transition_probabilities -------//
00577 void DepartmentInfo::generate_student_transition_prob_n_year_in_program_doctor() {
00578     //----- transition probabilities for DOCTOR -----//
00579     // refer to techdo3.3, section 4.2, p.12-p.13
00580     //
00581     short sl = DOCTOR;
00582     short yr;
00583 
00584     PeerSchool *playerEx = school_res.player_peer_school;
00585     float targetSchoolGradRate = playerEx->target_grad_rate_sl[sl] / 100.0f;
00586     float avgTimeToDegree = playerEx->doc_time_to_degree;
00587 
00588     //temp vars for debug
00589     //targetSchoolGradRate = 0.465f;
00590     //avgTimeToDegree = 4.21f;
00591 
00592     float avgTimeToDropout = 0.5f * avgTimeToDegree;// B102
00593 
00594     // step1: F106:H106 of student_par spreadsheet
00595     //
00596 #define MAX_GRADUATE_RATE 0.8f
00597 
00598     DepartmentInfo* deptInfo = this;                // department_res[department_id];
00599 
00600     float cummGradRate = targetSchoolGradRate * deptInfo->doctoral_grad_rate_multiplier;
00601     if ( cummGradRate > MAX_GRADUATE_RATE )
00602         cummGradRate = MAX_GRADUATE_RATE;
00603 
00604     float aveTimeToDropout  = avgTimeToDropout * deptInfo->doctoral_time_to_dropout_multiplier;
00605     float aveTimeToDegree = avgTimeToDegree * deptInfo->doctoral_time_to_degree_multiplier;
00606 
00607     // step2: I106:P106
00608 
00609     float graduateFraction, dropoutFraction;
00610     float fractionSurvivors[MAX_GRADUATE_YEARS], popDivisor;
00611 
00612     for (yr=0; yr<MAX_GRADUATE_YEARS; yr++) {
00613         if ( yr > 0 ) {
00614             fractionSurvivors[yr]  = fractionSurvivors[yr-1] * (1.0f - doctor_dropout_trans_prob[yr-1] - doctor_graduate_trans_prob[yr-1]);
00615             popDivisor += fractionSurvivors[yr];
00616         }
00617         else {
00618             fractionSurvivors[yr] = 1.0f;
00619             popDivisor = fractionSurvivors[yr];
00620         }
00621 
00622         //askbillok: 1-yr or yr-1:
00623         yr++;                                         // see equation (3) in p.13 techdoc 3.3
00624         dropoutFraction
00625             = float( exp((1-yr)/aveTimeToDropout) - exp(-yr/aveTimeToDropout));
00626         graduateFraction
00627             = float( exp((3-yr)/(aveTimeToDegree-2)) - exp((2-yr)/(aveTimeToDegree-2)));
00628         yr--;
00629 
00630         //----- calc trans_prob -----//
00631 
00632         doctor_dropout_trans_prob[yr] = dropoutFraction*(1-cummGradRate)/fractionSurvivors[yr];
00633 
00634         if ( yr==0 || yr==1 )
00635             doctor_graduate_trans_prob[yr]  = 0.0f;
00636         else
00637             doctor_graduate_trans_prob[yr]  = graduateFraction*cummGradRate/fractionSurvivors[yr];
00638     }
00639 
00640     fractionSurvivors[yr]  = fractionSurvivors[yr-1] * (1.0f - doctor_dropout_trans_prob[yr-1] - doctor_graduate_trans_prob[yr-1]);
00641     popDivisor += fractionSurvivors[yr];
00642 
00643     for (yr=0; yr<MAX_GRADUATE_YEARS+1; yr++) {     //askbillok: take the easiest approaach; why yr=0to8 (why+1)
00644         doctor_year_in_program_pct[yr] = fractionSurvivors[yr] / popDivisor;
00645     }
00646 }
00647 
00648 //---------- End of function PlayerSchool::generate_faculty_calc_vars -----------//
00649 
00650 //-------- Begin of function PlayerSchool::generate_student_gender_ethnic -------//
00654 void PlayerSchool::generate_student_gender_ethnic() {
00655     //----- initial percent for each gender-ethic group ----//
00656 
00657     PeerSchool *playerEx = school_res.player_peer_school;
00658 
00659     for ( int sl=0; sl<MAX_STUDENT_LEVEL; sl++ ) {
00660         //----- get female and minority percentages from player_school_ex -----//
00661 
00662         float femalePercent = playerEx->percent_female_sl[sl] / 100.0f;
00663         float minorityPercent = playerEx->percent_minority_sl[sl] / 100.0f;
00664 
00665         //--------- special case: scenario ---------//
00666 
00667         if ( info.year_passed == 1 && player_school.scenario_id == SCN_STUDENT_DIVERSITY ) {
00668             minorityPercent *= 0.571f;
00669         }
00670 
00671         // calc what we want
00672 
00673         student_gender_pct[sl][MINORITY_FEMALE] = femalePercent*minorityPercent;
00674         student_gender_pct[sl][NONMINORITY_FEMALE] = femalePercent*(1.0f - minorityPercent);
00675         student_gender_pct[sl][MINORITY_MALE] = (1.0f - femalePercent)*minorityPercent;
00676         student_gender_pct[sl][NONMINORITY_MALE] = (1.0f - femalePercent)*(1.0f - minorityPercent);
00677     }
00678 }
00679 
00680 //---------- End of function PlayerSchool::generate_student_gender_ethnic -----------//
00681 
00682 //-------- Begin of function PlayerSchool::generate_student_major_preference -------//
00686 void PlayerSchool::generate_student_major_preference() {
00687     short i, sl, deptCount, deptId;
00688     DepartmentInfo *deptInfo;
00689 
00690     deptCount = department_res.department_count;
00691     for( i=1 ; i<=deptCount ; i++ ) {
00692         deptInfo = department_res[i];
00693         deptInfo->generate_student_major_preference();
00694     }
00695 
00696     //----- adjust the preferecne percentages for the included dept -----//
00697     //
00698     // please note that if a department is not included in department_array,
00699     // it won't have an entry in adjusted_student_major_pref
00700     //
00701 
00702     deptCount = department_array.department_count;
00703     float totalPctIncludedDept = 0.0f;
00704 
00705     err_when(!deptCount);
00706     memset(adjusted_student_major_pref, 0, sizeof(adjusted_student_major_pref));
00707 
00708     for (sl=0; sl<MAX_STUDENT_LEVEL_INI; sl++) {
00709         totalPctIncludedDept = 0.0f;
00710 
00711         for (i=1; i<=deptCount; i++) {
00712             deptId = department_array[i]->department_id;
00713             deptInfo = department_res[deptId];
00714             totalPctIncludedDept += deptInfo->student_major_pref[sl];
00715         }
00716 
00717         for (i=1; i<=deptCount; i++) {
00718             deptId = department_array[i]->department_id;
00719             deptInfo = department_res[deptId];
00720 
00721             adjusted_student_major_pref[sl][i-1] = math.safe_divide(deptInfo->student_major_pref[sl], totalPctIncludedDept);
00722             // another alternative:
00723             // adjusted_student_major_pref[sl][deptId] /= totalPctIncludedDept;
00724         }
00725 
00726         // 0304 change upon Jesse's latest email
00727         float minPct = 1.0f / deptCount;
00728         totalPctIncludedDept = 0;
00729 
00730         for (i=1; i<=deptCount; i++) {
00731             // if pref < 0.1 (10%)
00732             if ( adjusted_student_major_pref[sl][i-1] < minPct )
00733                 // + 1% pref to this dept
00734                 adjusted_student_major_pref[sl][i-1] += 0.03f;
00735 
00736             totalPctIncludedDept += adjusted_student_major_pref[sl][i-1];
00737         }
00738 
00739         for (i=1; i<=deptCount; i++)
00740             adjusted_student_major_pref[sl][i-1] /= totalPctIncludedDept;
00741 
00742         // end 0304
00743     }
00744 }
00745 
00746 //---------- End of function PlayerSchool::generate_student_major_preference -----------//
00747 
00748 //-------- Begin of function DepartmentInfo::generate_student_major_preference -------//
00752 void DepartmentInfo::generate_student_major_preference() {
00753     short sl;
00754     PeerSchool *playerEx = school_res.player_peer_school;
00755 
00756     for (sl=0; sl<MAX_STUDENT_LEVEL_INI; sl++) {
00757         // refer to spreadsheet: student_par: E24 = C24*D24:
00758         // Preference for major = IPEDS %UG degrees * Fraction of field pct
00759 
00760         student_major_pref[sl]
00761             = playerEx->student_ifield_pct[sl][iped_field]
00762             * field_fraction_pct[sl];
00763     }
00764 
00765     //TO debug the values of student_major_pref?
00766 }
00767 
00768 //---------- Begin of function DeptInfo::generate_student_ajdust_arrays -----------//
00769 
00770 //---------- Begin of function PlayerSchool::generate_student_ajdust_arrays -----------//
00773 void PlayerSchool::generate_student_adjust_pct_arrays() {
00774     int sl, i;
00775 
00776     generate_student_adjust_pct_array
00777         (student_level_pct, MAX_STUDENT_LEVEL);
00778 
00779     for (sl=0; sl<MASTER_ARRAY_SIZE; sl++) {
00780         generate_student_adjust_pct_array
00781             (year_in_program_pct[sl], MAX_GRADUATE_YEARS+1);
00782     }
00783 
00784     short deptCount = department_res.department_count;
00785     for( i=1 ; i<=deptCount ; i++ ) {
00786         generate_student_adjust_pct_array
00787             (department_res[i]->doctor_year_in_program_pct, MAX_GRADUATE_YEARS+1);
00788     }
00789 
00790     for (sl=0; sl<MAX_STUDENT_LEVEL; sl++) {
00791         generate_student_adjust_pct_array
00792             (student_gender_pct[sl], GENDER_ETHNIC_TYPE_COUNT);
00793     }
00794 
00795     for (sl=0; sl<MAX_STUDENT_LEVEL_INI; sl++) {
00796         generate_student_adjust_pct_array
00797             (adjusted_student_major_pref[sl], department_array.department_count);
00798     }
00799 }
00800 
00801 void PlayerSchool::generate_student_adjust_pct_array(float *arr, int size) {
00802     int i;
00803     for (i=1; i<size; i++)
00804         arr[i] += arr[i-1];
00805 
00806     if ( arr[size-1] > 0.95)
00807         arr[size-1] = 1.0f;
00808     else {
00809         if (arr[0] != 0 )                             //1120 bug from special game_setting
00810             err_here();                                 // debug_msg("PlayerSchool::generate_student_adjust_pct_array: Array Data Incorrect");
00811     }
00812 }
00813 
00814 void PlayerSchool::generate_student_readjust_pct_array(float *arr, int size) {
00815     int i;
00816     for (i=size-1; i>0; i--)
00817         arr[i] -= arr[i-1];
00818 
00819     err_when(arr[0]<0);
00820 }
00821 
00822 //---------- End of function PlayerSchool::generate_student_adjust_arrays -----------//
00823 
00824 //---------- End of function PlayerSchool::generate_student_random_get_group_index -----------//
00825 //
00826 // <size> = number of group
00827 // return the group index
00828 //
00829 char PlayerSchool::generate_student_random_get_group_index(float *arr, int size) {
00830     const int randomPrecesion = 10000;
00831     float rand = float(m.random(randomPrecesion+1)) / randomPrecesion;
00832 
00833     err_when(size >127);                            // since return type is char
00834 
00835     for ( int i=0; i<size; i++ ) {
00836         if ( rand <= arr[i] )
00837             return (char) i;
00838     }
00839     return 0;
00840 }
00841 
00842 //---------- End of function PlayerSchool::generate_student_random_get_group_index -----------//
00843 
00844 //---------- End of function PlayerSchool::get_random_major -----------//
00845 //
00846 // <sl> = student level
00847 // return the dept_recno index
00848 //
00849 int PlayerSchool::get_random_major(char sl) {
00850     if ( sl == DISTANCE_LEARN)                      // 0107
00851         sl = UG_TRADITION;
00852     if ( sl >= UG_NONTRADITION )
00853         sl--;
00854 
00855     err_when(sl<0 || sl>= MAX_STUDENT_LEVEL_INI);
00856 
00857     int returnValue = 1 + generate_student_random_get_group_index( adjusted_student_major_pref[sl], department_array.department_count );
00858 
00859 #if(GAME_VERSION>=200)
00860     if ( returnValue > department_array.size() )
00861         returnValue = department_array.size();
00862 #endif
00863 
00864     return returnValue;                             // major is dept_recno to department_array
00865 
00866 }
00867 
00868 //---------- End of function PlayerSchool::get_random_major -----------//
00869 
00870 //### begin trevor 1908 ##//
00871 
00872 //---------- End of function PlayerSchool::generate_student_init_course -----------//
00873 //
00874 // Initialize previous course selection data for newly generated students.
00875 //
00876 /*
00877 void PlayerSchool::generate_student_init_course(int progressIndex)
00878 {
00879   //err_here();         // 990413
00880 
00881   for( int processYearInProgram=4 ; processYearInProgram>=2 ; processYearInProgram-- )          // only process students whose year in program equal to this
00882   {
00883     for( int deptRecno=department_array.size() ; deptRecno>0 ; deptRecno-- )
00884     {
00885       if ( deptRecno==3 || deptRecno==6 || deptRecno==9 )
00886 
00887 if( department_array.is_deleted(deptRecno) )
00888 continue;
00889 
00890 department_array[deptRecno]->student_array.init_course(processYearInProgram);
00891 }
00892 }
00893 }
00894 //---------- End of function PlayerSchool::generate_student_init_course -----------//
00895 */
00896 //### end trevor 1908 ##//
00897 
00898 //--------------------------------------------------------------------------//
00899 //--------------------------------------------------------------------------//
00900 //--------------------------------------------------------------------------//
00901 
00902 static char cur_student_level_for_sorting = 0;
00903 
00904 //------ Begin of function sort_stu_talent_function ------//
00908 static int sort_stu_talent_function( const void *a, const void *b ) {
00909     // 1st sort key: trimester_tag
00910     // 2nd sort key: talent
00911 
00912     StudentStruct* stuStrPtrA, *stuStrPtrB;
00913     Student* stuPtrA, *stuPtrB;
00914 
00915     stuStrPtrA = (StudentStruct *) stuArr[cur_student_level_for_sorting].get(*((short*)a));
00916     stuStrPtrB = (StudentStruct *) stuArr[cur_student_level_for_sorting].get(*((short*)b));
00917 
00918     float rc = float(stuStrPtrA->trimester_tag - stuStrPtrB->trimester_tag);
00919 
00920     if( rc > 0 )
00921         return 1;
00922     else if( rc < 0 )
00923         return -1;
00924 
00925     stuPtrA = department_array[stuStrPtrA->dept_recno]->student_array[stuStrPtrA->stu_recno];
00926     stuPtrB = department_array[stuStrPtrB->dept_recno]->student_array[stuStrPtrB->stu_recno];
00927 
00928     float valueA = stuPtrA->talent_academic;
00929     float valueB = stuPtrB->talent_academic;
00930 
00931     rc = valueA - valueB;
00932 
00933     if( rc > 0 )
00934         return 1;
00935     else if( rc < 0 )
00936         return -1;
00937     else
00938         return 0;
00939 }
00940 
00941 //------- End of function sort_stu_talent_function ------//
00942 
00943 //---------- Begin of function PlayerSchool::generate_student_init_course -----------//
00948 /*
00949   for SL-1,2,4,5
00950   {
00951        set tag = 0
00952 
00953        for eachTriGroup (note: i.e. there're (8-2 = 6) TriGroups for SL-1)
00954        {
00955           generate sims for this triGroup
00956           assign the current tag to these sims
00957           for each sim generated for this triGroup AND sims created SO FAR
00958           {
00959 run A-2
00960 }
00961 increment tag!!!
00962 }
00963 
00964 run B for SL-1,2,3,4,5
00965 }
00966 
00967 */
00968 
00969 void PlayerSchool::generate_student_init_course(int progressIndex) {
00970     int try_to_count = 0;
00971     const char norm_ft_trimesters[MAX_STUDENT_LEVEL] = { 8,8,2,4,8 };
00972     //## chea 281099
00973     const char no_of_time_sel_cour[MAX_STUDENT_LEVEL] = {
00974         2,2,1,1,2
00975     };
00976 
00977     int i;
00978 
00979     StudentStruct* stuStrPtr;
00980     Student* stuPtr;
00981 
00982     //---- get the maximum # of students in all student levels ----//
00983 
00984     int stuCount = 0;
00985 
00986     for( i=0 ; i<MAX_STUDENT_LEVEL ; i++ ) {
00987         if( stuArr[i].size() > stuCount )
00988             stuCount = stuArr[i].size();
00989     }
00990 
00991     err_when( stuCount <= 0 );
00992     err_when( stuCount > 10000000 );
00993 
00994     //---- allocate the array ---------//
00995 
00996     short* stuSortArray = (short*) mem_add( stuCount * sizeof(short) );
00997 
00998     for ( char sl=0; sl<MAX_STUDENT_LEVEL; sl++ ) {
00999         /*
01000           int tag = 1;
01001           int stuCountThisLevel = stuArr[sl].size();
01002           int stuCountPerTrimester = stuCountThisLevel / norm_ft_trimesters[sl];
01003 
01004           // ------ Part A ------
01005 
01006           for ( int t=0; t<norm_ft_trimesters[sl]-2; t++ )  //## chea 281099 for testing
01007           {
01008           for ( i=1; i<=stuCountPerTrimester*(1+t); i++ )
01009           {
01010           stuStrPtr = (StudentStruct *) stuArr[sl].get(i);
01011           stuPtr = department_array[stuStrPtr->dept_recno]->student_array[stuStrPtr->stu_recno];
01012 
01013           if ( i > stuCountPerTrimester * t )                   // shoudn't be ">="
01014           stuStrPtr->trimester_tag = tag;
01015 
01016           err_when(stuPtr->student_level != sl);                //BUGHERE
01017           stuPtr->select_course(1);             // 1: ignoreFaculty
01018           }
01019 
01020           tag++;
01021           }
01022         */
01023 
01024         //## chea 281099 new idea since the old alg. ignor year_in_program
01025         int tag = 1;
01026         int time_in_school;
01027         int stuCountThisLevel = stuArr[sl].size();
01028 
01029         int stuCountPerTrimester = stuCountThisLevel / norm_ft_trimesters[sl];
01030 
01031 #ifdef DEBUG
01032         int studentYearCount[MAX_GRADUATE_YEARS+1];
01033         memset( studentYearCount, 0, sizeof(studentYearCount) );
01034         int studentCredit[32+1];
01035         memset( studentCredit, 0, sizeof(studentCredit) );
01036 #endif
01037 
01038         for ( i=1; i<=stuCountThisLevel; i++ ) {
01039 
01040             stuStrPtr = (StudentStruct *) stuArr[sl].get(i);
01041             stuPtr = department_array[stuStrPtr->dept_recno]->student_array[stuStrPtr->stu_recno];
01042 
01043             err_when(stuPtr->year_in_program == 1);
01044             time_in_school = stuPtr->year_in_program-1;
01045 
01046 #if(GAME_VERSION>=200)
01047             //                  if(sl==UG_TRADITION && time_in_school>BACHELOR_YEAR_COUNT+1)   //Gilbert : too many graduate at the end of pre-run year
01048             //                          time_in_school=BACHELOR_YEAR_COUNT-1;
01049 #else
01050             if(sl==UG_TRADITION && time_in_school>5)    //## chea 281099 try not to handle student study ug. over 5 years.
01051                 time_in_school=3;
01052 #endif
01053 
01054 #ifdef DEBUG
01055             if( time_in_school > MAX_GRADUATE_YEARS )
01056                 studentYearCount[MAX_GRADUATE_YEARS]++;
01057             else if( time_in_school >= 0 )
01058                 studentYearCount[time_in_school]++;
01059 #endif
01060 
01061             for ( int t=0; t<no_of_time_sel_cour[sl]*time_in_school; t++ ) {
01062 #if(GAME_VERSION>=200)
01063                 if ( stuPtr->audit_flag ) {
01064                     File file;
01065 
01066                     char fileName[123];
01067 
01068                     switch( stuPtr->student_level ) {
01069                     case UG_TRADITION:    strcpy( fileName, "TRADITION" );
01070                         break;
01071                     case UG_NONTRADITION: strcpy( fileName, "NONTRADITION" );
01072                         break;
01073                     case MASTER:        strcpy( fileName, "MASTER" );
01074                         break;
01075                     case DOCTOR:        strcpy( fileName, "DOCTOR" );
01076                         break;
01077                     }
01078 
01079                     strcat( fileName, m.format(stuPtr->old_student_recno) );
01080                     strcat( fileName, ".txt" );
01081 
01082                     file.file_append( fileName );
01083                     file.file_seek(0, FILE_END);
01084 
01085                     char textDisplay[128];
01086                     sprintf( textDisplay, "****** This is the No.%d trimester in the history ******", t );
01087                     WRITE_STR_FIELD( (&file), textDisplay );
01088 
01089                     WRITE_RECORD_SEPARATOR( (&file) );
01090 
01091                     file.file_close();
01092                 }
01093 #endif
01094 
01095 #if(GAME_VERSION>=200)
01096                 stuPtr->select_course(1, 1);              // 1: ignoreFaculty, 1: ignore course student count, denial count
01097 #else
01098                 stuPtr->select_course(1);                 // 1: ignoreFaculty
01099 #endif
01100             }
01101 
01102             //          if ( i > stuCountPerTrimester * t )                     // shoudn't be ">="
01103             //                          stuStrPtr->trimester_tag = tag;
01104 
01105 #ifdef DEBUG
01106             if( stuPtr->total_course_all >= 32 )
01107                 ++studentCredit[32];
01108             else if( stuPtr->total_course_all >= 0 )
01109                 ++studentCredit[stuPtr->total_course_all];
01110 #endif
01111             tag++;
01112         }
01113 
01114         // ------ Part B ------
01115 
01116         int t = norm_ft_trimesters[sl]-2;
01117         int tmpBound = stuCountPerTrimester * t;
01118 
01119         for ( i=1; i<=stuCountThisLevel; i++ ) {
01120             stuStrPtr = (StudentStruct *) stuArr[sl].get(i);
01121             stuPtr = department_array[stuStrPtr->dept_recno]->student_array[stuStrPtr->stu_recno];
01122 
01123             if ( i > tmpBound )
01124                 stuStrPtr->trimester_tag = tag;
01125             try_to_count++;
01126 #if(GAME_VERSION>=200)
01127             if ( stuPtr->audit_flag ) {
01128                 File file;
01129 
01130                 char fileName[123];
01131 
01132                 switch( stuPtr->student_level ) {
01133                 case UG_TRADITION:    strcpy( fileName, "TRADITION" );
01134                     break;
01135                 case UG_NONTRADITION: strcpy( fileName, "NONTRADITION" );
01136                     break;
01137                 case MASTER:        strcpy( fileName, "MASTER" );
01138                     break;
01139                 case DOCTOR:        strcpy( fileName, "DOCTOR" );
01140                     break;
01141                 }
01142 
01143                 strcat( fileName, m.format(stuPtr->old_student_recno) );
01144                 strcat( fileName, ".txt" );
01145 
01146                 file.file_append( fileName );
01147                 file.file_seek(0, FILE_END);
01148 
01149                 WRITE_STR_FIELD( (&file), "********** It is the start of the prerun year **********" );
01150 
01151                 WRITE_RECORD_SEPARATOR( (&file) );
01152 
01153                 file.file_close();
01154             }
01155 #endif
01156             stuPtr->select_course(1);                   // 1: ignoreFaculty
01157         }
01158 
01159         // ------ Part C-1 ------ // sort tag and talent
01160 
01161         for( i=1; i<=stuCountThisLevel; i++ )
01162             stuSortArray[i-1] = i;                      // stuArr[sl].get();
01163 
01164         cur_student_level_for_sorting = sl;
01165         qsort( stuSortArray, stuCountThisLevel, sizeof(stuSortArray[0]), sort_stu_talent_function );
01166 
01167         // ------ Part C-2 ------
01168 
01169         float *yearInProgramPctArr;
01170 
01171         if ( sl <= MASTER ) {
01172             yearInProgramPctArr = year_in_program_pct[sl];
01173         }
01174         else if ( sl == DOCTOR ) {
01175             //major = 1 + generate_student_random_get_group_index                                       // major is dept_recno to department_array
01176             //  (adjusted_student_major_pref[SL_DOCTOR], department_array.department_count);
01177 
01178             //yearInProgram = 1 + generate_student_random_get_group_index
01179             int major = 1+m.random(department_array.department_count);
01180             yearInProgramPctArr =
01181                 department_res[department_array[major]->department_id]->doctor_year_in_program_pct;
01182         }
01183         else if ( sl == DISTANCE_LEARN ) {
01184             yearInProgramPctArr = year_in_program_pct[UG_NONTRADITION];
01185         }
01186 
01187         // to find stuCountByYear[]
01188         int stuCountByYear[MAX_GRADUATE_YEARS+1];
01189         memset(stuCountByYear,0,sizeof(stuCountByYear));
01190 
01191         int chkCount = 0;
01192         float pct = yearInProgramPctArr[0];
01193 
01194         for (i=0; i<MAX_GRADUATE_YEARS+1 && pct<=1; i++) {
01195             stuCountByYear[i] = int(stuCountThisLevel * yearInProgramPctArr[i]);
01196 
01197             chkCount += stuCountByYear[i];
01198             pct += yearInProgramPctArr[i+1];
01199         }
01200 
01201         // to eliminate the difference
01202 
01203         int diff = stuCountThisLevel - chkCount;
01204         err_when(diff < 0);
01205 
01206         if ( diff > 0 ) {
01207             i = min(MAX_GRADUATE_YEARS, i);
01208             stuCountByYear[i] += diff;
01209         }
01210 
01211         /*              for (i=MAX_GRADUATE_YEARS; i>=0 && diff>0; i--)
01212                         {
01213                         if ( stuCountByYear[i] >= diff )
01214                         {
01215                         stuCountByYear[i] -= diff;
01216                         diff = 0;
01217                         }
01218                         else
01219                         {
01220                         diff -= stuCountByYear[i];
01221                         stuCountByYear[i] = 0;
01222                         }
01223                         }*/
01224 
01225         // ------ Part C-3 ------
01226 
01227         int year = MAX_GRADUATE_YEARS+1;
01228 
01229         for (i=0; ; ) {
01230             if ( stuCountByYear[year-1] > 0 )
01231                 stuCountByYear[year-1]--;
01232             else if ( year > 2 ) {
01233                 year--;
01234                 continue;
01235             }
01236             else
01237                 break;
01238 
01239             err_when(stuSortArray[i] < 1 || stuSortArray[i] > stuCountThisLevel);
01240 
01241             stuStrPtr = (StudentStruct *) stuArr[sl].get(stuSortArray[i]);
01242             stuPtr = department_array[stuStrPtr->dept_recno]->student_array[stuStrPtr->stu_recno];
01243 
01244             stuPtr->year_in_program = year;
01245 
01246             i++;
01247         }
01248 
01249         int finalStuCountThisLevel = i;
01250 
01251         // discard sims
01252         if ( finalStuCountThisLevel != stuCountThisLevel ) {
01253             for (int j=finalStuCountThisLevel; j<stuCountThisLevel; j++) {
01254                 stuStrPtr = (StudentStruct *) stuArr[sl].get(stuSortArray[j]);
01255                 department_array[stuStrPtr->dept_recno]->student_array.del(stuStrPtr->stu_recno);
01256                 stuStrPtr->dept_recno = 0;
01257                 stuStrPtr->stu_recno = 0;
01258             }
01259         }
01260 
01261         // ------ Part D ------ // admission procedure will be run in enrollment model
01262 
01263         // ------ Part E-1 ------
01264 
01265         float failRate = 0;
01266 
01267         for (int j=0; j<finalStuCountThisLevel; j++) {
01268             stuStrPtr = (StudentStruct *) stuArr[sl].get(stuSortArray[j]);
01269 
01270             // Last bug : sl=1, j=6 -> stuStrPtr = NULL
01271             // stuSortArray seems corruptted
01272             // chwg 072199 // avoid the bug of stuStrPtr become NULL
01273             if(stuStrPtr==NULL)
01274                 continue;
01275             stuPtr = department_array[stuStrPtr->dept_recno]->student_array[stuStrPtr->stu_recno];
01276 
01277             float newValue= 40+(stuPtr->talent_academic)*(.2f + .8f * ((50)-50)/100);
01278             newValue = math.single_response_func(0.0f, 0.1f, -70.11f, 53.65f, newValue);
01279 
01280             failRate += newValue;
01281         }
01282 
01283 #if(GAME_VERSION>=200)
01284         // BUG FIX if divided by zero
01285         failRate = math.safe_divide( failRate, (float)finalStuCountThisLevel );
01286 #else
01287         failRate /= finalStuCountThisLevel;
01288 #endif
01289 
01290         // ------ Part E-2 ------
01291 
01292         PeerSchool* player = school_res.player_peer_school;
01293         const float expectedYearsToDegree[MAX_STUDENT_LEVEL] = { 4.47f, 7.65f, 1.05f, player->doc_time_to_degree-2, 7.65f };
01294         const char normYearsToDegree[MAX_STUDENT_LEVEL] = { 4,8,1,2,8 };
01295 
01296         //## chea 151099
01297         float lagRate = expectedYearsToDegree[sl] / normYearsToDegree[sl];
01298         //              float lagRate = normYearsToDegree[sl] / expectedYearsToDegree[sl];    //## chea 151099  want to change to this but I am lost
01299 
01300         // ------ Part E-3 ------
01301 
01302         //## chea 151099
01303         this->delay_rate[sl] = 1 - (1-lagRate) / (1-failRate);
01304         //              this->delay_rate[sl] = min(0.975f,max(0.8f,1 - (1-lagRate) / (1-failRate)));   //## chea 151099 want to change to this but I am lost
01305 
01306     }                                               // end for
01307 
01308     mem_del( stuSortArray );                        // sorting finished
01309 }
01310 
01311 //---------- End of function PlayerSchool::generate_student_init_course -----------//

Generated on Fri Aug 23 01:38:14 2002 for VirtualU by doxygen1.2.17