544 lines
16 KiB
JavaScript
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* Job Search Parser Demo
*
* Demonstrates the Job Search Parser's capabilities for job market intelligence,
* trend analysis, and competitive insights.
*
* This demo uses simulated data for demonstration purposes.
*/
const { logger } = require("../ai-analyzer");
const fs = require("fs");
const path = require("path");
// Terminal colors for demo output
const colors = {
reset: "\x1b[0m",
bright: "\x1b[1m",
cyan: "\x1b[36m",
green: "\x1b[32m",
yellow: "\x1b[33m",
blue: "\x1b[34m",
magenta: "\x1b[35m",
red: "\x1b[31m",
};
const demo = {
title: (text) =>
console.log(`\n${colors.bright}${colors.cyan}${text}${colors.reset}`),
section: (text) =>
console.log(`\n${colors.bright}${colors.magenta}${text}${colors.reset}`),
success: (text) => console.log(`${colors.green}${text}${colors.reset}`),
info: (text) => console.log(`${colors.blue} ${text}${colors.reset}`),
warning: (text) => console.log(`${colors.yellow}⚠️ ${text}${colors.reset}`),
error: (text) => console.log(`${colors.red}${text}${colors.reset}`),
code: (text) => console.log(`${colors.cyan}${text}${colors.reset}`),
};
// Mock job data for demonstration
const mockJobs = [
{
id: "job_1",
title: "Senior Software Engineer",
company: "TechCorp",
location: "Toronto, Ontario",
remote_type: "hybrid",
salary: { min: 100000, max: 140000, currency: "CAD" },
required_skills: ["React", "Node.js", "TypeScript", "AWS"],
preferred_skills: ["GraphQL", "Docker", "Kubernetes"],
experience_level: "senior",
job_url: "https://example.com/job/1",
posted_date: "2024-01-10T09:00:00Z",
scraped_at: "2024-01-15T10:30:00Z",
},
{
id: "job_2",
title: "Data Scientist",
company: "DataCorp",
location: "Vancouver, British Columbia",
remote_type: "remote",
salary: { min: 90000, max: 130000, currency: "CAD" },
required_skills: ["Python", "SQL", "Machine Learning", "Statistics"],
preferred_skills: ["TensorFlow", "PyTorch", "AWS"],
experience_level: "mid",
job_url: "https://example.com/job/2",
posted_date: "2024-01-09T14:30:00Z",
scraped_at: "2024-01-15T10:30:00Z",
},
{
id: "job_3",
title: "Frontend Developer",
company: "StartupXYZ",
location: "Calgary, Alberta",
remote_type: "onsite",
salary: { min: 70000, max: 95000, currency: "CAD" },
required_skills: ["React", "JavaScript", "CSS", "HTML"],
preferred_skills: ["Vue.js", "TypeScript", "Webpack"],
experience_level: "entry",
job_url: "https://example.com/job/3",
posted_date: "2024-01-08T11:15:00Z",
scraped_at: "2024-01-15T10:30:00Z",
},
{
id: "job_4",
title: "DevOps Engineer",
company: "CloudTech",
location: "Toronto, Ontario",
remote_type: "hybrid",
salary: { min: 95000, max: 125000, currency: "CAD" },
required_skills: ["Docker", "Kubernetes", "AWS", "Linux"],
preferred_skills: ["Terraform", "Jenkins", "Prometheus"],
experience_level: "senior",
job_url: "https://example.com/job/4",
posted_date: "2024-01-07T16:45:00Z",
scraped_at: "2024-01-15T10:30:00Z",
},
{
id: "job_5",
title: "Machine Learning Engineer",
company: "AI Solutions",
location: "Vancouver, British Columbia",
remote_type: "remote",
salary: { min: 110000, max: 150000, currency: "CAD" },
required_skills: ["Python", "TensorFlow", "PyTorch", "ML"],
preferred_skills: ["AWS", "Docker", "Kubernetes", "Spark"],
experience_level: "senior",
job_url: "https://example.com/job/5",
posted_date: "2024-01-06T10:20:00Z",
scraped_at: "2024-01-15T10:30:00Z",
},
];
async function runDemo() {
demo.title("=== Job Search Parser Demo ===");
demo.info(
"This demo showcases the Job Search Parser's capabilities for job market intelligence."
);
demo.info("All data shown is simulated for demonstration purposes.");
demo.info("Press Enter to continue through each section...\n");
await waitForEnter();
// 1. Configuration Demo
await demonstrateConfiguration();
// 2. Job Search Process Demo
await demonstrateJobSearch();
// 3. Market Analysis Demo
await demonstrateMarketAnalysis();
// 4. Trend Analysis Demo
await demonstrateTrendAnalysis();
// 5. Skill Analysis Demo
await demonstrateSkillAnalysis();
// 6. Competitive Intelligence Demo
await demonstrateCompetitiveIntelligence();
// 7. Output Generation Demo
await demonstrateOutputGeneration();
demo.title("=== Demo Complete ===");
demo.success("Job Search Parser demo completed successfully!");
demo.info("Check the README.md for detailed usage instructions.");
}
async function demonstrateConfiguration() {
demo.section("1. Configuration Setup");
demo.info(
"The Job Search Parser uses environment variables and command-line options for configuration."
);
demo.code("// Environment Variables (.env file)");
demo.info("SEARCH_SOURCES=linkedin,indeed,glassdoor");
demo.info("TARGET_ROLES=software engineer,data scientist,product manager");
demo.info("LOCATION_FILTER=Toronto,Vancouver,Calgary");
demo.info("EXPERIENCE_LEVELS=entry,mid,senior");
demo.info("REMOTE_PREFERENCE=remote,hybrid,onsite");
demo.info("ENABLE_SALARY_ANALYSIS=true");
demo.info("ENABLE_SKILL_ANALYSIS=true");
demo.info("ENABLE_TREND_ANALYSIS=true");
demo.code("// Command Line Options");
demo.info('node index.js --roles="frontend developer,backend developer"');
demo.info('node index.js --locations="Toronto,Vancouver"');
demo.info('node index.js --experience="senior" --salary-min=100000');
demo.info('node index.js --remote="remote" --trends --skills');
await waitForEnter();
}
async function demonstrateJobSearch() {
demo.section("2. Job Search Process");
demo.info(
"The parser searches multiple job platforms for relevant positions."
);
const searchSources = ["LinkedIn", "Indeed", "Glassdoor"];
const targetRoles = [
"Software Engineer",
"Data Scientist",
"Frontend Developer",
];
demo.code("// Multi-source job search");
for (const source of searchSources) {
logger.search(`Searching ${source} for job postings...`);
await simulateSearch();
const jobsFound = Math.floor(Math.random() * 200) + 50;
logger.success(`Found ${jobsFound} jobs on ${source}`);
}
demo.code("// Role-specific filtering");
for (const role of targetRoles) {
logger.info(`Filtering for ${role} positions...`);
await simulateProcessing();
const roleJobs = Math.floor(Math.random() * 30) + 10;
logger.success(`Found ${roleJobs} ${role} positions`);
}
await waitForEnter();
}
async function demonstrateMarketAnalysis() {
demo.section("3. Market Analysis");
demo.info(
"The parser analyzes market trends, salary ranges, and job distribution."
);
demo.code("// Market overview analysis");
logger.info("Analyzing market overview...");
await simulateProcessing();
const marketOverview = {
total_jobs: 1250,
average_salary: 95000,
salary_range: { min: 65000, max: 180000, median: 92000 },
remote_distribution: { remote: 45, hybrid: 35, onsite: 20 },
experience_distribution: { entry: 15, mid: 45, senior: 40 },
};
demo.success(`Total jobs found: ${marketOverview.total_jobs}`);
demo.info(
`Average salary: $${marketOverview.average_salary.toLocaleString()}`
);
demo.info(
`Salary range: $${marketOverview.salary_range.min.toLocaleString()} - $${marketOverview.salary_range.max.toLocaleString()}`
);
demo.info(
`Remote work: ${marketOverview.remote_distribution.remote}% remote, ${marketOverview.remote_distribution.hybrid}% hybrid`
);
demo.code("// Geographic distribution");
const locations = {
Toronto: 45,
Vancouver: 30,
Calgary: 15,
Other: 10,
};
Object.entries(locations).forEach(([location, percentage]) => {
demo.info(`${location}: ${percentage}% of jobs`);
});
await waitForEnter();
}
async function demonstrateTrendAnalysis() {
demo.section("4. Trend Analysis");
demo.info(
"The parser identifies growing and declining skills and emerging roles."
);
demo.code("// Skill trend analysis");
logger.info("Analyzing skill trends...");
await simulateProcessing();
const growingSkills = [
{ skill: "React", growth_rate: 25 },
{ skill: "Python", growth_rate: 18 },
{ skill: "AWS", growth_rate: 22 },
{ skill: "TypeScript", growth_rate: 30 },
{ skill: "Docker", growth_rate: 15 },
];
const decliningSkills = [
{ skill: "jQuery", growth_rate: -12 },
{ skill: "PHP", growth_rate: -8 },
{ skill: "Angular", growth_rate: -5 },
];
demo.success("Growing skills:");
growingSkills.forEach((skill) => {
demo.info(` ${skill.skill}: +${skill.growth_rate}% growth`);
});
demo.warning("Declining skills:");
decliningSkills.forEach((skill) => {
demo.info(` ${skill.skill}: ${skill.growth_rate}% decline`);
});
demo.code("// Emerging roles");
const emergingRoles = [
"AI Engineer",
"DevSecOps Engineer",
"Data Engineer",
"Cloud Architect",
"Site Reliability Engineer",
];
demo.success("Emerging roles:");
emergingRoles.forEach((role) => {
demo.info(` ${role}`);
});
await waitForEnter();
}
async function demonstrateSkillAnalysis() {
demo.section("5. Skill Analysis");
demo.info("The parser analyzes skill demand and salary correlation.");
demo.code("// Skill demand analysis");
logger.info("Analyzing skill demand...");
await simulateProcessing();
const skillDemand = {
React: { count: 45, avg_salary: 98000 },
Python: { count: 38, avg_salary: 102000 },
AWS: { count: 32, avg_salary: 105000 },
TypeScript: { count: 28, avg_salary: 95000 },
Docker: { count: 25, avg_salary: 103000 },
"Machine Learning": { count: 22, avg_salary: 115000 },
};
demo.success("Top in-demand skills:");
Object.entries(skillDemand)
.sort((a, b) => b[1].count - a[1].count)
.forEach(([skill, data]) => {
demo.info(
` ${skill}: ${
data.count
} jobs, avg salary $${data.avg_salary.toLocaleString()}`
);
});
demo.code("// Salary correlation analysis");
const salaryCorrelation = [
{ skill: "Machine Learning", correlation: 0.85 },
{ skill: "AWS", correlation: 0.78 },
{ skill: "Docker", correlation: 0.72 },
{ skill: "Python", correlation: 0.68 },
{ skill: "React", correlation: 0.65 },
];
demo.success("Skills with highest salary correlation:");
salaryCorrelation.forEach((item) => {
demo.info(
` ${item.skill}: ${(item.correlation * 100).toFixed(0)}% correlation`
);
});
await waitForEnter();
}
async function demonstrateCompetitiveIntelligence() {
demo.section("6. Competitive Intelligence");
demo.info(
"The parser provides insights into company hiring patterns and salary competitiveness."
);
demo.code("// Company hiring analysis");
logger.info("Analyzing company hiring patterns...");
await simulateProcessing();
const topHirers = [
{ company: "TechCorp", jobs: 25, avg_salary: 105000 },
{ company: "StartupXYZ", jobs: 18, avg_salary: 95000 },
{ company: "DataCorp", jobs: 15, avg_salary: 110000 },
{ company: "CloudTech", jobs: 12, avg_salary: 115000 },
{ company: "AI Solutions", jobs: 10, avg_salary: 120000 },
];
demo.success("Top hiring companies:");
topHirers.forEach((company) => {
demo.info(
` ${company.company}: ${
company.jobs
} jobs, avg salary $${company.avg_salary.toLocaleString()}`
);
});
demo.code("// Salary competitiveness");
const salaryLeaders = [
{ company: "BigTech", avg_salary: 120000, market_position: "leader" },
{ company: "FinTech", avg_salary: 115000, market_position: "leader" },
{ company: "AI Solutions", avg_salary: 120000, market_position: "leader" },
{
company: "StartupXYZ",
avg_salary: 95000,
market_position: "competitive",
},
{ company: "TechCorp", avg_salary: 105000, market_position: "competitive" },
];
demo.success("Salary leaders:");
salaryLeaders.forEach((company) => {
const position = company.market_position === "leader" ? "🏆" : "📊";
demo.info(
` ${position} ${
company.company
}: $${company.avg_salary.toLocaleString()}`
);
});
await waitForEnter();
}
async function demonstrateOutputGeneration() {
demo.section("7. Output Generation");
demo.info(
"Results are saved in multiple formats with comprehensive analysis."
);
demo.code("// Generating comprehensive report");
logger.file("Generating job market analysis report...");
const outputData = {
metadata: {
timestamp: new Date().toISOString(),
search_parameters: {
roles: ["software engineer", "data scientist", "frontend developer"],
locations: ["Toronto", "Vancouver", "Calgary"],
experience_levels: ["entry", "mid", "senior"],
remote_preference: ["remote", "hybrid", "onsite"],
},
total_jobs_found: 1250,
analysis_duration_seconds: 45,
},
market_overview: {
total_jobs: 1250,
average_salary: 95000,
salary_range: { min: 65000, max: 180000, median: 92000 },
remote_distribution: { remote: 45, hybrid: 35, onsite: 20 },
experience_distribution: { entry: 15, mid: 45, senior: 40 },
},
trends: {
growing_skills: [
{ skill: "React", growth_rate: 25 },
{ skill: "Python", growth_rate: 18 },
{ skill: "AWS", growth_rate: 22 },
],
declining_skills: [
{ skill: "jQuery", growth_rate: -12 },
{ skill: "PHP", growth_rate: -8 },
],
emerging_roles: ["AI Engineer", "DevSecOps Engineer", "Data Engineer"],
},
jobs: mockJobs,
analysis: {
skill_demand: {
React: { count: 45, avg_salary: 98000 },
Python: { count: 38, avg_salary: 102000 },
AWS: { count: 32, avg_salary: 105000 },
},
company_insights: {
top_hirers: [
{ company: "TechCorp", jobs: 25 },
{ company: "StartupXYZ", jobs: 18 },
],
salary_leaders: [
{ company: "BigTech", avg_salary: 120000 },
{ company: "FinTech", avg_salary: 115000 },
],
},
},
};
// Save to demo file
const outputPath = path.join(__dirname, "demo-job-analysis.json");
fs.writeFileSync(outputPath, JSON.stringify(outputData, null, 2));
demo.success(`Analysis report saved to: ${outputPath}`);
demo.info(`Total jobs analyzed: ${outputData.metadata.total_jobs_found}`);
demo.info(
`Analysis duration: ${outputData.metadata.analysis_duration_seconds} seconds`
);
demo.code("// Output formats available");
demo.info("📁 JSON: Comprehensive analysis with metadata");
demo.info("📊 CSV: Tabular data for spreadsheet analysis");
demo.info("📈 Charts: Visual trend analysis");
demo.info("📋 Summary: Executive summary report");
await waitForEnter();
}
// Helper functions
function waitForEnter() {
return new Promise((resolve) => {
const readline = require("readline");
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout,
});
rl.question("\nPress Enter to continue...", () => {
rl.close();
resolve();
});
});
}
async function simulateSearch() {
return new Promise((resolve) => {
const steps = [
"Connecting to source",
"Searching jobs",
"Filtering results",
"Extracting data",
];
let i = 0;
const interval = setInterval(() => {
if (i < steps.length) {
logger.info(steps[i]);
i++;
} else {
clearInterval(interval);
resolve();
}
}, 600);
});
}
async function simulateProcessing() {
return new Promise((resolve) => {
const dots = [".", "..", "..."];
let i = 0;
const interval = setInterval(() => {
process.stdout.write(`\rProcessing${dots[i]}`);
i = (i + 1) % dots.length;
}, 500);
setTimeout(() => {
clearInterval(interval);
process.stdout.write("\r");
resolve();
}, 2000);
});
}
// Run the demo if this file is executed directly
if (require.main === module) {
runDemo().catch((error) => {
demo.error(`Demo failed: ${error.message}`);
process.exit(1);
});
}
module.exports = { runDemo };