Выполнение математического выражения из файла конфигурации - PullRequest
0 голосов
/ 20 августа 2011

Я помогаю другу поработать над модом RPG на Java, мы в основном хотим дать администраторам сервера возможность предоставить свои собственные формулы для расчета результатов некоторых событий.

Например, сейчас у нас есть событие, которое происходит в 1% случаев, и шанс увеличивается на 1% на каждом уровне персонажа.Как мы можем сделать так, чтобы администратор сервера мог определить функцию, основанную на уровне символов, которая возвращает вероятность того, что это событие произойдет?

Есть ли способ сделать это безопасно, поскольку в Java нетпрямая лямбда-поддержка?Возможно, без необходимости писать токенизатор, который анализирует строку и выполняет функцию?

В php я мог бы использовать eval для таких действий (как только я очистил ввод), но в Java я в тупике.*

Ответы [ 4 ]

2 голосов
/ 20 августа 2011

Почему бы не использовать некоторый язык сценариев, такой как Groovy, который может очень хорошо интегрировать с Java (вы можете передавать параметры из Java и получать результат обратно в Java). Тогда вам не нужно писать собственный синтаксический анализатор, и вы можете выйти за рамки простых математических формул, если возникнет такая необходимость. (Помните, что, с другой стороны, вам может потребоваться ограничить использование Groovy, чтобы предотвратить некоторые проблемы с безопасностью, см., Например, здесь , как это сделать.)

0 голосов
/ 21 августа 2011

Если вы хотите избежать использования языка сценариев, такого как Groovy, вы можете рассмотреть возможность использования синтаксиса конфигурации, который позволяет указывать name = список значений .Давайте предположим, что синтаксис:

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 =синтаксис с одним значением , затем вы можете эмулировать имя = список значений , задав в качестве значения строку, содержащую элементы, разделенные запятыми, а затем используйте java.util.StringTokenizer или String.split()разбить строку, чтобы получить доступ к отдельным элементам.

Другой подход, который является гораздо более гибким, но опасным, поскольку позволяет человеку выполнять произвольный код, выглядит следующим образом ...

Шаг 1 .Определите интерфейс Java (или абстрактный базовый класс), который определяет один метод.Например:

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

Шаг 2 .Напишите класс «по умолчанию», который реализует этот интерфейс, используя простой алгоритм.

Шаг 3 .Разрешите администраторам написать свой собственный класс, который реализует вышеуказанный интерфейс, и добавить файл jar, содержащий этот класс, в CLASSPATH.

Шаг 4 .Имейте переменную в файле конфигурации, укажите имя класса, который реализует вышеупомянутый интерфейс.Если эта переменная отсутствует в файле конфигурации, вернитесь к использованию имени класса реализации по умолчанию.

Шаг 5 .Используйте API отражения Java для создания экземпляра класса, указанного в файле конфигурации, а затем вызовите его метод calculateProbabilityForLevel().

Если вы еще не знакомы с отражением Java, посмотрите на мой Java Reflection объяснил просто презентация, чтобы узнать, что вам нужно знать.

0 голосов
/ 20 августа 2011

Если выражения, которые вам нужно вычислить, ограничены относительно простой арифметикой, возможно, некоторыми строковыми манипуляциями и вызовами метода / метода доступа к свойству объекта, я хотел бы использовать одну из доступных библиотек выражений библиотек и посмотрите, достаточно ли они, например MVEL или OGNL .

В противном случае, как указывали другие, если вам нужно более сложное поведение, рассмотрите полноценные языки сценариев, такие как Groovy или JRuby.

0 голосов
/ 20 августа 2011

Может быть, вам следует разрешить только некоторые функции, например, сумму a x n , где x - уровень. После этого вы можете сохранить его как массив пар a,n

.Не думаю, что вы будете использовать что-то вроде греха.Обычно это будет что-то вроде ax+b

...