add example with rule project dependancy
This commit is contained in:
parent
efb424d524
commit
f2d9bc13ca
41 changed files with 2991 additions and 35 deletions
78
cost-calculation-base/README.md
Normal file
78
cost-calculation-base/README.md
Normal file
|
|
@ -0,0 +1,78 @@
|
||||||
|
# Cost Calculation project
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# Requirements
|
||||||
|
We are working for a retail company that buys its products from different places in Asian mostly. each shop can go to the buying web site and say what he wants and put an order.
|
||||||
|
Up to now, the transport cost was a estimated but not calculated on the content of the order.
|
||||||
|
The purpose is to implement such a calculator.
|
||||||
|
|
||||||
|
## Data model
|
||||||
|
|
||||||
|
A customer puts an order that contains products. An order contains a lost of products with a number.
|
||||||
|
A product has
|
||||||
|
* a name
|
||||||
|
* a height,
|
||||||
|
* a width,
|
||||||
|
* a depth,
|
||||||
|
* transport type : if the product can be put with other products in a pallet, individual(alone) or bulk (like sand for example)
|
||||||
|
* a weight
|
||||||
|
|
||||||
|
A product can be put on a pallet. a pallet 120 cm width and and 80 cm depth. It can be maximum 2 meters height and the weight should not exceed 1400 kg. We should use a simple algorithm to fill each pallet. It will be not optimized but we should used that as a margin of the costs. a product that is bigger than 60 cm in width or depth or higher than 1m should be put alone in a pallet.
|
||||||
|
|
||||||
|
All products start from the same city and go to the same city in an order. A trip is composed f steps. Each step can be done by train, boat or truck.
|
||||||
|
|
||||||
|
|
||||||
|
Here is the list of products in our test order.
|
||||||
|
|
||||||
|
| Product | Transport type | Number | Height | Weight | depth | weight |
|
||||||
|
| -- | -- | -- | -- | -- | -- | -- |
|
||||||
|
| drill | pallet | 1000 | 20cm | 40cm | 30cm | 2 kg |
|
||||||
|
| screwdriver | pallet | 30000 | 3cm | 2cm | 20cm | 0,2 kg |
|
||||||
|
| Sand | bulk | | | | | 35 Tons |
|
||||||
|
| Gravel | bulk | | | | | 14 Tons |
|
||||||
|
| furniture | individual |23 | | | | 500 kg |
|
||||||
|
|
||||||
|
And the trip is a follows :
|
||||||
|
|
||||||
|
| # | start city | arrival city | distance (km) | travel mode |
|
||||||
|
| -- | -- | -- | -- | -- |
|
||||||
|
| 1 | Shangai | Rotterdam | 22000 | Boat|
|
||||||
|
| 2 | Rotterdam | Tournai | 300 | Train |
|
||||||
|
| 3 | Tournai | Lille | 20 | Truck |
|
||||||
|
|
||||||
|
|
||||||
|
there are 3 types of costs :
|
||||||
|
- transport costs per Pallet
|
||||||
|
|
||||||
|
| Transport| Cost
|
||||||
|
| -- | -- |
|
||||||
|
| boat | 0,2€/km |
|
||||||
|
| Train | 0,5€/km |
|
||||||
|
| Truck | 1€/km |
|
||||||
|
|
||||||
|
- Taxes
|
||||||
|
|
||||||
|
| City| Cost
|
||||||
|
| -- | -- |
|
||||||
|
| Shangai | 0,02€/kg |
|
||||||
|
| Rotterdam | 0,05€/kg and 1€ per handling person |
|
||||||
|
| Tournai | 2€ per handling person |
|
||||||
|
| Lille | 30€ per handling person |
|
||||||
|
|
||||||
|
|
||||||
|
- handling
|
||||||
|
|
||||||
|
| City| Cost
|
||||||
|
| -- | -- |
|
||||||
|
| Shangai | 20€/hour and a person can handle 13 pallets/hour |
|
||||||
|
| Rotterdam | 45€/hour and a person can handle 60 pallets/hour |
|
||||||
|
| Tournai | 67€/hour and can handle 40 pallets/hour |
|
||||||
|
| Lille | 79€/hour and can handle 30 pallets/hour |
|
||||||
|
|
||||||
|
The handling should not take more than 12 hours.
|
||||||
|
|
||||||
|
[Data Model ](src/main/java/cost/README.md)
|
||||||
|
|
||||||
|
[The rules we implemented ](src/main/resources/rules/README.md)
|
||||||
34
cost-calculation-base/cost-calculation-base.iml
Normal file
34
cost-calculation-base/cost-calculation-base.iml
Normal file
|
|
@ -0,0 +1,34 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<module org.jetbrains.idea.maven.project.MavenProjectsManager.isMavenModule="true" type="JAVA_MODULE" version="4">
|
||||||
|
<component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_7" inherit-compiler-output="false">
|
||||||
|
<output url="file://$MODULE_DIR$/target/classes" />
|
||||||
|
<output-test url="file://$MODULE_DIR$/target/test-classes" />
|
||||||
|
<content url="file://$MODULE_DIR$">
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/src/main/java" isTestSource="false" />
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/src/main/resources" type="java-resource" />
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/src/test/java" isTestSource="true" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/target" />
|
||||||
|
</content>
|
||||||
|
<orderEntry type="inheritedJdk" />
|
||||||
|
<orderEntry type="sourceFolder" forTests="false" />
|
||||||
|
<orderEntry type="library" name="Maven: org.drools:drools-compiler:6.5.0.Final" level="project" />
|
||||||
|
<orderEntry type="library" name="Maven: org.drools:drools-core:6.5.0.Final" level="project" />
|
||||||
|
<orderEntry type="library" name="Maven: commons-codec:commons-codec:1.4" level="project" />
|
||||||
|
<orderEntry type="library" name="Maven: org.kie:kie-internal:6.5.0.Final" level="project" />
|
||||||
|
<orderEntry type="library" name="Maven: org.antlr:antlr-runtime:3.5" level="project" />
|
||||||
|
<orderEntry type="library" name="Maven: org.mvel:mvel2:2.2.8.Final" level="project" />
|
||||||
|
<orderEntry type="library" name="Maven: com.thoughtworks.xstream:xstream:1.4.9" level="project" />
|
||||||
|
<orderEntry type="library" name="Maven: xmlpull:xmlpull:1.1.3.1" level="project" />
|
||||||
|
<orderEntry type="library" name="Maven: xpp3:xpp3_min:1.1.4c" level="project" />
|
||||||
|
<orderEntry type="library" name="Maven: com.google.protobuf:protobuf-java:2.6.0" level="project" />
|
||||||
|
<orderEntry type="library" name="Maven: org.slf4j:slf4j-api:1.7.2" level="project" />
|
||||||
|
<orderEntry type="library" name="Maven: org.eclipse.jdt.core.compiler:ecj:4.4.2" level="project" />
|
||||||
|
<orderEntry type="library" name="Maven: org.jbpm:jbpm-bpmn2:6.5.0.Final" level="project" />
|
||||||
|
<orderEntry type="library" name="Maven: org.jbpm:jbpm-flow-builder:6.5.0.Final" level="project" />
|
||||||
|
<orderEntry type="library" name="Maven: org.jbpm:jbpm-flow:6.5.0.Final" level="project" />
|
||||||
|
<orderEntry type="library" name="Maven: joda-time:joda-time:2.2" level="project" />
|
||||||
|
<orderEntry type="library" scope="TEST" name="Maven: junit:junit:4.5" level="project" />
|
||||||
|
<orderEntry type="library" name="Maven: org.kie:kie-api:6.5.0.Final" level="project" />
|
||||||
|
<orderEntry type="module" module-name="drools-lesson-pojo" />
|
||||||
|
</component>
|
||||||
|
</module>
|
||||||
43
cost-calculation-base/pom.xml
Normal file
43
cost-calculation-base/pom.xml
Normal file
|
|
@ -0,0 +1,43 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xmlns="http://maven.apache.org/POM/4.0.0"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<parent>
|
||||||
|
<artifactId>droolscourse</artifactId>
|
||||||
|
<groupId>com.pymma-software.droolscourse</groupId>
|
||||||
|
<version>2.0.0-SNAPSHOT</version>
|
||||||
|
</parent>
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
<artifactId>cost-calculation-base</artifactId>
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.drools</groupId>
|
||||||
|
<artifactId>drools-compiler</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.eclipse.jdt.core.compiler</groupId>
|
||||||
|
<artifactId>ecj</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.jbpm</groupId>
|
||||||
|
<artifactId>jbpm-bpmn2</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>junit</groupId>
|
||||||
|
<artifactId>junit</artifactId>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.kie</groupId>
|
||||||
|
<artifactId>kie-api</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.pymma-software.droolscourse</groupId>
|
||||||
|
<artifactId>drools-lesson-pojo</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
</project>
|
||||||
|
|
@ -0,0 +1,57 @@
|
||||||
|
package cost;
|
||||||
|
|
||||||
|
public class CalculatedElement {
|
||||||
|
private String key;
|
||||||
|
private int numberValue;
|
||||||
|
private String stringValue;
|
||||||
|
private long longValue;
|
||||||
|
private double doubleValue;
|
||||||
|
|
||||||
|
public String getKey() {
|
||||||
|
return key;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setKey(String key) {
|
||||||
|
this.key = key;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getNumberValue() {
|
||||||
|
return numberValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setNumberValue(int numberValue) {
|
||||||
|
this.numberValue = numberValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getStringValue() {
|
||||||
|
return stringValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setStringValue(String stringValue) {
|
||||||
|
this.stringValue = stringValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getLongValue() {
|
||||||
|
return longValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setLongValue(long longValue) {
|
||||||
|
this.longValue = longValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getDoubleValue() {
|
||||||
|
return doubleValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDoubleValue(double doubleValue) {
|
||||||
|
this.doubleValue = doubleValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "CalculatedElement [key=" + key + ", numberValue=" + numberValue + ", stringValue=" + stringValue
|
||||||
|
+ ", longValue=" + longValue + ", doubleValue=" + doubleValue + "]";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
30
cost-calculation-base/src/main/java/cost/City.java
Normal file
30
cost-calculation-base/src/main/java/cost/City.java
Normal file
|
|
@ -0,0 +1,30 @@
|
||||||
|
package cost;
|
||||||
|
|
||||||
|
public class City {
|
||||||
|
|
||||||
|
public static String ShangaiCityName = "Shangai";
|
||||||
|
public static String RotterdamCityName = "Rotterdam";
|
||||||
|
public static String TournaiCityName = "Tournai";
|
||||||
|
public static String LilleCityName = "Lille";
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
public City(String name) {
|
||||||
|
super();
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setName(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "City [name=" + name + "]";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,47 @@
|
||||||
|
package cost;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class CostCalculationRequest {
|
||||||
|
private Order order;
|
||||||
|
|
||||||
|
private Trip trip;
|
||||||
|
|
||||||
|
private List<Pallet> pallets = new ArrayList<Pallet>();
|
||||||
|
private List<CostElement> costElements = new ArrayList<CostElement>();
|
||||||
|
|
||||||
|
public Order getOrder() {
|
||||||
|
return order;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setOrder(Order order) {
|
||||||
|
this.order = order;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Trip getTrip() {
|
||||||
|
return trip;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTrip(Trip trip) {
|
||||||
|
this.trip = trip;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Pallet> getPallets() {
|
||||||
|
return pallets;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPallets(List<Pallet> pallets) {
|
||||||
|
this.pallets = pallets;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<CostElement> getCostElements() {
|
||||||
|
return costElements;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCostElements(List<CostElement> costElements) {
|
||||||
|
this.costElements = costElements;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,5 @@
|
||||||
|
package cost;
|
||||||
|
|
||||||
|
public interface CostElement {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,31 @@
|
||||||
|
package cost;
|
||||||
|
|
||||||
|
public class HandlingCostElement implements CostElement {
|
||||||
|
|
||||||
|
private double amount;
|
||||||
|
private City city;
|
||||||
|
|
||||||
|
public double getAmount() {
|
||||||
|
return amount;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAmount(double amount) {
|
||||||
|
this.amount = amount;
|
||||||
|
}
|
||||||
|
|
||||||
|
public City getCity() {
|
||||||
|
return city;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCity(City city) {
|
||||||
|
this.city = city;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "HandlingCostElement [amount=" + amount + ", city=" + city + "]";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,53 @@
|
||||||
|
package cost;
|
||||||
|
|
||||||
|
public class LeftToDistribute {
|
||||||
|
|
||||||
|
private OrderLine orderLine;
|
||||||
|
private long quantityLeft;
|
||||||
|
private double weightLeft;
|
||||||
|
|
||||||
|
|
||||||
|
public LeftToDistribute(OrderLine orderLine, double weightLeft) {
|
||||||
|
super();
|
||||||
|
this.orderLine = orderLine;
|
||||||
|
this.weightLeft = weightLeft;
|
||||||
|
}
|
||||||
|
|
||||||
|
public LeftToDistribute(OrderLine orderLine, long quantityLeft) {
|
||||||
|
super();
|
||||||
|
this.orderLine = orderLine;
|
||||||
|
this.quantityLeft = quantityLeft;
|
||||||
|
}
|
||||||
|
|
||||||
|
public OrderLine getOrderLine() {
|
||||||
|
return orderLine;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setOrderLine(OrderLine orderLine) {
|
||||||
|
this.orderLine = orderLine;
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getQuantityLeft() {
|
||||||
|
return quantityLeft;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setQuantityLeft(long quantityLeft) {
|
||||||
|
this.quantityLeft = quantityLeft;
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getWeightLeft() {
|
||||||
|
return weightLeft;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setWeightLeft(double weightLeft) {
|
||||||
|
this.weightLeft = weightLeft;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "LeftToDistribute [orderLine=" + orderLine + ", quantityLeft=" + quantityLeft + ", weightLeft="
|
||||||
|
+ weightLeft + "]";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
37
cost-calculation-base/src/main/java/cost/Order.java
Normal file
37
cost-calculation-base/src/main/java/cost/Order.java
Normal file
|
|
@ -0,0 +1,37 @@
|
||||||
|
package cost;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class Order {
|
||||||
|
private String id;
|
||||||
|
private List<OrderLine> orderLines = new ArrayList();
|
||||||
|
|
||||||
|
|
||||||
|
public Order(String id) {
|
||||||
|
super();
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public String getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void setId(String id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public List<OrderLine> getOrderLines() {
|
||||||
|
return orderLines;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void setOrderLines(List<OrderLine> orderLines) {
|
||||||
|
this.orderLines = orderLines;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
51
cost-calculation-base/src/main/java/cost/OrderLine.java
Normal file
51
cost-calculation-base/src/main/java/cost/OrderLine.java
Normal file
|
|
@ -0,0 +1,51 @@
|
||||||
|
package cost;
|
||||||
|
|
||||||
|
public class OrderLine {
|
||||||
|
|
||||||
|
private int numberItems;
|
||||||
|
private double weight;
|
||||||
|
private Product product;
|
||||||
|
|
||||||
|
|
||||||
|
public OrderLine(int numberItems, Product product) {
|
||||||
|
super();
|
||||||
|
this.numberItems = numberItems;
|
||||||
|
this.product = product;
|
||||||
|
}
|
||||||
|
|
||||||
|
public OrderLine(double weight, Product product) {
|
||||||
|
super();
|
||||||
|
this.weight = weight;
|
||||||
|
this.product = product;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getNumberItems() {
|
||||||
|
return numberItems;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setNumberItems(int numberItems) {
|
||||||
|
this.numberItems = numberItems;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Product getProduct() {
|
||||||
|
return product;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setProduct(Product product) {
|
||||||
|
this.product = product;
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getWeight() {
|
||||||
|
return weight;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setWeight(double weight) {
|
||||||
|
this.weight = weight;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "OrderLine [numberItems=" + numberItems + ", weight=" + weight + ", product=" + product + "]";
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
89
cost-calculation-base/src/main/java/cost/Pallet.java
Normal file
89
cost-calculation-base/src/main/java/cost/Pallet.java
Normal file
|
|
@ -0,0 +1,89 @@
|
||||||
|
package cost;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public class Pallet {
|
||||||
|
private boolean isFull = false;
|
||||||
|
private double heightLeft = 2.0;
|
||||||
|
private double width = 0.8;
|
||||||
|
private double depth = 1.2;
|
||||||
|
private Map<Product, Long> contentQuantity = new HashMap<Product, Long>();
|
||||||
|
private Map<Product, Double> contentWeight = new HashMap<Product, Double>();
|
||||||
|
private int palletType;
|
||||||
|
|
||||||
|
public Map<Product, Long> getContentQuantity() {
|
||||||
|
return contentQuantity;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Map<Product, Double> getContentWeight() {
|
||||||
|
return contentWeight;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addContent(Product product, Long quantity) {
|
||||||
|
if (contentQuantity.containsKey(product) == false) {
|
||||||
|
contentQuantity.put(product, quantity);
|
||||||
|
} else {
|
||||||
|
Long oldQuantity = contentQuantity.get(product);
|
||||||
|
oldQuantity = oldQuantity + quantity;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addContent(Product product, Double weight) {
|
||||||
|
if (contentWeight.containsKey(product) == false) {
|
||||||
|
contentWeight.put(product, weight);
|
||||||
|
} else {
|
||||||
|
Double oldQuantity = contentWeight.get(product);
|
||||||
|
oldQuantity = oldQuantity + weight;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isFull() {
|
||||||
|
return isFull;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFull(boolean isFull) {
|
||||||
|
this.isFull = isFull;
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getHeightLeft() {
|
||||||
|
return heightLeft;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setHeightLeft(double heightLeft) {
|
||||||
|
this.heightLeft = heightLeft;
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getWidth() {
|
||||||
|
return width;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setWidth(double width) {
|
||||||
|
this.width = width;
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getDepth() {
|
||||||
|
return depth;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDepth(double depth) {
|
||||||
|
this.depth = depth;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getPalletType() {
|
||||||
|
return palletType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPalletType(int palletType) {
|
||||||
|
this.palletType = palletType;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "Pallet [isFull=" + isFull + ", heightLeft=" + heightLeft + ", width=" + width + ", depth=" + depth
|
||||||
|
+ ", palletType=" + palletType + "]";
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
106
cost-calculation-base/src/main/java/cost/Product.java
Normal file
106
cost-calculation-base/src/main/java/cost/Product.java
Normal file
|
|
@ -0,0 +1,106 @@
|
||||||
|
package cost;
|
||||||
|
|
||||||
|
public class Product {
|
||||||
|
|
||||||
|
public static int transportType_pallet = 1;
|
||||||
|
public static int transportType_individual = 2;
|
||||||
|
public static int transportType_bulkt = 3;
|
||||||
|
private String name;
|
||||||
|
private double height;
|
||||||
|
private double width;
|
||||||
|
private double depth;
|
||||||
|
private double weight;
|
||||||
|
private int transportType;
|
||||||
|
|
||||||
|
|
||||||
|
public Product(String name, double height, double width, double depth, double weight, int transportType) {
|
||||||
|
super();
|
||||||
|
this.name = name;
|
||||||
|
this.height = height;
|
||||||
|
this.width = width;
|
||||||
|
this.depth = depth;
|
||||||
|
this.weight = weight;
|
||||||
|
this.transportType = transportType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setName(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getHeight() {
|
||||||
|
return height;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setHeight(double height) {
|
||||||
|
this.height = height;
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getWidth() {
|
||||||
|
return width;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setWidth(double width) {
|
||||||
|
this.width = width;
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getDepth() {
|
||||||
|
return depth;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDepth(double depth) {
|
||||||
|
this.depth = depth;
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getWeight() {
|
||||||
|
return weight;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setWeight(double weight) {
|
||||||
|
this.weight = weight;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getTransportType() {
|
||||||
|
return transportType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTransportType(int transportType) {
|
||||||
|
this.transportType = transportType;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
final int prime = 31;
|
||||||
|
int result = 1;
|
||||||
|
result = prime * result + ((name == null) ? 0 : name.hashCode());
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object obj) {
|
||||||
|
if (this == obj)
|
||||||
|
return true;
|
||||||
|
if (obj == null)
|
||||||
|
return false;
|
||||||
|
if (getClass() != obj.getClass())
|
||||||
|
return false;
|
||||||
|
Product other = (Product) obj;
|
||||||
|
if (name == null) {
|
||||||
|
if (other.name != null)
|
||||||
|
return false;
|
||||||
|
} else if (!name.equals(other.name))
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "Product [name=" + name + ", height=" + height + ", width=" + width + ", depth=" + depth + ", weight="
|
||||||
|
+ weight + ", transportType=" + transportType + "]";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
42
cost-calculation-base/src/main/java/cost/README.md
Normal file
42
cost-calculation-base/src/main/java/cost/README.md
Normal file
|
|
@ -0,0 +1,42 @@
|
||||||
|
# Cost Calculation Data model
|
||||||
|
|
||||||
|
The first thing to do when using drools is to build the java class model on which the rules will apply.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
* CostCalculationRequest
|
||||||
|
This is the top entity that will contain the trip description as well as the order the customer did and witch trip has to be calculated.
|
||||||
|
And in the same object, we shall put the final result in a list of costs and the complete list of pallets where we will put the products.
|
||||||
|
* Trip
|
||||||
|
Contains the list of steps of the trip.
|
||||||
|
* Step
|
||||||
|
A step happens between two cities and a unique transport type : train, truck or boat
|
||||||
|
* City
|
||||||
|
A city which can ne a harbour, a train station or a a final destination by truck.
|
||||||
|
* Order
|
||||||
|
The detail of the customer order.
|
||||||
|
* OrderLine
|
||||||
|
It contains the product as well as the number of items.
|
||||||
|
* LeftToDistribute
|
||||||
|
As we have to distribute all products in the pallets, we shall store here during the distribution what is left to be distributed.
|
||||||
|
* Product
|
||||||
|
The product that is bought and has to be in the transport.
|
||||||
|
* Pallet
|
||||||
|
Here is a picture of a pallet.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
|
||||||
|
* HandlingCostElement, TaxesCostElement and TransportCostElement
|
||||||
|
they represent the different costs that we have to calculate.
|
||||||
|
|
||||||
|
* CalculatedElement
|
||||||
|
We shall use this class to store intermediate values.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
61
cost-calculation-base/src/main/java/cost/Step.java
Normal file
61
cost-calculation-base/src/main/java/cost/Step.java
Normal file
|
|
@ -0,0 +1,61 @@
|
||||||
|
package cost;
|
||||||
|
|
||||||
|
public class Step {
|
||||||
|
public static int Ship_TransportType = 1;
|
||||||
|
public static int train_TransportType = 2;
|
||||||
|
public static int truck_TransportType = 3;
|
||||||
|
|
||||||
|
private City stepStart;
|
||||||
|
private City stepEnd;
|
||||||
|
private double distance;
|
||||||
|
private int transportType;
|
||||||
|
|
||||||
|
|
||||||
|
public Step(City stepStart, City stepEnd, double distance, int transportType) {
|
||||||
|
super();
|
||||||
|
this.stepStart = stepStart;
|
||||||
|
this.stepEnd = stepEnd;
|
||||||
|
this.distance = distance;
|
||||||
|
this.transportType = transportType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public City getStepStart() {
|
||||||
|
return stepStart;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setStepStart(City stepStart) {
|
||||||
|
this.stepStart = stepStart;
|
||||||
|
}
|
||||||
|
|
||||||
|
public City getStepEnd() {
|
||||||
|
return stepEnd;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setStepEnd(City stepEnd) {
|
||||||
|
this.stepEnd = stepEnd;
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getDistance() {
|
||||||
|
return distance;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDistance(double distance) {
|
||||||
|
this.distance = distance;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getTransportType() {
|
||||||
|
return transportType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTransportType(int transportType) {
|
||||||
|
this.transportType = transportType;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "Step [stepStart=" + stepStart + ", stepEnd=" + stepEnd + ", distance=" + distance + ", transportType="
|
||||||
|
+ transportType + "]";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,30 @@
|
||||||
|
package cost;
|
||||||
|
|
||||||
|
public class TaxesCostElement implements CostElement {
|
||||||
|
private double amount;
|
||||||
|
private City city;
|
||||||
|
|
||||||
|
|
||||||
|
public double getAmount() {
|
||||||
|
return amount;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAmount(double amount) {
|
||||||
|
this.amount = amount;
|
||||||
|
}
|
||||||
|
|
||||||
|
public City getCity() {
|
||||||
|
return city;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCity(City city) {
|
||||||
|
this.city = city;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "TaxesCostElement [amount=" + amount + ", city=" + city + "]";
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,29 @@
|
||||||
|
package cost;
|
||||||
|
|
||||||
|
public class TransportCostElement implements CostElement {
|
||||||
|
private double amount;
|
||||||
|
private Step step;
|
||||||
|
|
||||||
|
public double getAmount() {
|
||||||
|
return amount;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAmount(double amount) {
|
||||||
|
this.amount = amount;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Step getStep() {
|
||||||
|
return step;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setStep(Step step) {
|
||||||
|
this.step = step;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "TransportCostElement [amount=" + amount + ", step=" + step + "]";
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
37
cost-calculation-base/src/main/java/cost/Trip.java
Normal file
37
cost-calculation-base/src/main/java/cost/Trip.java
Normal file
|
|
@ -0,0 +1,37 @@
|
||||||
|
package cost;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class Trip {
|
||||||
|
private String id;
|
||||||
|
private List<Step> steps = new ArrayList<Step>();
|
||||||
|
|
||||||
|
public Trip(String id) {
|
||||||
|
super();
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setId(String id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Step> getSteps() {
|
||||||
|
return steps;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSteps(List<Step> steps) {
|
||||||
|
this.steps = steps;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "Trip [id=" + id + "]";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
BIN
cost-calculation-base/src/main/java/cost/diagram.jpg
Normal file
BIN
cost-calculation-base/src/main/java/cost/diagram.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 96 KiB |
BIN
cost-calculation-base/src/main/java/cost/pallet.jpg
Normal file
BIN
cost-calculation-base/src/main/java/cost/pallet.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 14 KiB |
19
cost-calculation-base/src/main/java/util/DateHelper.java
Normal file
19
cost-calculation-base/src/main/java/util/DateHelper.java
Normal file
|
|
@ -0,0 +1,19 @@
|
||||||
|
package util;
|
||||||
|
|
||||||
|
import java.text.SimpleDateFormat;
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
public class DateHelper {
|
||||||
|
public static String sFormat = "yyyy-MM-dd";
|
||||||
|
|
||||||
|
public static Date getDate(String sDate) throws Exception {
|
||||||
|
SimpleDateFormat sdf = new SimpleDateFormat(sFormat);
|
||||||
|
return sdf.parse(sDate);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Date getDate(String sDate, String anotherFormat)
|
||||||
|
throws Exception {
|
||||||
|
SimpleDateFormat sdf = new SimpleDateFormat(anotherFormat);
|
||||||
|
return sdf.parse(sDate);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,175 @@
|
||||||
|
package util;
|
||||||
|
|
||||||
|
import org.jbpm.workflow.instance.node.RuleSetNodeInstance;
|
||||||
|
import org.kie.api.KieServices;
|
||||||
|
import org.kie.api.event.process.*;
|
||||||
|
import org.kie.api.event.rule.*;
|
||||||
|
import org.kie.api.runtime.KieContainer;
|
||||||
|
import org.kie.api.runtime.KieSession;
|
||||||
|
import org.kie.api.runtime.StatelessKieSession;
|
||||||
|
|
||||||
|
public class KnowledgeSessionHelper {
|
||||||
|
public static KieContainer createRuleBase() {
|
||||||
|
|
||||||
|
KieServices ks = KieServices.Factory.get();
|
||||||
|
KieContainer kieContainer = ks.getKieClasspathContainer();
|
||||||
|
return kieContainer;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static StatelessKieSession getStatelessKnowledgeSession(KieContainer kieContainer, String sessionName) {
|
||||||
|
StatelessKieSession kSession = kieContainer.newStatelessKieSession(sessionName);
|
||||||
|
|
||||||
|
return kSession;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static KieSession getStatefulKnowledgeSession(KieContainer kieContainer, String sessionName) {
|
||||||
|
|
||||||
|
KieSession kSession = kieContainer.newKieSession();
|
||||||
|
|
||||||
|
return kSession;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static KieSession getStatefulKnowledgeSessionForJBPM(
|
||||||
|
KieContainer kieContainer, String sessionName) {
|
||||||
|
KieSession session = getStatefulKnowledgeSessionWithCallback(kieContainer, sessionName);
|
||||||
|
session.addEventListener(new ProcessEventListener() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void beforeVariableChanged(ProcessVariableChangedEvent arg0) {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void beforeProcessStarted(ProcessStartedEvent arg0) {
|
||||||
|
System.out.println("Process Name " + arg0.getProcessInstance().getProcessName() + " has been started");
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void beforeProcessCompleted(ProcessCompletedEvent arg0) {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void beforeNodeTriggered(ProcessNodeTriggeredEvent arg0) {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void beforeNodeLeft(ProcessNodeLeftEvent arg0) {
|
||||||
|
if (arg0.getNodeInstance() instanceof RuleSetNodeInstance) {
|
||||||
|
System.out.println("Node Name " + arg0.getNodeInstance().getNodeName() + " has been left");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void afterVariableChanged(ProcessVariableChangedEvent arg0) {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void afterProcessStarted(ProcessStartedEvent arg0) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void afterProcessCompleted(ProcessCompletedEvent arg0) {
|
||||||
|
System.out.println("Process Name " + arg0.getProcessInstance().getProcessName() + " has stopped");
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void afterNodeTriggered(ProcessNodeTriggeredEvent arg0) {
|
||||||
|
if (arg0.getNodeInstance() instanceof RuleSetNodeInstance) {
|
||||||
|
System.out.println("Node Name " + arg0.getNodeInstance().getNodeName() + " has been entered");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void afterNodeLeft(ProcessNodeLeftEvent arg0) {
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return session;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static KieSession getStatefulKnowledgeSessionWithCallback(
|
||||||
|
KieContainer kieContainer, String sessionName) {
|
||||||
|
KieSession session = getStatefulKnowledgeSession(kieContainer, sessionName);
|
||||||
|
session.addEventListener(new RuleRuntimeEventListener() {
|
||||||
|
public void objectInserted(ObjectInsertedEvent event) {
|
||||||
|
System.out.println("Object inserted \n"
|
||||||
|
+ event.getObject().toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void objectUpdated(ObjectUpdatedEvent event) {
|
||||||
|
System.out.println("Object was updated \n"
|
||||||
|
+ "new Content \n" + event.getObject().toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void objectDeleted(ObjectDeletedEvent event) {
|
||||||
|
System.out.println("Object retracted \n"
|
||||||
|
+ event.getOldObject().toString());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
session.addEventListener(new AgendaEventListener() {
|
||||||
|
public void matchCreated(MatchCreatedEvent event) {
|
||||||
|
System.out.println("The rule "
|
||||||
|
+ event.getMatch().getRule().getName()
|
||||||
|
+ " can be fired in agenda");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void matchCancelled(MatchCancelledEvent event) {
|
||||||
|
System.out.println("The rule "
|
||||||
|
+ event.getMatch().getRule().getName()
|
||||||
|
+ " cannot b in agenda");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void beforeMatchFired(BeforeMatchFiredEvent event) {
|
||||||
|
System.out.println("The rule "
|
||||||
|
+ event.getMatch().getRule().getName()
|
||||||
|
+ " will be fired");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void afterMatchFired(AfterMatchFiredEvent event) {
|
||||||
|
System.out.println("The rule "
|
||||||
|
+ event.getMatch().getRule().getName()
|
||||||
|
+ " has be fired");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void agendaGroupPopped(AgendaGroupPoppedEvent event) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void agendaGroupPushed(AgendaGroupPushedEvent event) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void beforeRuleFlowGroupActivated(RuleFlowGroupActivatedEvent event) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void afterRuleFlowGroupActivated(RuleFlowGroupActivatedEvent event) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void beforeRuleFlowGroupDeactivated(RuleFlowGroupDeactivatedEvent event) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void afterRuleFlowGroupDeactivated(RuleFlowGroupDeactivatedEvent event) {
|
||||||
|
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
return session;
|
||||||
|
}
|
||||||
|
}
|
||||||
10
cost-calculation-base/src/main/java/util/OutputDisplay.java
Normal file
10
cost-calculation-base/src/main/java/util/OutputDisplay.java
Normal file
|
|
@ -0,0 +1,10 @@
|
||||||
|
package util;
|
||||||
|
|
||||||
|
public class OutputDisplay {
|
||||||
|
|
||||||
|
public void showText(String someText) {
|
||||||
|
long time = System.currentTimeMillis();
|
||||||
|
System.out.println("time=" + time + "-" + someText);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,5 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<kmodule xmlns="http://jboss.org/kie/6.0.0/kmodule">
|
||||||
|
|
||||||
|
|
||||||
|
</kmodule>
|
||||||
92
cost-calculation-base/src/main/resources/rules/P1.bpmn2
Normal file
92
cost-calculation-base/src/main/resources/rules/P1.bpmn2
Normal file
|
|
@ -0,0 +1,92 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<definitions id="Definition"
|
||||||
|
targetNamespace="http://www.jboss.org/drools"
|
||||||
|
typeLanguage="http://www.java.com/javaTypes"
|
||||||
|
expressionLanguage="http://www.mvel.org/2.0"
|
||||||
|
xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://www.omg.org/spec/BPMN/20100524/MODEL BPMN20.xsd"
|
||||||
|
xmlns:g="http://www.jboss.org/drools/flow/gpd"
|
||||||
|
xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI"
|
||||||
|
xmlns:dc="http://www.omg.org/spec/DD/20100524/DC"
|
||||||
|
xmlns:di="http://www.omg.org/spec/DD/20100524/DI"
|
||||||
|
xmlns:tns="http://www.jboss.org/drools">
|
||||||
|
|
||||||
|
<process processType="Private" isExecutable="true" id="P1" name="CalcuateCostProces" tns:packageName="cost.calculation" >
|
||||||
|
|
||||||
|
<!-- nodes -->
|
||||||
|
<startEvent id="_1" isInterrupting="true">
|
||||||
|
</startEvent>
|
||||||
|
<endEvent id="_3" >
|
||||||
|
<terminateEventDefinition />
|
||||||
|
</endEvent>
|
||||||
|
<businessRuleTask id="_jbpm-unique-2" name="pallet" g:ruleFlowGroup="distribution" >
|
||||||
|
<ioSpecification>
|
||||||
|
<inputSet>
|
||||||
|
</inputSet>
|
||||||
|
<outputSet>
|
||||||
|
</outputSet>
|
||||||
|
</ioSpecification>
|
||||||
|
</businessRuleTask>
|
||||||
|
<businessRuleTask id="_jbpm-unique-0" name="Amount " g:ruleFlowGroup="calculate" >
|
||||||
|
<ioSpecification>
|
||||||
|
<inputSet>
|
||||||
|
</inputSet>
|
||||||
|
<outputSet>
|
||||||
|
</outputSet>
|
||||||
|
</ioSpecification>
|
||||||
|
</businessRuleTask>
|
||||||
|
<businessRuleTask id="_jbpm-unique-1" name="Sum" g:ruleFlowGroup="total" >
|
||||||
|
<ioSpecification>
|
||||||
|
<inputSet>
|
||||||
|
</inputSet>
|
||||||
|
<outputSet>
|
||||||
|
</outputSet>
|
||||||
|
</ioSpecification>
|
||||||
|
</businessRuleTask>
|
||||||
|
|
||||||
|
<!-- connections -->
|
||||||
|
<sequenceFlow id="_jbpm-unique-1-_3" sourceRef="_jbpm-unique-1" targetRef="_3" />
|
||||||
|
<sequenceFlow id="_1-_jbpm-unique-2" sourceRef="_1" targetRef="_jbpm-unique-2" />
|
||||||
|
<sequenceFlow id="_jbpm-unique-2-_jbpm-unique-0" sourceRef="_jbpm-unique-2" targetRef="_jbpm-unique-0" />
|
||||||
|
<sequenceFlow id="_jbpm-unique-0-_jbpm-unique-1" sourceRef="_jbpm-unique-0" targetRef="_jbpm-unique-1" />
|
||||||
|
|
||||||
|
</process>
|
||||||
|
|
||||||
|
<bpmndi:BPMNDiagram>
|
||||||
|
<bpmndi:BPMNPlane bpmnElement="P1" >
|
||||||
|
<bpmndi:BPMNShape bpmnElement="_1" >
|
||||||
|
<dc:Bounds x="24" y="16" width="48" height="48" />
|
||||||
|
</bpmndi:BPMNShape>
|
||||||
|
<bpmndi:BPMNShape bpmnElement="_3" >
|
||||||
|
<dc:Bounds x="433" y="21" width="48" height="48" />
|
||||||
|
</bpmndi:BPMNShape>
|
||||||
|
<bpmndi:BPMNShape bpmnElement="_jbpm-unique-2" >
|
||||||
|
<dc:Bounds x="123" y="18" width="80" height="48" />
|
||||||
|
</bpmndi:BPMNShape>
|
||||||
|
<bpmndi:BPMNShape bpmnElement="_jbpm-unique-0" >
|
||||||
|
<dc:Bounds x="233" y="20" width="80" height="48" />
|
||||||
|
</bpmndi:BPMNShape>
|
||||||
|
<bpmndi:BPMNShape bpmnElement="_jbpm-unique-1" >
|
||||||
|
<dc:Bounds x="337" y="22" width="80" height="48" />
|
||||||
|
</bpmndi:BPMNShape>
|
||||||
|
<bpmndi:BPMNEdge bpmnElement="_jbpm-unique-1-_3" >
|
||||||
|
<di:waypoint x="377" y="46" />
|
||||||
|
<di:waypoint x="457" y="45" />
|
||||||
|
</bpmndi:BPMNEdge>
|
||||||
|
<bpmndi:BPMNEdge bpmnElement="_1-_jbpm-unique-2" >
|
||||||
|
<di:waypoint x="48" y="40" />
|
||||||
|
<di:waypoint x="163" y="42" />
|
||||||
|
</bpmndi:BPMNEdge>
|
||||||
|
<bpmndi:BPMNEdge bpmnElement="_jbpm-unique-2-_jbpm-unique-0" >
|
||||||
|
<di:waypoint x="163" y="42" />
|
||||||
|
<di:waypoint x="273" y="44" />
|
||||||
|
</bpmndi:BPMNEdge>
|
||||||
|
<bpmndi:BPMNEdge bpmnElement="_jbpm-unique-0-_jbpm-unique-1" >
|
||||||
|
<di:waypoint x="273" y="44" />
|
||||||
|
<di:waypoint x="377" y="46" />
|
||||||
|
</bpmndi:BPMNEdge>
|
||||||
|
</bpmndi:BPMNPlane>
|
||||||
|
</bpmndi:BPMNDiagram>
|
||||||
|
|
||||||
|
</definitions>
|
||||||
468
cost-calculation-base/src/main/resources/rules/README.md
Normal file
468
cost-calculation-base/src/main/resources/rules/README.md
Normal file
|
|
@ -0,0 +1,468 @@
|
||||||
|
# Rules
|
||||||
|
|
||||||
|
We shall use a Ruleflow and implement the rules in 3 steps :
|
||||||
|
* Distribute the products in the pallet
|
||||||
|
* Calculate the costs
|
||||||
|
* Calculate and Display the results
|
||||||
|
|
||||||
|
This is done in the P1.bpmn2.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
## Distribute the products in the pallet
|
||||||
|
|
||||||
|
This rules will be executed in the rule step "distribution". So we shall add the keyworruleflow-group "distribution".
|
||||||
|
|
||||||
|
There are 3 types of product : those we have to put individually, the bulk and the others.
|
||||||
|
|
||||||
|
### Initialize a counter for each order line
|
||||||
|
|
||||||
|
First we shall the rule that created the LeftToDistribute object.
|
||||||
|
For each orderline we create and link to the orderline element
|
||||||
|
```
|
||||||
|
rule "Create Counter leftToDistribute quantity"
|
||||||
|
ruleflow-group "distribution"
|
||||||
|
when
|
||||||
|
$elt : OrderLine( numberItems >0 )
|
||||||
|
not (LeftToDistribute(orderLine==$elt))
|
||||||
|
then
|
||||||
|
LeftToDistribute e= new LeftToDistribute($elt,$elt.getNumberItems());
|
||||||
|
insert(e);
|
||||||
|
end
|
||||||
|
rule "Create Counter leftToDistribute weight"
|
||||||
|
ruleflow-group "distribution"
|
||||||
|
when
|
||||||
|
$elt : OrderLine( weight >0 )
|
||||||
|
not (LeftToDistribute(orderLine==$elt))
|
||||||
|
then
|
||||||
|
LeftToDistribute e= new LeftToDistribute($elt,$elt.getWeight());
|
||||||
|
insert(e);
|
||||||
|
end
|
||||||
|
|
||||||
|
```
|
||||||
|
So here the rule above for each OrderLine that is not yet connected to a LeftToDistribute fact.
|
||||||
|
Then we create it and initialize the counter with the number of elements in the line.
|
||||||
|
We have one rule when items are
|
||||||
|
|
||||||
|
### individual items
|
||||||
|
|
||||||
|
For each product of type individual, we shall put it on the pallet.
|
||||||
|
And in the then part, we create the pallet, decrease the number of element left and update the objects?
|
||||||
|
|
||||||
|
```
|
||||||
|
rule "Create PalletForIndividual"
|
||||||
|
ruleflow-group "distribution"
|
||||||
|
when
|
||||||
|
$c : CostCalculationRequest()
|
||||||
|
$p : Product(transportType==Product.transportType_individual)
|
||||||
|
$elt : OrderLine(product==$p )
|
||||||
|
$l : LeftToDistribute(quantityLeft> 0,orderLine==$elt)
|
||||||
|
then
|
||||||
|
Pallet pp = new Pallet();
|
||||||
|
pp.setPalletType($p.getTransportType());
|
||||||
|
pp.addContent($p,new Long(1));
|
||||||
|
insert(pp);
|
||||||
|
$c.getPallets().add(pp);
|
||||||
|
$l.setQuantityLeft($l.getQuantityLeft()-1);
|
||||||
|
update($l);
|
||||||
|
end
|
||||||
|
```
|
||||||
|
|
||||||
|
### bulk item
|
||||||
|
|
||||||
|
For the bulk product, we shall do the same way.
|
||||||
|
The first rule files 1400kg on each pallet.
|
||||||
|
The second rule is if there is less than 1400kg left, then we put the rest in the pallet.
|
||||||
|
|
||||||
|
```
|
||||||
|
rule "Create PalletForBulkMore1400Kg"
|
||||||
|
ruleflow-group "distribution"
|
||||||
|
when
|
||||||
|
$c : CostCalculationRequest()
|
||||||
|
$p : Product(transportType==Product.transportType_bulkt)
|
||||||
|
$elt : OrderLine(product==$p )
|
||||||
|
$l : LeftToDistribute(weightLeft > 1400,orderLine==$elt)
|
||||||
|
then
|
||||||
|
Pallet pp = new Pallet();
|
||||||
|
pp.setPalletType($p.getTransportType());
|
||||||
|
pp.addContent($p,new Long(1400));
|
||||||
|
insert(pp);
|
||||||
|
$c.getPallets().add(pp);
|
||||||
|
$l.setWeightLeft($l.getWeightLeft()-1400);
|
||||||
|
update($l);
|
||||||
|
end
|
||||||
|
rule "Create PalletForBulkless1400Kg"
|
||||||
|
ruleflow-group "distribution"
|
||||||
|
when
|
||||||
|
$c : CostCalculationRequest()
|
||||||
|
$p : Product(transportType==Product.transportType_bulkt)
|
||||||
|
$elt : OrderLine(product==$p )
|
||||||
|
$l : LeftToDistribute(weightLeft <= 1400,weightLeft > 0,orderLine==$elt)
|
||||||
|
then
|
||||||
|
Pallet pp = new Pallet();
|
||||||
|
pp.setPalletType($p.getTransportType());
|
||||||
|
pp.addContent($p,$l.getWeightLeft());
|
||||||
|
insert(pp);
|
||||||
|
$c.getPallets().add(pp);
|
||||||
|
$l.setWeightLeft(0);
|
||||||
|
update($l);
|
||||||
|
end
|
||||||
|
```
|
||||||
|
|
||||||
|
### Distribute the other product type.
|
||||||
|
We shall first create a rule that create a new Pallet if none is available
|
||||||
|
|
||||||
|
```
|
||||||
|
rule "Create Empty Pallet"
|
||||||
|
ruleflow-group "distribution"
|
||||||
|
when
|
||||||
|
not (Pallet (palletType == Product.transportType_pallet,full ==false))
|
||||||
|
then
|
||||||
|
Pallet p = new Pallet();
|
||||||
|
p.setPalletType(Product.transportType_pallet);
|
||||||
|
insert (p);
|
||||||
|
end
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
As we are going to fill the pallet in height, we shall declare a pallet as full if the place left in height is smaller than the smallest product in height.
|
||||||
|
|
||||||
|
```
|
||||||
|
rule "GetSmallestHeight"
|
||||||
|
ruleflow-group "distribution"
|
||||||
|
when
|
||||||
|
accumulate( Product( $h : height ,transportType==Product.transportType_pallet );
|
||||||
|
$min : min( $h );
|
||||||
|
true )
|
||||||
|
|
||||||
|
then
|
||||||
|
CalculatedElement elt = new CalculatedElement();
|
||||||
|
elt.setKey("minValue.product");
|
||||||
|
elt.setDoubleValue((Double)$min);
|
||||||
|
insert(elt);
|
||||||
|
end
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
And then the rule that sets the pallet as filled (full has the true value). We only set the value of a pallet that has been filled by one type of product by adding constranint heightLeft!= 2.0.
|
||||||
|
|
||||||
|
```
|
||||||
|
rule "FillPalletIfNoProductGoesIn"
|
||||||
|
ruleflow-group "distribution"
|
||||||
|
when
|
||||||
|
CalculatedElement($min : doubleValue ,key=="minValue.product")
|
||||||
|
$p : Pallet(heightLeft!= 2.0,$hl : heightLeft < $min ,full ==false,palletType == Product.transportType_pallet)
|
||||||
|
then
|
||||||
|
$p.setFull(true);
|
||||||
|
System.out.println("MinValue="+$min);
|
||||||
|
update($p);
|
||||||
|
end
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
Then the rule that fills the pallet with product depending on the size of the product.
|
||||||
|
|
||||||
|
```
|
||||||
|
rule "Create PalletFortransportType_pallet"
|
||||||
|
ruleflow-group "distribution"
|
||||||
|
when
|
||||||
|
$c : CostCalculationRequest()
|
||||||
|
$pp : Pallet($hl : heightLeft ,full ==false,palletType == Product.transportType_pallet)
|
||||||
|
$p : Product(height <= $hl,transportType==Product.transportType_pallet)
|
||||||
|
$elt : OrderLine(product==$p )
|
||||||
|
$l : LeftToDistribute(quantityLeft > 0,orderLine==$elt)
|
||||||
|
then
|
||||||
|
long a = (long) Math.round($pp.getWidth()/$p.getWidth());
|
||||||
|
long b = (long) Math.round($pp.getDepth()/$p.getDepth());
|
||||||
|
long n = Math.min(a*b,$l.getQuantityLeft());
|
||||||
|
$pp.addContent($p,n);
|
||||||
|
$pp.setHeightLeft($pp.getHeightLeft()-$p.getHeight());
|
||||||
|
update($pp);
|
||||||
|
$l.setQuantityLeft($l.getQuantityLeft()-n);
|
||||||
|
update($l);
|
||||||
|
end
|
||||||
|
```
|
||||||
|
|
||||||
|
## Calculate the costs
|
||||||
|
Now we take each cost and add a CostElement depending on the number of pallets we created in previous step
|
||||||
|
|
||||||
|
### Transport cost
|
||||||
|
For each step type we calculate the cost
|
||||||
|
|
||||||
|
```
|
||||||
|
rule "boatTransportCost"
|
||||||
|
ruleflow-group "calculate"
|
||||||
|
when
|
||||||
|
$c : CostCalculationRequest( )
|
||||||
|
$s : Step(transportType ==Step.Ship_TransportType)
|
||||||
|
then
|
||||||
|
TransportCostElement t = new TransportCostElement();
|
||||||
|
t.setStep($s);
|
||||||
|
t.setAmount($c.getPallets().size()*$s.getDistance()*0.2);
|
||||||
|
$c.getCostElements().add(t);
|
||||||
|
insert(t);
|
||||||
|
end
|
||||||
|
|
||||||
|
rule "trainTransportCost"
|
||||||
|
ruleflow-group "calculate"
|
||||||
|
when
|
||||||
|
$c : CostCalculationRequest( )
|
||||||
|
$s : Step(transportType ==Step.train_TransportType)
|
||||||
|
then
|
||||||
|
TransportCostElement t = new TransportCostElement();
|
||||||
|
t.setStep($s);
|
||||||
|
t.setAmount($c.getPallets().size()*$s.getDistance()*0.5);
|
||||||
|
$c.getCostElements().add(t);
|
||||||
|
insert(t);
|
||||||
|
end
|
||||||
|
|
||||||
|
rule "truckTransportCost"
|
||||||
|
ruleflow-group "calculate"
|
||||||
|
when
|
||||||
|
$c : CostCalculationRequest( )
|
||||||
|
$s : Step(transportType ==Step.truck_TransportType)
|
||||||
|
then
|
||||||
|
TransportCostElement t = new TransportCostElement();
|
||||||
|
t.setStep($s);
|
||||||
|
t.setAmount($c.getPallets().size()*$s.getDistance()*1.0);
|
||||||
|
$c.getCostElements().add(t);
|
||||||
|
insert(t);
|
||||||
|
end
|
||||||
|
```
|
||||||
|
### Taxes Cost
|
||||||
|
For each City we go through, we calculate the cost (Shangai and Rotterdam)
|
||||||
|
As sometimes it depends on the weight, we have to sum the total amount of weigh on all pallets.
|
||||||
|
Here we chose not to put all calculation in the drools session, so we do the sum in the them part of the rules.
|
||||||
|
Se here how we obtain the list of Pallet we want in an ArrayList. In the then part we then iterate on the founded pallet and in the pallet we go through all the products to sum the weight.
|
||||||
|
```
|
||||||
|
rule "ShangaiTaxesCost_bulk"
|
||||||
|
ruleflow-group "calculate"
|
||||||
|
when
|
||||||
|
$c : CostCalculationRequest( )
|
||||||
|
$ci : City(name==City.ShangaiCityName)
|
||||||
|
$listPallet : ArrayList( )
|
||||||
|
from collect( Pallet(palletType == Product.transportType_bulkt) )
|
||||||
|
then
|
||||||
|
TaxesCostElement t = new TaxesCostElement();
|
||||||
|
t.setCity($ci);
|
||||||
|
double totalWeight=0;
|
||||||
|
for (Object oo : $listPallet){
|
||||||
|
Pallet pp = (Pallet)oo;
|
||||||
|
for (Double d : pp.getContentWeight().values()){
|
||||||
|
totalWeight=totalWeight+d;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
t.setAmount(totalWeight*0.02);
|
||||||
|
$c.getCostElements().add(t);
|
||||||
|
insert(t);
|
||||||
|
end
|
||||||
|
|
||||||
|
rule "ShangaiTaxesCost_notbulk"
|
||||||
|
ruleflow-group "calculate"
|
||||||
|
when
|
||||||
|
$c : CostCalculationRequest( )
|
||||||
|
$ci : City(name==City.ShangaiCityName)
|
||||||
|
$listPallet : ArrayList( )
|
||||||
|
from collect( Pallet(palletType != Product.transportType_bulkt) )
|
||||||
|
then
|
||||||
|
TaxesCostElement t = new TaxesCostElement();
|
||||||
|
t.setCity($ci);
|
||||||
|
double totalWeight=0;
|
||||||
|
for (Object oo : $listPallet){
|
||||||
|
Pallet pp = (Pallet)oo;
|
||||||
|
for (Product p : pp.getContentQuantity().keySet()){
|
||||||
|
totalWeight=totalWeight+p.getWeight()* pp.getContentQuantity().get(p);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
t.setAmount(totalWeight*0.05);
|
||||||
|
$c.getCostElements().add(t);
|
||||||
|
insert(t);
|
||||||
|
end
|
||||||
|
|
||||||
|
rule "RotterdamTaxesCost_bulk_weight"
|
||||||
|
ruleflow-group "calculate"
|
||||||
|
when
|
||||||
|
$c : CostCalculationRequest( )
|
||||||
|
$ci : City(name==City.RotterdamCityName)
|
||||||
|
$listPallet : ArrayList( )
|
||||||
|
from collect( Pallet(palletType == Product.transportType_bulkt) )
|
||||||
|
then
|
||||||
|
TaxesCostElement t = new TaxesCostElement();
|
||||||
|
t.setCity($ci);
|
||||||
|
double totalWeight=0;
|
||||||
|
for (Object oo : $listPallet){
|
||||||
|
Pallet pp = (Pallet)oo;
|
||||||
|
for (Double d : pp.getContentWeight().values()){
|
||||||
|
totalWeight=totalWeight+d;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
t.setAmount(totalWeight*0.05);
|
||||||
|
$c.getCostElements().add(t);
|
||||||
|
insert(t);
|
||||||
|
end
|
||||||
|
rule "RotterdamTaxesCost_notbulk_weight"
|
||||||
|
ruleflow-group "calculate"
|
||||||
|
when
|
||||||
|
$c : CostCalculationRequest( )
|
||||||
|
$ci : City(name==City.RotterdamCityName)
|
||||||
|
$listPallet : ArrayList( )
|
||||||
|
from collect( Pallet(palletType != Product.transportType_bulkt) )
|
||||||
|
then
|
||||||
|
TaxesCostElement t = new TaxesCostElement();
|
||||||
|
t.setCity($ci);
|
||||||
|
double totalWeight=0;
|
||||||
|
for (Object oo : $listPallet){
|
||||||
|
Pallet pp = (Pallet)oo;
|
||||||
|
for (Product p : pp.getContentQuantity().keySet()){
|
||||||
|
totalWeight=totalWeight+p.getWeight()* pp.getContentQuantity().get(p);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
t.setAmount(totalWeight*0.05);
|
||||||
|
$c.getCostElements().add(t);
|
||||||
|
insert(t);
|
||||||
|
end
|
||||||
|
```
|
||||||
|
|
||||||
|
### Handling Cost and taxes on the Handling
|
||||||
|
Here we admit that it takes 12 hours to do the handling.
|
||||||
|
Based on that we then see how many pallets we have to handle per hour and then depending on the what a person can handle per hour, we calculate the number of persons we need.
|
||||||
|
```
|
||||||
|
rule "ShangaiHandlingCost"
|
||||||
|
ruleflow-group "calculate"
|
||||||
|
when
|
||||||
|
$c : CostCalculationRequest( )
|
||||||
|
$ci : City(name==City.ShangaiCityName)
|
||||||
|
then
|
||||||
|
int n = $c.getPallets().size();
|
||||||
|
int nbrePalletPerHour = Math.round( n/12)+1;
|
||||||
|
int nbrePerson = Math.round( nbrePalletPerHour/13)+1;
|
||||||
|
HandlingCostElement t = new HandlingCostElement();
|
||||||
|
t.setCity($ci);
|
||||||
|
t.setAmount(nbrePerson*12*20.0);
|
||||||
|
$c.getCostElements().add(t);
|
||||||
|
insert(t);
|
||||||
|
end
|
||||||
|
|
||||||
|
rule "RotterdamHandlingCostAndPersonTaxes"
|
||||||
|
ruleflow-group "calculate"
|
||||||
|
when
|
||||||
|
$c : CostCalculationRequest( )
|
||||||
|
$ci : City(name==City.RotterdamCityName)
|
||||||
|
then
|
||||||
|
int n = $c.getPallets().size();
|
||||||
|
int nbrePalletPerHour = Math.round( n/12)+1;
|
||||||
|
int nbrePerson = Math.round( nbrePalletPerHour/60)+1;
|
||||||
|
HandlingCostElement t = new HandlingCostElement();
|
||||||
|
t.setCity($ci);
|
||||||
|
t.setAmount(nbrePerson*12*45.0);
|
||||||
|
$c.getCostElements().add(t);
|
||||||
|
insert(t);
|
||||||
|
TaxesCostElement t1 = new TaxesCostElement();
|
||||||
|
t1.setAmount(nbrePerson*1.0);
|
||||||
|
$c.getCostElements().add(t1);
|
||||||
|
insert(t1);
|
||||||
|
end
|
||||||
|
|
||||||
|
rule "TournaiHandlingCostAndPersonTaxes"
|
||||||
|
ruleflow-group "calculate"
|
||||||
|
when
|
||||||
|
$c : CostCalculationRequest( )
|
||||||
|
$ci : City(name==City.TournaiCityName)
|
||||||
|
then
|
||||||
|
int n = $c.getPallets().size();
|
||||||
|
int nbrePalletPerHour = Math.round( n/12)+1;
|
||||||
|
int nbrePerson = Math.round( nbrePalletPerHour/40)+1;
|
||||||
|
HandlingCostElement t = new HandlingCostElement();
|
||||||
|
t.setCity($ci);
|
||||||
|
t.setAmount(nbrePerson*12*67.0);
|
||||||
|
$c.getCostElements().add(t);
|
||||||
|
insert(t);
|
||||||
|
TaxesCostElement t1 = new TaxesCostElement();
|
||||||
|
t1.setAmount(nbrePerson*2.0);
|
||||||
|
$c.getCostElements().add(t1);
|
||||||
|
insert(t1);
|
||||||
|
end
|
||||||
|
|
||||||
|
rule "LilleHandlingCostAndPersonTaxes"
|
||||||
|
ruleflow-group "calculate"
|
||||||
|
when
|
||||||
|
$c : CostCalculationRequest( )
|
||||||
|
$ci : City(name==City.LilleCityName)
|
||||||
|
then
|
||||||
|
int n = $c.getPallets().size();
|
||||||
|
int nbrePalletPerHour = Math.round( n/12)+1;
|
||||||
|
int nbrePerson = Math.round( nbrePalletPerHour/30)+1;
|
||||||
|
HandlingCostElement t = new HandlingCostElement();
|
||||||
|
t.setCity($ci);
|
||||||
|
t.setAmount(nbrePerson*12*79.0);
|
||||||
|
$c.getCostElements().add(t);
|
||||||
|
insert(t);
|
||||||
|
TaxesCostElement t1 = new TaxesCostElement();
|
||||||
|
t1.setAmount(nbrePerson*30.0);
|
||||||
|
$c.getCostElements().add(t1);
|
||||||
|
insert(t1);
|
||||||
|
end
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
## Sum the results
|
||||||
|
We use the accumulate function to show the results. We just show the result in the console. On a real project, the results could habe stored in a data structure.
|
||||||
|
|
||||||
|
```
|
||||||
|
rule "CalculateTotal"
|
||||||
|
ruleflow-group "total"
|
||||||
|
when
|
||||||
|
$c : CostCalculationRequest( )
|
||||||
|
$totalBoatTransport : Number( doubleValue > 100 )
|
||||||
|
from accumulate( $s : Step(transportType ==Step.Ship_TransportType) &&
|
||||||
|
TransportCostElement(step ==$s, $value : amount ),
|
||||||
|
init( double total = 0; ),
|
||||||
|
action( total += $value; ),
|
||||||
|
reverse( total -= $value; ),
|
||||||
|
result( total ) )
|
||||||
|
$totalTrainTransport : Number( doubleValue > 100 )
|
||||||
|
from accumulate( $s : Step(transportType ==Step.train_TransportType) &&
|
||||||
|
TransportCostElement(step ==$s, $value : amount ),
|
||||||
|
init( double total = 0; ),
|
||||||
|
action( total += $value; ),
|
||||||
|
reverse( total -= $value; ),
|
||||||
|
result( total ) )
|
||||||
|
$totalTruckTransport : Number( doubleValue > 100 )
|
||||||
|
from accumulate( $s : Step(transportType ==Step.truck_TransportType) &&
|
||||||
|
TransportCostElement(step ==$s, $value : amount ),
|
||||||
|
init( double total = 0; ),
|
||||||
|
action( total += $value; ),
|
||||||
|
reverse( total -= $value; ),
|
||||||
|
result( total ) )
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
$totalTransport : Number( doubleValue > 100 )
|
||||||
|
from accumulate( TransportCostElement( $value : amount ),
|
||||||
|
init( double total = 0; ),
|
||||||
|
action( total += $value; ),
|
||||||
|
reverse( total -= $value; ),
|
||||||
|
result( total ) )
|
||||||
|
$totalTaxes : Number( doubleValue > 100 )
|
||||||
|
from accumulate( TaxesCostElement( $value : amount ),
|
||||||
|
init( double total = 0; ),
|
||||||
|
action( total += $value; ),
|
||||||
|
reverse( total -= $value; ),
|
||||||
|
result( total ) )
|
||||||
|
$totalHandling : Number( doubleValue > 100 )
|
||||||
|
from accumulate( HandlingCostElement( $value : amount ),
|
||||||
|
init( double total = 0; ),
|
||||||
|
action( total += $value; ),
|
||||||
|
reverse( total -= $value; ),
|
||||||
|
result( total ) )
|
||||||
|
then
|
||||||
|
System.out.println("NumberOfPallets="+$c.getPallets().size());
|
||||||
|
System.out.println("TotalShipTransport="+$totalBoatTransport);
|
||||||
|
System.out.println("TotalTrainTransport="+$totalTrainTransport);
|
||||||
|
System.out.println("TotalTruckTransport="+$totalTruckTransport);
|
||||||
|
System.out.println("TotalTransport="+$totalTransport);
|
||||||
|
System.out.println("TotalTaxes="+$totalTaxes);
|
||||||
|
System.out.println("TotalHandling="+$totalHandling);
|
||||||
|
end;
|
||||||
|
```
|
||||||
|
|
||||||
72
cost-calculation-base/src/main/resources/rules/SumRules.drl
Normal file
72
cost-calculation-base/src/main/resources/rules/SumRules.drl
Normal file
|
|
@ -0,0 +1,72 @@
|
||||||
|
|
||||||
|
package cost.calculation
|
||||||
|
|
||||||
|
import cost.OrderLine;
|
||||||
|
import cost.LeftToDistribute;
|
||||||
|
import cost.Product;
|
||||||
|
import cost.Pallet;
|
||||||
|
import cost.CostCalculationRequest;
|
||||||
|
import cost.CalculatedElement;
|
||||||
|
import cost.HandlingCostElement;
|
||||||
|
import cost.TaxesCostElement;
|
||||||
|
import cost.TransportCostElement;
|
||||||
|
import cost.Step;
|
||||||
|
import cost.City;
|
||||||
|
|
||||||
|
import java.lang.Math;
|
||||||
|
|
||||||
|
rule "CalculateTotal"
|
||||||
|
ruleflow-group "total"
|
||||||
|
when
|
||||||
|
$c : CostCalculationRequest( )
|
||||||
|
$totalBoatTransport : Number( doubleValue > 100 )
|
||||||
|
from accumulate( $s : Step(transportType ==Step.Ship_TransportType) &&
|
||||||
|
TransportCostElement(step ==$s, $value : amount ),
|
||||||
|
init( double total = 0; ),
|
||||||
|
action( total += $value; ),
|
||||||
|
reverse( total -= $value; ),
|
||||||
|
result( total ) )
|
||||||
|
$totalTrainTransport : Number( doubleValue > 100 )
|
||||||
|
from accumulate( $s : Step(transportType ==Step.train_TransportType) &&
|
||||||
|
TransportCostElement(step ==$s, $value : amount ),
|
||||||
|
init( double total = 0; ),
|
||||||
|
action( total += $value; ),
|
||||||
|
reverse( total -= $value; ),
|
||||||
|
result( total ) )
|
||||||
|
$totalTruckTransport : Number( doubleValue > 100 )
|
||||||
|
from accumulate( $s : Step(transportType ==Step.truck_TransportType) &&
|
||||||
|
TransportCostElement(step ==$s, $value : amount ),
|
||||||
|
init( double total = 0; ),
|
||||||
|
action( total += $value; ),
|
||||||
|
reverse( total -= $value; ),
|
||||||
|
result( total ) )
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
$totalTransport : Number( doubleValue > 100 )
|
||||||
|
from accumulate( TransportCostElement( $value : amount ),
|
||||||
|
init( double total = 0; ),
|
||||||
|
action( total += $value; ),
|
||||||
|
reverse( total -= $value; ),
|
||||||
|
result( total ) )
|
||||||
|
$totalTaxes : Number( doubleValue > 100 )
|
||||||
|
from accumulate( TaxesCostElement( $value : amount ),
|
||||||
|
init( double total = 0; ),
|
||||||
|
action( total += $value; ),
|
||||||
|
reverse( total -= $value; ),
|
||||||
|
result( total ) )
|
||||||
|
$totalHandling : Number( doubleValue > 100 )
|
||||||
|
from accumulate( HandlingCostElement( $value : amount ),
|
||||||
|
init( double total = 0; ),
|
||||||
|
action( total += $value; ),
|
||||||
|
reverse( total -= $value; ),
|
||||||
|
result( total ) )
|
||||||
|
then
|
||||||
|
System.out.println("NumberOfPallets="+$c.getPallets().size());
|
||||||
|
System.out.println("TotalShipTransport="+$totalBoatTransport);
|
||||||
|
System.out.println("TotalTrainTransport="+$totalTrainTransport);
|
||||||
|
System.out.println("TotalTruckTransport="+$totalTruckTransport);
|
||||||
|
System.out.println("TotalTransport="+$totalTransport);
|
||||||
|
System.out.println("TotalTaxes="+$totalTaxes);
|
||||||
|
System.out.println("TotalHandling="+$totalHandling);
|
||||||
|
end;
|
||||||
BIN
cost-calculation-base/src/main/resources/rules/ruleflow.png
Normal file
BIN
cost-calculation-base/src/main/resources/rules/ruleflow.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 12 KiB |
78
cost-calculation-extention/README.md
Normal file
78
cost-calculation-extention/README.md
Normal file
|
|
@ -0,0 +1,78 @@
|
||||||
|
# Cost Calculation project
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# Requirements
|
||||||
|
We are working for a retail company that buys its products from different places in Asian mostly. each shop can go to the buying web site and say what he wants and put an order.
|
||||||
|
Up to now, the transport cost was a estimated but not calculated on the content of the order.
|
||||||
|
The purpose is to implement such a calculator.
|
||||||
|
|
||||||
|
## Data model
|
||||||
|
|
||||||
|
A customer puts an order that contains products. An order contains a lost of products with a number.
|
||||||
|
A product has
|
||||||
|
* a name
|
||||||
|
* a height,
|
||||||
|
* a width,
|
||||||
|
* a depth,
|
||||||
|
* transport type : if the product can be put with other products in a pallet, individual(alone) or bulk (like sand for example)
|
||||||
|
* a weight
|
||||||
|
|
||||||
|
A product can be put on a pallet. a pallet 120 cm width and and 80 cm depth. It can be maximum 2 meters height and the weight should not exceed 1400 kg. We should use a simple algorithm to fill each pallet. It will be not optimized but we should used that as a margin of the costs. a product that is bigger than 60 cm in width or depth or higher than 1m should be put alone in a pallet.
|
||||||
|
|
||||||
|
All products start from the same city and go to the same city in an order. A trip is composed f steps. Each step can be done by train, boat or truck.
|
||||||
|
|
||||||
|
|
||||||
|
Here is the list of products in our test order.
|
||||||
|
|
||||||
|
| Product | Transport type | Number | Height | Weight | depth | weight |
|
||||||
|
| -- | -- | -- | -- | -- | -- | -- |
|
||||||
|
| drill | pallet | 1000 | 20cm | 40cm | 30cm | 2 kg |
|
||||||
|
| screwdriver | pallet | 30000 | 3cm | 2cm | 20cm | 0,2 kg |
|
||||||
|
| Sand | bulk | | | | | 35 Tons |
|
||||||
|
| Gravel | bulk | | | | | 14 Tons |
|
||||||
|
| furniture | individual |23 | | | | 500 kg |
|
||||||
|
|
||||||
|
And the trip is a follows :
|
||||||
|
|
||||||
|
| # | start city | arrival city | distance (km) | travel mode |
|
||||||
|
| -- | -- | -- | -- | -- |
|
||||||
|
| 1 | Shangai | Rotterdam | 22000 | Boat|
|
||||||
|
| 2 | Rotterdam | Tournai | 300 | Train |
|
||||||
|
| 3 | Tournai | Lille | 20 | Truck |
|
||||||
|
|
||||||
|
|
||||||
|
there are 3 types of costs :
|
||||||
|
- transport costs per Pallet
|
||||||
|
|
||||||
|
| Transport| Cost
|
||||||
|
| -- | -- |
|
||||||
|
| boat | 0,2€/km |
|
||||||
|
| Train | 0,5€/km |
|
||||||
|
| Truck | 1€/km |
|
||||||
|
|
||||||
|
- Taxes
|
||||||
|
|
||||||
|
| City| Cost
|
||||||
|
| -- | -- |
|
||||||
|
| Shangai | 0,02€/kg |
|
||||||
|
| Rotterdam | 0,05€/kg and 1€ per handling person |
|
||||||
|
| Tournai | 2€ per handling person |
|
||||||
|
| Lille | 30€ per handling person |
|
||||||
|
|
||||||
|
|
||||||
|
- handling
|
||||||
|
|
||||||
|
| City| Cost
|
||||||
|
| -- | -- |
|
||||||
|
| Shangai | 20€/hour and a person can handle 13 pallets/hour |
|
||||||
|
| Rotterdam | 45€/hour and a person can handle 60 pallets/hour |
|
||||||
|
| Tournai | 67€/hour and can handle 40 pallets/hour |
|
||||||
|
| Lille | 79€/hour and can handle 30 pallets/hour |
|
||||||
|
|
||||||
|
The handling should not take more than 12 hours.
|
||||||
|
|
||||||
|
[Data Model ](src/main/java/cost/README.md)
|
||||||
|
|
||||||
|
[The rules we implemented ](src/main/resources/rules/README.md)
|
||||||
35
cost-calculation-extention/cost-calculation-extension.iml
Normal file
35
cost-calculation-extention/cost-calculation-extension.iml
Normal file
|
|
@ -0,0 +1,35 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<module org.jetbrains.idea.maven.project.MavenProjectsManager.isMavenModule="true" type="JAVA_MODULE" version="4">
|
||||||
|
<component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_7" inherit-compiler-output="false">
|
||||||
|
<output url="file://$MODULE_DIR$/target/classes" />
|
||||||
|
<output-test url="file://$MODULE_DIR$/target/test-classes" />
|
||||||
|
<content url="file://$MODULE_DIR$">
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/src/main/java" isTestSource="false" />
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/src/main/resources" type="java-resource" />
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/src/test/java" isTestSource="true" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/target" />
|
||||||
|
</content>
|
||||||
|
<orderEntry type="inheritedJdk" />
|
||||||
|
<orderEntry type="sourceFolder" forTests="false" />
|
||||||
|
<orderEntry type="module" module-name="cost-calculation-base" />
|
||||||
|
<orderEntry type="library" name="Maven: org.drools:drools-compiler:6.5.0.Final" level="project" />
|
||||||
|
<orderEntry type="library" name="Maven: org.drools:drools-core:6.5.0.Final" level="project" />
|
||||||
|
<orderEntry type="library" name="Maven: commons-codec:commons-codec:1.4" level="project" />
|
||||||
|
<orderEntry type="library" name="Maven: org.kie:kie-internal:6.5.0.Final" level="project" />
|
||||||
|
<orderEntry type="library" name="Maven: org.antlr:antlr-runtime:3.5" level="project" />
|
||||||
|
<orderEntry type="library" name="Maven: org.mvel:mvel2:2.2.8.Final" level="project" />
|
||||||
|
<orderEntry type="library" name="Maven: com.thoughtworks.xstream:xstream:1.4.9" level="project" />
|
||||||
|
<orderEntry type="library" name="Maven: xmlpull:xmlpull:1.1.3.1" level="project" />
|
||||||
|
<orderEntry type="library" name="Maven: xpp3:xpp3_min:1.1.4c" level="project" />
|
||||||
|
<orderEntry type="library" name="Maven: com.google.protobuf:protobuf-java:2.6.0" level="project" />
|
||||||
|
<orderEntry type="library" name="Maven: org.slf4j:slf4j-api:1.7.2" level="project" />
|
||||||
|
<orderEntry type="library" name="Maven: org.eclipse.jdt.core.compiler:ecj:4.4.2" level="project" />
|
||||||
|
<orderEntry type="library" name="Maven: org.jbpm:jbpm-bpmn2:6.5.0.Final" level="project" />
|
||||||
|
<orderEntry type="library" name="Maven: org.jbpm:jbpm-flow-builder:6.5.0.Final" level="project" />
|
||||||
|
<orderEntry type="library" name="Maven: org.jbpm:jbpm-flow:6.5.0.Final" level="project" />
|
||||||
|
<orderEntry type="library" name="Maven: joda-time:joda-time:2.2" level="project" />
|
||||||
|
<orderEntry type="library" scope="TEST" name="Maven: junit:junit:4.5" level="project" />
|
||||||
|
<orderEntry type="library" name="Maven: org.kie:kie-api:6.5.0.Final" level="project" />
|
||||||
|
<orderEntry type="module" module-name="drools-lesson-pojo" />
|
||||||
|
</component>
|
||||||
|
</module>
|
||||||
47
cost-calculation-extention/pom.xml
Normal file
47
cost-calculation-extention/pom.xml
Normal file
|
|
@ -0,0 +1,47 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xmlns="http://maven.apache.org/POM/4.0.0"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<parent>
|
||||||
|
<artifactId>droolscourse</artifactId>
|
||||||
|
<groupId>com.pymma-software.droolscourse</groupId>
|
||||||
|
<version>2.0.0-SNAPSHOT</version>
|
||||||
|
</parent>
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
<artifactId>cost-calculation-extension</artifactId>
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.pymma-software.droolscourse</groupId>
|
||||||
|
<artifactId>cost-calculation-base</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.drools</groupId>
|
||||||
|
<artifactId>drools-compiler</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.eclipse.jdt.core.compiler</groupId>
|
||||||
|
<artifactId>ecj</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.jbpm</groupId>
|
||||||
|
<artifactId>jbpm-bpmn2</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>junit</groupId>
|
||||||
|
<artifactId>junit</artifactId>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.kie</groupId>
|
||||||
|
<artifactId>kie-api</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.pymma-software.droolscourse</groupId>
|
||||||
|
<artifactId>drools-lesson-pojo</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
</project>
|
||||||
|
|
@ -0,0 +1,6 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<kmodule xmlns="http://jboss.org/kie/6.0.0/kmodule">
|
||||||
|
<kbase name="kbase4" packages="rules-extension, rules">
|
||||||
|
|
||||||
|
</kbase>
|
||||||
|
</kmodule>
|
||||||
|
|
@ -0,0 +1,219 @@
|
||||||
|
|
||||||
|
package cost.calculation
|
||||||
|
|
||||||
|
import cost.OrderLine;
|
||||||
|
import cost.LeftToDistribute;
|
||||||
|
import cost.Product;
|
||||||
|
import cost.Pallet;
|
||||||
|
import cost.CostCalculationRequest;
|
||||||
|
import cost.CalculatedElement;
|
||||||
|
import cost.HandlingCostElement;
|
||||||
|
import cost.TaxesCostElement;
|
||||||
|
import cost.TransportCostElement;
|
||||||
|
import cost.Step;
|
||||||
|
import cost.City;
|
||||||
|
|
||||||
|
import java.lang.Math;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
rule "boatTransportCost"
|
||||||
|
ruleflow-group "calculate"
|
||||||
|
when
|
||||||
|
$c : CostCalculationRequest( )
|
||||||
|
$s : Step(transportType ==Step.Ship_TransportType)
|
||||||
|
then
|
||||||
|
TransportCostElement t = new TransportCostElement();
|
||||||
|
t.setStep($s);
|
||||||
|
t.setAmount($c.getPallets().size()*$s.getDistance()*0.2);
|
||||||
|
$c.getCostElements().add(t);
|
||||||
|
insert(t);
|
||||||
|
end
|
||||||
|
|
||||||
|
rule "trainTransportCost"
|
||||||
|
ruleflow-group "calculate"
|
||||||
|
when
|
||||||
|
$c : CostCalculationRequest( )
|
||||||
|
$s : Step(transportType ==Step.train_TransportType)
|
||||||
|
then
|
||||||
|
TransportCostElement t = new TransportCostElement();
|
||||||
|
t.setStep($s);
|
||||||
|
t.setAmount($c.getPallets().size()*$s.getDistance()*0.5);
|
||||||
|
$c.getCostElements().add(t);
|
||||||
|
insert(t);
|
||||||
|
end
|
||||||
|
|
||||||
|
rule "truckTransportCost"
|
||||||
|
ruleflow-group "calculate"
|
||||||
|
when
|
||||||
|
$c : CostCalculationRequest( )
|
||||||
|
$s : Step(transportType ==Step.truck_TransportType)
|
||||||
|
then
|
||||||
|
TransportCostElement t = new TransportCostElement();
|
||||||
|
t.setStep($s);
|
||||||
|
t.setAmount($c.getPallets().size()*$s.getDistance()*1.0);
|
||||||
|
$c.getCostElements().add(t);
|
||||||
|
insert(t);
|
||||||
|
end
|
||||||
|
|
||||||
|
rule "ShangaiTaxesCost_bulk"
|
||||||
|
ruleflow-group "calculate"
|
||||||
|
when
|
||||||
|
$c : CostCalculationRequest( )
|
||||||
|
$ci : City(name==City.ShangaiCityName)
|
||||||
|
$listPallet : ArrayList( )
|
||||||
|
from collect( Pallet(palletType == Product.transportType_bulkt) )
|
||||||
|
then
|
||||||
|
TaxesCostElement t = new TaxesCostElement();
|
||||||
|
t.setCity($ci);
|
||||||
|
double totalWeight=0;
|
||||||
|
for (Object oo : $listPallet){
|
||||||
|
Pallet pp = (Pallet)oo;
|
||||||
|
for (Double d : pp.getContentWeight().values()){
|
||||||
|
totalWeight=totalWeight+d;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
t.setAmount(totalWeight*0.02);
|
||||||
|
$c.getCostElements().add(t);
|
||||||
|
insert(t);
|
||||||
|
end
|
||||||
|
|
||||||
|
rule "ShangaiTaxesCost_notbulk"
|
||||||
|
ruleflow-group "calculate"
|
||||||
|
when
|
||||||
|
$c : CostCalculationRequest( )
|
||||||
|
$ci : City(name==City.ShangaiCityName)
|
||||||
|
$listPallet : ArrayList( )
|
||||||
|
from collect( Pallet(palletType != Product.transportType_bulkt) )
|
||||||
|
then
|
||||||
|
TaxesCostElement t = new TaxesCostElement();
|
||||||
|
t.setCity($ci);
|
||||||
|
double totalWeight=0;
|
||||||
|
for (Object oo : $listPallet){
|
||||||
|
Pallet pp = (Pallet)oo;
|
||||||
|
for (Product p : pp.getContentQuantity().keySet()){
|
||||||
|
totalWeight=totalWeight+p.getWeight()* pp.getContentQuantity().get(p);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
t.setAmount(totalWeight*0.05);
|
||||||
|
$c.getCostElements().add(t);
|
||||||
|
insert(t);
|
||||||
|
end
|
||||||
|
|
||||||
|
rule "RotterdamTaxesCost_bulk_weight"
|
||||||
|
ruleflow-group "calculate"
|
||||||
|
when
|
||||||
|
$c : CostCalculationRequest( )
|
||||||
|
$ci : City(name==City.RotterdamCityName)
|
||||||
|
$listPallet : ArrayList( )
|
||||||
|
from collect( Pallet(palletType == Product.transportType_bulkt) )
|
||||||
|
then
|
||||||
|
TaxesCostElement t = new TaxesCostElement();
|
||||||
|
t.setCity($ci);
|
||||||
|
double totalWeight=0;
|
||||||
|
for (Object oo : $listPallet){
|
||||||
|
Pallet pp = (Pallet)oo;
|
||||||
|
for (Double d : pp.getContentWeight().values()){
|
||||||
|
totalWeight=totalWeight+d;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
t.setAmount(totalWeight*0.05);
|
||||||
|
$c.getCostElements().add(t);
|
||||||
|
insert(t);
|
||||||
|
end
|
||||||
|
rule "RotterdamTaxesCost_notbulk_weight"
|
||||||
|
ruleflow-group "calculate"
|
||||||
|
when
|
||||||
|
$c : CostCalculationRequest( )
|
||||||
|
$ci : City(name==City.RotterdamCityName)
|
||||||
|
$listPallet : ArrayList( )
|
||||||
|
from collect( Pallet(palletType != Product.transportType_bulkt) )
|
||||||
|
then
|
||||||
|
TaxesCostElement t = new TaxesCostElement();
|
||||||
|
t.setCity($ci);
|
||||||
|
double totalWeight=0;
|
||||||
|
for (Object oo : $listPallet){
|
||||||
|
Pallet pp = (Pallet)oo;
|
||||||
|
for (Product p : pp.getContentQuantity().keySet()){
|
||||||
|
totalWeight=totalWeight+p.getWeight()* pp.getContentQuantity().get(p);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
t.setAmount(totalWeight*0.05);
|
||||||
|
$c.getCostElements().add(t);
|
||||||
|
insert(t);
|
||||||
|
end
|
||||||
|
|
||||||
|
rule "ShangaiHandlingCost"
|
||||||
|
ruleflow-group "calculate"
|
||||||
|
when
|
||||||
|
$c : CostCalculationRequest( )
|
||||||
|
$ci : City(name==City.ShangaiCityName)
|
||||||
|
then
|
||||||
|
int n = $c.getPallets().size();
|
||||||
|
int nbrePalletPerHour = Math.round( n/12)+1;
|
||||||
|
int nbrePerson = Math.round( nbrePalletPerHour/13)+1;
|
||||||
|
HandlingCostElement t = new HandlingCostElement();
|
||||||
|
t.setCity($ci);
|
||||||
|
t.setAmount(nbrePerson*12*20.0);
|
||||||
|
$c.getCostElements().add(t);
|
||||||
|
insert(t);
|
||||||
|
end
|
||||||
|
|
||||||
|
rule "RotterdamHandlingCostAndPersonTaxes"
|
||||||
|
ruleflow-group "calculate"
|
||||||
|
when
|
||||||
|
$c : CostCalculationRequest( )
|
||||||
|
$ci : City(name==City.RotterdamCityName)
|
||||||
|
then
|
||||||
|
int n = $c.getPallets().size();
|
||||||
|
int nbrePalletPerHour = Math.round( n/12)+1;
|
||||||
|
int nbrePerson = Math.round( nbrePalletPerHour/60)+1;
|
||||||
|
HandlingCostElement t = new HandlingCostElement();
|
||||||
|
t.setCity($ci);
|
||||||
|
t.setAmount(nbrePerson*12*45.0);
|
||||||
|
$c.getCostElements().add(t);
|
||||||
|
insert(t);
|
||||||
|
TaxesCostElement t1 = new TaxesCostElement();
|
||||||
|
t1.setAmount(nbrePerson*1.0);
|
||||||
|
$c.getCostElements().add(t1);
|
||||||
|
insert(t1);
|
||||||
|
end
|
||||||
|
|
||||||
|
rule "TournaiHandlingCostAndPersonTaxes"
|
||||||
|
ruleflow-group "calculate"
|
||||||
|
when
|
||||||
|
$c : CostCalculationRequest( )
|
||||||
|
$ci : City(name==City.TournaiCityName)
|
||||||
|
then
|
||||||
|
int n = $c.getPallets().size();
|
||||||
|
int nbrePalletPerHour = Math.round( n/12)+1;
|
||||||
|
int nbrePerson = Math.round( nbrePalletPerHour/40)+1;
|
||||||
|
HandlingCostElement t = new HandlingCostElement();
|
||||||
|
t.setCity($ci);
|
||||||
|
t.setAmount(nbrePerson*12*67.0);
|
||||||
|
$c.getCostElements().add(t);
|
||||||
|
insert(t);
|
||||||
|
TaxesCostElement t1 = new TaxesCostElement();
|
||||||
|
t1.setAmount(nbrePerson*2.0);
|
||||||
|
$c.getCostElements().add(t1);
|
||||||
|
insert(t1);
|
||||||
|
end
|
||||||
|
|
||||||
|
rule "LilleHandlingCostAndPersonTaxes"
|
||||||
|
ruleflow-group "calculate"
|
||||||
|
when
|
||||||
|
$c : CostCalculationRequest( )
|
||||||
|
$ci : City(name==City.LilleCityName)
|
||||||
|
then
|
||||||
|
int n = $c.getPallets().size();
|
||||||
|
int nbrePalletPerHour = Math.round( n/12)+1;
|
||||||
|
int nbrePerson = Math.round( nbrePalletPerHour/30)+1;
|
||||||
|
HandlingCostElement t = new HandlingCostElement();
|
||||||
|
t.setCity($ci);
|
||||||
|
t.setAmount(nbrePerson*12*79.0);
|
||||||
|
$c.getCostElements().add(t);
|
||||||
|
insert(t);
|
||||||
|
TaxesCostElement t1 = new TaxesCostElement();
|
||||||
|
t1.setAmount(nbrePerson*30.0);
|
||||||
|
$c.getCostElements().add(t1);
|
||||||
|
insert(t1);
|
||||||
|
end
|
||||||
|
|
@ -0,0 +1,134 @@
|
||||||
|
package cost.calculation
|
||||||
|
|
||||||
|
import cost.OrderLine;
|
||||||
|
import cost.LeftToDistribute;
|
||||||
|
import cost.Product;
|
||||||
|
import cost.Pallet;
|
||||||
|
import cost.CostCalculationRequest;
|
||||||
|
import cost.CalculatedElement;
|
||||||
|
import java.lang.Math;
|
||||||
|
|
||||||
|
|
||||||
|
rule "Create Counter leftToDistribute quantity"
|
||||||
|
ruleflow-group "distribution"
|
||||||
|
when
|
||||||
|
$elt : OrderLine( numberItems >0 )
|
||||||
|
not (LeftToDistribute(orderLine==$elt))
|
||||||
|
then
|
||||||
|
LeftToDistribute e= new LeftToDistribute($elt,$elt.getNumberItems());
|
||||||
|
insert(e);
|
||||||
|
end
|
||||||
|
rule "Create Counter leftToDistribute weight"
|
||||||
|
ruleflow-group "distribution"
|
||||||
|
when
|
||||||
|
$elt : OrderLine( weight >0 )
|
||||||
|
not (LeftToDistribute(orderLine==$elt))
|
||||||
|
then
|
||||||
|
LeftToDistribute e= new LeftToDistribute($elt,$elt.getWeight());
|
||||||
|
insert(e);
|
||||||
|
end
|
||||||
|
rule "Create PalletForIndividual"
|
||||||
|
ruleflow-group "distribution"
|
||||||
|
when
|
||||||
|
$c : CostCalculationRequest()
|
||||||
|
$p : Product(transportType==Product.transportType_individual)
|
||||||
|
$elt : OrderLine(product==$p )
|
||||||
|
$l : LeftToDistribute(quantityLeft> 0,orderLine==$elt)
|
||||||
|
then
|
||||||
|
Pallet pp = new Pallet();
|
||||||
|
pp.setPalletType($p.getTransportType());
|
||||||
|
pp.addContent($p,new Long(1));
|
||||||
|
insert(pp);
|
||||||
|
$c.getPallets().add(pp);
|
||||||
|
$l.setQuantityLeft($l.getQuantityLeft()-1);
|
||||||
|
update($l);
|
||||||
|
end
|
||||||
|
|
||||||
|
rule "Create PalletForBulkMore1400Kg"
|
||||||
|
ruleflow-group "distribution"
|
||||||
|
when
|
||||||
|
$c : CostCalculationRequest()
|
||||||
|
$p : Product(transportType==Product.transportType_bulkt)
|
||||||
|
$elt : OrderLine(product==$p )
|
||||||
|
$l : LeftToDistribute(weightLeft > 1400,orderLine==$elt)
|
||||||
|
then
|
||||||
|
Pallet pp = new Pallet();
|
||||||
|
pp.setPalletType($p.getTransportType());
|
||||||
|
pp.addContent($p,new Long(1400));
|
||||||
|
insert(pp);
|
||||||
|
$c.getPallets().add(pp);
|
||||||
|
$l.setWeightLeft($l.getWeightLeft()-1400);
|
||||||
|
update($l);
|
||||||
|
end
|
||||||
|
rule "Create PalletForBulkless1400Kg"
|
||||||
|
ruleflow-group "distribution"
|
||||||
|
when
|
||||||
|
$c : CostCalculationRequest()
|
||||||
|
$p : Product(transportType==Product.transportType_bulkt)
|
||||||
|
$elt : OrderLine(product==$p )
|
||||||
|
$l : LeftToDistribute(weightLeft <= 1400,weightLeft > 0,orderLine==$elt)
|
||||||
|
then
|
||||||
|
Pallet pp = new Pallet();
|
||||||
|
pp.setPalletType($p.getTransportType());
|
||||||
|
pp.addContent($p,$l.getWeightLeft());
|
||||||
|
insert(pp);
|
||||||
|
$c.getPallets().add(pp);
|
||||||
|
$l.setWeightLeft(0);
|
||||||
|
update($l);
|
||||||
|
end
|
||||||
|
|
||||||
|
rule "Create Empty Pallet"
|
||||||
|
ruleflow-group "distribution"
|
||||||
|
when
|
||||||
|
not (Pallet (palletType == Product.transportType_pallet,full ==false))
|
||||||
|
then
|
||||||
|
Pallet p = new Pallet();
|
||||||
|
p.setPalletType(Product.transportType_pallet);
|
||||||
|
insert (p);
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
rule "Create PalletFortransportType_pallet"
|
||||||
|
ruleflow-group "distribution"
|
||||||
|
when
|
||||||
|
$c : CostCalculationRequest()
|
||||||
|
$pp : Pallet($hl : heightLeft ,full ==false,palletType == Product.transportType_pallet)
|
||||||
|
$p : Product(height <= $hl,transportType==Product.transportType_pallet)
|
||||||
|
$elt : OrderLine(product==$p )
|
||||||
|
$l : LeftToDistribute(quantityLeft > 0,orderLine==$elt)
|
||||||
|
then
|
||||||
|
long a = (long) Math.round($pp.getWidth()/$p.getWidth());
|
||||||
|
long b = (long) Math.round($pp.getDepth()/$p.getDepth());
|
||||||
|
long n = Math.min(a*b,$l.getQuantityLeft());
|
||||||
|
$pp.addContent($p,n);
|
||||||
|
$pp.setHeightLeft($pp.getHeightLeft()-$p.getHeight());
|
||||||
|
update($pp);
|
||||||
|
$l.setQuantityLeft($l.getQuantityLeft()-n);
|
||||||
|
update($l);
|
||||||
|
end
|
||||||
|
|
||||||
|
rule "FillPalletIfNoProductGoesIn"
|
||||||
|
ruleflow-group "distribution"
|
||||||
|
when
|
||||||
|
CalculatedElement($min : doubleValue ,key=="minValue.product")
|
||||||
|
$p : Pallet(heightLeft!= 2.0,$hl : heightLeft < $min ,full ==false,palletType == Product.transportType_pallet)
|
||||||
|
then
|
||||||
|
$p.setFull(true);
|
||||||
|
System.out.println("MinValue="+$min);
|
||||||
|
update($p);
|
||||||
|
end
|
||||||
|
|
||||||
|
rule "GetSmallestHeight"
|
||||||
|
ruleflow-group "distribution"
|
||||||
|
when
|
||||||
|
accumulate( Product( $h : height ,transportType==Product.transportType_pallet );
|
||||||
|
$min : min( $h );
|
||||||
|
true )
|
||||||
|
|
||||||
|
then
|
||||||
|
CalculatedElement elt = new CalculatedElement();
|
||||||
|
elt.setKey("minValue.product");
|
||||||
|
elt.setDoubleValue((Double)$min);
|
||||||
|
insert(elt);
|
||||||
|
end
|
||||||
|
|
@ -0,0 +1,468 @@
|
||||||
|
# Rules
|
||||||
|
|
||||||
|
We shall use a Ruleflow and implement the rules in 3 steps :
|
||||||
|
* Distribute the products in the pallet
|
||||||
|
* Calculate the costs
|
||||||
|
* Calculate and Display the results
|
||||||
|
|
||||||
|
This is done in the P1.bpmn2.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
## Distribute the products in the pallet
|
||||||
|
|
||||||
|
This rules will be executed in the rule step "distribution". So we shall add the keyworruleflow-group "distribution".
|
||||||
|
|
||||||
|
There are 3 types of product : those we have to put individually, the bulk and the others.
|
||||||
|
|
||||||
|
### Initialize a counter for each order line
|
||||||
|
|
||||||
|
First we shall the rule that created the LeftToDistribute object.
|
||||||
|
For each orderline we create and link to the orderline element
|
||||||
|
```
|
||||||
|
rule "Create Counter leftToDistribute quantity"
|
||||||
|
ruleflow-group "distribution"
|
||||||
|
when
|
||||||
|
$elt : OrderLine( numberItems >0 )
|
||||||
|
not (LeftToDistribute(orderLine==$elt))
|
||||||
|
then
|
||||||
|
LeftToDistribute e= new LeftToDistribute($elt,$elt.getNumberItems());
|
||||||
|
insert(e);
|
||||||
|
end
|
||||||
|
rule "Create Counter leftToDistribute weight"
|
||||||
|
ruleflow-group "distribution"
|
||||||
|
when
|
||||||
|
$elt : OrderLine( weight >0 )
|
||||||
|
not (LeftToDistribute(orderLine==$elt))
|
||||||
|
then
|
||||||
|
LeftToDistribute e= new LeftToDistribute($elt,$elt.getWeight());
|
||||||
|
insert(e);
|
||||||
|
end
|
||||||
|
|
||||||
|
```
|
||||||
|
So here the rule above for each OrderLine that is not yet connected to a LeftToDistribute fact.
|
||||||
|
Then we create it and initialize the counter with the number of elements in the line.
|
||||||
|
We have one rule when items are
|
||||||
|
|
||||||
|
### individual items
|
||||||
|
|
||||||
|
For each product of type individual, we shall put it on the pallet.
|
||||||
|
And in the then part, we create the pallet, decrease the number of element left and update the objects?
|
||||||
|
|
||||||
|
```
|
||||||
|
rule "Create PalletForIndividual"
|
||||||
|
ruleflow-group "distribution"
|
||||||
|
when
|
||||||
|
$c : CostCalculationRequest()
|
||||||
|
$p : Product(transportType==Product.transportType_individual)
|
||||||
|
$elt : OrderLine(product==$p )
|
||||||
|
$l : LeftToDistribute(quantityLeft> 0,orderLine==$elt)
|
||||||
|
then
|
||||||
|
Pallet pp = new Pallet();
|
||||||
|
pp.setPalletType($p.getTransportType());
|
||||||
|
pp.addContent($p,new Long(1));
|
||||||
|
insert(pp);
|
||||||
|
$c.getPallets().add(pp);
|
||||||
|
$l.setQuantityLeft($l.getQuantityLeft()-1);
|
||||||
|
update($l);
|
||||||
|
end
|
||||||
|
```
|
||||||
|
|
||||||
|
### bulk item
|
||||||
|
|
||||||
|
For the bulk product, we shall do the same way.
|
||||||
|
The first rule files 1400kg on each pallet.
|
||||||
|
The second rule is if there is less than 1400kg left, then we put the rest in the pallet.
|
||||||
|
|
||||||
|
```
|
||||||
|
rule "Create PalletForBulkMore1400Kg"
|
||||||
|
ruleflow-group "distribution"
|
||||||
|
when
|
||||||
|
$c : CostCalculationRequest()
|
||||||
|
$p : Product(transportType==Product.transportType_bulkt)
|
||||||
|
$elt : OrderLine(product==$p )
|
||||||
|
$l : LeftToDistribute(weightLeft > 1400,orderLine==$elt)
|
||||||
|
then
|
||||||
|
Pallet pp = new Pallet();
|
||||||
|
pp.setPalletType($p.getTransportType());
|
||||||
|
pp.addContent($p,new Long(1400));
|
||||||
|
insert(pp);
|
||||||
|
$c.getPallets().add(pp);
|
||||||
|
$l.setWeightLeft($l.getWeightLeft()-1400);
|
||||||
|
update($l);
|
||||||
|
end
|
||||||
|
rule "Create PalletForBulkless1400Kg"
|
||||||
|
ruleflow-group "distribution"
|
||||||
|
when
|
||||||
|
$c : CostCalculationRequest()
|
||||||
|
$p : Product(transportType==Product.transportType_bulkt)
|
||||||
|
$elt : OrderLine(product==$p )
|
||||||
|
$l : LeftToDistribute(weightLeft <= 1400,weightLeft > 0,orderLine==$elt)
|
||||||
|
then
|
||||||
|
Pallet pp = new Pallet();
|
||||||
|
pp.setPalletType($p.getTransportType());
|
||||||
|
pp.addContent($p,$l.getWeightLeft());
|
||||||
|
insert(pp);
|
||||||
|
$c.getPallets().add(pp);
|
||||||
|
$l.setWeightLeft(0);
|
||||||
|
update($l);
|
||||||
|
end
|
||||||
|
```
|
||||||
|
|
||||||
|
### Distribute the other product type.
|
||||||
|
We shall first create a rule that create a new Pallet if none is available
|
||||||
|
|
||||||
|
```
|
||||||
|
rule "Create Empty Pallet"
|
||||||
|
ruleflow-group "distribution"
|
||||||
|
when
|
||||||
|
not (Pallet (palletType == Product.transportType_pallet,full ==false))
|
||||||
|
then
|
||||||
|
Pallet p = new Pallet();
|
||||||
|
p.setPalletType(Product.transportType_pallet);
|
||||||
|
insert (p);
|
||||||
|
end
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
As we are going to fill the pallet in height, we shall declare a pallet as full if the place left in height is smaller than the smallest product in height.
|
||||||
|
|
||||||
|
```
|
||||||
|
rule "GetSmallestHeight"
|
||||||
|
ruleflow-group "distribution"
|
||||||
|
when
|
||||||
|
accumulate( Product( $h : height ,transportType==Product.transportType_pallet );
|
||||||
|
$min : min( $h );
|
||||||
|
true )
|
||||||
|
|
||||||
|
then
|
||||||
|
CalculatedElement elt = new CalculatedElement();
|
||||||
|
elt.setKey("minValue.product");
|
||||||
|
elt.setDoubleValue((Double)$min);
|
||||||
|
insert(elt);
|
||||||
|
end
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
And then the rule that sets the pallet as filled (full has the true value). We only set the value of a pallet that has been filled by one type of product by adding constranint heightLeft!= 2.0.
|
||||||
|
|
||||||
|
```
|
||||||
|
rule "FillPalletIfNoProductGoesIn"
|
||||||
|
ruleflow-group "distribution"
|
||||||
|
when
|
||||||
|
CalculatedElement($min : doubleValue ,key=="minValue.product")
|
||||||
|
$p : Pallet(heightLeft!= 2.0,$hl : heightLeft < $min ,full ==false,palletType == Product.transportType_pallet)
|
||||||
|
then
|
||||||
|
$p.setFull(true);
|
||||||
|
System.out.println("MinValue="+$min);
|
||||||
|
update($p);
|
||||||
|
end
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
Then the rule that fills the pallet with product depending on the size of the product.
|
||||||
|
|
||||||
|
```
|
||||||
|
rule "Create PalletFortransportType_pallet"
|
||||||
|
ruleflow-group "distribution"
|
||||||
|
when
|
||||||
|
$c : CostCalculationRequest()
|
||||||
|
$pp : Pallet($hl : heightLeft ,full ==false,palletType == Product.transportType_pallet)
|
||||||
|
$p : Product(height <= $hl,transportType==Product.transportType_pallet)
|
||||||
|
$elt : OrderLine(product==$p )
|
||||||
|
$l : LeftToDistribute(quantityLeft > 0,orderLine==$elt)
|
||||||
|
then
|
||||||
|
long a = (long) Math.round($pp.getWidth()/$p.getWidth());
|
||||||
|
long b = (long) Math.round($pp.getDepth()/$p.getDepth());
|
||||||
|
long n = Math.min(a*b,$l.getQuantityLeft());
|
||||||
|
$pp.addContent($p,n);
|
||||||
|
$pp.setHeightLeft($pp.getHeightLeft()-$p.getHeight());
|
||||||
|
update($pp);
|
||||||
|
$l.setQuantityLeft($l.getQuantityLeft()-n);
|
||||||
|
update($l);
|
||||||
|
end
|
||||||
|
```
|
||||||
|
|
||||||
|
## Calculate the costs
|
||||||
|
Now we take each cost and add a CostElement depending on the number of pallets we created in previous step
|
||||||
|
|
||||||
|
### Transport cost
|
||||||
|
For each step type we calculate the cost
|
||||||
|
|
||||||
|
```
|
||||||
|
rule "boatTransportCost"
|
||||||
|
ruleflow-group "calculate"
|
||||||
|
when
|
||||||
|
$c : CostCalculationRequest( )
|
||||||
|
$s : Step(transportType ==Step.Ship_TransportType)
|
||||||
|
then
|
||||||
|
TransportCostElement t = new TransportCostElement();
|
||||||
|
t.setStep($s);
|
||||||
|
t.setAmount($c.getPallets().size()*$s.getDistance()*0.2);
|
||||||
|
$c.getCostElements().add(t);
|
||||||
|
insert(t);
|
||||||
|
end
|
||||||
|
|
||||||
|
rule "trainTransportCost"
|
||||||
|
ruleflow-group "calculate"
|
||||||
|
when
|
||||||
|
$c : CostCalculationRequest( )
|
||||||
|
$s : Step(transportType ==Step.train_TransportType)
|
||||||
|
then
|
||||||
|
TransportCostElement t = new TransportCostElement();
|
||||||
|
t.setStep($s);
|
||||||
|
t.setAmount($c.getPallets().size()*$s.getDistance()*0.5);
|
||||||
|
$c.getCostElements().add(t);
|
||||||
|
insert(t);
|
||||||
|
end
|
||||||
|
|
||||||
|
rule "truckTransportCost"
|
||||||
|
ruleflow-group "calculate"
|
||||||
|
when
|
||||||
|
$c : CostCalculationRequest( )
|
||||||
|
$s : Step(transportType ==Step.truck_TransportType)
|
||||||
|
then
|
||||||
|
TransportCostElement t = new TransportCostElement();
|
||||||
|
t.setStep($s);
|
||||||
|
t.setAmount($c.getPallets().size()*$s.getDistance()*1.0);
|
||||||
|
$c.getCostElements().add(t);
|
||||||
|
insert(t);
|
||||||
|
end
|
||||||
|
```
|
||||||
|
### Taxes Cost
|
||||||
|
For each City we go through, we calculate the cost (Shangai and Rotterdam)
|
||||||
|
As sometimes it depends on the weight, we have to sum the total amount of weigh on all pallets.
|
||||||
|
Here we chose not to put all calculation in the drools session, so we do the sum in the them part of the rules.
|
||||||
|
Se here how we obtain the list of Pallet we want in an ArrayList. In the then part we then iterate on the founded pallet and in the pallet we go through all the products to sum the weight.
|
||||||
|
```
|
||||||
|
rule "ShangaiTaxesCost_bulk"
|
||||||
|
ruleflow-group "calculate"
|
||||||
|
when
|
||||||
|
$c : CostCalculationRequest( )
|
||||||
|
$ci : City(name==City.ShangaiCityName)
|
||||||
|
$listPallet : ArrayList( )
|
||||||
|
from collect( Pallet(palletType == Product.transportType_bulkt) )
|
||||||
|
then
|
||||||
|
TaxesCostElement t = new TaxesCostElement();
|
||||||
|
t.setCity($ci);
|
||||||
|
double totalWeight=0;
|
||||||
|
for (Object oo : $listPallet){
|
||||||
|
Pallet pp = (Pallet)oo;
|
||||||
|
for (Double d : pp.getContentWeight().values()){
|
||||||
|
totalWeight=totalWeight+d;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
t.setAmount(totalWeight*0.02);
|
||||||
|
$c.getCostElements().add(t);
|
||||||
|
insert(t);
|
||||||
|
end
|
||||||
|
|
||||||
|
rule "ShangaiTaxesCost_notbulk"
|
||||||
|
ruleflow-group "calculate"
|
||||||
|
when
|
||||||
|
$c : CostCalculationRequest( )
|
||||||
|
$ci : City(name==City.ShangaiCityName)
|
||||||
|
$listPallet : ArrayList( )
|
||||||
|
from collect( Pallet(palletType != Product.transportType_bulkt) )
|
||||||
|
then
|
||||||
|
TaxesCostElement t = new TaxesCostElement();
|
||||||
|
t.setCity($ci);
|
||||||
|
double totalWeight=0;
|
||||||
|
for (Object oo : $listPallet){
|
||||||
|
Pallet pp = (Pallet)oo;
|
||||||
|
for (Product p : pp.getContentQuantity().keySet()){
|
||||||
|
totalWeight=totalWeight+p.getWeight()* pp.getContentQuantity().get(p);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
t.setAmount(totalWeight*0.05);
|
||||||
|
$c.getCostElements().add(t);
|
||||||
|
insert(t);
|
||||||
|
end
|
||||||
|
|
||||||
|
rule "RotterdamTaxesCost_bulk_weight"
|
||||||
|
ruleflow-group "calculate"
|
||||||
|
when
|
||||||
|
$c : CostCalculationRequest( )
|
||||||
|
$ci : City(name==City.RotterdamCityName)
|
||||||
|
$listPallet : ArrayList( )
|
||||||
|
from collect( Pallet(palletType == Product.transportType_bulkt) )
|
||||||
|
then
|
||||||
|
TaxesCostElement t = new TaxesCostElement();
|
||||||
|
t.setCity($ci);
|
||||||
|
double totalWeight=0;
|
||||||
|
for (Object oo : $listPallet){
|
||||||
|
Pallet pp = (Pallet)oo;
|
||||||
|
for (Double d : pp.getContentWeight().values()){
|
||||||
|
totalWeight=totalWeight+d;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
t.setAmount(totalWeight*0.05);
|
||||||
|
$c.getCostElements().add(t);
|
||||||
|
insert(t);
|
||||||
|
end
|
||||||
|
rule "RotterdamTaxesCost_notbulk_weight"
|
||||||
|
ruleflow-group "calculate"
|
||||||
|
when
|
||||||
|
$c : CostCalculationRequest( )
|
||||||
|
$ci : City(name==City.RotterdamCityName)
|
||||||
|
$listPallet : ArrayList( )
|
||||||
|
from collect( Pallet(palletType != Product.transportType_bulkt) )
|
||||||
|
then
|
||||||
|
TaxesCostElement t = new TaxesCostElement();
|
||||||
|
t.setCity($ci);
|
||||||
|
double totalWeight=0;
|
||||||
|
for (Object oo : $listPallet){
|
||||||
|
Pallet pp = (Pallet)oo;
|
||||||
|
for (Product p : pp.getContentQuantity().keySet()){
|
||||||
|
totalWeight=totalWeight+p.getWeight()* pp.getContentQuantity().get(p);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
t.setAmount(totalWeight*0.05);
|
||||||
|
$c.getCostElements().add(t);
|
||||||
|
insert(t);
|
||||||
|
end
|
||||||
|
```
|
||||||
|
|
||||||
|
### Handling Cost and taxes on the Handling
|
||||||
|
Here we admit that it takes 12 hours to do the handling.
|
||||||
|
Based on that we then see how many pallets we have to handle per hour and then depending on the what a person can handle per hour, we calculate the number of persons we need.
|
||||||
|
```
|
||||||
|
rule "ShangaiHandlingCost"
|
||||||
|
ruleflow-group "calculate"
|
||||||
|
when
|
||||||
|
$c : CostCalculationRequest( )
|
||||||
|
$ci : City(name==City.ShangaiCityName)
|
||||||
|
then
|
||||||
|
int n = $c.getPallets().size();
|
||||||
|
int nbrePalletPerHour = Math.round( n/12)+1;
|
||||||
|
int nbrePerson = Math.round( nbrePalletPerHour/13)+1;
|
||||||
|
HandlingCostElement t = new HandlingCostElement();
|
||||||
|
t.setCity($ci);
|
||||||
|
t.setAmount(nbrePerson*12*20.0);
|
||||||
|
$c.getCostElements().add(t);
|
||||||
|
insert(t);
|
||||||
|
end
|
||||||
|
|
||||||
|
rule "RotterdamHandlingCostAndPersonTaxes"
|
||||||
|
ruleflow-group "calculate"
|
||||||
|
when
|
||||||
|
$c : CostCalculationRequest( )
|
||||||
|
$ci : City(name==City.RotterdamCityName)
|
||||||
|
then
|
||||||
|
int n = $c.getPallets().size();
|
||||||
|
int nbrePalletPerHour = Math.round( n/12)+1;
|
||||||
|
int nbrePerson = Math.round( nbrePalletPerHour/60)+1;
|
||||||
|
HandlingCostElement t = new HandlingCostElement();
|
||||||
|
t.setCity($ci);
|
||||||
|
t.setAmount(nbrePerson*12*45.0);
|
||||||
|
$c.getCostElements().add(t);
|
||||||
|
insert(t);
|
||||||
|
TaxesCostElement t1 = new TaxesCostElement();
|
||||||
|
t1.setAmount(nbrePerson*1.0);
|
||||||
|
$c.getCostElements().add(t1);
|
||||||
|
insert(t1);
|
||||||
|
end
|
||||||
|
|
||||||
|
rule "TournaiHandlingCostAndPersonTaxes"
|
||||||
|
ruleflow-group "calculate"
|
||||||
|
when
|
||||||
|
$c : CostCalculationRequest( )
|
||||||
|
$ci : City(name==City.TournaiCityName)
|
||||||
|
then
|
||||||
|
int n = $c.getPallets().size();
|
||||||
|
int nbrePalletPerHour = Math.round( n/12)+1;
|
||||||
|
int nbrePerson = Math.round( nbrePalletPerHour/40)+1;
|
||||||
|
HandlingCostElement t = new HandlingCostElement();
|
||||||
|
t.setCity($ci);
|
||||||
|
t.setAmount(nbrePerson*12*67.0);
|
||||||
|
$c.getCostElements().add(t);
|
||||||
|
insert(t);
|
||||||
|
TaxesCostElement t1 = new TaxesCostElement();
|
||||||
|
t1.setAmount(nbrePerson*2.0);
|
||||||
|
$c.getCostElements().add(t1);
|
||||||
|
insert(t1);
|
||||||
|
end
|
||||||
|
|
||||||
|
rule "LilleHandlingCostAndPersonTaxes"
|
||||||
|
ruleflow-group "calculate"
|
||||||
|
when
|
||||||
|
$c : CostCalculationRequest( )
|
||||||
|
$ci : City(name==City.LilleCityName)
|
||||||
|
then
|
||||||
|
int n = $c.getPallets().size();
|
||||||
|
int nbrePalletPerHour = Math.round( n/12)+1;
|
||||||
|
int nbrePerson = Math.round( nbrePalletPerHour/30)+1;
|
||||||
|
HandlingCostElement t = new HandlingCostElement();
|
||||||
|
t.setCity($ci);
|
||||||
|
t.setAmount(nbrePerson*12*79.0);
|
||||||
|
$c.getCostElements().add(t);
|
||||||
|
insert(t);
|
||||||
|
TaxesCostElement t1 = new TaxesCostElement();
|
||||||
|
t1.setAmount(nbrePerson*30.0);
|
||||||
|
$c.getCostElements().add(t1);
|
||||||
|
insert(t1);
|
||||||
|
end
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
## Sum the results
|
||||||
|
We use the accumulate function to show the results. We just show the result in the console. On a real project, the results could habe stored in a data structure.
|
||||||
|
|
||||||
|
```
|
||||||
|
rule "CalculateTotal"
|
||||||
|
ruleflow-group "total"
|
||||||
|
when
|
||||||
|
$c : CostCalculationRequest( )
|
||||||
|
$totalBoatTransport : Number( doubleValue > 100 )
|
||||||
|
from accumulate( $s : Step(transportType ==Step.Ship_TransportType) &&
|
||||||
|
TransportCostElement(step ==$s, $value : amount ),
|
||||||
|
init( double total = 0; ),
|
||||||
|
action( total += $value; ),
|
||||||
|
reverse( total -= $value; ),
|
||||||
|
result( total ) )
|
||||||
|
$totalTrainTransport : Number( doubleValue > 100 )
|
||||||
|
from accumulate( $s : Step(transportType ==Step.train_TransportType) &&
|
||||||
|
TransportCostElement(step ==$s, $value : amount ),
|
||||||
|
init( double total = 0; ),
|
||||||
|
action( total += $value; ),
|
||||||
|
reverse( total -= $value; ),
|
||||||
|
result( total ) )
|
||||||
|
$totalTruckTransport : Number( doubleValue > 100 )
|
||||||
|
from accumulate( $s : Step(transportType ==Step.truck_TransportType) &&
|
||||||
|
TransportCostElement(step ==$s, $value : amount ),
|
||||||
|
init( double total = 0; ),
|
||||||
|
action( total += $value; ),
|
||||||
|
reverse( total -= $value; ),
|
||||||
|
result( total ) )
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
$totalTransport : Number( doubleValue > 100 )
|
||||||
|
from accumulate( TransportCostElement( $value : amount ),
|
||||||
|
init( double total = 0; ),
|
||||||
|
action( total += $value; ),
|
||||||
|
reverse( total -= $value; ),
|
||||||
|
result( total ) )
|
||||||
|
$totalTaxes : Number( doubleValue > 100 )
|
||||||
|
from accumulate( TaxesCostElement( $value : amount ),
|
||||||
|
init( double total = 0; ),
|
||||||
|
action( total += $value; ),
|
||||||
|
reverse( total -= $value; ),
|
||||||
|
result( total ) )
|
||||||
|
$totalHandling : Number( doubleValue > 100 )
|
||||||
|
from accumulate( HandlingCostElement( $value : amount ),
|
||||||
|
init( double total = 0; ),
|
||||||
|
action( total += $value; ),
|
||||||
|
reverse( total -= $value; ),
|
||||||
|
result( total ) )
|
||||||
|
then
|
||||||
|
System.out.println("NumberOfPallets="+$c.getPallets().size());
|
||||||
|
System.out.println("TotalShipTransport="+$totalBoatTransport);
|
||||||
|
System.out.println("TotalTrainTransport="+$totalTrainTransport);
|
||||||
|
System.out.println("TotalTruckTransport="+$totalTruckTransport);
|
||||||
|
System.out.println("TotalTransport="+$totalTransport);
|
||||||
|
System.out.println("TotalTaxes="+$totalTaxes);
|
||||||
|
System.out.println("TotalHandling="+$totalHandling);
|
||||||
|
end;
|
||||||
|
```
|
||||||
|
|
||||||
Binary file not shown.
|
After Width: | Height: | Size: 12 KiB |
78
cost-calculation-run/README.md
Normal file
78
cost-calculation-run/README.md
Normal file
|
|
@ -0,0 +1,78 @@
|
||||||
|
# Cost Calculation project
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# Requirements
|
||||||
|
We are working for a retail company that buys its products from different places in Asian mostly. each shop can go to the buying web site and say what he wants and put an order.
|
||||||
|
Up to now, the transport cost was a estimated but not calculated on the content of the order.
|
||||||
|
The purpose is to implement such a calculator.
|
||||||
|
|
||||||
|
## Data model
|
||||||
|
|
||||||
|
A customer puts an order that contains products. An order contains a lost of products with a number.
|
||||||
|
A product has
|
||||||
|
* a name
|
||||||
|
* a height,
|
||||||
|
* a width,
|
||||||
|
* a depth,
|
||||||
|
* transport type : if the product can be put with other products in a pallet, individual(alone) or bulk (like sand for example)
|
||||||
|
* a weight
|
||||||
|
|
||||||
|
A product can be put on a pallet. a pallet 120 cm width and and 80 cm depth. It can be maximum 2 meters height and the weight should not exceed 1400 kg. We should use a simple algorithm to fill each pallet. It will be not optimized but we should used that as a margin of the costs. a product that is bigger than 60 cm in width or depth or higher than 1m should be put alone in a pallet.
|
||||||
|
|
||||||
|
All products start from the same city and go to the same city in an order. A trip is composed f steps. Each step can be done by train, boat or truck.
|
||||||
|
|
||||||
|
|
||||||
|
Here is the list of products in our test order.
|
||||||
|
|
||||||
|
| Product | Transport type | Number | Height | Weight | depth | weight |
|
||||||
|
| -- | -- | -- | -- | -- | -- | -- |
|
||||||
|
| drill | pallet | 1000 | 20cm | 40cm | 30cm | 2 kg |
|
||||||
|
| screwdriver | pallet | 30000 | 3cm | 2cm | 20cm | 0,2 kg |
|
||||||
|
| Sand | bulk | | | | | 35 Tons |
|
||||||
|
| Gravel | bulk | | | | | 14 Tons |
|
||||||
|
| furniture | individual |23 | | | | 500 kg |
|
||||||
|
|
||||||
|
And the trip is a follows :
|
||||||
|
|
||||||
|
| # | start city | arrival city | distance (km) | travel mode |
|
||||||
|
| -- | -- | -- | -- | -- |
|
||||||
|
| 1 | Shangai | Rotterdam | 22000 | Boat|
|
||||||
|
| 2 | Rotterdam | Tournai | 300 | Train |
|
||||||
|
| 3 | Tournai | Lille | 20 | Truck |
|
||||||
|
|
||||||
|
|
||||||
|
there are 3 types of costs :
|
||||||
|
- transport costs per Pallet
|
||||||
|
|
||||||
|
| Transport| Cost
|
||||||
|
| -- | -- |
|
||||||
|
| boat | 0,2€/km |
|
||||||
|
| Train | 0,5€/km |
|
||||||
|
| Truck | 1€/km |
|
||||||
|
|
||||||
|
- Taxes
|
||||||
|
|
||||||
|
| City| Cost
|
||||||
|
| -- | -- |
|
||||||
|
| Shangai | 0,02€/kg |
|
||||||
|
| Rotterdam | 0,05€/kg and 1€ per handling person |
|
||||||
|
| Tournai | 2€ per handling person |
|
||||||
|
| Lille | 30€ per handling person |
|
||||||
|
|
||||||
|
|
||||||
|
- handling
|
||||||
|
|
||||||
|
| City| Cost
|
||||||
|
| -- | -- |
|
||||||
|
| Shangai | 20€/hour and a person can handle 13 pallets/hour |
|
||||||
|
| Rotterdam | 45€/hour and a person can handle 60 pallets/hour |
|
||||||
|
| Tournai | 67€/hour and can handle 40 pallets/hour |
|
||||||
|
| Lille | 79€/hour and can handle 30 pallets/hour |
|
||||||
|
|
||||||
|
The handling should not take more than 12 hours.
|
||||||
|
|
||||||
|
[Data Model ](src/main/java/cost/README.md)
|
||||||
|
|
||||||
|
[The rules we implemented ](src/main/resources/rules/README.md)
|
||||||
36
cost-calculation-run/cost-calculation-run.iml
Normal file
36
cost-calculation-run/cost-calculation-run.iml
Normal file
|
|
@ -0,0 +1,36 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<module org.jetbrains.idea.maven.project.MavenProjectsManager.isMavenModule="true" type="JAVA_MODULE" version="4">
|
||||||
|
<component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_7" inherit-compiler-output="false">
|
||||||
|
<output url="file://$MODULE_DIR$/target/classes" />
|
||||||
|
<output-test url="file://$MODULE_DIR$/target/test-classes" />
|
||||||
|
<content url="file://$MODULE_DIR$">
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/src/main/java" isTestSource="false" />
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/src/main/resources" type="java-resource" />
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/src/test/java" isTestSource="true" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/target" />
|
||||||
|
</content>
|
||||||
|
<orderEntry type="inheritedJdk" />
|
||||||
|
<orderEntry type="sourceFolder" forTests="false" />
|
||||||
|
<orderEntry type="module" module-name="cost-calculation-extension" />
|
||||||
|
<orderEntry type="module" module-name="cost-calculation-base" />
|
||||||
|
<orderEntry type="library" name="Maven: org.drools:drools-compiler:6.5.0.Final" level="project" />
|
||||||
|
<orderEntry type="library" name="Maven: org.drools:drools-core:6.5.0.Final" level="project" />
|
||||||
|
<orderEntry type="library" name="Maven: commons-codec:commons-codec:1.4" level="project" />
|
||||||
|
<orderEntry type="library" name="Maven: org.kie:kie-internal:6.5.0.Final" level="project" />
|
||||||
|
<orderEntry type="library" name="Maven: org.antlr:antlr-runtime:3.5" level="project" />
|
||||||
|
<orderEntry type="library" name="Maven: org.mvel:mvel2:2.2.8.Final" level="project" />
|
||||||
|
<orderEntry type="library" name="Maven: com.thoughtworks.xstream:xstream:1.4.9" level="project" />
|
||||||
|
<orderEntry type="library" name="Maven: xmlpull:xmlpull:1.1.3.1" level="project" />
|
||||||
|
<orderEntry type="library" name="Maven: xpp3:xpp3_min:1.1.4c" level="project" />
|
||||||
|
<orderEntry type="library" name="Maven: com.google.protobuf:protobuf-java:2.6.0" level="project" />
|
||||||
|
<orderEntry type="library" name="Maven: org.slf4j:slf4j-api:1.7.2" level="project" />
|
||||||
|
<orderEntry type="library" name="Maven: org.eclipse.jdt.core.compiler:ecj:4.4.2" level="project" />
|
||||||
|
<orderEntry type="library" name="Maven: org.jbpm:jbpm-bpmn2:6.5.0.Final" level="project" />
|
||||||
|
<orderEntry type="library" name="Maven: org.jbpm:jbpm-flow-builder:6.5.0.Final" level="project" />
|
||||||
|
<orderEntry type="library" name="Maven: org.jbpm:jbpm-flow:6.5.0.Final" level="project" />
|
||||||
|
<orderEntry type="library" name="Maven: joda-time:joda-time:2.2" level="project" />
|
||||||
|
<orderEntry type="library" scope="TEST" name="Maven: junit:junit:4.5" level="project" />
|
||||||
|
<orderEntry type="library" name="Maven: org.kie:kie-api:6.5.0.Final" level="project" />
|
||||||
|
<orderEntry type="module" module-name="drools-lesson-pojo" />
|
||||||
|
</component>
|
||||||
|
</module>
|
||||||
47
cost-calculation-run/pom.xml
Normal file
47
cost-calculation-run/pom.xml
Normal file
|
|
@ -0,0 +1,47 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xmlns="http://maven.apache.org/POM/4.0.0"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<parent>
|
||||||
|
<artifactId>droolscourse</artifactId>
|
||||||
|
<groupId>com.pymma-software.droolscourse</groupId>
|
||||||
|
<version>2.0.0-SNAPSHOT</version>
|
||||||
|
</parent>
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
<artifactId>cost-calculation-run</artifactId>
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.pymma-software.droolscourse</groupId>
|
||||||
|
<artifactId>cost-calculation-extension</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.drools</groupId>
|
||||||
|
<artifactId>drools-compiler</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.eclipse.jdt.core.compiler</groupId>
|
||||||
|
<artifactId>ecj</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.jbpm</groupId>
|
||||||
|
<artifactId>jbpm-bpmn2</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>junit</groupId>
|
||||||
|
<artifactId>junit</artifactId>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.kie</groupId>
|
||||||
|
<artifactId>kie-api</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.pymma-software.droolscourse</groupId>
|
||||||
|
<artifactId>drools-lesson-pojo</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
</project>
|
||||||
|
|
@ -0,0 +1,96 @@
|
||||||
|
package calculation;
|
||||||
|
|
||||||
|
import cost.*;
|
||||||
|
import org.junit.After;
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.BeforeClass;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.kie.api.runtime.KieContainer;
|
||||||
|
import org.kie.api.runtime.KieSession;
|
||||||
|
import org.kie.api.runtime.StatelessKieSession;
|
||||||
|
import util.KnowledgeSessionHelper;
|
||||||
|
|
||||||
|
@SuppressWarnings("restriction")
|
||||||
|
public class TestExecercice {
|
||||||
|
|
||||||
|
static KieContainer kieContainer;
|
||||||
|
StatelessKieSession sessionStateless = null;
|
||||||
|
KieSession sessionStatefull = null;
|
||||||
|
|
||||||
|
@BeforeClass
|
||||||
|
public static void beforeClass() {
|
||||||
|
kieContainer = KnowledgeSessionHelper.createRuleBase();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void setUp() throws Exception {
|
||||||
|
System.out.println("------------Before------------");
|
||||||
|
}
|
||||||
|
|
||||||
|
@After
|
||||||
|
public void tearDown() throws Exception {
|
||||||
|
System.out.println("------------After------------");
|
||||||
|
}
|
||||||
|
|
||||||
|
private void insertIntoSession(KieSession sessionStatefull, CostCalculationRequest request) {
|
||||||
|
sessionStatefull.insert(request);
|
||||||
|
if (request.getOrder() != null) {
|
||||||
|
sessionStatefull.insert(request.getOrder());
|
||||||
|
for (OrderLine orderLine : request.getOrder().getOrderLines()) {
|
||||||
|
sessionStatefull.insert(orderLine);
|
||||||
|
sessionStatefull.insert(orderLine.getProduct());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (request.getTrip() != null) {
|
||||||
|
sessionStatefull.insert(request.getTrip());
|
||||||
|
for (Step step : request.getTrip().getSteps()) {
|
||||||
|
sessionStatefull.insert(step);
|
||||||
|
sessionStatefull.insert(step.getStepStart());
|
||||||
|
sessionStatefull.insert(step.getStepEnd());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testFirstOne() {
|
||||||
|
sessionStatefull = KnowledgeSessionHelper.getStatefulKnowledgeSessionForJBPM(kieContainer, "ksession4");
|
||||||
|
City cityOfShangai = new City(City.ShangaiCityName);
|
||||||
|
City cityOfRotterdam = new City(City.RotterdamCityName);
|
||||||
|
City cityOfTournai = new City(City.TournaiCityName);
|
||||||
|
City cityOfLille = new City(City.LilleCityName);
|
||||||
|
Step step1 = new Step(cityOfShangai, cityOfRotterdam, 22000, Step.Ship_TransportType);
|
||||||
|
Step step2 = new Step(cityOfRotterdam, cityOfTournai, 300, Step.train_TransportType);
|
||||||
|
Step step3 = new Step(cityOfTournai, cityOfLille, 20, Step.truck_TransportType);
|
||||||
|
Trip myTrip = new Trip("trip1");
|
||||||
|
myTrip.getSteps().add(step1);
|
||||||
|
myTrip.getSteps().add(step2);
|
||||||
|
myTrip.getSteps().add(step3);
|
||||||
|
CostCalculationRequest request = new CostCalculationRequest();
|
||||||
|
request.setTrip(myTrip);
|
||||||
|
Product drillProduct = new Product("Drill", 0.2, 0.4, 0.3, 2, Product.transportType_pallet);
|
||||||
|
Product screwDriverProduct = new Product("Screwdriver", 0.03, 0.02, 0.2, 0.2, Product.transportType_pallet);
|
||||||
|
Product sandProduct = new Product("Sand", 0.0, 0.0, 0.0, 0.0, Product.transportType_bulkt);
|
||||||
|
Product gravelProduct = new Product("Gravel", 0.0, 0.0, 0.0, 0.0, Product.transportType_bulkt);
|
||||||
|
Product furnitureProduct = new Product("Furniture", 0.0, 0.0, 0.0, 0.0, Product.transportType_individual);
|
||||||
|
Order myOrder = new Order("1");
|
||||||
|
|
||||||
|
myOrder.getOrderLines().add(new OrderLine(1000, drillProduct));
|
||||||
|
myOrder.getOrderLines().add(new OrderLine(1000, screwDriverProduct));
|
||||||
|
myOrder.getOrderLines().add(new OrderLine(35000.0, sandProduct));
|
||||||
|
myOrder.getOrderLines().add(new OrderLine(14000.0, gravelProduct));
|
||||||
|
myOrder.getOrderLines().add(new OrderLine(500, furnitureProduct));
|
||||||
|
request.setOrder(myOrder);
|
||||||
|
long before = System.currentTimeMillis();
|
||||||
|
|
||||||
|
this.insertIntoSession(sessionStatefull, request);
|
||||||
|
sessionStatefull.startProcess("P1");
|
||||||
|
int i = sessionStatefull.fireAllRules();
|
||||||
|
long after = System.currentTimeMillis();
|
||||||
|
System.out.println("NumberRules Executed " + i);
|
||||||
|
System.out.println("Rules executed in " + (after - before) + " ms");
|
||||||
|
Double dd = new Double(i) / (after - before) * 1000;
|
||||||
|
System.out.println("NbreRules/seconde=" + dd);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
15
pom.xml
15
pom.xml
|
|
@ -12,7 +12,9 @@
|
||||||
<modules>
|
<modules>
|
||||||
<module>AccountProject</module>
|
<module>AccountProject</module>
|
||||||
<module>cost-calculation</module>
|
<module>cost-calculation</module>
|
||||||
|
<module>cost-calculation-base</module>
|
||||||
|
<module>cost-calculation-extention</module>
|
||||||
|
<module>cost-calculation-run</module>
|
||||||
</modules>
|
</modules>
|
||||||
<properties>
|
<properties>
|
||||||
|
|
||||||
|
|
@ -54,7 +56,16 @@
|
||||||
|
|
||||||
<dependencyManagement>
|
<dependencyManagement>
|
||||||
<dependencies>
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.pymma-software.droolscourse</groupId>
|
||||||
|
<artifactId>cost-calculation-base</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.pymma-software.droolscourse</groupId>
|
||||||
|
<artifactId>cost-calculation-extension</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>joda-time</groupId>
|
<groupId>joda-time</groupId>
|
||||||
<artifactId>joda-time</artifactId>
|
<artifactId>joda-time</artifactId>
|
||||||
|
|
|
||||||
Loading…
Add table
editor.link_modal.header
Reference in a new issue