Home Page Downloads Contact Us

Free Open Source Artificial Intelligence C++ Parts

aiParts Open Source Project  

Home Page
Open Source
Contact
Free Downloads
Releases and Credits
Software Status
License
v0.9.3 README File
About rrproj
assigning people and/or equipment to projects
High-Hope Technique
History of the AI
View Source Files
and how they are organized
Making Programs
Development Notes
Using aiParts
Your Application
Support and Services

aiParts Source File

//**********************************************************************
//  rrproj_prob.h  -  rrproj Problem
//
//  An rrproj problem is the problem of assigning people and/or 
//  equipment to projects.  An application includes this file to 
//  define and solve this type of problem.
//    
//  Copyright (c)  2008  Brian Marshall
//
//  See the license at end of this file.
//
//  Developers/Contributers:
//    [BRM] Brian Marshall - Calgary - bmarshal@agt.net
//
//  08/01/19  [BRM] began development
//
//----------------------------------------------------------------------
//  Required Source Files
//
// To use the solve() function, the following files must be compiled:
//     rrproj_prob.cpp       (with rrproj_prob.h)
//     rrproj_solv.cpp       (with rrproj_solv.h)
//     rrproj_fctry.cpp      (with rrproj_fctry.h)
//     aipReqRes.cpp         (with aipReqRes.h)
//     aipHighHope.cpp       (with aipHighHope.h)
//     aipProblem.cpp        (with aipProblem.h)
//     aipDecision.cpp       (with aipDecision.h)
//     aipEmotion.cpp        (with aipEmotion.h)
//     aipPandemonium.cpp    (with aipPandemonium.h)
//     aipBase.cpp           (with aipBase.h)
//     aipGood.cpp           (with aipGood.h)
//
//----------------------------------------------------------------------
//  Data relationships in a rrproj Problem
//
//  If A is joined to B by a line, and A is higher than B in the
//  diagram, there is a one-to-many relationship between A and B.
//
//   angle brackets indicate output solution data
//  {abc} curly braces   indicate virtual datasets
//
//                        [Problem]____[ProbWriter]
//               _________|     | |__________
//              |               |            |
//       {Position}  {Project}  |       _{Employee}__________
//       |  |  |  |    |        |      |  |  |  | |_______   |
//       |  |  |  [Pos_Day]     |      |  |  |  |         |  |
//       |  |  |       |        |      |  |  |  [Emp_Dow] |  |
//       |  |  |      ____|  |  |            |  |
//       |  |  |                          |  [Emp_Off]    |  |
//       |  |  |__________[Pos_Emp]_______|               |  |
//       |  |                                             |  |
//       |  |___________[Emp_Day_Pos]_____________________|  |
//       |                                                   |
//       |_______________[Assignment]________________________|
//
//
//
//  Pos_Day_Emp is the normalized output solution data.
//  Emp_Day_Pos is for (optional) historic data.
//  Other entities define the problem to be solved.
//
//  If the problem is configured with an rppProbWriteWeek1
//  for a [ProbWriter], the output solution data is
//  denormalized into weeks:
//
//                        [Problem]____[rppProbWriteWeek1]
//               _________|     | |__________
//              |               |            |
//       {Position}  {Project}  |        {Employee}
//               |     |        |          |  |
//              [Pos_Day]   <>  |  |
//                |             |          |  |
//                |      <>_|  |
//                |             |             |
//     _______|
//
//
//   is the normalized solution data
//   is reordered noralized solution data
//  <>  and  <> are the solution data
//      by project-week: master and detail data
//      which are created from 
//
//  The data is stored in the order indicated by the name.
//  Input data can be provided in any order.
//
//  In this software, Problem, Project, Position and Employee are 
//  virtual datasets.  They would be in a logical data model, but
//  they are not datasets in this software.
//
//----------------------------------------------------------------------
//  Optionally providing historic Emp_Day_Pos data
//
//  If an application expects the solver to consider data prior to
//  the start of the problem, historic Emp_Day_Pos data must
//  be supplied before the problem solve() function is called.
//
//  Adding Emp_Day_Pos data is optional, and it may be added for 
//  just the employees for which it matters.
//
//  Examples requiring (some) historic data:
//  - It may be desirable to rotate through (some) employees 
//    (ex. part-time employees, contractors, volunteers).
//  - It is desirable, for an employee who worked a position yesterday
//    to work the same position today (if the employee works today).
//
//  Currently, the minimum desirable amount of historic Emp_Day_Pos 
//  data is the last day worked (before the first day of the problem)
//  for each employee.  Employees may be omitted if they worked
//  in the last couple of days before the problem.
//
//  The solver does not get historic Emp_Day_Pos data; this data is
//  used to set attributes in entities that are part of the solver.
//
//  The output solution data does not include the historic data.
//
//----------------------------------------------------------------------
//  Using this software in an application
//
//  The application will create an instance of class rppProblem
//  and call (some of) its public functions:
//    either:
//      - call functions to add the problem data to the rppProblem
//    or:
//      - call the problem read() function
//    call solve() to solve the problem
//    either:
//      - call get_rslt_desc()
//      - call get_pos_day_emp () to get the solution
//    or:
//      - create an instance of a subclass of rppProbWrite
//      - call the write() function of the instance
//  and then delete the instance of rrpProblem if required.
//
//  The char* pointer returned from rrpProblem::get_rslt_desc()
//  must not be used after the rrpProblem is deleted.
//
//  A subclass of rppProbWrite can denormalize the data in a
//  particular way - it customizes the solution data file
//  for one or more applications.
//
//  The application developer does not have to know or care about:
//   - how rrpProblem stores data
//   - how the public functions work
//   - anything about any of the other classes in this file
//
//----------------------------------------------------------------------
//  What rppProblem::solve() does  (optional information)
//
//  When solve() is called, it:
//    - creates an instance of rpsFactory
//    - uses the factory with the problem data to build a solver
//    - deletes the factory
//    - calls the solver solve() function
//    - copies the solution data to the problem data
//    - deletes the solver
//
//----------------------------------------------------------------------

