$('body').css("margin", "10px");
$('body').css("padding", "10px");
document.write(`
<h2>Spam/Ham Analyser</h2>
<div style="display:flex; gap:20px; background:#e6ffe6; padding:20px; border-radius:10px; border:2px solid #b2d8b2; width:1000px;">
<div>
<label>Gemini API Key:</label><br>
<input id="apiKey1" type="text" style="width:250px; margin-top:10px">
</div>
<div>
<label>Groq API Key:</label><br>
<input id="apiKey2" type="text" style="width:250px; margin-top:10px">
</div>
<div>
<button onclick="setKeys()" class="ab-normbutton"
style="height:40px;padding:0 15px;cursor:pointer;background:#4CAF50;color:white;border:none;border-radius:5px; margin-top:15px">
<b>Set API Keys</b>
</button>
</div>
</div>
<div style="display:flex; gap:30px;background:#e6ffe6;padding:20px;border-radius:10px;border:2px solid #b2d8b2;width:1000px;margin-top:10px;">
<div>
<label>Enter your message:</label><br>
<textarea id="promptInput" rows="4" cols="50" style="margin-top:5px" placeholder="Write your message here..."></textarea>
</div>
<div>
<button onclick="analyse()" id="btnAnalyse"
style="height:40px;padding:0 15px;margin-top:30px;cursor:pointer;background:#4CAF50;color:white;border:none;border-radius:5px; font-size: 15px;">
<b>Analyse</b>
</button>
</div>
</div>
<hr>
<div style="background:#e6ffe6;padding:20px;border-radius:10px;border:2px solid #b2d8b2;margin-top:20px; width:1000px;">
<h3>API Responses</h3>
<div style="display:flex;gap:20px;flex-wrap:wrap;">
<!-- Gemini -->
<div style="flex:1; padding:10px; background:#d9f2d9; border:2px solid #4CAF50; border-radius:10px;">
<h4 style="margin-bottom:10px;">Gemini Response</h4>
<div style="padding:10px; background:white; border:1px solid #ccc; border-radius:5px; margin-bottom:10px;">
<strong>Status:</strong> <span id="status1">N/A</span>
</div>
<div style="padding:10px; background:white; border:1px solid #ccc; border-radius:5px;">
<strong>Accuracy:</strong> <span id="accuracy1">0%</span>
</div>
</div>
<!-- Groq -->
<div style="flex:1; padding:10px; background:#d9f2d9; border:2px solid #4CAF50; border-radius:10px;">
<h4 style="margin-bottom:10px;">Groq Response</h4>
<div style="padding:10px; background:white; border:1px solid #ccc; border-radius:5px; margin-bottom:10px;">
<strong>Status:</strong> <span id="status2">N/A</span>
</div>
<div style="padding:10px; background:white; border:1px solid #ccc; border-radius:5px;">
<strong>Accuracy:</strong> <span id="accuracy2">0%</span>
</div>
</div>
</div>
<!-- Dataset Result (hidden by default) -->
<div id="datasetResultBox" style="display:none; margin-top:20px; padding:10px; background:white; border:1px solid #ccc; border-radius:5px;">
<strong>Correct response: </strong> <span id="datasetResult"></span>
</div>
<!-- Custom Alert (hidden by default) -->
<div id="customAlertBox" style="display:none; margin-top:10px; padding:10px; background:#ffe6e6; border:1px solid #ff4d4d; border-radius:5px; color:red;">
<span id="custom-alert"></span>
</div>
</div>
`);
// Global variables
let GEMINI_KEY = "";
let GROQ_KEY = "";
let DATASET = [];
const GEMINI_URL = "https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-flash:generateContent";
const GROQ_URL = "https://api.groq.com/openai/v1/chat/completions";
let startTime = null;
const DATASET_URL = "https://raw.githubusercontent.com/justmarkham/DAT8/master/data/sms.tsv";
// function to set API keys
function setKeys() {
const k1 = document.getElementById("apiKey1").value.trim();
const k2 = document.getElementById("apiKey2").value.trim();
if (!k1 || !k2) {
showCustomAlert("Both API keys are required");
return;
}
if (k1 === k2) {
showCustomAlert("Both keys cannot be the same.");
return;
}
GEMINI_KEY = k1;
GROQ_KEY = k2;
showCustomAlert("API Keys set successfully");
}
// function to analyse message whether its spam or ham
function analyse() {
//begin by setting status and accuracy as N/A and 0%
document.getElementById("status1").innerText = "N/A";
document.getElementById("status2").innerText = "N/A";
document.getElementById("accuracy1").innerText = "0%";
document.getElementById("accuracy2").innerText = "0%";
// Check if both API keys are set
if(!GEMINI_KEY || !GROQ_KEY){
showCustomAlert("Set API keys.");
return;
}
// Check if dataset is choosen
if(DATASET.length === 0){
showCustomAlert("Choose Dataset.");
return;
}
//Check if the message is provided to analyse
const message = document.getElementById("promptInput").value.trim();
if (!message) {
showCustomAlert("Please enter a message.");
return;
}
console.info("Analysing started");
const prompt = `Classify this text strictly as "spam" or "ham": ${message}`;
console.log("prompt: ", prompt);
startTimer();
analyseWithGroq(prompt);
analyseWithGemini(prompt);
}
// function to analyse the message using Gemini Call, passing promt as varible
function analyseWithGemini(prompt) {
document.getElementById("status1").innerText = "Analyzing...";
console.info("Analysing with Gemini started");
fetch(GEMINI_URL + "?key=" + GEMINI_KEY, {
method: "POST",
headers: {"Content-Type": "application/json"},
body: JSON.stringify({
contents: [{ parts: [{ text: prompt }] }]
}),
})
.then(res => res.json())
.then(data => {
const text = data?.candidates?.[0]?.content?.parts?.[0]?.text || "error";
const cleaned = text.toLowerCase().includes("spam") ? "spam" : "ham";
document.getElementById("status1").innerText = cleaned;
console.log("Gemini response: ", cleaned);
computeAccuracy(cleaned, "accuracy1");
});
}
// function to analyse the message using Groq Call, passing promt as varible
function analyseWithGroq(prompt) {
document.getElementById("status2").innerText = "Analyzing...";
console.info("Analysing with Groq started");
fetch(GROQ_URL, {
method: "POST",
headers: {
"Content-Type": "application/json",
"Authorization": "Bearer " + GROQ_KEY
},
body: JSON.stringify({
model: "llama-3.1-8b-instant",
messages: [{ role: "user", content: prompt }]
}),
})
.then(res => res.json())
.then(data => {
const text = data?.choices?.[0]?.message?.content || "error";
const cleaned = text.toLowerCase().includes("spam") ? "spam" : "ham";
document.getElementById("status2").innerText = cleaned;
console.log("Groq response: ", cleaned);
computeAccuracy(cleaned, "accuracy2");
});
}
// For Accuracy & Dataset Comparison
// Function to load CSV dataset
function loadDataset() {
const file = document.getElementById("datasetFile").files[0];
if (!file) return;
const reader = new FileReader();
reader.onload = function(e) {
const text = e.target.result;
DATASET = parseCSV(text);
console.log("Dataset loaded:", DATASET);
showCustomAlert("Dataset loaded successfully!");
};
reader.readAsText(file);
}
// Robust TSV parser
function parseTSV(tsvText) {
const lines = tsvText.trim().split("\n");
const result = [];
for (let i = 1; i < lines.length; i++) {
const [label, message] = lines[i].split("\t");
result.push({
label: label.trim().toLowerCase(),
message: message.trim()
});
}
return result;
}
// Start timer when user types or clicks Analyse (to identify the total time taken to analyse)
function startTimer() {
startTime = Date.now();
}
// Function to get actual label for a given message from dataset
function getActualLabelFromDataset(userMessage) {
const lowerMessage = userMessage.toLowerCase();
const userWords = lowerMessage.split(/\s+/);
const row = DATASET.find(r => {
const datasetWords = r.message.toLowerCase().split(/\s+/);
// Match if at least 50% of user words appear in dataset
const matchCount = userWords.filter(word => datasetWords.includes(word)).length;
return matchCount / userWords.length >= 0.5;
});
return row ? row.label.toLowerCase() : "unknown";// return spam/ham if message is found, else return unknown
}
// Compute accuracy as a percentage of two factors (response and time taken)
function computeAccuracy(prediction, accuracyElementId) {
const userMessage = document.getElementById("promptInput").value.trim();
const actual = getActualLabelFromDataset(userMessage);
const datasetBox = document.getElementById("datasetResultBox");
if (actual === "unknown") {
document.getElementById(accuracyElementId).innerText = "--";
datasetBox.style.display = "none"; // to hide if message not found
showCustomAlert("Message not found in dataset.");
return;
}
datasetBox.style.display = "block"; // to show dataset result
document.getElementById("datasetResult").innerText = actual;
const factors = [];
// Factor 1: Correctness (weight 70%)
const correctnessScore = (prediction.toLowerCase() === actual) ? 100 : 0;
factors.push({ score: correctnessScore, weight: 0.7 });
// Factor 2: Time taken (weight 30%)
let timeScore = 100; // start at 100%
if (startTime) {
const elapsedMilliseconds = Date.now() - startTime;
console.log("Elapsed milliseconds:", elapsedMilliseconds);
// Reduce accuracy by 0.0001% per 1ms
timeScore = Math.max(0, 100 - (elapsedMilliseconds * 0.0001));
}
factors.push({ score: timeScore, weight: 0.3 });
// Weighted average
const finalAccuracy = factors.reduce((sum, f) => sum + f.score * f.weight, 0);
document.getElementById(accuracyElementId).innerText = finalAccuracy.toFixed(2) + "%";
}
// function to show alert messages
function showCustomAlert(message) {
const alertBox = document.getElementById("customAlertBox");
const alertSpan = document.getElementById("custom-alert");
alertSpan.innerText = message;
alertBox.style.display = "block";
// Automatically hide after 10 seconds
setTimeout(() => {
alertBox.style.display = "none";
}, 10000);
}
// Load dataset automatically from internet
function loadDataset() {
showCustomAlert("Loading dataset from internet...");
fetch(DATASET_URL)
.then(res => {
if (!res.ok) throw new Error("Network error");
return res.text();
})
.then(text => {
DATASET = parseTSV(text);
console.log("Dataset loaded:", DATASET);
showCustomAlert("Dataset loaded successfully!");
})
.catch(err => {
console.error(err);
showCustomAlert("Failed to load dataset from internet.");
});
}
// Load dataset automatically on page load
window.onload = function() {
loadDataset();
};