Skip to content

Commit 51addf0

Browse files
committed
feat: implement AIInterview component with multi-accent voice support and session management
1 parent 4a0d926 commit 51addf0

1 file changed

Lines changed: 58 additions & 20 deletions

File tree

client/src/pages/AIInterview.jsx

Lines changed: 58 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -360,25 +360,60 @@ const AIInterview = () => {
360360

361361
let activeVoice = null;
362362
if (browserVoices.length > 0) {
363-
// 1. Try to find matching language and name query
364-
activeVoice = browserVoices.find(bv => {
365-
const bvName = bv.name.toLowerCase();
366-
const bvLang = bv.lang.toLowerCase();
367-
return bvLang.startsWith(customVoice.lang.toLowerCase()) &&
368-
customVoice.baseQuery.some(q => bvName.includes(q));
369-
});
363+
// Find all voices matching the custom voice's target language
364+
const langVoices = browserVoices.filter(bv =>
365+
bv.lang.toLowerCase().replace('_', '-').startsWith(customVoice.lang.toLowerCase())
366+
);
370367

371-
// 2. Try to find matching language start
372-
if (!activeVoice) {
373-
activeVoice = browserVoices.find(bv => bv.lang.toLowerCase().startsWith(customVoice.lang.toLowerCase()));
368+
if (langVoices.length > 0) {
369+
// 1. Try to find a voice matching the specific name query (excluding generic brand names)
370+
const specificQueries = customVoice.baseQuery.filter(q =>
371+
q !== 'google' && q !== 'microsoft' && q !== 'in' && q !== 'us' && q !== 'gb' && q !== 'uk' && q !== 'ca' && q !== 'au' && q !== 'ie' && q !== 'nz'
372+
);
373+
374+
activeVoice = langVoices.find(bv => {
375+
const bvName = bv.name.toLowerCase();
376+
return specificQueries.some(q => bvName.includes(q));
377+
});
378+
379+
// 2. Try to find matching gender within the language voices
380+
if (!activeVoice) {
381+
const targetGender = customVoice.gender; // 'girlish' or 'boyish'
382+
const femaleKeywords = ['female', 'girl', 'woman', 'zira', 'samantha', 'aria', 'hazel', 'heera', 'neerja', 'ananya', 'diya', 'isha', 'lily', 'mia', 'amelia', 'matilda', 'harper', 'sophia', 'saoirse', 'kiwi'];
383+
const maleKeywords = ['male', 'boy', 'man', 'david', 'guy', 'aarav', 'rohan', 'kabir', 'tyler', 'leo', 'ethan', 'oliver', 'harry', 'charlie', 'liam', 'cooper', 'owen', 'connor', 'finn'];
384+
385+
const genderMatchedVoices = langVoices.filter(bv => {
386+
const nameLower = bv.name.toLowerCase();
387+
if (targetGender === 'girlish') {
388+
return femaleKeywords.some(kw => nameLower.includes(kw)) && !maleKeywords.some(kw => nameLower.includes(kw));
389+
} else {
390+
return maleKeywords.some(kw => nameLower.includes(kw)) && !femaleKeywords.some(kw => nameLower.includes(kw));
391+
}
392+
});
393+
394+
if (genderMatchedVoices.length > 0) {
395+
const charCodeSum = customVoice.id.split('').reduce((sum, char) => sum + char.charCodeAt(0), 0);
396+
activeVoice = genderMatchedVoices[charCodeSum % genderMatchedVoices.length];
397+
}
398+
}
399+
400+
// 3. Fallback to any voice of that language (hash/index index)
401+
if (!activeVoice) {
402+
const charCodeSum = customVoice.id.split('').reduce((sum, char) => sum + char.charCodeAt(0), 0);
403+
activeVoice = langVoices[charCodeSum % langVoices.length];
404+
}
374405
}
375-
376-
// 3. Try standard English voice
406+
407+
// 4. Fallback to any english voice matching gender/index
377408
if (!activeVoice) {
378-
activeVoice = browserVoices.find(bv => bv.lang.toLowerCase().startsWith('en'));
409+
const englishVoices = browserVoices.filter(bv => bv.lang.toLowerCase().startsWith('en'));
410+
if (englishVoices.length > 0) {
411+
const charCodeSum = customVoice.id.split('').reduce((sum, char) => sum + char.charCodeAt(0), 0);
412+
activeVoice = englishVoices[charCodeSum % englishVoices.length];
413+
}
379414
}
380415

381-
// 4. Fallback to first available browser voice
416+
// 5. Fallback to first available browser voice
382417
if (!activeVoice) {
383418
activeVoice = browserVoices[0];
384419
}
@@ -549,13 +584,16 @@ The interview is conducted end-to-end based strictly on the candidate's resume,
549584
Candidate Target Role/Title: "${targetRole}"
550585
Candidate Years of Experience (YoE): "${yoe}"
551586
Difficulty Level: "${difficulty}"
587+
Interview Duration: ${duration} minutes (approx. 10 questions total)
588+
589+
Sequence & Importance of Questions:
590+
You must strictly sequence questions from the most important and frequently asked to the least:
591+
- Question 1 to 3 (Core & High-Impact): Ask the absolute most critical, common, and important questions related to the candidate's primary skills, target role duties, and major projects. These should be the high-priority concepts or tools they must master.
592+
- Question 4 to 6 (Applied & Scenario-Based): Ask key situational, architectural, or scenario-based questions about how they implement their skills, handle trade-offs, or make design choices.
593+
- Question 7 to 9 (Secondary Skills & Behavioral): Ask about secondary tools mentioned in their resume, team collaboration, or behavioral scenarios relevant to their experience level.
594+
- Question 10 and onwards (Niche Deep-Dives): Ask about specific minor details, niche tools, or lesser-known details from their resume.
552595
553-
Sequence of Questions Instruction:
554-
- The interview sequence should progress logically:
555-
- Question 1 & 2: Ask the most frequently asked, most common, core, and most important questions for this role/experience level and key skills from their resume.
556-
- Question 3 & 4: Ask moderately common, secondary skills, or scenario-based questions from their resume.
557-
- Question 5 and onwards: Ask less frequently asked, niche, or deep-dive details from their resume.
558-
- We are currently on Question #${sessionLogs.length + 1} of this interview session. Generate the single next appropriate question matching this sequence stage.
596+
We are currently on Question #${sessionLogs.length + 1} of this session. Generate the single next question that matches this sequence stage. Make sure the question is highly productive, allowing the candidate to learn the most important lessons first.
559597
560598
Exclusions to avoid repetition:
561599
${exclusionsPrompt}

0 commit comments

Comments
 (0)