|
@@ -0,0 +1,126 @@
|
|
|
+/**
|
|
|
+ * Represents the smallest part of a content. Is a wrapper for what is being compared.
|
|
|
+ * Holds an array of things. Only returns positive comparisons when all of them match, unless both sides only left optional nouns.
|
|
|
+ */
|
|
|
+class ContentAtom {
|
|
|
+ protected nouns : Array<any> = [];
|
|
|
+
|
|
|
+ public constructor (...nouns : Array<any>) {
|
|
|
+ this.addNoun(...nouns);
|
|
|
+ }
|
|
|
+
|
|
|
+ public addNoun (...nouns : Array<any>) {
|
|
|
+ this.nouns.push(...nouns);
|
|
|
+ return this;
|
|
|
+ }
|
|
|
+
|
|
|
+ public setNouns (...nouns : Array<any>) {
|
|
|
+ this.nouns = [];
|
|
|
+ this.addNoun(...nouns);
|
|
|
+ return this;
|
|
|
+ }
|
|
|
+
|
|
|
+ public getNouns () {
|
|
|
+ return [...this.nouns];
|
|
|
+ }
|
|
|
+
|
|
|
+ public getAtomPriority () {
|
|
|
+ let weight = 0;
|
|
|
+ this.nouns.forEach(value => {
|
|
|
+ weight += ContentAtom.weightNoun(value);
|
|
|
+ });
|
|
|
+ return weight;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Comparisons are always made assuming we're comparing the SPECIFIC side to the VAGUE side.
|
|
|
+ * @param other
|
|
|
+ */
|
|
|
+ public compareAgainst (other : ContentAtom) {
|
|
|
+ let specificNouns = [...this.nouns];
|
|
|
+ let vagueNouns = [...other.nouns];
|
|
|
+
|
|
|
+ for (let i = specificNouns.length - 1; i >= 0; i--) {
|
|
|
+ let specificNoun = specificNouns[i];
|
|
|
+ for (let k = vagueNouns.length - 1; k >= 0; k--) {
|
|
|
+ let vagueNoun = vagueNouns[k];
|
|
|
+ if (ContentAtom.compareNoun(specificNoun, vagueNoun)) {
|
|
|
+ specificNouns.splice(i, 1);
|
|
|
+ vagueNouns.splice(k, 1);
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if (specificNouns.length == 0 && vagueNouns.length == 0) {
|
|
|
+ return true;
|
|
|
+ } else {
|
|
|
+ // If any mandatory nouns were left unfilled, return false
|
|
|
+ for (let i = 0; i < specificNouns.length; i++) {
|
|
|
+ if (!(specificNouns[i] instanceof ContentNoun) || (<ContentNoun> specificNouns[i]).getType() == ContentNounType.MANDATORY) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // If any non-adaptive nouns were left on the vague side, return false
|
|
|
+ // Adaptive nouns means the content will handle it not existing for us
|
|
|
+ for (let i = 0; i < vagueNouns.length; i++) {
|
|
|
+ if (!(vagueNouns[i] instanceof ContentNoun) || (<ContentNoun> vagueNouns[i]).getType() != ContentNounType.FULLY_ADAPTIVE) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // All tests passed, must be okay
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ public static compareNoun (specificNoun : any, vagueNoun : any) {
|
|
|
+ if (specificNoun instanceof ContentNoun) {
|
|
|
+ return specificNoun.compareAgainst(vagueNoun);
|
|
|
+ } else if (typeof vagueNoun == "function") {
|
|
|
+ // specific must inherit vague or be vague
|
|
|
+ return specificNoun == vagueNoun || specificNoun instanceof vagueNoun ||
|
|
|
+ (typeof specificNoun == "function" && (<any> specificNoun).prototype instanceof vagueNoun)
|
|
|
+ } else if (vagueNoun instanceof Thing) {
|
|
|
+ // specific must be vague
|
|
|
+ return specificNoun == vagueNoun;
|
|
|
+ }
|
|
|
+
|
|
|
+ // Last strict check, probably returns false every time, unless we're dealing with numbers?
|
|
|
+ return vagueNoun === specificNoun;
|
|
|
+ }
|
|
|
+
|
|
|
+ public static weightNoun (noun : any) : number {
|
|
|
+ if (noun instanceof ContentNoun) {
|
|
|
+ // This is a collection of multiple nouns! Add the weights?
|
|
|
+ let weight = 0;
|
|
|
+ noun.getNouns().forEach(value => {
|
|
|
+ weight += ContentAtom.weightNoun(value);
|
|
|
+ });
|
|
|
+ return weight;
|
|
|
+ } else if (noun instanceof ContentNounSimple) {
|
|
|
+ // It's just a marker
|
|
|
+ return 1;
|
|
|
+ } else {
|
|
|
+ // Normal noun.
|
|
|
+ if (typeof noun == "function") {
|
|
|
+ if (<any>noun.prototype instanceof Thing) {
|
|
|
+ let specificity = 2; // Vague Thing
|
|
|
+ let parentClass = Object.getPrototypeOf(noun);
|
|
|
+ while (parentClass != Thing) {
|
|
|
+ specificity += 0.1;
|
|
|
+ parentClass = Object.getPrototypeOf(parentClass);
|
|
|
+ }
|
|
|
+ return specificity;
|
|
|
+ } else {
|
|
|
+ return 2.5; // It's not a "Thing", so it's probably a weird class, which is kind of specific
|
|
|
+ }
|
|
|
+ } else if (noun instanceof Thing) {
|
|
|
+ return 4; // Specific thing
|
|
|
+ } else {
|
|
|
+ return 0.5; // The fuck is this shit, probably a number or something.
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|