diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..eb5d15c --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +node_modules +package-lock.json +dbfile +Session.vim diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..9c011fb --- /dev/null +++ b/Makefile @@ -0,0 +1,89 @@ +.PHONY: run stop deepclean + +ifeq (\$(UNAME),Darwin) +BROWSER=open +else +BROWSER=xdg-open +endif +#BROWSER=chromium +SETTINGS_MONGO=settings/database.json +SETTINGS_APP=settings/web.json +NODE_BIN=$(if `which nodemon`, "nodemon", "node") +DBPATH=dbfile +LOCKFILE=$(DBPATH)/mongod.lock +MONGO_PORT=`cat $(SETTINGS_MONGO)|sed -ne '/"port"\s*:/p' | sed -e 's/^.*"port"\s*:[^0-9]*\([0-9]*\)[^0-9]*$$/\1/'` +APP_PORT=`cat $(SETTINGS_APP)|sed -ne '/"port"\s*:/p' | sed -e 's/^.*"port"\s*:[^0-9]*\([0-9]*\)[^0-9]*$$/\1/'` + +run: $(LOCKFILE) app.js node_modules + @sh -c "sleep 0.5 ; $(BROWSER) http://localhost:$(APP_PORT)/ &> /dev/null " & + @$(NODE_BIN) app.js ; $(MAKE) stop + +stop: + @echo stopping mongodb... + @if [ -e "$(LOCKFILE)" -a -s "$(LOCKFILE)" ]; then\ + mongod --dbpath $(DBPATH) --shutdown;\ + fi + @rm -rf $(LOCKFILE) + @echo mongodb stopped. + +$(LOCKFILE): + @echo "running mongodb (port $(MONGO_PORT))..." + @mkdir -p $(DBPATH) + @sh -c "mongod --port $(MONGO_PORT) --dbpath $(DBPATH) &" > /dev/null + @echo mongodb started. + +node_modules: + npm install + +deepclean: + rm -rf node_modules $(DBPATH) package-lock.json + +fetch: + @whiptail --checklist "Select gakubu to fetch:" 30 50 20 \ + "111973" "政治経済学部" on\ + "121973" "法学部" on\ + "132002" "第一文学部" on\ + "142002" "第二文学部" on\ + "151949" "教育学部" on\ + "161973" "商学部" on\ + "171968" "理工学部" on\ + "181966" "社会科学部" on\ + "192000" "人間科学部" on\ + "202003" "スポーツ科学部" on\ + "212004" "国際教養学部" on\ + "232006" "文化構想学部" on\ + "242006" "文学部" on\ + "252003" "人間科学部eスクール" on\ + "262006" "基幹理工学部" on\ + "272006" "創造理工学部" on\ + "282006" "先進理工学部" on\ + "311951" "政治学研究科" on\ + "321951" "経済学研究科" on\ + "331951" "法学研究科" on\ + "342002" "文学研究科" on\ + "351951" "商学研究科" on\ + "371990" "教育学研究科" on\ + "381991" "人間科学研究科" on\ + "391994" "社会科学研究科" on\ + "402003" "アジア太平洋研究科" on\ + "422000" "国際情報通信研究科" on\ + "432001" "日本語教育研究科" on\ + "442003" "情報生産システム研究科" on\ + "452003" "公共経営研究科" on\ + "462004" "ファイナンス研究科" on\ + "472004" "法務研究科" on\ + "482005" "会計研究科" on\ + "502005" "スポーツ科学研究科" on\ + "512006" "基幹理工学研究科" on\ + "522006" "創造理工学研究科" on\ + "532006" "先進理工学研究科" on\ + "542006" "環境・エネルギー研究科" on\ + "552007" "教職研究科" on\ + "562012" "国際コミュニケーション研究科" on\ + "572015" "経営管理研究科" on\ + "712001" "芸術学校" on\ + "922006" "日本語教育研究センター" on\ + "982007" "留学センター" on\ + "9S2013" "グローバルエデュケーションセンター" on ; : + + diff --git a/app.js b/app.js new file mode 100644 index 0000000..34d431f --- /dev/null +++ b/app.js @@ -0,0 +1,39 @@ +"use strict"; + +const express = require('express'), + morgan = require('morgan'), + bodyParser = require('body-parser'), + methodOverride = require('method-override'), + cookieParser = require('cookie-parser'), + expressSession = require('express-session'), + csrf = require('csurf'); + +global['ROOT_DIR'] = __dirname; +global['dbsettings'] = require('./settings/database.json'); +global['websettings'] = require('./settings/web.json'); + +const www = require('./app/www'); + +process.on('SIGINT', () => { + console.log("Interrupted."); + process.exit(0); +}); + +process.stdin.resume(); +process.stdin.on('end', () => { + process.exit(0); +}); + +const app = express(); +const server = app.listen(websettings.port, ()=>{ + console.log("coursecompass is available at http://localhost:" + websettings.port + "/"); +}); + +app.set('views', ROOT_DIR + '/views'); +app.set('view engine', 'ejs'); + +app.use(morgan('combind')); +app.use('/', www); +app.use(express.static(ROOT_DIR + '/public')); + + diff --git a/app/www.js b/app/www.js new file mode 100644 index 0000000..abf9cd2 --- /dev/null +++ b/app/www.js @@ -0,0 +1,110 @@ +"use strict"; + +let express = require('express'); +let www = express(); +let mongoClient = require('mongodb').MongoClient; + +function connectDB(callback) { + mongoClient.connect("mongodb://localhost:" + dbsettings.port + "/" + dbsettings.dbname, function(err, db) { + if (err) { + console.log("db connection error: " + err); + } else { + callback(db); + } + }); +} + +function createSearchQuery(q) { + let splitChars = ["[", "]", "(", ")", " ", " "]; + let fields = ["courseTitle", "instructor", "category", "academyDisciplines", + "content.outline", "content.objective", "content.studyBeforeOrAfter", + "content.schedule", "content.textbooks", "content.reference", "content.evaluation", + "content.note", "subtitle", "classroom"]; + let words = []; + let s = "", i = 0; + for (i = 0; i < q.length; i++) { + let c = q[i]; + if (c == '"') { + if (s.length > 0) words.push(s); + s = ""; + for (;;) { + c = q[++i]; + if (c == '"') { + if (q[i + 1] != '"') break; + c = q[++i]; + } + if (i >= q.length) break; + s += c; + } + if (s.length > 0) words.push(s); + s = ""; + } else if (splitChars.indexOf(c) >= 0) { + if (s.length > 0) words.push(s); + s = ""; + } else { + s += c; + } + } + if (s.length > 0) words.push(s); + let ret = []; + for (let word of words) { + let list = []; + for (let field of fields) { + let obj = {}; + obj[field] = new RegExp(word, 'i'); + list.push(obj); + } + ret.push({$or: list}); + } + return {$and: ret}; +} + +www.set('x-powered-by', false); +www.set('views', ROOT_DIR + '/views'); +www.set('view engine', 'ejs'); + +www.get('/', function(req, res) { + //res.send("hello"); + res.render('index'); +}); +www.get('/search', function(req, res) { + let results = []; + if (req.query.q) { + console.log("q"); + let q = req.query.q; + if (!q) { + res.redirect('/'); + return; + } + let rgx = new RegExp(q, "i"); + connectDB((db)=>{ + let collection = db.collection('classes'); + collection.find(createSearchQuery(q)).toArray((err, docs)=>{ + if (err) { + console.log("find error: " + err); + } else { + res.render('search', { + results: docs, + q: q + }); + + } + + + }); + + }); + } + +}); + +www.use(function(req, res, next) { + res.status(404) + .render('404'); +}); +www.use(function(err, req, res, next) { + res.status(500) + .render('500'); +}); + +module.exports = www; diff --git a/package.json b/package.json new file mode 100644 index 0000000..ac8a262 --- /dev/null +++ b/package.json @@ -0,0 +1,23 @@ +{ + "name": "coursecompass", + "version": "1.0.0", + "description": "", + "main": "app.js", + "scripts": { + "test": "make" + }, + "author": "", + "license": "MIT", + "dependencies": { + "body-parser": "^1.18.1", + "cookie-parser": "^1.4.3", + "csurf": "^1.9.0", + "ejs": "^2.5.7", + "express": "^4.15.4", + "express-session": "^1.15.5", + "method-override": "^2.3.9", + "morgan": "^1.8.2", + "mongodb": "^2.2.31" + }, + "devDependencies": {} +} diff --git a/settings/database.json b/settings/database.json new file mode 100644 index 0000000..899e5e4 --- /dev/null +++ b/settings/database.json @@ -0,0 +1,5 @@ +{ + "host": "localhost", + "port": "27018", + "dbname": "coursecompass" +} diff --git a/settings/web.json b/settings/web.json new file mode 100644 index 0000000..fcb43fb --- /dev/null +++ b/settings/web.json @@ -0,0 +1,3 @@ +{ + "port": 8080 +} diff --git a/views/404.ejs b/views/404.ejs new file mode 100644 index 0000000..f277ac8 --- /dev/null +++ b/views/404.ejs @@ -0,0 +1,9 @@ + + +
+