1
0
mirror of https://github.com/JuanCanham/HackMyResume.git synced 2025-05-02 20:37:08 +01:00

Finish HackMyCore reshaping.

Reintroduce HackMyCore, dropping the interim submodule, and reorganize
and improve tests.
This commit is contained in:
hacksalot
2016-01-29 15:23:57 -05:00
parent e9971eb882
commit 0f65e4c9f3
130 changed files with 5384 additions and 337 deletions

138
dist/inspectors/gap-inspector.js vendored Normal file
View File

@ -0,0 +1,138 @@
/**
Employment gap analysis for HackMyResume.
@license MIT. See LICENSE.md for details.
@module inspectors/gap-inspector
*/
(function() {
var FluentDate, LO, _, gapInspector, moment;
_ = require('underscore');
FluentDate = require('../core/fluent-date');
moment = require('moment');
LO = require('lodash');
/**
Identify gaps in the candidate's employment history.
*/
gapInspector = module.exports = {
moniker: 'gap-inspector',
/**
Run the Gap Analyzer on a resume.
@method run
@return {Array} An array of object representing gaps in the candidate's
employment history. Each object provides the start, end, and duration of the
gap:
{ <-- gap
start: // A Moment.js date
end: // A Moment.js date
duration: // Gap length
}
*/
run: function(rez) {
var coverage, dur, g, gap_start, hist, new_e, num_gaps, o, ref_count, tdur, total_gap_days;
coverage = {
gaps: [],
overlaps: [],
pct: '0%',
duration: {
total: 0,
work: 0,
gaps: 0
}
};
hist = LO.get(rez, 'employment.history');
if (!hist || !hist.length) {
return coverage;
}
new_e = hist.map(function(job) {
var obj;
obj = _.pick(job, ['start', 'end']);
if (obj && (obj.start || obj.end)) {
obj = _.pairs(obj);
obj[0][1] = FluentDate.fmt(obj[0][1]);
if (obj.length > 1) {
obj[1][1] = FluentDate.fmt(obj[1][1]);
}
}
return obj;
});
new_e = _.filter(_.flatten(new_e, true), function(v) {
return v && v.length && v[0] && v[0].length;
});
if (!new_e || !new_e.length) {
return coverage;
}
new_e = _.sortBy(new_e, function(elem) {
return elem[1].unix();
});
num_gaps = 0;
ref_count = 0;
total_gap_days = 0;
gap_start = null;
new_e.forEach(function(point) {
var inc, lastGap, lastOver;
inc = point[0] === 'start' ? 1 : -1;
ref_count += inc;
if (ref_count === 0) {
return coverage.gaps.push({
start: point[1],
end: null
});
} else if (ref_count === 1 && inc === 1) {
lastGap = _.last(coverage.gaps);
if (lastGap) {
lastGap.end = point[1];
lastGap.duration = lastGap.end.diff(lastGap.start, 'days');
return total_gap_days += lastGap.duration;
}
} else if (ref_count === 2 && inc === 1) {
return coverage.overlaps.push({
start: point[1],
end: null
});
} else if (ref_count === 1 && inc === -1) {
lastOver = _.last(coverage.overlaps);
if (lastOver) {
lastOver.end = point[1];
lastOver.duration = lastOver.end.diff(lastOver.start, 'days');
if (lastOver.duration === 0) {
return coverage.overlaps.pop();
}
}
}
});
if (coverage.overlaps.length) {
o = _.last(coverage.overlaps);
if (o && !o.end) {
o.end = moment();
o.duration = o.end.diff(o.start, 'days');
}
}
if (coverage.gaps.length) {
g = _.last(coverage.gaps);
if (g && !g.end) {
g.end = moment();
g.duration = g.end.diff(g.start, 'days');
}
}
tdur = rez.duration('days');
dur = {
total: tdur,
work: tdur - total_gap_days,
gaps: total_gap_days
};
coverage.pct = dur.total > 0 && dur.work > 0 ? (((dur.total - dur.gaps) / dur.total) * 100).toFixed(1) + '%' : '???';
coverage.duration = dur;
return coverage;
}
};
}).call(this);

61
dist/inspectors/keyword-inspector.js vendored Normal file
View File

@ -0,0 +1,61 @@
/**
Keyword analysis for HackMyResume.
@license MIT. See LICENSE.md for details.
@module inspectors/keyword-inspector
*/
(function() {
var FluentDate, _, keywordInspector;
_ = require('underscore');
FluentDate = require('../core/fluent-date');
/**
Analyze the resume's use of keywords.
TODO: BUG: Keyword search regex is inaccurate, especially for one or two
letter keywords like "C" or "CLI".
@class keywordInspector
*/
keywordInspector = module.exports = {
/** A unique name for this inspector. */
moniker: 'keyword-inspector',
/**
Run the Keyword Inspector on a resume.
@method run
@return An collection of statistical keyword data.
*/
run: function(rez) {
var prefix, regex_quote, searchable, suffix;
regex_quote = function(str) {
return (str + '').replace(/[.?*+^$[\]\\(){}|-]/ig, "\\$&");
};
searchable = '';
rez.transformStrings(['imp', 'computed', 'safe'], function(key, val) {
return searchable += ' ' + val;
});
prefix = '(?:' + ['^', '\\s+', '[\\.,]+'].join('|') + ')';
suffix = '(?:' + ['$', '\\s+', '[\\.,]+'].join('|') + ')';
return rez.keywords().map(function(kw) {
var count, myArray, regex, regex_str;
regex_str = prefix + regex_quote(kw) + suffix;
regex = new RegExp(regex_str, 'ig');
myArray = null;
count = 0;
while ((myArray = regex.exec(searchable)) !== null) {
count++;
}
return {
name: kw,
count: count
};
});
}
};
}).call(this);

49
dist/inspectors/totals-inspector.js vendored Normal file
View File

@ -0,0 +1,49 @@
/**
Section analysis for HackMyResume.
@license MIT. See LICENSE.md for details.
@module inspectors/totals-inspector
*/
(function() {
var FluentDate, _, totalsInspector;
_ = require('underscore');
FluentDate = require('../core/fluent-date');
/**
Retrieve sectional overview and summary information.
@class totalsInspector
*/
totalsInspector = module.exports = {
moniker: 'totals-inspector',
/**
Run the Totals Inspector on a resume.
@method run
@return An object containing summary information for each section on the
resume.
*/
run: function(rez) {
var sectionTotals;
sectionTotals = {};
_.each(rez, function(val, key) {
if (_.isArray(val) && !_.isString(val)) {
return sectionTotals[key] = val.length;
} else if (val.history && _.isArray(val.history)) {
return sectionTotals[key] = val.history.length;
} else if (val.sets && _.isArray(val.sets)) {
return sectionTotals[key] = val.sets.length;
}
});
return {
totals: sectionTotals,
numSections: Object.keys(sectionTotals).length
};
}
};
}).call(this);