00001
00002
00003
00004 #include <OSYS.H>
00005 #include <OINFO.H>
00006 #include <OPSCHOOL.H>
00007 #include <ODEPT.H>
00008 #include <ODEPTRES.H>
00009 #include <GAMEDEF.H>
00010 #include <OFINANCE.H>
00011 #include <ODATE.H>
00012 #include <OSTUDENT.H>
00013 #include <OMATH.H>
00014 #include <OBOX.H>
00015 #include <OCOURSE.H>
00016 #include <OSTUDENT.H>
00017
00018 #if(GAME_VERSION>=200)
00019 const RECORD_SEPARATOR_LEN = 2;
00020 static char *RECORD_SEPARATOR = "\r\n";
00021 const FIELD_SEPARATOR_LEN = 1;
00022 static char *FIELD_SEPARATOR = "\t";
00023
00024 static char *export_num(int value) {
00025 static char num_str[20];
00026 return itoa( value, num_str, 10 );
00027 }
00028
00029 static char *export_num(double value) {
00030 static char num_str[20];
00031 return gcvt( value, 7, num_str );
00032 }
00033
00034 static char *export_percent(double value) {
00035 static char num_str[20];
00036 return gcvt( value*0.01, 7, num_str );
00037 }
00038
00039 #define WRITE_FIELD_SEPARATOR(f) f->file_write(FIELD_SEPARATOR, FIELD_SEPARATOR_LEN)
00040 #define WRITE_STR_FIELD(f,s) { f->file_write(s, strlen(s)); }
00041 #define WRITE_NUM_FIELD(f,n) { char *s=export_num(n); f->file_write(s, strlen(s)); }
00042 #define WRITE_PERCENT_FIELD(f,n) { char *s=export_percent(n); f->file_write(s, strlen(s)); }
00043 #define WRITE_RECORD_SEPARATOR(f) f->file_write(RECORD_SEPARATOR, RECORD_SEPARATOR_LEN)
00044 #endif
00045
00046
00047
00049
00050 memset( this, 0, sizeof(Student) );
00051
00052
00053
00054 department_recno = major;
00055
00056 student_level = studentLevel;
00057 gender_ethnic_group = genderEthnicGroup;
00058 student_segment = stuSeg;
00059
00060 date_admitted = info.game_date-(yearInProgram-1)*365;
00061
00062
00063
00064 year_in_program = yearInProgram;
00065 financial_aid = finAid;
00066 academic_achievement = 0;
00067
00068
00069
00070 #if(GAME_VERSION>=200)
00071 if ( student_level != UG_NONTRADITION ) {
00072 course_per_trimester[AUTUMN] = STD_COURSE_PER_TRIMESTER;
00073 course_per_trimester[WINTER] = STD_COURSE_PER_TRIMESTER;
00074 }
00075 else {
00076 course_per_trimester[AUTUMN] = STD_COURSE_NUG_PER_TRIMESTER;
00077 course_per_trimester[WINTER] = STD_COURSE_NUG_PER_TRIMESTER;
00078 }
00079
00080 off_quarter = SUMMER;
00081 #else
00082 course_per_trimester[AUTUMN] = STD_COURSE_PER_TRIMESTER;
00083 course_per_trimester[WINTER] = STD_COURSE_PER_TRIMESTER;
00084 off_quarter = SUMMER;
00085 #endif
00086
00087
00088 if ( student_level == UG_TRADITION && year_in_program == 1 ) {
00089 #if(GAME_VERSION>=200)
00090 if( m.random(4)==0 )
00091 #else
00092 if ( m.random(4) != 0 )
00093 return;
00094 #endif
00095 {
00096
00097 off_quarter = m.random(1) + AUTUMN;
00098
00099 err_when(AUTUMN!=0);
00100
00101 course_per_trimester[off_quarter] = 0;
00102 course_per_trimester[SUMMER] = STD_COURSE_PER_TRIMESTER;
00103 }
00104 }
00105
00106
00107
00108
00109 talent_academic = (char) max(0.0f,min(100.0f, talentArr[ACADEMIC] * 10));
00110
00111
00112
00113 talent_extracurricular = (char) max(0.0f,min(100.0f, talentArr[EXTRA_CURRI] * 10));
00114
00115 talent_athletics = (char) max(0.0f,min(100.0f, talentArr[ATHLETIC] * 10));
00116
00117
00118
00119 satisfaction_academic = 0;
00120 satisfaction_student_life = 0;
00121 satisfaction_athletics = 0;
00122
00123 err_when( studentLevel < 0 || studentLevel >= MAX_STUDENT_LEVEL );
00124 err_when( genderEthnicGroup < 0 || genderEthnicGroup >= GENDER_ETHNIC_TYPE_COUNT );
00125 err_when( major < 0 || major > department_array.department_count );
00126
00127
00128 err_when( major==0 && student_level != UG_TRADITION && !is_nontradition_ug_group(student_level) );
00129 }
00130
00131
00132
00133
00134
00136
00137 return date.year(date_admitted);
00138 }
00139
00140
00141
00142
00144
00145
00146
00147
00148 if ( info.game_day == player_school.trimester_array[player_school.cur_trimester].start_day
00149 && info.game_month == player_school.trimester_array[player_school.cur_trimester].start_month ) {
00150 update_history(UPDATE_TRIMESTER);
00151 }
00152
00153
00154 if ( info.game_day == 1 ) {
00155 update_history(UPDATE_MONTH);
00156
00157 sys.yield();
00158
00159
00160 if ( info.game_month == finance.fiscal_year_start_month )
00161 update_history(UPDATE_YEAR);
00162 }
00163
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183 }
00184
00185
00186
00187
00189
00190
00191
00192
00193
00194 if( think_graduate() )
00195 return;
00196
00197
00198
00199 if( think_dropout() )
00200 return;
00201
00202
00203
00204 if( think_change_major() )
00205 return;
00206
00207
00208
00209
00210
00211 if( player_school.cur_trimester == FIRST_TRIMESTER )
00212 year_in_program++;
00213 }
00214
00215
00216
00217
00221
00222
00223
00224 int requiredCourseCount;
00225
00226 switch( student_level ) {
00227 case UG_TRADITION:
00228 case UG_NONTRADITION:
00229 case DISTANCE_LEARN:
00230
00231 requiredCourseCount = COURSE_COUNT_REQUIRED_FOR_BACHELOR;
00232 break;
00233
00234 case MASTER:
00235
00236 requiredCourseCount = COURSE_COUNT_REQUIRED_FOR_MASTER;
00237 break;
00238
00239 case DOCTOR:
00240
00241 requiredCourseCount = COURSE_COUNT_REQUIRED_FOR_DOCTOR;
00242 break;
00243 }
00244
00245
00246
00247
00248
00249 if( total_course_all < requiredCourseCount ) {
00250
00251 return 0;
00252 }
00253
00254 err_when(department_recno == 0);
00255 Department* deptPtr = department_array[department_recno];
00256
00257 if ( student_level == DOCTOR ) {
00258 err_when(department_recno == 0);
00259
00260 char yearIn = min(year_in_program-1, MAX_GRADUATE_YEARS-1);
00261 float gradProb = department_res[deptPtr->department_id]->doctor_graduate_trans_prob[yearIn];
00262
00263
00264 float input[2];
00265 float multiplier = 1;
00266
00267 input[0] = math.dual_response_func(0.80f, 1.02f, 1.30f, 0.891f, 1.295f, 0.557f, 2.326f, 0);
00268
00269 input[1] = math.dual_response_func(0.80f, 1.00f, 1.30f, -0.912f, -0.863f, 2.502f, 0.489f, 0);
00270
00271 multiplier = 0.5f * input[0] + 0.5f * input[1];
00272
00273
00274 if ( math.get_random_float() > gradProb * multiplier ) {
00275
00276 return 0;
00277 }
00278 }
00279
00280
00281
00282
00283
00284
00285 switch( student_level ) {
00286 case UG_TRADITION:
00287 case UG_NONTRADITION:
00288 #if(GAME_VERSION>=200)
00289 if ( student_level == UG_TRADITION ) {
00290 deptPtr->student_array.cur_bachelor_degree++;
00291 deptPtr->student_array.last_year_degree[0]++;
00292 }
00293 else {
00294 deptPtr->student_array.cur_non_ug_bachelor_degree++;
00295 deptPtr->student_array.last_year_degree[1]++;
00296 }
00297 #else
00298 case DISTANCE_LEARN:
00299 deptPtr->student_array.cur_bachelor_degree++;
00300 #endif
00301 deptPtr->student_array.time_to_degree_cumm[BACHELOR_DEGREE] += year_in_program;
00302 break;
00303
00304 case MASTER:
00305 deptPtr->student_array.cur_master_degree++;
00306 #if(GAME_VERSION>=200)
00307 deptPtr->student_array.last_year_degree[2]++;
00308 #endif
00309 deptPtr->student_array.time_to_degree_cumm[MASTER_DEGREE] += year_in_program;
00310 break;
00311
00312 case DOCTOR:
00313 deptPtr->student_array.cur_doctor_degree++;
00314 #if(GAME_VERSION>=200)
00315 deptPtr->student_array.last_year_degree[3]++;
00316 #endif
00317 deptPtr->student_array.time_to_degree_cumm[DOCTOR_DEGREE] += year_in_program;
00318 break;
00319 }
00320
00321
00322
00323 if( student_level == UG_TRADITION ) {
00324
00325 int graduationTime = info.game_date - date_admitted;
00326
00327 deptPtr->student_array.ave_time_to_graduation_for_ug =
00328 ( deptPtr->student_array.ave_time_to_graduation_for_ug *
00329 (deptPtr->student_array.cur_bachelor_degree - 1) + graduationTime ) /
00330 deptPtr->student_array.cur_bachelor_degree;
00331
00332 #ifdef DEBUG
00333 static int grad4Year[2] = { 0, 0 };
00334 if( graduationTime > 1461 ) {
00335 grad4Year[1]++;
00336 }
00337 else {
00338 grad4Year[0]++;
00339 }
00340 #endif
00341 }
00342
00343 #if(GAME_VERSION>=200)
00344 if ( audit_flag ) {
00345 File file;
00346
00347 char fileName[123];
00348
00349 switch( student_level ) {
00350 case UG_TRADITION: strcpy( fileName, "TRADITION" );
00351 break;
00352 case UG_NONTRADITION: strcpy( fileName, "NONTRADITION" );
00353 break;
00354 case MASTER: strcpy( fileName, "MASTER" );
00355 break;
00356 case DOCTOR: strcpy( fileName, "DOCTOR" );
00357 break;
00358 }
00359
00360 strcat( fileName, m.format(old_student_recno) );
00361 strcat( fileName, ".txt" );
00362
00363 file.file_append( fileName );
00364 file.file_seek(0, FILE_END);
00365
00366
00367 if ( info.prerun_year ) {
00368 WRITE_NUM_FIELD( (&file), -1 );
00369 }
00370 else {
00371 WRITE_NUM_FIELD( (&file), info.financial_year() );
00372 }
00373
00374 WRITE_FIELD_SEPARATOR( (&file) );
00375
00376
00377 switch( player_school.cur_trimester ) {
00378 case AUTUMN: WRITE_STR_FIELD( (&file), "A" ); break;
00379 case WINTER: WRITE_STR_FIELD( (&file), "W" ); break;
00380 case SUMMER: WRITE_STR_FIELD( (&file), "S" ); break;
00381 }
00382
00383
00384 file_course_id++;
00385 WRITE_FIELD_SEPARATOR( (&file) );
00386 WRITE_FIELD_SEPARATOR( (&file) );
00387 WRITE_NUM_FIELD( (&file), file_course_id );
00388 WRITE_FIELD_SEPARATOR( (&file) );
00389
00390 WRITE_STR_FIELD( (&file), "Status" );
00391 WRITE_FIELD_SEPARATOR( (&file) );
00392 WRITE_FIELD_SEPARATOR( (&file) );
00393 if ( department_recno ) {
00394 WRITE_STR_FIELD( (&file), "Grad" );
00395 }
00396
00397 file.file_close();
00398 }
00399 #endif
00400
00401
00402
00403 deptPtr->student_array.del(student_recno);
00404
00405
00406 return 1;
00407 }
00408
00409
00410
00411
00412
00419
00420 calc_multiplier_on_dropout_prob();
00421
00422
00423 err_when(year_in_program<1);
00424
00425 float dropProb = 0;
00426 char yearIn = min(year_in_program-1, MAX_GRADUATE_YEARS-1);
00427 GeneralDepartment* deptPtr = department_recno ? (GeneralDepartment *) department_array[department_recno] : &department_res.general_dept;
00428
00429
00430 if ( deptPtr->student_array.student_count <= 10 ) {
00431
00432 return 0;
00433 }
00434 switch( student_level ) {
00435 #if(GAME_VERSION>=200)
00436 case UG_NONTRADITION:
00437 dropProb = 0.5f * player_school.dropout_trans_prob[student_level][yearIn];
00438 break;
00439 case UG_TRADITION:
00440 case MASTER:
00441
00442 dropProb = player_school.dropout_trans_prob[student_level][yearIn];
00443 break;
00444
00445 case DOCTOR:
00446 err_when(&department_res.general_dept == deptPtr);
00447 dropProb = 0.5f * department_res[deptPtr->department_id]->doctor_dropout_trans_prob[yearIn];
00448 break;
00449
00450 case DISTANCE_LEARN:
00451 dropProb = player_school.dropout_trans_prob[UG_NONTRADITION][yearIn];
00452 break;
00453 #else
00454 case UG_TRADITION:
00455 case UG_NONTRADITION:
00456 case MASTER:
00457
00458 dropProb = player_school.dropout_trans_prob[student_level][yearIn];
00459 break;
00460
00461 case DOCTOR:
00462 err_when(&department_res.general_dept == deptPtr);
00463 dropProb = 0.5f * department_res[deptPtr->department_id]->doctor_dropout_trans_prob[yearIn];
00464 break;
00465
00466 case DISTANCE_LEARN:
00467 dropProb = player_school.dropout_trans_prob[UG_NONTRADITION][yearIn];
00468 break;
00469 #endif
00470 }
00471
00472
00473 dropProb = max(0.0f, min(1.0f, dropProb * multiplier_on_dropout_prob));
00474
00475 if ( math.get_random_float() > dropProb ) {
00476
00477 return 0;
00478 }
00479
00480
00481
00482 #if(GAME_VERSION>=200)
00483 char level2Degree[] = {BACHELOR_DEGREE, BACHELOR_DEGREE, MASTER_DEGREE, DOCTOR_DEGREE, -1};
00484 #else
00485 char level2Degree[] = {BACHELOR_DEGREE, BACHELOR_DEGREE, MASTER_DEGREE, DOCTOR_DEGREE, BACHELOR_DEGREE};
00486 #endif
00487
00488 if ( level2Degree[student_level] >=0 ) {
00489 #if(GAME_VERSION>=200)
00490 deptPtr->student_array.last_year_dropout[student_level]++;
00491 #endif
00492 deptPtr->student_array.cur_dropout[level2Degree[student_level]]++;
00493 }
00494
00495 #if(GAME_VERSION>=200)
00496 if ( audit_flag ) {
00497 File file;
00498
00499 char fileName[123];
00500
00501 switch( student_level ) {
00502 case UG_TRADITION: strcpy( fileName, "TRADITION" );
00503 break;
00504 case UG_NONTRADITION: strcpy( fileName, "NONTRADITION" );
00505 break;
00506 case MASTER: strcpy( fileName, "MASTER" );
00507 break;
00508 case DOCTOR: strcpy( fileName, "DOCTOR" );
00509 break;
00510 }
00511
00512 strcat( fileName, m.format(old_student_recno) );
00513 strcat( fileName, ".txt" );
00514
00515 file.file_append( fileName );
00516 file.file_seek(0, FILE_END);
00517
00518
00519 if ( info.prerun_year ) {
00520 WRITE_NUM_FIELD( (&file), -1 );
00521 }
00522 else {
00523 WRITE_NUM_FIELD( (&file), info.financial_year() );
00524 }
00525
00526 WRITE_FIELD_SEPARATOR( (&file) );
00527
00528
00529 switch( player_school.cur_trimester ) {
00530 case AUTUMN: WRITE_STR_FIELD( (&file), "A" ); break;
00531 case WINTER: WRITE_STR_FIELD( (&file), "W" ); break;
00532 case SUMMER: WRITE_STR_FIELD( (&file), "S" ); break;
00533 }
00534
00535
00536 file_course_id++;
00537 WRITE_FIELD_SEPARATOR( (&file) );
00538 WRITE_FIELD_SEPARATOR( (&file) );
00539 WRITE_NUM_FIELD( (&file), file_course_id );
00540 WRITE_FIELD_SEPARATOR( (&file) );
00541
00542 WRITE_STR_FIELD( (&file), "Status" );
00543 WRITE_FIELD_SEPARATOR( (&file) );
00544 WRITE_FIELD_SEPARATOR( (&file) );
00545 if ( department_recno ) {
00546 WRITE_STR_FIELD( (&file), "Drop" );
00547 }
00548
00549 file.file_close();
00550 }
00551 #endif
00552
00553 deptPtr->student_array.del(student_recno);
00554
00555
00556 return 1;
00557 }
00558
00559
00560
00561
00565
00566
00567
00568 if ( player_school.scenario_id == SCN_COMPENSATE_FOR_ENROLLMENT_SHIFTS && info.prerun_year )
00569 return change_major(1);
00570
00571
00572
00573 calc_probability_change_major();
00574
00575
00576 if ( department_recno != 0 && year_in_program == 1 )
00577 return 0;
00578
00579 if ( department_recno != 0 && math.get_random_float() > probability_change_major )
00580 return 0;
00581
00582
00583
00584 return change_major(courseCompleted);
00585 }
00586
00587
00588
00589
00590
00591
00595
00596
00597
00598
00599 int major = player_school.get_random_major(student_level);
00600
00601
00602 if ( couCompleted ) {
00603
00604 err_when(major == 0 );
00605 }
00606 else if ( department_recno==0 ) {
00607 err_when( student_level != UG_TRADITION && !is_nontradition_ug_group(student_level));
00608
00609 if ( year_in_program == 1 )
00610 return 0;
00611
00612 err_when(year_in_program!=2);
00613 }
00614
00615 if ( department_recno == major )
00616 return 0;
00617
00618 err_when(major == 0);
00619
00620 GeneralDepartment* oldDeptPtr = department_recno ? (GeneralDepartment *) department_array[department_recno] : &department_res.general_dept;
00621 Department* newDeptPtr = department_array[major];
00622
00623 int ods = oldDeptPtr->student_array.packed_size();
00624 int nds = newDeptPtr->student_array.packed_size();
00625 int oldStudentRecno = student_recno;
00626
00627 if (student_recno <=0 ) {
00628
00629 oldDeptPtr->student_array.del(student_recno);
00630 return 0;
00631 }
00632
00633
00634 department_recno = major;
00635 newDeptPtr->student_array.linkin(this);
00636
00637
00638 ((Student*)(newDeptPtr->student_array.get()))->student_recno
00639 = newDeptPtr->student_array.recno();
00640
00641 newDeptPtr->student_array.student_count++;
00642
00643 #if(GAME_VERSION>=200)
00644 if ( audit_flag ) {
00645 File file;
00646
00647 char fileName[123];
00648
00649 switch( student_level ) {
00650 case UG_TRADITION: strcpy( fileName, "TRADITION" );
00651 break;
00652 case UG_NONTRADITION: strcpy( fileName, "NONTRADITION" );
00653 break;
00654 case MASTER: strcpy( fileName, "MASTER" );
00655 break;
00656 case DOCTOR: strcpy( fileName, "DOCTOR" );
00657 break;
00658 }
00659
00660 strcat( fileName, m.format(old_student_recno) );
00661 strcat( fileName, ".txt" );
00662
00663 file.file_append( fileName );
00664 file.file_seek(0, FILE_END);
00665
00666
00667 if ( info.prerun_year ) {
00668 WRITE_NUM_FIELD( (&file), -1 );
00669 }
00670 else {
00671 WRITE_NUM_FIELD( (&file), info.financial_year() );
00672 }
00673
00674 WRITE_FIELD_SEPARATOR( (&file) );
00675
00676
00677 switch( player_school.cur_trimester ) {
00678 case AUTUMN: WRITE_STR_FIELD( (&file), "A" ); break;
00679 case WINTER: WRITE_STR_FIELD( (&file), "W" ); break;
00680 case SUMMER: WRITE_STR_FIELD( (&file), "S" ); break;
00681 }
00682
00683
00684 file_course_id++;
00685 WRITE_FIELD_SEPARATOR( (&file) );
00686 WRITE_FIELD_SEPARATOR( (&file) );
00687 WRITE_NUM_FIELD( (&file), 0 );
00688 WRITE_FIELD_SEPARATOR( (&file) );
00689
00690 WRITE_STR_FIELD( (&file), "Status" );
00691 WRITE_FIELD_SEPARATOR( (&file) );
00692 WRITE_FIELD_SEPARATOR( (&file) );
00693 WRITE_STR_FIELD( (&file), department_res[newDeptPtr->department_id]->name );
00694
00695 WRITE_RECORD_SEPARATOR( (&file) );
00696
00697 file.file_close();
00698 }
00699 #endif
00700
00701
00702 oldDeptPtr->student_array.del(oldStudentRecno);
00703
00704 int oods = oldDeptPtr->student_array.packed_size();
00705 int onds = newDeptPtr->student_array.packed_size();
00706
00707 err_when(ods-1 != oods);
00708 err_when(nds+1 != onds);
00709 err_when( newDeptPtr->student_array[newDeptPtr->student_array.recno()]->department_recno != major);
00710
00711
00712 this->department_recno = major;
00713 return 1;
00714 }
00715
00716
00717