Coder19/interview_system
0
1import time2from typing import List, Dict, Optional3import numpy as np4from datetime import datetime5 6class InterviewMonitor:7 def __init__(self):8 self.typing_patterns: List[Dict] = []9 self.response_times: List[float] = []10 self.suspicious_activities: List[Dict] = []11 self.last_activity_time = time.time()12 13 def reset(self):14 """Reset all monitoring data"""15 self.typing_patterns = []16 self.response_times = []17 self.suspicious_activities = []18 self.last_activity_time = time.time()19 20 def record_response_time(self, response_text: str) -> Optional[Dict]:21 """Monitor response time and length to detect potential cheating"""22 current_time = time.time()23 response_time = current_time - self.last_activity_time24 self.last_activity_time = current_time25 26 # Calculate words per minute27 words = len(response_text.split())28 wpm = (words / response_time) * 60 if response_time > 0 else float('inf')29 30 self.response_times.append(response_time)31 32 suspicious_activity = None33 34 # Check for unusually fast responses (more than 100 WPM)35 if wpm > 100:36 suspicious_activity = {37 'type': 'fast_response',38 'details': f'Unusually fast response: {wpm:.0f} words per minute',39 'severity': 'medium',40 'timestamp': datetime.now().isoformat()41 }42 43 # Check for very long responses that came too quickly44 if words > 50 and response_time < 10:45 suspicious_activity = {46 'type': 'potential_copypaste',47 'details': f'Long response ({words} words) in very short time ({response_time:.1f}s)',48 'severity': 'high',49 'timestamp': datetime.now().isoformat()50 }51 52 if suspicious_activity:53 self.suspicious_activities.append(suspicious_activity)54 55 return suspicious_activity56 57 def analyze_typing_pattern(self, keystrokes: List[Dict]) -> Optional[Dict]:58 """Analyze typing patterns to detect copy-paste or unusual input patterns"""59 if not keystrokes:60 return None61 62 # Calculate time between keystrokes63 intervals = []64 for i in range(1, len(keystrokes)):65 interval = keystrokes[i]['timestamp'] - keystrokes[i-1]['timestamp']66 intervals.append(interval)67 68 if not intervals:69 return None70 71 # Detect sudden bursts of text (potential copy-paste)72 avg_interval = np.mean(intervals)73 std_interval = np.std(intervals)74 75 suspicious_activity = None76 77 if any(interval > avg_interval + 3 * std_interval for interval in intervals):78 suspicious_activity = {79 'type': 'irregular_typing',80 'details': 'Detected irregular typing pattern, possible copy-paste',81 'severity': 'medium',82 'timestamp': datetime.now().isoformat()83 }84 self.suspicious_activities.append(suspicious_activity)85 86 return suspicious_activity87 88 def analyze_video_frame(self, frame_data: Dict) -> Optional[Dict]:89 """Analyze video frame to detect suspicious behavior"""90 suspicious_activity = None91 92 # Check if eyes are looking away from camera93 if frame_data.get('looking_away', False):94 suspicious_activity = {95 'type': 'looking_away',96 'details': 'Candidate frequently looking away from camera',97 'severity': 'low',98 'timestamp': datetime.now().isoformat()99 }100 101 # Check if multiple faces detected102 if frame_data.get('face_count', 1) > 1:103 suspicious_activity = {104 'type': 'multiple_faces',105 'details': f"Detected {frame_data['face_count']} faces in frame",106 'severity': 'high',107 'timestamp': datetime.now().isoformat()108 }109 110 if suspicious_activity:111 self.suspicious_activities.append(suspicious_activity)112 113 return suspicious_activity114 115 def analyze_audio(self, audio_data: Dict) -> Optional[Dict]:116 """Analyze audio to detect potential prompting or background voices"""117 suspicious_activity = None118 119 # Check for multiple voices120 if audio_data.get('voice_count', 1) > 1:121 suspicious_activity = {122 'type': 'multiple_voices',123 'details': 'Detected multiple voices in audio',124 'severity': 'high',125 'timestamp': datetime.now().isoformat()126 }127 128 # Check for background conversation129 if audio_data.get('background_speech', False):130 suspicious_activity = {131 'type': 'background_speech',132 'details': 'Detected background conversation',133 'severity': 'medium',134 'timestamp': datetime.now().isoformat()135 }136 137 if suspicious_activity:138 self.suspicious_activities.append(suspicious_activity)139 140 return suspicious_activity141 142 def get_cheating_report(self) -> Dict:143 """Generate a report of all suspicious activities"""144 severity_counts = {145 'high': len([a for a in self.suspicious_activities if a['severity'] == 'high']),146 'medium': len([a for a in self.suspicious_activities if a['severity'] == 'medium']),147 'low': len([a for a in self.suspicious_activities if a['severity'] == 'low'])148 }149 150 return {151 'total_suspicious_activities': len(self.suspicious_activities),152 'severity_breakdown': severity_counts,153 'activities': self.suspicious_activities,154 'average_response_time': np.mean(self.response_times) if self.response_times else 0,155 'recommendation': self._generate_recommendation(severity_counts)156 }157 158 def _generate_recommendation(self, severity_counts: Dict) -> str:159 """Generate a recommendation based on suspicious activities"""160 total_weighted_score = (161 severity_counts['high'] * 3 +162 severity_counts['medium'] * 2 +163 severity_counts['low'] * 1164 )165 166 if total_weighted_score == 0:167 return "No suspicious activities detected. Interview appears to be conducted fairly."168 elif total_weighted_score < 3:169 return "Minor suspicious activities detected. Manual review recommended."170 elif total_weighted_score < 6:171 return "Multiple suspicious activities detected. Close review strongly recommended."172 else:173 return "Significant suspicious activities detected. Interview validity questionable."