Quintiq file version 2.0
|
#parent: #root
|
Method GenerateOptCampaignSubPeriods
|
{
|
Description: 'Generate campaign sub period objects for opt campaign unit'
|
TextBody:
|
[*
|
this.OptCampaignUnitSubPeriod( relflush );
|
|
startpuzzle := this.OptCampaign().PuzzleStart();
|
endpuzzle := this.OptCampaign().PuzzleEnd();
|
tokenizer := OptCampaign::Tokenizer()
|
|
unit := Unit::FindUnitTypeIndex( this.UnitID() );
|
|
//First: create ocusp for last period of frozen horizon
|
lastfrozenup := maxselect( unit,
|
UnitPeriod,
|
up,
|
not up.IsFrozen()
|
and up.IsPlanning()
|
and up.Start() <= endpuzzle
|
and up.End() > startpuzzle
|
and Unit::GetIsPeriodFrozen( unit, up.Period_MP() ),
|
up.Start() )
|
|
firstcampaignvalue := "";
|
firsttransitionvalue := ""
|
|
if( not isnull( lastfrozenup ) )
|
{
|
lastfrozenperiod := lastfrozenup.Period_MP()
|
campaignonfrozenlimit := select( unit, Campaign_MP, c, c.Start() < lastfrozenperiod.End(), c.End() >= lastfrozenperiod.End() )
|
transitiononfrozenlimit := select( unit, Transition_MP, t, t.Start() < lastfrozenperiod.End(), t.End() >= lastfrozenperiod.End() )
|
|
if( not isnull( campaignonfrozenlimit ) )
|
{
|
firstcampaignvalue := campaignonfrozenlimit.Start().Format( "YM2D2 H2:m:s" )
|
+ tokenizer + campaignonfrozenlimit.End().Format( "YM2D2 H2:m:s" )
|
+ tokenizer + OptCampaign::TypeCampaign()
|
+ tokenizer + [String]campaignonfrozenlimit.Start()
|
+ tokenizer + [String]lastfrozenperiod.End()
|
+ tokenizer + [String]campaignonfrozenlimit.Key()
|
|
}
|
else if( not isnull( transitiononfrozenlimit ) )
|
{
|
firsttransitionvalue := transitiononfrozenlimit.Start().Format( "YM2D2 H2:m:s" )
|
+ tokenizer + transitiononfrozenlimit.End().Format( "YM2D2 H2:m:s" )
|
+ tokenizer + OptCampaign::TypeTransition()
|
+ tokenizer + [String]transitiononfrozenlimit.Start()
|
+ tokenizer + [String]minvalue( transitiononfrozenlimit.End(), unit.EndOfFrozen() )
|
+ tokenizer + [String]transitiononfrozenlimit.Key()
|
|
}
|
}
|
//Then, create other ocusps
|
|
endcampaignhorizon := unit.CampaignTypeRequirementHorizon();
|
//set the endpuzzle to take campaign horizon into account. Need the - 1 days here due to difference in inclusive / exclusive
|
endpuzzle := minvalue( endpuzzle, endcampaignhorizon - Duration::Days( 1 ) );
|
|
//the timeblock values will concatenated as follows:
|
//start time formatted to get correct sorting
|
//end time formatted to get correct sorting
|
//type of the timeblock (period, campaign or transition
|
//start time formatted as string that can be converted back to datetime using standard conversion
|
//end time formatted as string that can be converted back to datetime using standard conversion
|
//Reference key for fixed campaigns and transitions
|
periods := selectuniquevalues( unit
|
, UnitPeriod
|
, up
|
, not up.IsFrozen()
|
and up.IsPlanning()
|
and up.Start() <= endpuzzle
|
and up.End() > startpuzzle
|
and not Unit::GetIsPeriodFrozen( unit, up.Period_MP() )
|
, up.Start().Format( "YM2D2 H2:m:s" )
|
+ tokenizer + up.End().Format( "YM2D2 H2:m:s" )
|
+ tokenizer + OptCampaign::TypePeriod()
|
+ tokenizer + [String]up.Start()
|
+ tokenizer + [String]up.End()
|
+ tokenizer + [String]up.Key()
|
)
|
|
fixedcampaigns := selectuniquevalues( unit
|
, Campaign_MP
|
, campaign
|
, campaign.IsFrozen() //this should be changed to campagins being fixed
|
and campaign.Start() <= endpuzzle
|
and campaign.End() > startpuzzle
|
, campaign.Start().Format( "YM2D2 H2:m:s" )
|
+ tokenizer + campaign.End().Format( "YM2D2 H2:m:s" )
|
+ tokenizer + OptCampaign::TypeCampaign()
|
+ tokenizer + [String]campaign.Start()
|
+ tokenizer + [String]campaign.End()
|
+ tokenizer + [String]campaign.Key()
|
)
|
fixedtransitions := selectuniquevalues( unit
|
, Transition_MP
|
, transition
|
, transition.IsFrozen() //this should be changed to campagins being fixed
|
and transition.Start() <= endpuzzle
|
and transition.End() > startpuzzle
|
, transition.Start().Format( "YM2D2 H2:m:s" )
|
+ tokenizer + transition.End().Format( "YM2D2 H2:m:s" )
|
+ tokenizer + OptCampaign::TypeTransition()
|
+ tokenizer + [String]transition.Start()
|
+ tokenizer + [String]transition.End()
|
+ tokenizer + [String]transition.Key()
|
)
|
|
if( not firstcampaignvalue = "" )
|
{
|
fixedcampaigns := fixedcampaigns.Union( firstcampaignvalue )
|
}
|
if( not firsttransitionvalue = "" )
|
{
|
fixedtransitions := fixedtransitions.Union( firsttransitionvalue )
|
}
|
|
timeblocks := periods.Union( fixedcampaigns ).Union( fixedtransitions );
|
timeblocks := timeblocks.Sort();
|
//init variables
|
if( timeblocks.Size() > 0 )
|
{
|
//Get the values from the first element. This will prevent having to
|
timeblockelements := timeblocks.Element( 0 ).Tokenize( tokenizer );
|
subperiodstart := [DateTime]timeblockelements.Element( 3 ); //get the start that can be converted
|
subperiodend := [DateTime]timeblockelements.Element( 4 ); //get the end that can be converted
|
subperiodtype := timeblockelements.Element( 2 );
|
subperiodrefkey := [Key]timeblockelements.Element( 5 );
|
subperiodisfixed := subperiodtype <> "Period";
|
|
subperiodend := minvalue( subperiodend, endcampaignhorizon );
|
|
traverse( timeblocks, Elements, timeblock )
|
{
|
timeblockelements := timeblock.Tokenize( tokenizer );
|
timeblockstart := [DateTime]timeblockelements.Element( 3 );
|
timeblockend := [DateTime]timeblockelements.Element( 4 );
|
timeblocktype := timeblockelements.Element( 2 );
|
timeblockrefkey := [Key]timeblockelements.Element( 5 )
|
timeblockisfixed := timeblocktype <> "Period";
|
|
//If the next period starts earlier than the previous ends and its a fixed period
|
//then keep creating fixed sub periods until the end of the fixed campaign/transition is reached
|
if( timeblockstart < subperiodend and subperiodisfixed )
|
{
|
endsubperiodfixed := timeblockstart
|
//Close off the previous subperiod for the fixed block, but only if the subperiod has a duration
|
if( endsubperiodfixed > subperiodstart )
|
{
|
OptCampaignUnitSubPeriod::Create( this, subperiodstart, endsubperiodfixed, subperiodtype, subperiodrefkey, subperiodisfixed );
|
}
|
//Set the start time to the end of subperiod that was just created
|
subperiodstart := endsubperiodfixed;
|
//if the fixed period ends in this subperiod create an additional block for the end part of the fixed block
|
if( subperiodend < timeblockend )
|
{
|
OptCampaignUnitSubPeriod::Create( this, subperiodstart, subperiodend, subperiodtype, subperiodrefkey, subperiodisfixed );
|
//now set the variables for the next subperiod
|
subperiodstart := subperiodend
|
subperiodend := timeblockend;
|
subperiodtype := timeblocktype;
|
subperiodrefkey := timeblockrefkey;
|
subperiodisfixed := timeblockisfixed;
|
}
|
}
|
else
|
{
|
//when we have a fixed supperiod then the end date is known, in other cases the enddate the previous period is the start of the next period
|
if( not subperiodisfixed )
|
{
|
subperiodend := timeblockstart;
|
}
|
//Close off the previous timeblock, but only if the subperiod has a duration
|
if( subperiodend > subperiodstart )
|
{
|
OptCampaignUnitSubPeriod::Create( this, subperiodstart, subperiodend, subperiodtype, subperiodrefkey, subperiodisfixed );
|
}
|
//Setup the next period
|
//the start is the start of the period or the end of the previous period which could be later if it was a fixed period
|
subperiodstart := timeblockstart
|
subperiodend := minvalue( timeblockend, endcampaignhorizon );
|
subperiodtype := timeblocktype;
|
subperiodrefkey := timeblockrefkey;
|
subperiodisfixed := timeblockisfixed;
|
}
|
}
|
//Close the last timeblock
|
if( subperiodend > subperiodstart )
|
{
|
//Close off the previous timeblock
|
OptCampaignUnitSubPeriod::Create( this, subperiodstart, subperiodend, subperiodtype, subperiodrefkey, subperiodisfixed );
|
}
|
}
|
*]
|
}
|