diff --git a/license b/license index c166f3e..0934990 100644 --- a/license +++ b/license @@ -632,7 +632,7 @@ state the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Moodle test solver userscript webserver - Copyright (C) + Copyright (C) 2019 mrfry This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -653,7 +653,7 @@ Also add information on how to contact you by electronic and paper mail. notice like this when it starts in an interactive mode: - Moodle test solver userscript webserver Copyright (C) 2019 YourFriendlyNeighborhoodDealer + Moodle test solver userscript webserver Copyright (C) 2019 MrFry This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. diff --git a/server.js b/server.js index 67fdd25..2cf1e52 100644 --- a/server.js +++ b/server.js @@ -26,9 +26,9 @@ const express = require('express') const vhost = require('vhost') const logger = require('./utils/logger.js') const utils = require('./utils/utils.js') -const fs = require('fs'); -const http = require('http'); -const https = require('https'); +const fs = require('fs') +const http = require('http') +const https = require('https') const stat = require('./utils/stat.js') stat.Load() @@ -115,11 +115,11 @@ app.use(vhost('www.qmining.tk', old)) logger.Log('Node version: ' + process.version) logger.Log('Listening on port: ' + port) -const httpServer = http.createServer(app); -httpServer.listen(port); +const httpServer = http.createServer(app) +httpServer.listen(port) if (certsLoaded) { - const httpsServer = https.createServer(certs, app); - httpsServer.listen(httpsport); + const httpsServer = https.createServer(certs, app) + httpsServer.listen(httpsport) logger.Log('Listening on port: ' + httpsport + ' (https)') } else { logger.Log('Https not avaible') diff --git a/utils/actions.js b/utils/actions.js index dd75f52..dd59c18 100644 --- a/utils/actions.js +++ b/utils/actions.js @@ -34,182 +34,7 @@ const qaFile = './public/qa' var logger = require('../utils/logger.js') var utils = require('../utils/utils.js') - -class Question { - constructor (q, a, i) { - this.Q = q - this.A = a - this.I = i - } - toString () { - var r = '?' + this.Q + '\n!' + this.A - if (this.I) { r += '\n>' + this.I } - return r - } - HasQuestion () { - return this.Q !== undefined - } - HasAnswer () { - return this.A !== undefined - } - HasImage () { - return this.I !== undefined - } - IsComplete () { - return this.HasQuestion() && this.HasAnswer() - } - Compare (q2, i) { - if (typeof q2 === 'string') { - var qmatchpercent = Question.CompareString(this.Q, q2) - - if (i == undefined || i.length == 0) { return qmatchpercent } else { - if (this.HasImage()) { - const imatchpercent = this.HasImage() ? Question.CompareString(this.I.join(' '), i.join(' ')) - : 0 - return (qmatchpercent + imatchpercent) / 2 - } else { - qmatchpercent -= 30 - if (qmatchpercent < 0) { return 0 } else { return qmatchpercent } - } - } - } else { - const qmatchpercent = Question.CompareString(this.Q, q2.Q) - const amatchpercent = Question.CompareString(this.A, q2.A) - if (this.I !== undefined) { - const imatchpercent = this.I === undefined ? Question.CompareString(this.I.join(' '), q2.I.join( - ' ')) : 0 - return (qmatchpercent + amatchpercent + imatchpercent) / 3 - } else { - return (qmatchpercent + amatchpercent) / 2 - } - } - } - - // static CompareString (s1, s2) { - // // if (s1 == undefined || s2 == undefined) - // // return 0; - // s1 = SimplifyStringForComparison(s1).split(' ') - // s2 = SimplifyStringForComparison(s2).split(' ') - // var match = 0 - // for (var i = 0; i < s1.length; i++) { - // if (s2.includes(s1[i])) { match++ } - // } - // var percent = Math.round(((match / s1.length) * 100).toFixed(2)) // matched words percent - // var lengthDifference = Math.abs(s2.length - s1.length) - // percent -= lengthDifference * 3 - // if (percent < 0) { percent = 0 } - // return percent - // } -} - -class Subject { - constructor (n) { - this.Name = n - this.Questions = [] - } - get length () { - return this.Questions.length - } - AddQuestion (q) { - this.Questions.push(q) - } - Search (q, img) { - const minMatchAmmount = 90 - var r = [] - for (let i = 0; i < this.length; i++) { - let percent = this.Questions[i].Compare(q, img) - if (percent > minMatchAmmount) { - r.push({ - q: this.Questions[i], - match: percent - }) - } - } - - for (let i = 0; i < r.length; i++) { - for (var j = i; j < r.length; j++) { - if (r[i].match < r[j].match) { - var tmp = r[i] - r[i] = r[j] - r[j] = tmp - } - } - } - - return r - } - toString () { - var r = [] - for (var i = 0; i < this.Questions.length; i++) { r.push(this.Questions[i].toString()) } - return '+' + this.Name + '\n' + r.join('\n') - } -} - -class QuestionDB { - constructor () { - this.Subjects = [] - } - get length () { - return this.Subjects.length - } - // get activeIndexes () { - // var r = [] - // for (var i = 0; i < this.length; i++) { - // if (GM_getValue('Is' + i + 'Active')) { - // r.push(i) - // } - // } - // return r - // } - // GetIfActive (ind) { - // return GM_getValue('Is' + ind + 'Active') - // } - // ChangeActive (i, value) { - // GM_setValue('Is' + i + 'Active', !!value) - // } - AddQuestion (subj, q) { - var i = 0 - while (i < this.Subjects.length && this.Subjects[i].Name !== subj) { i++ } - if (i < this.Subjects.length) { this.Subjects[i].AddQuestion(q) } else { - const n = new Subject(subj) - n.AddQuestion(q) - this.Subjects.push(n) - } - } - Search (q, img) { - var r = [] - for (let i = 0; i < this.length; i++) { - if (this.GetIfActive(i)) { r = r.concat(this.Subjects[i].Search(q, img)) } - } - - for (let i = 0; i < r.length; i++) { - for (var j = i; j < r.length; j++) { - if (r[i].match < r[j].match) { - var tmp = r[i] - r[i] = r[j] - r[j] = tmp - } - } - } - - return r - } - AddSubject (subj) { - var i = 0 - while (i < this.length && subj.Name !== this.Subjects[i].Name) { i++ } - - if (i < this.length) { - this.Subjects.concat(subj.Questions) - } else { - this.Subjects.push(subj) - } - } - toString () { - var r = [] - for (var i = 0; i < this.Subjects.length; i++) { r.push(this.Subjects[i].toString()) } - return r.join('\n\n') - } -} +const classes = require('./classes.js') function Process (d, file) { try { @@ -260,11 +85,11 @@ function ProcessIncomingRequest (data) { data = LoadJSON(dfile) var allQuestions = [] for (let i = 0; i < d.allData.length; i++) { - allQuestions.push(new Question(d.allData[i].Q, d.allData[i].A, d.allData[i].I)) + allQuestions.push(new classes.Question(d.allData[i].Q, d.allData[i].A, d.allData[i].I)) } var questions = [] for (let i = 0; i < d.data.length; i++) { - let q = new Question(d.data[i].Q, d.data[i].A, d.data[i].I) + let q = new classes.Question(d.data[i].Q, d.data[i].A, d.data[i].I) questions.push(q) data.AddQuestion(d.subj, q) } @@ -328,7 +153,7 @@ function SetupData (data) { var pdata = data.split('<#>') if (pdata.length <= 0) { logger.Log('Data length is zero !', logger.GetColor('redbg')) - throw 'No data recieved!' + throw new Error('No data recieved!') } var d = {} // parsed data @@ -336,7 +161,7 @@ function SetupData (data) { var td = pdata[i].split('<=>') if (td.length === 2) { d[td[0]] = td[1] } else { logger.Log('Invalid parameter!', logger.GetColor('redbg')) - throw 'Invalid parameter recieved!' + throw new Error('Invalid parameter recieved!') } } return d @@ -358,9 +183,9 @@ function CheckData (data) { function NLoad (resource) { var resultLog = [] var allCount = 0 - if (resource === undefined) { throw 'A megadott adat undefined!' } + if (resource === undefined) { throw new Error('A megadott adat undefined!') } resource = resource.split('\n') // splitting by enters - if (resource.length === 1) { throw 'A megadott adat nem sorokból áll!' } + if (resource.length === 1) { throw new Error('A megadott adat nem sorokból áll!') } var data = [] // initializing data declared at the begining function AddNewSubj (name) { @@ -372,15 +197,13 @@ function NLoad (resource) { // setting if its active only if its undefined, otherwise previous user setting shouldt be overwritten } - function AddItem () // adds an item to the last subjects questions - { + function AddItem () { // adds an item to the last subjects questions GetCurrSubj().count++ allCount++ // incrementing all count GetCurrSubj().questions.push({}) // adding a new empty object to the last item in the data } - function GetLastItem () // returns the last item of the last item of data - { + function GetLastItem () { // returns the last item of the last item of data var q = GetCurrSubj().questions.length // questions length return GetCurrSubj().questions[q - 1] } @@ -395,45 +218,37 @@ function NLoad (resource) { // + : subject name // checking for name - for (var j = 0; j < resource.length; j++) // goes through resources - { - if (resource[j][0] == '+') // if there is a name identifier - { + for (var j = 0; j < resource.length; j++) { // goes through resources + if (resource[j][0] === '+') { // if there is a name identifier break // breaks, couse there will be a name } - if (resource[j][0] == '?' || resource[j][0] == '!' || resource[j][0] == '>') // if it begins with another identifier: - { + if (resource[j][0] === '?' || resource[j][0] === '!' || resource[j][0] === '>') { // if it begins with another identifier: AddNewSubj('NONAME') // there is no name (for the first question at least), so setting it noname. break } // else it does nothing, continues to check } var jumped = 0 // the amount of lines it processed - for (var i = 0; i < resource.length; i += jumped) // gouing through the resource - { + for (var i = 0; i < resource.length; i += jumped) { // gouing through the resource jumped = 0 // resetting it to 0 var currRawDataQ = resource[i] // current question var currRawDataA = resource[i + 1] // current answer var currRawDataI = resource[i + 2] // current image - if (currRawDataQ != undefined && currRawDataQ[0] == '?' && currRawDataA != undefined && - currRawDataA[0] == '!') // if the current line is ? and the next is ! its a data - { + if (currRawDataQ !== undefined && currRawDataQ[0] === '?' && currRawDataA !== undefined && currRawDataA[0] === '!') { // if the current line is ? and the next is ! its a data AddItem() GetLastItem().q = currRawDataQ.substr(1) GetLastItem().a = currRawDataA.substr(1) jumped += 2 - if (currRawDataI != undefined && currRawDataI[0] == '>') { + if (currRawDataI !== undefined && currRawDataI[0] === '>') { GetLastItem().i = currRawDataI.substr(1) jumped++ } - } else if (currRawDataQ[0] == '+') // if its a new subject - { + } else if (currRawDataQ[0] === '+') { // if its a new subject AddNewSubj(currRawDataQ.substr(1)) jumped++ } else { // this should be invalid question order - resultLog.push('Warning @ line ' + i + ':' + currRawDataQ + ' ' + currRawDataA + ' ' + - currRawDataI) + resultLog.push('Warning @ line ' + i + ':' + currRawDataQ + ' ' + currRawDataA + ' ' + currRawDataI) jumped++ } } // end of parsing all data @@ -445,25 +260,22 @@ function NLoad (resource) { // loading stuff function LoadJSON (resource) { - var count = -1 try { - var d = JSON.parse(resource) - var r = new QuestionDB() + var d = JSON.parse(resource) + var r = new classes.QuestionDB((x) => true, (x, y) => console.log(x, y)) var rt = [] - var allCount = -1 for (var i = 0; i < d.Subjects.length; i++) { - let s = new Subject(d.Subjects[i].Name) + let s = new classes.Subject(d.Subjects[i].Name) var j = 0 for (j = 0; j < d.Subjects[i].Questions.length; j++) { var currQ = d.Subjects[i].Questions[j] - s.AddQuestion(new Question(currQ.Q, currQ.A, currQ.I)) + s.AddQuestion(new classes.Question(currQ.Q, currQ.A, currQ.I)) } rt.push({ name: d.Subjects[i].Name, count: j }) - allCount += j r.AddSubject(s) } return r @@ -479,13 +291,13 @@ function ProcessQA () { let r = [] let ind = 0 for (let i = 0; i < a.length; i++) { - if (a[i] == '#') { ind++ } else { - if (r[ind] == undefined) { r[ind] = {} } + if (a[i] === '#') { ind++ } else { + if (r[ind] === undefined) { r[ind] = {} } - if (r[ind].q == undefined) { + if (r[ind].q === undefined) { r[ind].q = a[i] } else { - if (r[ind].a == undefined) { r[ind].a = [] } + if (r[ind].a === undefined) { r[ind].a = [] } r[ind].a.push(a[i]) } diff --git a/utils/classes.js b/utils/classes.js new file mode 100644 index 0000000..682beae --- /dev/null +++ b/utils/classes.js @@ -0,0 +1,404 @@ +const commonUselessAnswerParts = [ + 'A helyes válasz az ', + 'A helyes válasz a ', + 'A helyes válaszok: ', + 'A helyes válaszok:', + 'A helyes válasz: ', + 'A helyes válasz:', + 'The correct answer is:', + '\'' +] +const commonUselessStringParts = [',', '\\.', ':', '!'] +const lengthDiffMultiplier = 10 /* Percent minus for length difference */ +const minMatchAmmount = 60 /* Minimum ammount to consider that two questions match during answering */ + +const assert = (val) => { + if (!val) { throw new Error('Assertion failed') } +} + +class StringUtils { + RemoveStuff (value, removableStrings) { + removableStrings.forEach((x) => { + var regex = new RegExp(x, 'g') + value = value.replace(regex, '') + }) + return value + } + + SimplifyQuery (q) { + assert(q) + + var result = q.replace(/\n/g, ' ').replace(/\s/g, ' ') + return this.RemoveUnnecesarySpaces(result) + } + + ShortenString (toShorten, ammount) { + assert(toShorten) + + var result = '' + var i = 0 + while (i < toShorten.length && i < ammount) { + result += toShorten[i] + i++ + } + return result + } + + ReplaceCharsWithSpace (val, char) { + assert(val) + assert(char) + + var toremove = this.NormalizeSpaces(val) + + var regex = new RegExp(char, 'g') + toremove = toremove.replace(regex, ' ') + + return this.RemoveUnnecesarySpaces(toremove) + } + + // removes whitespace from begining and and, and replaces multiple spaces with one space + RemoveUnnecesarySpaces (toremove) { + assert(toremove) + + toremove = this.NormalizeSpaces(toremove) + while (toremove.includes(' ')) { + toremove = toremove.replace(/ {2}/g, ' ') + } + return toremove.trim() + } + + // simplifies a string for easier comparison + SimplifyStringForComparison (value) { + assert(value) + + value = this.RemoveUnnecesarySpaces(value).toLowerCase() + return this.RemoveStuff(value, commonUselessStringParts) + } + + RemoveSpecialChars (value) { + assert(value) + + return this.RemoveStuff(value, ['&']) + } + + // if the value is empty, or whitespace + EmptyOrWhiteSpace (value) { + // replaces /n-s with "". then replaces spaces with "". if it equals "", then its empty, or only consists of white space + if (value === undefined) { return true } + return (value.replace(/\n/g, '').replace(/ /g, '').replace(/\s/g, ' ') === '') + } + + // damn nonbreaking space + NormalizeSpaces (input) { + assert(input) + + return input.replace(/\s/g, ' ') + } + + CompareString (s1, s2) { + if (!s1 || !s2) { + return 0 + } + + s1 = this.SimplifyStringForComparison(s1).split(' ') + s2 = this.SimplifyStringForComparison(s2).split(' ') + var match = 0 + for (var i = 0; i < s1.length; i++) { + if (s2.includes(s1[i])) { match++ } + } + var percent = Math.round(((match / s1.length) * 100).toFixed(2)) // matched words percent + var lengthDifference = Math.abs(s2.length - s1.length) + percent -= lengthDifference * lengthDiffMultiplier + if (percent < 0) { percent = 0 } + return percent + } + + AnswerPreProcessor (value) { + assert(value) + + return this.RemoveStuff( + value, commonUselessAnswerParts) + } + + // 'a. pécsi sör' -> 'pécsi sör' + RemoveAnswerLetters (value) { + assert(value) + + let s = value.split('. ') + if (s[0].length < 2 && s.length > 1) { + s.shift() + return s.join(' ') + } else { + return value + } + } + + SimplifyQA (value, mods) { + if (!value) { return } + + const reducer = (res, fn) => { + return fn(res) + } + + return mods.reduce(reducer, value) + } + + SimplifyAnswer (value) { + return this.SimplifyQA( + value, + [ + this.RemoveSpecialChars.bind(this), + this.RemoveUnnecesarySpaces.bind(this), + this.AnswerPreProcessor.bind(this), + this.RemoveAnswerLetters.bind(this) + ]) + } + + SimplifyQuestion (value) { + return this.SimplifyQA( + value, + [ + this.RemoveSpecialChars.bind(this), + this.RemoveUnnecesarySpaces.bind(this) + ]) + } + + SimplifyStack (stack) { + return this.SimplifyQuery(stack) + } +} + +const SUtils = new StringUtils() + +class Question { + constructor (q, a, i) { + this.Q = SUtils.SimplifyQuestion(q) + this.A = SUtils.SimplifyAnswer(a) + this.I = i + } + + toString () { + var r = '?' + this.Q + '\n!' + this.A + if (this.I) { r += '\n>' + this.I } + return r + } + + HasQuestion () { + return this.Q !== undefined + } + + HasAnswer () { + return this.A !== undefined + } + + HasImage () { + return this.I !== undefined && (typeof this.I === 'string' || Array.isArray(this.I)) + } + + IsComplete () { + return this.HasQuestion() && this.HasAnswer() + } + + Compare (q2, i) { + assert(q2) + + if (typeof q2 === 'string') { + var qmatchpercent = SUtils.CompareString(this.Q, q2) + + if (i === undefined || i.length === 0) { return qmatchpercent } else { + if (this.HasImage()) { + const imatchpercent = this.HasImage() ? SUtils.CompareString(this.I.join(' '), i.join(' ')) + : 0 + return (qmatchpercent + imatchpercent) / 2 + } else { + qmatchpercent -= 30 + if (qmatchpercent < 0) { return 0 } else { return qmatchpercent } + } + } + } else { + const qmatchpercent = SUtils.CompareString(this.Q, q2.Q) + const amatchpercent = SUtils.CompareString(this.A, q2.A) + if (this.I !== undefined) { + const imatchpercent = this.I === undefined ? SUtils.CompareString(this.I.join(' '), q2.I.join( + ' ')) : 0 + return (qmatchpercent + amatchpercent + imatchpercent) / 3 + } else { + return (qmatchpercent + amatchpercent) / 2 + } + } + } +} + +class Subject { + constructor (n) { + assert(n) + + this.Name = n + this.Questions = [] + this.active = false + } + + setIndex (i) { + this.index = i + } + + getIndex () { + return this.index || -1 + } + + get length () { + return this.Questions.length + } + + markActive () { + this.active = true + } + + getIfActive () { + return this.active + } + + AddQuestion (q) { + assert(q) + + this.Questions.push(q) + } + + getSubjNameWithoutYear () { + let t = this.Name.split(' - ') + if (t[0].match(/^[0-9]{4}\/[0-9]{2}\/[0-9]{1}$/i)) { + return t[1] || '' + } else { + return '' + } + } + + getYear () { + let t = this.Name.split(' - ')[0] + if (t.match(/^[0-9]{4}\/[0-9]{2}\/[0-9]{1}$/i)) { + return t + } else { + return '' + } + } + + Search (q, img) { + assert(q) + + var r = [] + for (let i = 0; i < this.length; i++) { + let percent = this.Questions[i].Compare(q, img) + if (percent > minMatchAmmount) { + r.push({ + q: this.Questions[i], + match: percent + }) + } + } + + for (let i = 0; i < r.length; i++) { + for (var j = i; j < r.length; j++) { + if (r[i].match < r[j].match) { + var tmp = r[i] + r[i] = r[j] + r[j] = tmp + } + } + } + + return r + } + + toString () { + var r = [] + for (var i = 0; i < this.Questions.length; i++) { r.push(this.Questions[i].toString()) } + return '+' + this.Name + '\n' + r.join('\n') + } +} + +class QuestionDB { + constructor (getVal, setVal) { + this.Subjects = [] + this.getVal = getVal + this.setVal = setVal + } + + get length () { + return this.Subjects.length + } + + get activeIndexes () { + var r = [] + for (var i = 0; i < this.length; i++) { + if (this.getVal('Is' + i + 'Active')) { + r.push(i) + } + } + return r + } + + GetIfActive (ind) { + return this.getVal('Is' + ind + 'Active') + } + + ChangeActive (i, value) { + this.setVal('Is' + i + 'Active', !!value) + } + + AddQuestion (subj, q) { + assert(subj) + + var i = 0 + while (i < this.Subjects.length && this.Subjects[i].Name !== subj) { i++ } + if (i < this.Subjects.length) { this.Subjects[i].AddQuestion(q) } else { + const n = new Subject(subj) + n.AddQuestion(q) + this.Subjects.push(n) + } + } + + Search (q, img) { + assert(q) + + var r = [] + for (let i = 0; i < this.length; i++) { + if (this.GetIfActive(i)) { r = r.concat(this.Subjects[i].Search(q, img)) } + } + + for (let i = 0; i < r.length; i++) { + for (var j = i; j < r.length; j++) { + if (r[i].match < r[j].match) { + var tmp = r[i] + r[i] = r[j] + r[j] = tmp + } + } + } + + return r + } + + AddSubject (subj) { + assert(subj) + + var i = 0 + while (i < this.length && subj.Name !== this.Subjects[i].Name) { i++ } + + if (i < this.length) { + this.Subjects.concat(subj.Questions) + } else { + this.Subjects.push(subj) + } + } + + toString () { + var r = [] + for (var i = 0; i < this.Subjects.length; i++) { r.push(this.Subjects[i].toString()) } + return r.join('\n\n') + } +} + +module.exports.StringUtils = StringUtils +module.exports.Question = Question +module.exports.Subject = Subject +module.exports.QuestionDB = QuestionDB diff --git a/utils/merger.js b/utils/merger.js index ab1ed24..9d23e53 100644 --- a/utils/merger.js +++ b/utils/merger.js @@ -22,127 +22,8 @@ // join json datas, or raw datas // or something else -const minMatchAmmount = 55 -const minResultMatchPercent = 99 -const lengthDiffMultiplier = 10 - -class Question { - constructor (q, a, i) { - this.Q = q - this.A = a - this.I = i - } - toString () { - var r = '?' + this.Q + '\n!' + this.A - if (this.I) { r += '\n>' + this.I } - return r - } - HasQuestion () { - return this.Q != undefined - } - HasAnswer () { - return this.A != undefined - } - HasImage () { - return this.I != undefined - } - IsComplete () { - return this.HasQuestion() && this.HasAnswer() - } - // TODO: TEST DIS - Compare (q2, i) { - if (typeof q2 === 'string') { - var qmatchpercent = Question.CompareString(this.Q, q2) - - if (i == undefined || i.length == 0) { return qmatchpercent } else { - if (this.HasImage()) { - const imatchpercent = this.HasImage() ? Question.CompareString(this.I.join(' '), i.join(' ')) - : 0 - return (qmatchpercent + imatchpercent) / 2 - } else { - qmatchpercent -= 30 - if (qmatchpercent < 0) { return 0 } else { return qmatchpercent } - } - } - } else { - const qmatchpercent = Question.CompareString(this.Q, q2.Q) - const amatchpercent = Question.CompareString(this.A, q2.A) - if (this.I != undefined) { - const imatchpercent = this.I == undefined ? Question.CompareString(this.I.join(' '), q2.I.join( - ' ')) : 0 - return (qmatchpercent + amatchpercent + imatchpercent) / 3 - } else { - return (qmatchpercent + amatchpercent) / 2 - } - } - } - static CompareString (s1, s2) { - s1 = SimplifyStringForComparison(s1).split(' ') - s2 = SimplifyStringForComparison(s2).split(' ') - var match = 0 - for (var i = 0; i < s1.length; i++) { - if (s2.includes(s1[i])) { match++ } - } - var percent = Math.round(((match / s1.length) * 100).toFixed(2)) // matched words percent - var lengthDifference = Math.abs(s2.length - s1.length) - percent -= lengthDifference * lengthDiffMultiplier - if (percent < 0) { percent = 0 } - return percent - } -} - -class Subject { - constructor (n) { - this.Name = n - this.Questions = [] - } - get length () { - return this.Questions.length - } - AddQuestion (q) { - this.Questions.push(q) - } - toString () { - var r = [] - for (var i = 0; i < this.Questions.length; i++) { r.push(this.Questions[i].toString()) } - return '+' + this.Name + '\n' + r.join('\n') - } -} - -class QuestionDB { - constructor () { - this.Subjects = [] - } - get length () { - return this.Subjects.length - } - AddQuestion (subj, q) { - var i = 0 - while (i < this.Subjects.length && this.Subjects[i].Name != subj) { i++ } - if (i < this.Subjects.length) { this.Subjects[i].AddQuestion(q) } else { - const n = new Subject(subj) - n.AddQuestion(q) - this.Subjects.push(n) - } - } - AddSubject (subj) { - var i = 0 - while (i < this.length && subj.Name != this.Subjects[i].Name) { i++ } - - if (i < this.length) { - this.Subjects.concat(subj.Questions) - } else { - this.Subjects.push(subj) - } - } - toString () { - var r = [] - for (var i = 0; i < this.Subjects.length; i++) { r.push(this.Subjects[i].toString()) } - return r.join('\n\n') - } -} +var classes = require('./classes.js') var utils = require('./utils.js') -var actions = require('./actions.js') Main() @@ -171,7 +52,7 @@ function Main () { }) var olds = [] - if (dbs.length == 1) { + if (dbs.length === 1) { for (let i = 0; i < dbs[0].length; i++) { olds.push(dbs[0].Subjects[i].length) } } @@ -198,13 +79,13 @@ function PrintLN () { function PrintDB (r, olds) { console.log('Data subject count: ' + r.length) var maxLength = 0 - for (var i = 0; i < r.length; i++) { + for (let i = 0; i < r.length; i++) { if (maxLength < r.Subjects[i].Name.length) { maxLength = r.Subjects[i].Name.length } } let qcount = 0 - for (var i = 0; i < r.length; i++) { + for (let i = 0; i < r.length; i++) { let line = i if (line < 10) { line += ' ' } @@ -213,7 +94,7 @@ function PrintDB (r, olds) { line += r.Subjects[i].Name while (line.length < currLength) { - if (i % 4 == 0) { line += '.' } else { line += ' ' } + if (i % 4 === 0) { line += '.' } else { line += ' ' } } if (olds && olds.length > 0) { @@ -247,15 +128,15 @@ function GetParams () { function ParseJSONData (data) { var d = JSON.parse(data) - var r = new QuestionDB() + var r = new classes.QuestionDB((x) => true, (x, y) => console.log(x, y)) var rt = [] for (var i = 0; i < d.Subjects.length; i++) { - let s = new Subject(d.Subjects[i].Name) + let s = new classes.Subject(d.Subjects[i].Name) var j = 0 for (j = 0; j < d.Subjects[i].Questions.length; j++) { var currQ = d.Subjects[i].Questions[j] - s.AddQuestion(new Question(currQ.Q, currQ.A, currQ.I)) + s.AddQuestion(new classes.Question(currQ.Q, currQ.A, currQ.I)) } rt.push({ name: d.Subjects[i].Name, @@ -267,7 +148,7 @@ function ParseJSONData (data) { } function MergeDatabases (dbs) { - var db = new QuestionDB() + var db = new classes.QuestionDB((x) => true, (x, y) => console.log(x, y)) for (var i = 0; i < dbs.length; i++) { for (var j = 0; j < dbs[i].length; j++) { db.AddSubject(dbs[i].Subjects[j]) } } @@ -281,11 +162,11 @@ function MergeDatabases (dbs) { * */ function ReadData (data) { const d = data.split('\n') - const r = new QuestionDB() + const r = new classes.QuestionDB((x) => true, (x, y) => console.log(x, y)) var logs = [] var currSubj = '' // the current subjects name var ExpectedIdentifier = ['+', '?'] - let currQuestion = new Question() + let currQuestion = new classes.Question() var i = -1 while (i < d.length) { @@ -307,18 +188,18 @@ function ReadData (data) { let currData = d[i].substring(1).trim() - if (currIdentifier == '+') { + if (currIdentifier === '+') { if (currQuestion.IsComplete()) { r.AddQuestion(currSubj, currQuestion) } - currQuestion = new Question() + currQuestion = new classes.Question() currSubj = currData ExpectedIdentifier = ['?'] continue } - if (currIdentifier == '?') { + if (currIdentifier === '?') { if (currQuestion.IsComplete()) { r.AddQuestion(currSubj, currQuestion) - currQuestion = new Question() + currQuestion = new classes.Question() } // overwriting is allowed here, bcus: // ?????!> @@ -327,9 +208,9 @@ function ReadData (data) { continue } - if (currIdentifier == '!') { + if (currIdentifier === '!') { // if dont have question continue - if (!currQuestion.HasQuestion()) { throw 'No question! (A)' } + if (!currQuestion.HasQuestion()) { throw new Error('No question! (A)') } // dont allow overwriting // ?!!!! if (!currQuestion.HasAnswer()) { @@ -342,10 +223,10 @@ function ReadData (data) { continue } - if (currIdentifier == '>') { + if (currIdentifier === '>') { // if dont have question or answer continue - if (!currQuestion.HasQuestion()) { throw 'No question! (I)' } - if (!currQuestion.HasAnswer()) { throw 'No asnwer! (I)' } + if (!currQuestion.HasQuestion()) { throw new Error('No question! (I)') } + if (!currQuestion.HasAnswer()) { throw new Error('No asnwer! (I)') } // dont allow overwriting // ?!>>> if (!currQuestion.HasImage()) { @@ -377,7 +258,7 @@ function RemoveDuplFromSubject (subj) { for (var i = 0; i < cp.length; i++) { var j = 0 // Only removes 100% match! - while (j < subj.length && cp[i].Compare(subj.Questions[j]) != 100) { + while (j < subj.length && cp[i].Compare(subj.Questions[j]) !== 100) { j++ } if (j < subj.length) { @@ -395,26 +276,3 @@ function RemoveDuplFromSubject (subj) { } } } - -function SimplifyStringForComparison (value) { - value = RemoveUnnecesarySpaces(value).toLowerCase() - var removableChars = [',', '.', ':', '!'] - for (var i = 0; i < removableChars.length; i++) { - var regex = new RegExp(removableChars[i], 'g') - value.replace(regex, '') - } - return value -} - -function RemoveUnnecesarySpaces (toremove) { - toremove = NormalizeSpaces(toremove) - while (toremove.includes(' ')) // while the text includes double spaces replaces all of them with a single one - { - toremove = toremove.replace(/ {2}/g, ' ') - } - return toremove.trim() -} - -function NormalizeSpaces (input) { - return input.replace(/\s/g, ' ') -} diff --git a/utils/motd.js b/utils/motd.js index 6f50a6a..2b2e011 100644 --- a/utils/motd.js +++ b/utils/motd.js @@ -1,6 +1,5 @@ const utils = require('../utils/utils.js') const dataFile = '../public/data.json' -const versionFile = '../public/version' const motdFile = '../public/motd' var p = GetParams() diff --git a/utils/stat.js b/utils/stat.js index 30e6cd4..dd9e322 100644 --- a/utils/stat.js +++ b/utils/stat.js @@ -61,23 +61,21 @@ function LogStat (url) { function Inc (value) { if (value.startsWith('/?')) { value = '/' } - if (data[value] == undefined) { data[value] = 0 } + if (data[value] === undefined) { data[value] = 0 } data[value]++ } function AddVisitStat (name) { var m = new Date() - const now = m.getFullYear() + '/' + - ('0' + (m.getMonth() + 1)).slice(-2) + '/' + - ('0' + m.getDate()).slice(-2) - if (vData[now] == undefined) { vData[now] = {} } - if (vData[now][name] == undefined) { vData[now][name] = 0 } + const now = m.getFullYear() + '/' + ('0' + (m.getMonth() + 1)).slice(-2) + '/' + ('0' + m.getDate()).slice(-2) + if (vData[now] === undefined) { vData[now] = {} } + if (vData[now][name] === undefined) { vData[now][name] = 0 } vData[now][name]++ } function Save () { writes++ - if (writes == writeInterval) { + if (writes === writeInterval) { try { utils.WriteFile(JSON.stringify(data), statFile) // logger.Log("Stats wrote."); diff --git a/utils/utils.js b/utils/utils.js index e4a7c42..97c7e79 100644 --- a/utils/utils.js +++ b/utils/utils.js @@ -6,8 +6,7 @@ module.exports = { Beep: Beep, WriteBackup: WriteBackup, FileExists: FileExists, - CreatePath: CreatePath, - GetAllFilesFromFolder: GetAllFilesFromFolder + CreatePath: CreatePath } var fs = require('fs') @@ -17,7 +16,7 @@ var logger = require('../utils/logger.js') const dataFile = './public/data.json' function ReadFile (name) { - if (!FileExists(name)) { throw 'No such file: ' + name } + if (!FileExists(name)) { throw new Error('No such file: ' + name) } return fs.readFileSync(name, 'utf8') } @@ -31,14 +30,14 @@ function CreatePath (path, onlyPath) { var p = path.split('/') var currDir = p[0] for (var i = 1; i < p.length; i++) { - if (currDir != '' && !fs.existsSync(currDir)) { + if (currDir !== '' && !fs.existsSync(currDir)) { try { fs.mkdirSync(currDir) } catch (e) { console.log('Failed to make ' + currDir + ' directory... ') } } currDir += '/' + p[i] } - if (onlyPath == undefined || onlyPath == false) { fs.writeFileSync(path, '') } else { fs.mkdirSync(path) } + if (onlyPath === undefined || onlyPath === false) { fs.writeFileSync(path, '') } else { fs.mkdirSync(path) } } function WriteFile (content, path) { @@ -78,18 +77,3 @@ function WriteBackup () { console.log(e) } } - -function GetAllFilesFromFolder (dir) { - var results = [] - - fs.readdirSync(dir).forEach(function (file) { - file = dir + '/' + file - var stat = fs.statSync(file) - - if (stat && stat.isDirectory()) { - results = results.concat(_getAllFilesFromFolder(file)) - } else results.push(file) - }) - - return results -}