#ifndef rrproj_prob_h_guard
#define rrproj_prob_h_guard

#include "aipPandemonium.h"
#include "aipTime.h"

#include <stdio.h>

//----------------------------------------------------------------------
//  Local Constants

const long Max_Str_Key_Len = 30;

const long File_Date_Len = 10;   // "yyyy-mm-dd"
const long File_Time_Len =  5;   // "hh:mm"

const long Max_Log_Len = 300;

const long Max_File_Name = 100;

//----------------------------------------------------------------------
//  Classes.  Sub-classing is shown by indentation.
//
//  class  aipG  is a typedef for aipGoodness.
//
//  A class is a subclass of aipDemon (a list element) so that
//  a pointer to it can be added to pandemoniums (lists). 

// class aipBase;                        ( in aipBase.h )
     class rppProblem;             // rrproj problem
//   class aipDemon;                     ( in aipPandemonium.h )
       class rppPosDay;            // position on a day
       class rppEmpDow;            // days-of-week the emp can work
       class rppEmpOff;            // days an emp cannot work
       class rppPosEmp;            // pos and an emp that can work it
       class rppAssignment;        // an emp pre-assigned to a pos
       class rppEmpDayPos;         // historic solution data
       class rppPosDayEmp;         // normalized solution data
       class rppProjWeekEmpDay;    // re-ordered normalized solution
       class rppProjWeek;          // output master for a week 
       class rppProjWeekEmp;       // output detail for a week
     class rppProbWrite;           // problem solution-writer
       class rppProbWriteWeek1;    // week-based writer number 1
//   class aipLogger;                    ( in aipBase.h )
//     class aipStringLogger;            ( in aipBase.h )
// class aipDemonItr;                    ( in aipPandemonium.h )
     class rppPosDayItr;           // position-day iterator
     class rppEmpItr;              // employee iterator
     class rppEmpDowItr;           // emp-off iterator
     class rppEmpOffItr;           // emp-off iterator
     class rppPosEmpItr;           // position-employee-pair iterator
     class rppAssgnItr;            // assignment iterator
     class rppEmpDayPosItr;        // historic emp-day-pos iterator
     class rppPosDayEmpItr;        // normalized-output iterator
     class rppProjWeekEmpDayItr;   // re-ordered output iterator
     class rppProjWeekItr;         // output-master iterator
     class rppProjWeekEmpItr;      // output-detail iterator
   class rppFileDate;              // read/write dates in a file
   class rppFileTime;              // read/write times in a file

//======================================================================
//  rppProblem  -  an rrproj problem as defined by the application

class rppProblem : public aipBase {

  long      m_start_yyyymmdd;
  long      m_end_yyyymmdd;
  long      m_week_start_day;          // 0=Sunday
  long      m_num_tries;

  aipStringLogger * m_logger;          // for calls to log()

