natural 6.10.2 → 6.10.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (44) hide show
  1. package/.gitconfig +3 -0
  2. package/.github/workflows/node.js.yml +1 -1
  3. package/.github/workflows/npm-publish.yml +4 -4
  4. package/lib/natural/brill_pos_tagger/index.d.ts +32 -26
  5. package/lib/natural/brill_pos_tagger/lib/Brill_POS_Tagger.js +33 -31
  6. package/lib/natural/brill_pos_tagger/lib/Brill_POS_Tester.js +33 -35
  7. package/lib/natural/brill_pos_tagger/lib/Brill_POS_Trainer.js +326 -324
  8. package/lib/natural/brill_pos_tagger/lib/Corpus.js +140 -138
  9. package/lib/natural/brill_pos_tagger/lib/Lexicon.js +78 -76
  10. package/lib/natural/brill_pos_tagger/lib/Predicate.js +19 -17
  11. package/lib/natural/brill_pos_tagger/lib/RuleSet.js +58 -56
  12. package/lib/natural/brill_pos_tagger/lib/RuleTemplate.js +11 -9
  13. package/lib/natural/brill_pos_tagger/lib/Sentence.js +21 -20
  14. package/lib/natural/brill_pos_tagger/lib/TransformationRule.js +58 -58
  15. package/lib/natural/classifiers/bayes_classifier.js +24 -29
  16. package/lib/natural/classifiers/classifier.js +136 -121
  17. package/lib/natural/classifiers/logistic_regression_classifier.js +33 -37
  18. package/lib/natural/classifiers/maxent/Classifier.js +81 -79
  19. package/lib/natural/classifiers/maxent/Context.js +11 -9
  20. package/lib/natural/classifiers/maxent/Distribution.js +107 -105
  21. package/lib/natural/classifiers/maxent/Element.js +12 -10
  22. package/lib/natural/classifiers/maxent/Feature.js +56 -54
  23. package/lib/natural/classifiers/maxent/FeatureSet.js +40 -38
  24. package/lib/natural/classifiers/maxent/GISScaler.js +110 -109
  25. package/lib/natural/classifiers/maxent/POS/ME_Corpus.js +26 -31
  26. package/lib/natural/classifiers/maxent/POS/ME_Sentence.js +37 -42
  27. package/lib/natural/classifiers/maxent/POS/POS_Element.js +119 -124
  28. package/lib/natural/classifiers/maxent/Sample.js +96 -94
  29. package/lib/natural/classifiers/maxent/SimpleExample/SE_Element.js +14 -20
  30. package/lib/natural/inflectors/fr/count_inflector.js +1 -1
  31. package/lib/natural/inflectors/fr/noun_inflector.js +179 -196
  32. package/lib/natural/inflectors/ja/noun_inflector.js +67 -84
  33. package/lib/natural/inflectors/noun_inflector.js +124 -139
  34. package/lib/natural/inflectors/present_verb_inflector.js +34 -48
  35. package/lib/natural/inflectors/singular_plural_inflector.js +62 -61
  36. package/lib/natural/tfidf/tfidf.js +118 -114
  37. package/lib/natural/trie/trie.js +161 -159
  38. package/lib/natural/util/directed_edge.js +49 -0
  39. package/lib/natural/util/edge_weighted_digraph.js +54 -74
  40. package/lib/natural/util/index.js +1 -0
  41. package/lib/natural/util/longest_path_tree.js +54 -52
  42. package/lib/natural/util/shortest_path_tree.js +56 -54
  43. package/lib/natural/util/topological.js +17 -15
  44. package/package.json +1 -1
@@ -26,165 +26,167 @@ const JSON = 2
26
26
  // sentences: an array of annotated sentences
27
27
  // A sentence is an array of annotated tokens
28
28
  // A token is an object with (token, tag, testTag, ruleList)
