5.15. Step 15: School Tracking

5.15.1. Model Description

At this step we add an optional module for tracking students through the grade system of primary school. The module builds on the school fate model which decides on school entry and graduation. This module then adds information on the pathway. It models age at first entry, grade repetition, temporary school career interruptions, current enrolment and current highest grade attended and passed.

5.15.2. The new Educ1BaseTracking.mpp Module

This is an optional module used to track students through a grade system of “School One” - in the current implementation refering to primary school. The number of grades is declared in the range EDUC_ONE_GRADE and can be adapted to different school systems. Students are moved through the grade system by an actor SchoolOneActor. This actor has two events, one at the end of the school season, the other at the beginning of the school season. At the end of each school season it is decided who newly enters the school at grade one, who of the active students passed the attended grade, who graduated, who permanently leaves school, and for all others if enrollment is continued or the school career is interrupted by one year. The module builds on a fate model of school entry and success, thusonly models the careers of those fated to enter school. Those fated to graduate from school at some point pass all grades. Those fated to drop out accordingly do not pass all grades - the distribution of the highest grade attended being a model parameter.

The module is driven by 6 parameters:

  • The distribution of school entry ages by year of birth. Even in presence of a legislated school entry age, data in some developing countries reflect a wider range of ages when school is first enterd. This parameter allows to account for that fact and allows for scenarios in which school entry ages become more concentrated toward the legislated age.
  • The start of the school year: e.g. 0.666 for September 1st
  • The end of the school year: e.g. 0.5 for June 30
  • A grade repetition rate. The probability that a grade has to be repeated. Currently the only dimension is calendar year to allow for scenarios of changing grade success rates. More dimensions can be added easily e.g. for accountig for geographical variation, the grade, or individual characteristics.
  • A school interruption rate. The probability that the school career is interrupted for a year. Currently the only dimension is calendar year to allow for scenarios of changing retention rates. More dimensions can be added easily e.g. for accountig for geographical variation, the grade, or individual characteristics.
  • The distribution of the highest grade attended of dropout students. Currently year of birth is the only dimension allowing for scenarios of changing retention patterns. More dimensions can be added easily e.g. for accountig for geographical variation, or individual characteristics.

Besides grade and period, the school progression parameters have two additional dimensions, one for geographical region, the other for personal characteristics. The levels of these two characteristics are model specific, they are declared in the classifications EDUC_ONE_GEO and EDUC_ONE_GROUP, with the corresponding states educ_one_geo and educ_one_group. Currently only totals are implemented.

As an optional module the module can be added or removed from the model. The only required code change in other modules is the creation of the actor SchoolOneActor in the Simulation() function.



////////////////////////////////////////////////////////////////////////////////////////////////////
// Actor-Sets
////////////////////////////////////////////////////////////////////////////////////////////////////

//EN The School One
actor_set SchoolOneActor asSchoolOneActor;

//EN Potential Students of School One
actor_set Person asPotentialSchoolOneStudent
filter is_alive && educ_one_status != EOS_OUT && educ_one_fate !=  EOL_LOW;

//EN Students of School One To Be Processed
actor_set Person asPotentialSchoolOneStudentToProcess
filter is_alive && educ_one_to_process;

////////////////////////////////////////////////////////////////////////////////////////////////////
// Types
////////////////////////////////////////////////////////////////////////////////////////////////////

range EDUC_ONE_GRADE { 1, 6 };          //EN Grades School One
range EDUC_ONE_GRADE0 { 0 , 6 };        //EN Grades School One (incl. 0)
range EDUC_ONE_ENTRY_AGE { 5, 8 };      //EN Possible entry ages School One

classification EDUC_ONE_STATUS          //EN Current attendance status in School One
{
    EOS_NEVER,                          //EN Never entered
    EOS_WAIT,                           //EN Wait for entry (e.g. school break)
    EOS_ATTEND,                         //EN Currently attending
    EOS_PAUSE,                          //EN Pause
    EOS_OUT                             //EN Left school
};

classification EDUC_ONE_GEO             //EN Regional Unit
{
    EOG_OO                              //EN All
};

classification EDUC_ONE_GROUP           //EN Population Group
{
    E1G_OO                              //EN All
};

////////////////////////////////////////////////////////////////////////////////////////////////////
// Prameters
////////////////////////////////////////////////////////////////////////////////////////////////////