  aipPandemonium  * m_posdays;         // problem data
  aipPandemonium  * m_empdows;
  aipPandemonium  * m_empoffs;
  aipPandemonium  * m_posemps;
  aipPandemonium  * m_assignments;

  aipPandemonium  * m_empdaypos;       // historic solution data

  aipPandemonium  * m_posdayemps;      // output solution data

  rppPosDayEmpItr * m_posdayemp_itr;   // for get_pos_day_emp()

public:
                   //  Functions Used by the Application
  rppProblem ();
  virtual ~rppProblem ();

  int is_valid ();    // returns true if valid

  virtual int read (const char *filename);  // return 0 on failure

                   // for problem data record - returns 0 on failure
  virtual int read_str  (const char *x);
  virtual int write_str (char *x) const;

  virtual int write_input (const char *filename);

  const char * get_rslt_desc () const;  

                                        // or i/o by calls
  void add_pos_day    (long a_proj_id, long a_pos_id, 
                       long a_yyyymmdd, long a_num_emps_req);

  void add_emp_dow    (long a_emp_id, long a_dow,
                       long a_start_hhmm, long a_end_hhmm);

  void add_emp_off    (long a_emp_id, 
                       long a_start_yyyymmdd, long a_end_yyyymmdd);

  void add_pos_emp    (long a_pos_id, long a_emp_id);

  void add_assignment (long a_proj_id, long a_pos_id, long a_emp_id,
                       long a_start_yyyymmdd, long a_end_yyyymmdd);

  void add_empdaypos  (long a_emp_id, long a_yyyymmdd,  // historic
                       long a_proj_id, long a_pos_id);

  void add_posdayemp  (long a_proj_id, long a_pos_id,   // solution
                       long a_yyyymmdd, long a_emp_id);

  virtual int solve();      // returns 1 (true) on success

                    // get solution, returns 0 after last
  int get_pos_day_emp (long *a_proj_id, long *a_pos_id, 
                       long *a_yyyymmdd, long *a_emp_id);

                    //  Functions Used Internally

  long  start_yyyymmdd () const { return m_start_yyyymmdd; }
  long  end_yyyymmdd   () const { return m_end_yyyymmdd;   }
  long  week_start_day () const { return m_week_start_day; }
  long  num_tries      () const { return m_num_tries;      }

  rppPosDayItr       posday_iterator    () const;  // get an iterator
  rppEmpDowItr       empdow_iterator    () const;
  rppEmpOffItr       empoff_iterator    () const;
  rppPosEmpItr       posemp_iterator    () const;
  rppAssgnItr        assgn_iterator     () const;
  rppEmpDayPosItr    empdaypos_iterator () const;
  rppPosDayEmpItr    posdayemp_iterator () const;

};

//======================================================================
//  rppPosDay  -  Position on a Day that requires Employees

class rppPosDay : public aipDemon {

  long      m_proj_id;
  long      m_pos_id;
  long      m_yyyymmdd;

  long      m_num_emps_req;   // employees required

  long      m_start_hhmm;     // 1430 is 2:30 pm
  long      m_end_hhmm;

public:

  rppPosDay () {}
  rppPosDay (long a_proj_id, long a_pos_id,
             long a_yyyymmdd, long a_num_emps_req,
             long a_start_hhmm =0, long a_end_hhmm =0);
  virtual ~rppPosDay ();

  virtual long num_keys (void) const { return 3;          }
  virtual long     key1 (void) const { return m_proj_id;  }
  virtual long     key2 (void) const { return m_pos_id;   }
  virtual long     key3 (void) const { return m_yyyymmdd; }

                                          // returns 0 on failure
  virtual int read_str  (const char *x);
  virtual int write_str       (char *x) const;

  long  proj_id      () const { return m_proj_id;      }
  long  pos_id       () const { return m_pos_id;       }
  long  yyyymmdd     () const { return m_yyyymmdd;     }
  long  num_emps_req () const { return m_num_emps_req; }
  long  start_hhmm   () const { return m_start_hhmm;   }
  long  end_hhmm     () const { return m_end_hhmm;     }

};

//======================================================================
//  rppEmpDow  -  Day-of-week on which the employee can work

class rppEmpDow : public aipDemon {

  long      m_emp_id;
  long      m_dow;           // ex: 0=sun, 1=mon, 2=tue, etc.

  long      m_start_hhmm;    // 1430 is 2:30 pm
  long      m_end_hhmm;

public:

  rppEmpDow () {}
  rppEmpDow (long a_emp_id, long a_dow, 
             long a_start_hhmm, long a_end_hhmm);
  virtual ~rppEmpDow ();

