Last active
July 29, 2024 07:43
-
-
Save Shipu/f049956b6ca1a36a638ddb395376f28e to your computer and use it in GitHub Desktop.
RCT
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(c1 result >= 35 AND ( c3 result <= 30 AND c2 progress > 50)) | |
AND | |
(c3 result > 10 AND purchase_date < 2025-01-10 ) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import ( | |
"fmt" | |
"github.com/gin-gonic/gin" | |
"github.com/shipu/artifact" | |
"net/http" | |
"strconv" | |
"time" | |
) | |
type Expression struct { | |
Content string `json:"content,omitempty"` | |
Variable string `json:"variable,omitempty"` | |
Comparison string `json:"comparison,omitempty"` | |
Value string `json:"value,omitempty"` | |
From string `json:"from,omitempty"` | |
Operator string `json:"operator,omitempty"` | |
Conditions []Expression `json:"conditions,omitempty"` | |
} | |
type VisibilityLogic struct { | |
Type string `json:"type"` | |
Until []Expression `json:"until"` | |
} | |
var context = map[string]interface{}{ | |
"c1_result": 40, | |
"c2_progress": 80, | |
"c3_result": 20, | |
"purchase_date": "2024-07-01", | |
} | |
// compareDate compares two dates based on the operator. | |
func compareDate(from, to, operator string) (bool, error) { | |
fromDate, err := time.Parse("2006-01-02", from) | |
if err != nil { | |
return false, err | |
} | |
toDate, err := time.Parse("2006-01-02", to) | |
if err != nil { | |
return false, err | |
} | |
switch operator { | |
case "=": | |
return fromDate.Equal(toDate), nil | |
case "!=": | |
return !fromDate.Equal(toDate), nil | |
case ">": | |
return fromDate.After(toDate), nil | |
case "<": | |
return fromDate.Before(toDate), nil | |
case ">=": | |
return fromDate.After(toDate) || fromDate.Equal(toDate), nil | |
case "<=": | |
return fromDate.Before(toDate) || fromDate.Equal(toDate), nil | |
} | |
return false, nil | |
} | |
// evaluateExpression evaluates a single expression condition. | |
func evaluateExpression(cond Expression) bool { | |
// Handle date and time related comparisons | |
if cond.Variable == "date" || cond.Variable == "time" { | |
from := cond.From | |
if from == "" { | |
from = time.Now().Format("2006-01-02") | |
} else { | |
from = context[from].(string) | |
} | |
result, err := compareDate(from, cond.Value, cond.Comparison) | |
if err != nil { | |
fmt.Println("Error comparing dates:", err) | |
return false | |
} | |
return result | |
} | |
left, ok := context[cond.Content+"_"+cond.Variable] | |
if !ok { | |
fmt.Println("Context value not found for:", cond.Content+"_"+cond.Variable) | |
return false | |
} | |
var rightParsed interface{} | |
var err error | |
switch left.(type) { | |
case int: | |
rightParsed, err = strconv.Atoi(cond.Value) | |
if err != nil { | |
fmt.Println("Error parsing integer value:", err) | |
return false | |
} | |
case float64: | |
rightParsed, err = strconv.ParseFloat(cond.Value, 64) | |
if err != nil { | |
fmt.Println("Error parsing float value:", err) | |
return false | |
} | |
default: | |
rightParsed = cond.Value | |
} | |
switch cond.Comparison { | |
case "=": | |
return left == rightParsed | |
case "!=": | |
return left != rightParsed | |
case ">": | |
return left.(int) > rightParsed.(int) | |
case "<": | |
return left.(int) < rightParsed.(int) | |
case ">=": | |
return left.(int) >= rightParsed.(int) | |
case "<=": | |
return left.(int) <= rightParsed.(int) | |
} | |
return false | |
} | |
func evaluateExpressions(conditions []Expression) bool { | |
for _, condition := range conditions { | |
if condition.Operator == "" { | |
if !evaluateExpression(condition) { | |
return false | |
} | |
} else { | |
switch condition.Operator { | |
case "AND": | |
if !evaluateExpressions(condition.Conditions) { | |
return false | |
} | |
case "OR": | |
if evaluateExpressions(condition.Conditions) { | |
return true | |
} | |
} | |
} | |
} | |
return true | |
} | |
func Evaluate() gin.HandlerFunc { | |
return func(c *gin.Context) { | |
var visibilityLogic VisibilityLogic | |
if err := c.ShouldBind(&visibilityLogic); err != nil { | |
artifact.Res.Code(http.StatusBadRequest).Message("Bad Request").Data(err.Error()).AbortWithStatusJSON(c) | |
return | |
} | |
result := evaluateExpressions(visibilityLogic.Until) | |
artifact.Res.Code(200).Data(map[string]interface{}{ | |
"result": result, | |
}).Message("success").Json(c) | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"type": "lock", | |
"until": [ | |
{ | |
"operator": "AND", | |
"conditions": [ | |
{ | |
"operator": "AND", | |
"conditions": [ | |
{ | |
"content": "c1", | |
"variable": "result", | |
"comparison": ">=", | |
"value": "35" | |
}, | |
{ | |
"operator": "AND", | |
"conditions": [ | |
{ | |
"content": "c3", | |
"variable": "result", | |
"comparison": "<=", | |
"value": "30" | |
}, | |
{ | |
"content": "c2", | |
"variable": "progress", | |
"comparison": ">", | |
"value": "50" | |
} | |
] | |
} | |
] | |
}, | |
{ | |
"operator": "AND", | |
"conditions": [ | |
{ | |
"content": "c3", | |
"variable": "result", | |
"comparison": ">", | |
"value": "10" | |
}, | |
{ | |
"variable": "date", | |
"comparison": "<", | |
"value": "2025-01-10", | |
"from": "purchase_date" | |
} | |
] | |
} | |
] | |
} | |
] | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
userApi := Router.Group("api/v1") | |
userApi.POST("evaluate", c.Evaluate()) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment