1
1

Rulebook.ts 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144
  1. /// <reference path="../../Functions.ts" />
  2. interface RulebookOptions<T> {
  3. noun? : T;
  4. }
  5. /**
  6. * Without the Runner, Rulebooks were not "thread-safe", so we need the runner.
  7. */
  8. class RulebookRunner<T> {
  9. public noun : T;
  10. private rulesToExecute : Array<Rule> = [];
  11. public rulebook : Rulebook<T>;
  12. public rule : Rule;
  13. private ruleRunner : number = -1;
  14. public constructor (rulebook : Rulebook<T>, noun : T) {
  15. this.rulebook = rulebook;
  16. this.noun = noun;
  17. }
  18. public addRulebooks (...rulebooks : Array<Rulebook<T>>) {
  19. rulebooks = arrayUniqueNewArray(rulebooks);
  20. rulebooks.forEach((rulebook) => {
  21. this.addRules(...rulebook.rules);
  22. });
  23. }
  24. public addRules (...rules) {
  25. if (this.ruleRunner < 0) {
  26. this.rulesToExecute.push(...rules);
  27. }
  28. }
  29. public skipRule (rule : Rule) {
  30. if (this.ruleRunner >= 0) {
  31. let index = this.rulesToExecute.indexOf(rule);
  32. if (index > this.ruleRunner) {
  33. this.rulesToExecute.splice(index, 1);
  34. console.debug("[Rulebook]" + this.rulebook.name + ", skipping Rule " + rule.name + " due to request.");
  35. } else {
  36. console.warn("[Rulebook]" + this.rulebook.name + ": uname to skip Rule" + rule.name + " due to it being too late to stop it.");
  37. }
  38. }
  39. }
  40. public async execute () {
  41. arrayUnique(this.rulesToExecute).sort(function (a: Rule, b: Rule) {
  42. return a.compareTo(b);
  43. });
  44. for (this.ruleRunner = 0; this.ruleRunner < this.rulesToExecute.length; this.ruleRunner++) {
  45. this.rule = this.rulesToExecute[this.ruleRunner];
  46. let result = await this.rule.execute(this);
  47. if (result != undefined) {
  48. return result;
  49. }
  50. }
  51. }
  52. }
  53. class Rulebook<T> {
  54. public rules : Array<Rule> = [];
  55. public name : string;
  56. private static indentantionSpaces = 2;
  57. public static rulebookStack : Array<any> = [];
  58. public static getStack () {
  59. let stack = [];
  60. Rulebook.rulebookStack.forEach((rl) => {
  61. if (rl instanceof Object && rl.name != undefined) {
  62. stack.push(rl.name);
  63. } else if (typeof rl == "string") {
  64. stack.push(rl);
  65. } else if (rl instanceof Object && rl.id != undefined) {
  66. stack.push(rl.id);
  67. } else {
  68. stack.push("Undefined");
  69. }
  70. });
  71. return stack;
  72. }
  73. public static getIndentation () {
  74. return " ".repeat(Rulebook.indentantionSpaces).repeat(Rulebook.rulebookStack.length);
  75. }
  76. public static increaseIndentation (rulebook : any) {
  77. Rulebook.rulebookStack.push(rulebook);
  78. }
  79. public static decreaseIndentation () {
  80. Rulebook.rulebookStack.pop();
  81. }
  82. public static isRunning (r : Rule | Rulebook<any>) {
  83. return Rulebook.rulebookStack.indexOf(r) != -1;
  84. }
  85. public isRunning () {
  86. return Rulebook.isRunning(this);
  87. }
  88. public constructor (name : string) {
  89. this.name = name;
  90. }
  91. public async execute (options : RulebookOptions<T>, ...rulebooks) : Promise<any>{
  92. options = options == undefined ? {} : options;
  93. let runner = new RulebookRunner<T>(this, options.noun); // duplicate array
  94. runner.addRulebooks(this, ...rulebooks);
  95. var names = [];
  96. for (let i = 0; i < rulebooks.length; i++) {
  97. if (rulebooks[i] === this) continue;
  98. names.push(rulebooks[i].name);
  99. }
  100. console.debug(Rulebook.getIndentation() + "[RULEBOOK] " + this.name + (names.length > 0 ? (" merged with " + names.join(", ")) : ""));
  101. Rulebook.increaseIndentation(this);
  102. let result = await runner.execute();
  103. Rulebook.decreaseIndentation();
  104. return result;
  105. }
  106. public createAndAddRule (r : RuleOptions<T>) : Rule {
  107. let rule = new Rule(r);
  108. this.addRule(rule);
  109. return rule;
  110. }
  111. public addRule (r : Rule) {
  112. this.rules.push(r);
  113. }
  114. public sortRules () {
  115. this.rules.sort(function (a : Rule, b : Rule) {
  116. return a.compareTo(b);
  117. });
  118. }
  119. }