Saahil-doryu commited on
Commit
28b5ddf
·
verified ·
1 Parent(s): ae72574

Upload 18 files

Browse files
ClearPassAIApp.java ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
 
1
+ import javax.swing.*;
2
+
3
+ public class ClearPassAIApp {
4
+ public static void main(String[] args) {
5
+ SwingUtilities.invokeLater(() -> {
6
+ ClearPassAIGUI gui = new ClearPassAIGUI();
7
+ gui.setVisible(true);
8
+ });
9
+ }
10
+ }
ClearPassAIGUI.java ADDED
@@ -0,0 +1,113 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import javax.swing.*;
2
+ import java.awt.*;
3
+ import java.io.FileInputStream;
4
+ import java.io.IOException;
5
+ import java.util.Properties;
6
+
7
+ public class ClearPassAIGUI extends JFrame {
8
+ private CardLayout cardLayout;
9
+ private JPanel mainPanel;
10
+ private LoginPage loginPage;
11
+ private WelcomeScreen welcomeScreen;
12
+ private InterviewScreen interviewScreen;
13
+ private ResultScreen resultScreen;
14
+ private String role;
15
+ private String currentUser;
16
+ private int questionCount = 5;
17
+ private GeminiClient geminiClient;
18
+ private ESpeakTTSClient ttsClient;
19
+ private DataModel dataModel;
20
+
21
+ public ClearPassAIGUI() {
22
+ setTitle("ClearPass AI - Interview Coach");
23
+ setSize(900, 700);
24
+ setDefaultCloseOperation(EXIT_ON_CLOSE);
25
+
26
+ Properties props = loadConfig();
27
+ String geminiApiKey = props.getProperty("GEMINI_API_KEY");
28
+
29
+ geminiClient = new GeminiClient(geminiApiKey, "gemini-1.5-flash");
30
+ ttsClient = new ESpeakTTSClient();
31
+ dataModel = new DataModel();
32
+
33
+ cardLayout = new CardLayout();
34
+ mainPanel = new JPanel(cardLayout);
35
+
36
+ loginPage = new LoginPage(this);
37
+ welcomeScreen = new WelcomeScreen(this);
38
+ resultScreen = new ResultScreen(this);
39
+
40
+ mainPanel.add(loginPage, "Login");
41
+ mainPanel.add(welcomeScreen, "Welcome");
42
+ mainPanel.add(resultScreen, "Results");
43
+
44
+ add(mainPanel);
45
+ showScreen("Login");
46
+ }
47
+
48
+ private Properties loadConfig() {
49
+ Properties props = new Properties();
50
+ try (FileInputStream fis = new FileInputStream("config.properties")) {
51
+ props.load(fis);
52
+ } catch (IOException e) {
53
+ JOptionPane.showMessageDialog(this, "Configuration file not found", "Error", JOptionPane.ERROR_MESSAGE);
54
+ }
55
+ return props;
56
+ }
57
+
58
+ public void showScreen(String screenName) {
59
+ cardLayout.show(mainPanel, screenName);
60
+ }
61
+
62
+ public void startSession(String role, int questionCount) {
63
+ this.role = role;
64
+ this.questionCount = questionCount;
65
+ this.dataModel = new DataModel();
66
+ interviewScreen = new InterviewScreen(this, questionCount);
67
+ JScrollPane scrollPane = new JScrollPane(interviewScreen);
68
+ mainPanel.add(scrollPane, "Interview");
69
+ showScreen("Interview");
70
+ }
71
+
72
+ public void finishSession() {
73
+ resultScreen = new ResultScreen(this);
74
+ mainPanel.add(resultScreen, "Results");
75
+ showScreen("Results");
76
+ }
77
+
78
+ public GeminiClient getGeminiClient() {
79
+ return geminiClient;
80
+ }
81
+
82
+ public String getRole() {
83
+ return role;
84
+ }
85
+
86
+ public void setRole(String role) {
87
+ this.role = role;
88
+ }
89
+
90
+ public DataModel getDataModel() {
91
+ return dataModel;
92
+ }
93
+
94
+ public int getQuestionCount() {
95
+ return questionCount;
96
+ }
97
+
98
+ public void setQuestionCount(int questionCount) {
99
+ this.questionCount = questionCount;
100
+ }
101
+
102
+ public String getCurrentUser() {
103
+ return currentUser;
104
+ }
105
+
106
+ public void setCurrentUser(String currentUser) {
107
+ this.currentUser = currentUser;
108
+ }
109
+
110
+ public ESpeakTTSClient getTTSClient() {
111
+ return ttsClient;
112
+ }
113
+ }
DataModel.java ADDED
@@ -0,0 +1,18 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import java.util.ArrayList;
2
+ import java.util.List;
3
+
4
+ public class DataModel {
5
+ private List<QuestionData> history;
6
+
7
+ public DataModel() {
8
+ history = new ArrayList<>();
9
+ }
10
+
11
+ public void setHistory(QuestionData qd) {
12
+ history.add(qd);
13
+ }
14
+
15
+ public List<QuestionData> getHistory() {
16
+ return history;
17
+ }
18
+ }
ESpeakTTSClient.java ADDED
@@ -0,0 +1,77 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import java.io.*;
2
+
3
+ public class ESpeakTTSClient {
4
+ private Process currentProcess;
5
+
6
+ public ESpeakTTSClient() {
7
+ // Check if espeak is installed
8
+ try {
9
+ Process process = Runtime.getRuntime().exec("espeak --version");
10
+ BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
11
+ String version = reader.readLine();
12
+ System.out.println("eSpeak version: " + version);
13
+
14
+ int exitCode = process.waitFor();
15
+ if (exitCode != 0) {
16
+ throw new RuntimeException("eSpeak is not installed. Please install it first.");
17
+ }
18
+ } catch (IOException | InterruptedException e) {
19
+ throw new RuntimeException("Error checking eSpeak installation: " + e.getMessage());
20
+ }
21
+ }
22
+
23
+ public void speakText(String text) throws IOException {
24
+ try {
25
+ // Stop any existing speech
26
+ stopSpeaking();
27
+
28
+ System.out.println("Attempting to speak text: " + text);
29
+
30
+ // Use espeak to generate speech directly
31
+ ProcessBuilder pb = new ProcessBuilder(
32
+ "espeak",
33
+ "-v", "en-gb", // British English voice
34
+ "-s", "120", // Slower speed for clarity
35
+ "-p", "50", // Medium pitch
36
+ "-a", "100", // Full amplitude
37
+ "-g", "5", // Word gap
38
+ "-k", "5", // Emphasis
39
+ text // Text to speak
40
+ );
41
+
42
+ System.out.println("Starting eSpeak process...");
43
+ currentProcess = pb.start();
44
+
45
+ // Capture any error output
46
+ BufferedReader errorReader = new BufferedReader(new InputStreamReader(currentProcess.getErrorStream()));
47
+ String errorLine;
48
+ while ((errorLine = errorReader.readLine()) != null) {
49
+ System.err.println("eSpeak error: " + errorLine);
50
+ }
51
+
52
+ int exitCode = currentProcess.waitFor();
53
+ System.out.println("eSpeak process completed with exit code: " + exitCode);
54
+
55
+ if (exitCode != 0) {
56
+ System.err.println("Error generating speech with exit code: " + exitCode);
57
+ throw new IOException("Error generating speech: " + exitCode);
58
+ }
59
+
60
+ } catch (InterruptedException e) {
61
+ System.err.println("Speech generation interrupted: " + e.getMessage());
62
+ throw new IOException("Speech generation interrupted: " + e.getMessage());
63
+ }
64
+ }
65
+
66
+ public void stopSpeaking() {
67
+ if (currentProcess != null && currentProcess.isAlive()) {
68
+ currentProcess.destroy();
69
+ try {
70
+ currentProcess.waitFor();
71
+ } catch (InterruptedException e) {
72
+ System.err.println("Error stopping speech: " + e.getMessage());
73
+ }
74
+ currentProcess = null;
75
+ }
76
+ }
77
+ }
GeminiClient.java ADDED
@@ -0,0 +1,64 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import java.io.*;
2
+ import java.net.HttpURLConnection;
3
+ import java.net.URL;
4
+ import org.json.JSONArray;
5
+ import org.json.JSONObject;
6
+
7
+ public class GeminiClient {
8
+ private final String apiKey;
9
+ private final String model;
10
+
11
+ public GeminiClient(String apiKey, String model) {
12
+ this.apiKey = apiKey;
13
+ this.model = model;
14
+ }
15
+
16
+ public String generateResponse(String prompt) throws IOException {
17
+ String safePrompt = prompt.replace("\"", "\\\"");
18
+ String inputJson = "{\n" +
19
+ " \"contents\": [\n" +
20
+ " {\n" +
21
+ " \"parts\": [\n" +
22
+ " { \"text\": \"" + safePrompt + "\" }\n" +
23
+ " ]\n" +
24
+ " }\n" +
25
+ " ]\n" +
26
+ "}";
27
+
28
+ URL url = new URL(
29
+ "https://generativelanguage.googleapis.com/v1beta/models/" + model + ":generateContent?key=" + apiKey);
30
+ HttpURLConnection conn = (HttpURLConnection) url.openConnection();
31
+ conn.setRequestMethod("POST");
32
+ conn.setRequestProperty("Content-Type", "application/json");
33
+ conn.setDoOutput(true);
34
+
35
+ try (OutputStream os = conn.getOutputStream()) {
36
+ os.write(inputJson.getBytes("utf-8"));
37
+ }
38
+
39
+ int status = conn.getResponseCode();
40
+ InputStream stream = (status == 200) ? conn.getInputStream() : conn.getErrorStream();
41
+ BufferedReader br = new BufferedReader(new InputStreamReader(stream, "utf-8"));
42
+
43
+ StringBuilder response = new StringBuilder();
44
+ String line;
45
+ while ((line = br.readLine()) != null) {
46
+ response.append(line.trim());
47
+ }
48
+ br.close();
49
+
50
+ return extractTextFromResponse(response.toString());
51
+ }
52
+
53
+ private String extractTextFromResponse(String raw) {
54
+ try {
55
+ JSONObject json = new JSONObject(raw);
56
+ JSONArray candidates = json.getJSONArray("candidates");
57
+ JSONObject content = candidates.getJSONObject(0).getJSONObject("content");
58
+ JSONArray parts = content.getJSONArray("parts");
59
+ return parts.getJSONObject(0).getString("text");
60
+ } catch (Exception e) {
61
+ return "Error: Could not parse response.";
62
+ }
63
+ }
64
+ }
GoogleTTSClient.java ADDED
@@ -0,0 +1,83 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import java.io.*;
2
+ import java.net.HttpURLConnection;
3
+ import java.net.URL;
4
+ import javax.sound.sampled.*;
5
+ import org.json.JSONObject;
6
+
7
+ public class GoogleTTSClient {
8
+ private final String apiKey;
9
+ private final String voiceName = "en-US-Neural2-F"; // Female voice
10
+ private final String languageCode = "en-US";
11
+
12
+ public GoogleTTSClient(String apiKey) {
13
+ this.apiKey = apiKey;
14
+ }
15
+
16
+ public void speakText(String text) throws IOException {
17
+ String inputJson = "{\n" +
18
+ " \"input\": {\n" +
19
+ " \"text\": \"" + text.replace("\"", "\\\"") + "\"\n" +
20
+ " },\n" +
21
+ " \"voice\": {\n" +
22
+ " \"languageCode\": \"" + languageCode + "\",\n" +
23
+ " \"name\": \"" + voiceName + "\"\n" +
24
+ " },\n" +
25
+ " \"audioConfig\": {\n" +
26
+ " \"audioEncoding\": \"LINEAR16\",\n" +
27
+ " \"speakingRate\": 1.0,\n" +
28
+ " \"pitch\": 0.0\n" +
29
+ " }\n" +
30
+ "}";
31
+
32
+ URL url = new URL("https://texttospeech.googleapis.com/v1/text:synthesize?key=" + apiKey);
33
+ HttpURLConnection conn = (HttpURLConnection) url.openConnection();
34
+ conn.setRequestMethod("POST");
35
+ conn.setRequestProperty("Content-Type", "application/json");
36
+ conn.setDoOutput(true);
37
+
38
+ try (OutputStream os = conn.getOutputStream()) {
39
+ os.write(inputJson.getBytes("utf-8"));
40
+ }
41
+
42
+ int status = conn.getResponseCode();
43
+ if (status == 200) {
44
+ try (InputStream is = conn.getInputStream()) {
45
+ // Parse the response
46
+ BufferedReader br = new BufferedReader(new InputStreamReader(is));
47
+ StringBuilder response = new StringBuilder();
48
+ String line;
49
+ while ((line = br.readLine()) != null) {
50
+ response.append(line);
51
+ }
52
+
53
+ JSONObject jsonResponse = new JSONObject(response.toString());
54
+ String audioContent = jsonResponse.getString("audioContent");
55
+
56
+ // Decode base64 audio content
57
+ byte[] audioBytes = java.util.Base64.getDecoder().decode(audioContent);
58
+
59
+ // Save to temporary file
60
+ File tempFile = File.createTempFile("speech", ".wav");
61
+ try (FileOutputStream fos = new FileOutputStream(tempFile)) {
62
+ fos.write(audioBytes);
63
+ }
64
+
65
+ // Play the audio
66
+ try (AudioInputStream audioIn = AudioSystem.getAudioInputStream(tempFile)) {
67
+ Clip clip = AudioSystem.getClip();
68
+ clip.open(audioIn);
69
+ clip.start();
70
+ clip.drain();
71
+ clip.close();
72
+ } catch (UnsupportedAudioFileException | LineUnavailableException e) {
73
+ throw new IOException("Error playing audio: " + e.getMessage());
74
+ }
75
+
76
+ // Clean up
77
+ tempFile.delete();
78
+ }
79
+ } else {
80
+ throw new IOException("Error: " + status);
81
+ }
82
+ }
83
+ }
InterviewScreen.java ADDED
@@ -0,0 +1,211 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import javax.swing.*;
2
+ import java.awt.*;
3
+ import java.awt.event.*;
4
+ import java.io.*;
5
+
6
+ public class InterviewScreen extends JPanel {
7
+ private ClearPassAIGUI controller;
8
+ private JTextArea questionArea;
9
+ private JTextArea answerInput;
10
+ private JTextArea feedbackArea;
11
+ private JButton generateBtn, nextBtn, evaluateBtn, submitBtn, readBtn, stopBtn;
12
+ private JLabel timerLabel, counterLabel, welcomeLabel;
13
+ private Timer timer;
14
+ private int timeLeft = 60;
15
+ private int answeredCount = 0;
16
+ private int totalQuestions;
17
+
18
+ public InterviewScreen(ClearPassAIGUI controller, int questionCount) {
19
+ this.controller = controller;
20
+ this.totalQuestions = questionCount;
21
+ setLayout(new BorderLayout(10, 10));
22
+
23
+ String username = controller.getCurrentUser();
24
+ welcomeLabel = new JLabel("Welcome, " + username + "!");
25
+ welcomeLabel.setFont(new Font("Arial", Font.BOLD, 16));
26
+ welcomeLabel.setHorizontalAlignment(SwingConstants.CENTER);
27
+
28
+ questionArea = createTextArea(false);
29
+ answerInput = createTextArea(true);
30
+ feedbackArea = createTextArea(false);
31
+ disableCopyPaste(answerInput);
32
+
33
+ generateBtn = new JButton("Generate Question");
34
+ evaluateBtn = new JButton("Evaluate Answer");
35
+ nextBtn = new JButton("Next Question");
36
+ readBtn = new JButton("Read Question");
37
+ stopBtn = new JButton("Stop Reading");
38
+ submitBtn = new JButton("Submit Interview");
39
+ timerLabel = new JLabel("Time Left: 60s");
40
+ counterLabel = new JLabel(getCounterText());
41
+
42
+ JPanel buttonPanel = new JPanel(new GridBagLayout());
43
+ GridBagConstraints gbc = new GridBagConstraints();
44
+ gbc.insets = new Insets(5, 10, 5, 10);
45
+
46
+ gbc.gridx = 0;
47
+ buttonPanel.add(generateBtn, gbc);
48
+ gbc.gridx = 1;
49
+ buttonPanel.add(evaluateBtn, gbc);
50
+ gbc.gridx = 2;
51
+ buttonPanel.add(nextBtn, gbc);
52
+ gbc.gridx = 3;
53
+ buttonPanel.add(readBtn, gbc);
54
+ gbc.gridx = 4;
55
+ buttonPanel.add(stopBtn, gbc);
56
+ gbc.gridx = 5;
57
+ buttonPanel.add(timerLabel, gbc);
58
+ gbc.gridx = 6;
59
+ buttonPanel.add(counterLabel, gbc);
60
+
61
+ JPanel topPanel = new JPanel(new BorderLayout());
62
+ topPanel.add(welcomeLabel, BorderLayout.NORTH);
63
+ topPanel.add(buttonPanel, BorderLayout.CENTER);
64
+
65
+ JPanel centerPanel = new JPanel();
66
+ centerPanel.setLayout(new BoxLayout(centerPanel, BoxLayout.Y_AXIS));
67
+ centerPanel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
68
+ centerPanel.add(new JLabel("Generated Question:"));
69
+ centerPanel.add(new JScrollPane(questionArea));
70
+ centerPanel.add(Box.createVerticalStrut(10));
71
+ centerPanel.add(new JLabel("Your Answer:"));
72
+ centerPanel.add(new JScrollPane(answerInput));
73
+ centerPanel.add(Box.createVerticalStrut(10));
74
+ centerPanel.add(new JLabel("AI Feedback:"));
75
+ centerPanel.add(new JScrollPane(feedbackArea));
76
+
77
+ // Create bottom panel for submit button
78
+ JPanel bottomPanel = new JPanel(new FlowLayout(FlowLayout.CENTER));
79
+ submitBtn.setPreferredSize(new Dimension(200, 40)); // Make submit button larger
80
+ bottomPanel.add(submitBtn);
81
+
82
+ add(topPanel, BorderLayout.NORTH);
83
+ add(centerPanel, BorderLayout.CENTER);
84
+ add(bottomPanel, BorderLayout.SOUTH);
85
+
86
+ addListeners();
87
+ }
88
+
89
+ private JTextArea createTextArea(boolean editable) {
90
+ JTextArea ta = new JTextArea(5, 50);
91
+ ta.setLineWrap(true);
92
+ ta.setWrapStyleWord(true);
93
+ ta.setEditable(editable);
94
+ return ta;
95
+ }
96
+
97
+ private void disableCopyPaste(JTextArea ta) {
98
+ ta.getInputMap().put(KeyStroke.getKeyStroke("ctrl C"), "none");
99
+ ta.getInputMap().put(KeyStroke.getKeyStroke("ctrl V"), "none");
100
+ ta.getInputMap().put(KeyStroke.getKeyStroke("ctrl X"), "none");
101
+ ta.setComponentPopupMenu(null);
102
+ ta.setTransferHandler(null);
103
+ }
104
+
105
+ private void addListeners() {
106
+ generateBtn.addActionListener(e -> generateQuestion());
107
+ evaluateBtn.addActionListener(e -> evaluateAnswer());
108
+ nextBtn.addActionListener(e -> generateBtn.doClick());
109
+ submitBtn.addActionListener(e -> {
110
+ if (answeredCount > 0) {
111
+ controller.finishSession();
112
+ } else {
113
+ JOptionPane.showMessageDialog(this,
114
+ "Please answer at least one question before submitting.",
115
+ "No Answers",
116
+ JOptionPane.WARNING_MESSAGE);
117
+ }
118
+ });
119
+ readBtn.addActionListener(e -> {
120
+ String question = questionArea.getText().trim();
121
+ if (!question.isEmpty()) {
122
+ try {
123
+ controller.getTTSClient().speakText(question);
124
+ } catch (IOException ex) {
125
+ JOptionPane.showMessageDialog(this,
126
+ "Error reading question: " + ex.getMessage(),
127
+ "Error",
128
+ JOptionPane.ERROR_MESSAGE);
129
+ }
130
+ }
131
+ });
132
+ stopBtn.addActionListener(e -> {
133
+ controller.getTTSClient().stopSpeaking();
134
+ });
135
+ }
136
+
137
+ private void generateQuestion() {
138
+ String role = controller.getRole();
139
+ String username = controller.getCurrentUser();
140
+ if (!role.isEmpty()) {
141
+ String prompt = "Imagine you are an expert interviewer. The candidate is applying for the job role: \""
142
+ + role + "\". Please create a thoughtful and beginner-friendly interview question.";
143
+ try {
144
+ questionArea.setText(controller.getGeminiClient().generateResponse(prompt));
145
+ answerInput.setText("");
146
+ feedbackArea.setText("");
147
+ startTimer();
148
+ } catch (IOException ex) {
149
+ questionArea.setText("Error: " + ex.getMessage());
150
+ }
151
+ }
152
+ }
153
+
154
+ private void evaluateAnswer() {
155
+ String question = questionArea.getText().trim();
156
+ String answer = answerInput.getText().trim();
157
+ if (!question.isEmpty() && !answer.isEmpty()) {
158
+ String evalPrompt = "Evaluate this answer to the question: \"" + question + "\".\n\nAnswer: \"" + answer
159
+ + "\"\n\nGive short, clear feedback.";
160
+ try {
161
+ String feedback = controller.getGeminiClient().generateResponse(evalPrompt);
162
+ feedbackArea.setText(feedback);
163
+ recordAnswer(question, answer, feedback);
164
+ } catch (IOException ex) {
165
+ feedbackArea.setText("Error: " + ex.getMessage());
166
+ }
167
+ }
168
+ }
169
+
170
+ private void startTimer() {
171
+ timeLeft = 60;
172
+ if (timer != null)
173
+ timer.stop();
174
+ timer = new Timer(1000, e -> {
175
+ if (timeLeft <= 0) {
176
+ timer.stop();
177
+ nextBtn.doClick();
178
+ } else {
179
+ timeLeft--;
180
+ timerLabel.setText("Time Left: " + timeLeft + "s");
181
+ }
182
+ });
183
+ timer.start();
184
+ }
185
+
186
+ private void recordAnswer(String question, String answer, String feedback) {
187
+ QuestionData qd = new QuestionData();
188
+ qd.setQuestion(question);
189
+ qd.setAnswer(answer);
190
+ qd.setFeedback(feedback);
191
+ controller.getDataModel().setHistory(qd);
192
+
193
+ String filename = controller.getCurrentUser() + "_answers.txt";
194
+ try (BufferedWriter writer = new BufferedWriter(new FileWriter(filename, true))) {
195
+ writer.write("Q: " + question + "\nA: " + answer + "\nF: " + feedback + "\n\n");
196
+ } catch (IOException e) {
197
+ e.printStackTrace();
198
+ }
199
+
200
+ answeredCount++;
201
+ counterLabel.setText(getCounterText());
202
+
203
+ if (answeredCount >= totalQuestions) {
204
+ controller.finishSession();
205
+ }
206
+ }
207
+
208
+ private String getCounterText() {
209
+ return "Answered: " + answeredCount + "/" + totalQuestions;
210
+ }
211
+ }
LoginPage.java ADDED
@@ -0,0 +1,145 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import javax.swing.*;
2
+ import java.awt.*;
3
+ import java.awt.event.*;
4
+ import java.io.*;
5
+
6
+ public class LoginPage extends JPanel {
7
+ private JTextField usernameField;
8
+ private JPasswordField passwordField;
9
+ private JButton loginButton, signupButton;
10
+ private JLabel statusLabel;
11
+ private boolean isSignUpMode = false;
12
+ private ClearPassAIGUI controller;
13
+
14
+ public LoginPage(ClearPassAIGUI controller) {
15
+ this.controller = controller;
16
+ setLayout(new GridBagLayout());
17
+ GridBagConstraints gbc = new GridBagConstraints();
18
+ gbc.insets = new Insets(10, 10, 10, 10);
19
+ gbc.fill = GridBagConstraints.HORIZONTAL;
20
+
21
+ JLabel titleLabel = new JLabel("Welcome to ClearPass AI", SwingConstants.CENTER);
22
+ titleLabel.setFont(new Font("Arial", Font.BOLD, 24));
23
+ gbc.gridx = 0;
24
+ gbc.gridy = 0;
25
+ gbc.gridwidth = 2;
26
+ add(titleLabel, gbc);
27
+
28
+ gbc.gridy++;
29
+ gbc.gridwidth = 1;
30
+ add(new JLabel("Username:"), gbc);
31
+ gbc.gridx = 1;
32
+ usernameField = new JTextField(15);
33
+ add(usernameField, gbc);
34
+
35
+ gbc.gridx = 0;
36
+ gbc.gridy++;
37
+ add(new JLabel("Password:"), gbc);
38
+ gbc.gridx = 1;
39
+ passwordField = new JPasswordField(15);
40
+ add(passwordField, gbc);
41
+
42
+ gbc.gridx = 0;
43
+ gbc.gridy++;
44
+ gbc.gridwidth = 2;
45
+ loginButton = new JButton("Login");
46
+ signupButton = new JButton("Sign Up");
47
+ JPanel buttonPanel = new JPanel(new FlowLayout());
48
+ buttonPanel.add(loginButton);
49
+ buttonPanel.add(signupButton);
50
+ add(buttonPanel, gbc);
51
+
52
+ gbc.gridy++;
53
+ statusLabel = new JLabel("", SwingConstants.CENTER);
54
+ add(statusLabel, gbc);
55
+
56
+ loginButton.addActionListener(e -> {
57
+ if (isSignUpMode)
58
+ handleSignUp();
59
+ else
60
+ handleLogin();
61
+ });
62
+
63
+ signupButton.addActionListener(e -> toggleMode());
64
+ }
65
+
66
+ private void toggleMode() {
67
+ isSignUpMode = !isSignUpMode;
68
+ loginButton.setText(isSignUpMode ? "Create Account" : "Login");
69
+ signupButton.setText(isSignUpMode ? "Back to Login" : "Sign Up");
70
+ statusLabel.setText("");
71
+ }
72
+
73
+ private void handleLogin() {
74
+ String username = usernameField.getText().trim();
75
+ String password = new String(passwordField.getPassword());
76
+
77
+ if (username.isEmpty() || password.isEmpty()) {
78
+ showMessage("Please enter both fields", Color.RED);
79
+ return;
80
+ }
81
+
82
+ if (authenticate(username, password)) {
83
+ controller.setCurrentUser(username);
84
+ controller.showScreen("Welcome");
85
+ } else {
86
+ showMessage("Invalid credentials", Color.RED);
87
+ }
88
+ }
89
+
90
+ private void handleSignUp() {
91
+ String username = usernameField.getText().trim();
92
+ String password = new String(passwordField.getPassword());
93
+
94
+ if (username.isEmpty() || password.isEmpty()) {
95
+ showMessage("Please fill all fields", Color.RED);
96
+ return;
97
+ }
98
+
99
+ File file = new File("users.txt");
100
+ try {
101
+ file.createNewFile();
102
+ BufferedReader reader = new BufferedReader(new FileReader(file));
103
+ String line;
104
+ while ((line = reader.readLine()) != null) {
105
+ if (line.startsWith(username + ":")) {
106
+ reader.close();
107
+ showMessage("Username already exists", Color.RED);
108
+ return;
109
+ }
110
+ }
111
+ reader.close();
112
+
113
+ BufferedWriter writer = new BufferedWriter(new FileWriter(file, true));
114
+ writer.write(username + ":" + password);
115
+ writer.newLine();
116
+ writer.close();
117
+
118
+ JOptionPane.showMessageDialog(this, "Account created successfully!");
119
+ toggleMode();
120
+ } catch (IOException ex) {
121
+ showMessage("Error accessing file", Color.RED);
122
+ }
123
+ }
124
+
125
+ private boolean authenticate(String username, String password) {
126
+ File file = new File("users.txt");
127
+ try (BufferedReader reader = new BufferedReader(new FileReader(file))) {
128
+ String line;
129
+ while ((line = reader.readLine()) != null) {
130
+ String[] parts = line.split(":");
131
+ if (parts.length == 2 && parts[0].equals(username) && parts[1].equals(password)) {
132
+ return true;
133
+ }
134
+ }
135
+ } catch (IOException e) {
136
+ showMessage("Error reading file", Color.RED);
137
+ }
138
+ return false;
139
+ }
140
+
141
+ private void showMessage(String message, Color color) {
142
+ statusLabel.setText(message);
143
+ statusLabel.setForeground(color);
144
+ }
145
+ }
MozillaTTSClient.java ADDED
@@ -0,0 +1,63 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import java.io.*;
2
+ import java.net.HttpURLConnection;
3
+ import java.net.URL;
4
+ import javax.sound.sampled.*;
5
+
6
+ public class MozillaTTSClient {
7
+ private final String voiceId = "en_US/vctk_low"; // Free voice model
8
+ private final String apiUrl = "https://api-inference.huggingface.co/models/mozilla/tts";
9
+
10
+ public MozillaTTSClient() {
11
+ // No API key needed for basic usage
12
+ }
13
+
14
+ public void speakText(String text) throws IOException {
15
+ String inputJson = "{\n" +
16
+ " \"inputs\": \"" + text.replace("\"", "\\\"") + "\",\n" +
17
+ " \"parameters\": {\n" +
18
+ " \"voice_preset\": \"" + voiceId + "\"\n" +
19
+ " }\n" +
20
+ "}";
21
+
22
+ URL url = new URL(apiUrl);
23
+ HttpURLConnection conn = (HttpURLConnection) url.openConnection();
24
+ conn.setRequestMethod("POST");
25
+ conn.setRequestProperty("Content-Type", "application/json");
26
+ conn.setDoOutput(true);
27
+
28
+ try (OutputStream os = conn.getOutputStream()) {
29
+ os.write(inputJson.getBytes("utf-8"));
30
+ }
31
+
32
+ int status = conn.getResponseCode();
33
+ if (status == 200) {
34
+ try (InputStream is = conn.getInputStream()) {
35
+ // Save the audio to a temporary file
36
+ File tempFile = File.createTempFile("speech", ".wav");
37
+ try (FileOutputStream fos = new FileOutputStream(tempFile)) {
38
+ byte[] buffer = new byte[1024];
39
+ int bytesRead;
40
+ while ((bytesRead = is.read(buffer)) != -1) {
41
+ fos.write(buffer, 0, bytesRead);
42
+ }
43
+ }
44
+
45
+ // Play the audio
46
+ try (AudioInputStream audioIn = AudioSystem.getAudioInputStream(tempFile)) {
47
+ Clip clip = AudioSystem.getClip();
48
+ clip.open(audioIn);
49
+ clip.start();
50
+ clip.drain();
51
+ clip.close();
52
+ } catch (UnsupportedAudioFileException | LineUnavailableException e) {
53
+ throw new IOException("Error playing audio: " + e.getMessage());
54
+ }
55
+
56
+ // Clean up the temporary file
57
+ tempFile.delete();
58
+ }
59
+ } else {
60
+ throw new IOException("Error: " + status);
61
+ }
62
+ }
63
+ }
QuestionData.java ADDED
@@ -0,0 +1,35 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ public class QuestionData {
2
+ private String question;
3
+ private String answer;
4
+ private String feedback;
5
+
6
+ public QuestionData() {
7
+ this.question = "";
8
+ this.feedback = "";
9
+ this.answer = "";
10
+ }
11
+
12
+ public void setQuestion(String question) {
13
+ this.question = question;
14
+ }
15
+
16
+ public void setFeedback(String feedback) {
17
+ this.feedback = feedback;
18
+ }
19
+
20
+ public void setAnswer(String answer) {
21
+ this.answer = answer;
22
+ }
23
+
24
+ public String getQuestion() {
25
+ return question;
26
+ }
27
+
28
+ public String getFeedback() {
29
+ return feedback;
30
+ }
31
+
32
+ public String getAnswer() {
33
+ return answer;
34
+ }
35
+ }
README.md CHANGED
@@ -1,12 +1,77 @@
1
- ---
2
- title: AIProject
3
- emoji: 😻
4
- colorFrom: blue
5
- colorTo: yellow
6
- sdk: gradio
7
- sdk_version: 5.27.1
8
- app_file: app.py
9
- pinned: false
10
- ---
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
11
 