  virtual long num_keys (void) const { return 2;        }
  virtual long     key1 (void) const { return m_emp_id; }
  virtual long     key2 (void) const { return m_dow;    }

                                          // returns 0 on failure
  virtual int read_str  (const char *x);
  virtual int write_str       (char *x) const;

  long emp_id () const { return m_emp_id; }
  long dow    () const { return m_dow;    }

  long start_hhmm () const { return m_start_hhmm; }
  long end_hhmm   () const { return m_end_hhmm;   }

};

//======================================================================
//  rppEmpOff  -  Days on which the employee cannot work

class rppEmpOff : public aipDemon {

  long      m_emp_id;
  long      m_start_yyyymmdd;
  long      m_end_yyyymmdd;

  aipTime   m_start_day;   // derived
  aipTime   m_end_day;     // derived

protected:

  void derive_data();

public:

  rppEmpOff () {}
  rppEmpOff (long a_emp_id, long a_start_yyyymmdd, long a_end_yyyymmdd);
  virtual ~rppEmpOff ();

  virtual long num_keys (void) const { return 3;                }
  virtual long     key1 (void) const { return m_emp_id;         }
  virtual long     key2 (void) const { return m_start_yyyymmdd; }
  virtual long     key3 (void) const { return m_end_yyyymmdd;   }

                                          // returns 0 on failure
  virtual int read_str  (const char *x);
  virtual int write_str       (char *x) const;

  long emp_id         () const { return m_emp_id;         }
  long start_yyyymmdd () const { return m_start_yyyymmdd; }

  long end_yyyymmdd   () const { return m_end_yyyymmdd;   }

  aipTime start_day   () const { return m_start_day;      }
  aipTime end_day     () const { return m_end_day;        }

};

//======================================================================
//  rppPosEmp  -  Position and an Employee that can work it

class rppPosEmp : public aipDemon {

  long      m_pos_id;
  long      m_emp_id;

public:

  rppPosEmp () {}
  rppPosEmp (long a_pos_id, long a_emp_id);
  virtual ~rppPosEmp ();

  virtual long num_keys (void) const { return 2;         }
  virtual long     key1 (void) const { return m_pos_id;  }
  virtual long     key2 (void) const { return m_emp_id;  }

                                          // returns 0 on failure
  virtual int read_str  (const char *x);
  virtual int write_str       (char *x) const;

  long pos_id  () const { return m_pos_id; }
  long emp_id  () const { return m_emp_id; }

};

//======================================================================
//  rppAssignment  -  Assignment of an emp to a pos for some day(s)

class rppAssignment : public aipDemon {

  long      m_proj_id;
  long      m_pos_id;
  long      m_emp_id;
  long      m_start_yyyymmdd;
  long      m_end_yyyymmdd;

public:

  rppAssignment () {}
  rppAssignment (long a_proj_id, long a_pos_id, long a_emp_id, 
                 long a_start_yyyymmdd, long a_end_yyyymmdd);
  virtual ~rppAssignment ();

  virtual long num_keys (void) const { return 3;               }
  virtual long     key1 (void) const { return m_emp_id;        }
  virtual long     key2 (void) const { return m_pos_id;        }
  virtual long     key3 (void) const { return m_start_yyyymmdd;}

                                          // returns 0 on failure
  virtual int read_str  (const char *x);
  virtual int write_str       (char *x) const;

  long proj_id        () const { return m_proj_id;        }
  long pos_id         () const { return m_pos_id;         }
  long emp_id         () const { return m_emp_id;         }
  long start_yyyymmdd () const { return m_start_yyyymmdd; }
  long end_yyyymmdd   () const { return m_end_yyyymmdd;   }

};

//======================================================================
//  rppEmpDayPos  -  historic results of solving the problem

class rppEmpDayPos : public aipDemon {

  long      m_emp_id;
  long      m_yyyymmdd;
  long      m_proj_id;
  long      m_pos_id;

public:

  rppEmpDayPos () {}
  rppEmpDayPos (long a_emp_id, long a_yyyymmdd,
                long a_proj_id, long a_pos_id);
  virtual ~rppEmpDayPos ();

  virtual long num_keys (void) const { return 4;          }
  virtual long     key1 (void) const { return m_emp_id;   }
  virtual long     key2 (void) const { return m_yyyymmdd; }
  virtual long     key3 (void) const { return m_proj_id;  }
  virtual long     key4 (void) const { return m_pos_id;   }

