[*] ContractCode (код из словаря)
[*] Персональные данные клиента (например, возраст, адрес)
[*] страховая сумма (Si)
[*]. Использование этого формулы :
Код: Выделить всё
premium := SI * px * (1 + py) / pz
- px фактор параметризуется в файле Excel, а зависит от 2 свойств (возраст клиента и пол)
- py strong> in -in five in in in in in in file in in in in file in in in in in piefize на 4 свойства контракта < /li>
pz < /strong> - аналогично < /li>
< /ul>
Требования < /h2>
r1 < /strong> - Java. Формула [/b], - r2 - код Java ничего не знает о зависимости от формулы , другими словами, что премия зависит от: px, py, pz,
- r3 - код Java. В возрасте и полу клиента и т. Д. /> У меня есть модель домена контракта < /strong>, которая состоит из контракта классов, продукта, клиента, политики и так далее. Класс контракта определяется как: < /p>
Кроме того, я ввел var класс, который является контейнером для any параметризованная переменная:
Код: Выделить всё
public class Contract { String code; // contractCode double sumInsured; // SI String clientSex; // M, F int professionCode; // code from dictionary int policyYear; // 1..5 int clientAge; // ... // etc.и, наконец, - запрос class:Код: Выделить всё
public class Var { public final String name; public final ContractPremiumRequest request; private double value; // calculated value private boolean ready; // true if value is calculated public Var(String name, ContractPremiumRequest request) { this.name = name; this.request = request; } ... public void setReady(boolean ready) { this.ready = ready; request.check(); } ... // getters, setters }Теперь я могу использовать эти классы с таким потоком:Код: Выделить всё
public class ContractPremiumRequest { public static enum State { INIT, IN_PROGRESS, READY } public final Contract contract; private State state = State.INIT; // all dependencies (parameterized factors, e.g. px, py, ...) private Map varMap = new TreeMap(); // calculated response - premium value private BigDecimal value; public ContractPremiumRequest(Contract contract) { this.contract = contract; } // true if *all* vars are ready private boolean _isReady() { for (Var var : varMap.values()) { if (!var.isReady()) { return false; } } return true; } // check if should modify state public void check() { if (_isReady()) { setState(State.READY); } } // read number from var with given [name] public double getVar(String name) { return varMap.get(name).getValue(); } // adding uncalculated factor to this request – makes request IN_PROGRESS public Var addVar(String name) { Var var = new Var(name, this); varMap.put(name, var); setState(State.IN_PROGRESS); return var; } ... // getters, setters }- Создает var ("px") с ready == false
Код: Выделить всё
request = new ContractPremiumRequest(contract)< /code> Создает запрос со состоянием == init < /code> < /li> < /ul> < /li> px = request.addVar( "px" ) - Перемещает запрос на утверждение == in_progress
Код: Выделить всё
py = request.addVar( "py" )- , px.setready (true)
Код: Выделить всё
px.setValue( factor )- Установите рассчитанное значение на px
- Подготавливание == true
wation == ready если все var готовыКод: Выделить всё
request.check() - Теперь мы можем использовать формулу, так как запрос имеет все зависимости
rule1 - contract_premium_prepare.drl:
Код: Выделить всё
rule "contract premium request - prepare dependencies"
when
$req : ContractPremiumRequest (state == ContractPremiumRequest.State.INIT)
then
insert( $req.addVar("px") );
insert( $req.addVar("py") );
insert( $req.addVar("pz") );
$req.setState(ContractPremiumRequest.State.IN_PROGRESS);
end
Код: Выделить всё
rule "contract premium request - calculate premium"
when
$req : ContractPremiumRequest (state == ContractPremiumRequest.State.READY)
then
double px = $req.getVar("px");
double py = $req.getVar("py");
double pz = $req.getVar("pz");
double si = $req.contract.getSumInsured();
// use formula to calculate premium
double premium = si * px * (1 + py) / pz;
// round to 2 digits
$req.setValue(premium);
end
таблица решений. py.xls:
kiecontainer создается один раз на старте: p> p> p> p> p> p> p> p> p> p> p> p> p> p> p> p> pslious p> p> pless> p> pless>
kiecontainer.
Код: Выделить всё
dtconf = KnowledgeBuilderFactory.newDecisionTableConfiguration();
dtconf.setInputType(DecisionTableInputType.XLS);
KieServices ks = KieServices.Factory.get();
KieContainer kc = ks.getKieClasspathContainer();
Код: Выделить всё
ContractPremiumRequest request = new ContractPremiumRequest(contract); // state == INIT
kc.newStatelessKieSession("session-rules").execute(request);
BigDecimal premium = request.getValue();
- Правило 1 для ContractPremiumRequest [init]
- Это правило создает и добавляет PX и PZ -зависимости (PR и PZ (PR и PZ (PR и PZ (PR и PZ (PZ и PZ (PZ и PZ (PR и PZ (Li>
.objects)Код: Выделить всё
Var - proper excel row fires for each px, py, pz object and makes it ready
- Rule2 fires for ContractPremiumRequest[READY] and use formula
- Таблица решений PX имеет ~ 100 Rows,
- Таблица решений Py имеет ~ 8000 rows,
- pz. />
мои результаты < /h2>
Первый расчет, который загружает и инициализирует таблицы решений, требует ~ 45 секунд < /strong> - это может стать проблематичным. < /p>
< /li>
. acceptable for our team. - Heap consumption is ~150 MB – which is problematic as we expect much more big tables will be used.
Я использую Drools неправильным способом? < /li>
Как удовлетворить требования более эффективным образом? ==========
Это короткое резюме через 2 года.
Наша система очень сильно выросла, как мы и ожидали. Мы закончили более 500 таблицами (или матрицами) с страховыми ценами, актуарными коэффициентами, конфигурациями покрытия и т. Д.
Некоторые таблицы имеют размер более 1 миллиона строк. Мы использовали слюни, но мы не могли справиться с проблемами производительности.
Наконец, мы использовали higson Engine (http://higson.io) - прежнее название было гипероном. пересчете на каждом событии Keytype на полях UI. Code.
Application просто продолжает работать с новой логикой, не требуется разработка или перезапуск. src = "https://i.sstatic.net/u43p6.png"/>
Подробнее здесь: https://stackoverflow.com/questions/392 ... ion-tables