/* * Copyright 2015 Red Hat, Inc. and/or its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.drools.scorecards; import org.dmg.pmml.pmml_4_2.descr.Extension; import org.dmg.pmml.pmml_4_2.descr.Output; import org.dmg.pmml.pmml_4_2.descr.OutputField; import org.dmg.pmml.pmml_4_2.descr.PMML; import org.dmg.pmml.pmml_4_2.descr.Scorecard; import org.drools.pmml.pmml_4_2.PMML4Compiler; import org.drools.pmml.pmml_4_2.PMML4Helper; import org.drools.pmml.pmml_4_2.extensions.PMMLExtensionNames; import org.drools.scorecards.example.Applicant; import org.drools.scorecards.pmml.ScorecardPMMLUtils; import org.junit.Assert; import org.junit.Before; import org.junit.Test; import org.kie.api.KieBase; import org.kie.api.KieServices; import org.kie.api.builder.KieBuilder; import org.kie.api.builder.KieFileSystem; import org.kie.api.builder.Results; import org.kie.api.definition.type.FactType; import org.kie.api.runtime.ClassObjectFilter; import org.kie.api.runtime.KieContainer; import org.kie.api.runtime.KieSession; import org.kie.api.io.ResourceType; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.Map; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import static org.drools.scorecards.ScorecardCompiler.DrlType.EXTERNAL_OBJECT_MODEL; public class ExternalObjectModelTest { private static ScorecardCompiler scorecardCompiler; @Before public void setUp() throws Exception { scorecardCompiler = new ScorecardCompiler(EXTERNAL_OBJECT_MODEL); } @Test public void testPMMLCustomOutput() throws Exception { PMML pmmlDocument = null; String drl = null; if (scorecardCompiler.compileFromExcel(PMMLDocumentTest.class.getResourceAsStream("/scoremodel_externalmodel.xls")) ) { pmmlDocument = scorecardCompiler.getPMMLDocument(); assertNotNull( pmmlDocument ); PMML4Compiler.dumpModel( pmmlDocument, System.out ); drl = scorecardCompiler.getDRL(); assertTrue( drl != null && ! drl.isEmpty() ); //System.out.println(drl); } else { fail("failed to parse scoremodel Excel."); } for (Object serializable : pmmlDocument.getAssociationModelsAndBaselineModelsAndClusteringModels()){ if (serializable instanceof Scorecard){ Scorecard scorecard = (Scorecard)serializable; for (Object obj :scorecard.getExtensionsAndCharacteristicsAndMiningSchemas()){ if ( obj instanceof Output) { Output output = (Output)obj; final List<OutputField> outputFields = output.getOutputFields(); assertEquals(1, outputFields.size()); final OutputField outputField = outputFields.get(0); assertNotNull(outputField); assertEquals("totalScore", outputField.getName()); assertEquals("Final Score", outputField.getDisplayName()); assertEquals("double", outputField.getDataType().value()); assertEquals("predictedValue", outputField.getFeature().value()); final Extension extension = ScorecardPMMLUtils.getExtension(outputField.getExtensions(), PMMLExtensionNames.EXTERNAL_CLASS ); assertNotNull(extension); assertEquals("org.drools.scorecards.example.Applicant",extension.getValue()); return; } } } } fail(); } @Test public void testDRLExecution() throws Exception { PMML pmmlDocument = null; String drl = null; if (scorecardCompiler.compileFromExcel(PMMLDocumentTest.class.getResourceAsStream("/scoremodel_externalmodel.xls")) ) { pmmlDocument = scorecardCompiler.getPMMLDocument(); assertNotNull( pmmlDocument ); PMML4Compiler.dumpModel( pmmlDocument, System.out ); drl = scorecardCompiler.getDRL(); assertTrue( drl != null && ! drl.isEmpty() ); //System.out.println(drl); } else { fail("failed to parse scoremodel Excel."); } KieServices ks = KieServices.Factory.get(); KieFileSystem kfs = ks.newKieFileSystem(); kfs.write( ks.getResources().newByteArrayResource( drl.getBytes() ) .setSourcePath( "test_scorecard_rules.drl" ) .setResourceType( ResourceType.DRL ) ); KieBuilder kieBuilder = ks.newKieBuilder( kfs ); Results res = kieBuilder.buildAll().getResults(); System.err.print( res.getMessages() ); KieContainer kieContainer = ks.newKieContainer( kieBuilder.getKieModule().getReleaseId() ); KieBase kbase = kieContainer.getKieBase(); KieSession session = kbase.newKieSession(); Applicant applicant = new Applicant(); applicant.setAge(10); session.insert( applicant ); session.fireAllRules(); session.dispose(); //occupation = 0, age = 30, validLicence -1 assertEquals(29.0,applicant.getTotalScore(), 0.0); session = kbase.newKieSession(); applicant = new Applicant(); applicant.setOccupation("SKYDIVER"); applicant.setAge(0); session.insert( applicant ); session.fireAllRules(); session.dispose(); //occupation = -10, age = +10, validLicense = -1; assertEquals(-1.0, applicant.getTotalScore(), 0.0); session = kbase.newKieSession(); applicant = new Applicant(); applicant.setResidenceState("AP"); applicant.setOccupation("TEACHER"); applicant.setAge(20); applicant.setValidLicense(true); session.insert( applicant ); session.fireAllRules(); session.dispose(); //occupation = +10, age = +40, state = -10, validLicense = 1 assertEquals(41.0,applicant.getTotalScore(), 0.0); } @Test public void testWithInitialScore() throws Exception { ScorecardCompiler scorecardCompiler2 = new ScorecardCompiler(EXTERNAL_OBJECT_MODEL); PMML pmmlDocument2 = null; String drl2 = null; if ( scorecardCompiler2.compileFromExcel( PMMLDocumentTest.class.getResourceAsStream("/scoremodel_externalmodel.xls" ), "scorecards_initialscore" ) ) { pmmlDocument2 = scorecardCompiler2.getPMMLDocument(); assertNotNull(pmmlDocument2); drl2 = scorecardCompiler2.getDRL(); PMML4Compiler.dumpModel( pmmlDocument2, System.out ); } else { fail("failed to parse scoremodel Excel."); } assertNotNull( pmmlDocument2 ); assertTrue( drl2 != null && ! drl2.isEmpty() ); KieServices ks = KieServices.Factory.get(); KieFileSystem kfs = ks.newKieFileSystem(); kfs.write( ks.getResources().newByteArrayResource( drl2.getBytes() ) .setSourcePath( "test_scorecard_rules.drl" ) .setResourceType( ResourceType.DRL ) ); KieBuilder kieBuilder = ks.newKieBuilder( kfs ); Results res = kieBuilder.buildAll().getResults(); System.err.println( res.getMessages() ); KieContainer kieContainer = ks.newKieContainer( kieBuilder.getKieModule().getReleaseId() ); KieBase kbase = kieContainer.getKieBase(); KieSession session = kbase.newKieSession(); Applicant applicant = new Applicant(); applicant.setAge(10); session.insert(applicant); //session.addEventListener(new DebugWorkingMemoryEventListener()); session.fireAllRules(); session.dispose(); //occupation = 0, age = 30, validLicence -1, initialScore=100 assertEquals(129.0,applicant.getTotalScore(), 0.0); session = kbase.newKieSession(); applicant = new Applicant(); applicant.setOccupation("SKYDIVER"); applicant.setAge(0); session.insert( applicant ); session.fireAllRules(); session.dispose(); //occupation = -10, age = +10, validLicense = -1, initialScore=100; assertEquals(99.0, applicant.getTotalScore(), 0.0); session = kbase.newKieSession(); applicant = new Applicant(); applicant.setResidenceState("AP"); applicant.setOccupation("TEACHER"); applicant.setAge(20); applicant.setValidLicense(true); session.insert( applicant ); session.fireAllRules(); session.dispose(); //occupation = +10, age = +40, state = -10, validLicense = 1, initialScore=100 assertEquals(141.0,applicant.getTotalScore(), 0.0); } @Test public void testWithReasonCodes() throws Exception { ScorecardCompiler scorecardCompiler2 = new ScorecardCompiler(EXTERNAL_OBJECT_MODEL); PMML pmmlDocument2 = null; String drl2 = null; if (scorecardCompiler2.compileFromExcel(PMMLDocumentTest.class.getResourceAsStream("/scoremodel_externalmodel.xls"), "scorecards_reasoncode") ) { pmmlDocument2 = scorecardCompiler2.getPMMLDocument(); PMML4Compiler.dumpModel( pmmlDocument2, System.out ); assertNotNull( pmmlDocument2 ); drl2 = scorecardCompiler2.getDRL(); //System.out.println(drl2); } else { for (ScorecardError error : scorecardCompiler2.getScorecardParseErrors()){ System.out.println(error.getErrorLocation()+":"+error.getErrorMessage()); } fail("failed to parse scoremodel Excel (scorecards_reasoncode)."); } assertNotNull( pmmlDocument2 ); assertTrue( drl2 != null && ! drl2.isEmpty() ); KieServices ks = KieServices.Factory.get(); KieFileSystem kfs = ks.newKieFileSystem(); kfs.write( ks.getResources().newByteArrayResource( drl2.getBytes() ) .setSourcePath( "test_scorecard_rules.drl" ) .setResourceType( ResourceType.DRL ) ); KieBuilder kieBuilder = ks.newKieBuilder( kfs ); Results res = kieBuilder.buildAll().getResults(); KieContainer kieContainer = ks.newKieContainer( kieBuilder.getKieModule().getReleaseId() ); KieBase kbase = kieContainer.getKieBase(); KieSession session = kbase.newKieSession(); FactType scorecardInternalsType = kbase.getFactType( PMML4Helper.pmmlDefaultPackageName(),"ScoreCard" ); Applicant applicant = new Applicant(); applicant.setAge(10); session.insert(applicant); //session.addEventListener(new DebugWorkingMemoryEventListener()); session.fireAllRules(); //occupation = 0, age = 30, validLicence -1, initialScore=100 assertEquals( 129.0,applicant.getTotalScore(), 0.0 ); assertEquals( "VL0099", applicant.getReasonCodes() ); Object scorecardInternals = session.getObjects( new ClassObjectFilter( scorecardInternalsType.getFactClass() ) ).iterator().next(); Assert.assertEquals( 129.0, scorecardInternalsType.get( scorecardInternals, "score" ) ); Map reasonCodesMap = (Map) scorecardInternalsType.get( scorecardInternals, "ranking" ); Assert.assertNotNull( reasonCodesMap ); Assert.assertEquals( Arrays.asList( "VL0099", "AGE02" ), new ArrayList( reasonCodesMap.keySet() ) ); session.dispose(); session = kbase.newKieSession(); applicant = new Applicant(); applicant.setOccupation("SKYDIVER"); applicant.setAge(0); session.insert( applicant ); session.fireAllRules(); session.dispose(); //occupation = -10, age = +10, validLicense = -1, initialScore=100; assertEquals(99.0, applicant.getTotalScore(), 0.0); session = kbase.newKieSession(); applicant = new Applicant(); applicant.setResidenceState("AP"); applicant.setOccupation("TEACHER"); applicant.setAge(20); applicant.setValidLicense(true); session.insert( applicant ); session.fireAllRules(); session.dispose(); //occupation = +10, age = +40, state = -10, validLicense = 1, initialScore=100 assertEquals(141.0,applicant.getTotalScore(), 0.0); } }