forked from Mroziu12/DVP
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathskillDataProcessor.js
More file actions
190 lines (154 loc) · 5.56 KB
/
skillDataProcessor.js
File metadata and controls
190 lines (154 loc) · 5.56 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
/**
* Skill Data Processor
*
* Processes ClearOffers.json to extract skill-specific data for pie charts.
* Filters job offers by a specific skill and provides distribution data.
*/
class SkillDataProcessor {
constructor() {
this.offers = [];
this.loaded = false;
}
/**
* Load ClearOffers.json data from embedded window.CLEAR_OFFERS_DATA
*/
loadData() {
if (this.loaded) return;
try {
// Use embedded data instead of fetch to avoid CORS issues
if (typeof window.CLEAR_OFFERS_DATA === 'undefined') {
throw new Error('CLEAR_OFFERS_DATA not found. Make sure clearOffersData.js is loaded before this script.');
}
this.offers = window.CLEAR_OFFERS_DATA;
this.loaded = true;
} catch (error) {
console.error('Error loading ClearOffers data:', error);
throw error;
}
}
/**
* Filter offers by skill name
* @param {string} skillName - The skill to filter by
* @returns {Array} Filtered offers containing the skill
*/
filterBySkill(skillName) {
if (!skillName) return [];
const normalizedSkillName = skillName.toLowerCase().trim();
return this.offers.filter(offer => {
if (!offer.skills || !Array.isArray(offer.skills)) return false;
return offer.skills.some(skill => {
const offerSkillName = (skill.name || skill.original_name || '').toLowerCase().trim();
return offerSkillName === normalizedSkillName;
});
});
}
/**
* Get experience level distribution for a specific skill
* @param {string} skillName - The skill to analyze
* @returns {Array} Experience level data for pie chart
*/
getExperienceLevelData(skillName) {
const filteredOffers = this.filterBySkill(skillName);
if (filteredOffers.length === 0) {
return [];
}
const experienceCounts = {
'Junior': 0,
'Mid': 0,
'Senior': 0,
'Lead': 0
};
filteredOffers.forEach(offer => {
let level = offer.experience_level;
// Treat "unknown" as "Lead"
if (!level || level.toLowerCase() === 'unknown') {
level = 'Lead';
}
// Normalize the level name
const normalizedLevel = level.charAt(0).toUpperCase() + level.slice(1).toLowerCase();
if (experienceCounts.hasOwnProperty(normalizedLevel)) {
experienceCounts[normalizedLevel]++;
} else {
experienceCounts['Lead']++;
}
});
const total = filteredOffers.length;
return Object.entries(experienceCounts)
.filter(([_, value]) => value > 0)
.map(([label, value]) => ({
label,
value,
percentage: ((value / total) * 100).toFixed(1)
}));
}
/**
* Get work mode distribution for a specific skill
* @param {string} skillName - The skill to analyze
* @returns {Array} Work mode data for pie chart
*/
getWorkModeData(skillName) {
const filteredOffers = this.filterBySkill(skillName);
if (filteredOffers.length === 0) {
return [];
}
const workModeCounts = {};
filteredOffers.forEach(offer => {
let mode = offer.work_mode;
if (!mode || mode.trim() === '') {
mode = 'Unknown';
}
// Normalize the mode name
const normalizedMode = mode
.split(' ')
.map(word => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase())
.join(' ');
workModeCounts[normalizedMode] = (workModeCounts[normalizedMode] || 0) + 1;
});
const total = filteredOffers.length;
return Object.entries(workModeCounts)
.map(([label, value]) => ({
label,
value,
percentage: ((value / total) * 100).toFixed(1)
}))
.sort((a, b) => b.value - a.value);
}
/**
* Get contract type distribution for a specific skill
* @param {string} skillName - The skill to analyze
* @returns {Array} Contract type data for pie chart
*/
getContractTypeData(skillName) {
const filteredOffers = this.filterBySkill(skillName);
if (filteredOffers.length === 0) {
return [];
}
const contractTypeCounts = {};
filteredOffers.forEach(offer => {
let contractType = offer.contract_type;
if (!contractType || contractType.trim() === '') {
contractType = 'Unknown';
}
const normalizedType = contractType.trim();
contractTypeCounts[normalizedType] = (contractTypeCounts[normalizedType] || 0) + 1;
});
const total = filteredOffers.length;
return Object.entries(contractTypeCounts)
.map(([label, value]) => ({
label,
value,
percentage: ((value / total) * 100).toFixed(1)
}))
.sort((a, b) => b.value - a.value);
}
/**
* Get total count of offers for a skill
* @param {string} skillName - The skill to count
* @returns {number} Total number of offers
*/
getOfferCount(skillName) {
return this.filterBySkill(skillName).length;
}
}
// Export for use in other scripts
window.SkillDataProcessor = SkillDataProcessor;