diff options
| author | JoelHMikael <joel.h.kronqvist@gmail.com> | 2022-01-09 20:17:16 +0200 | 
|---|---|---|
| committer | JoelHMikael <joel.h.kronqvist@gmail.com> | 2022-01-09 20:17:16 +0200 | 
| commit | 21e79dcc1eabebfd661a2fd38681348ae9428c4e (patch) | |
| tree | 5a3022d974155a403ee0e1e573a20db6f4ea3003 | |
| parent | 24709fa862636702fd0430e832463b751fce323e (diff) | |
| download | LYLLRuoka-21e79dcc1eabebfd661a2fd38681348ae9428c4e.tar.gz LYLLRuoka-21e79dcc1eabebfd661a2fd38681348ae9428c4e.zip  | |
Database implemented
Some polishing wouldn't do bad though...
| -rw-r--r-- | Cont/index.css | 6 | ||||
| -rw-r--r-- | Cont/index.html | 14 | ||||
| -rw-r--r-- | dbparse.js | 175 | ||||
| -rw-r--r-- | parse.js | 265 | ||||
| -rw-r--r-- | scrape.js | 7 | ||||
| -rw-r--r-- | server.js | 74 | 
6 files changed, 96 insertions, 445 deletions
diff --git a/Cont/index.css b/Cont/index.css index 1f5a422..80e5dc6 100644 --- a/Cont/index.css +++ b/Cont/index.css @@ -107,10 +107,16 @@ footer > a {  }  /*** the info buttons & their animations ***/ +img.info:hover { +	filter: drop-shadow(.125rem .125rem 0 black); +	transform: translate(-0.125rem, -0.125rem); +}  img.info {  	width: 1em;  	height: 1em;  	vertical-align: middle; +	filter: drop-shadow(.0625rem .0625rem 0 black); +	transform: translate(-0.0625rem, -0.0625rem);  }  img.info + span { diff --git a/Cont/index.html b/Cont/index.html index c35b7c1..95dcb32 100644 --- a/Cont/index.html +++ b/Cont/index.html @@ -25,13 +25,13 @@  					<label for="day">Päivä:</label>  					<br>  					<select name="day"> -						<option value="1">ma</option> -						<option value="2">ti</option> -						<option value="3">ke</option> -						<option value="4">to</option> -						<option value="5">pe</option> -						<option value="6" disabled>la</option> -						<option value="0" disabled>su</option> +						<option value="0">ma</option> +						<option value="1">ti</option> +						<option value="2">ke</option> +						<option value="3">to</option> +						<option value="4">pe</option> +						<option value="5" disabled>la</option> +						<option value="6" disabled>su</option>  					</select>  					<br>  					<input type="submit" id="send" class="highlight" value="Löydä vuoro"> @@ -84,98 +84,7 @@ async function writeClasses(classData, DB)  		let res = await DB.execute("INSERT INTO classes VALUES (?, ?)", [key, val]);  	}  } -/* -function parseShift(data, weekdays = ["MAANANTAISIN", "TIISTAISIN", "KESKIVIIKKOISIN", "TORSTAISIN", "PERJANTAISIN"]) -{ -	 -	let i = 0; -	let db = []; -	while (db.length < weekdays.length) -	{ -		let day = []; -		 -		i = getNextChar(data, "\n", findExpression(data, weekdays[db.length])); -		let end; -		if (db.length === weekdays.length - 1) -			end = data.length; -		else -			end = findExpression(data, weekdays[db.length + 1]); -		let unparsedDay = data.substring(i + 1, end); -		day = parseDay(unparsedDay); - -		db.push(day); -	} -	return db; -} - -function parseDay(day) -{ -	let shifts = {}; -	let i = getToLineStartingWith(day, "RUOKAILUVUORO"); -	do -	{ -		let endOfLine = getNextChar(day, "\n", i); -		let shiftDesc = day.substring(i, endOfLine); -		i = getNextChar(day, "\n", i) + 1; -		i = getNextChar(day, "\n", i) + 1; -		if (getNextChar(day, "\n", i) === -1) -			endOfLine = day.length; -		else -			endOfLine = getNextChar(day, "\n", i); -		let unparsedIndexes = day.substring(i, endOfLine); -		shifts[shiftDesc] = parseLine(unparsedIndexes); -		i = getToLineStartingWith(day, "RUOKAILUVUORO", i); -	} while (i !== -1); -	return shifts; -} -function parseLine(line, toRemove = " ja KAHDEN TUTKINNON OPINNOT 1., 2. ja 3. VUOSITASON RYHMÄT ") -{ -	let i = 0; -	let courses = []; -	let teachers = []; -	// get to the teachers & courses -	let nextSpace = 0; - -	if (line.substring(line.length - toRemove.length, line.length) === toRemove) -		line = line.substring(0, line.length - toRemove.length); -	line = line.replaceAll(",", "").replaceAll("ja ", "").replaceAll(" + ", "+"); - -	while (i < line.length) -	{ -		if (line[i] === "+") -		{ - -			nextSpace = getNextChar(line, " ", i); -			let nextNextSpace = getNextChar(line, " ", nextSpace + 1); -			if (nextNextSpace === -1) -				nextNextSpace = line.length; -			line = `${line.substring(0, i)} ${line.substring(nextSpace + 1, nextNextSpace)} ${line.substring(i + 1, line.length)}`; -			i = nextNextSpace - 1; -		} -		i++; -	} -	nextSpace = 0; -	i = 0; - -	const getElement = list => -	{ -		nextSpace = getNextChar(line, " ", i); -		if (nextSpace === -1) -			nextSpace = line.length; -		list.push(line.substring(i, nextSpace)); -		i = nextSpace + 1; -	} -	do -	{ -		getElement(courses); -		getElement(teachers); -	} while (i < line.length) - -	return [courses, teachers]; -} - -*/  async function parseLine(data, day, shift, DB)  {  	// "preprocessing" @@ -285,10 +194,31 @@ async function writeShifts(data, DB)  		i = end;  	} + +	const courses = await DB.query_raw("SELECT * FROM classes"); +	const results = []; +	for (let course = 0; course < courses.length; course++) +	{ +		results.push(DB.query("UPDATE shifts SET class = ? WHERE course = ?", [courses[course].class, courses[course].course])); +	} +	await Promise.all(results);  	return 0;  } -/* +async function getShift(day, index, DB) +{ +	let shift = DB.execute("SELECT name FROM shiftnames WHERE day = ? and id = (SELECT shift FROM shifts WHERE (day = ?) AND (course = ? OR teacher = ? OR class = ?) LIMIT 1)", [day, day, index, index, index]); +	let additional = DB.execute("SELECT course, teacher, class FROM shifts WHERE (day = ?) AND (course = ? OR teacher = ? OR class = ?)", [day, index, index, index]); +	[shift, additional] = await Promise.all([shift, additional]); +	if (shift.length !== 0) +	{ +		shift.push(additional); +		return shift; +	} +	return undefined; +} + +  function getIndexType(index)  {  	if (/^[A-Za-zåäöÅÄÖ]{2,3}\d{2,3}$/.test(index)) @@ -299,67 +229,32 @@ function getIndexType(index)  		return "class";  } -function getShift(day, index, db) // day: int, 1 = monday; index: string of course/teacher; db: parsed shifts -{ -	if ((typeof day !== "number") || isNaN(day) || (typeof index !== "string")) -		return -1; - -	let shifts = db[day - 1]; - -	let _endOfIndex = parseInt(index.substring(2, 4)); -	let type = getIndexType(index); -	if (type === undefined) -		return {}; -	let type_index = +(type === "teacher") + (+(type === "class") * 2); - -	let res = {}; -	for (const [key, val] of Object.entries(shifts)) -	{ -		let indexes = val[type_index]; -		for (let i = 0; i < indexes.length; i++) -		{ -			if (indexes[i] === index) -				res[key] = [val[0][i], val[1][i], val[2][i]]; -		} -	} -	return res; -} -  function randInt(start, stop)  {  	return start + Math.floor(Math.random() * (stop - start));  } -function getIndexes(db, day, shift, type) -{ -	let d = db[day]; -	let sh = Object.values(d)[shift][type]; -	return Object.values(db[day])[shift][type]; -} - -function getRandomIndex(db, day = randInt(0, 5), shift = randInt(0, 3), type = randInt(0, 3)) +async function getRandomIndex(day, DB)  { -	let el; -	let i = 0; -	let indexes = getIndexes(db, day, shift, type); -	while ((el === undefined) && (i < indexes.length)) +	let indexes = await DB.execute("SELECT course, teacher, class FROM shifts WHERE day = ? ORDER BY RAND() LIMIT 1", [day]); +	indexes = Object.values(indexes[0]); +	let start = randInt(0, indexes.length); +	for (let test = 0; test < 3; test++)  	{ -		el = indexes[i]; -		i++; +		let i = (start + test) % indexes.length; +		if (indexes[i] !== null) +			return indexes[i];  	} -	if (el == undefined) -		return getRandomIndex(db); -	return el; +	console.log("Warning: row without class/teacher/course in database!"); +	return getRandomIndex(day, DB);  } -exports.build	= parseShift; +  exports.indexType = getIndexType; -exports.classes = parseClasses; -exports.get 	= getShift;  exports.cluttered = parseCluttered;  exports.find = findExpression;  exports.getNextChar = getNextChar; -exports.randomIndex = getRandomIndex;*/ -  exports.classes = writeClasses;  exports.build = writeShifts; +exports.get = getShift; +exports.randomIndex = getRandomIndex; diff --git a/parse.js b/parse.js deleted file mode 100644 index a776f13..0000000 --- a/parse.js +++ /dev/null @@ -1,265 +0,0 @@ -function getCharAmount(s, c) -{ -	let n = 0; -	for (let c_i = 0; c_i < s.length; c_i++) -	{ -		n += +(s[c_i] === c); -	} -	return n; -} - -function getNextChar(s, c, i = 0) -{ -	if (!(Number.isInteger(i) && (i >= 0))) -		return -1; -	for (; i < s.length; i++) -	{ -		if (s[i] === c) -			return i; -	} -	return -1; -} -function getNextLine(s, i) -{ -	i = getNextChar(s, "\n", i); -	i += +(i !== -1) * 1; -	return i; -} -function getToLineStartingWith(s, ss, start = 0) -{ -	if (!(Number.isInteger(start) && (start >= 0))) -		return -1 -	 -	let i = start; -	do -	{ -		if (s.substring(i, i + ss.length) === ss) -			break; -		i = getNextLine(s, i); -	} while(i !== -1) -	 -	return i; -} - -function findExpression(data, expr, start = 0) -{ -	if (start == -1) -		return -1; -	if (!(Number.isInteger(start) && (start >= 0))) -		throw new TypeError("Start must be a positive integer!"); -	while ((data.substring(start, start + expr.length) !== expr) && (start + expr.length < data.length)) -		start++; -	if (data.substring(start, start + expr.length) !== expr) -		return -1; -	return start; -} - -function parseCluttered(s) -{ -	if (!(typeof s === "string")) -		return ""; -	return s.replaceAll(".", "").replaceAll(" ", "").toUpperCase(); -} - -function parseClasses(classData, DB) -{ -	classData = parseCluttered(classData) + "\n"; // newline so that loop can find last value -	// parse data to dict -	let classes = {}; -	let i = 0; -	while (i < classData.length) -	{ -		let separator = getNextChar(classData, ":", i); -		let lineEnd = getNextChar(classData, "\n", i); -		let key = classData.substring(i, separator); -		let val = classData.substring(separator + 1, lineEnd); -		i = lineEnd + 1; -		classes[key] = val; -	} - -	for (let day = 0; day < DB.length; day++) -	{ -		let shifts = DB[day]; -		for (const [key, val] of Object.entries(shifts)) -		{ -			DB[day][key].push([]); -			let indexes = val[0]; // use courses: the classes are paired to them and they are unique with a higher probability -			for (let i = 0; i < indexes.length; i++) -			{ -				DB[day][key][2].push(classes[indexes[i]]); -			} -		} -	} - -} - -function parseLine(line, toRemove = " ja KAHDEN TUTKINNON OPINNOT 1., 2. ja 3. VUOSITASON RYHMÄT ") -{ -	let i = 0; -	let courses = []; -	let teachers = []; -	let nextSpace = 0; - -	if (line.substring(line.length - toRemove.length, line.length) === toRemove) -		line = line.substring(0, line.length - toRemove.length); -	line = line.replaceAll(",", "").replaceAll("ja ", "").replaceAll(" + ", "+"); - -	while (i < line.length) -	{ -		if (line[i] === "+") -		{ - -			nextSpace = getNextChar(line, " ", i); -			let nextNextSpace = getNextChar(line, " ", nextSpace + 1); -			if (nextNextSpace === -1) -				nextNextSpace = line.length; -			line = `${line.substring(0, i)} ${line.substring(nextSpace + 1, nextNextSpace)} ${line.substring(i + 1, line.length)}`; -			i = nextNextSpace - 1; -		} -		i++; -	} -	nextSpace = 0; -	i = 0; - -	const getElement = list => -	{ -		nextSpace = getNextChar(line, " ", i); -		if (nextSpace === -1) -			nextSpace = line.length; -		list.push(line.substring(i, nextSpace)); -		i = nextSpace + 1; -	} - -	do -	{ -		getElement(courses); -		getElement(teachers); -	} while (i < line.length) - -	return [courses, teachers]; -} - -function parseDay(day) -{ -	let shifts = {}; -	let i = getToLineStartingWith(day, "RUOKAILUVUORO"); -	do -	{ -		let endOfLine = getNextChar(day, "\n", i); -		let shiftDesc = day.substring(i, endOfLine); -		i = getNextChar(day, "\n", i) + 1; -		i = getNextChar(day, "\n", i) + 1; -		if (getNextChar(day, "\n", i) === -1) -			endOfLine = day.length; -		else -			endOfLine = getNextChar(day, "\n", i); -		let unparsedIndexes = day.substring(i, endOfLine); -		shifts[shiftDesc] = parseLine(unparsedIndexes); -		i = getToLineStartingWith(day, "RUOKAILUVUORO", i); -	} while (i !== -1); -	return shifts; -} - -function parseShift(data, weekdays = ["MAANANTAISIN", "TIISTAISIN", "KESKIVIIKKOISIN", "TORSTAISIN", "PERJANTAISIN"]) -{ -	 -	let i = 0; -	let db = []; -	while (db.length < weekdays.length) -	{ -		let day = []; -		 -		i = getNextChar(data, "\n", findExpression(data, weekdays[db.length])); -		let end; -		if (db.length === weekdays.length - 1) -			end = data.length; -		else -			end = findExpression(data, weekdays[db.length + 1]); -		let unparsedDay = data.substring(i + 1, end); -		day = parseDay(unparsedDay); - -		db.push(day); -	} -	return db; -} - -/* - * DB structure: - * WEEKDAY - list - * 	FOOD SHIFTS - dict - * 		COURSE INDEXES - list - * 		TEACHER INDEXES - list - * 	maybe:	CLASSES - list - */ - -function getIndexType(index) -{ -	if (/^[A-Za-zåäöÅÄÖ]{2,3}\d{2,3}$/.test(index)) -		return "course"; -	if (/^[A-Za-zåäöÅÄÖ]{4}$/.test(index)) -		return "teacher"; -	if (/^\w\d{3}$/.test(index)) -		return "class"; -} - -function getShift(day, index, db) // day: int, 1 = monday; index: string of course/teacher; db: parsed shifts -{ -	if ((typeof day !== "number") || isNaN(day) || (typeof index !== "string")) -		return -1; - -	let shifts = db[day - 1]; - -	let _endOfIndex = parseInt(index.substring(2, 4)); -	let type = getIndexType(index); -	if (type === undefined) -		return {}; -	let type_index = +(type === "teacher") + (+(type === "class") * 2); - -	let res = {}; -	for (const [key, val] of Object.entries(shifts)) -	{ -		let indexes = val[type_index]; -		for (let i = 0; i < indexes.length; i++) -		{ -			if (indexes[i] === index) -				res[key] = [val[0][i], val[1][i], val[2][i]]; -		} -	} -	return res; -} - -function randInt(start, stop) -{ -	return start + Math.floor(Math.random() * (stop - start)); -} - -function getIndexes(db, day, shift, type) -{ -	let d = db[day]; -	let sh = Object.values(d)[shift][type]; -	return Object.values(db[day])[shift][type]; -} - -function getRandomIndex(db, day = randInt(0, 5), shift = randInt(0, 3), type = randInt(0, 3)) -{ -	let el; -	let i = 0; -	let indexes = getIndexes(db, day, shift, type); -	while ((el === undefined) && (i < indexes.length)) -	{ -		el = indexes[i]; -		i++; -	} -	if (el == undefined) -		return getRandomIndex(db); -	return el; -} - -exports.build	= parseShift; -exports.indexType = getIndexType; -exports.classes = parseClasses; -exports.get 	= getShift; -exports.cluttered = parseCluttered; -exports.find = findExpression; -exports.getNextChar = getNextChar; -exports.randomIndex = getRandomIndex; @@ -1,4 +1,7 @@ -const https = require("https"); const parse = require("./parse.js"); const fs = require("fs"); const events = require("events"); +const https = require("https"); +const parse = require("./DBPARSE.js"); +const fs = require("fs"); +const events = require("events");  async function urlOpen(path)  { @@ -22,7 +25,7 @@ async function scrapeFood(url)  	data = data.toString("utf-8");  	let foodList = []; -	const weekdays = ["su", "ma", "ti", "ke", "to", "pe", "la"]; +	const weekdays = ["ma", "ti", "ke", "to", "pe", "la", "su"];  	let titleTags = ["<title>", "</title>"];  	let foodTags = ["<![CDATA[", "]]>"]; @@ -1,7 +1,6 @@  const http	= require("http");  const fs	= require("fs");  const url	= require("url"); -const parse	= require("./parse.js");  const scrape	= require("./scrape.js");  const SQL_DBS	= require("./database.js");  const DBPARSE	= require("./dbparse.js"); @@ -23,10 +22,11 @@ async function init()  	};  	const errorPath = "./Cont/404/index.html"; + + +  	// await for needed things in async -	let [shiftCont, classCont, foodsThisWeek, foodsNextWeek, dbcredentials] = await Promise.all([ -		openFile("./shifts.txt"), -		openFile("./classes.txt"), +	let [foodsThisWeek, foodsNextWeek, dbcredentials] = await Promise.all([  		scrape.food(scrape.link(1)),  		scrape.food(scrape.link(2)),  		openFile("../dblogin.txt") @@ -35,16 +35,6 @@ async function init()  	// get the MySQL DB connection  	const SQLDB = new SQL_DBS.Database(JSON.parse(dbcredentials)); -	// get the food shift "database" -	shiftCont = shiftCont.toString("utf-8").replaceAll("\r", ""); // \r because of the \r\n newline on windows which creates problems -	classCont = classCont.toString("utf-8").replaceAll("\r", ""); - -	await DBPARSE.classes(classCont, SQLDB); -	await DBPARSE.build(shiftCont, SQLDB); - -	let DB = parse.build(shiftCont); -	parse.classes(classCont, DB); -  	// get the food "database"  	const foods = [foodsThisWeek, foodsNextWeek]; @@ -77,7 +67,6 @@ async function init()  			"path": path,  			"path404": errorPath,  			"query": q.query, -			"db": DB,  			"foods": foods,  			"sqldb": SQLDB  		}; @@ -108,7 +97,7 @@ async function init()  function validateIndex(sus)  { -	return antiXSS(parse.cluttered(sus)); +	return antiXSS(DBPARSE.cluttered(sus));  }  function antiXSS(sus) @@ -120,7 +109,7 @@ function antiXSS(sus)  function isDir(path)  { -	return (parse.getNextChar(path.substring(1), ".") === -1); +	return (DBPARSE.getNextChar(path.substring(1), ".") === -1);  } @@ -152,7 +141,7 @@ async function buildMain(args)  	const query = args["query"];  	const foods = args["foods"];  	const index = query.index; -	const DB = args["db"]; +	const SQLDB = args["sqldb"];  	const data = await openFile(path);  	let data_string = data.toString("utf-8"); @@ -160,9 +149,10 @@ async function buildMain(args)  	const d = new Date();  	let day = d.getDay(); +	day = (day + +(day === 0) * 7) - 1;  	const actualDay = day; -	day = +((day === 0) || (day === 6)) + (+(!(day === 0) && !(day === 6)) * day); -	if ((typeof query.day === "string") && (parseInt(query.day).toString() === query.day) && (!isNaN(parseInt(query.day))) && (parseInt(query.day) > 0) && (parseInt(query.day) < 6)) +	day = +(!(day === 5) && !(day === 6)) * day; +	if ((typeof query.day === "string") && (parseInt(query.day).toString() === query.day) && (!isNaN(parseInt(query.day))) && (parseInt(query.day) >= 0) && (parseInt(query.day) < 5))  		day = parseInt(query.day);  	data_string = data_string.replace(`<option value=\"${day}\">`, `<option value=\"${day}\" selected>`); @@ -177,21 +167,26 @@ async function buildMain(args)  		res["shift"] = "";  	if (res["shift"] === undefined)  	{ -		let shift = parse.get(day, index, DB); -		let key = Object.keys(shift)[0]; -		if (key !== undefined) +		let shift = await DBPARSE.get(day, index, SQLDB); +		if (shift !== undefined)  		{ -			res["shift"] = key; -			res["shift-header"] = `${shift[key][0]}/${shift[key][1]}`; -			if (shift[key][2] !== undefined) -				res["shift-header"] += `/${shift[key][2]}` -			res["index-type"] = "Kurssin"; +			res["shift"] = shift[0].name; +			res["shift-header"] = ""; +			for (let i = 0; i < shift[1].length; i++) +			{ +				res["shift-header"] += `${shift[1][i].course}/${shift[1][i].teacher}`; +				if (shift[1][i].class !== null) +					res["shift-header"] += `/${shift[1][i].class}` +				if (i + 1 !== shift[1].length) +					res["shift-header"] += " ja "; +			} +			res["index-type"] = ["Kurssin", "Kurssien"][+(shift[1].length > 1)];  		}  		else  		{  			res["shift"] = -1;  			res["shift-header"] = `${index}`; -			res["index-type"] = indexTypes[parse.indexType(index)]; +			res["index-type"] = indexTypes[DBPARSE.indexType(index)];  			if (res["index-type"] === undefined)  				res["index-type"] = "";  		} @@ -200,10 +195,10 @@ async function buildMain(args)  		res["shift"] = "Kurssilla/opettajalla/luokalla ei ole ruokailua päivällä tai kurssia ei ole olemassa!";  	// get the example input -	res["example-input"] = parse.randomIndex(DB, day - 1); +	res["example-input"] = await DBPARSE.randomIndex(day, SQLDB);  	// get the day -	let weekdays = ["su", "ma", "ti", "ke", "to", "pe", "la"]; +	let weekdays = ["ma", "ti", "ke", "to", "pe", "la", "su"];  	res["day"] = weekdays[day];  	if (res["shift"] === "")  		data_string = data_string.replace('<div id="shift-result" class="float-block">', '<div id="shift-result" class="float-block" style="display: none;">'); @@ -284,4 +279,21 @@ function build_replace(s, dict)  } +// Run this if you want to build the database from text files +async function buildDB(DB) +{ +	let [shiftCont, classCont] = await Promise.all([ +		openFile("./shifts.txt"), +		openFile("./classes.txt") +	]); +	shiftCont = shiftCont.toString("utf-8").replaceAll("\r", ""); // \r because of the \r\n newline on windows which creates problems +	classCont = classCont.toString("utf-8").replaceAll("\r", ""); +	await Promise.all([ +		DBPARSE.classes(classCont, SQLDB), +		DBPARSE.build(shiftCont, SQLDB) +	]); +	return 0; +} + +  init();  | 