29
- function Corpus (data, typeOfCorpus, SentenceClass) {
30
- this.wordCount = 0
31
- this.sentences = []
32
- const that = this
33
- if (data) {
34
- // For other types of corpora add a case here and supply a parsing method
35
- switch (typeOfCorpus) {
36
- case BROWN:
37
- this.parseBrownCorpus(data, SentenceClass)
38
- break
39
- case JSON:
40
- // Assume it is a JSON object of a corpus
41
- data.sentences.forEach(function (s) {
42
- const taggedSentence = new SentenceClass(s.taggedWords)
43
- that.sentences.push(taggedSentence)
44
- that.wordCount += s.taggedWords.length
45
- })
46
- break
29
+ class Corpus {
30
+ constructor (data, typeOfCorpus, SentenceClass) {
31
+ this.wordCount = 0
32
+ this.sentences = []
33
+ const that = this
34
+ if (data) {
35
+ // For other types of corpora add a case here and supply a parsing method
36
+ switch (typeOfCorpus) {
37
+ case BROWN:
38
+ this.parseBrownCorpus(data, SentenceClass)
39
+ break
40
+ case JSON:
41
+ // Assume it is a JSON object of a corpus
42
+ data.sentences.forEach(function (s) {
43
+ const taggedSentence = new SentenceClass(s.taggedWords)
44
+ that.sentences.push(taggedSentence)
45
+ that.wordCount += s.taggedWords.length
46
+ })
47
+ break
48
+ }
47
49
  }
48
50
  }
49
- }
50
-
51
- // data is raw text
52
- // A corpus parsing method should split the corpus in sentences each of which
53
- // consist of an array of tokens.
54
- Corpus.prototype.parseBrownCorpus = function (data, SentenceClass) {
55
- const that = this
56
-
57
- const lines = data.split('\n')
58
- lines.forEach(function (line) {
59
- const trimmedLine = line.trim()
60
- // Only parse lines that contain characters
61
- if (trimmedLine !== '') {
62
- const taggedSentence = new SentenceClass()
63
- const tokens = line.trim().split(/\s+/)
64
- tokens.forEach(function (token) {
65
- that.wordCount++
66
- // Create a tagged sentences consisting of tokens
67
- const wordPlusTag = token.split('_')
68
- taggedSentence.addTaggedWord(wordPlusTag[0], wordPlusTag[1])
69
- })
70
51
 
71
- // Add the sentence to the corpus
72
- that.sentences.push(taggedSentence)
73
- }
74
- })
75
- }
52
+ // data is raw text
53
+ // A corpus parsing method should split the corpus in sentences each of which
54
+ // consist of an array of tokens.
55
+ parseBrownCorpus (data, SentenceClass) {
56
+ const that = this
57
+
58
+ const lines = data.split('\n')
59
+ lines.forEach(function (line) {
60
+ const trimmedLine = line.trim()
61
+ // Only parse lines that contain characters
62
+ if (trimmedLine !== '') {
63
+ const taggedSentence = new SentenceClass()
64
+ const tokens = line.trim().split(/\s+/)
65
+ tokens.forEach(function (token) {
66
+ that.wordCount++
67
+ // Create a tagged sentences consisting of tokens
68
+ const wordPlusTag = token.split('_')
69
+ taggedSentence.addTaggedWord(wordPlusTag[0], wordPlusTag[1])
70
+ })
76
71
 
77
- // Returns an array of all POS tags used in the corpus
78
- Corpus.prototype.getTags = function () {
79
- return Object.keys(this.posTags)
80
- }
72
+ // Add the sentence to the corpus
73
+ that.sentences.push(taggedSentence)
74
+ }
75
+ })
76
+ }
81
77
 
82
- // Splits the corpus in a training and testing set.
83
- // percentageTrain is the size of the training corpus in percent
84
- // Returns an array with two elements: training corpus, testing corpus
85
- Corpus.prototype.splitInTrainAndTest = function (percentageTrain) {
86
- const corpusTrain = new Corpus()
87
- const corpusTest = new Corpus()
88
-
89
- const p = percentageTrain / 100
90
- this.sentences.forEach(function (sentence, i) {
91
- if (Math.random() < p) {
92
- corpusTrain.sentences.push(sentence)
93
- } else {
94
- corpusTest.sentences.push(sentence)
95
- }
96
- })
97
- return [corpusTrain, corpusTest]
98
- }
78
+ // Returns an array of all POS tags used in the corpus
79
+ getTags () {
80
+ return Object.keys(this.posTags)
81
+ }
99
82
 
100
- // Analyses the corpus:
101
- // - registers used POS tags
102
- // - records the frequency of POS tag for each word
103
- Corpus.prototype.analyse = function () {
104
- this.tagFrequencies = {}
105
- this.posTags = {}
106
- this.wordCount = 0
107
-
108
- const that = this
109
- this.sentences.forEach(function (sentence) {
110
- sentence.taggedWords.forEach(function (token) {
111
- that.wordCount++
112
-
113
- // Register the tags used in the corpus
114
- that.posTags[token.tag] = true
115
-
116
- // Register the frequency of the tag
117
- if (!that.tagFrequencies[token.token]) {
118
- that.tagFrequencies[token.token] = {}
119
- }
120
- if (!that.tagFrequencies[token.token][token.tag]) {
121
- that.tagFrequencies[token.token][token.tag] = 0
83
+ // Splits the corpus in a training and testing set.
84
+ // percentageTrain is the size of the training corpus in percent
85
+ // Returns an array with two elements: training corpus, testing corpus
86
+ splitInTrainAndTest (percentageTrain) {
87
+ const corpusTrain = new Corpus()
88
+ const corpusTest = new Corpus()
89
+
90
+ const p = percentageTrain / 100
91
+ this.sentences.forEach(function (sentence, i) {
92
+ if (Math.random() < p) {
93
+ corpusTrain.sentences.push(sentence)
94
+ } else {
95
+ corpusTest.sentences.push(sentence)
122
96
  }
123
- that.tagFrequencies[token.token][token.tag]++
124
97
  })
125
- })
126
- }
98
+ return [corpusTrain, corpusTest]
99
+ }
127
100
 
128
- // Creates a lexicon by taking the most frequently occurring tag of a word
129
- // as the right tag
130
- Corpus.prototype.buildLexicon = function () {
131
- const lexicon = new Lexicon()
132
- const that = this
101
+ // Analyses the corpus:
102
+ // - registers used POS tags
103
+ // - records the frequency of POS tag for each word
104
+ analyse () {
105
+ this.tagFrequencies = {}
106
+ this.posTags = {}
107
+ this.wordCount = 0
108
+
109
+ const that = this
110
+ this.sentences.forEach(function (sentence) {
111
+ sentence.taggedWords.forEach(function (token) {
112
+ that.wordCount++
133
113
 
134
- this.analyse()
135
- Object.keys(this.tagFrequencies).forEach(function (token) {
136
- const catToFreq = that.tagFrequencies[token]
137
- const categories = Object.keys(catToFreq)
114
+ // Register the tags used in the corpus
115
+ that.posTags[token.tag] = true
138
116
 
139
- function compareByFrequency (a, b) {
140
- if (catToFreq[a] > catToFreq[b]) {
141
- return -1
142
- } else {
143
- if (catToFreq[a] < catToFreq[b]) {
144
- return 1
117
+ // Register the frequency of the tag
118
+ if (!that.tagFrequencies[token.token]) {
119
+ that.tagFrequencies[token.token] = {}
120
+ }
121
+ if (!that.tagFrequencies[token.token][token.tag]) {
122
+ that.tagFrequencies[token.token][token.tag] = 0
123
+ }
124
+ that.tagFrequencies[token.token][token.tag]++
125
+ })
126
+ })
127
+ }
128
+
129
+ // Creates a lexicon by taking the most frequently occurring tag of a word
130
+ // as the right tag
131
+ buildLexicon () {
132
+ const lexicon = new Lexicon()
133
+ const that = this
134
+
135
+ this.analyse()
136
+ Object.keys(this.tagFrequencies).forEach(function (token) {
137
+ const catToFreq = that.tagFrequencies[token]
138
+ const categories = Object.keys(catToFreq)
139
+
140
+ function compareByFrequency (a, b) {
141
+ if (catToFreq[a] > catToFreq[b]) {
142
+ return -1
145
143
  } else {
146
- return 0
144
+ if (catToFreq[a] < catToFreq[b]) {
145
+ return 1
146
+ } else {
147
+ return 0
148
+ }
147
149
  }
148
150
  }
149
- }
150
151
 
151
- const sortedCategories = categories.sort(compareByFrequency)
152
- lexicon.addWord(token, sortedCategories)
153
- })
154
- return lexicon
155
- }
152
+ const sortedCategories = categories.sort(compareByFrequency)
153
+ lexicon.addWord(token, sortedCategories)
154
+ })
155
+ return lexicon
156
+ }
156
157
 
157
- Corpus.prototype.tag = function (lexicon) {
158
- this.sentences.forEach(function (sentence) {
159
- sentence.taggedWords.forEach(function (token) {
160
- // tagWord returns a list of categories, take the first category
161
- token.testTag = lexicon.tagWord(token.token)[0]
158
+ tag (lexicon) {
159
+ this.sentences.forEach(function (sentence) {
160
+ sentence.taggedWords.forEach(function (token) {
161
+ // tagWord returns a list of categories, take the first category
162
+ token.testTag = lexicon.tagWord(token.token)[0]
163
+ })
162
164
  })
163
- })
164
- }
165
+ }
165
166
 
166
- Corpus.prototype.nrSentences = function () {
167
- return this.sentences.length
168
- }
167
+ nrSentences () {
168
+ return this.sentences.length
169
+ }
169
170
 
170
- Corpus.prototype.nrWords = function () {
171
- return this.wordCount
172
- }
171
+ nrWords () {
172
+ return this.wordCount
173
+ }
173
174
 
174
- Corpus.prototype.generateFeatures = function () {
175
- let features = []
176
- this.sentences.forEach(function (sentence) {
177
- features = sentence.generateFeatures(features)
178
- })
179
- // console.log(JSON.stringify(features));
180
- return features
181
- }
175
+ generateFeatures () {
176
+ let features = []
177
+ this.sentences.forEach(function (sentence) {
178
+ features = sentence.generateFeatures(features)
179
+ })
180
+ // console.log(JSON.stringify(features));
181
+ return features
182
+ }
182
183
 
183
- Corpus.prototype.prettyPrint = function () {
184
- this.sentences.forEach(function (sentence, index) {
185
- // logger.debug("sentence no " + index + "\n" +
186
- // JSON.stringify(sentence, null, 2));
187
- })
184
+ prettyPrint () {
185
+ this.sentences.forEach(function (sentence, index) {
186
+ // logger.debug("sentence no " + index + "\n" +
187
+ // JSON.stringify(sentence, null, 2));
188
+ })
189
+ }
188
190
  }
189
191
 
190
192
  module.exports = Corpus
@@ -23,97 +23,99 @@ const dutchLexicon = require('../data/Dutch/brill_Lexicon.json')
23
23
 
24
24
  const DEBUG = false
25
25
 
26
- // Constructor creates a Lexicon for language
27
- function Lexicon (language, defaultCategory, defaultCategoryCapitalised, extendedLexicon) {
28
- const lexicon = (() => {
29
- switch (language) {
30
- case 'EN':
31
- return englishLexicon
32
- case 'DU':
33
- return dutchLexicon
34
- default:
35
- return dutchLexicon
26
+ class Lexicon {
27
+ // Constructor creates a Lexicon for language
28
+ constructor (language, defaultCategory, defaultCategoryCapitalised, extendedLexicon) {
29
+ const lexicon = (() => {
30
+ switch (language) {
31
+ case 'EN':
32
+ return englishLexicon
33
+ case 'DU':
34
+ return dutchLexicon
35
+ default:
36
+ return dutchLexicon
37
+ }
38
+ })()
39
+
40
+ this.lexicon = Object.assign(lexicon, extendedLexicon || {})
41
+
42
+ if (defaultCategory) {
43
+ this.defaultCategory = defaultCategory
44
+ if (defaultCategoryCapitalised) {
45
+ this.defaultCategoryCapitalised = defaultCategoryCapitalised
46
+ }
36
47
  }
37
- })()
48
+ }
38
49
 
39
- this.lexicon = Object.assign(lexicon, extendedLexicon || {})
50
+ // Parses a lexicon in text format: word cat1 cat2 ... catn
51
+ parseLexicon (data) {
52
+ // Split into an array of non-empty lines
53
+ const arrayOfLines = data.match(/[^\r\n]+/g)
54
+ this.lexicon = {} // Object.create(null);
55
+ const that = this
56
+ arrayOfLines.forEach(function (line) {
57
+ // Split line by whitespace
58
+ const elements = line.trim().split(/\s+/)
59
+ if (elements.length > 0) {
60
+ that.lexicon[elements[0]] = elements.slice(1)
61
+ }
62
+ })
63
+ }
40
64
 
41
- if (defaultCategory) {
42
- this.defaultCategory = defaultCategory
43
- if (defaultCategoryCapitalised) {
44
- this.defaultCategoryCapitalised = defaultCategoryCapitalised
65
+ tagWordWithDefaults (word) {
66
+ if (/[A-Z]/.test(word[0]) && this.defaultCategoryCapitalised) {
67
+ // Capitalised
68
+ return this.defaultCategoryCapitalised
69
+ } else {
70
+ // If not found assign default_category
71
+ return this.defaultCategory
45
72
  }
46
73
  }
47
- }
48
74
 
49
- // Parses a lexicon in text format: word cat1 cat2 ... catn
50
- Lexicon.prototype.parseLexicon = function (data) {
51
- // Split into an array of non-empty lines
52
- const arrayOfLines = data.match(/[^\r\n]+/g)
53
- this.lexicon = {} // Object.create(null);
54
- const that = this
55
- arrayOfLines.forEach(function (line) {
56
- // Split line by whitespace
57
- const elements = line.trim().split(/\s+/)
58
- if (elements.length > 0) {
59
- that.lexicon[elements[0]] = elements.slice(1)
75
+ // Returns a list of categories for word
76
+ tagWord (word) {
77
+ let categories = this.lexicon[word]
78
+ DEBUG && console.log(categories)
79
+ if (!categories || (typeof categories === 'function')) {
80
+ categories = this.lexicon[word.toLowerCase()]
60
81
  }
61
- })
62
- }
63
-
64
- Lexicon.prototype.tagWordWithDefaults = function (word) {
65
- if (/[A-Z]/.test(word[0]) && this.defaultCategoryCapitalised) {
66
- // Capitalised
67
- return this.defaultCategoryCapitalised
68
- } else {
69
- // If not found assign default_category
70
- return this.defaultCategory
82
+ if (!categories || (typeof categories === 'function')) {
83
+ categories = [this.tagWordWithDefaults(word)]
84
+ }
85
+ return (categories)
71
86
  }
72
- }
73
87
 
74
- // Returns a list of categories for word
75
- Lexicon.prototype.tagWord = function (word) {
76
- let categories = this.lexicon[word]
77
- DEBUG && console.log(categories)
78
- if (!categories || (typeof categories === 'function')) {
79
- categories = this.lexicon[word.toLowerCase()]
88
+ // Adds a word to the lexicon. NB simply replaces the entry
89
+ addWord (word, categories) {
90
+ this.lexicon[word] = categories
80
91
  }
81
- if (!categories || (typeof categories === 'function')) {
82
- categories = [this.tagWordWithDefaults(word)]
83
- }
84
- return (categories)
85
- }
86
92
 
87
- // Adds a word to the lexicon. NB simply replaces the entry
88
- Lexicon.prototype.addWord = function (word, categories) {
89
- this.lexicon[word] = categories
90
- }
91
-
92
- Lexicon.prototype.prettyPrint = function () {
93
- let result = ''
94
- const that = this
95
- Object.keys(this.lexicon).forEach(function (token) {
96
- result += token + '\t'
97
- that.lexicon[token].forEach(function (cat) {
98
- result += cat + '\t'
93
+ prettyPrint () {
94
+ let result = ''
95
+ const that = this
96
+ Object.keys(this.lexicon).forEach(function (token) {
97
+ result += token + '\t'
98
+ that.lexicon[token].forEach(function (cat) {
99
+ result += cat + '\t'
100
+ })
101
+ result += '\n'
99
102
  })
100
- result += '\n'
101
- })
102
- return result
103
- }
103
+ return result
104
+ }
104
105
 
105
- Lexicon.prototype.nrEntries = function () {
106
- return Object.keys(this.lexicon).length
107
- }
106
+ nrEntries () {
107
+ return Object.keys(this.lexicon).length
108
+ }
108
109
 
109
- Lexicon.prototype.size = function () {
110
- return this.nrEntries()
111
- }
110
+ size () {
111
+ return this.nrEntries()
112
+ }
112
113
 
113
- Lexicon.prototype.setDefaultCategories = function (category, categoryCapitalised) {
114
- this.defaultCategory = category
115
- if (categoryCapitalised) {
116
- this.defaultCategoryCapitalised = categoryCapitalised
114
+ setDefaultCategories (category, categoryCapitalised) {
115
+ this.defaultCategory = category
116
+ if (categoryCapitalised) {
117
+ this.defaultCategoryCapitalised = categoryCapitalised
118
+ }
117
119
  }
118
120
  }
119
121
 
@@ -23,25 +23,27 @@ const DEBUG = false
23
23
  const predicates = require('./RuleTemplates')
24
24
  DEBUG && console.log('RuleSet loaded predicates: ' + predicates)
25
25
 
26
- function Predicate (name, parameter1, parameter2) {
27
- this.name = name
28
- this.meta = predicates[name]
29
- if (!this.meta) {
30
- this.meta = predicates.DEFAULT
26
+ class Predicate {
27
+ constructor (name, parameter1, parameter2) {
28
+ this.name = name
29
+ this.meta = predicates[name]
30
+ if (!this.meta) {
31
+ this.meta = predicates.DEFAULT
32
+ }
33
+ // if (this.meta.nrParameters > 0) {
34
+ this.parameter1 = parameter1
35
+ // }
36
+ // if (this.meta.nrParameters > 1) {
37
+ this.parameter2 = parameter2
38
+ // }
39
+ DEBUG && console.log('Predicate\n' + JSON.toString(this.meta, null, 2))
31
40
  }
32
- // if (this.meta.nrParameters > 0) {
33
- this.parameter1 = parameter1
34
- // }
35
- // if (this.meta.nrParameters > 1) {
36
- this.parameter2 = parameter2
37
- // }
38
- DEBUG && console.log('Predicate\n' + JSON.toString(this.meta, null, 2))
39
- }
40
41
 
41
- Predicate.prototype.evaluate = function (sentence, position) {
42
- DEBUG && console.log('Predicate.evalute: ' + this.name)
43
- const predicate = this.meta.function
44
- return (predicate(sentence, position, this.parameter1, this.parameter2))
42
+ evaluate (sentence, position) {
43
+ DEBUG && console.log('Predicate.evalute: ' + this.name)
44
+ const predicate = this.meta.function
45
+ return (predicate(sentence, position, this.parameter1, this.parameter2))
46
+ }
45
47
  }
46
48
 
47
49
  module.exports = Predicate
@@ -25,72 +25,74 @@ const englishRuleSet = require('../data/English/tr_from_posjs.json')
25
25
 
26
26
  const DEBUG = false
27
27
 
28
- // Constructor takes a language abbreviation and loads the right rule set
29
- function RuleSet (language) {
30
- let data = englishRuleSet
31
- DEBUG && console.log(data)
32
- switch (language) {
33
- case 'EN':
34
- data = englishRuleSet
35
- break
36
- case 'DU':
37
- data = dutchRuleSet
38
- break
28
+ class RuleSet {
29
+ // Constructor takes a language abbreviation and loads the right rule set
30
+ constructor (language) {
31
+ let data = englishRuleSet
32
+ DEBUG && console.log(data)
33
+ switch (language) {
34
+ case 'EN':
35
+ data = englishRuleSet
36
+ break
37
+ case 'DU':
38
+ data = dutchRuleSet
39
+ break
40
+ }
41
+ if (data.rules) {
42
+ this.rules = {}
43
+ const that = this
44
+ data.rules.forEach(function (ruleString) {
45
+ that.addRule(TFParser.parse(ruleString))
46
+ })
47
+ }
48
+ DEBUG && console.log(this.rules)
49
+ DEBUG && console.log('Brill_POS_Tagger.read_transformation_rules: number of transformation rules read: ' + Object.keys(this.rules).length)
39
50
  }
40
- if (data.rules) {
41
- this.rules = {}
42
- const that = this
43
- data.rules.forEach(function (ruleString) {
44
- that.addRule(TFParser.parse(ruleString))
45
- })
46
- }
47
- DEBUG && console.log(this.rules)
48
- DEBUG && console.log('Brill_POS_Tagger.read_transformation_rules: number of transformation rules read: ' + Object.keys(this.rules).length)
49
- }
50
51
 
51
- RuleSet.prototype.addRule = function (rule) {
52
- // this.rules.push(rule);
53
- if (!this.rules[rule.key()]) {
54
- this.rules[rule.key()] = rule
55
- return true
56
- } else {
57
- return false
52
+ addRule (rule) {
53
+ // this.rules.push(rule);
54
+ if (!this.rules[rule.key()]) {
55
+ this.rules[rule.key()] = rule
56
+ return true
57
+ } else {
58
+ return false
59
+ }
58
60
  }
59
- }
60
61
 
61
- RuleSet.prototype.removeRule = function (rule) {
62
- if (this.rules[rule.key()]) {
63
- delete this.rules[rule.key()]
62
+ removeRule (rule) {
63
+ if (this.rules[rule.key()]) {
64
+ delete this.rules[rule.key()]
65
+ }
64
66
  }
65
- }
66
67
 
67
- RuleSet.prototype.getRules = function () {
68
- const that = this
69
- return Object.keys(this.rules).map(function (key) {
70
- return that.rules[key]
71
- })
72
- }
68
+ getRules () {
69
+ const that = this
70
+ return Object.keys(this.rules).map(function (key) {
71
+ return that.rules[key]
72
+ })
73
+ }
73
74
 
74
- RuleSet.prototype.nrRules = function () {
75
- return Object.keys(this.rules).length
76
- }
75
+ nrRules () {
76
+ return Object.keys(this.rules).length
77
+ }
77
78
 
78
- RuleSet.prototype.hasRule = function (rule) {
79
- if (this.rules[rule.key()]) {
80
- return true
81
- } else {
82
- return false
79
+ hasRule (rule) {
80
+ if (this.rules[rule.key()]) {
81
+ return true
82
+ } else {
83
+ return false
84
+ }
83
85
  }
84
- }
85
86
 
86
- RuleSet.prototype.prettyPrint = function () {
87
- let result = ''
88
- const that = this
89
- Object.keys(this.rules).forEach(function (key) {
90
- const rule = that.rules[key]
91
- result += rule.prettyPrint() + '\n'
92
- })
93
- return result
87
+ prettyPrint () {
88
+ let result = ''
89
+ const that = this
90
+ Object.keys(this.rules).forEach(function (key) {
91
+ const rule = that.rules[key]
92
+ result += rule.prettyPrint() + '\n'
93
+ })
94
+ return result
95
+ }
94
96
  }
95
97
 
96
98
  module.exports = RuleSet