[
https://issues.jboss.org/browse/DROOLS-1071?page=com.atlassian.jira.plugi...
]
Geoffrey De Smet moved PLANNER-541 to DROOLS-1071:
--------------------------------------------------
Project: Drools (was: OptaPlanner)
Key: DROOLS-1071 (was: PLANNER-541)
Issue Type: Enhancement (was: Bug)
Workflow: GIT Pull Request workflow (was: classic default workflow)
Component/s: core engine
(was: optaplanner-core)
Steps to Reproduce: (was: DRL:
{code:java}
package com.rdthree.plenty.services.activities.planner;
dialect "java"
import org.optaplanner.core.api.score.buildin.simple.SimpleScoreHolder;
import org.optaplanner.core.api.score.buildin.hardsoft.HardSoftScoreHolder;
import org.joda.time.Interval;
import org.joda.time.DateTime;
import org.apache.commons.lang.time.DateUtils;
import org.optaplanner.core.api.domain.solution.PlanningEntityCollectionProperty;
import org.optaplanner.core.api.domain.solution.PlanningSolution;
import org.optaplanner.core.api.domain.solution.Solution;
import org.optaplanner.core.api.domain.valuerange.ValueRangeProvider;
import org.optaplanner.core.api.score.buildin.hardsoft.HardSoftScore;
import com.rdthree.plenty.config.GeneralPrefs;
import com.rdthree.plenty.services.activities.helpers.dtos.TaskPlannerDto;
import
com.rdthree.plenty.services.activities.helpers.dtos.TaskResourceAllocationPlannerDto;
import com.rdthree.plenty.services.activities.helpers.dtos.SkillsAndRatesPlannerDto;
import
com.rdthree.plenty.services.activities.helpers.dtos.EquipmentEquipmentTypesPlannerDto;
import com.rdthree.plenty.services.activities.helpers.dtos.ProductPlannerDto;
import com.rdthree.plenty.services.activities.helpers.dtos.LabourDayOffPlannerDto;
import com.rdthree.plenty.services.activities.helpers.dtos.OnHandForProduct;
import com.rdthree.plenty.services.activities.planner.TaskRequirementsMapper;
import com.rdthree.plenty.domain.users.LabourDayOff.ApprovalState;
import com.rdthree.plenty.services.activities.planner.ScheduleState;
global HardSoftScoreHolder scoreHolder;
dialect "java"
dialect "mvel"
// ############################################################################
// Soft constraints
// ############################################################################
// DOC
rule "setAllConflictingToFalseFirst"
salience 100
when
$allocation : TaskResourceAllocationPlannerDto()
then
$allocation.setScheduleState(ScheduleState.SCHEDULING);
$allocation.setLabourDayOffConflict(null);
$allocation.setProductShortage(0);
end
rule "taskDateChangeRule"
when
TaskPlannerDto($taskId : id, $taskStart : interval.getStart().toDate())
TaskRequirementsMapper( taskId == $taskId, $taskReqStartMS : startDate.getTime(),
startDate.getTime() != $taskStart.getTime())
then
scoreHolder.addSoftConstraintMatch(kcontext, Math.round(Math.abs($taskReqStartMS -
$taskStart.getTime()) / 1000 / 60 / 60) * -100);
end
rule "taskPlanIndexChangeRule"
when
$task1 : TaskPlannerDto($task1Activity : activity, $task1Plan : activity.getPlan(),
$task1Start : interval.getStart().toDate())
TaskPlannerDto(!activity.equals($task1Activity), activity.getPlan().equals($task1Plan),
$task1Activity.indexInPlan > activity.indexInPlan, interval.getStart().toDate() <
$task1Start)
TaskPlannerDto(!activity.equals($task1Activity), activity.getPlan().equals($task1Plan),
$task1Activity.indexInPlan < activity.indexInPlan, interval.getStart().toDate() <
$task1Start)
then
scoreHolder.addHardConstraintMatch(kcontext, -100000);
end
rule "taskLengthChangeRule"
when
TaskPlannerDto($taskId : id, $taskLength : interval.toPeriod().getDays())
TaskRequirementsMapper( taskId == $taskId, $taskReqLength : length,
length!=$taskLength)
then
scoreHolder.addSoftConstraintMatch(kcontext, Math.abs($taskReqLength -
$taskLength) * -1000);
end
rule "taskResourceChangeRule"
when
$allocation : TaskResourceAllocationPlannerDto( $taskId : taskId )
$mapper : TaskRequirementsMapper( taskId == $taskId )
TaskRequirement( resourceClass.equals($allocation.getResourceClass()),
resourceTypeOrSkill.getId() == $allocation.getResourceTypeId(), originalResource.getId()
!= $allocation.getResource().getId()) from $mapper.getRequirements()
then
scoreHolder.addSoftConstraintMatch(kcontext, -10);
end
// This rule checks if the allocated resource has already been allocated to the same task
rule "duplicateResourceAllocation"
when
TaskPlannerDto($taskId : id)
TaskResourceAllocationPlannerDto($alloc1Id : id, taskId == $taskId, $alloc1Resource :
resource)
TaskResourceAllocationPlannerDto(id != $alloc1Id, taskId == $taskId, resource.getId() ==
$alloc1Resource.getId())
then
scoreHolder.addHardConstraintMatch(kcontext, -100000);
end
// This rule creates a constraint based on overlap of two tasks which use the
// same labourer at the same time. The constraint is multipled by the size of the overlap
in days
rule "TaskLabourerTimeOverlap"
when
$task1 : TaskPlannerDto($task1Interval : interval)
$task1ResourceAllocation : TaskResourceAllocationPlannerDto(taskId == $task1.id,
resource instanceof SkillsAndRatesPlannerDto, $task1UserId : resource.getUserId())
$task2 : TaskPlannerDto($task1.id != id, $task1Interval.overlaps(interval))
$task2ResourceAllocation : TaskResourceAllocationPlannerDto(taskId == $task2.id,
resource instanceof SkillsAndRatesPlannerDto, resource.getUserId().equals($task1UserId))
then
scoreHolder.addHardConstraintMatch(kcontext,
$task1Interval.overlap($task2.getInterval()).toPeriod(org.joda.time.PeriodType.days()).getDays()
* -1);
$task1ResourceAllocation.setScheduleState(ScheduleState.CONFLICT);
$task2ResourceAllocation.setScheduleState(ScheduleState.CONFLICT);
$task1.setState(ScheduleState.CONFLICT);
$task2.setState(ScheduleState.CONFLICT);
end
// This rule creates a constraint based on overlap of a task and it's labour days off
// The constraint is multipled by the size of the overlap in days
rule "TaskLabourerDayOffOverlap"
when
$task1 : TaskPlannerDto($taskInterval : interval)
$task1ResourceAllocation : TaskResourceAllocationPlannerDto(taskId == $task1.id,
resource instanceof SkillsAndRatesPlannerDto, $task1UserId : resource.getUserId())
$labourDayOff : LabourDayOffPlannerDto(userId == $task1UserId,
$taskInterval.contains(new DateTime(date).plusMinutes(15)),
state.equals(ApprovalState.APPROVED))
then
scoreHolder.addHardConstraintMatch(kcontext, -1);
$task1ResourceAllocation.setScheduleState(ScheduleState.CONFLICT);
$task1ResourceAllocation.setLabourDayOffConflict($labourDayOff.getDate().toDate());
$task1.setState(ScheduleState.CONFLICT);
end
// This rule creates a constraint based on overlap of two tasks which use the
// same equipment at the same time. The constraint is multipled by the size of the overlap
in days
rule "TaskEquipmentTimeOverlap"
when
$task1 : TaskPlannerDto($task1Interval : interval)
$task1ResourceAllocation : TaskResourceAllocationPlannerDto(taskId == $task1.id,
resource instanceof EquipmentEquipmentTypesPlannerDto, $task1EquipmentId :
resource.getEquipmentId())
$task2 : TaskPlannerDto($task1.id != id, $task1Interval.overlaps(interval))
$task2ResourceAllocation : TaskResourceAllocationPlannerDto(taskId == $task2.id,
resource instanceof EquipmentEquipmentTypesPlannerDto, resource.getEquipmentId() ==
$task1EquipmentId)
then
scoreHolder.addHardConstraintMatch(kcontext,
$task1Interval.overlap($task2.getInterval()).toPeriod(org.joda.time.PeriodType.days()).getDays()
* -1);
$task1ResourceAllocation.setScheduleState(ScheduleState.CONFLICT);
$task2ResourceAllocation.setScheduleState(ScheduleState.CONFLICT);
$task1.setState(ScheduleState.CONFLICT);
$task2.setState(ScheduleState.CONFLICT);
end
// This rule create a constraint based on product defficiency for a product at a
taks's start date
rule "TaskProductShortage"
when
$task : TaskPlannerDto( $taskId : id, $taskNeedsProductBy :
interval.getStart().plusDays(0).withTimeAtStartOfDay())
$allocation : TaskResourceAllocationPlannerDto( taskId == $taskId, resource instanceof
ProductPlannerDto)
OnHandForProduct(date.compareTo($taskNeedsProductBy) == 0 , productId ==
$allocation.resource.getId(), $onHandAmount : amount, amount - $allocation.amount <=
0)
then
scoreHolder.addHardConstraintMatch(kcontext, $allocation.getAmount() * -1);
$allocation.setScheduleState(ScheduleState.CONFLICT);
$allocation.setProductShortage($allocation.getAmount());
$task.setState(ScheduleState.CONFLICT);
end
{code}
added domain classes as attachments
)
Affects Version/s: 6.4.0.Beta2
6.3.0.Final
(was: 6.3.0.Final)
(was: 6.4.0.Beta2)
NPE's stacktracke for an MvelConstraint.evaluate() should give a
line number from the source DRL file
-----------------------------------------------------------------------------------------------------
Key: DROOLS-1071
URL:
https://issues.jboss.org/browse/DROOLS-1071
Project: Drools
Issue Type: Enhancement
Components: core engine
Affects Versions: 6.4.0.Beta2, 6.3.0.Final
Environment: JDK: Java 7
OS: Mac OSX 10.10.2
IDE: Spring Tool Suite 3.6.4
Reporter: Ido Flax
Assignee: Geoffrey De Smet
Attachments: AbstractPlannerDto.java, activity-scoring.drl,
EquipmentEquipmentTypesPlannerDto.java, LabourDayOffPlannerDto.java,
OnHandForProduct.java, ProductInventoryTransactionPlannerDto.java, ProductPlannerDto.java,
SkillsAndRatesPlannerDto.java, TaskPlannerDto.java, TaskResourceAllocationPlannerDto.java,
TaskResourcePlannerDto.java, UserPlannerDto.java
The attached code generates an NPE when running optaplanner/drools, but that stacktrace
doesn't tell me which DRL line is responsible for it.
Stacktrace:
{code:java}
Caused by: java.lang.NullPointerException: null
at ConditionEvaluatoreaa3997683d949e28ce6eaf6feca0ced.evaluate(Unknown Source)
<================ No source DRL line
at org.drools.core.rule.constraint.MvelConstraint.evaluate(MvelConstraint.java:258)
at
org.drools.core.rule.constraint.MvelConstraint.isAllowedCachedLeft(MvelConstraint.java:226)
at
org.drools.core.common.DoubleBetaConstraints.isAllowedCachedLeft(DoubleBetaConstraints.java:111)
at org.drools.core.phreak.PhreakJoinNode.doLeftInserts(PhreakJoinNode.java:112)
at org.drools.core.phreak.PhreakJoinNode.doNode(PhreakJoinNode.java:75)
at
org.drools.core.phreak.RuleNetworkEvaluator.switchOnDoBetaNode(RuleNetworkEvaluator.java:547)
at
org.drools.core.phreak.RuleNetworkEvaluator.evalBetaNode(RuleNetworkEvaluator.java:533)
at org.drools.core.phreak.RuleNetworkEvaluator.evalNode(RuleNetworkEvaluator.java:369)
at org.drools.core.phreak.RuleNetworkEvaluator.innerEval(RuleNetworkEvaluator.java:329)
at org.drools.core.phreak.RuleNetworkEvaluator.outerEval(RuleNetworkEvaluator.java:163)
at
org.drools.core.phreak.RuleNetworkEvaluator.evaluateNetwork(RuleNetworkEvaluator.java:120)
at org.drools.core.phreak.RuleExecutor.reEvaluateNetwork(RuleExecutor.java:194)
at org.drools.core.phreak.RuleExecutor.evaluateNetworkAndFire(RuleExecutor.java:73)
at org.drools.core.common.DefaultAgenda.fireNextItem(DefaultAgenda.java:1003)
at org.drools.core.common.DefaultAgenda.fireLoop(DefaultAgenda.java:1346)
at org.drools.core.common.DefaultAgenda.fireAllRules(DefaultAgenda.java:1284)
at
org.drools.core.impl.StatefulKnowledgeSessionImpl.internalFireAllRules(StatefulKnowledgeSessionImpl.java:1303)
at
org.drools.core.impl.StatefulKnowledgeSessionImpl.fireAllRules(StatefulKnowledgeSessionImpl.java:1293)
at
org.drools.core.impl.StatefulKnowledgeSessionImpl.fireAllRules(StatefulKnowledgeSessionImpl.java:1274)
at
org.optaplanner.core.impl.score.director.drools.DroolsScoreDirector.calculateScore(DroolsScoreDirector.java:84)
at
org.optaplanner.core.impl.solver.recaller.BestSolutionRecaller.solvingStarted(BestSolutionRecaller.java:70)
at
org.optaplanner.core.impl.solver.DefaultSolver.solvingStarted(DefaultSolver.java:197)
at org.optaplanner.core.impl.solver.DefaultSolver.solve(DefaultSolver.java:175)
{code}
--
This message was sent by Atlassian JIRA
(v6.4.11#64026)