                                          // returns 0 on failure
  virtual int read_str  (const char *x);
  virtual int write_str       (char *x) const;

  long emp_id   () const { return m_emp_id;   }
  long yyyymmdd () const { return m_yyyymmdd; }
  long proj_id  () const { return m_proj_id;  }
  long pos_id   () const { return m_pos_id;   }

};

//======================================================================
//  rppPosDayEmp  -  normalized solution data

class rppPosDayEmp : public aipDemon {

  long      m_proj_id;
  long      m_pos_id;
  long      m_yyyymmdd;
  long      m_emp_id;

public:

  rppPosDayEmp (long a_proj_id, long a_pos_id,
                long a_yyyymmdd, long a_emp_id);
  virtual ~rppPosDayEmp ();

  virtual long num_keys (void) const { return 3;          }
  virtual long     key1 (void) const { return m_proj_id;  }
  virtual long     key2 (void) const { return m_pos_id;   }
  virtual long     key3 (void) const { return m_yyyymmdd; }

  virtual int write_hdr (char *x) const;    // returns 0 on failure
  virtual int write_str (char *x) const;    // returns 0 on failure

  long proj_id  () const { return m_proj_id;  }
  long pos_id   () const { return m_pos_id;   }
  long yyyymmdd () const { return m_yyyymmdd; }
  long emp_id   () const { return m_emp_id;   }

};

//======================================================================
//  rppProjWeekEmpDay  -  re-ordered normalized output with week-number

class rppProjWeekEmpDay : public aipDemon {

  long      m_proj_id;
  long      m_week_num;
  long      m_emp_id;
  long      m_week_pos;       // 1 to 7
  long      m_yyyymmdd;
  long      m_pos_id;

public:

  rppProjWeekEmpDay ();
  virtual ~rppProjWeekEmpDay ();

  virtual long num_keys (void) const { return 4;          }
  virtual long     key1 (void) const { return m_proj_id;  }
  virtual long     key2 (void) const { return m_week_num; }
  virtual long     key3 (void) const { return m_emp_id;   }
  virtual long     key4 (void) const { return m_week_pos; }

  void set (long a_proj_id, long a_week_num, long a_emp_id,
            long a_week_pos, long a_yyyymmdd, long a_pos_id);

  long proj_id  () const { return m_proj_id;  }
  long week_num () const { return m_week_num; }
  long emp_id   () const { return m_emp_id;   }
  long week_pos () const { return m_week_pos; }
  long yyyymmdd () const { return m_yyyymmdd; }
  long pos_id   () const { return m_pos_id;   }

};

//======================================================================
//  rppProjWeek  -  master for one week of the problem solution  

class rppProjWeek : public aipDemon {

  long      m_proj_id;
  long      m_week_num;
  long      m_yyyymmdd[7];    // -1 = null = past end of problem

public:

  rppProjWeek () { reset(); }
  virtual ~rppProjWeek () {}

  //   currently not storing these objects in a pandemonium
  virtual long num_keys (void) const { return 2;          }
  virtual long     key1 (void) const { return m_proj_id;  }
  virtual long     key2 (void) const { return m_week_num; }

  void set_pw (long p, long w) { m_proj_id = p;   m_week_num = w; }

  void set_day (long iday, long a_yyyymmdd) {
    m_yyyymmdd[iday-1] = a_yyyymmdd;
  }

  void reset ();

  virtual int write_hdr (char *x)   const;   // returns 0 on failure
  virtual int write_hdr (FILE *opf) const;   // returns 0 on failure
  virtual int write_str (char *x)   const;   // returns 0 on failure
  virtual int write     (FILE *ofp) const;   // returns 0 on failure

  long proj_id  () const { return m_proj_id;  }
  long week_num () const { return m_week_num; }

  long yyyymmdd (long iday) const { 
    if (iday < 1 || iday > 7) return -1;
    return m_yyyymmdd[iday-1]; 
  }

};

//======================================================================
//  rppProjWeekEmp  -  details for one week of the problem solution

class rppProjWeekEmp : public aipDemon {

  long      m_proj_id;
  long      m_week_num;
  long      m_emp_id;
  long      m_pos_id[7];    // -1 = null = not working that day

public:

  rppProjWeekEmp () { reset(); }
  virtual ~rppProjWeekEmp () {}

  //   currently not storing these objects in a pandemonium
  // virtual long num_keys (void) const { return 3;          }
  // virtual long     key1 (void) const { return m_proj_id;  }
  // virtual long     key2 (void) const { return m_week_num; }
  // virtual long     key3 (void) const { return m_emp_id;   }

