Skip to content

幸运的表达式,一款优质的支付,财务,物流系统计算引擎

Notifications You must be signed in to change notification settings

fayewon/LuckyExp

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

LuckyExp

幸运的表达式,首款面向对象计算的开源工具。

Alt text

Introduction

  • 轻量,快速,易用,面向对象计算
  • 极大降低企业项目业务逻辑和计算逻辑的粘度,实现业务和计算结构分离。
  • 不需要依赖任何jar包,只需要JDK1.8即可。通过绑定对象计算出结果。
  • 开发者是持续维护的原动力,更多功能敬请期待。

requirements:

  • JDK1.8

pom.xml

<dependency>
  <groupId>com.github.fayewon</groupId>
  <artifactId>LuckyExp</artifactId>
  <version>1.0.2</version>
</dependency>

简述

   LuckyExp是一款快速易用的面向对象计算的引擎,通过绑定实体类的全局变量作为计算参数并且自动注入结果。注入结果的变量也可做为绑定参数为下一个结果变量的计算参数。
   LuckyExp的制作目的是为了整合项目开发中的计算业务,通过配置注解的方式即可完成整个计算过程达到与其他的业务逻辑实现分离的目的。 这样的好处是方便修改计算规则。

快速开始

简单计算

//被计算的对象(entity)需要实现序列化接口
public class Dog implements Serializable{
  //绑定计算参数
  @BindVar("A")
  private Double one;
  //绑定计算参数
  @BindVar("B")
  private int two;
  //绑定计算参数和公式
  @BindVar("C")
  @Calculation(formula= {"A+B"},format = "##.###")//format = "##.###" 格式,默认是保留后五位小数
  private Double three;
}
@Test
public void test(){
  Dog dog = new Dog();
  dog.setOne(40);//计算参数 'A'
  dog.setTwo(60.0);//计算参数 'B'
  new DefaultLuckyExpBuilder()//创建一个幸运表达式对象
  .build(dog)//计算入口
  .result();//计算结果
  System.out.println(dog.getThree());//A+B=100
}

选择公式和追加参数计算

public class Dog implements Serializable{
  //绑定计算参数
  @BindVar("A")
  private Double one;
  //绑定计算参数
  @BindVar("B")
  private int two;
  //绑定计算参数和公式
  @BindVar("C")
  @Calculation(formula= {"A+B","A+B*HelloKitty"},format = "##.###")//format = "##.###" 格式,默认是保留后五位小数
  private Double three;
}
@Test
public void test() {
  Map<String,Double> param = new HashMap<String,Double>();
  param.put("HelloKitty", 5.0);//追加计算参数
  Selector selector = new Selector();//创建一个公式选择器
  selector.formulaFiled(Dog.class, "three", Formula_Choose._2);//计算对象dog的类信息,需要选择的变量名称,选择第二个公式
  Dog dog = new Dog();
  dog.setOne(40);//计算参数 'A'
  dog.setTwo(60.0);//计算参数 'B'
  new DefaultLuckyExpBuilder()//创建一个幸运表达式对象
  .build(dog,param,selector)//计算入口  计算对象,追加计算参数,公式选择器
  //.addSelector(selector)
  .result();//获取结果
  System.out.println(dog.getThree());//A+B*HelloKitty=340.0
}

依赖计算和复杂计算

public class Dog implements Serializable{
  @BindObject //绑定对象变量,当setCat的时候该注解生效
  private Cat cat;
  //绑定计算参数
  @BindVar("A")
  private Double one;
  //绑定计算参数
  @BindVar("B")
  private int two;
  //绑定计算参数和公式
  @BindVar("C")
  @Calculation(formula= {"A+B","A+B*HelloKitty"},format = "##.###")//format = "##.###" 格式,默认是保留后五位小数
  private Double three;
}
public class Cat implements Serializable{
  @BindVar("K")
  private Double eleven;
  @BindVar("L")
  //max 求4位最大值,位数不够添加占位符。if:高级函数,搭配运算符 '>','<','='使用 三目运算函数 第1位返回布尔值.2,3位返回浮点数
  @Calculation(formula= {"C+K","max(if(A>B,A,B),1,2,300000)"},format = "##.###")
  private Double twelve;
}
@Test
public void test() {
  Map<String,Double> param = new HashMap<String,Double>();
  param.put("HelloKitty", 5.0);//追加计算参数
		Selector selector = new Selector();//创建一个公式选择器
		selector.formulaFiled(Dog.class, "three", Formula_Choose._2);//计算对象Dog的类信息,需要选择的变量名称,选择第二个公式
		Dog dog = new Dog();
		dog.setOne(40.0);//计算参数 'A' = 40
		dog.setTwo(60);//计算参数 'B' = 60.0
		Cat cat = new Cat();
		cat.setEleven(50.0);//计算参数 'K' = 50.0
		dog.setCat(cat);//使@BindObject注解生效
		new DefaultLuckyExpBuilder()//创建一个幸运表达式对象
		.build(dog,param,selector)//计算入口
		.result();//获取结果
		System.out.println(dog.getThree());//A+B*HelloKitty=(C)340.0
		System.out.println(dog.getCat().getTwelve());//C+K=(L)390.0
		dog.getCat().setTwelve(null);
				
		//选择cat的twelve第二个公式
		selector.formulaFiled(Cat.class, "twelve", Formula_Choose._2);//计算对象Cat的类信息,需要选择的变量名称,选择第二个公式
		new DefaultLuckyExpBuilder()//创建一个幸运表达式对象
		.build(dog,param)//计算入口
		.result();//获取结果
		System.out.println(dog.getCat().getTwelve());//max(if(A>B,A,B),1,2,3)=60
		  
		//给计算公式变量设置默认值 则解绑自动计算属性,结果为默认值
		dog.setThree(123.8);
		dog.getCat().setTwelve(520.0);
		System.out.println(dog.getThree());//123.8
		System.out.println(dog.getCat().getTwelve());//520.0		
}

自定义函数和运算符

public class Dog implements Serializable{
  //绑定计算参数
  @BindVar("A")
  private Double one;
  //绑定计算参数
  @BindVar("B")
  private int two;
  //绑定计算参数和公式
  @BindVar("C")
  @Calculation(formula= {"funTest(A+B#1.5)","A+B*HelloKitty"},format = "##.###")//format = "##.###" 格式,默认是保留后五位小数
  private Double three;
}
@Test
public void test2() {
  Dog dog = new Dog();
  dog.setOne(40);//计算参数 'A'
  dog.setTwo(60.0);//计算参数 'B'
  new DefaultLuckyExpBuilder()//创建一个幸运表达式对象
  .build(dog)//计算入口
  .addFunc(new Func("funTest") {//自定义公式
	public double call(Object... args) {
		 return Math.ceil(((double)args[0]));//向上取整
		}
      })
  .addOper(new Oper("#", 2/**操作数只接受1或2**/, true/**true:向左运算:false向右运算**/, Oper.PRECEDENCE_ADDITION/**加法优先值**/) {//自定义运算符
	public Object call(final double... args) {
             return args[0] + args[1];
           }
      })
  .result();//计算结果
  System.out.println(dog.getThree());//funTest(A+B#1.5)=102.0   40+60+1.5向上取整 = 102
}

缓存计算和回调结果

公式多且复杂,遍历次数多建议开启缓存计算
@Test
public void test3() {
  Long start = System.currentTimeMillis();
  for(int i=0;i<1000000;i++) {
  Dog dog = new Dog();
  dog.setOne((short)3);
  dog.setTwo(2.1* i);
  Cat cat = new Cat();
  cat.setEleven(123.9);
  dog.setCat(cat);
  new DefaultLuckyExpBuilder()
  .build(dog)//不需要追加计算参数和只绑定一个公式  //默认使用第一个公式,param,selector
  .addCache(false)//关闭缓存计算
  .addCache(true,3 * 60 * 1000)//开启缓存计算,缓存3分钟  默认关闭缓存计算
  .result((handle)->{//回调结果
        if(handle.isSuccess()) {//全部计算成功返回 true
	Dog successDog = (Dog)handle.getT();
	System.out.println(successDog);
	}else {//部分计算出来或没有计算出来 都会返回该对象
	Dog errorDog = (Dog)handle.getT();
	Set<String> errors = handle.getErrors();//没有计算出来的变量缺少的计算参数
	System.out.println(errors);
	System.out.println(errorDog);
	}
    });
 }
  Long end = System.currentTimeMillis();
  System.out.println("简单测试一百万条缓存计算时间:"+(end-start)/1000+"秒"); // 19秒
  System.out.println("简单测试一百万条不缓存计算时间:"+(end-start)/1000+"秒"); // 26秒
}
    内置函数 Funcs.java
     函数名     位数     作用
     min4          4         取最小值,位数不够添加占位符
     max4          4         取最大值,位数不够添加占位符
     sin          1         正弦函数
     cos          1         余弦函数
     tan          1         正切函数
     cot          1         余切函数
     log          1         对角函数,1 以e为底的对数
     log2          1         对角函数,2 以e为底的对数
     log10          1         对角函数,10 以e为底的对数
     log1p          1         对角函数,Ln(x+ 1)
     abs          1         绝对值函数
     acos          1         返回角度值[0~π] arc cos(y/z)
     asin          1         返回角度值[-π/2,π/2] arc sin(x/z)
     atan          1         返回角度值[-π/2,π/2]
     cbrt          1         立方根函数
     floor          1         向下取整
     sinh          1         双曲正弦函数sinh(x)=(exp(x) - exp(-x)) / 2.0
     sqrt          1         平方根函数
     tanh          1         tanh(x) = sinh(x) / cosh(x)
     cosh          1         双曲余弦函数cosh(x)=(exp(x) + exp(-x)) / 2.0
     ceil          1         向上取整
     pow          2         次方函数
     exp          1         e的x次幂
     expm1          1         e的x次幂 - 1
     signum          1         整数比较
     if          3         高级函数。三目运算符函数,第一位boolean值。搭配boolean运算符 '<' , '>','=' 使用
    内置运算符 Opers.java
     运算名     优先值     返回值
     +          加法运算的优先值         double
     -          减法运算的优先值         double
     *          乘法运算的优先值         double
     /          除法运算的优先值         double
     ^          电源操作的优先值         double
     %          除法运算的优先值         double
     >          一元加运算的优先值         boolean
     <          一元加运算的优先值         boolean
     =          一元加运算的优先值         boolean

About

幸运的表达式,一款优质的支付,财务,物流系统计算引擎

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages