| Quintiq file version 2.0 | 
| #parent: #root | 
| Method GetBaseAvailableCapacity ( | 
|   const ShiftPattern shiftpattern | 
| ) const declarative as Duration | 
| { | 
|   TextBody: | 
|   [* | 
|     value := Duration::Zero(); | 
|      | 
|     datetimevector := DateTimeVector::Construct(); | 
|     durationvector := RealVector::Construct(); | 
|      | 
|     planningup := ifexpr( this.IsPlanning(),  | 
|                             this,                                             // Case 1: planning UnitPeriod: aggregate values from associated period tasks  | 
|                             this.PlanningUP().astype( UnitPeriodTimeBase ) ); // Case 2: base, non planning UnitPeriod: disaggregate value from planning UnitPeriod | 
|                             | 
|     if( not isnull( planningup ) ) | 
|     { | 
|       if( not isnull( planningup.Period_MP() )  | 
|           and not isnull( shiftpattern )  | 
|           and not planningup.Period_MP().IsInHour() ) //gdn1 HourlyPeriod is not applicable for ShiftPattern | 
|       { | 
|         lastshiftday := planningup.StartDate() - planningup.Period_MP().Start().StartOfWeek().Date() + 1 | 
|          | 
|         nrdaysinthisperiod := planningup.Duration().DaysAsReal(); | 
|            | 
|         firstday := planningup.Period_MP().Start(); | 
|         numberofshiftday := shiftpattern.ShiftDay( relsize ); | 
|       | 
|         if( not isnull( planningup.Previous() ) ) | 
|         { | 
|           lastshiftday := planningup.Previous().astype( UnitPeriodTimeBase ).PreviousPeriodLastShiftDay() + 1; | 
|          | 
|         } | 
|      | 
|         for( i := 0; i < nrdaysinthisperiod and firstday + Duration::Days( i ) >= planningup.Unit().StartDate().DateTime() ; i++ ) | 
|         { | 
|           shiftday := lastshiftday + i; | 
|      | 
|           if( shiftday > numberofshiftday ) | 
|           { | 
|             shiftday := shiftday mod numberofshiftday; | 
|      | 
|             if( shiftday = 0 ) | 
|             { | 
|               shiftday := numberofshiftday; | 
|             } | 
|           } | 
|      | 
|           shift := select( shiftpattern, ShiftDay, shift, shift.Day() = shiftday, true ); | 
|           unavailable := planningup.Unit().UnavailableTime( firstday + Duration::Days( i ), firstday + Duration::Days( i + 1 ) ); | 
|      | 
|           if( not isnull( shift ) ) | 
|           { | 
|             shiftduration := maxvalue( ( shift.Capacity() - unavailable ), Duration::Zero() ); | 
|             //value := value + shiftduration; | 
|             datetimevector.Append( firstday + Duration ::Days( i ) ); | 
|             durationvector.Append( shiftduration.HoursAsReal() ); | 
|           } | 
|         } // for  | 
|         | 
|         value := this.GetPlanningCapacity( datetimevector, durationvector ); | 
|       }// if planning period not in hour | 
|       else if ( planningup.Period_MP().DurationInDays() < 1 )   //gdn1 HourlyPeriod is always same as PeriodDuration  | 
|       { | 
|         value := planningup.Unit().UnitCalendar().AvailableTime( planningup.Start(), planningup.End(), 0.00000001 ); // Check calendar to make hourly period work with the calendar | 
|       } | 
|        | 
|       value := maxvalue( ( value * planningup.Efficiency() * planningup.Allocation()  -  ( planningup.Maintenance() * this.PlanningSystemRatio() ) )* planningup.NrOfOpen(), Duration::Zero() );    | 
|     } | 
|      | 
|     return value; | 
|   *] | 
| } |