parameters
{
    double  StartSchoolOneYear;         //EN Start of school year
    double  EndSchoolOneYear;           //EN End of school year

    //EN Grade repetition rate
    double  SchoolOneRepetitionRate[EDUC_ONE_GEO][EDUC_ONE_GROUP][SIM_YEAR_RANGE];

    //EN School interruption rate
    double  SchoolOneInterruptionRate[EDUC_ONE_GEO][EDUC_ONE_GROUP][SIM_YEAR_RANGE];

    //EN Distribution entry age
    cumrate EducOneEntryAge[EDUC_ONE_GEO][EDUC_ONE_GROUP][YOB_GRAD_PRIMARY][EDUC_ONE_ENTRY_AGE];

    //EN Distribution dropout grade
    cumrate EducOneDropoutGrade[EDUC_ONE_GEO][EDUC_ONE_GROUP][YOB_GRAD_PRIMARY][EDUC_ONE_GRADE];
};

parameter_group PG_ShoolOneTracking                                 //EN Grade system tracking
{
    StartSchoolOneYear, EndSchoolOneYear, EducOneEntryAge,
    EducOneDropoutGrade, SchoolOneRepetitionRate,
    SchoolOneInterruptionRate
};

parameter_group PG_ShoolOne                                         //EN Primary School
{
    PG_SchoolOneFate, PG_ShoolOneTracking
};

////////////////////////////////////////////////////////////////////////////////////////////////////
// Actors
////////////////////////////////////////////////////////////////////////////////////////////////////

actor Person
{
    logical             educ_one_to_process = { FALSE };    //EN Flag for students to be processed
    EDUC_ONE_GRADE0     educ_one_grade_attended = { 0 };    //EN Highest grade attended
    EDUC_ONE_GRADE0     educ_one_grade_passed = { 0 };      //EN Highest grade passed
    EDUC_ONE_STATUS     educ_one_status = { EOS_NEVER };    //EN Primary school status
    EDUC_ONE_ENTRY_AGE  educ_one_entry_age = { 6 };         //EN Primary school entry age
    EDUC_ONE_GRADE      educ_one_grade_fate = { 1 };        //EN Highest level attended of dropouts
    EDUC_ONE_GEO        educ_one_geo = {EOG_OO};            //EN Geographical location
    EDUC_ONE_GROUP      educ_one_group = {E1G_OO};          //EN Person group

    void SetEducOneEntryAgeDroputGrade();                   //EN Sample entry age and dropout grade
    hook SetEducOneEntryAgeDroputGrade, Start;              //EN Hook to Start()
};

actor SchoolOneActor
{
    TIME time_start_school_one_year = { TIME_INFINITE};         //EN Next start of school year
    TIME time_end_school_one_year = { TIME_INFINITE};           //EN Next end of school year

    event timeStartSchoolOneYearEvent, StartSchoolOneYearEvent; //EN Start school year event
    event timeEndSchoolOneYearEvent, EndSchoolOneYearEvent;     //EN End school year event
};

actor Clock
{
    void SetSchoolYearOneClock();                           //EN Clock for scheduling school year
    hook SetSchoolYearOneClock, StartYearClock;             //EN Hooked to Start Year
};

////////////////////////////////////////////////////////////////////////////////////////////////////
// Implementatation Person Functions
////////////////////////////////////////////////////////////////////////////////////////////////////

void Person::SetEducOneEntryAgeDroputGrade()
{
    int nAge;
    Lookup_EducOneEntryAge(RandUniform(32), (int)educ_one_geo, (int)educ_one_group,
        RANGE_POS(YOB_GRAD_PRIMARY,year_of_birth), &nAge);
    educ_one_entry_age = MIN(EDUC_ONE_ENTRY_AGE) + nAge;

    int nGrade;
    Lookup_EducOneDropoutGrade(RandUniform(34), (int)educ_one_geo, (int)educ_one_group,
        RANGE_POS(YOB_GRAD_PRIMARY,year_of_birth), &nGrade);
    educ_one_grade_fate = MIN(EDUC_ONE_GRADE) + nGrade;
}

////////////////////////////////////////////////////////////////////////////////////////////////////
// Implementatation SchoolOneActor Functions
////////////////////////////////////////////////////////////////////////////////////////////////////

TIME SchoolOneActor::timeStartSchoolOneYearEvent(){return time_start_school_one_year;}
void SchoolOneActor::StartSchoolOneYearEvent()
{
    for (long nJ = 0; nJ < asPotentialSchoolOneStudent->Count(); nJ++)
    {
        auto prPerson = asPotentialSchoolOneStudent->Item(nJ);
        if (prPerson->educ_one_status == EOS_WAIT )
        {
            prPerson->educ_one_status = EOS_ATTEND ;
            prPerson->educ_one_grade_attended = prPerson->educ_one_grade_passed + 1;
        }
    }
    time_start_school_one_year = TIME_INFINITE;
}

TIME SchoolOneActor::timeEndSchoolOneYearEvent(){return time_end_school_one_year;}
void SchoolOneActor::EndSchoolOneYearEvent()
{
    // Flag the persons to be processed
    for (long nJ = 0; nJ < asPotentialSchoolOneStudent->Count(); nJ++)
    {
        auto prPerson = asPotentialSchoolOneStudent->Item(nJ);
        prPerson->educ_one_to_process = TRUE;
    }

    // Process all potential students
    for (long nJ = 0; nJ < asPotentialSchoolOneStudentToProcess->Count(); nJ++)
    {
        auto prPerson = asPotentialSchoolOneStudentToProcess->Item(nJ);
        bool bIsDropout = (prPerson->educ_one_fate == EOL_MEDIUM );

        // Potential Student has not entered school yet or currently in pause
        if (prPerson->integer_age == prPerson->educ_one_entry_age || prPerson->educ_one_status == EOS_PAUSE )
        {
            prPerson->educ_one_status = EOS_WAIT;
        }

        // Active student in last year
        else if (prPerson->educ_one_grade_attended == MAX(EDUC_ONE_GRADE))
        {
            // Leave school without passing grade if fated school dropout
            if ( bIsDropout )  prPerson->educ_one_status = EOS_OUT;
            // Leave school as graduate if rate passed
            else if (RandUniform(35) > SchoolOneRepetitionRate[prPerson->educ_one_geo]
                [prPerson->educ_one_group][RANGE_POS(SIM_YEAR_RANGE, prPerson->calendar_year)])
            {
                prPerson->educ_one_grade_passed = prPerson->educ_one_grade_attended;
                prPerson->educ_one_status = EOS_OUT;
            }
            // Repeat grade: decide now or after a break
            else if (RandUniform(36) < SchoolOneInterruptionRate[prPerson->educ_one_geo]
                [prPerson->educ_one_group][RANGE_POS(SIM_YEAR_RANGE, prPerson->calendar_year)])
            {
                prPerson->educ_one_status = EOS_PAUSE;
            }
            else prPerson->educ_one_status = EOS_WAIT;
        }

        // Active student before last year
        else if (prPerson->integer_age > prPerson->educ_one_entry_age)
        {
            // Check if grade passed
            if (RandUniform(37) > SchoolOneRepetitionRate[prPerson->educ_one_geo]
                [prPerson->educ_one_group][RANGE_POS(SIM_YEAR_RANGE, prPerson->calendar_year)])
            {
                prPerson->educ_one_grade_passed = prPerson->educ_one_grade_attended;
            }

            // Dropout reached highest fated grade
            if (bIsDropout && prPerson->educ_one_grade_fate == prPerson->educ_one_grade_attended)
            {
                prPerson->educ_one_status = EOS_OUT;
            }
            // All others continue now or after a break
            else if (RandUniform(38) > SchoolOneInterruptionRate[prPerson->educ_one_geo]
                [prPerson->educ_one_group][RANGE_POS(SIM_YEAR_RANGE, prPerson->calendar_year)])
            {
                prPerson->educ_one_status = EOS_WAIT;
            }
            else prPerson->educ_one_status = EOS_PAUSE;
        }
    }

    // Unflag all persons
    while (asPotentialSchoolOneStudentToProcess->Count() > 0)
    {
        asPotentialSchoolOneStudentToProcess->Item(0)->educ_one_to_process = FALSE;
    }
    time_end_school_one_year = TIME_INFINITE;
}

////////////////////////////////////////////////////////////////////////////////////////////////////
// Implementatation Clock Functions
////////////////////////////////////////////////////////////////////////////////////////////////////

void Clock::SetSchoolYearOneClock()
{
    asSchoolOneActor->Item(0)->time_start_school_one_year = WAIT(StartSchoolOneYear);
    asSchoolOneActor->Item(0)->time_end_school_one_year = WAIT(EndSchoolOneYear);
}

////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////

table Person SchoolTrackTab //EN School Enrolment
[trigger_changes(calendar_year) && in_projected_time && is_resident && educ_one_status == EOS_ATTEND]
{
{
    unit          //EN Students
}
* sim_year
* educ_one_grade_attended+
};

actor Person
{
logical track_me = (RandUniform(33)<0.01) ? TRUE : FALSE;
};

track Person
[track_me]
{
    integer_age,
    educ_one_fate,
    educ_one_grade_attended,
    educ_one_grade_passed,
    educ_one_status,
    educ_one_grade_fate
};

5.15.3. Initializations in the Simulation() Function

The new actor is created in the Simulation() function.


    // Create the School One
    auto prSchoolOneActor = new SchoolOneActor();
    prSchoolOneActor->Start();