📄 rrproj_fctry.cpp
字号:
//**********************************************************************
// rrproj_fctry.cpp function bodies for rrproj_fctry.h
//
// Copyright (c) 2008 Brian Marshall
//
// See the license at end of this file.
//
// Developers/Contributers:
// [BRM] Brian Marshall - Calgary - bmarshal@agt.net
//
// 08/01/28 [BRM] began development
//
//----------------------------------------------------------------------
#include "rrproj_fctry.h"
// for debugging...
// #include <string.h>
// #include <iostream>
// using namespace std;
//======================================================================
// Factory Data
//
// 3 datasets:
// - problem - setup with data from the user
// - solver - factory creates it from the problem dataset
// - factory - temporary data owned by the factory
//
// variable names in functions:
// The first letter of some variables in functions indicates the
// dataset from which the function is set:
// pemp is an emp from the problem
// semp is an emp from the solver
// fempid is an empid from the factory
//
// class name prefix
// rpp rrproj problem (setup by application)
// rps rrproj solver (used by the problem)
// rpf rrproj factory (solver-factory)
//
//----------------------------------------------------------------------
// Constructor
rpfFactory::rpfFactory (rppProblem *pdata) {
m_problem_data = pdata;
m_emp_ids = new aipPandemonium;
if (m_emp_ids) m_emp_ids->set_is_distinct();
m_opts = new aipPandemonium;
if (m_opts) m_opts->set_is_distinct();
}
//----------------------------------------------------------------------
// Destructor
rpfFactory::~rpfFactory () {
if (m_emp_ids) delete m_emp_ids;
if (m_opts) delete m_opts;
}
//----------------------------------------------------------------------
// create and setup a new rpsProblem from the problem data.
rpsProblem * rpfFactory::make_rps_problem () {
if (!m_problem_data) return 0;
rpsProblem *sp = new rpsProblem ();
if (!sp) return 0;
sp->set_num_try (m_problem_data->num_tries());
int status = 1;
if (status) status = setup(sp);
if (!status) return 0;
return sp;
}
//----------------------------------------------------------------------
// setup an rpsProblem - return true on success
int rpfFactory::setup (rpsProblem *sprob) {
int status = 1;
// iterators in the problem data
rppPosDayItr pditr = pprob()->posday_iterator();
rppPosEmpItr peitr = pprob()->posemp_iterator();
rppAssgnItr aitr = pprob()->assgn_iterator();
// iterators in the factory data
rpfOptItr oitr = opt_iterator();
// setup pos, posday, dcsn
if (status) status = handle_pd (pditr, sprob);
// setup emp, empday
if (status) status = handle_pe_a (peitr, aitr, sprob);
// add to the opt list
if (status) status = handle_a_ed (aitr, sprob);
// add to opt list
if (status) status = handle_pe_pd_ed (peitr, sprob);
// setup options from opt list
if (status) status = handle_o (oitr, sprob);
return status;
}
//----------------------------------------------------------------------
// handle the set of PosDays in the problem data
//
// create positions and handle individual posdays
int rpfFactory::handle_pd (rppPosDayItr pditr, rpsProblem *sprob) {
int status = 1;
long min_yyyymmdd = 20200101;
long max_yyyymmdd = 19800101;
long prev_pos_id = very_unlikely_id();
long pner; // num-emps_required in the problem
rppPosDay *ppd; // posday in the problem
rpsPosDay *spd; // posday in the solver
rpsPosition *spos; // pos in the solver
if (status) { // create (Pos), (PosDay), (Dcsn)
for (ppd = pditr.first(); ppd; ppd = pditr.next()) {
if (ppd->pos_id() != prev_pos_id) {
spos = new rpsPosition(ppd->pos_id(), sprob);
if (!spos) { status = 0; log(" Err new rpsPosition"); break; }
sprob->add_position(spos);
prev_pos_id = ppd->pos_id();
}
spd = new rpsPosDay(spos, ppd->yyyymmdd(), ppd->proj_id(),
ppd->start_hhmm(), ppd->end_hhmm());
if (!spd) { status = 0; log("Err new rpsPosDay"); break; }
spos->add_posday(spd);
pner = ppd->num_emps_req();
if (pner < 1 || pner > 1000) {
status = 0; log("Err bad num-emps-required"); break;
}
rpsDecision *sdcsn = new rpsDecision(spd, pner);
if (!sdcsn) {status = 0; log("Err new rpsDecision"); break; }
sprob->add_decision(sdcsn);
spd->set_dcsn(sdcsn);
long ppd_yyyymmdd = ppd->yyyymmdd();
if (ppd_yyyymmdd < min_yyyymmdd) min_yyyymmdd = ppd_yyyymmdd;
if (ppd_yyyymmdd > max_yyyymmdd) max_yyyymmdd = ppd_yyyymmdd;
}
}
if (status) {
sprob->set_day_range (min_yyyymmdd, max_yyyymmdd);
}
return status;
}
//----------------------------------------------------------------------
// handle the sets of posemps and assignments in the problem data
//
// create a distinct list of empids, and then create emps and empdays
// (which also uses empdows and empoffs)
int rpfFactory::handle_pe_a (rppPosEmpItr peitr, rppAssgnItr aitr,
rpsProblem *sprob) {
int status = 1;
rpfEmpId *feid; // an empid owned by the factory
long prev_eid = very_unlikely_id();
if (status) { // start {EmpId}
rppPosEmp *ppe; // a posemp in the problem
for (ppe = peitr.first(); ppe; ppe = peitr.next()) {
if (ppe->emp_id() != prev_eid) {
feid = new rpfEmpId(ppe->emp_id());
if (!feid) { status = 0; log("Err new rpfEmpId"); break; }
m_emp_ids->add (feid); // list is forced distinct
prev_eid = ppe->emp_id();
}
}
}
if (status) { // add to {EmpId}
rppAssignment *pa; // an assignment in the problem
for (pa = aitr.first(); pa; pa = aitr.next()) {
if (pa->emp_id() != prev_eid) {
feid = new rpfEmpId(pa->emp_id());
if (!feid) { status = 0; log("Err new rpfEmpId"); break; }
m_emp_ids->add (feid); // list is forced distinct
prev_eid = pa->emp_id();
}
}
}
// we now have a distinct list of emp_ids
rpsEmployee *semp; // an emp in the solver
if (status) { // create (Emp)
rpfEmpIdItr eiditr = empid_iterator();
for (feid = eiditr.first(); feid; feid = eiditr.next()) {
semp = new rpsEmployee(feid->emp_id(), sprob);
if (!semp) { status = 0; log("Err new rpsEmployee"); break; }
sprob->add_employee(semp);
status = handle_e (semp, sprob);
if (!status) break;
}
}
return status;
}
//----------------------------------------------------------------------
// handle a solver emp - create empday
int rpfFactory::handle_e (rpsEmployee *semp, rpsProblem *sprob) {
int status = 1;
if (status) {
apply_empdaypos(semp);
}
if (status) { // create (EmpDay)
aipTime curday( (sprob->start_day()) );
aipTime lastday( (sprob->end_day()) );
for ( ; curday <= lastday; curday.add_days(1) ) {
long x_yyyymmdd = curday.yyyymmdd();
if (!x_yyyymmdd) { status = 0; log("Err h_e yyyymmdd"); break; }
if ( emp_is_off (semp->emp_id(), curday) ) continue;
long x_start_hhmm, x_end_hhmm;
long x_dow = curday.days_since_sunday();
get_dow_data (semp->emp_id(), x_dow,
&x_start_hhmm, &x_end_hhmm);
if (x_start_hhmm == x_end_hhmm) continue;
rpsEmpDay *sed = new rpsEmpDay (semp, x_yyyymmdd,
x_start_hhmm, x_end_hhmm);
if (!sed) { status = 0; log("Err new rpsEmpDay"); break; }
semp->add_empday(sed);
}
}
return status;
}
//----------------------------------------------------------------------
// handle the set of assignments (plus solution EmpDays)
//
// start a list of options (that is forced to have distinct keys)
int rpfFactory::handle_a_ed (rppAssgnItr aitr, rpsProblem *sprob) {
int status = 1;
if (status) { // create {opt} from [Assgnmnt]
rppAssignment *pa; // an assignment in the problem
rpsPosDay *spd; // a posday in the solver
rpsEmpDay *sed; // an empday in the solver
for (pa = aitr.first(); pa; pa = aitr.next()) {
aipTime curday(pa->start_yyyymmdd());
aipTime lastday(pa->end_yyyymmdd());
for ( ; curday <= lastday; curday.add_days(1) ) {
spd = find_posday (pa->pos_id(), curday.yyyymmdd(),
pa->proj_id(), sprob);
if (!spd) continue;
sed = find_empday (pa->emp_id(), curday.yyyymmdd(), sprob);
if (!sed) continue;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -