-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathAlgorithm.java
More file actions
247 lines (229 loc) · 9.4 KB
/
Algorithm.java
File metadata and controls
247 lines (229 loc) · 9.4 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
import java.io.FileNotFoundException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
public class Algorithm {
//Set of all potential candidates in pool
private HashSet<Resume> candidates;
//map of candidates and if they are accepted/rejected along with percentile against population
private HashMap<Resume, Decision> acceptance;
private double median;
private double stndDev;
private double avg;
private HashSet<String> basicSkills;
private HashSet<String> desiredSkills;
private String weight;
//constructs an algorithm object with a HashSet<Resume> of candidates, HashSet<String> of basicSKills,
//HashSet<String> of desiredSkills, and String weight as parameters
public Algorithm(HashSet<Resume> newCandidates, HashSet<String> newBasicSkills, HashSet<String> newDesiredSkills, String newWeight) throws FileNotFoundException {
basicSkills = newBasicSkills;
desiredSkills = newDesiredSkills;
weight = newWeight;
candidates = newCandidates;
//these three fields get defined in evaluate method
median = 0;
stndDev=0;
avg=0;
acceptance = this.evaluate(candidates);
}
//returns boolean of whether or not candidate meets basic requirements
//given HashSet<String> of basicSkills, and Resume candidate as parameters
public boolean qualify(HashSet<String> basicSkills, Resume candidate) {
if (candidate.getKeyWords().containsAll(basicSkills)) return true;
return false;
}
//returns integer value of total points a candidate earned on their resume
//given a Resume candidate, a HashSet<String> of desired skills, and String weight as parameters
public Integer assess(Resume candidate, HashSet<String> desiredSkills, String weight) throws FileNotFoundException {
int totalPoints = 0;
Set<String> skills = candidate.getKeyWords();
Map<String, Integer> experience = candidate.getExperience();
//determines if recruiter enters in skills, experience, or both for weighted points
if(weight.toLowerCase().equals("skills")) {
for(String skill:desiredSkills) {
if(skills.contains(skill)) {
totalPoints+=2;
totalPoints+=experience.get(skill.toLowerCase());
}
}
}else if(weight.toLowerCase().equals("experience")) {
for(String skill:desiredSkills) {
if(skills.contains(skill)) {
totalPoints+=1;
totalPoints+=2*experience.get(skill.toLowerCase());
}
}
}else {
for(String skill:desiredSkills) {
if(skills.contains(skill)) {
totalPoints+=1;
totalPoints+=experience.get(skill.toLowerCase());
}
}
}
return totalPoints;
}
//determines if candidate is rejected/accepted
//if candidate is less than 50% percentile, they are rejected (can potentially let recruiter enter method)
//takes in HashSet<Resume> of candidates as parameter
//returns results in a HashMap<Resume, Decision>
public HashMap<Resume, Decision> evaluate(HashSet<Resume> potCandidates) throws FileNotFoundException{
HashMap<Resume, Decision> evaluation = new HashMap<>();
HashSet<Resume> tempCands = new HashSet<>();
if(potCandidates != null) {
Iterator<Resume> itr = potCandidates.iterator();
//reject candidates without basic skills
while(itr.hasNext()) {
Resume candidate = itr.next();
if(!qualify(basicSkills, candidate)) {
//just give 0 points if don't even meet basic qualifications
evaluation.put(candidate, new Decision(false, 0.0, 0, "Doesn't meet basic skills"));
tempCands.add(candidate);
itr.remove();
}
}
//do assess method to assign points to candidates
HashMap<Integer, Resume> candidatePoints = new HashMap<>();
for (Resume remainCandidate: potCandidates) {
int points = assess(remainCandidate,desiredSkills,weight);
candidatePoints.put(points, remainCandidate);
}
//sort from least to most total points, with points as they key
TreeMap<Integer, Resume> tempOrderedCandidates = new TreeMap<>(candidatePoints);
if(!tempOrderedCandidates.isEmpty()) {
//array list of total points in order for calculating statistics
//sorted an array list in this manner because don't know how to sort a set
ArrayList<Integer> orderedPoints = new ArrayList<>();
//add all candidate points in ordered arraylist
for(Integer points: tempOrderedCandidates.keySet()) {
orderedPoints.add(points);
}
median = getMedian(orderedPoints);
stndDev = getStandardDev(orderedPoints, median);
avg = getAverage(orderedPoints);
//less than certain percentile -> rejected
//in this case use 50% as example, can be changed if want recruiter to make choice
for(Integer points:tempOrderedCandidates.keySet()) {
int totalPoints = points;
Double percent = getPercentile(points, orderedPoints);
Resume candidate = tempOrderedCandidates.get(points);
//give each candidate a decision
Decision temp = new Decision(false, percent, totalPoints, "");
if(percent < 0.5) {
//if less than 50%, candidate is rejected
temp.setExplanation("Less qualified than 50% of candidate pool");
evaluation.put(candidate, temp);
}else {
//only accept candidate if they are better than 50%
temp.setAcceptance(true);
evaluation.put(candidate, temp);
}
}
}
}else {
System.out.println("No candidates meet basic skills requirement");
}
for(Resume cand: tempCands) {
potCandidates.add(cand);
}
return evaluation;
}
//print overall statistics of all candidates
public void printAllResults() {
System.out.println("--------- Overall Statistics ---------");
System.out.println("Median: " + median);
System.out.println("Average: " + avg);
System.out.println("Standard Deviation: " + stndDev);
System.out.println("--------- Candidate Statistics ---------");
for(Resume candidate:acceptance.keySet()) {
System.out.println("Candidate: " + candidate.getName());
if(acceptance.get(candidate).getAcceptance()) {
System.out.println("Candidate was accepted");
}else {
System.out.println("Candidate was rejected");
System.out.println("Explanation: " + acceptance.get(candidate).getExplanation());
}
System.out.println("Points: " + acceptance.get(candidate).getTotalPoints());
System.out.println("Percentile: " + acceptance.get(candidate).getPercentile());
System.out.println();
}
printCurve();
}
//prints individual candidate statistics
public void printIndvResult(Resume candidate) {
System.out.println("Candidate: " + candidate.getName());
if(acceptance.get(candidate).getAcceptance()) {
System.out.println("Candidate was accepted");
}else {
System.out.println("Candidate was rejected");
System.out.println("Explanation: " + acceptance.get(candidate).getExplanation());
}
System.out.println("Percentile: " + acceptance.get(candidate).getPercentile());
Set<String> candKeys = new HashSet<String>();
candKeys = candidate.getKeyWords();
Set<String> temp = filter(candKeys);
System.out.println("Main Skills: " + temp.toString());
printIndvCurve(candidate);
}
//returns HashSet<String> of candidate keywords that are also contained in the desiredSkills set
//takes in HashSet<String> of skills as parameter
public Set<String> filter(Set<String> allSkills) {
Set<String> res = new HashSet<String>();
for (String skill : allSkills) {
if (basicSkills.contains(skill) || desiredSkills.contains(skill)) {
res.add(skill);
}
}
return res;
}
//prints out overall bell curve of population
public void printCurve() {
BellCurve newCurve = new BellCurve(avg, stndDev);
newCurve.plot();
}
//plots point against curve for candidate
public void printIndvCurve(Resume candidate) {
BellCurve newCurve = new BellCurve(avg, stndDev);
newCurve.plotIndvCandidate(acceptance.get(candidate).getTotalPoints(), candidate.getName());
}
//returns median points of population
public Double getMedian(ArrayList<Integer> orderedCandidates) {
if(orderedCandidates.size() == 1) return (double)(orderedCandidates.get(0));
if(orderedCandidates.size()%2!=0) {
return (double) (orderedCandidates.get(orderedCandidates.size()/2));
}else {
int m1 = orderedCandidates.get(orderedCandidates.size()/2-1);
int m2 = orderedCandidates.get((orderedCandidates.size()/2));
return (m1+m2)/2.0;
}
}
//returns average points of population
public Double getAverage(ArrayList<Integer> orderedCandidates) {
double total = 0;
for(Integer points: orderedCandidates) {
total+=points;
}
return total/orderedCandidates.size();
}
//returns standard deviation in points of population
public Double getStandardDev(ArrayList<Integer> orderedCandidates, Double median) {
double sum = 0;
for(Integer points: orderedCandidates) {
double temp = points;
sum+= Math.pow(temp-median, 2.0);
}
return Math.sqrt(sum/orderedCandidates.size());
}
//returns percentile of candidate
public double getPercentile(Integer candidate, ArrayList<Integer> orderedCandidates) {
//if there's only one candidate they are accepted if they meet basic qualifications
if(orderedCandidates.size() == 1) return 1.0;
double index = orderedCandidates.indexOf(candidate);
return (double)(index/(orderedCandidates.size()-1));
}
}