  void set_pwe (long p, long w, long e) { 
    m_proj_id = p;   m_week_num = w;   m_emp_id = e;
  }

  void set_day (long iday, long a_pos_id) {
    m_pos_id[iday-1] = a_pos_id ;
  }

  void reset ();

  virtual int write_hdr (char *x)   const;   // returns 0 on failure
  virtual int write_hdr (FILE *ofp) const;   // returns 0 on failure
  virtual int write_str (char *x)   const;   // returns 0 on failure
  virtual int write     (FILE *ofp) const;   // returns 0 on failure

  long proj_id   () const { return m_proj_id;  }
  long week_num  () const { return m_week_num; }
  long emp_id    () const { return m_emp_id;   }

  long pos_id (long iday) const { 
    if (iday < 1 || iday > 7) return -1;
    return m_pos_id[iday-1]; 
  }

};

//======================================================================
//  rppProbWrite  -  Solution-Writer for a problem
//
//  Calling write():
//    - opens the output file
//    - calls pre_proc()
//    - iterates through the problem Pos-Day-Emps, and for each:
//      - calls handle_pos_day_emp()
//    - calls post_proc()
//    - closes the output file
//
//  This class may be used for its default behavior - writing the
//  solution data in the normalized form - or as a base class.

class rppProbWrite : public aipBase {

  const rppProblem  * m_prob;

  char                m_out_file_name[Max_File_Name+1];

  int                 m_any_pos_day_emp_written;

protected:

  const rppProblem  * prob () const { return m_prob; }

  virtual int pre_proc           (FILE *ofp);
  virtual int handle_pos_day_emp (FILE *ofp, 
                                  const rppPosDayEmp *pde);
  virtual int post_proc          (FILE *ofp);

  int write_blank_line (FILE *ofp);

public:

  rppProbWrite (const rppProblem *x, const char *out_file_name);
  virtual ~rppProbWrite ();

  int write ();        // return zero on error

};

//======================================================================
//  rppProbWriteWeek1  - Week-based Solution-Writer number 1
//
//  m_proj_week_emp_days is the re-ordered normalized-solution-data
//  with a week-number.

class rppProbWriteWeek1 : public rppProbWrite {

  aipTime           m_week1_start_dt;      // 1st, determine this

  aipPandemonium  * m_proj_week_emp_days;  // 2nd, reorder the data

  rppProjWeek     * m_proj_week;
  int               m_any_week_data;       // 0=no

  rppProjWeekEmp  * m_proj_week_emp;
  int               m_any_emp_data;        // 0=no

protected:

  int is_valid () const;

  void reset ();

  void set_week1_start_dt ();

  virtual int week_dt (aipTime x, 
                       long *week_num, long *week_pos) const;

  virtual int handle_pos_day_emp (FILE *ofp, 
                                  const rppPosDayEmp *pde);

  virtual int post_proc (FILE *ofp);
  virtual int set_proj_week (rppProjWeekEmpDay *x);
  virtual int add_to_proj_week_emp (rppProjWeekEmpDay *x);

  rppProjWeekEmpDayItr  projweekempday_iterator () const;

public:

  rppProbWriteWeek1 (const rppProblem *x, const char *out_file_name);
  virtual ~rppProbWriteWeek1 ();

  // int write()    from parent

};

//======================================================================
//  rppPosDayItr  -  Iterator for Position-Days in a Problem

class rppPosDayItr : public aipDemonItr {

public:

  rppPosDayItr (aipPandemonium *p) {
    set_demon_itr(p,0);
  }

  rppPosDayItr (const rppPosDayItr& x) {
    set_demon_itr (x.pandemonium(), x.current());
  }

  virtual ~rppPosDayItr () {}

  rppPosDayItr& operator = (const rppPosDayItr& x) {
    set_demon_itr(x.pandemonium(), x.current());
    return *this;
  }

  rppPosDay * first () {
    return (rppPosDay*)aipDemonItr::first();
  }

  rppPosDay * next () {
    return (rppPosDay*)aipDemonItr::next();
  }

};

//======================================================================
//  rppEmpDowItr  -  Iterator for Emp-Days-of-week in a Problem

class rppEmpDowItr : public aipDemonItr {

public:

  rppEmpDowItr (aipPandemonium *p) {
    set_demon_itr(p,0);
  }

  rppEmpDowItr (const rppEmpDowItr& x) {
    set_demon_itr (x.pandemonium(), x.current());
  }

