2018-09-02 13:36:49 +02:00
package it.cavallium.warppi.math.rules ;
2017-12-21 23:21:29 +01:00
2019-08-09 20:51:31 +02:00
import it.cavallium.warppi.Platform ;
2018-09-12 22:16:33 +02:00
import it.cavallium.warppi.Platform.ConsoleUtils ;
2019-11-16 01:32:47 +01:00
import it.cavallium.warppi.WarpPI ;
2018-09-02 13:36:49 +02:00
import it.cavallium.warppi.math.Function ;
import it.cavallium.warppi.math.MathContext ;
import it.cavallium.warppi.math.functions.Expression ;
import it.cavallium.warppi.math.functions.Variable ;
import it.cavallium.warppi.math.functions.Variable.V_TYPE ;
2019-01-30 21:42:35 +01:00
import it.cavallium.warppi.math.rules.dsl.DslAggregateException ;
2019-01-28 18:19:27 +01:00
import it.cavallium.warppi.math.rules.dsl.RulesDsl ;
2019-08-06 19:01:00 +02:00
import it.cavallium.warppi.math.rules.dsl.errorutils.DslFilesException ;
2019-02-10 19:59:38 +01:00
import it.cavallium.warppi.math.rules.functions.* ;
2018-09-02 13:36:49 +02:00
import it.cavallium.warppi.math.solver.MathSolver ;
2018-09-12 22:16:33 +02:00
import it.cavallium.warppi.util.Error ;
2017-12-21 23:21:29 +01:00
import it.unimi.dsi.fastutil.objects.ObjectArrayList ;
2019-08-09 20:51:31 +02:00
import java.io.IOException ;
import java.io.InputStream ;
import java.util.stream.Stream ;
2017-12-21 23:21:29 +01:00
public class RulesManager {
2018-05-12 21:18:29 +02:00
2017-12-21 23:21:29 +01:00
public static ObjectArrayList < Rule > [ ] rules ;
2018-05-12 21:18:29 +02:00
2019-11-16 01:32:47 +01:00
private RulesManager ( ) {
}
2017-12-21 23:21:29 +01:00
2019-11-16 01:32:47 +01:00
@SuppressWarnings ( { " unchecked " } )
2017-12-21 23:21:29 +01:00
public static void initialize ( ) {
2019-02-27 23:29:03 +01:00
WarpPI . getPlatform ( ) . getConsoleUtils ( ) . out ( ) . println ( ConsoleUtils . OUTPUTLEVEL_NODEBUG , " RulesManager " , " Loading the rules " ) ;
2018-09-22 11:17:30 +02:00
RulesManager . rules = new ObjectArrayList [ RuleType . values ( ) . length ] ;
2018-09-28 11:39:28 +02:00
for ( final RuleType val : RuleType . values ( ) ) {
2018-09-22 11:17:30 +02:00
RulesManager . rules [ val . ordinal ( ) ] = new ObjectArrayList < > ( ) ;
2018-09-28 11:39:28 +02:00
}
2019-01-28 18:19:27 +01:00
2019-02-10 19:59:38 +01:00
loadBuiltinRules ( ) ;
2019-08-09 20:51:31 +02:00
try {
loadDslRules ( ) ;
} catch ( IOException | DslFilesException e ) {
e . printStackTrace ( ) ;
if ( e instanceof DslFilesException ) {
2019-08-12 13:50:18 +02:00
System . err . println ( ) ;
2019-08-09 20:51:31 +02:00
System . err . print ( ( ( DslFilesException ) e ) . format ( ) ) ;
2018-09-28 11:39:28 +02:00
}
2019-11-01 18:04:01 +01:00
WarpPI . getPlatform ( ) . exit ( 1 ) ;
2017-12-21 23:21:29 +01:00
}
}
2018-05-12 21:18:29 +02:00
2019-02-10 19:59:38 +01:00
private static void loadBuiltinRules ( ) {
Stream . of (
2019-11-16 01:32:47 +01:00
new DivisionRule ( ) ,
new EmptyNumberRule ( ) ,
new ExpressionRule ( ) ,
new JokeRule ( ) ,
new MultiplicationRule ( ) ,
new NegativeRule ( ) ,
new NumberRule ( ) ,
new PowerRule ( ) ,
new RootRule ( ) ,
new RootSquareRule ( ) ,
new SubtractionRule ( ) ,
new SumRule ( ) ,
new SumSubtractionRule ( ) ,
new VariableRule ( )
2019-02-10 19:59:38 +01:00
) . forEach ( RulesManager : : addRule ) ;
}
2019-08-06 19:01:00 +02:00
private static void loadDslRules ( ) throws IOException , DslFilesException {
2019-11-01 18:04:01 +01:00
final Platform platform = WarpPI . getPlatform ( ) ;
2019-01-28 18:19:27 +01:00
2019-08-06 19:01:00 +02:00
final DslFilesException fileErrors = new DslFilesException ( ) ;
2019-08-09 20:51:31 +02:00
for ( final String path : platform . getRuleFilePaths ( ) ) {
platform . getConsoleUtils ( ) . out ( ) . println (
2019-11-16 01:32:47 +01:00
ConsoleUtils . OUTPUTLEVEL_NODEBUG ,
" RulesManager " ,
" Found DSL rules file: " + path
2019-01-28 18:19:27 +01:00
) ;
final String source ;
2019-08-09 20:51:31 +02:00
try ( final InputStream resource = platform . getStorageUtils ( ) . getResourceStream ( path ) ) {
source = platform . getStorageUtils ( ) . read ( resource ) ;
2019-01-28 18:19:27 +01:00
}
2019-08-06 19:01:00 +02:00
try {
2019-08-09 20:51:31 +02:00
// This loop used to be written as RulesDsl.makeRules(source).forEach(RulesManager::addRule),
// but the forEach method hangs on TeaVM.
for ( Rule rule : RulesDsl . makeRules ( source ) ) {
addRule ( rule ) ;
}
2019-08-06 19:01:00 +02:00
} catch ( DslAggregateException e ) {
2019-08-09 20:51:31 +02:00
fileErrors . addFileErrors ( path , source , e . getErrors ( ) ) ;
2019-08-06 19:01:00 +02:00
}
}
if ( fileErrors . hasErrors ( ) ) {
throw fileErrors ;
2019-01-28 18:19:27 +01:00
}
}
2018-03-25 12:36:22 +02:00
public static void warmUp ( ) throws Error , InterruptedException {
2017-12-23 15:20:42 +01:00
ObjectArrayList < Function > uselessResult = null ;
2018-02-05 00:05:31 +01:00
boolean uselessVariable = false ;
2018-05-12 21:18:29 +02:00
for ( final RuleType val : RuleType . values ( ) ) {
2018-09-22 11:17:30 +02:00
final ObjectArrayList < Rule > ruleList = RulesManager . rules [ val . ordinal ( ) ] ;
2017-12-23 15:20:42 +01:00
for ( final Rule rule : ruleList ) {
2018-02-05 00:05:31 +01:00
String ruleName = " <null> " ;
try {
ruleName = rule . getRuleName ( ) ;
2018-09-22 11:17:30 +02:00
final ObjectArrayList < Function > uselessResult2 = rule . execute ( RulesManager . generateUselessExpression ( ) ) ;
2018-02-05 00:05:31 +01:00
uselessVariable = ( uselessResult = = null ? new ObjectArrayList < > ( ) : uselessResult ) . equals ( uselessResult2 ) ;
uselessResult = uselessResult2 ;
2018-05-12 21:18:29 +02:00
} catch ( final Exception e ) {
2018-02-05 00:05:31 +01:00
if ( uselessVariable | | true ) {
System . err . println ( " Exception thrown by rule ' " + ruleName + " '! " ) ;
e . printStackTrace ( ) ;
}
}
2017-12-23 15:20:42 +01:00
}
}
try {
2018-09-22 11:17:30 +02:00
new MathSolver ( RulesManager . generateUselessExpression ( ) ) . solveAllSteps ( ) ;
2017-12-23 15:20:42 +01:00
} catch ( InterruptedException | Error e ) {
e . printStackTrace ( ) ;
}
}
2018-05-12 21:18:29 +02:00
2017-12-24 11:59:09 +01:00
private static Function generateUselessExpression ( ) {
2018-05-12 21:18:29 +02:00
final MathContext mc = new MathContext ( ) ;
2017-12-24 11:59:09 +01:00
Function expr = new Expression ( mc ) ;
expr = expr . setParameter ( 0 , new Variable ( mc , 'x' , V_TYPE . VARIABLE ) ) ;
2017-12-23 15:20:42 +01:00
return expr ;
}
2018-05-12 21:18:29 +02:00
2018-09-22 11:17:30 +02:00
public static void addRule ( final Rule rule ) {
RulesManager . rules [ rule . getRuleType ( ) . ordinal ( ) ] . add ( rule ) ;
2019-02-27 23:29:03 +01:00
WarpPI . getPlatform ( ) . getConsoleUtils ( ) . out ( ) . println ( ConsoleUtils . OUTPUTLEVEL_DEBUG_MIN , " RulesManager " , rule . getRuleName ( ) , " Loaded as " + rule . getRuleType ( ) + " rule " ) ;
2017-12-21 23:21:29 +01:00
}
}