ContentAtom.ts 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126
  1. /**
  2. * Represents the smallest part of a content. Is a wrapper for what is being compared.
  3. * Holds an array of things. Only returns positive comparisons when all of them match, unless both sides only left optional nouns.
  4. */
  5. class ContentAtom {
  6. protected nouns : Array<any> = [];
  7. public constructor (...nouns : Array<any>) {
  8. this.addNoun(...nouns);
  9. }
  10. public addNoun (...nouns : Array<any>) {
  11. this.nouns.push(...nouns);
  12. return this;
  13. }
  14. public setNouns (...nouns : Array<any>) {
  15. this.nouns = [];
  16. this.addNoun(...nouns);
  17. return this;
  18. }
  19. public getNouns () {
  20. return [...this.nouns];
  21. }
  22. public getAtomPriority () {
  23. let weight = 0;
  24. this.nouns.forEach(value => {
  25. weight += ContentAtom.weightNoun(value);
  26. });
  27. return weight;
  28. }
  29. /**
  30. * Comparisons are always made assuming we're comparing the SPECIFIC side to the VAGUE side.
  31. * @param other
  32. */
  33. public compareAgainst (other : ContentAtom) {
  34. let specificNouns = [...this.nouns];
  35. let vagueNouns = [...other.nouns];
  36. for (let i = specificNouns.length - 1; i >= 0; i--) {
  37. let specificNoun = specificNouns[i];
  38. for (let k = vagueNouns.length - 1; k >= 0; k--) {
  39. let vagueNoun = vagueNouns[k];
  40. if (ContentAtom.compareNoun(specificNoun, vagueNoun)) {
  41. specificNouns.splice(i, 1);
  42. vagueNouns.splice(k, 1);
  43. break;
  44. }
  45. }
  46. }
  47. if (specificNouns.length == 0 && vagueNouns.length == 0) {
  48. return true;
  49. } else {
  50. // If any mandatory nouns were left unfilled, return false
  51. for (let i = 0; i < specificNouns.length; i++) {
  52. if (!(specificNouns[i] instanceof ContentNoun) || (<ContentNoun> specificNouns[i]).getType() == ContentNounType.MANDATORY) {
  53. return false;
  54. }
  55. }
  56. // If any non-adaptive nouns were left on the vague side, return false
  57. // Adaptive nouns means the content will handle it not existing for us
  58. for (let i = 0; i < vagueNouns.length; i++) {
  59. if (!(vagueNouns[i] instanceof ContentNoun) || (<ContentNoun> vagueNouns[i]).getType() != ContentNounType.FULLY_ADAPTIVE) {
  60. return false;
  61. }
  62. }
  63. // All tests passed, must be okay
  64. return true;
  65. }
  66. }
  67. public static compareNoun (specificNoun : any, vagueNoun : any) {
  68. if (specificNoun instanceof ContentNoun) {
  69. return specificNoun.compareAgainst(vagueNoun);
  70. } else if (typeof vagueNoun == "function") {
  71. // specific must inherit vague or be vague
  72. return specificNoun == vagueNoun || specificNoun instanceof vagueNoun ||
  73. (typeof specificNoun == "function" && (<any> specificNoun).prototype instanceof vagueNoun)
  74. } else if (vagueNoun instanceof Thing) {
  75. // specific must be vague
  76. return specificNoun == vagueNoun;
  77. }
  78. // Last strict check, probably returns false every time, unless we're dealing with numbers?
  79. return vagueNoun === specificNoun;
  80. }
  81. public static weightNoun (noun : any) : number {
  82. if (noun instanceof ContentNoun) {
  83. // This is a collection of multiple nouns! Add the weights?
  84. let weight = 0;
  85. noun.getNouns().forEach(value => {
  86. weight += ContentAtom.weightNoun(value);
  87. });
  88. return weight;
  89. } else if (noun instanceof ContentNounSimple) {
  90. // It's just a marker
  91. return 1;
  92. } else {
  93. // Normal noun.
  94. if (typeof noun == "function") {
  95. if (<any>noun.prototype instanceof Thing) {
  96. let specificity = 2; // Vague Thing
  97. let parentClass = Object.getPrototypeOf(noun);
  98. while (parentClass != Thing) {
  99. specificity += 0.1;
  100. parentClass = Object.getPrototypeOf(parentClass);
  101. }
  102. return specificity;
  103. } else {
  104. return 2.5; // It's not a "Thing", so it's probably a weird class, which is kind of specific
  105. }
  106. } else if (noun instanceof Thing) {
  107. return 4; // Specific thing
  108. } else {
  109. return 0.5; // The fuck is this shit, probably a number or something.
  110. }
  111. }
  112. }
  113. }