  virtual ~rppEmpDowItr () {}

  rppEmpDowItr& operator = (const rppEmpDowItr& x) {
    set_demon_itr(x.pandemonium(), x.current());
    return *this;
  }

  rppEmpDow * first () {
    return (rppEmpDow*)aipDemonItr::first();
  }

  rppEmpDow * next () {
    return (rppEmpDow*)aipDemonItr::next();
  }

};

//======================================================================
//  rppEmpOffItr  -  Iterator for Emp-Offs in a Problem

class rppEmpOffItr : public aipDemonItr {

public:

  rppEmpOffItr (aipPandemonium *p) {
    set_demon_itr(p,0);
  }

  rppEmpOffItr (const rppEmpOffItr& x) {
    set_demon_itr (x.pandemonium(), x.current());
  }

  virtual ~rppEmpOffItr () {}

  rppEmpOffItr& operator = (const rppEmpOffItr& x) {
    set_demon_itr(x.pandemonium(), x.current());
    return *this;
  }

  rppEmpOff * first () {
    return (rppEmpOff*)aipDemonItr::first();
  }

  rppEmpOff * next () {
    return (rppEmpOff*)aipDemonItr::next();
  }

};

//======================================================================
//  rppPosEmpItr  -  Iterator for Position-Employee pairs in a Problem

class rppPosEmpItr : public aipDemonItr {

public:

  rppPosEmpItr (aipPandemonium *p) {
    set_demon_itr(p,0);
  }

  rppPosEmpItr (const rppPosEmpItr& x) {
    set_demon_itr (x.pandemonium(), x.current());
  }

  virtual ~rppPosEmpItr () {}

  rppPosEmpItr& operator = (const rppPosEmpItr& x) {
    set_demon_itr(x.pandemonium(), x.current());
    return *this;
  }

  rppPosEmp * first () {
    return (rppPosEmp*)aipDemonItr::first();
  }

  rppPosEmp * next () {
    return (rppPosEmp*)aipDemonItr::next();
  }

};

//======================================================================
//  rppAssgnItr  -  Iterator for Assignments in a Problem

class rppAssgnItr : public aipDemonItr {

public:

  rppAssgnItr (aipPandemonium *p) {
    set_demon_itr(p,0);
  }

  rppAssgnItr (const rppAssgnItr& x) {
    set_demon_itr (x.pandemonium(), x.current());
  }

  virtual ~rppAssgnItr () {}

  rppAssgnItr& operator = (const rppAssgnItr& x) {
    set_demon_itr(x.pandemonium(), x.current());
    return *this;
  }

  rppAssignment * first () {
    return (rppAssignment*)aipDemonItr::first();
  }

  rppAssignment * next () {
    return (rppAssignment*)aipDemonItr::next();
  }

};

//======================================================================
//  rppEmpDayPosItr  -  Iterator for historic Emp-Day-Pos in a Problem 

class rppEmpDayPosItr : public aipDemonItr {

public:

  rppEmpDayPosItr (aipPandemonium *p) {
    set_demon_itr(p,0);
  }

  rppEmpDayPosItr (const rppEmpDayPosItr& x) {
    set_demon_itr (x.pandemonium(), x.current());
  }

  virtual ~rppEmpDayPosItr () {}

  rppEmpDayPosItr& operator = (const rppEmpDayPosItr& x) {
    set_demon_itr(x.pandemonium(), x.current());
    return *this;
  }

  rppEmpDayPos * first () {
    return (rppEmpDayPos*)aipDemonItr::first();
  }

  rppEmpDayPos * next () {
    return (rppEmpDayPos*)aipDemonItr::next();
  }

};

//======================================================================
//  rppPosDayEmpItr  -  Iterator for normalized solution datam

class rppPosDayEmpItr : public aipDemonItr {

public:

  rppPosDayEmpItr (aipPandemonium *p) {
    set_demon_itr(p,0);
  }

  rppPosDayEmpItr (const rppPosDayEmpItr& x) {
    set_demon_itr (x.pandemonium(), x.current());
  }

  virtual ~rppPosDayEmpItr () {}

  rppPosDayEmpItr& operator = (const rppPosDayEmpItr& x) {
    set_demon_itr(x.pandemonium(), x.current());
    return *this;
  }

  rppPosDayEmp * first () {
    return (rppPosDayEmp*)aipDemonItr::first();
  }

  rppPosDayEmp * next () {
    return (rppPosDayEmp*)aipDemonItr::next();
  }

};

