1
0
mirror of https://github.com/JuanCanham/HackMyResume.git synced 2025-04-19 14:20:25 +01:00
HackMyResume/src/sheet.js
2015-09-23 00:26:24 -04:00

158 lines
5.1 KiB
JavaScript

/**
Abstract character/resume sheet representation.
@license Copyright (c) 2015 by James M. Devlin. All rights reserved.
*/
(function() {
var FS = require('fs')
, extend = require('./utils/extend')
, validator = require('is-my-json-valid')
, _ = require('underscore')
, moment = require('moment');
/**
Initialize a new Sheet instance.
*/
function Sheet() {
this.id = null;
this.title = "New";
this.fileName = null;
}
/**
Open and parse the specified JSON resume sheet.
*/
Sheet.prototype.open = function( file, title ) {
var rep = JSON.parse( FS.readFileSync( file, 'utf8' ) );
extend( true, this, rep );
this.fileName = file;
this.title = title || this.basics.name;
_parseDates.call( this );
this.sort();
this.computed = this.computed || { };
this.computed.numYears = this.duration();
return this;
};
/**
Determine if the sheet includes a specific social profile (eg, GitHub).
*/
Sheet.prototype.hasProfile = function( socialNetwork ) {
socialNetwork = socialNetwork.trim().toLowerCase();
return this.basics.profiles && _.some( this.basics.profiles, function(prof) {
return prof.network.trim().toLowerCase() === socialNetwork;
});
};
/**
Determine if the sheet includes a specific skill.
*/
Sheet.prototype.hasSkill = function( skill ) {
skill = skill.trim().toLowerCase();
return this.skills && _.some( this.skills, function(sk) {
return sk.keywords && _.some( sk.keywords, function(kw) {
return kw.trim().toLowerCase() === skill;
});
});
};
/**
Validate the sheet against a specific JSON schema.
*/
Sheet.prototype.isValid = function( ) {
var schemaObj = JSON.parse( FS.readFileSync( __dirname + '/resume-schema.json', 'utf8' ) );
var validator = require('is-my-json-valid')
var validate = validator( schemaObj );
return validate( this );
};
/**
Calculate the total duration of the sheet. Assumes this.work has been sorted
by start date descending.
*/
Sheet.prototype.duration = function() {
var careerStart = this.work[ this.work.length - 1].safeStartDate;
var careerLast = _.max( this.work, function( w ) { return w.safeEndDate.unix(); }).safeEndDate;
return careerLast.diff( careerStart, 'years' );
};
/**
Sort dated things by start date descending.
*/
Sheet.prototype.sort = function( ) {
this.work && this.work.length > 1 && this.work.sort( function(a, b) {
return( a.safeStartDate.isBefore(b.safeStartDate) ) ? 1 : ( a.safeStartDate.isAfter(b.safeStartDate) && -1 ) || 0;
});
this.education && this.education.length > 1 && this.education.sort( function(a, b) {
return( a.safeStartDate.isBefore(b.safeStartDate) ) ? 1 : ( a.safeStartDate.isAfter(b.safeStartDate) && -1 ) || 0;
});
this.volunteer && this.volunteer.length > 1 && this.volunteer.sort( function(a, b) {
return( a.safeStartDate.isBefore(b.safeStartDate) ) ? 1 : ( a.safeStartDate.isAfter(b.safeStartDate) && -1 ) || 0;
});
this.awards && this.awards.length > 1 && this.awards.sort( function(a, b) {
return( a.safeDate.isBefore(b.safeDate) ) ? 1 : ( a.safeDate.isAfter(b.safeDate) && -1 ) || 0;
});
this.publications && this.publications.length > 1 && this.publications.sort( function(a, b) {
return( a.safeReleaseDate.isBefore(b.safeReleaseDate) ) ? 1 : ( a.safeReleaseDate.isAfter(b.safeReleaseDate) && -1 ) || 0;
});
};
/**
Format a human-friendly FluentCV date to a Moment.js-compatible date.
*/
function _fmt( dt ) {
dt = dt.toLowerCase().trim();
if( /\s*(present|now)\s*/i.test(dt) ) { // "Present", "Now"
return moment();
}
else if( /^\D+/.test(dt) ) { // "Mar 2015"
var parts = dt.split(' ');
return moment( parts[1] + '-' + (months[ parts[0] ] || abbr[ parts[0] ] || ( parts[0] === 'sept' && '09' )) + '-' + '01', 'YYYY-MM-DD' );
}
else if( /^\d+$/.test(dt) ) { // "2015"
return moment( dt, 'YYYY' );
}
else {
var mt = moment( dt );
if(mt.isValid())
return mt;
throw 'Invalid date format encountered. Use YYYY-MM-DD.';
}
}
/**
Convert human-friendly dates into formal Moment.js dates for all collections.
*/
function _parseDates() {
this.work.forEach( function(job) {
job.safeStartDate = _fmt( job.startDate );
job.safeEndDate = _fmt( job.endDate );
});
this.education.forEach( function(edu) {
edu.safeStartDate = _fmt( edu.startDate );
edu.safeEndDate = _fmt( edu.endDate );
});
this.volunteer.forEach( function(vol) {
vol.safeStartDate = _fmt( vol.startDate );
vol.safeEndDate = _fmt( vol.endDate );
});
this.awards.forEach( function(awd) {
awd.safeDate = _fmt( awd.date );
});
this.publications.forEach( function(pub) {
pub.safeReleaseDate = _fmt( pub.releaseDate );
});
}
var months = {}, abbr = {};
moment.months().forEach( function(m, idx) { months[ m.toLowerCase() ] = idx + 1; });
moment.monthsShort().forEach( function(m, idx) { abbr[ m.toLowerCase() ] = idx + 1; });
/**
Export the Sheet function/ctor.
*/
module.exports = Sheet;
}());