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

Password:

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

Oenroll.cpp

Go to the documentation of this file.
00001 //Filename              : OEnroll.cpp
00002 //Description   : EnrollRes Class Definition
00003 //Owner                 : Fred
00004 
00005 #include <obox.h>                                 // for progress box
00006 #include <stdio.h>                                // for DEBUG
00007 #include <osys.h>                                 // for progress box
00008 
00009 // ES library header file
00010 #include <ALL.H>
00011 #include <OGAMESET.H>
00012 #include <OMATH.H>                                // average_float, gammaCDF
00013 #include <OSTR.h>                                 // strcmp
00014 #include <OLINALG.H>                              // for this calc_enroll_offers
00015 
00016 // CU header file
00017 #include <GAMEDEF.H>                              // enum { NONMINORITY_MALE, NONMINORITY_FEMALE, MINORITY_MALE, MINORITY_FEMALE };
00018 #include <OPSCHOOL.H>
00019 #include <OPEERSCH.H>
00020 #include <OSCHLRES.H>
00021 #include <ODEPTRES.H>
00022 #include <OFINANCE.H>                             // for next_day
00023 #include <OINFO.H>                                // for next_day
00024 #include <ODEPT.H>                                // for calc_student_count
00025 #include <OSTUDENT.H>                             // for calc_student_count
00026 #include <OLIBTECH.H>
00027 #include <OATHLETI.H>
00028 #include <OSTUOFF.H>
00029 #include "OEnroll.h"
00030 
00031 // database come from data_to_db.xls
00032 //
00033 #define PREFERENCE_DB "STUPREF"
00034 #define APP_YIELD_DB    "APPYIELD"
00035 #define PREFERENCE_DB2  "STUPREF2"
00036 #define TALENT_DB     "STTALENT"
00037 
00038 //----------- Define constants -------------//
00039 //----------- Define static variables -------------//
00040 #if(GAME_VERSION>=200)
00041 short TRADIT_COUNT = 0;
00042 
00043 #define MAX_TRADITION_COUNT 5
00044 #define MAX_NONTRA_COUNT    5
00045 #define MAX_MASTER_COUNT    3
00046 #define MAX_DOCTOR_COUNT    3
00047 
00048 const RECORD_SEPARATOR_LEN = 2;
00049 static char *RECORD_SEPARATOR = "\r\n";
00050 const FIELD_SEPARATOR_LEN = 1;
00051 static char *FIELD_SEPARATOR = "\t";
00052 
00053 static char *export_num(int value) {
00054     static char num_str[20];
00055     return itoa( value, num_str, 10 );              // 10 is radix
00056 }
00057 
00058 static char *export_num(double value) {
00059     static char num_str[20];
00060     return gcvt( value, 7, num_str );               // a few more more than 7, for negative sign, decimal point and exponent
00061 }
00062 
00063 static char *export_percent(double value) {       // value already multiplied by 100
00064     static char num_str[20];
00065     return gcvt( value*0.01, 7, num_str );          // a few more more than 7, for negative sign, decimal point and exponent
00066 }
00067 
00068 #define WRITE_FIELD_SEPARATOR(f)      f->file_write(FIELD_SEPARATOR, FIELD_SEPARATOR_LEN)
00069 #define WRITE_STR_FIELD(f,s)          { f->file_write(s, strlen(s)); }
00070 #define WRITE_NUM_FIELD(f,n)          { char *s=export_num(n); f->file_write(s, strlen(s)); }
00071 #define WRITE_PERCENT_FIELD(f,n)      { char *s=export_percent(n); f->file_write(s, strlen(s)); }
00072 #define WRITE_RECORD_SEPARATOR(f)     f->file_write(RECORD_SEPARATOR, RECORD_SEPARATOR_LEN)
00073 #endif
00074 
00075 //----------- Define static class member variables -------------//
00076 const float EnrollRes::apps_latency[MAX_STUDENT_LEVEL] = { .4f, .4f, .5f, .6f, .7f };
00077 // 990408 const float EnrollRes::yield_latency[MAX_STUDENT_LEVEL] = { .6f, .5f, .5f, .5f, .5f };        // elm 1-4 are useless
00078 // elm 1-4 are useless
00079 const float EnrollRes::yield_latency[MAX_STUDENT_LEVEL] = {
00080     .9f, .5f, .5f, .5f, .5f
00081 };
00082 
00083 // (* given to minority scores *)
00084 const float EnrollRes::aidMinMultipliers[PRIORITY_LEVEL_COUNT] = {
00085     1, 1.05f, 1.10f
00086 };
00087 //const float aidAthMultipliers         = {1, 1.25f, 1.50f}; // (* extra aid for athletes *)
00088 
00089 EnrollRes::EnrollRes() {
00090 }
00091 
00092 //----------- Define static functions -------------//
00093 static bool is_minority_group(char group) {
00094     return group == MINORITY_MALE || group == MINORITY_FEMALE;
00095 }
00096 
00097 static bool is_male_group(char group) {
00098     return group == MINORITY_MALE || group == NONMINORITY_MALE;
00099 }
00100 
00101 //----------- Begin of function EnrollRes::adjust_fraction_merit_aid --------//
00104 void EnrollRes::adjust_fraction_merit_aid(float& fraction) {
00105     if ( fraction > 0 && fraction < fraction_merit_top - .005f )
00106         fraction = fraction_merit_top + .005f;
00107     else if ( fraction > 1 + .005f - fraction_merit_top )
00108         fraction = (1 - .005f - fraction_merit_top) ;
00109 }
00110 
00111 //----------- Begin of function EnrollRes::adjust_fraction_merit_aid --------//
00112 
00113 //----------- Begin of function EnrollRes::init --------//
00116 void EnrollRes::init() {
00117     memset(this, 0, sizeof(EnrollRes));
00118 
00119     load_db_student_pref();
00120     load_db_student_pref2();
00121     load_db_app_yield();
00122     load_db_student_talent();
00123 
00124 #if(GAME_VERSION>=200)
00125     distance_learner_acceptance = 1;
00126 #endif
00127 
00128     //-------- init constants ----------//
00129     s_lower_bound = 0.5f;
00130     s_upper_bound = 1.5f;
00131     s_slope     = 5.0f;
00132 
00133     chance_avg  = 1.0f;
00134     chance_sd = 1.0f;
00135 
00136     fraction_merit_top = 0.025f;                    // see section 2.4 last paragraph
00137 }
00138 
00139 //------------- End of function EnrollRes::init --------//
00140 
00141 //----------- Begin of function EnrollRes::deinit --------//
00143 void EnrollRes::deinit() {
00144 }
00145 
00146 //------------- End of function EnrollRes::deinit --------//
00147 
00148 //----------- Begin of function EnrollRes::load_db_student_pref ------//
00152 void EnrollRes::load_db_student_pref() {
00153     PreferenceRec  *prefRec;
00154     Database    *dbPreference = game_set.open_db(PREFERENCE_DB);
00155 
00156     int db_count = (short) dbPreference->rec_count();
00157 
00158     err_when( db_count != PREFERECNE_COUNT * 2 );   // 2: average and deviation
00159 
00160     //askbillok: how to handle "na in cells like E119-120
00161     //  segment2 = segment1
00162 
00163     //------ read in Preference information array -------//
00164 
00165     memset( preference_array, 0, sizeof(preference_array));
00166 
00167     for( int i=0 ; i<db_count ; i++ ) {
00168         //----- odd row/record store average -----//
00169         prefRec = (PreferenceRec*) dbPreference->read(i+1);
00170 
00171         for( int j=0 ; j<INSTITU_SEGMENT_COUNT; j++ ) {
00172             preference_array[i/2][j].average = (float) m.atof( prefRec->value[j], 9 );
00173             preference_array[i/2][j].weight = (float) m.atof( prefRec->weight, 9 );
00174         }
00175 
00176         i++;
00177         //-----  even row/record store deviation -----//
00178         prefRec = (PreferenceRec*) dbPreference->read(i+1);
00179 
00180         for( j=0 ; j<INSTITU_SEGMENT_COUNT; j++ )
00181             preference_array[i/2][j].deviation = (float) m.atof( prefRec->value[j], 9 );
00182 
00183         preference_array[i/2][j].tmp_fuzzy_value = 0.0f;
00184     }
00185 }
00186 
00187 //------------- End of function EnrollRes::load_db_student_pref ------//
00188 
00189 //----------- Begin of function EnrollRes::load_db_student_pref2 ------//
00193 void EnrollRes::load_db_student_pref2() {
00194     PreferenceRec2  *prefRec;
00195     Database    *dbPreference = game_set.open_db(PREFERENCE_DB2);
00196     String      tmpStr;
00197 
00198     int db_count = (short) dbPreference->rec_count();
00199 
00200     err_when( db_count != PREFERECNE_COUNT2 * (SCHOOL_CONTROL_COUNT + MAX_STUDENT_LEVEL - 1) );
00201 
00202     // make sure values of constants conformed to database column order
00203     err_when( NON_MINORITY != 0 );
00204     err_when( PUBLIC != 1 || PRIVATE != 0 );
00205 
00206     //------ read in Preference information array -------//
00207 
00208     memset( preference_array2, 0, sizeof(preference_array2));
00209 
00210     // for sl1
00211 
00212     int i, j, arrSL;
00213     char  control = PRIVATE;
00214 
00215     for( i=0; i<PREFERECNE_COUNT2*SCHOOL_CONTROL_COUNT; i++ ) {
00216         if ( i >= PREFERECNE_COUNT2 ) {
00217             control = PUBLIC;
00218             j = i - PREFERECNE_COUNT2;
00219         }
00220         else {
00221             j = i;
00222         }
00223 
00224         prefRec = (PreferenceRec2*) dbPreference->read(i+1);
00225 
00226         m.rtrim_fld(tmpStr, prefRec->weight[0], 9);
00227         if ( strcmp(tmpStr, "") != 0 )
00228             preference_array2[control][NON_MINORITY][j].apps_ratio  = (float) m.atof( prefRec->weight[0], 9 );
00229         else
00230             preference_array2[control][NON_MINORITY][j].apps_ratio  = -1.0f;
00231 
00232         m.rtrim_fld(tmpStr, prefRec->weight[1], 9);
00233         if ( strcmp(tmpStr, "") != 0 )
00234             preference_array2[control][MINORITY][j].apps_ratio      = (float) m.atof( prefRec->weight[1], 9 );
00235         else
00236             preference_array2[control][MINORITY][j].apps_ratio      = -1.0f;
00237 
00238         m.rtrim_fld(tmpStr, prefRec->weight[2], 9);
00239         if ( strcmp(tmpStr, "") != 0 )
00240             preference_array2[control][NON_MINORITY][j].yield_rate  = (float) m.atof( prefRec->weight[2], 9 );
00241         else
00242             preference_array2[control][NON_MINORITY][j].yield_rate  = -1.0f;
00243 
00244         m.rtrim_fld(tmpStr, prefRec->weight[3], 9);
00245         if ( strcmp(tmpStr, "") != 0 )
00246             preference_array2[control][MINORITY][j].yield_rate      = (float) m.atof( prefRec->weight[3], 9 );
00247         else
00248             preference_array2[control][MINORITY][j].yield_rate      = -1.0f;
00249 
00250     }
00251 
00252     // for sl2-5;  arrSL=0 -> sl2
00253 
00254     for( i=0, arrSL=-1; i<PREFERECNE_COUNT2 * (MAX_STUDENT_LEVEL - 1); i++ ) {
00255         j = i % PREFERECNE_COUNT2;
00256 
00257         if ( j==0 ) {
00258             arrSL++;    err_when(arrSL == MAX_STUDENT_LEVEL-1);
00259         }
00260 
00261         prefRec = (PreferenceRec2*) dbPreference->read(PREFERECNE_COUNT2*SCHOOL_CONTROL_COUNT + i+1);
00262 
00263         // for sl1
00264 #if(GAME_VERSION>=200)
00265         if ( i == 63 ) {                              // start of SL5, Institutional Prestige
00266             preference_array2_sls[arrSL][PRIVATE][NON_MINORITY][0]  = 0.1;
00267             preference_array2_sls[arrSL][PRIVATE][MINORITY][0]      = 0.1;
00268             preference_array2_sls[arrSL][PUBLIC][NON_MINORITY][0]   = 0.1;
00269             preference_array2_sls[arrSL][PUBLIC][MINORITY][0]     = 0.1;
00270         }
00271         else
00272             if ( i == 75 ) {                              // % of minority
00273                 preference_array2_sls[arrSL][PRIVATE][NON_MINORITY][12] = -1.0f;
00274                 preference_array2_sls[arrSL][PRIVATE][MINORITY][12]   = -1.0f;
00275                 preference_array2_sls[arrSL][PUBLIC][NON_MINORITY][12]  = -1.0f;
00276                 preference_array2_sls[arrSL][PUBLIC][MINORITY][12]      = -1.0f;
00277             }
00278             else
00279                 if ( i == 78 ) {                              // Tuition: Private Institutions
00280                     preference_array2_sls[arrSL][PRIVATE][NON_MINORITY][15] = 0.5;
00281                     preference_array2_sls[arrSL][PRIVATE][MINORITY][15]   = 0.5;
00282                     preference_array2_sls[arrSL][PUBLIC][NON_MINORITY][15]  = -1.0f;
00283                     preference_array2_sls[arrSL][PUBLIC][MINORITY][15]      = -1.0f;
00284                 }
00285                 else
00286                     if ( i == 79 ) {                              // Blended Tuition: Public Institutions
00287                         preference_array2_sls[arrSL][PRIVATE][NON_MINORITY][16] = -1.0f;
00288                         preference_array2_sls[arrSL][PRIVATE][MINORITY][16]   = -1.0f;
00289                         preference_array2_sls[arrSL][PUBLIC][NON_MINORITY][16]  = 0.3;
00290                         preference_array2_sls[arrSL][PUBLIC][MINORITY][16]      = 0.3;
00291                     }
00292                     else {
00293 #endif
00294                         m.rtrim_fld(tmpStr, prefRec->weight[0], 9);
00295                         preference_array2_sls[arrSL][PRIVATE][NON_MINORITY][j]
00296                             = ( strcmp(tmpStr, "") != 0 ) ? (float) m.atof( prefRec->weight[0], 9 ) : -1.0f;
00297 
00298                         m.rtrim_fld(tmpStr, prefRec->weight[1], 9);
00299                         preference_array2_sls[arrSL][PRIVATE][MINORITY][j]
00300                             = ( strcmp(tmpStr, "") != 0 ) ? (float) m.atof( prefRec->weight[1], 9 ) : -1.0f;
00301 
00302                         m.rtrim_fld(tmpStr, prefRec->weight[2], 9);
00303                         preference_array2_sls[arrSL][PUBLIC][NON_MINORITY][j]
00304                             = ( strcmp(tmpStr, "") != 0 ) ? (float) m.atof( prefRec->weight[2], 9 ) : -1.0f;
00305 
00306                         m.rtrim_fld(tmpStr, prefRec->weight[3], 9);
00307                         preference_array2_sls[arrSL][PUBLIC][MINORITY][j]
00308                             = ( strcmp(tmpStr, "") != 0 ) ? (float) m.atof( prefRec->weight[3], 9 ) : -1.0f;
00309 #if(GAME_VERSION>=200)
00310                     }
00311 #endif
00312     }
00313 #if(GAME_VERSION>=200)
00314     // set new variable (Percent of courses redesigned for optimal IT)
00315     // just for SL-5 Distance Learning
00316     preference_array2_sls[3][PRIVATE][NON_MINORITY][21] = 0.4;
00317     preference_array2_sls[3][PRIVATE][MINORITY][21]     = 0.4;
00318     preference_array2_sls[3][PUBLIC][NON_MINORITY][21]    = 0.6;
00319     preference_array2_sls[3][PUBLIC][MINORITY][21]      = 0.6;
00320 #endif
00321 }
00322 
00323 //------------- End of function EnrollRes::load_db_student_pref2 ------//
00324 
00325 //----------- Begin of function EnrollRes::load_db_app_yield ------//
00329 void EnrollRes::load_db_app_yield() {
00330     AppYieldRec   *appRec;
00331     Database    *dbAppYield = game_set.open_db(APP_YIELD_DB);
00332     int       varOffset, stuSubSeg, stuSeg, iSeg, i=0;
00333 
00334     int db_count = (short) dbAppYield->rec_count();
00335 
00336     err_when( db_count != STUDENT_SEGMENT_COUNT * STUDENT_SUBSEGMENT_COUNT * APP_YIELD_VAR_COUNT);
00337 
00338     //------ read in Preference information array -------//
00339 
00340     memset( app_yield_array, 0, sizeof(app_yield_array));
00341 
00342     for ( varOffset=0; varOffset<APP_YIELD_VAR_COUNT; varOffset++ )
00343         for ( stuSubSeg=0; stuSubSeg<STUDENT_SUBSEGMENT_COUNT; stuSubSeg++ )
00344             for ( stuSeg=0; stuSeg<STUDENT_SEGMENT_COUNT; stuSeg++ ) {
00345                 appRec = (AppYieldRec*) dbAppYield->read(i+1);
00346                 i++;
00347                 for ( iSeg=0; iSeg<INSTITU_SEGMENT_COUNT; iSeg++ ) {
00348                     app_yield_array[stuSubSeg][stuSeg][iSeg][varOffset]
00349                         = (short) m.atoi( appRec->count[iSeg], 9 );
00350                     err_when(app_yield_array[stuSubSeg][stuSeg][iSeg][varOffset] < 0);
00351                 }
00352             }
00353 
00354 #ifdef DEBUG_
00355     debug_msg("----- begin enroll: app_yield -----");
00356 
00357     for ( stuSubSeg=0; stuSubSeg<STUDENT_SUBSEGMENT_COUNT; stuSubSeg++ )
00358         for ( stuSeg=0; stuSeg<STUDENT_SEGMENT_COUNT; stuSeg++ ) {
00359             char str[100] = "";
00360             for ( iSeg=0; iSeg<INSTITU_SEGMENT_COUNT; iSeg++ ) {
00361                 sprintf(str, "%s, %d", str, app_yield_array[stuSubSeg][stuSeg][iSeg].apps);
00362             }
00363             debug_msg(str);
00364         }
00365     debug_msg("----- end enroll: app_yield -----");
00366 #endif
00367 }
00368 
00369 //------------- End of function EnrollRes::load_db_app_yield ------//
00370 
00371 //----------- Begin of function EnrollRes::load_db_student_talent ------//
00375 
00376 //------- static var for the 2 func below ------------//
00377 static float income_growth[STUDENT_SUBSEGMENT_COUNT][STUDENT_SEGMENT_COUNT];
00378 static float income_growth_last2[STUDENT_SUBSEGMENT_COUNT][STUDENT_SEGMENT_COUNT];
00379 
00380 void EnrollRes::load_db_student_talent() {
00381 #define TALENT_VAR_PROPERTIES_COUNT   3         // mean, sd, count
00382 
00383     TalentRec *talentRec;
00384     Database    *dbPreference = game_set.open_db(TALENT_DB);
00385 
00386     int db_count = (short) dbPreference->rec_count();
00387 
00388     err_when( db_count !=  STUDENT_SUBSEGMENT_COUNT * TALENT_INCOME_VAR_COUNT * TALENT_VAR_PROPERTIES_COUNT);
00389 
00390     //------ read in array -------//
00391 
00392     memset( talent_array, 0, sizeof(talent_array));
00393 
00394     int var, subSeg, seg, i=1;
00395 
00396     for ( subSeg=0; subSeg<STUDENT_SUBSEGMENT_COUNT; subSeg++ )
00397         for ( var=0; var<TALENT_INCOME_VAR_COUNT; var++ ) {
00398             // read average row
00399             talentRec = (TalentRec*) dbPreference->read(i++);
00400 
00401             for ( seg=0; seg<STUDENT_SEGMENT_COUNT; seg++ ) {
00402                 talent_array[subSeg][seg][var].average
00403                     = (float) m.atof( talentRec->seg[seg], 9 );
00404             }
00405 
00406             // read standard deviation row
00407             talentRec = (TalentRec*) dbPreference->read(i++);
00408 
00409             for ( seg=0; seg<STUDENT_SEGMENT_COUNT; seg++ ) {
00410                 talent_array[subSeg][seg][var].variance
00411                     = (float) m.atof( talentRec->seg[seg], 9 );
00412             }
00413 
00414             // skip the row "count" for each talent rating
00415             //talentRec = (TalentRec*) dbPreference->read(i++);
00416             i++;
00417         }
00418 
00419     // adjust the talent_array
00420     // refer to mathca cell:
00421     // "Traditional Undergraduates: sL-1: Test financial data"
00422     //
00423     // 10 years
00424     const float INCOME_UPDATE = math.safe_pow(1.04f, 10);
00425 
00426     for ( subSeg=0; subSeg<STUDENT_SUBSEGMENT_COUNT; subSeg++ ) {
00427         for ( var=0; var<TALENT_VAR_COUNT; var++ )
00428             for ( seg=0; seg<STUDENT_SEGMENT_COUNT; seg++ ) {
00429                 talent_array[subSeg][seg][var].variance
00430                     = math.safe_pow(talent_array[subSeg][seg][var].variance, 2);
00431             }
00432 
00433         for ( seg=0; seg<STUDENT_SEGMENT_COUNT; seg++ ) {
00434             talent_array[subSeg][seg][INCOME].average
00435                 *= INCOME_UPDATE;
00436             talent_array[subSeg][seg][INCOME].variance
00437                 // * INCOME_UPDATE
00438                 = math.safe_pow(talent_array[subSeg][seg][var].variance / 10, 2);
00439         }
00440     }
00441 
00442     //--------------------------//
00443 
00444     // 1027 req26.txt
00445 
00446     for ( subSeg=0; subSeg<STUDENT_SUBSEGMENT_COUNT; subSeg++ ) {
00447         for ( seg=0; seg<STUDENT_SEGMENT_COUNT; seg++ ) {
00448             income_growth[subSeg][seg] = math.get_random_snd(0.015f, PSCH_SD(.0025f));
00449             income_growth_last2[subSeg][seg] = 0;
00450         }
00451     }
00452 }
00453 
00454 //------------- End of function EnrollRes::load_db_student_talent ------//
00455 
00456 //----------- Begin of function EnrollRes::update_income ------//
00460 void EnrollRes::update_income() {
00461     // adjust this var: Talent talent_array[STUDENT_SUBSEGMENT_COUNT][STUDENT_SEGMENT_COUNT][TALENT_INCOME_VAR_COUNT];
00462     //
00463 
00464     int subSeg, seg;
00465     float inflationRate = (float) finance.inflation_rate / 100.0f;
00466 
00467     for ( subSeg=0; subSeg<STUDENT_SUBSEGMENT_COUNT; subSeg++ ) {
00468         for ( seg=0; seg<STUDENT_SEGMENT_COUNT; seg++ ) {
00469             float lastValue = income_growth[subSeg][seg];
00470 
00471             income_growth[subSeg][seg] = math.time_variation(lastValue, income_growth_last2[subSeg][seg], 0.9908f, -0.6314f, 0.003202690f);
00472             income_growth_last2[subSeg][seg] = lastValue;
00473 
00474             talent_array[subSeg][seg][INCOME].average *= (1+inflationRate+income_growth[subSeg][seg]);
00475         }
00476     }
00477 }
00478 
00479 //----------- End of function EnrollRes::update_income ------//
00480 
00481 //----------- Begin of function EnrollRes::calc_student_pref --------//
00488 void EnrollRes::calc_student_pref() {
00489     // column L
00490     // recalculate PeerSchool's properties to prefArray to speed up calculation
00491     // '10' is the additional field included in PREFERECNE_COUNT2 (pref_vars_array)
00492     // but not PREFERECNE_COUNT (prefArray)
00493     //
00494     PeerSchool* player = school_res.player_peer_school;
00495     float prefArray[PREFERECNE_COUNT];
00496     int i, j;
00497 
00498     for (j=0, i=0; j<PREFERECNE_COUNT; j++, i++) {
00499         if ( j == 10 )                                // skip in-state freshmen percent
00500             i++;
00501 
00502         prefArray[j] = player->pref_vars_array[i];
00503     }
00504 
00505     err_when( PREFERECNE_COUNT != 20 );
00506 
00507     // E129-K147: Fuzzy Logic Indices for Undergraduate Applications Ratios and Yield Rates
00508     Preference *prefPtr;
00509 
00510     for (j=0; j<PREFERECNE_COUNT; j++)
00511         for (i=0; i<INSTITU_SEGMENT_COUNT; i++) {
00512             prefPtr = (enroll_res.preference_array[j]) + i;
00513             //prefPtr++;
00514             prefPtr->tmp_fuzzy_value = (float) exp(-math.safe_pow((  math.safe_divide((prefPtr->average-prefArray[j]), prefPtr->deviation)  ), 2));
00515         }
00516 
00517     // E150-K150: weighted raw index value: update player's preference_array
00518     bool isPlayerSchoolPublic = player_school.is_public();
00519     float tmpSumOfSum = 0.0f;
00520 
00521     for (i=0; i<INSTITU_SEGMENT_COUNT; i++) {
00522         float tmpSum = 0.0f;
00523 
00524         for (j=0; j<NON_FINANCIAL_PREFERECNE_COUNT; j++) {
00525             prefPtr = (enroll_res.preference_array[j]) + i;
00526 
00527             tmpSum += prefPtr->tmp_fuzzy_value * prefPtr->weight;
00528 
00529         }
00530 
00531         err_when(tmpSum==0);
00532 
00533         for (j=NON_FINANCIAL_PREFERECNE_COUNT; j<PREFERECNE_COUNT; j+=2) {
00534             prefPtr = (enroll_res.preference_array[j]) + i;
00535 
00536             if ( isPlayerSchoolPublic )
00537                 prefPtr++;
00538 
00539             tmpSum += prefPtr->tmp_fuzzy_value * prefPtr->weight;
00540         }
00541         pref_weight_array[i] = tmpSum;
00542         tmpSumOfSum += tmpSum;
00543 
00544         err_when(tmpSumOfSum==0);
00545     }
00546 
00547     // E151-K151: calc segment weight
00548     for (i=0; i<INSTITU_SEGMENT_COUNT; i++)
00549         pref_weight_array[i] /= tmpSumOfSum;
00550 }
00551 
00552 //------------- End of function EnrollRes::calc_student_pref --------//
00553 
00554 //----------- Begin of function EnrollRes::calc_app_yield --------//
00565 void EnrollRes::calc_app_yield() {
00566     float     appYield[APP_YIELD_VAR_COUNT], totalMatrics=0;
00567     int     varOffset, stuSubSeg, stuSeg, iSeg, i=0;
00568     // short                            *shortPtr
00569     // short                    *studenCountPtr;
00570 
00571     // refer to columns BM:QR
00572     for ( stuSubSeg=0; stuSubSeg<STUDENT_SUBSEGMENT_COUNT; stuSubSeg++ )
00573         for ( stuSeg=0; stuSeg<STUDENT_SEGMENT_COUNT; stuSeg++ ) {
00574             memset(appYield, 0, sizeof(appYield));
00575             for ( varOffset=0; varOffset<APP_YIELD_VAR_COUNT; varOffset++ ) {
00576                 //studenCountPtr = &( appYieldArray[varOffset] );
00577                 for ( iSeg=0; iSeg<INSTITU_SEGMENT_COUNT; iSeg++ ) {
00578                     appYield[varOffset] += (enroll_res.app_yield_array[stuSubSeg][stuSeg][iSeg][varOffset] * pref_weight_array[iSeg]);
00579 
00580                     err_when(appYield[varOffset] < 0);
00581                 }
00582             }
00583 
00584             err_when( appYield[MATRICS] < 0.000001f || appYield[OFFERS] < 0.000001f );
00585             //err_when( appYield[OFFERS] > appYield[APPS] );    //1117
00586             err_when( appYield[MATRICS] > appYield[OFFERS] );
00587 
00588             //TO use pointer to speed it up
00589             enroll_data_sl1[stuSubSeg][stuSeg].apps_ratio = float(appYield[APPS]) / appYield[MATRICS];
00590             enroll_data_sl1[stuSubSeg][stuSeg].yield_rate = float(appYield[MATRICS]) / appYield[OFFERS];
00591             enroll_data_sl1[stuSubSeg][stuSeg].fraction_matrics = appYield[MATRICS];
00592 
00593             totalMatrics += appYield[MATRICS];
00594         }
00595 
00596     // note: apps_ratio in enroll_data is not updated yearly, it's just for init_enroll
00597     err_when(totalMatrics <= 0);
00598 
00599     for ( stuSubSeg=0; stuSubSeg<STUDENT_SUBSEGMENT_COUNT; stuSubSeg++ )
00600         for ( stuSeg=0; stuSeg<STUDENT_SEGMENT_COUNT; stuSeg++ ) {
00601             enroll_data_sl1[stuSubSeg][stuSeg].fraction_matrics /= totalMatrics;
00602         }
00603 }
00604 
00605 //------------- End of function EnrollRes::calc_app_yield --------//
00606 
00607 //------------- End of function EnrollRes::set_app_yield --------//
00608 //
00609 void EnrollRes::set_app_yield(float appMultipler, float yieldMultiplier) {
00610     int stuSubSeg, stuSeg;
00611 
00612     for ( stuSubSeg=0; stuSubSeg<STUDENT_SUBSEGMENT_COUNT; stuSubSeg++ )
00613         for ( stuSeg=0; stuSeg<STUDENT_SEGMENT_COUNT; stuSeg++ ) {
00614             enroll_data_sl1[stuSubSeg][stuSeg].apps_ratio *= appMultipler;
00615             enroll_data_sl1[stuSubSeg][stuSeg].yield_rate *= yieldMultiplier;
00616         }
00617 }
00618 
00619 //------------- End of function EnrollRes::set_app_yield --------//
00620 
00621 //----------- static variables of class PeerSchool --------//
00622 float PeerSchool::pref_vars_average_array[PREFERECNE_COUNT2];
00623 float PeerSchool::pref_vars_average_array_last[PREFERECNE_COUNT2];
00624 
00625 //----------- Begin of function PeerSchool::calc_student_pref_vars_array --------//
00633 void PeerSchool::calc_student_pref_vars_array() {
00634     if ( this != school_res.player_peer_school ) {
00635         calc_student_pref_vars_array_peer();
00636         return;
00637     }
00638 
00639     memcpy( pref_vars_array_last, pref_vars_array, sizeof(pref_vars_array) );
00640 
00641     // calculate the column Q in [HE.STU.pref.xls]Sheet1
00642     //
00643     // recalculate PeerSchool's properties to prefArray to speed up calculation
00644     // (refer to column L of [HE.initialization]stu_pref)
00645     // local var: float pref_vars_array[PREFERECNE_COUNT2];
00646 
00647     // (minor bug) the following RHSs may NOT be updated during play
00648 
00649     // assume "this" is the player_peeer_school
00650     int studentEnrollCount[MAX_STUDENT_LEVEL];
00651     int i;
00652 
00653     for ( i=0; i<MAX_STUDENT_LEVEL; i++ ) {
00654         studentEnrollCount[i] = enroll_res.student_count[i];
00655         percent_female_sl[i] = (char) enroll_res.student_female_percent[i];
00656         percent_minority_sl[i] = (char) enroll_res.student_minority_percent[i];
00657     }
00658 
00659     pref_vars_array[0] = prestige;
00660     // by 1021 email
00661     pref_vars_array[1] = (float) athletics_office.ncaa_level_value;
00662     pref_vars_array[2] = float(student_life_staff_salaries+student_life_other_expense)/(full_time_undergrad+part_time_undergrad);
00663     pref_vars_array[3] = percent_traditional_ug_in_residence_halls / 100.0f;
00664     pref_vars_array[4] = percent_get_bacc_in_5_year / 100.0f;
00665 
00666     pref_vars_array[5] = enroll_res.applications_rate[UG_TRADITION];
00667     pref_vars_array[6] = enroll_res.cur_yield_rate[UG_TRADITION];
00668     pref_vars_array[7] = float(studentEnrollCount[1]) / float(studentEnrollCount[0]+studentEnrollCount[1]);
00669 
00670     float tmpCount = 0;
00671 
00672     pref_vars_array[8] = float(studentEnrollCount[0]+studentEnrollCount[1]) / enroll_res.total_student_count;
00673     pref_vars_array[9] = float(studentEnrollCount[4]) / enroll_res.total_student_count;
00674 
00675     // the additional field included in PREFERECNE_COUNT2 but not PREFERECNE_COUNT
00676     pref_vars_array[10] = float(percent_instate_freshmen) / 100;
00677 
00678     for (i = 0, tmpCount = 0; i<MAX_STUDENT_LEVEL; i++)
00679         tmpCount += float(studentEnrollCount[i]) * percent_female_sl[i] / 100;
00680 
00681     pref_vars_array[11] = float(tmpCount) / enroll_res.total_student_count;
00682 
00683     for (i = 0, tmpCount = 0; i<MAX_STUDENT_LEVEL; i++)
00684         tmpCount += studentEnrollCount[i] * percent_minority_sl[i] / 100;
00685 
00686     pref_vars_array[12] = float(tmpCount) /  enroll_res.total_student_count;
00687     pref_vars_array[13] = doc_time_to_degree;
00688     pref_vars_array[14] = sponsored_research_rating;
00689     pref_vars_array[15] = (float) finance.tuition_rate;
00690 
00691     pref_vars_array[16] = pref_vars_array[15];
00692     pref_vars_array[17] = percent_ug_students_on_aid / 100.0f;
00693     pref_vars_array[18] = pref_vars_array[17];
00694     pref_vars_array[19] = institutional_aid_per_fte;
00695     pref_vars_array[20] = institutional_aid_per_fte;
00696 
00697     err_when( PREFERECNE_COUNT2 != 21 );
00698 
00699     for (i=0; i<PREFERECNE_COUNT2; i++)
00700         err_when( pref_vars_array[i] < 0 );
00701 
00702 }
00703 
00704 //------------- End of function PeerSchool::calc_student_pref_vars_array --------//
00705 
00706 //------------- Begin of function PeerSchool::calc_student_pref_vars_array_peer --------//
00716 void PeerSchool::calc_student_pref_vars_array_peer() {
00717     memcpy( pref_vars_array_last, pref_vars_array, sizeof(pref_vars_array) );
00718 
00719     // calculate the column Q in [HE.STU.pref.xls]Sheet1
00720     //
00721     // recalculate PeerSchool's properties to prefArray to speed up calculation
00722     // (refer to column L of [HE.initialization]stu_pref)
00723     // local var: float pref_vars_array[PREFERECNE_COUNT2];
00724 
00725     // the following RHSs may NOT be updated during play
00726 
00727     pref_vars_array[0] = prestige;
00728     pref_vars_array[1] = (float) athletics_office.ncaa_level_value;
00729 #if(GAME_VERSION>=200)
00730     pref_vars_array[2] = math.safe_divide( float(student_life_staff_salaries+student_life_other_expense), (float)full_time_undergrad+part_time_undergrad );
00731 #else
00732     pref_vars_array[2] = float(student_life_staff_salaries+student_life_other_expense)/(full_time_undergrad+part_time_undergrad);
00733 #endif
00734     pref_vars_array[3] = percent_traditional_ug_in_residence_halls / 100.0f;
00735     pref_vars_array[4] = percent_get_bacc_in_5_year / 100.0f;
00736 
00737     pref_vars_array[5] = ug_applications_rate;
00738     pref_vars_array[6] = ug_yield_rate / 100.0f;
00739 #if(GAME_VERSION>=200)
00740     pref_vars_array[7] = math.safe_divide( (float)part_time_undergrad, (float)full_time_undergrad+part_time_undergrad );
00741 #else
00742     pref_vars_array[7] = part_time_undergrad/float(full_time_undergrad+part_time_undergrad);
00743 #endif
00744 
00745     int studentEnrollCount[MAX_STUDENT_LEVEL];
00746     studentEnrollCount[0] = full_time_undergrad;
00747     studentEnrollCount[1] = part_time_undergrad;
00748     studentEnrollCount[2] = enrollment_masters;
00749     studentEnrollCount[3] = enrollment_doctoral;
00750     studentEnrollCount[4] = non_degree_seeking;
00751 
00752     float studentCount = 0.0f;
00753     int i, tmpCount=0;
00754     for (i=0; i<MAX_STUDENT_LEVEL; i++)
00755         studentCount += (float) studentEnrollCount[i];
00756 
00757 #if(GAME_VERSION>=200)
00758     pref_vars_array[8] = math.safe_divide( (int)(full_time_undergrad+part_time_undergrad), (int)studentCount );
00759     pref_vars_array[9] = math.safe_divide( (int)non_degree_seeking, (int)studentCount );
00760 #else
00761     pref_vars_array[8] = (full_time_undergrad+part_time_undergrad) / studentCount;
00762     pref_vars_array[9] = non_degree_seeking / studentCount;
00763 #endif
00764 
00765     // the additional field included in PREFERECNE_COUNT2 but not PREFERECNE_COUNT
00766     pref_vars_array[10] = percent_instate_freshmen;
00767 
00768     for (i=0; i<MAX_STUDENT_LEVEL; i++)
00769         tmpCount += studentEnrollCount[i] * percent_female_sl[i] / 100;
00770 
00771 #if(GAME_VERSION>=200)
00772     pref_vars_array[11] = math.safe_divide( (int)tmpCount, (int)studentCount );
00773 #else
00774     pref_vars_array[11] = tmpCount / studentCount;
00775 #endif
00776 
00777     for (i=0, tmpCount = 0; i<MAX_STUDENT_LEVEL; i++)
00778         tmpCount += studentEnrollCount[i] * percent_minority_sl[i] / 100;
00779 
00780 #if(GAME_VERSION>=200)
00781     pref_vars_array[12] = math.safe_divide( (int)tmpCount, (int)studentCount );
00782 #else
00783     pref_vars_array[12] = tmpCount / studentCount;
00784 #endif
00785     pref_vars_array[13] = doc_time_to_degree;
00786     pref_vars_array[14] = sponsored_research_rating;
00787     pref_vars_array[15] = (float) tuition_rate;
00788 
00789     pref_vars_array[16] = pref_vars_array[15];
00790     pref_vars_array[17] = percent_ug_students_on_aid / 100.0f;
00791     pref_vars_array[18] = pref_vars_array[17];
00792     pref_vars_array[19] = institutional_aid_per_fte;
00793     pref_vars_array[20] = institutional_aid_per_fte;
00794 
00795     err_when( PREFERECNE_COUNT2 != 21 );
00796 
00797     for (i=0; i<PREFERECNE_COUNT2; i++)
00798         err_when( pref_vars_array[i] < 0 );
00799 }
00800 
00801 //------------- End of function PeerSchool::calc_student_pref_vars_array_peer --------//
00802 
00803 //----------- Begin of static function PeerSchool::calc_student_pref_vars_average_array --------//
00804 //
00805 // Refer to [HE.STU.pref.xls]Sheet1
00806 //
00807 // Calc values for column Q for PGI and peer schools
00808 //
00809 void PeerSchool::calc_student_pref_vars_average_array() {
00810     memcpy( pref_vars_average_array_last, pref_vars_average_array, sizeof(pref_vars_average_array) );
00811 
00812     float sum;
00813     short psCount = school_res.peer_school_count;
00814 
00815     // pref_vars_average_array is static
00816     //
00817     for (int var=0; var<PREFERECNE_COUNT2; var++) {
00818         sum = 0.0f;
00819 
00820         for (int i=0; i<psCount; i++) {
00821             PeerSchool *ps = &(school_res.peer_school_array[i]);
00822 
00823             if ( ps != school_res.player_peer_school )
00824 
00825                 sum += ps->pref_vars_array[var];
00826         }
00827 
00828         pref_vars_average_array[var] = sum / psCount;
00829     }
00830 }
00831 
00832 //------------- End of static function PeerSchool::calc_student_pref_vars_average_array --------//
00833 
00834 //----------- Begin of function EnrollRes::calc_enroll_applications --------//
00847 void EnrollRes::calc_enroll_applications() {
00848     const int sl = 0;
00849     float prefVarsArray[PREFERECNE_COUNT2];         // column Q
00850     int i, j;
00851 
00852     // calc values for column Q
00853     // The data in column Q represent
00854     // the "ratio of the variable for the PGI to the average of the same variable
00855     // for the peer institutions." (from email req11_enroll.txt)
00856     //
00857     PeerSchool* player = school_res.player_peer_school;
00858     memcpy(prefVarsArray, player->pref_vars_array, sizeof(prefVarsArray));
00859 
00860     for (i=0; i<PREFERECNE_COUNT2; i++) {
00861         // (* uses lagged financial aid variables; current values for all else *)
00862         //
00863         if ( i < PREFERECNE_COUNT2 - 4 )
00864             prefVarsArray[i] = math.safe_divide(prefVarsArray[i], PeerSchool::pref_vars_average_array[i]);
00865         else
00866             prefVarsArray[i] = math.safe_divide(player->pref_vars_array_last[i], PeerSchool::pref_vars_average_array_last[i]);
00867     }
00868 
00869     // calc values for column R
00870     //
00871     bool isPublic = player_school.is_public();
00872     float finalRatio[MINORITY_GROUP_COUNT];
00873     float tmpRatio;
00874     float tmp, sign;
00875 
00876     for (j=0; j<MINORITY_GROUP_COUNT; j++) {
00877         finalRatio[j] = 1;
00878 
00879         for (i=0; i<PREFERECNE_COUNT2; i++) {
00880             sign = (pref_special_case(i))? -1.0f: 1.0f;
00881 
00882             // 1
00883             tmp = enroll_res.preference_array2[isPublic][j][i].apps_ratio;
00884 
00885             if ( tmp <= 0.0 || prefVarsArray[i] == 0)
00886                 tmpRatio = 1.0f;
00887             else
00888                 tmpRatio = math.safe_pow(prefVarsArray[i], sign * tmp);
00889 
00890             // 2
00891             finalRatio[j] *= tmpRatio;
00892 
00893         }
00894 
00895         if ( !(1+ (float) exp(-s_slope*(finalRatio[j]-1))) )
00896             finalRatio[j] = 1;
00897         else
00898             finalRatio[j] = s_lower_bound+(s_upper_bound-s_lower_bound)/(1+ (float) exp(-s_slope*(finalRatio[j]-1)));
00899 
00900         err_when( finalRatio[j] < 0 );
00901     }
00902 
00903     // refer to mathca code only this part
00904     //
00905     int minorGroup, stuSubSeg, stuSeg;
00906     EnrollDataSL1* ed;
00907 
00908     total_applications[sl] = 0;
00909 
00910     finalRatio[MINORITY] *= app_multiplier[sl];
00911     finalRatio[NON_MINORITY] *= app_multiplier[sl];
00912 
00913     //----------------//
00914 
00915     //  total_applications[sl]=0;       // ## CHWG062199
00916 
00917     for ( stuSubSeg=0; stuSubSeg<STUDENT_SUBSEGMENT_COUNT; stuSubSeg++ ) {
00918         if ( is_minority_group(stuSubSeg) )
00919             minorGroup = MINORITY;
00920         else
00921             minorGroup = NON_MINORITY;
00922 
00923         for ( stuSeg=0; stuSeg<STUDENT_SEGMENT_COUNT; stuSeg++ ) {
00924             ed = &enroll_data_sl1[stuSubSeg][stuSeg];
00925 
00926             ed->applications
00927                 = int( (1.0f-apps_latency[sl]) * math.get_random_snd(chance_avg, PSCH_SD(chance_sd), true)
00928                        * finalRatio[minorGroup] * ed->base_apps
00929                        // + 0.5 for float-int rounding
00930                        + apps_latency[sl] * ed->applications + 0.5);
00931 
00932             err_when(ed->applications < 0);
00933             total_applications[sl] += ed->applications;
00934         }
00935     }
00936 }
00937 
00938 //---------------------////---------------------////---------------------//
00939 void EnrollRes::calc_enroll_matriculations() {
00940     const int sl = 0;                               //## chea 260899 try to use loop below
00941 
00942     float prefVarsArray[PREFERECNE_COUNT2];         // column Q
00943     int i, j;
00944 
00945     // calc values for column Q
00946     // The data in column Q represent
00947     // the "ratio of the variable for the PGI to the average of the same variable
00948     // for the peer institutions." (from email req11_enroll.txt)
00949     //
00950     PeerSchool* player = school_res.player_peer_school;
00951     memcpy(prefVarsArray, player->pref_vars_array, sizeof(prefVarsArray));
00952 
00953     for (i=0; i<PREFERECNE_COUNT2; i++) {
00954         // (* uses current values for all variables *)
00955         //
00956         prefVarsArray[i] = math.safe_divide(prefVarsArray[i], PeerSchool::pref_vars_average_array[i]);
00957     }
00958 
00959     // calc values for column R
00960     //
00961     bool isPublic = player_school.is_public();
00962     float finalRatio[MINORITY_GROUP_COUNT];
00963     float tmpRatio;
00964     float tmp, sign;
00965 
00966     for (j=0; j<MINORITY_GROUP_COUNT; j++) {
00967         finalRatio[j] = 1;
00968 
00969         for (i=0; i<PREFERECNE_COUNT2; i++) {
00970             sign = (pref_special_case(i))? -1.0f: 1.0f;
00971 
00972             // 1
00973             //tmp = enroll_res.preference_array2[isPublic][j][i].apps_ratio;
00974             tmp = enroll_res.preference_array2[isPublic][j][i].yield_rate;
00975 
00976             if ( tmp <= 0.0 )                           // empty entry in database
00977                 tmpRatio = 1;
00978             else if ( prefVarsArray[i] == 0 )           // 0.75: from mathca code
00979                 tmpRatio = 0.75f;
00980             else {
00981                 if ( i < PREFERECNE_COUNT2 - 4 )
00982                     tmpRatio = (float) math.safe_pow(prefVarsArray[i], sign * tmp);
00983                 else if ( i < PREFERECNE_COUNT2 - 2 )
00984                     tmpRatio = (float) math.safe_pow(math.safe_divide(fraction_on_aid[j], prefVarsArray[i]), sign * tmp);
00985                 else
00986                     tmpRatio = (float) math.safe_pow(math.safe_divide(float(average_aid[j]), prefVarsArray[i]), sign * tmp);
00987             }
00988 
00989             if ( tmpRatio < -100 || tmpRatio > 100 )    // fix bug on fly
00990                 tmpRatio = 1;
00991 
00992             // 2
00993             finalRatio[j] *= tmpRatio;
00994         }
00995 
00996         if ( !(1+ (float) exp(-s_slope*(finalRatio[j]-1))) )
00997             finalRatio[j] = 1;
00998         else
00999             finalRatio[j] = s_lower_bound+(s_upper_bound-s_lower_bound)/(1+ (float) exp(-s_slope*(finalRatio[j]-1)));
01000     }
01001 
01002     // refer to mathca code only for this part
01003     //
01004     int minorGroup, stuSubSeg, stuSeg;
01005     EnrollDataSL1* ed; {
01006 
01007         // BUG_HERE
01008         // for statement is missing in the original version..//## chwg0628      ..
01009         //              for(sl=0;sl<MAX_STUDENT_LEVEL;sl++)
01010         //
01011         //      for(int sl=0;sl<MAX_STUDENT_LEVEL;sl++)  //## chea 260899 try adding
01012         total_matrics[sl] = 0;
01013         matrics_top_athletes = 0; male_matrics_top_athletes = 0;
01014 
01015         for ( stuSubSeg=0; stuSubSeg<STUDENT_SUBSEGMENT_COUNT; stuSubSeg++ ) {
01016             if ( is_minority_group(stuSubSeg) )
01017                 minorGroup = MINORITY;
01018             else
01019                 minorGroup = NON_MINORITY;
01020 
01021             for ( stuSeg=0; stuSeg<STUDENT_SEGMENT_COUNT; stuSeg++ ) {
01022                 ed = &enroll_data_sl1[stuSubSeg][stuSeg];
01023 
01024                 ed->yield_rate
01025                     = (1.0f-yield_latency[sl]) * math.get_random_snd(chance_avg, PSCH_SD(chance_sd), true)
01026                     * yield_multiplier[sl] * finalRatio[minorGroup] * ed->base_yield_rate
01027                     + yield_latency[sl] * ed->yield_rate;
01028 
01029                 // make yield_rate within [1:0]
01030                 //min & max bug chea
01031                 ed->yield_rate = max(0.0f, min(1.0f, ed->yield_rate));
01032 
01033                 // calc matriculations
01034                 // + 0.5 for float-int rounding
01035                 ed->matrics =  int(ed->yield_rate * ed->offers+ 0.5);
01036 
01037                 // calc total matriculations
01038                 total_matrics[sl] += ed->matrics;
01039             }
01040 
01041             // calc number of top athletes *newly* recruited
01042             // which is the number of matriculants in stdent segment 4 (athlete)
01043             matrics_top_athletes += enroll_data_sl1[stuSubSeg][3].matrics;
01044 
01045             if(is_male_group(stuSubSeg))
01046                 male_matrics_top_athletes += enroll_data_sl1[stuSubSeg][3].matrics;
01047         }
01048     }
01049 
01050 #if(GAME_VERSION>=200)
01051     // do again to adjust total_matrics to target_enrollment
01052     if( (!info.prerun_year || info.prerun_year && info.game_year > 1 ) && total_matrics[sl] >= 10 ) {
01053         int oldTotalMatrics = total_matrics[sl];
01054         int targetIntake = target_student_intake[sl];
01055 
01056         total_matrics[sl] = 0;
01057         matrics_top_athletes = 0; male_matrics_top_athletes = 0;
01058 
01059         for ( stuSubSeg=0; stuSubSeg<STUDENT_SUBSEGMENT_COUNT; stuSubSeg++ ) {
01060             if ( is_minority_group(stuSubSeg) )
01061                 minorGroup = MINORITY;
01062             else
01063                 minorGroup = NON_MINORITY;
01064 
01065             for ( stuSeg=0; stuSeg<STUDENT_SEGMENT_COUNT; stuSeg++ ) {
01066                 ed = &enroll_data_sl1[stuSubSeg][stuSeg];
01067 
01068                 ed->yield_rate = ed->yield_rate * targetIntake / oldTotalMatrics;
01069 
01070                 // make yield_rate within [1:0]
01071                 //min & max bug chea
01072                 ed->yield_rate = max(0.0f, min(1.0f, ed->yield_rate));
01073 
01074                 // calc matriculations
01075                 // + 0.5 for float-int rounding
01076                 ed->matrics =  int(ed->yield_rate * ed->offers+ 0.5);
01077 
01078                 // calc total matriculations
01079                 total_matrics[sl] += ed->matrics;
01080             }
01081 
01082             // calc number of top athletes *newly* recruited
01083             // which is the number of matriculants in stdent segment 4 (athlete)
01084             matrics_top_athletes += enroll_data_sl1[stuSubSeg][3].matrics;
01085 
01086             if(is_male_group(stuSubSeg))
01087                 male_matrics_top_athletes += enroll_data_sl1[stuSubSeg][3].matrics;
01088         }
01089     }
01090 #endif
01091 
01092     for ( stuSubSeg=0; stuSubSeg<STUDENT_SUBSEGMENT_COUNT; stuSubSeg++ ) {
01093         for ( stuSeg=0; stuSeg<STUDENT_SEGMENT_COUNT; stuSeg++ ) {
01094             ed = &enroll_data_sl1[stuSubSeg][stuSeg];
01095 
01096             if ( total_matrics[sl] > 0 )
01097                 ed->fraction_matrics = float(ed->matrics) / total_matrics[sl];
01098             else
01099                 ed->fraction_matrics = 0;
01100         }
01101     }
01102 }
01103 
01104 //------------- End of function EnrollRes::calc_enroll_matriculations --------//
01105 //------------- End of function EnrollRes::calc_enroll_applications --------//
01106 
01107 //----------- Begin of function EnrollRes::calc_enroll_offers --------//
01112 void EnrollRes::calc_enroll_offers() {
01113     // for sl1 temporarily
01114     const int sl = 0;
01115     int stuSubSeg, stuSeg;
01116     EnrollDataSL1* ed;
01117     float sum=0;
01118     total_offers[sl] = 0;
01119 
01120     //PeerSchool* player = school_res.player_peer_school;
01121     int targetIntake = target_student_intake[sl];
01122 
01123     // calc sum
01124     for ( stuSubSeg=0; stuSubSeg<STUDENT_SUBSEGMENT_COUNT; stuSubSeg++ )
01125         for ( stuSeg=0; stuSeg<STUDENT_SEGMENT_COUNT; stuSeg++ ) {
01126             ed = &enroll_data_sl1[stuSubSeg][stuSeg];
01127             sum += ed->yield_rate * ed->applications;
01128         }
01129 
01130     // check the calculated sum: (* If applications allow selectivity do QP, else admit all applicants. *)
01131     if ( sum <= targetIntake ) {
01132         // admit all applicants
01133         //
01134         for ( stuSubSeg=0; stuSubSeg<STUDENT_SUBSEGMENT_COUNT; stuSubSeg++ )
01135             for ( stuSeg=0; stuSeg<STUDENT_SEGMENT_COUNT; stuSeg++ ) {
01136                 ed = &enroll_data_sl1[stuSubSeg][stuSeg];
01137                 ed->offers = ed->applications;
01138                 total_offers[sl] += ed->offers;
01139             }
01140     }
01141     else {
01142         // use quadratic program to solve
01143         //
01144         const int size = STUDENT_SUBSEGMENT_COUNT*STUDENT_SEGMENT_COUNT;
01145 
01146         DiagonalMatrix  mQ(size);
01147         ColumnVector  mQdiag(size);
01148         DiagonalMatrix I(size);       I = 1;
01149         Matrix mA = I;
01150         RowVector vA(size);
01151         ColumnVector  vc(size);
01152         ColumnVector  vb(size+1);                     //bug
01153         ColumnVector  vtmp(1);        vtmp(1) = targetIntake;
01154         ColumnVector  vOffers(size);
01155 
01156         const int K_FACTOR = 5;
01157         int i=1;
01158 
01159         // init mQdiag, vA, vc
01160         for ( stuSubSeg=0; stuSubSeg<STUDENT_SUBSEGMENT_COUNT; stuSubSeg++ )
01161             for ( stuSeg=0; stuSeg<STUDENT_SEGMENT_COUNT; stuSeg++ ) {
01162                 ed = &enroll_data_sl1[stuSubSeg][stuSeg];
01163                 mQdiag(i) = ed->applications;
01164                 vA(i) = ed->yield_rate;
01165                 vc(i) = - ed->util - K_FACTOR;
01166                 i++;
01167             }
01168 
01169         // init mQ, mA, vb
01170         vb = mQdiag & vtmp;
01171         mA &= vA;
01172         mA *= -1; vb *= -1;
01173 
01174         for (i=1; i<=size; i++)
01175             mQdiag(i) = 2 * K_FACTOR / max(mQdiag(i), 0.001);
01176         mQ.set_diagonal(mQdiag);
01177 
01178         // here the main call
01179         if ( !LinearAlgebra::quadratic_prog(vc,mQ,mA,vb,vOffers) ) {
01180             vOffers = 0;
01181         }
01182 
01183         // "Partition" vOffers (a list) to ed->offers (list in list)
01184         int offs;
01185         i =1;
01186 
01187         for ( stuSubSeg=0; stuSubSeg<STUDENT_SUBSEGMENT_COUNT; stuSubSeg++ )
01188             for ( stuSeg=0; stuSeg<STUDENT_SEGMENT_COUNT; stuSeg++ ) {
01189                 offs = enroll_data_sl1[stuSubSeg][stuSeg].offers = int( vOffers(i++) +0.5);
01190                 total_offers[sl] += offs;
01191             }
01192     }
01193     /*
01194       y as prior  year's yield rates
01195       z as number of applications
01196       eU is expected (average)  utility
01197     */
01198 }
01199 
01200 //------------- End of function EnrollRes::calc_enroll_offers --------//
01201 
01202 //----------- Begin of function PeerSchool::calc_enroll_aid --------//
01211 void EnrollRes::calc_enroll_aid() {
01212     // for sl1 temporarily
01213     const int sl = 0;
01214 
01215     //-------------------//
01216     //---- Need Aid -----//
01217     //-------------------//
01218 
01219     float x = 60, lastDeviate, deviate;
01220     float inc = x / 100.f;
01221 
01222     // nH = FindMinimum[(needFrObj[sL1,x]-frOfTradUGsWithNeed)^2,{x,60}][[2,1,2]];
01223     // FindMinimum is used in lieu of Golden Section
01224     //
01225 
01226     if ( calc_need_aid(x+inc) > calc_need_aid(x-inc) )
01227         inc *= -1;
01228 
01229     deviate = calc_need_aid(x);
01230 
01231     do {
01232         x += inc;
01233         lastDeviate = deviate;
01234         deviate = calc_need_aid(x);
01235     }
01236     while ( deviate < lastDeviate && deviate > 0 );
01237 
01238     need_upper = x;
01239     need_lower = need_upper - max_aid;
01240 
01241     //-------------------//
01242     //---- Merit Aid ----//
01243     //-------------------//
01244 
01245     adjust_fraction_merit_aid(fraction_sl1_offered_merit_aid);
01246 
01247     // mL = FindMinimum[(meritFrObj[sL1,x]-frStudentsOfferedMeritAid)^2,{x,5}][[2,1,2]];
01248     x = 5;
01249     inc = x / 100.f;
01250 
01251     if ( calc_merit_aid(x+inc, fraction_sl1_offered_merit_aid)
01252          > calc_merit_aid(x-inc, fraction_sl1_offered_merit_aid) )
01253         inc *= -1;
01254 
01255     deviate = calc_merit_aid(x, fraction_sl1_offered_merit_aid);
01256 
01257     do {
01258         x += inc;
01259         lastDeviate = deviate;
01260         deviate = calc_merit_aid(x, fraction_sl1_offered_merit_aid);
01261     }
01262     while ( deviate < lastDeviate && deviate > 0 );
01263 
01264     merit_lower[sl] = x;
01265 
01266     // mH = FindMinimum[(meritFrObj[sL1,x]-frMeritTop)^2,{x,6}][[2,1,2]];
01267     x = 6;
01268     inc = x / 100.f;
01269 
01270     if ( calc_merit_aid(x+inc, fraction_merit_top)
01271          > calc_merit_aid(x-inc, fraction_merit_top) )
01272         inc *= -1;
01273 
01274     deviate = calc_merit_aid(x, fraction_merit_top);
01275 
01276     do {
01277         x += inc;
01278         lastDeviate = deviate;
01279         deviate = calc_merit_aid(x, fraction_merit_top);
01280     }
01281     while ( deviate < lastDeviate && deviate > 0 );
01282 
01283     merit_upper[sl] = x;
01284 }
01285 
01286 //------------- End of function EnrollRes::calc_enroll_aid --------//
01287 
01288 //----------- Begin of function EnrollRes::calc_need_aid --------//
01293 float EnrollRes::calc_need_aid(float aid) {
01294     // for sl1 temporarily
01295     const int sl = 0;
01296     PeerSchool* player = school_res.player_peer_school;
01297 
01298     // (* Equals the max of % stu with need and % with need given need aid (cols DR & DS);
01299     //  taking the max is and approximation to mitigate data problems *)
01300 
01301     //min & max bug chea
01302     const float frOfTradUGsWithNeed = max(player->percent_freshmen_with_need, (float)(player->freshmen_offered_aid))  / 100.0f;
01303 
01304     // constant mulitpliers
01305     // refer also to "Genral: helper function: Minority, athletics, and non-traditional multipliers"
01306 
01307     float deviate = 0, cdfTmp;
01308 
01309     float aidMinMultiplier;
01310     int subSeg, seg;
01311     //EnrollDataSL1     *ed;
01312     Talent    *talentPtr;
01313 
01314     for ( subSeg=0; subSeg<STUDENT_SUBSEGMENT_COUNT; subSeg++ ) {
01315         if ( subSeg == NONMINORITY_MALE || subSeg == NONMINORITY_FEMALE )
01316             aidMinMultiplier = 1.0f;
01317         else
01318             aidMinMultiplier = aidMinMultipliers[minority_aid_special];
01319 
01320         for ( seg=0; seg<STUDENT_SEGMENT_COUNT; seg++ ) {
01321             //ed = &enroll_data_sl1[subSeg][seg];
01322             talentPtr = &(enroll_res.talent_array[subSeg][seg][INCOME]);
01323 
01324             cdfTmp = math.get_random_gamma_CDF( aidMinMultiplier * talentPtr->average,
01325                                                 PSCH_SD(talentPtr->variance), aid );
01326             deviate += cdfTmp * enroll_data_sl1[subSeg][seg].fraction_matrics;
01327         }
01328     }
01329 
01330     return math.safe_pow(deviate - frOfTradUGsWithNeed, 2);
01331 
01332     /*
01333       nH = FindMinimum[(needFrObj[sL1,x]-frOfTradUGsWithNeed)^2,{x,60}][[2,1,2]];
01334 
01335       nL = nH-maxAid;
01336 
01337       needFrObj[sL1,nH_] := Plus@@Flatten[needFrObj[sL1,nH,#]&/@gegs];
01338       needFrObj[sL1,nH_,geg_] := With[{cdfTmp = cdf[inc,geg,nH]},
01339       cdfTmp[[#]]*frPriorMatrics[geg][[#]]&/@Range[7]];
01340 
01341       cdf[var_,geg_,x_] :=
01342       gammaCDF[minMultF[aid,geg]*means[var,geg][[#]],
01343       variances[var,geg][[#]],
01344       x]&/@Range[7];
01345     */
01346 }
01347 
01348 //------------- End of function EnrollRes::calc_need_aid --------//
01349 
01350 //----------- Begin of function EnrollRes::calc_merit_aid --------//
01355 float EnrollRes::calc_merit_aid(float aid, float base) {
01356     // for sl1 temporarily
01357     const int sl = 0;
01358 
01359     // constant mulitpliers
01360     // refer also to "Genral: helper function: Minority, athletics, and non-traditional multipliers"
01361 
01362     float deviate = 0, cdfTmp;
01363 
01364     float aidMinMultiplier;
01365     int subSeg, seg;
01366     EnrollDataSL1 *ed;
01367     //Talent            *talentPtr;
01368 
01369     for ( subSeg=0; subSeg<STUDENT_SUBSEGMENT_COUNT; subSeg++ ) {
01370         if ( subSeg == NONMINORITY_MALE || subSeg == NONMINORITY_FEMALE )
01371             aidMinMultiplier = 1.0f;
01372         else
01373             aidMinMultiplier = aidMinMultipliers[minority_aid_special];
01374 
01375         for ( seg=0; seg<STUDENT_SEGMENT_COUNT; seg++ ) {
01376             ed = &enroll_data_sl1[subSeg][seg];
01377 
01378             cdfTmp = 1 - math.get_random_gamma_CDF( aidMinMultiplier * ed->util,
01379                                                     PSCH_SD(ed->util_variance), aid );
01380 
01381             deviate += cdfTmp * enroll_data_sl1[subSeg][seg].fraction_matrics;
01382         }
01383     }
01384 
01385     return math.safe_pow(deviate - base, 2);
01386 
01387     /*  
01388         meritFrObj[sL1,mL_] := Plus@@Flatten[meritFrObj[sL1,mL,#]&/@gegs];
01389         meritFrObj[sL1,mL_,geg_] := With[{cdfTmp = 1-cdf[util,geg,mL]},
01390         cdfTmp[[#]]*frPriorMatrics[geg][[#]]&/@Range[7]];
01391     */
01392 }
01393 
01394 //------------- End of function EnrollRes::calc_merit_aid --------//
01395 
01396 //----------- Begin of function EnrollRes::player_change_offers_priority --------//
01402 void EnrollRes::player_change_offers_priority() {
01403     // for sl1 temporarily
01404     const int sl = 0;
01405 
01406     // constant mulitpliers
01407     // refer also to "Genral: helper function: Minority, athletics, and non-traditional multipliers"
01408     //
01409     // (* these respresent the "boost" *)
01410     const float admMinMultipliers[PRIORITY_LEVEL_COUNT] = {
01411         1.0f, 2.0f, 3.0f
01412     };
01413 
01414     int subSeg, seg, var;
01415     float admMinMultiplier;
01416     EnrollDataSL1 *ed;
01417 
01418     // update utility on player input
01419     //
01420     for ( subSeg=0; subSeg<STUDENT_SUBSEGMENT_COUNT; subSeg++ ) {
01421         if ( subSeg == NONMINORITY_MALE || subSeg == NONMINORITY_FEMALE )
01422             admMinMultiplier = 1.0f;
01423         else
01424             admMinMultiplier = admMinMultipliers[minority_offers_special];
01425 
01426         for ( seg=0; seg<STUDENT_SEGMENT_COUNT; seg++ ) {
01427             ed = &enroll_data_sl1[subSeg][seg];
01428             ed->util = ed->util_variance = 0.0f;
01429 
01430             for ( var=0; var<TALENT_VAR_COUNT; var++ ) {
01431                 ed->util += float(offers_priority[var]) / MAX_TALENT_PRIORITY_LEVEL * admMinMultiplier * enroll_res.talent_array[subSeg][seg][var].average;
01432                 ed->util_variance += math.safe_pow(offers_priority[var] / MAX_TALENT_PRIORITY_LEVEL,2) * enroll_res.talent_array[subSeg][seg][var].variance;
01433             }
01434         }
01435     }
01436 }
01437 
01438 //------------- End of function EnrollRes::player_change_offers_priority --------//
01439 
01440 //----------- Begin of function EnrollRes::calc_doctoral_intake_target --------//
01442 void EnrollRes::calc_doctoral_intake_target() {
01443     // 0113
01444     if ( player_school.doctoral_program_intensity == 0 ) {
01445         target_student_intake[DOCTOR] = 0;
01446         return;
01447     }
01448 
01449     int i,j;
01450     int targetTotal = 0;
01451     CourseArray* courArr;
01452     Department* deptPtr;
01453 
01454     for ( i=department_array.size(); i>0; i-- ) {
01455         if ( department_array.is_deleted(i) )
01456             continue;
01457 
01458         deptPtr = department_array[i];
01459 
01460         int totalBreakoutSections = 0;
01461         courArr = &(department_array[i]->course_array);
01462 
01463         for (j=courArr->size(); j>0; j--) {
01464             if ( courArr->operator[](j)->teaching_method == BREAKOUT_LAB )
01465                 totalBreakoutSections++;
01466         }
01467 
01468         targetTotal += (int) max(deptPtr->doctors_per_research_dollar * deptPtr->total_research_dollar_direct * 1000,
01469                                  deptPtr->init_doctor_count + deptPtr->breakout_section_by_doctor * (totalBreakoutSections - deptPtr->init_breakout_section_count));
01470     }
01471 
01472     target_student_intake[DOCTOR] = max(0, targetTotal - student_count[DOCTOR]);
01473 
01474     if ( target_student_intake[DOCTOR] > 3000 )
01475         target_student_intake[DOCTOR] = 3000;         // possibly above has bug
01476     //  else if ( target_student_intake[DOCTOR] <= 0 )
01477     //          target_student_intake[DOCTOR] = target_student_intake[MASTER];
01478 
01479     err_when(targetTotal < 0);
01480 
01481     //-------- fix: use the updated target_student_intake[] to recalculate base_apps --------//
01482 
01483     if( info.prerun_year==1 ) {
01484         EnrollData* edSL;
01485         int sl=3;
01486 
01487         // 0.3 -> 30%
01488         float studentGenderPct[STUDENT_SUBSEGMENT_COUNT];
01489 
01490         err_when(GENDER_ETHNIC_TYPE_COUNT != STUDENT_SUBSEGMENT_COUNT);
01491         float femalePercent = student_female_percent[sl] / 100.0f;
01492         float minorityPercent = student_minority_percent[sl] / 100.0f;
01493 
01494         //askbill inital gender percent affect future enrollment?  BUG? = 0 when sl=5
01495         studentGenderPct[MINORITY_FEMALE] = femalePercent*minorityPercent;
01496         studentGenderPct[NONMINORITY_FEMALE] = femalePercent*(1.0f - minorityPercent);
01497         studentGenderPct[MINORITY_MALE] = (1.0f - femalePercent)*minorityPercent;
01498         studentGenderPct[NONMINORITY_MALE] = (1.0f - femalePercent)*(1.0f - minorityPercent);
01499 
01500         for ( int subSeg=0; subSeg<STUDENT_SUBSEGMENT_COUNT; subSeg++ ) {
01501             //--------- calc enroll_data_sls[][].apps_ratio, applications and conversion_rate ---------//
01502             edSL = &enroll_data_sls[sl-1][subSeg];
01503 
01504             edSL->base_apps
01505                 // 0.5: rounding
01506                 = int(edSL->apps_ratio * studentGenderPct[subSeg] * target_student_intake[sl] + 0.5);
01507         }
01508     }
01509 }
01510 
01511 //------------- End of function EnrollRes::calc_doctoral_intake_target --------//
01512 
01513 //----------- Begin of function EnrollRes::calc_app_multiplier --------//
01515 void EnrollRes::calc_app_multiplier(char sl) {
01516     const int VAR_COUNT = 3;
01517     float input[VAR_COUNT];
01518     int i;
01519 
01520     err_when(UG_TRADITION != 0);
01521     err_when(sl>=MAX_STUDENT_LEVEL);
01522 
01523     if ( sl == DISTANCE_LEARN ) {
01524         float in=0;
01525 
01526         for (int m=THIS_MONTH; m>=THIS_MONTH-info.graph_month_passed+1; m--)
01527             in += library_tech_office.tech_utilization_history[m];
01528 
01529         //## org.
01530         in = math.single_response_func(0.0f, 1.5f, 10.0f, 5.0f, in/100);
01531 
01532         //              app_multiplier[sl] = math.latency_func(0.3f, app_multiplier[sl], in);
01533         //## chea 300899 change latency_func(HE.RespF_Defs.Rev 230899 E-mail)
01534         app_multiplier[sl] = player_school.latency_func(0.25f, app_multiplier[sl], in);
01535 
01536     }
01537     else {
01538         // Applications multiplier: on-campus students // 1009 response_func
01539         //
01540 
01541         memset(input, 0, sizeof(input));
01542 
01543         //-------------------//
01544         input[0] = school_res.player_peer_school->prestige;
01545 
01546         //-------------------//
01547         // (minor bug) should depend on [sl]
01548         input[1] = player_school.satisfaction_overall[THIS_MONTH];
01549 
01550         //-------------------//
01551         int totalTargetIntake = 0;
01552 
01553         for (i=0; i<MAX_STUDENT_LEVEL; i++)
01554             totalTargetIntake += target_student_intake[i];
01555 
01556         //min & max bug chea
01557         input[2] = max(1000.0f, float(finance.projected_expense_array[AC_ENROLLMENT_MANAGEMENT].this_year.total)) / totalTargetIntake;
01558 
01559         if ( input[2] == 0 )
01560             input[2] = 1;
01561 
01562         input[2] *= (float) finance.cost_rise_policy_array[PL_ENROLLMENT_MANAGEMENT].penalty_multiplier1;
01563 
01564         //-------------------//
01565         float weight[VAR_COUNT] = { 0.35f, 0.3f, 0.35f };
01566         float newValue = 0;
01567         for (i=0; i<VAR_COUNT; i++)
01568             newValue += input[i] * weight[i];
01569 
01570         //-------------------//
01571 
01572         //## chea 300899 change latency_func(HE.RespF_Defs.Rev 230899 E-mail)
01573         app_multiplier[sl] = max(0.7f,min(1.3f, player_school.latency_func(0.8f, app_multiplier[sl], newValue)));
01574     }
01575 
01576     //-------------------//
01577     // calc yield_multiplier
01578     //-------------------//
01579     float weight[VAR_COUNT] = { 0.35f, 0.5f, 0.15f};
01580     float newValue = 0;
01581 
01582     for (i=0; i<VAR_COUNT; i++)
01583         newValue += input[i] * weight[i];
01584 
01585     //-------------------//
01586 
01587     //## chea 300899 change latency_func(HE.RespF_Defs.Rev 230899 E-mail)
01588     yield_multiplier[sl] = max(0.7f,min(1.3f, player_school.latency_func(0.80f, yield_multiplier[sl], newValue)));
01589 
01590 }
01591 
01592 //----------- End of function EnrollRes::calc_app_multiplier --------//
01593 
01594 //----------- Begin of function EnrollRes::calc_post_enroll --------//
01598 void EnrollRes::calc_post_enroll() {
01599     // for sl1 temporarily
01600     const int sl = UG_TRADITION;                    // 0305
01601 
01602     //-------------------------//
01603     //           generate student               //
01604     //-------------------------//
01605     // refer to td3.4 section 2.7
01606 
01607     char subSeg, seg;
01608     int newStudentCount, i, t, aid=0;
01609 
01610     // temp vars storing new sim properties
01611     float talentArr[TALENT_VAR_COUNT];
01612     int maleCount=0, femaleCount=0;
01613 
01614     avg_athletic_talent_male_matrics = 0;
01615     avg_athletic_talent_female_matrics = 0;
01616 
01617     for ( subSeg=0; subSeg<