//======================================================================
//  rppProjWeekEmpDayItr -  Iterator for re-ordered normalized solution
//                             data, including a week-number

class rppProjWeekEmpDayItr : public aipDemonItr {

public:

  rppProjWeekEmpDayItr (aipPandemonium *p) {
    set_demon_itr(p,0);
  }

  rppProjWeekEmpDayItr (const rppProjWeekEmpDayItr& x) {
    set_demon_itr (x.pandemonium(), x.current());
  }

  virtual ~rppProjWeekEmpDayItr () {}

  rppProjWeekEmpDayItr& operator = (const rppProjWeekEmpDayItr& x) {
    set_demon_itr(x.pandemonium(), x.current());
    return *this;
  }

  rppProjWeekEmpDay * first () {
    return (rppProjWeekEmpDay*)aipDemonItr::first();
  }

  rppProjWeekEmpDay * next () {
    return (rppProjWeekEmpDay*)aipDemonItr::next();
  }

};

//======================================================================
//  rppProjWeekItr  -  Iterator for output-masters (weeks in a project)

class rppProjWeekItr : public aipDemonItr {

public:

  rppProjWeekItr (aipPandemonium *p) {
    set_demon_itr(p,0);
  }

  rppProjWeekItr (const rppProjWeekItr& x) {
    set_demon_itr (x.pandemonium(), x.current());
  }

  virtual ~rppProjWeekItr () {}

  rppProjWeekItr& operator = (const rppProjWeekItr& x) {
    set_demon_itr(x.pandemonium(), x.current());
    return *this;
  }

  rppProjWeek * first () {
    return (rppProjWeek*)aipDemonItr::first();
  }

  rppProjWeek * next () {
    return (rppProjWeek*)aipDemonItr::next();
  }

};

//======================================================================
//  rppProjWeekEmpItr  -  Iterator for output-details (Proj-Week Emps)

class rppProjWeekEmpItr : public aipDemonItr {

public:

  rppProjWeekEmpItr (aipPandemonium *p) {
    set_demon_itr(p,0);
  }

  rppProjWeekEmpItr (const rppProjWeekEmpItr& x) {
    set_demon_itr (x.pandemonium(), x.current());
  }

  virtual ~rppProjWeekEmpItr () {}

  rppProjWeekEmpItr& operator = (const rppProjWeekEmpItr& x) {
    set_demon_itr(x.pandemonium(), x.current());
    return *this;
  }

  rppProjWeekEmp * first () {
    return (rppProjWeekEmp*)aipDemonItr::first();
  }

  rppProjWeekEmp * next () {
    return (rppProjWeekEmp*)aipDemonItr::next();
  }

};

//======================================================================
//  rppFileDate  -  used to read/write dates to/from a file

class rppFileDate {

  char   m_yyyy_mm_dd[File_Date_Len+1];
  long   m_yyyymmdd;

protected:

  void reset () { m_yyyy_mm_dd[0] = '\0';  m_yyyymmdd = 0; }

public:

  rppFileDate (const char *a_yyyy_mm_dd);
  rppFileDate (long a_yyyymmdd);
  ~rppFileDate ();

  int is_valid ();

  const char * file_date () const { return m_yyyy_mm_dd; }
  long         long_date () const { return m_yyyymmdd;   }

};

//======================================================================
//  rppFileTime  -  used to read/write dates to/from a file

class rppFileTime {

  char   m_hh_mm[File_Time_Len+1];
  long   m_hhmm;

protected:

  void reset () { m_hh_mm[0] = '\0';  m_hhmm = 3333; }

public:

  rppFileTime (const char *a_hh_mm);
  rppFileTime (long a_hhmm);
  ~rppFileTime ();

  int is_valid ();

  const char * file_time () const { return m_hh_mm; }
  long         long_time () const { return m_hhmm;   }

};

//======================================================================

#endif

//======================================================================
//                           License
//
//   Permission is hereby granted, free of charge, to any
//   person obtaining a copy of this software and associated
//   documentation files (the "Software"), to deal in the Software
//   without restriction, including without limitation the rights
//   to use, copy, modify, merge, publish, distribute, sublicense,
//   and/or sell copies of the Software, and to permit persons to
//   whom the Software is furnished to do so, subject to the
//   following conditions:
//
//   The copyright notice and this license shall be included in all
//   copies or substantial portions of the Software.
//
//   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
//   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
//   OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
//   NON-INFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
//   HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
//   WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
//   FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
//   OTHER DEALINGS IN THE SOFTWARE.
//
//**********************************************************************