从配置文件执行数学表达式

时间:2011-08-20 15:14:04

标签: java configuration eval

我正在帮助一个朋友在Java上使用rpg mod,我们基本上想让服务器的管理员有机会提供他/她自己的公式来计算某些事件的结果。

例如,现在我们有一个事件发生在1%的时间,并且每个角色的几率增加1%。我们如何才能使服务器管理员能够根据返回该事件发生机会的角色级别指定一个函数?

有没有办法安全地做到这一点,因为Java没有直接的lambda支持?可能无需编写解析字符串并执行函数的tokenizer?

在php中我可能会使用eval来做这样的事情(一旦我清理了输入)但是在Java中我很难过。

4 个答案:

答案 0 :(得分:2)

为什么不使用一些脚本语言,比如Groovy,它可以非常nicely integrate使用Java(您可以从Java传递参数并将结果返回给Java)。然后你不必编写自己的解析器,如果需要的话,也可以超越简单的数学公式。 (请注意,另一方面,您可能必须限制使用Groovy,以防止出现某些安全问题,例如,请参阅here如何执行此操作。)

答案 1 :(得分:0)

也许你应该只允许某种函数,即a x n 的总和,其中x是水平之后,你可以将它存储为成对的数组a,n

我认为你不会使用像罪这样的东西。通常它会像ax+b

答案 2 :(得分:0)

如果你需要评估的表达式仅限于相对简单的算术,可能是一些字符串操作和对象属性访问器/方法调用,那么我会考虑使用一个现成的表达式语言库并查看它们是否足够,例如MVELOGNL

否则,正如其他人所指出的那样,如果您需要更复杂的行为,请考虑使用Groovy或JRuby等完整的脚本语言。

答案 3 :(得分:0)

如果您想避免像Groovy这样的脚本语言,那么您可能需要考虑使用允许您指定 name = list-of-values 的配置语法。我们假设语法是:

name = [ "list", "of", "values" ];

使用这样的语法,您可以指定值的,以提供从字符级别到事件发生概率的映射。如果字符级别从1到10并且默认概率镜像字符级别,则配置文件中的条目将为:

level_to_probability_mapping = [
    # character level  -->  probability
    #----------------------------------
      "1",                  "1",
      "2",                  "2",
      "3",                  "3",
      "4",                  "4",
      "5",                  "5",
      "6",                  "6",
      "7",                  "7",
      "8",                  "8",
      "9",                  "9",
      "10",                 "10",
];

如果您的配置文件语法仅支持 name = single-value 语法,则可以通过将值设置为a来模拟 name = list-of-values 包含以逗号分隔的项目的字符串,然后使用java.util.StringTokenizerString.split()分解字符串以访问各个项目。

一种更灵活但更危险的不同方法,因为它允许一个人执行任意代码,如下所示......

第1步。定义定义一个方法的Java接口(或抽象基类)。例如:

interface ProbabilityCalculator {
    public int calculateProbabilityForLevel(int level);
}

第2步。编写一个使用简单算法实现该接口的“默认”类。

第3步。允许管理员编写自己的实现上述接口的类,并将包含该类的jar文件添加到应用程序的CLASSPATH

第4步。在配置文件中有一个变量,指定实现上述接口的类的名称。如果配置文件中不存在此变量,则返回使用默认实现类的名称。

第5步。使用Java的反射API创建配置文件中指定的类的实例,然后调用其calculateProbabilityForLevel()方法。

如果您还不熟悉Java反射,那么请查看我的Java Reflection Explained Simply演示文稿,了解您需要了解的内容。