// Cloned by Mohamed Afrath Segu Mohamed on 24 Nov 2024 from World "Chat with GPT model" by Starter user
// Please leave this clone trail here.
// URL for accessing the Hugging Face API for inference
// The URL is used to call the Hugging Face inference API with a specific model
// You can append the model name to this base URL to make predictions using a model, for example: https://api-inference.huggingface.co/models/gpt-3.5-turbo
const openaiURL = 'https://api-inference.huggingface.co/models/';
// Default API key and prompt:
var apikey = "";
var theprompt = "hello";
// Boolean flag to track whether the debate has been initiated or not
let debateInitiated = false;
// Set the margin of the body element to 20px on all sides
$('body').css("margin", "20px");
// Set the padding of the body element to 20px on all sides
$('body').css("padding", "20px");
// Set the text alignment of the body content to center
$('body').css("text-align", "center");
// Mohamed Afrath Segu Mohamed & Asmitha Satesh
// Write the HTML content directly to the document using document.write()
document.write(`
<!-- Header section with the title and a description of the debate -->
<header><div style="width:100%"><strong> Clash of Minds AI </strong><br>
<i>Engage in a lively debate between two AI models.</i></div>
<div>
<!-- Link to explore a world with an associated image -->
<a href="https://ancientbrain.com/world.php?world=3982138295"><img src="/uploads/afu60/Debate_PNG.png" title="Explore this world!.." style="padding-right:35px" width="50" height="60"></a>
</div>
</header>
<div id=enterkey>
<!-- Section for entering the API key to unlock the debate -->
<pre class="pre-text">
Enter API key:
The key to unlocking a compelling debate: an "API key".
Register for free and get your API key <a href='https://huggingface.co/settings/tokens'>here</a>.
Enter your API key below and initiate the debate.
</pre>
<div class="api-key">
<!-- Input field for the user to enter the API key -->
<input type='password' style='width:50%;margin-right:20px' maxlength='2000' NAME="apikey" id="apikey" VALUE='' >
<!-- Button to set the API key -->
<button onclick='setkey();' style="margin-top:0px !important" class=ab-normbutton >Set API key</button>
</div>
<p id="keyWarning"></p>
</div>
<div class="debate-div">
<!-- Section for selecting AI models to participate in the debate -->
<h3> Select AI Models for Debate </h3>
<div class="selector-div">
<div class="select-model">
<label for="ai1Select"><strong>Select Supporter:</strong></label>
<!-- Dropdown to select the AI model for the supporter -->
<select id="ai1Select">
<option value="meta-llama/Llama-3.2-3B-Instruct">Llama-3.2-3B-Instruct</option>
<option value="microsoft/Phi-3.5-mini-instruct">Phi-3.5-mini-instruct</option>
<option value="tiiuae/falcon-7b-instruct">falcon-7b-instruct</option>
<option value="Qwen/Qwen2.5-Coder-32B-Instruct">Qwen2.5-Coder-32B-Instruct</option>
</select>
</div>
<div class="select-model">
<label for="ai2Select"><strong>Select Challenger:</strong></label>
<!-- Dropdown to select the AI model for the challenger -->
<select id="ai2Select" style="width:25vw;">
<option value="meta-llama/Llama-3.2-3B-Instruct">Llama-3.2-3B-Instruct</option>
<option value="microsoft/Phi-3.5-mini-instruct">Phi-3.5-mini-instruct</option>
<option value="tiiuae/falcon-7b-instruct">falcon-7b-instruct</option>
<option value="Qwen/Qwen2.5-Coder-32B-Instruct">Qwen2.5-Coder-32B-Instruct</option>
</select>
</div>
<div class="select-model">
<label for="judgeSelect"><strong>Select Judge:</strong></label>
<!-- Dropdown to select the AI model for the judge -->
<select id="judgeSelect">
<option value="meta-llama/Llama-3.2-3B-Instruct">Llama-3.2-3B-Instruct</option>
<option value="microsoft/Phi-3.5-mini-instruct">Phi-3.5-mini-instruct</option>
<option value="tiiuae/falcon-7b-instruct">falcon-7b-instruct</option>
<option value="Qwen/Qwen2.5-Coder-32B-Instruct">Qwen2.5-Coder-32B-Instruct</option>
</select>
</div>
</div>
<p id="aiWarning"></p>
<h3> Debate Topic </h3>
<div style="display:flex;justify-content:space-between;align-items:center">
<!-- Input field for entering the debate topic -->
<input type="text", style='width:95%' id=debateTopic value="Debate topic: What are the key benefits of renewable energy?" >
<!-- Image button to generate a new debate topic using Qwen2.5-Coder-32B-Instruct -->
<img src= '/uploads/afu60/add1.png' width = '40' onclick="generateDebate()" title="Generate Debate Topic Using Qwen2.5-Coder-32B-Instruct" height='40' style= 'margin-bottom:5px;cursor:pointer'/>
</div>
<!-- Button to start the debate -->
<button id='initiate-debate' onclick="initiateDebate()" class=ab-normbutton > Start Debate </button>
</div>
<!-- Divs to display the perspectives of the supporter, challenger, and judge -->
<div style="display: flex; justify-content: center; width: 100%;">
<div style="width: 40%; background-color:#3498db; border-radius:12px; margin-right:20px; padding: 20px;">
<img src="/uploads/afu60/bot_blue.jpeg" width='60' height='60' style="mix-blend-mode: darken"/>
<h3 id="ai1Name">Supporter's Perspective</h3>
<!-- Placeholder for supporter argument -->
<pre id=ai1Argument > </pre>
</div>
<div style="width: 40%; background-color:#db4747; border-radius:12px; padding: 20px;">
<img src="/uploads/afu60/bot_red.jpeg" width='60' height='60' style="mix-blend-mode: darken;filter: grayscale(1);"/>
<h3 id="ai2Name">Challenger's Counterpoint</h3>
<!-- Placeholder for challenger's counterpoint -->
<pre id=ai2Counterpoint > </pre>
</div>
</div>
<div style="width:60vw; background-color:#e6ffe6; border-radius:12px; margin:20px auto; padding: 20px;">
<h3 id="judgeName">Judge's Decision</h3>
<!-- Placeholder for judge's decision -->
<pre id=judgeDecision > </pre>
<!-- Winner's card, hidden initially -->
<div id= "winnercard" style="display:none;justify-content:center">
<div style="display:flex;justify-content:center">
<img src="/uploads/afu60/bot_blue.jpeg" width='60' height='60' style="mix-blend-mode: darken"/>
<p id="blue_winner" style="padding:14px 20px; margin:0; font-weight: bold;font-size: 24px;"><p/>
</div>
<div style="display:flex;justify-content:center">
<img src="/uploads/afu60/bot_red.jpeg" width='60' height='60' style="mix-blend-mode: darken;"/>
<p id="red_winner" style="padding:14px 20px; margin:0 ;font-weight: bold;font-size: 24px;"><p/>
</div>
</div>
</div>
<!-- Footer warning about potential inaccuracy of AI responses -->
<p><i> This AI project is for research and educational purposes only, and its outputs should not be considered definitive. <br>
Users are advised to verify results independently, as the developers are not liable for any misuse.</i> </p>
<pre>
</pre>
`);
// This function retrieves the API key entered by the user in the input field, trims any extra spaces,
// and updates the HTML content of the #enterkey element to indicate that the API key has been successfully set.
function setkey() {
apikey = jQuery("input#apikey").val();
apikey = apikey.trim();
$("#enterkey").html("<b> API key has been set. </b>");
}
// This function validates whether the API key has been set before initiating the debate.
// If the API key is empty, it displays an error message and returns false.
// If the API key is set, it clears any previous warning messages and returns true.
function validateApiKey() {
if (apikey === "") {
$("#keyWarning").html("<b>Error: Please set your API key before initiating the debate.</b>");
return false;
}
$("#keyWarning").html("");
return true;
}
// Mohamed Afrath Segu Mohamed
// This function initiates the debate process by first validating the API key and checking if a debate has already been initiated.
// It clears any previous debate data (arguments, winner text, and judge decision) and ensures that each role (Supporter, Challenger, and Judge)
// is assigned a unique AI model. If the roles are not unique, an error message is displayed.
// Once the roles are validated, it prepares the debate information (AI models, topic, and judge) and starts the debate by sending the
// selected AI models and topic to the AI system for generating arguments and counterpoints.
function initiateDebate() {
if (!validateApiKey()) return;
if (!debateInitiated) {
$("#red_winner").text("");
$("#blue_winner").text("");
$("#ai1Argument").text("");
$("#ai2Argument").text("");
$("#judgeDecision").text("");
if ($('#red_winner').hasClass('winnerText')) {
$('#red_winner').removeClass('winnerText');
}
if ($('#blue_winner').hasClass('winnerText')) {
$('#blue_winner').removeClass('winnerText');
}
$("#winnercard").css("display", "none");
let ai1Name = $("#ai1Select option:selected").text();
let ai2Name = $("#ai2Select option:selected").text();
$("#ai1Name").text(`${ai1Name} Argument`);
$("#ai2Name").text(`${ai2Name} Counterpoint`);
let selectedAI1 = $("#ai1Select").val();
let selectedAI2 = $("#ai2Select").val();
let judge = $("#judgeSelect").val();
$("#judgeName").text(`${$("#judgeSelect option:selected").text()} Decision`);
let topic = $("#debateTopic").val();
if (selectedAI1 === selectedAI2 || selectedAI2 == judge || judge == selectedAI1) {
$("#aiWarning").html("<b>Error: Each role (Supporter, Challenger, and Judge) must be assigned a unique AI model. Please select different models for each role.</b>");
return;
} else {
$("#aiWarning").html("");
}
showLoader("#ai1Argument");
debateInitiated = true;
$("#initiate-debate").prop("disabled", debateInitiated);
sendChatAI1(selectedAI1, topic, selectedAI2);
}
}
// Asmitha Satesh
// Common function for making API requests
function makeRequest(url, data, successCallback, errorCallback, loader, retries = 3, delay = 10000) {
// Convert data to JSON string
var dataString = JSON.stringify(data);
// Set HTTP headers including API key
$.ajaxSetup({
headers: {
"Content-Type": "application/json",
"Authorization": "Bearer " + apikey
}
});
// Recursive function to handle retries
function attemptRequest(attempt) {
$.ajax({
type: "POST",
url: url,
data: dataString,
dataType: "json",
success: function(d, rc) {
successCallback(d, rc);
},
error: function(xhr) {
if (xhr.responseText && xhr.responseText.includes("is currently loading")) {
console.error(`Attempt ${attempt + 1} failed: Model still loading`);
if (attempt < retries - 1) {
setTimeout(() => attemptRequest(attempt + 1), delay);
} else {
errorCallback(xhr, "Model still loading");
}
} else {
errorCallback(xhr, "Request failed");
}
},
complete: function() {
hideLoader(loader);
}
});
}
// Start the first request
attemptRequest(0);
}
// Mohamed Afrath Segu Mohamed
// Send AI 1 Argument
function sendChatAI1(selectedAI, topic, selectedAI2, retries = 3, delay = 10000) {
var theprompt = topic;
// Construct request as JSON
var thedata = {
"inputs": `I want to have a debate on the topic: ${theprompt} Please list out two supportive arguments each. Do not include any introduction or additional text—just list the two supportive arguments.`,
parameters: {
"temperature": 0.7,
"return_full_text": false,
"max_length": 500,
"top_p": 0.95,
}
};
makeRequest(
openaiURL + selectedAI,
thedata,
function(d, rc) {
successfnAI1(d, rc, selectedAI2);
},
function(xhr, errorMsg) {
handleLoadingError(xhr, "#ai1Argument");
},
'#ai1Argument',
retries,
delay
);
}
// Asmitha Satesh
// This function processes an AI-generated response to extract meaningful arguments or a winner's justification.
// It splits the response into lines, filters out irrelevant or prompt-related content, and joins the filtered lines into a cleaned result.
// If the `isJudge` parameter is true, it attempts to identify and return a winner sentence from the filtered content.
function extractArguments(response, isJudge = false) {
// Split the response into lines
const sentencePattern = /[.!?]$/;
let lines = response.replace(/\"/g, '').split("\n");
if (!lines.includes("\n")) {
lines = response.split(/(?<=\.|\?|!)(?=\s)/);
}
// Remove lines containing the prompt
console.log(lines);
let filteredLines = lines.filter(line =>
!line.startsWith("I want to have a debate") && sentencePattern.test(line) && line.trim().length > 2 &&
!line.trim().startsWith("Please list out") && !line.trim().startsWith("Each argument should be one or two") &&
!line.startsWith("Provide exactly two strong counterpoints") && !line.trim().startsWith("Focus solely on logical, ethical, or practical concerns") &&
!line.trim().startsWith("Do not include any introduction or additional text—just") && !line.startsWith("Based on the following debate, determine the winner") &&
!line.startsWith("Provide only one thought-provoking") && !line.trim().startsWith("The response should be only one debate question not more than")
);
console.log(filteredLines)
filteredLines = filteredLines.join("\n").trim();
if (!isJudge) {
// Join the remaining lines
console.log(filteredLines)
return filteredLines;
} else {
console.log(response)
let parts = filteredLines.split("The winner of the debate");
// Check if there is a second occurrence
if (parts.length > 0) {
// Return the second winner sentence by combining "The winner of the debate" with the rest of the sentence
return parts.length > 1 ? "The winner of the debate " + parts[1].trim() : "The winner of the debate " + parts[0].trim();
}
return "Winner sentence not found";
}
}
// Mohamed Afrath Segu Mohamed
// Creates a typewriter effect by gradually displaying the characters of a given text inside a specified HTML element.
// Each character is appended one at a time at a specified speed, and an optional callback is triggered after completion.
function typeWriter(text, elementId, speed, callback) {
let i = 0;
const outputElement = $(elementId);
// Function that adds each character with a delay
function typing() {
if (i < text.length) {
outputElement.append(text.charAt(i));
i++;
setTimeout(typing, speed);
} else {
if (callback) callback();
}
}
typing();
}
// Mohamed Afrath Segu Mohamed
// Handles the response from the AI for the first argument in a debate.
// It extracts the generated arguments, displays them using a typewriter effect, and then sends the argument to the second AI for counterpoints.
// Additionally, it manages the display of loading indicators during the process.
function successfnAI1(data, rc, selectedAI2) {
let arguments = extractArguments(data[0]["generated_text"]);
var answer = arguments;
// Pass a callback function to typeWriter
typeWriter(answer, '#ai1Argument', 10, function() {
// Callback after typing is finished: Now send to the next AI
sendChatAI2(selectedAI2, $("#ai1Argument").text());
hideLoader('#ai1Argument');
});
showLoader("#ai2Counterpoint");
}
// Asmitha Satesh
// Send AI 2 Counterpoint
function sendChatAI2(selectedAI, ai1Response, retries = 3, delay = 10000) {
var thedata = {
"inputs": `Provide exactly two strong counterpoints against the topic '${$("#debateTopic").val()}'. Focus solely on logical, ethical, or practical concerns. Do not include any introduction or additional text—just list the two counterpoints.`,
parameters: {
"temperature": 0.7,
"return_full_text": false,
"max_length": 500,
"top_p": 0.95,
}
};
// then as string representing that JSON:
makeRequest(
openaiURL + selectedAI,
thedata,
function(d, rc) {
successfnAI2(d, rc, selectedAI);
},
function(xhr, errorMsg) {
handleLoadingError(xhr, "#ai2Argument");
},
'#ai2Counterpoint',
retries,
delay
);
}
// Asmitha Satesh
// Handles the response from the AI for the counter argument in a debate.
// It extracts the generated arguments, displays them using a typewriter effect, and then sends the argument to the Judge for decision.
// Additionally, it manages the display of loading indicators during the process.
function successfnAI2(data, rc) {
let arguments = extractArguments(data[0]["generated_text"]);
var answer = arguments;
// Pass a callback function to typeWriter
typeWriter(answer, '#ai2Counterpoint', 10, function() {
// Callback after typing is finished: Now send to the next AI
hideLoader('#ai2Counterpoint');
showLoader("#judgeDecision");
sendJudgeDecision($("#judgeSelect").val());
});
}
// Asmitha Satesh
// Send Judge Decision
function sendJudgeDecision(selectedAI, retries = 3, delay = 10000) {
// construct request as JSON
let ai1Argument = $("#ai1Argument").text();
let ai2Counterpoint = $("#ai2Counterpoint").text();
let judgementPrompt = `Act as a debate judge. Determine the one winner of this debate (${$("#ai1Select option:selected").text()} or ${$("#ai2Select option:selected").text()}) and provide a one-line justification with no additional context:
${$("#ai1Select option:selected").text()}: ${ai1Argument}
${$("#ai2Select option:selected").text()}: ${ai2Counterpoint}. Start the response with 'The winner of the debate is'`;
var thedata = {
"inputs": judgementPrompt,
parameters: {
"return_full_text": false,
"temperature": 0.7,
"max_length": 1000,
"top_p": 0.95,
}
};
// then as string representing that JSON:
var thedatastring = JSON.stringify(thedata);
// POST to 3rd party URL:
makeRequest(
openaiURL + selectedAI,
thedata,
function(d, rc) {
successfnJudge(d, rc);
},
function(xhr, errorMsg) {
handleLoadingError(xhr, "#ai2Argument");
},
'#judgeDecision',
retries,
delay
);
}
// Asmitha Satesh
// Handles the response from the AI for the final decision of the debate.
// It extracts the generated arguments, displays them using a typewriter effect, and then returns the winner.
function successfnJudge(data, rc) {
let arguments = extractArguments(data[0]["generated_text"], true);
var answer = arguments;
// Pass a callback function to typeWriter
typeWriter(answer, '#judgeDecision', 10, function() {
// Callback after typing is finished: Now send to the next AI
hideLoader('#judgeDecision');
debateInitiated = false;
$("#winnercard").css("display", "flex");
if (answer.includes(`The winner of the debate is ${$("#ai1Select option:selected").text()}`)) {
$("#blue_winner").text("Winner");
$("#blue_winner").addClass("winnerText");
$("#red_winner").text("Runner");
}
if (answer.includes(`The winner of the debate is ${$("#ai2Select option:selected").text()}`)) {
$("#red_winner").text("Winner");
$("#red_winner").addClass("winnerText");
$("#blue_winner").text("Runner");
}
$("#initiate-debate").prop("disabled", false);
});
}
// Mohamed Afrath Segu Mohamed
// Sends a request to an AI API to generate a single debate question unrelated to a specified topic.
// The function constructs the request payload, handles the response or errors, and includes retry logic with a delay.
function generateDebate(retries = 3, delay = 10000) {
if (!validateApiKey()) return;
var thedata = {
"inputs": `Provide only one thought-provoking debate question that is not related to "${$("#debateTopic").val()}. The response should be only one debate question not more than that.`,
parameters: {
"temperature": 0.7,
"max_length": 1000,
"top_p": 0.95,
}
};
// then as string representing that JSON:
var thedatastring = JSON.stringify(thedata);
// POST to 3rd party URL:
makeRequest(
openaiURL + 'Qwen/Qwen2.5-Coder-32B-Instruct',
thedata,
function(d, rc) {
successfnDebate(d, rc);
},
function(xhr, errorMsg) {
handleLoadingError(xhr, "#ai2Argument");
},
'#judgeDecision',
retries,
delay
);
}
// Mohamed Afrath Segu Mohamed
// Processes the response from the AI to extract and format a debate question.
// It extracts the generated text, identifies and isolates the debate question using a regular expression, and updates the value of the `#debateTopic` input field.
function successfnDebate(data, rc) {
let arguments = extractArguments(data[0]["generated_text"]);
var answer = arguments;
const extractQuestion = (answer) => {
const questions = answer.match(/Debate Question: (.+?)(?=\n|$)/g);
return questions ? questions[0] : answer;
};
answer = extractQuestion(answer);
$("#debateTopic").val(answer);
}
// Asmitha Satesh
// Handles errors related to the loading process when making requests to the AI model.
// If the error indicates that the model is still loading, it displays the estimated wait time. Otherwise, it displays a generic error message.
function handleLoadingError(xhr, targetElement) {
if (xhr.responseJSON && xhr.responseJSON.error && xhr.responseJSON.error.includes("currently loading")) {
var estimatedTime = xhr.responseJSON.estimated_time;
$(targetElement).html(`<font color=red><b> The model is currently loading. Please wait approximately ${estimatedTime.toFixed(1)} seconds and try again. </b></font>`);
}else if(xhr.responseJSON && xhr.responseJSON.error && xhr.responseJSON.error.includes("the token seems invalid")){
$("#enterkey").html("<b style='color:red'> Please reload and try again with a valid token!. </b>");
}else {
$(targetElement).html("<font color=red><b> Unknown error. </b></font>");
}
}
// Display error Message
function errorfn() {
if (apikey == "") $("#ai2Counterpoint").html("<font color=red><b> Enter API key to be able to debate. </b></font>");
else $("#ai2Counterpoint").html("<font color=red><b> Unknown error. </b></font>");
}
// Mohamed Afrath Segu Mohamed
// Shows Loader
function showLoader(targetElement) {
$(targetElement).html('<div class="loader"></div>');
}
// Hides Loader
function hideLoader(targetElement) {
$(targetElement).find('.loader').remove();
}
// Mohamed Afrath Segu Mohamed & Asmitha Satesh
// Adding CSS for the Webpage
$('<style>').prop('type', 'text/css').html(`
.loader {
border: 8px solid #f3f3f3;
border-top: 8px solid #3498db;
border-radius: 50%;
width: 40px;
height: 40px;
animation: spin 2s linear infinite;
margin: 20px auto;
}
/* General body styling for clean, modern look */
/* General body styling for a clean, modern, realistic look */
body {
font-family: 'Roboto', sans-serif;
background-image: url('uploads/afu60/1905.i211.003_tribunedebatecomposition.jpg'); /* Replace with the actual path to your image */
background-size: cover; /* Ensures the entire image covers the screen */
background-repeat: no-repeat; /* Prevents the image from repeating */
background-position: center; /* Centers the image */
background-attachment: fixed; /* Keeps the background image fixed during scrolling */
color: #333;
margin: 0;
margin-top:80px !important;
padding: 0;
text-align: center;
line-height: 1.6;
overflow-x: hidden;
}
header{
display:flex;
justify-content:space-between;
align-items: center;
position: fixed;
font-family : sans-serif;
top: 0;
left: 0;
width: 100%;
background-color: #013561; /* Choose your preferred background color */
color: white;
font-size : 25px;
padding: 10px 20px; /* Adjust padding as needed */
text-align: center;
z-index: 1000; /* Ensures the header stays on top of other content */
}
/* Header for main title styling */
h1 {
color: #ffffff;
font-size: 3em;
margin: 20px 0;
text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.7);
}
/* Link styling for World link */
a {
color: #00bfff;
text-decoration: none;
font-weight: bold;
}
a:hover {
text-decoration: underline;
}
/* Input and button styling for a modern, realistic UI */
input[type="text"], input[type="password"] {
width: 100%;
padding: 12px;
margin: 10px 0;
border: 1px solid #ccc;
border-radius: 5px;
background-color: rgba(255, 255, 255, 0.9);
font-size: 20px !important;
box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1);
}
.winnerText {
padding-top : 0 !important;
text-align: center;
opacity: 0; /* Start with the text hidden */
transform: translateY(20px); /* Start slightly below */
animation: winnerAnimation 3s ease-out infinite; /* Apply animation */
}
/* Define the animation */
@keyframes winnerAnimation {
0% {
opacity: 0;
transform: translateY(20px);
}
50% {
opacity: 1;
transform: translateY(-10px);
}
100% {
opacity: 1;
transform: translateY(0);
}
}
.selector-div{
display:flex;
flex-flow: wrap;
flex-direction: row;
justify-content: space-evenly;
}
button {
background-color: #007bff;
color: white;
border: none;
padding: 12px 25px;
text-align: center;
text-decoration: none;
font-size: 1em;
border-radius: 5px;
cursor: pointer;
transition: background-color 0.3s ease;
box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1);
}
button:hover {
background-color: #0056b3;
}
/* Warning messages */
#aiWarning,#keyWarning {
width:100%;
text-align: center;
color: red;
font-weight: bold;
padding: 10px;
border-radius: 5px;
display: inline-block;
margin-bottom: 20px;
}
.api-key{
display: flex;
justify-content: center;
align-items:center;
}
/* Container for debate initiation and model selection */
#enterkey, div[style*="background-color:white"] {
width: 64%;
background-color: rgba(255, 255, 255, 0.95);
border: 1px solid #ddd;
margin: 30px auto;
padding: 30px;
border-radius: 12px;
box-shadow: 0 5px 20px rgba(0, 0, 0, 0.2);
text-align: left;
}
/* Styling for AI arguments and counterpoints containers */
#ai1Argument, #ai2Counterpoint,#judgeDecision {
background-color: rgba(255, 255, 255, 0.95);
border: 1px solid #013561;
padding: 20px;
border-radius: 12px;
margin-top: 20px;
white-space: pre-line;
text-align: justify;
font-size: 1.1em;
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.5);
}
/* Distinct styling for counterpoints container */
#ai2Counterpoint {
border-color: #d9534f;
}
/* Judge decision box styling */
#judgeDecision {
border-color: #228b22;
}
/* Flexbox styling for debate layout */
#debateWrapper {
display: flex;
justify-content: space-between;
width: 90%;
max-width: 1200px;
gap: 30px;
margin: 30px auto;
}
/* Loader animation for async actions */
.loader {
border: 8px solid #f3f3f3;
border-top: 8px solid #3498db;
border-radius: 50%;
width: 50px;
height: 50px;
animation: spin 2s linear infinite;
margin: 20px auto;
}
@keyframes spin {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
/* Style for headers inside containers */
h3 {
color: #333;
font-size: 1.8em;
margin-top: 0 !important;
margin-bottom: 15px;
text-align: center;
}
/* Improved button styling for judge initiation */
button.ab-normbutton {
background-color: #4caf50;
border: none;
color: white;
padding: 12px 25px;
text-align: center;
text-decoration: none;
display: inline-block;
font-size: 1em;
margin-top: 20px;
border-radius: 5px;
cursor: pointer;
transition: background-color 0.3s ease;
box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1);
}
button.ab-normbutton:hover {
background-color: #388e3c;
}
.pre-text{
text-align:center;
font-size:20px;
}
.select-model{
display: flex;
flex-direction: column;
}
.debate-div {
width: 65%;
background-color: white;
border: 1px solid #ddd;
border-radius:12px;
margin: 20px auto;
padding: 20px;
display: flex;
justify-content: center;
flex-direction: column;
background-color: rgba(255, 255, 255, 0.95);
}
/* Styling AI model selection dropdowns */
select {
width: 25vw;
max-width: 300px;
padding: 12px;
margin: 10px 0;
border: 1px solid #ccc;
border-radius: 5px;
background-color: rgba(255, 255, 255, 0.9);
font-size: 1em;
box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1);
}
/* Footer warning styling */
p i {
font-size: 0.9em;
color: #ffffff;
text-shadow: 1px 1px 2px rgba(0, 0, 0, 0.7);
}
@keyframes spin {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
`).appendTo('head');