12
- Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # ClearPass AI - Java Swing Interview Simulator
2
+
3
+ ClearPass AI is a Java Swing-based desktop application that simulates AI-powered interview questions. It allows users to log in, specify a job role, answer AI-generated questions, receive real-time feedback, and view or export their session summaries.
4
+
5
+ ## ✨ Features
6
+ - 🔐 User login and signup system (local file-based)
7
+ - 🧠 AI-generated interview questions based on job role (using Google's Gemini API)
8
+ - 😊 Sentiment analysis of answers (using HuggingFace's DistilBERT model)
9
+ - ✅ Real-time feedback on user responses
10
+ - ⏱ Countdown timer per question
11
+ - 📊 Progress tracker (answered vs. remaining)
12
+ - 💾 Save full session summary and result to `.txt` files
13
+ - 🧾 Clean MVC-based structure for easy updates
14
+
15
+ ## 🛠 Requirements
16
+ - Java 8 or higher
17
+ - Internet connection (for AI API calls)
18
+ - JSON library (org.json)
19
+
20
+ ## 📁 File Structure
21
+ ```
22
+ project-root/
23
+ ├── ClearPassAIApp.java
24
+ ├── ClearPassAIGUI.java
25
+ ├── InterviewScreen.java
26
+ ├── LoginPage.java
27
+ ├── WelcomeScreen.java
28
+ ├── ResultScreen.java
29
+ ├── DataModel.java
30
+ ├── QuestionData.java
31
+ ├── GeminiClient.java
32
+ ├── HuggingFaceClient.java
33
+ ├── users.txt
34
+ ├── config.properties <-- contains your API keys
35
+ ```
36
+
37
+ ## 🔑 Setup API Keys
38
+ 1. Create a `config.properties` file in the root directory.
39
+ 2. Add your API keys:
40
+
41
+ ```properties
42
+ GEMINI_API_KEY=your_gemini_api_key_here
43
+ HUGGINGFACE_API_KEY=your_huggingface_api_key_here
44
+ ```
45
 
46
+ ## ▶️ How to Run
47
+ ### If using terminal:
48
+ ```bash
49
+ javac -cp ".:lib/json-20250107.jar" *.java
50
+ java -cp ".:lib/json-20250107.jar" ClearPassAIApp
51
+ ```
52
+
53
+ ### If using an IDE:
54
+ - Open the project.
55
+ - Add the JSON library to your project dependencies.
56
+ - Set `ClearPassAIApp` as the main class.
57
+ - Run the project.
58
+
59
+ ## 💬 Sample Credentials
60
+ - Username: `dhruvparmar`
61
+ - Password: `1234`
62
+
63
+ You can create new users via the Sign-Up screen.
64
+
65
+ ## 📂 Output Files
66
+ - `username_answers.txt` → contains each Q&A + feedback
67
+ - `username_summary.txt` → full interview session
68
+ - `username_result.txt` → saved from Result screen (if user clicks save)
69
+
70
+ ## ✅ Future Improvements
71
+ - Add more AI models for different types of analysis
72
+ - Implement voice input/output
73
+ - Add support for different languages
74
+ - Enhance the UI with modern design elements
75
+
76
+ ---
77
+ Made with 💙 by Dhruv Parmar
ResultScreen.java ADDED
@@ -0,0 +1,63 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import javax.swing.*;
2
+ import java.awt.*;
3
+ import java.awt.event.ActionEvent;
4
+ import java.io.*;
5
+ import java.util.List;
6
+
7
+ public class ResultScreen extends JPanel {
8
+ private JTextArea resultArea;
9
+
10
+ public ResultScreen(ClearPassAIGUI controller) {
11
+ setLayout(new BorderLayout());
12
+
13
+ resultArea = new JTextArea();
14
+ resultArea.setEditable(false);
15
+ JScrollPane scrollPane = new JScrollPane(resultArea);
16
+ add(scrollPane, BorderLayout.CENTER);
17
+
18
+ List<QuestionData> history = controller.getDataModel().getHistory();
19
+ int total = controller.getQuestionCount();
20
+ String username = controller.getCurrentUser();
21
+
22
+ if (history.isEmpty()) {
23
+ resultArea.setText("No responses recorded.");
24
+ } else {
25
+ StringBuilder sb = new StringBuilder();
26
+ sb.append("Summary: You answered ").append(history.size()).append(" out of ").append(total)
27
+ .append(" questions.\n\n");
28
+
29
+ for (int i = 0; i < history.size(); i++) {
30
+ QuestionData q = history.get(i);
31
+ sb.append("Q").append(i + 1).append(": ").append(q.getQuestion()).append("\n");
32
+ sb.append("Your Answer: ").append(q.getAnswer()).append("\n");
33
+ sb.append("AI Feedback: ").append(q.getFeedback()).append("\n\n");
34
+ }
35
+
36
+ resultArea.setText(sb.toString());
37
+ }
38
+
39
+ JButton backBtn = new JButton("Back to Welcome");
40
+ backBtn.addActionListener(e -> controller.showScreen("Welcome"));
41
+
42
+ JButton saveBtn = new JButton("Save Result");
43
+ saveBtn.addActionListener(
44
+ (ActionEvent e) -> saveResultToFile(controller.getCurrentUser(), resultArea.getText()));
45
+
46
+ JPanel bottomPanel = new JPanel(new FlowLayout());
47
+ bottomPanel.add(backBtn);
48
+ bottomPanel.add(saveBtn);
49
+
50
+ add(bottomPanel, BorderLayout.SOUTH);
51
+ }
52
+
53
+ private void saveResultToFile(String username, String content) {
54
+ String filename = username + "_result.txt";
55
+ try (BufferedWriter writer = new BufferedWriter(new FileWriter(filename))) {
56
+ writer.write(content);
57
+ JOptionPane.showMessageDialog(this, "Result saved to " + filename);
58
+ } catch (IOException e) {
59
+ JOptionPane.showMessageDialog(this, "Failed to save result.", "Error", JOptionPane.ERROR_MESSAGE);
60
+ e.printStackTrace();
61
+ }
62
+ }
63
+ }
TextToSpeechClient.java ADDED
@@ -0,0 +1,65 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import java.io.*;
2
+ import java.net.HttpURLConnection;
3
+ import java.net.URL;
4
+ import javax.sound.sampled.*;
5
+ import org.json.JSONObject;
6
+
7
+ public class TextToSpeechClient {
8
+ private final String apiKey;
9
+ private final String model = "facebook/fastspeech2-en-ljspeech";
10
+
11
+ public TextToSpeechClient(String apiKey) {
12
+ this.apiKey = apiKey;
13
+ }
14
+
15
+ public void speakText(String text) throws IOException {
16
+ String inputJson = "{\n" +
17
+ " \"inputs\": \"" + text.replace("\"", "\\\"") + "\",\n" +
18
+ " \"parameters\": {\n" +
19
+ " \"return_timestamps\": false\n" +
20
+ " }\n" +
21
+ "}";
22
+
23
+ URL url = new URL("https://api-inference.huggingface.co/models/" + model);
24
+ HttpURLConnection conn = (HttpURLConnection) url.openConnection();
25
+ conn.setRequestMethod("POST");
26
+ conn.setRequestProperty("Authorization", "Bearer " + apiKey);
27
+ conn.setRequestProperty("Content-Type", "application/json");
28
+ conn.setDoOutput(true);
29
+
30
+ try (OutputStream os = conn.getOutputStream()) {
31
+ os.write(inputJson.getBytes("utf-8"));
32
+ }
33
+
34
+ int status = conn.getResponseCode();
35
+ if (status == 200) {
36
+ try (InputStream is = conn.getInputStream()) {
37
+ // Save the audio to a temporary file
38
+ File tempFile = File.createTempFile("speech", ".wav");
39
+ try (FileOutputStream fos = new FileOutputStream(tempFile)) {
40
+ byte[] buffer = new byte[1024];
41
+ int bytesRead;
42
+ while ((bytesRead = is.read(buffer)) != -1) {
43
+ fos.write(buffer, 0, bytesRead);
44
+ }
45
+ }
46
+
47
+ // Play the audio
48
+ try (AudioInputStream audioIn = AudioSystem.getAudioInputStream(tempFile)) {
49
+ Clip clip = AudioSystem.getClip();
50
+ clip.open(audioIn);
51
+ clip.start();
52
+ clip.drain();
53
+ clip.close();
54
+ } catch (UnsupportedAudioFileException | LineUnavailableException e) {
55
+ throw new IOException("Error playing audio: " + e.getMessage());
56
+ }
57
+
58
+ // Clean up the temporary file
59
+ tempFile.delete();
60
+ }
61
+ } else {
62
+ throw new IOException("Error: " + status);
63
+ }
64
+ }
65
+ }
WelcomeScreen.java ADDED
@@ -0,0 +1,37 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import javax.swing.*;
2
+ import java.awt.*;
3
+
4
+ public class WelcomeScreen extends JPanel {
5
+ private ClearPassAIGUI controller;
6
+ private JTextField roleField;
7
+ private JSpinner questionCountSpinner;
8
+
9
+ public WelcomeScreen(ClearPassAIGUI controller) {
10
+ this.controller = controller;
11
+ setLayout(new FlowLayout());
12
+
13
+ add(new JLabel("Enter Job Role:"));
14
+ roleField = new JTextField(20);
15
+ add(roleField);
16
+
17
+ add(new JLabel("Number of Questions:"));
18
+ questionCountSpinner = new JSpinner(new SpinnerNumberModel(5, 1, 20, 1));
19
+ add(questionCountSpinner);
20
+
21
+ JButton startButton = new JButton("Start Interview");
22
+ add(startButton);
23
+
24
+ startButton.addActionListener(e -> {
25
+ String role = roleField.getText().trim();
26
+ int questionCount = (int) questionCountSpinner.getValue();
27
+ if (!role.isEmpty()) {
28
+ controller.setRole(role);
29
+ controller.setQuestionCount(questionCount);
30
+ controller.startSession(role, questionCount);
31
+ } else {
32
+ JOptionPane.showMessageDialog(this, "Please enter a job role.", "Input Error",
33
+ JOptionPane.ERROR_MESSAGE);
34
+ }
35
+ });
36
+ }
37
+ }
json-20210307.jar ADDED
Binary file (69.7 kB). View file
 
json-20231013.jar ADDED
Binary file (74.7 kB). View file
 
json-20250107.jar ADDED
Binary file (81.4 kB). View file
 
users.txt ADDED
@@ -0,0 +1,6 @@
 
 
 
 
 
 
 
1
+ dhruvparmar:1234
2
+ aksha:123
3
+ justin:123
4
+ jason:123
5
+ saahil:123
6
+ justinTest:test