Optaplanner passing a variable through planning solution - solution

I have a planning entity Request and a planning variable as taxi.
I want to pass the Date(a particular day) to the drools file for cab allocation.
I tried adding Date to the planning solution but the rule always failed where i captured the Date.
Planning Solution
#PlanningSolution
public class NRequest extends AbstractPersistable implements Solution<HardMediumSoftScore> {
private Date date;
private List<Cabs> list_cabs;
#PlanningEntityCollectionProperty
private List<Requests> list_req;
.....
.....
}
Drools file
rule "Check overlap Shift1"
when
$date:Date()
then
scoreHolder.addHardConstraintMatch(kcontext, 3);
scoreHolder.addSoftConstraintMatch(kcontext, 2);
end

I'd suggest the NurseRosteringParametrization appoach.
The FooSolution class has a single FooParameterization class, which holds things like the date or the planning window starting date or the specific score weights etc. Then simply match on FooParameterization in your drools rules (you know there is only 1 instance) and that's it. Make sure that FooParameterization is part getProblemFacts() or #ProblemFactProperty

Related

Hibernate Search: Find in list of intervals

I am using Hibernate Search 6.x within my Spring Boot application. I got an indexed entity with a set of date intervals.
#Indexed
public class ProudParent {
...
#IndexedEmbedded(includePaths = {"start", "end"})
Set<DateInterval> parentalLeaves;
}
And the class DateInterval looks like
#Embeddable
public class DateInterval {
#GenericField
LocalDate start;
#GenericField
LocalDate end;
}
That is my range query to search for all proud parents which were in parental leave on a specific date:
bool.must(factory.range().field("parentalLeaves.start").lessThan(date));
bool.must(factory.range().field("parentalLeaves.end").greaterThan(date));
Now the problem is that it finds proud parents which first parental leave was before date and the last parental leave was after date. So it does not search in the "same" date interval.
Can someone give me a hint of what I'm doing wrong?
Regards, Rokko
#IndexedEmbedded will "flatten" the object structure by default, so all starts and ends are mixed together in the index, with no way to know which end matches which start.
You can read more about this in this section of the reference documentation. In short, this default is mainly for performance, because preserving the object structure can be (very) costly on large indexes, and is usually not necessary.
The solution, in your case, would be to use a NESTED structure:
#Indexed
public class ProudParent {
...
#IndexedEmbedded(includePaths = {"start", "end"}, structure = ObjectStructure.NESTED)
Set<DateInterval> parentalLeaves;
}
Then make sure to tell Hibernate Search you want the matches on start and end to be on the same parentalLeave, using a nested predicate:
bool.must(factory.nested().objectField("parentalLeaves")
.nest(factory.bool()
.must(factory.range()
.field("parentalLeaves.start")
.lessThan(date))
.must(factory.range()
.field("parentalLeaves.end")
.greaterThan(date)))
Don't forget to reindex your data before testing.
Side note: the syntax should be slightly more convenient with the upcoming Hibernate Search 6.2.0.Alpha2 (not yet released):
bool.must(factory.nested("parentalLeaves")
.add(factory.range()
.field("parentalLeaves.start")
.lessThan(date))
.add(factory.range()
.field("parentalLeaves.end")
.greaterThan(date)))
Other side note: hopefully one day we'll have date ranges as a primitive type in Hibernate Search (HSEARCH-4199) and this whole discussion will become irrelevant :)

How to get available classes at runtime

I would like to poll a class and have it return all available subclasses in a way I can then address them. It can return an array, a dictionary, or something else. As long as I can then loop through the set of them and read properties or call functions from each.
Scenario:
I want to create a form where the user inputs the details of a series of events. Then I read the form and output a report. Each kind of event has a ".Name", but a different set of inputs (FormOptions) and methods (FormatOutput) to create an output. Right now this is implemented with a complex form and a script that runs after the user submits the form.
The trouble is that every time I add an option to the form, I have to change code in several different places. In the interest of making my code easier to maintain, I would like to contain all the code for each event type in a Class, then build the form based on the available Classes.
So as an example, I'm building an itinerary from a collection of Meeting and Travel objects:
Class Itinerary
Class Event
Public Property Get Name()
Name = "Meeting"
End Property
Public Function FormOptions(id)
Form Options = "<div id="& id &">form code for Meeting options</div>"
End Function
Public Sub FormatOutput(Time, Title, Location)
'Make a fancy meeting entry
End Sub
End Class
Class Travel
Public Property Get Name()
Name = "Travel"
End Property
Public Function FormOptions(id)
Form Options = "<div id="& id &">form code for Travel options</div>"
End Function
Public Sub FormatOutput(StartTime, EndTime, Origin, Destination)
'Make a fancy travel entry
End Sub
End Class
End Class
When the script runs it creates a form where the user can add a series of events. Each time the user chooses between "Meeting" and "Travel" then fills out the options for that event type. At the end, they push a button and the script makes a pretty document listing all the user's inputs.
At some point in the future, I will want to add a new kind of event: lodging.
Class Lodging
Public Property Get Name()
Name = "Lodging"
End Property
Public Function FormOptions(id)
Form Options = "<div id="& id &">form code for Lodging options</div>"
End Function
Public Sub FormatOutput(Date, Location)
'Make a fancy Lodging entry
End Sub
End Class
How do I setup my Itinerary class so that it automatically recognizes the new class and can return it as an available event type? I can think of several ways of doing this, but they all involve keeping an index of the available classes separate from the actual classes, and I'm trying to minimize the number of places I have to change code when I add new event types.
I am very purposely not including any details on how I build the form since at this point I'm open to anything. Also, please be gentle with references to "inheritance", "extensibility", or "polymorphism". I'm a just a scripter and these OOP concepts are still a bit foreign to me.
I don't think this is possible, but one way to come close to this would be to have a unique list of class names -- the simplest would be to have a global dictionary.
You can get a list of classes by reading the Keys collection of the dictionary.
I don't think VBScript supports references to classes, so when the user chooses one of the types use Eval to create an instance of the appropriate class.
Dim ClassList
Set ClassList = CreateObject("Scripting.Dictionary")
'on type selection:
Function GetItineraryInstance(className)
Set GetItineraryInstance = Eval("New " & className)
End Function
ClassList("Travel") = 1
Class Travel
'methods
End Class
At least the class registration can be kept together with the class definition.

AspectJ Used to profile query execution making aplicaiont too slow

I am using AspecJ to capture the query being executed in each of the form and show the time each query takes to execute. We are using spring jdbc and my aspect look as below:
#Aspect
public class QueryProfilerAspect {
#Pointcut("call(* org.springframework.jdbc.core.simple.SimpleJdbcTemplate.query* (..))")
public void profileQuery() {
}
#Around("profileQuery()")
public Object profile(ProceedingJoinPoint thisJoinPoint) throws Throwable {
// System.out.println("Inside join point execution");
SimpleJdbcTemplate template = (SimpleJdbcTemplate) thisJoinPoint
.getTarget();
JdbcTemplate jdbcTemplate = (JdbcTemplate) template
.getNamedParameterJdbcOperations().getJdbcOperations();
DataSource ds = jdbcTemplate.getDataSource();
// System.out.println("Datasource name URL =="
// + ds.getConnection().getMetaData().getURL());
// System.out.println("Datasource name ==" + schemaName);
String sqlQuery = thisJoinPoint.getArgs()[0].toString();
final long start, end;
start = System.nanoTime();
Object ll = thisJoinPoint.proceed();
end = System.nanoTime();
long executionTime = ((end - start) / 1000) / 1000;
System.out.println("execution_time=" +executionTime + sqlquery="+sqlQuery );
return ll;
}
Functionality wise this works however if i put this i my application it makes the application too slow. I am using compile time weaving. And the aspect finds 1683 query* method calls within the application.
Is there anything I can do to optimize this. Any suggestion/help will be really appreciated.
First I would advice against using System.nanoTime(). It's precision using cold like that is atrocious and pretty much useless for measuring timespans. Certainly not better than System.currentTimeMillies() if you divide the result anyway.
What probably slows you down most though, are the the String operations performed at various places in your aspect. If you have to concatenate Strings, at least use a StringBuilder to do so before outputting it. That might be done by the optimizer already, but you can never be too sure. ;)
And... Sysout isn't exactly the way to go if you want logging - looking into one of the various logging implementations (slf4j with logback is my personal favourite, but there are others as well) will be worth your time.
Especially if you want to use the fact that Spring has the feature you are trying to build (, as asked and answered here before: Seeing the underlying SQL in the Spring JdbcTemplate?
(Edit: I know it's only the query, not the time measuring, but not having to worry about that should shave some time off your overhead as well.)

How to use drools to fit complex condition?

Recently I am leaning drools,I think it is a great software.Drools‘s core idea is drl file.We should write the rule file,For example:
rule "name"
when
then
end
And the when section depend on the entity's property.For example:Now I have a User class which is ready to use in my rule.
public class User {
private int money;
private Date time;
//getter and setter.....
}
Now I need to know a user's money between 2012-09-11 and 2013-01-01,and if his money>100 then do my logic,How drools do?
That could be easily been achieved using the following rule:
rule 'Some Rule'
$u: User( time > '11-sep-2009', time < '01-jan-2013', money > 100)
then
//do your logic here. $u references the User object
end
Hope it helps,
You can write a function in DRL file which will return true if user's money between 2012-09-11 and 2013-01-01 is greater than 100. You can call this function from when part of your rule using eval and write your logic in then part.Writing functions is not good idea in DRL files though!

How to implement scheduler in Apex?

I see scheduler like feature in salesforce but it is somewhat tied with existing features that salesforce provide and no sample source code is provided as far as my research goes.
What I want to do is to create my own scheduler that sends simple email based on date.
Goal:
Custom Object Player has fields
startDate : date like '2010-11-01'
email : text field like foo#bar.com
name : player's name like John.
If today's date is one day before the startDate, I want to send email to the Player.
For instance, Player's name is John and if today is 2010-12-10 and one Player's startDate is set to 2010-12-11, email saying "hello John" is sent.
Unfortunately I cannot find good example or tutorial online or salesforce doc how to do this using Apex.
Could anyone point out where to get started?
UPDATE
I want to extend the answer from eyescream.
After setting scheduler, you can set what follow up action to take like sending email using template or set custom object fields to some values.
Below I found useful for people using email template in Visualforce format.
I have custom object 'alertTester' which has reference to other object 'custom' and even this object 'custom' has reference to another object 'custom1GrandChild' and all the relationship (up to 3 or 5 layers I think) can be accessed like below.
I've tested below and works fine. Now I'm receiving email with my condition set :)
<messaging:emailTemplate subject="Hello" recipientType="User" relatedToType="alertTester__c" >
<messaging:plainTextEmailBody >
{!relatedTo.name}
{!relatedTo.custom__r.name}
{!relatedTo.custom__r.custom1GrandChild__r.name}
</messaging:plainTextEmailBody>
</messaging:emailTemplate>
Check out solutions that don't involve code before you'll dive deeply to Apex...
Email Alert + Workflow Rule should provide you with all functionality you need in this scenario and involve just clicking without any code.
I'm answering to my own question again..
Below link, search for schedule
http://www.salesforce.com/us/developer/docs/apexcode/index.htm
Looks like Apex has Schedulable interface that I can implements and set up cron task.
Below is sample code provided in the doc:
global class TestScheduledApexFromTestMethod implements Schedulable {
// This test runs a scheduled job at midnight Sept. 3rd. 2022
public static String CRON_EXP = '0 0 0 3 9 ? 2022';
global void execute(SchedulableContext ctx) {
CronTrigger ct = [SELECT id, CronExpression, TimesTriggered, NextFireTime
FROM CronTrigger WHERE id = :ctx.getTriggerId()];
System.assertEquals(CRON_EXP, ct.CronExpression);
System.assertEquals(0, ct.TimesTriggered);
System.assertEquals('2022-09-03 00:00:00', String.valueOf(ct.NextFireTime));
Account a = [SELECT id, name FROM Account WHERE name =
'testScheduledApexFromTestMethod'];
a.name = 'testScheduledApexFromTestMethodUpdated';
update a;
}
}