using System.Linq.Expressions;
using System.Collections.Generic;
public class CourseRecord {
public string Code { get; set; } = "";
public string Name { get; set; } = "";
public string Operator { get; set; }
public bool Passed { get; set; }
public bool GroupStart { get; set; }
public bool GroupEnd { get; set; }
public override string ToString(){
return (string.IsNullOrWhiteSpace(Operator) ? "" : Operator + " ") + (GroupStart ? "(" : "") + Code + " => " + Name + (GroupEnd ? ")" : "");
public static CourseRecord[] MapConditionToCourseRecord(Condition condition, string @operator = null, bool braceStart = false, bool braceEnd = false) {
var result = new List<CourseRecord>();
if (condition is ConditionGroup @group)
var op = @group.Operator == Operator.And ? "&" : "|";
for (int i = 0; i < @group.Conditions.Count; i++)
var cond = @group.Conditions[i];
result.AddRange(MapConditionToCourseRecord(cond, i == 0 ? @operator : op, i == 0 && @operator != null, i == @group.Conditions.Count - 1));
Code = condition.ToString(),
Name = condition.Expression,
public static void Main()
var condition = "(01151 AND 01201 AND 14374 AND 14384) OR (15214 AND 09212)";
var tokens = GetTokens(condition);
var cond = GetExpression(tokens);
Console.WriteLine(condition);
Console.WriteLine(cond.ToString());
Console.WriteLine(cond.Expression);
var records = MapConditionToCourseRecord(cond);
Console.WriteLine(records.Count());
foreach (var record in records)
Console.WriteLine(record);
private readonly string _rawText;
public Condition(string rawText, string expression) { _rawText = rawText; Expression = expression; }
protected Condition(bool isGroup) : this("", "") { IsGroup = isGroup; }
public virtual string Expression { get; }
public bool IsGroup { get; }
public override string ToString() { return _rawText; }
public class ConditionGroup : Condition
public ConditionGroup(Operator @operator) : base(true) { Operator = @operator; }
public List<Condition> Conditions { get; set; } = new();
public Operator Operator { get; }
public override string Expression => ToString(c => c.Expression);
public override string ToString() => ToString(c => c.ToString());
private string ToString(Func<Condition, string> selector, string opr = null)
var op = Operator == Operator.And ? " AND " : " OR ";
foreach (var c in Conditions)
if (c is ConditionGroup g)
result += (string.IsNullOrEmpty(result) ? "" : op) + g.ToString(selector, op);
result += (string.IsNullOrEmpty(result) ? "" : op) + selector(c);
if (string.IsNullOrEmpty(opr) || opr == op)
return "(" + result + ")";
public static string WriteCondition(ConditionGroup cond, string opr = "") {
var op = cond.Operator == Operator.And ? " AND " : " OR ";
foreach (var c in cond.Conditions) {
if (c is ConditionGroup g)
result += op + WriteCondition(g, op);
result += op + c.ToString();
result = result.Substring(op.Length);
if (opr == op || opr == "")
return "(" + result + ")";
public static string WriteCondition(Condition cond) {
if(cond.IsGroup && cond is ConditionGroup condG){
var op = condG.Operator == Operator.And ? " AND " : " OR ";
foreach (var c in condG.Conditions)
result += op + WriteCondition(c);
return "(" + result.Substring(op.Length) + ")";
public static void WriteCondition(Condition cond, string ttab) {
if(cond.IsGroup && cond is ConditionGroup condG){
Console.WriteLine(ttab + "ConditionGroup => " + (condG.Operator == Operator.And ? "{AND}" : "{OR}"));
Console.WriteLine(ttab + "Conditions =>");
foreach (var c in condG.Conditions)
Console.WriteLine(ttab + "Condition => " + cond.ToString());
public static Condition GetExpression(Queue<string> input)
var exp = input.Dequeue();
var isAnd = exp.Equals("and", StringComparison.OrdinalIgnoreCase);
var isOr = exp.Equals("or", StringComparison.OrdinalIgnoreCase);
var condition = GetExpression(input);
return new ConditionGroup(isAnd ? Operator.And : Operator.Or) {
Conditions = new List<Condition>(){ GetExpression(input), condition }
return new Condition(exp, GetCourseName(exp) ?? exp);
public static Queue<string> GetTokens(string condition)
var result = new Queue<string>();
var operations = new Stack<string>();
var tokens = condition.Replace("(", "( ").Replace(")", " )").Split(' ', StringSplitOptions.RemoveEmptyEntries);
foreach (var token in tokens)
if (!string.IsNullOrWhiteSpace(token))
if (token.Equals("and", StringComparison.OrdinalIgnoreCase) || token.Equals("or", StringComparison.OrdinalIgnoreCase))
while (operations.Count > 0 && (operations.Peek().Equals("and", StringComparison.OrdinalIgnoreCase) || operations.Peek().Equals("or", StringComparison.OrdinalIgnoreCase)))
result.Enqueue(operations.Pop());
else if (token.Equals("(", StringComparison.OrdinalIgnoreCase)) operations.Push(token);
else if (token.Equals(")", StringComparison.OrdinalIgnoreCase))
while (operations.Count > 0 && !operations.Peek().Equals("(", StringComparison.OrdinalIgnoreCase))
result.Enqueue(operations.Pop());
while (operations.Count > 0)
result.Enqueue(operations.Pop());
return new Queue<string>(result.Reverse());
public static string GetCourseName(string code){
if (code == "01151") return "الجبر الخطى";
if (code == "01201") return "الثقافه العلميه";
if (code == "14374") return "اصول التربيه";
if (code == "14384") return "مدخل الى علم النفس";
if (code == "15214") return "مقدمه فى تكنلوجيا التعلم";
if (code == "09212") return "مهارات دراسيه";