Add project files.
This commit is contained in:
14
Examples/Nodify.Calculator/Operations/BinaryOperation.cs
Normal file
14
Examples/Nodify.Calculator/Operations/BinaryOperation.cs
Normal file
@@ -0,0 +1,14 @@
|
||||
using System;
|
||||
|
||||
namespace Nodify.Calculator
|
||||
{
|
||||
public class BinaryOperation : IOperation
|
||||
{
|
||||
private readonly Func<double, double, double> _func;
|
||||
|
||||
public BinaryOperation(Func<double, double, double> func) => _func = func;
|
||||
|
||||
public double Execute(params double[] operands)
|
||||
=> _func.Invoke(operands[0], operands[1]);
|
||||
}
|
||||
}
|
||||
7
Examples/Nodify.Calculator/Operations/IOperation.cs
Normal file
7
Examples/Nodify.Calculator/Operations/IOperation.cs
Normal file
@@ -0,0 +1,7 @@
|
||||
namespace Nodify.Calculator
|
||||
{
|
||||
public interface IOperation
|
||||
{
|
||||
double Execute(params double[] operands);
|
||||
}
|
||||
}
|
||||
469
Examples/Nodify.Calculator/Operations/OperationFactory.cs
Normal file
469
Examples/Nodify.Calculator/Operations/OperationFactory.cs
Normal file
@@ -0,0 +1,469 @@
|
||||
using Microsoft.CodeAnalysis.CSharp;
|
||||
using Microsoft.CodeAnalysis.CSharp.Syntax;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Windows;
|
||||
using System.Windows.Shapes;
|
||||
using Size = System.Windows.Size;
|
||||
|
||||
namespace Nodify.Calculator
|
||||
{
|
||||
public static class OperationFactory
|
||||
{
|
||||
|
||||
public static List<OperationInfoViewModel> GetSystemNodes()
|
||||
{
|
||||
List<OperationInfoViewModel> systemNodes = new List<OperationInfoViewModel>();
|
||||
|
||||
var copynode = new OperationInfoViewModel()
|
||||
{
|
||||
Title = "COPY",
|
||||
Type = OperationType.System,
|
||||
OPType = "copy",
|
||||
IsFlowNode = false,
|
||||
};
|
||||
copynode.Input.Add("");
|
||||
copynode.Output.Add("");
|
||||
copynode.Output.Add("");
|
||||
|
||||
var begin = new OperationInfoViewModel()
|
||||
{
|
||||
Title = "Begin",
|
||||
Type = OperationType.System,
|
||||
sysOp = SystemOperations.BEGIN,
|
||||
IsFlowNode = true
|
||||
};
|
||||
begin.Output.Add("");
|
||||
|
||||
var ending = new OperationInfoViewModel()
|
||||
{
|
||||
Title = "End",
|
||||
Type = OperationType.System,
|
||||
sysOp = SystemOperations.END,
|
||||
IsFlowNode = true
|
||||
};
|
||||
ending.Input.Add("");
|
||||
|
||||
var debugAndCreateModels = new OperationInfoViewModel()
|
||||
{
|
||||
Title = "Debug & Create Model",
|
||||
Type = OperationType.System,
|
||||
sysOp = SystemOperations.DEBUG_AND_CREATE_MODEL,
|
||||
IsFlowNode = true
|
||||
};
|
||||
debugAndCreateModels.Input.Add("");
|
||||
debugAndCreateModels.Output.Add("");
|
||||
|
||||
var jsonParseNode = new OperationInfoViewModel()
|
||||
{
|
||||
Title = "Parse Json",
|
||||
Type = OperationType.System,
|
||||
sysOp = SystemOperations.PARSEJSON,
|
||||
IsFlowNode = false
|
||||
};
|
||||
jsonParseNode.Input.Add("");
|
||||
jsonParseNode.Output.Add("");
|
||||
|
||||
var splitNode = new OperationInfoViewModel()
|
||||
{
|
||||
Title = "Split",
|
||||
Type = OperationType.System,
|
||||
sysOp = SystemOperations.SPLIT,
|
||||
IsFlowNode = false
|
||||
};
|
||||
splitNode.Input.Add("");
|
||||
splitNode.Output.Add("");
|
||||
|
||||
var takeNode = new OperationInfoViewModel()
|
||||
{
|
||||
Title = "TAKE",
|
||||
Type = OperationType.System,
|
||||
sysOp = SystemOperations.TAKE,
|
||||
IsFlowNode = false
|
||||
};
|
||||
takeNode.Input.Add("");
|
||||
takeNode.Output.Add("");
|
||||
|
||||
var authNode = new OperationInfoViewModel()
|
||||
{
|
||||
Title = "Auth",
|
||||
Type = OperationType.System,
|
||||
sysOp = SystemOperations.AUTH,
|
||||
IsFlowNode = true
|
||||
};
|
||||
authNode.Input.Add("Base URL");
|
||||
authNode.Input.Add("Auth Type");
|
||||
authNode.Input.Add("Token");
|
||||
authNode.Input.Add("API Key");
|
||||
authNode.Input.Add("Username");
|
||||
authNode.Input.Add("Password");
|
||||
|
||||
systemNodes.Add(authNode);
|
||||
systemNodes.Add(copynode);
|
||||
systemNodes.Add(begin);
|
||||
systemNodes.Add(ending);
|
||||
systemNodes.Add(debugAndCreateModels);
|
||||
systemNodes.Add(jsonParseNode);
|
||||
systemNodes.Add(splitNode);
|
||||
systemNodes.Add(takeNode);
|
||||
return systemNodes;
|
||||
}
|
||||
|
||||
public static List<OperationInfoViewModel> GetOperationsInfo(Type container)
|
||||
{
|
||||
List<OperationInfoViewModel> result = new List<OperationInfoViewModel>();
|
||||
|
||||
foreach (var method in container.GetMethods())
|
||||
{
|
||||
if (method.IsStatic)
|
||||
{
|
||||
OperationInfoViewModel op = new OperationInfoViewModel
|
||||
{
|
||||
Title = method.Name
|
||||
};
|
||||
|
||||
var attr = method.GetCustomAttribute<OperationAttribute>();
|
||||
var para = method.GetParameters();
|
||||
|
||||
bool generateInputNames = true;
|
||||
|
||||
op.Type = OperationType.Normal;
|
||||
|
||||
if (para.Length == 2)
|
||||
{
|
||||
var delType = typeof(Func<double, double, double>);
|
||||
var del = (Func<double, double, double>)Delegate.CreateDelegate(delType, method);
|
||||
|
||||
op.Operation = new BinaryOperation(del);
|
||||
}
|
||||
else if (para.Length == 1)
|
||||
{
|
||||
if (para[0].ParameterType.IsArray)
|
||||
{
|
||||
op.Type = OperationType.Expando;
|
||||
|
||||
var delType = typeof(Func<double[], double>);
|
||||
var del = (Func<double[], double>)Delegate.CreateDelegate(delType, method);
|
||||
|
||||
op.Operation = new ParamsOperation(del);
|
||||
op.MaxInput = int.MaxValue;
|
||||
}
|
||||
else
|
||||
{
|
||||
var delType = typeof(Func<double, double>);
|
||||
var del = (Func<double, double>)Delegate.CreateDelegate(delType, method);
|
||||
|
||||
op.Operation = new UnaryOperation(del);
|
||||
}
|
||||
}
|
||||
else if (para.Length == 0)
|
||||
{
|
||||
var delType = typeof(Func<double>);
|
||||
var del = (Func<double>)Delegate.CreateDelegate(delType, method);
|
||||
|
||||
op.Operation = new ValueOperation(del);
|
||||
}
|
||||
|
||||
if (attr != null)
|
||||
{
|
||||
op.MinInput = attr.MinInput;
|
||||
op.MaxInput = attr.MaxInput;
|
||||
generateInputNames = attr.GenerateInputNames;
|
||||
}
|
||||
else
|
||||
{
|
||||
op.MinInput = (uint)para.Length;
|
||||
op.MaxInput = (uint)para.Length;
|
||||
}
|
||||
|
||||
foreach (var param in para)
|
||||
{
|
||||
op.Input.Add(generateInputNames ? param.Name : null);
|
||||
}
|
||||
|
||||
for (int i = op.Input.Count; i < op.MinInput; i++)
|
||||
{
|
||||
op.Input.Add(null);
|
||||
}
|
||||
op.Output.Add("");
|
||||
result.Add(op);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public static OperationViewModel GetOperation(OperationInfoViewModel info)
|
||||
{
|
||||
var input = info.Input.Select(i => new ConnectorViewModel
|
||||
{
|
||||
Title = i
|
||||
});
|
||||
|
||||
switch (info.Type)
|
||||
{
|
||||
case OperationType.Expression:
|
||||
var eo = new ExpressionOperationViewModel
|
||||
{
|
||||
Title = info.Title,
|
||||
Operation = info.Operation,
|
||||
Expression = "1 + sin {a} + cos {b}"
|
||||
};
|
||||
eo.Output.Add(new ConnectorViewModel());
|
||||
return eo;
|
||||
case OperationType.Calculator:
|
||||
return new CalculatorOperationViewModel
|
||||
{
|
||||
Title = info.Title,
|
||||
Operation = info.Operation,
|
||||
};
|
||||
|
||||
case OperationType.Expando:
|
||||
var o = new ExpandoOperationViewModel
|
||||
{
|
||||
MaxInput = info.MaxInput,
|
||||
MinInput = info.MinInput,
|
||||
Title = info.Title,
|
||||
Operation = info.Operation
|
||||
};
|
||||
o.Output.Add(new ConnectorViewModel());
|
||||
o.Input.AddRange(input);
|
||||
return o;
|
||||
|
||||
case OperationType.Group:
|
||||
return new OperationGroupViewModel
|
||||
{
|
||||
Title = info.Title,
|
||||
};
|
||||
|
||||
case OperationType.Graph:
|
||||
return new OperationGraphViewModel
|
||||
{
|
||||
Title = info.Title,
|
||||
DesiredSize = new Size(420, 250)
|
||||
};
|
||||
|
||||
case OperationType.API:
|
||||
var _o = new APIOperationViewModel
|
||||
{
|
||||
Title = info.Title,
|
||||
OperationType = info.OPType.ToUpper()
|
||||
};
|
||||
var connectorViewModel = new ConnectorViewModel()
|
||||
{
|
||||
Title = "",
|
||||
Shape = ConnectorShape.Triangle
|
||||
};
|
||||
var connectorViewModel2 = new ConnectorViewModel()
|
||||
{
|
||||
Title = "",
|
||||
Shape = ConnectorShape.Triangle,
|
||||
IsInput = false
|
||||
};
|
||||
_o.Output.Add(connectorViewModel2);
|
||||
_o.Output.Add(new ConnectorViewModel());
|
||||
_o.Input.Add(connectorViewModel);
|
||||
foreach (var item in input)
|
||||
{
|
||||
item.ConnectorColor = Color.GreenYellow;
|
||||
_o.Input.Add(item);
|
||||
}
|
||||
//_o.Input.AddRange(input);
|
||||
return _o;
|
||||
case OperationType.System:
|
||||
if (info.sysOp == SystemOperations.AUTH)
|
||||
{
|
||||
var authOp = new AuthOperationViewModel
|
||||
{
|
||||
Title = info.Title,
|
||||
SystemOperationType = SystemOperations.AUTH
|
||||
};
|
||||
// Add flow connectors (triangle)
|
||||
var flowIn = new ConnectorViewModel()
|
||||
{
|
||||
Title = "",
|
||||
Shape = ConnectorShape.Triangle
|
||||
};
|
||||
var flowOut = new ConnectorViewModel()
|
||||
{
|
||||
Title = "",
|
||||
Shape = ConnectorShape.Triangle,
|
||||
IsInput = false
|
||||
};
|
||||
authOp.Input.Add(flowIn);
|
||||
authOp.Output.Add(flowOut);
|
||||
// Add data input connectors
|
||||
foreach (var inp in input)
|
||||
{
|
||||
inp.ConnectorColor = System.Drawing.Color.Orange;
|
||||
authOp.Input.Add(inp);
|
||||
}
|
||||
return authOp;
|
||||
}
|
||||
|
||||
var sysOp = new SystemOperationViewModel
|
||||
{
|
||||
Title = info.Title,
|
||||
SystemOperationType = info.sysOp
|
||||
};
|
||||
|
||||
if (info.sysOp == SystemOperations.GET_SET && info.IsModelNode)
|
||||
{
|
||||
if (info.Title == "GET")
|
||||
{
|
||||
info.Output.Add("");
|
||||
info.IsFlowNode = false;
|
||||
}
|
||||
else if (info.Title == "SET")
|
||||
{
|
||||
info.Input.Add("");
|
||||
var customModelDir = "CustomModels";
|
||||
Directory.CreateDirectory(customModelDir);
|
||||
var flpath = System.IO.Path.Combine(customModelDir, info.ClassName + ".cs");
|
||||
if (File.Exists(flpath))
|
||||
{
|
||||
//Read all the properties from the file
|
||||
var fileContent = File.ReadAllText(flpath);
|
||||
|
||||
// Parse and analyze properties
|
||||
var properties = GetPropertiesFromClass(fileContent);
|
||||
|
||||
// Print out the extracted properties and their types
|
||||
Console.WriteLine("Properties found:");
|
||||
foreach (var property in properties)
|
||||
{
|
||||
Console.WriteLine($"Property Name: {property.Name}, Type: {property.Type}");
|
||||
info.Output.Add(property.Name);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
info.IsFlowNode = true;
|
||||
}
|
||||
var flTitle = $"{info.Title} {info.ClassName}";
|
||||
sysOp.Title = flTitle;
|
||||
}
|
||||
|
||||
if (info.sysOp == SystemOperations.GET_SET && info.IsSimpleVariable)
|
||||
{
|
||||
var varLabel = $"{info.Title} {info.ClassName} ({info.VariableType})";
|
||||
sysOp.Title = varLabel;
|
||||
|
||||
if (info.Title == "GET")
|
||||
{
|
||||
// GET variable: output the value, no flow needed
|
||||
info.Output.Add("Value");
|
||||
info.IsFlowNode = false;
|
||||
}
|
||||
else if (info.Title == "SET")
|
||||
{
|
||||
// SET variable: input connector for the value, flow node
|
||||
info.Input.Add("Value");
|
||||
info.IsFlowNode = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (info.sysOp != SystemOperations.BEGIN &&
|
||||
info.sysOp != SystemOperations.END &&
|
||||
info.IsFlowNode)
|
||||
{
|
||||
var flowinputnode = new ConnectorViewModel()
|
||||
{
|
||||
Title = "",
|
||||
Shape = ConnectorShape.Triangle
|
||||
};
|
||||
var flowoutputnode = new ConnectorViewModel()
|
||||
{
|
||||
Title = "",
|
||||
Shape = ConnectorShape.Triangle,
|
||||
IsInput = false
|
||||
};
|
||||
sysOp.Input.Add(flowinputnode);
|
||||
sysOp.Output.Add(flowoutputnode);
|
||||
}
|
||||
foreach (var item in info.Output)
|
||||
{
|
||||
var out1 = new ConnectorViewModel()
|
||||
{
|
||||
Title = string.IsNullOrEmpty(item) ? "" : item,
|
||||
IsInput = false,
|
||||
ConnectorColor = Color.DarkRed,
|
||||
Shape = (info.sysOp == SystemOperations.BEGIN || info.sysOp == SystemOperations.END) ? ConnectorShape.Triangle : ConnectorShape.Circle,
|
||||
};
|
||||
if (out1.Shape != ConnectorShape.Triangle)
|
||||
{
|
||||
out1.ConnectorColor = Color.DeepPink;
|
||||
}
|
||||
sysOp.Output.Add(out1);
|
||||
}
|
||||
foreach (var item in input)
|
||||
{
|
||||
item.Shape = (info.sysOp == SystemOperations.BEGIN || info.sysOp == SystemOperations.END) ? ConnectorShape.Triangle : ConnectorShape.Circle;
|
||||
sysOp.Input.Add(item);
|
||||
}
|
||||
return sysOp;
|
||||
default:
|
||||
{
|
||||
var op = new OperationViewModel
|
||||
{
|
||||
Title = info.Title,
|
||||
Operation = info.Operation,
|
||||
};
|
||||
var ccv = new ConnectorViewModel()
|
||||
{
|
||||
IsInput = false,
|
||||
Shape = ConnectorShape.Circle,
|
||||
Title = ""
|
||||
};
|
||||
op.Output.Add(ccv);
|
||||
|
||||
op.Input.AddRange(input);
|
||||
return op;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static List<CustomProperty> GetPropertiesFromClass(string classContent)
|
||||
{
|
||||
// Parse the C# class content using Roslyn
|
||||
var syntaxTree = CSharpSyntaxTree.ParseText(classContent);
|
||||
var root = syntaxTree.GetRoot();
|
||||
|
||||
// Find the first class declaration (you can refine this if there are multiple classes)
|
||||
var classDeclaration = root.DescendantNodes().OfType<ClassDeclarationSyntax>().FirstOrDefault();
|
||||
|
||||
// List to store extracted properties
|
||||
var properties = new List<CustomProperty>();
|
||||
|
||||
if (classDeclaration != null)
|
||||
{
|
||||
// Look for property declarations inside the class
|
||||
var propertyDeclarations = classDeclaration.Members.OfType<PropertyDeclarationSyntax>();
|
||||
foreach (var property in propertyDeclarations)
|
||||
{
|
||||
var propertyName = property.Identifier.Text; // Property name
|
||||
var propertyType = property.Type.ToString(); // Property type
|
||||
|
||||
// Add the property and its type to the list
|
||||
properties.Add(new CustomProperty
|
||||
{
|
||||
Name = propertyName,
|
||||
Type = propertyType
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return properties;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class CustomProperty // <- Renamed to avoid conflicts with System.Reflection.PropertyInfo
|
||||
{
|
||||
public string Name { get; set; }
|
||||
public string Type { get; set; }
|
||||
}
|
||||
35
Examples/Nodify.Calculator/Operations/OperationsContainer.cs
Normal file
35
Examples/Nodify.Calculator/Operations/OperationsContainer.cs
Normal file
@@ -0,0 +1,35 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
|
||||
namespace Nodify.Calculator
|
||||
{
|
||||
public static class OperationsContainer
|
||||
{
|
||||
[Operation(MinInput = 2, MaxInput = 10, GenerateInputNames = false)]
|
||||
public static double Add(params double[] operands)
|
||||
=> operands.Sum();
|
||||
|
||||
[Operation(MinInput = 2, MaxInput = 10, GenerateInputNames = false)]
|
||||
public static double Multiply(params double[] operands)
|
||||
=> operands.Aggregate((x, y) => x * y);
|
||||
|
||||
public static double Divide(double a, double b)
|
||||
=> a / b;
|
||||
|
||||
public static double Subtract(double a, double b)
|
||||
=> a - b;
|
||||
|
||||
public static double Pow(double value, double exp)
|
||||
=> (double)Math.Pow((double)value, (double)exp);
|
||||
|
||||
public static double PI()
|
||||
=> (double)Math.PI;
|
||||
}
|
||||
|
||||
public sealed class OperationAttribute : Attribute
|
||||
{
|
||||
public uint MaxInput { get; set; }
|
||||
public uint MinInput { get; set; }
|
||||
public bool GenerateInputNames { get; set; }
|
||||
}
|
||||
}
|
||||
14
Examples/Nodify.Calculator/Operations/ParamsOperation.cs
Normal file
14
Examples/Nodify.Calculator/Operations/ParamsOperation.cs
Normal file
@@ -0,0 +1,14 @@
|
||||
using System;
|
||||
|
||||
namespace Nodify.Calculator
|
||||
{
|
||||
public class ParamsOperation : IOperation
|
||||
{
|
||||
private readonly Func<double[], double> _func;
|
||||
|
||||
public ParamsOperation(Func<double[], double> func) => _func = func;
|
||||
|
||||
public double Execute(params double[] operands)
|
||||
=> _func.Invoke(operands);
|
||||
}
|
||||
}
|
||||
14
Examples/Nodify.Calculator/Operations/UnaryOperation.cs
Normal file
14
Examples/Nodify.Calculator/Operations/UnaryOperation.cs
Normal file
@@ -0,0 +1,14 @@
|
||||
using System;
|
||||
|
||||
namespace Nodify.Calculator
|
||||
{
|
||||
public class UnaryOperation : IOperation
|
||||
{
|
||||
private readonly Func<double, double> _func;
|
||||
|
||||
public UnaryOperation(Func<double, double> func) => _func = func;
|
||||
|
||||
public double Execute(params double[] operands)
|
||||
=> _func.Invoke(operands[0]);
|
||||
}
|
||||
}
|
||||
14
Examples/Nodify.Calculator/Operations/ValueOperation.cs
Normal file
14
Examples/Nodify.Calculator/Operations/ValueOperation.cs
Normal file
@@ -0,0 +1,14 @@
|
||||
using System;
|
||||
|
||||
namespace Nodify.Calculator
|
||||
{
|
||||
public class ValueOperation : IOperation
|
||||
{
|
||||
private readonly Func<double> _func;
|
||||
|
||||
public ValueOperation(Func<double> func) => _func = func;
|
||||
|
||||
public double Execute(params double[] operands)
|
||||
=> _func();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user