Commit 42cbe59a authored by Mark Stenglein's avatar Mark Stenglein

Add a ton of changes

This does not work yet. I'm trying to isolate why the database is not
loading properly right now.

Yeah, this has been a long time coming and really shouldve been done a
while ago, sorry I don't have a good description for what is in here.
parent 9433ee03
Pipeline #658 failed with stage
in 1 minute and 2 seconds
node_modules/
*.log
.devDB/
.idea/
......@@ -40,10 +40,9 @@ app.use(express.static(path.join(__dirname, 'public')))
// Initialize the Database and Connection
var db = require(path.join(__dirname, 'models'))
db.sequelize.sync({force: true})
// Populate initial data
// TODO: populate the information
require(path.join(__dirname, 'data'))
// Actually use the loaded routes
// TODO: make this automatic instead of being manually entered
......
......@@ -23,7 +23,8 @@ sequelize :
schools :
- slug : GMU
longName : George Mason University
name : George Mason University
website : www2.gmu.edu
semesters :
- slug : "GMU2016SP"
longName : "Spring 2016"
......
This diff is collapsed.
/*
* Schedules by Student Run Computing and Technology
*
* data/index.js
*
* This file takes care if the initial database population for the schedules
* application. Parsing the information stored in the config as well as the raw
* data exports (json in `./dataFiles`) is the first step. The file then
* incrementally builds up the `university` object for each school. This object
* contains inside of it an array of each `Semester` object, which in turn has
* all of the thousands of `Section` objects.
*
* Sequelize (Schedules' ORM) takes care of converting the nested objects into
* Has-Many relationships (forming a splitting tree of data from the base
* university objects).
*/
var config = require('config')
var path = require('path')
var db = require(path.join(__dirname, '..', 'models', 'index'))
// pull needed objects out of the config and database objects
var schools = config.schools
var sequelize = db.sequelize
var models = db.sequelize.models
console.log('day')
// Synchronize the database tables with their models (leave `{force: true}` to
// empty the database at each run)
// TODO: create a config switch that decides locally if the database is to be
// completely wiped each and every run of the application or not.
sequelize.sync({ force: true })
// Loop through each school stored in the configuration and build the
// university object for it. Everything else happens _insider_ this loop.
for (var i = 0; i < schools.length; i++) {
var school = schools[i]
// Barebone university object pulls data from config and leaves an empty
// array for any `Semesters` to be stored.
var university = {
'slug': school.slug,
'name': school.name,
'website': school.website,
'Semesters': []
}
/*
* Look through each of the `university`'s semesters and build a `semester`
* object for them. Again, most everything else happens in here.
*
* NOTE: This entire loop runs independently for _each_ different university
* configured in the `config.yaml` file.
*/
for (var j = 0; j < school.semesters.length; j++) {
// pull the raw semester data to work with (really to shorten further uses)
var rawSemester = school.semesters[j]
// Fetch the large JSON object file that stores all of the `Section` data
// for this particular semester.
var rawSections = require(path.join(__dirname, 'dataFiles', rawSemester.dataFile))
// Build a basic semester object according to the ORM. Again, leaves an
// empty array to be populated in the next loop.
var semester = {
'slug': rawSemester.slug,
'name': rawSemester.name,
'Sections': []
}
/*
* Loop through all of the hundreds of classes for the current university's
* semester being processed currently. Builds the base `section` object and
* does some processing to get the raw data into the ORM's needed format.
*
* NOTE: This is done independently for each `Semester` in each
* `University`. Keep in mind that this loop is run a stupid amount
* before adding some crazy expensive processing here.
*/
for (var z = 0; z < rawSections.classes.length; z++) {
var rawSection = rawSections.classes[z]
var sectionDateRange = rawSection.session_templates[0].date_range
var section = {
'crn': rawSection.crn,
'name': rawSection.name,
'title': rawSection.title,
'section': rawSection.section,
'instructors': '', // build this from all total instructors
'campus': rawSection.campus,
'location': '', // taken from only the first session_template
'class_type': '', // taken from only the first session_template
'startDate': sectionDateRange.substr(0, 12),
'endDate': sectionDateRange.substr(15, 12),
'Msession': false,
'MtimeStart': null,
'MtimeEnd': null,
'Mlocation': null,
'MclassType': null,
'Tsession': false,
'TtimeStart': null,
'TtimeEnd': null,
'Tlocation': null,
'TclassType': null,
'Wsession': false,
'WtimeStart': null,
'WtimeEnd': null,
'Wlocation': null,
'WclassType': null,
'Rsession': false,
'RtimeStart': null,
'RtimeEnd': null,
'Rlocation': null,
'RclassType': null,
'Fsession': false,
'FtimeStart': null,
'FtimeEnd': null,
'Flocation': null,
'FclassType': null
}
// Pull generic session information (location and type) from first
// session template
section.location = rawSection.session_templates[0].location
section.class_type = rawSection.session_templates[0].class_type
/*
* Loop through each session template for each section/class. This loop
* is what allows different days of the week to meet on different times
* and or locations.
*/
for (var c = 0; c < rawSection.session_templates.length; c++) {
var session_template = rawSection.session_templates[c]
// raw value of the start/stop times (to be processed to time values)
var sessionTime = session_template.time;
(['M', 'T', 'W', 'R', 'F']).forEach(function(day) {
if (session_template.days.indexOf(day) > -1) {
// if here then there is a session for the day
section[day + 'session'] = true
// set initial length for start time
var startLength = 8
// test if the time has 2 digits in hours (adjust length if yes)
if (sessionTime[1] === ':') {
startLength = 7
}
// set the start time
section[day + 'timeStart'] = sessionTime.substr(0, startLength)
// set initial length for end time
var endLength = 8
// test if the time has 2 digits in hours (adjust length if yes)
if (sessionTime[sessionTime.length - 8] === ' ') {
endLength = 7
}
var endOffset = sessionTime.length - endLength
// set the end time
section[day + 'timeEnd'] = sessionTime.substr(endOffset, endLength)
// Note down location and type information
section[day + 'location'] = session_template.location
section[day + 'classType'] = session_template.class_type
// If the instructor is not yet in the entire listing, add it.
// TODO: Make this tolerant of multiple instructors defined for
// one section. (ie. currently if you have 2 instructors in
// one section it'll search for all of them as one term and
// consequently add all of them to the full list.) Should
if (section.instructors.search(session_template.instructors) < 0) {
section.instructors += session_template.instructors
}
}
})
}
/* END JANKY WORKAROUND DESCRIBED IN ABOVE BLOCK */
console.log(section)
semester.Sections.push(section)
}
university.Semesters.push(semester)
}
// Actually add the data to the database and sync it.
sequelize.sync().then(function () {
return models.University.create(university, {
include: [
models.Semester
]
})
})
}
// grab the things we need
var mongoose = require('mongoose');
var Semester = require('../models/Semester');
var fs = require("fs");
// Load site wide configurations
//var config = require('../config');
var populateDB = function() {
if (config.ReloadDB) {
emptySemesters(); // NOTE: this is an asynchronous call
var semesters = [];
for (var i = 0; i < config.dataFiles.length; i++) {
var datafile = config.dataFiles[i];
var semester = new Semester(JSON.parse(fs.readFileSync("./setup/dataFiles/" + datafile)));
semesters.push(semester.toObject());
}
Semester.collection.insert(semesters, function(err) {
if (err) { console.error('Database Error!', err) }
else {
var findItems = Semester.find();
findItems.select('-_id');
findItems.select('-classes');
findItems.exec(function(err, users) {
if (err) {console.error(err); }
else { console.log(users); }
});
}
});
}
}
// Empty collections
// http://stackoverflow.com/questions/10081452/drop-database-with-mongoose
function emptySemesters() {
Semester.remove({}, handleEmptySemesters);
}
function handleEmptySemesters(err) {
if (err) { console.error('Database Error!', err) }
else{
console.log('semesters removed');
loadFiles();
}
}
function loadFiles() {
console.log('Test successful')
}
module.exports = populateDB;
......@@ -12,54 +12,70 @@ module.exports = function (sequelize, DataTypes) {
instructor: DataTypes.STRING,
campus: DataTypes.STRING,
location: DataTypes.STRING,
class_type: DataTypes.STRING,
// Start Time Information
startDate: DataTypes.DATE,
endDate: DataTypes.DATE,
startDate: DataTypes.STRING,
endDate: DataTypes.STRING,
/*
* NOTE: `campus` and `location` are stored overall as well as for each
* individual session to allow for changing rooms/buildings/campuses
* throughout the week. GMU may not do this but it's a good future
* proofing to add in now while it's easy.
*/
campus: DataTypes.STRING,
location: DataTypes.STRING,
Msession: {
type: DataTypes.BOOLEAN,
allowNull: false,
defaultValue: false
},
MtimeStart: DataTypes.TIME,
MtimeEnd: DataTypes.TIME,
MtimeStart: DataTypes.STRING,
MtimeEnd: DataTypes.STRING,
MclassType: DataTypes.STRING,
Mlocation: DataTypes.STRING,
Tsession: {
type: DataTypes.BOOLEAN,
allowNull: false,
defaultValue: false
},
TtimeStart: DataTypes.TIME,
TtimeEnd: DataTypes.TIME,
TtimeStart: DataTypes.STRING,
TtimeEnd: DataTypes.STRING,
Tcampus: DataTypes.STRING,
TclassType: DataTypes.STRING,
Wsession: {
type: DataTypes.BOOLEAN,
allowNull: false,
defaultValue: false
},
WtimeStart: DataTypes.TIME,
WtimeEnd: DataTypes.TIME,
WtimeStart: DataTypes.STRING,
WtimeEnd: DataTypes.STRING,
WclassType: DataTypes.STRING,
Wlocation: DataTypes.STRING,
Rsession: {
type: DataTypes.BOOLEAN,
allowNull: false,
defaultValue: false
},
RtimeStart: DataTypes.TIME,
RtimeEnd: DataTypes.TIME,
RtimeStart: DataTypes.STRING,
RtimeEnd: DataTypes.STRING,
RclassType: DataTypes.STRING,
Rlocation: DataTypes.STRING,
Fsession: {
type: DataTypes.BOOLEAN,
allowNull: false,
defaultValue: false
},
FtimeStart: DataTypes.TIME,
FtimeEnd: DataTypes.TIME
FtimeStart: DataTypes.STRING,
FtimeEnd: DataTypes.STRING,
FclassType: DataTypes.STRING,
Flocation: DataTypes.STRING
}, {
validate: {
Msession_validate: function (value) {
......@@ -101,8 +117,7 @@ module.exports = function (sequelize, DataTypes) {
' Friday if class is set to true.')
}
}
}
}, {
},
indexes: [
{
unique: true,
......@@ -128,6 +143,11 @@ module.exports = function (sequelize, DataTypes) {
unique: false,
fields: ['title']
}
]
],
classMethods: {
associate: function (models) {
models.Section.belongsTo(models.Semester)
}
}
})
}
module.exports = function (sequelize, DataTypes) {
return sequelize.define('Section', {
// unique index/key
crn: {
type: DataTypes.STRING,
unique: true
},
name: DataTypes.STRING,
title: DataTypes.STRING,
section: DataTypes.STRING,
instructor: DataTypes.STRING,
class_type: DataTypes.STRING,
// Start Time Information
startDate: DataTypes.DATE,
endDate: DataTypes.DATE,
/*
* NOTE: `campus` and `location` are stored overall as well as for each
* individual session to allow for changing rooms/buildings/campuses
* throughout the week. GMU may not do this but it's a good future
* proofing to add in now while it's easy.
*/
campus: DataTypes.STRING,
location: DataTypes.STRING,
Msession: {
type: DataTypes.BOOLEAN,
allowNull: false,
defaultValue: false
},
MtimeStart: DataTypes.TIME,
MtimeEnd: DataTypes.TIME,
MclassType: DataTypes.STRING,
Mlocation: DataTypes.STRING,
Tsession: {
type: DataTypes.BOOLEAN,
allowNull: false,
defaultValue: false
},
TtimeStart: DataTypes.TIME,
TtimeEnd: DataTypes.TIME,
Tcampus: DataTypes.STRING,
TclassType: DataTypes.STRING,
Wsession: {
type: DataTypes.BOOLEAN,
allowNull: false,
defaultValue: false
},
WtimeStart: DataTypes.TIME,
WtimeEnd: DataTypes.TIME,
WclassType: DataTypes.STRING,
Wlocation: DataTypes.STRING,
Rsession: {
type: DataTypes.BOOLEAN,
allowNull: false,
defaultValue: false
},
RtimeStart: DataTypes.TIME,
RtimeEnd: DataTypes.TIME,
RclassType: DataTypes.STRING,
Rlocation: DataTypes.STRING,
Fsession: {
type: DataTypes.BOOLEAN,
allowNull: false,
defaultValue: false
},
FtimeStart: DataTypes.TIME,
FtimeEnd: DataTypes.TIME
FclassType: DataTypes.STRING,
Flocation: DataTypes.STRING,
}, {
validate: {
Msession_validate: function (value) {
if ((this.Msession === true) &&
(this.MtimeStart === null || this.MtimeEnd === null)) {
throw new Error('Start and end times must be defined for' +
' Monday if class is set to true.')
}
},
Tsession_validate: function (value) {
if ((this.Tsession === true) &&
(this.TtimeStart === null || this.TtimeEnd === null)) {
throw new Error('Start and end times must be defined for' +
' Tuesday if class is set to true.')
}
},
Wsession_validate: function (value) {
if ((this.Wsession === true) &&
(this.WtimeStart === null || this.WtimeEnd === null)) {
throw new Error('Start and end times must be defined for' +
' Wednesday if class is set to true.')
}
},
Rsession_validate: function (value) {
if ((this.Rsession === true) &&
(this.RtimeStart === null || this.RtimeEnd === null)) {
throw new Error('Start and end times must be defined for' +
' Thursday if class is set to true.')
}
},
Fsession_validate: function (value) {
if ((this.Fsession === true) &&
(this.FtimeStart === null || this.FtimeEnd === null)) {
throw new Error('Start and end times must be defined for' +
' Friday if class is set to true.')
}
}
}
}, {
indexes: [
{
unique: true,
fields: ['crn']
},
{
unique: false,
fields: ['instructor']
},
{
unique: false,
fields: ['campus']
},
{
unique: false,
fields: ['location']
},
{
unique: false,
fields: ['title']
}
]
}, {
classMethods: {
associate: function (models) {
models.Section.belongsTo(models.Semester)
}
}
})
}
......@@ -5,19 +5,18 @@ module.exports = function (sequelize, DataTypes) {
unique: true
},
name: DataTypes.STRING,
name: DataTypes.STRING
universitySlug: {
type: DataTypes.STRING
// references: {
// model: University,
// key: slug
// }
}
}, {
classMethods: {
indexes: [
{
unique: true,
fields: ['slug']
}
], classMethods: {
associate: function (models) {
Semester.belongsTo(models.University, { foreignKey: 'slug' })
models.Semester.belongsTo(models.University)
models.Semester.hasMany(models.Section)
}
}
})
......
......@@ -16,9 +16,15 @@ module.exports = function (sequelize, DataTypes) {
allowNull: false
}
}, {
idexes: [
{
unique: true,
fields: ['slug']
}
],
classMethods: {
associate: function (models) {
University.hasMany(models.Semester, { foreignKey: 'slug' })
models.University.hasMany(models.Semester)
}
}
})
......
......@@ -23,9 +23,10 @@ modelNames.forEach(function (modelName) {
db[model.name] = model
})
// TODO: figure out exactly what this is doing
Object.keys(db).forEach(function (modelName) {
console.log(modelName)
if ('associate' in db[modelName]) {
console.log('yep, it ran for this one')
db[modelName].associate(db)
}
})
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment