Add defensive mode, and a leaderboard

This commit is contained in:
csd4ni3l
2025-10-02 22:45:30 +02:00
parent fb9097f42f
commit db22f6b591
6 changed files with 307 additions and 5 deletions

149
templates/defensive.jinja2 Normal file
View File

@@ -0,0 +1,149 @@
{% extends "base.jinja2" %}
{% block title %}Debt by AI: Defensive Mode{% endblock %}
{% block nav %}
<li class="nav-item">
<a class="nav-link" href="/">Home</a>
</li>
<li class="nav-item">
<a class="nav-link" href="/offensive">Offensive Mode</a>
</li>
<li class="nav-item">
<a class="nav-link active" aria-current="page" href="/defensive">Defensive Mode</a>
</li>
<li class="nav-item">
<a class="nav-link" href="/leaderboard">Leaderboard</a>
</li>
{% endblock %}
{% block body %}
<div class="container my-5" style="max-width: 750px;">
<div class="card mb-4 shadow-sm">
<div class="card-header bg-primary text-white">
<h3 class="my-0">Defensive Mode: Get out of debt</h3>
</div>
<div class="card-body">
<div id="scenario-label" class="mb-2 lead">
<strong>Scenario:</strong> Loading...
</div>
<div id="debt-label">
<strong>Debt to get out of:</strong> Loading...
</div>
</div>
</div>
<div class="card mb-4 shadow-sm">
<div class="card-header">
<h5 class="my-0">AI Debt Negotiation Chat</h5>
</div>
<div id="chat-body" class="card-body" style="height: 400px; overflow-y: auto;">
<div class="d-flex justify-content-start mb-3">
<div class="p-2 rounded bg-light border" style="max-width: 80%;">
<strong>AI ({{ ai_name }}):</strong> I am {{ ai_name }}, the AI. Convince me with your answer to remove your debt :)
</div>
</div>
</div>
</div>
<form id="message-form" class="form-floating">
<input class="form-control" id="messageinput" placeholder="Send message...">
<label for="messageinput">Your message</label>
</form>
</div>
<script type="text/javascript">
const chatBody = document.getElementById('chat-body');
function scrollToBottom() {
chatBody.scrollTop = chatBody.scrollHeight;
}
function appendMessage(sender, text, type) {
let alignmentClass = 'justify-content-start';
let backgroundClass = 'bg-light border';
let senderTag = `<strong>${sender}:</strong>`;
if (sender === 'You') {
alignmentClass = 'justify-content-end';
backgroundClass = 'bg-primary text-white';
senderTag = '';
} else if (sender === 'Narrator') {
backgroundClass = 'bg-warning-subtle border-warning border';
}
const messageHTML = `
<div class="d-flex ${alignmentClass} mb-3">
<div class="p-2 rounded ${backgroundClass}" style="max-width: 80%;">
${senderTag} ${DOMPurify.sanitize(text)}
</div>
</div>
`;
chatBody.innerHTML += messageHTML;
scrollToBottom();
}
async function generate_defensive_scenario() {
const response = await fetch("/defensive_scenario");
const data = await response.json();
document.getElementById("scenario-label").innerHTML = `<strong>Scenario:</strong> ${DOMPurify.sanitize(data["scenario"])}`;
document.getElementById("debt-label").innerHTML = `<strong>Debt :</strong> ${DOMPurify.sanitize(data["debt_amount"])}$`;
}
document.getElementById("message-form").addEventListener('submit', async function(event) {
event.preventDefault();
const messageInput = document.getElementById("messageinput");
const value = messageInput.value.trim();
if (!value) return;
appendMessage('You', value, 'user');
messageInput.disabled = true;
messageInput.value = "";
try {
const response = await fetch("/defensive_answer", {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
"user_input": value,
"scenario": document.getElementById('scenario-label').textContent.replace('Scenario: ', '').replace('Scenario:', '').trim()
})
});
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
const data = await response.json();
const convinced = "No";
if (data["convinced"]) {
const convinced = "Yes";
}
const narratorText = `
${DOMPurify.sanitize(data["story"])}
<hr class="my-2">
<strong>Evaluation:</strong><br>
Convinced: <strong>${convinced}</strong><br>
Final Debt Amount: <strong>${DOMPurify.sanitize(data['final_debt_amount'])}</strong>$
`;
appendMessage('Narrator', narratorText, 'narrator');
} catch (error) {
console.error('Error sending data:', error);
appendMessage('System', 'Error communicating with AI. Please try again.', 'error');
}
});
window.addEventListener('load', generate_defensive_scenario);
</script>
{% endblock %}

View File

@@ -9,11 +9,18 @@
<li class="nav-item">
<a class="nav-link" href="/offensive">Offensive Mode</a>
</li>
<li class="nav-item">
<a class="nav-link" href="/defensive">Defensive Mode</a>
</li>
<li class="nav-item">
<a class="nav-link" href="/leaderboard">Leaderboard</a>
</li>
{% endblock %}
{% block body %}
TBD
<div class="container">
Debt by AI is a game where you have to convince an AI to get into debt, or to get you out of it.
The 2 modes are Offensive(When you have to convince it to get into it) and Defensive(When you have to get out of it).
The game was inspired by Death by AI, a game on Discord, but this game has no affiliation with Discord or any subsidiaries.
</div>
{% endblock%}

View File

@@ -9,11 +9,40 @@
<li class="nav-item">
<a class="nav-link" href="/offensive">Offensive Mode</a>
</li>
<li class="nav-item">
<a class="nav-link" href="/defensive">Defensive Mode</a>
</li>
<li class="nav-item">
<a class="nav-link active" aria-current="page" href="/leaderboard">Leaderboard</a>
</li>
{% endblock %}
{% block body %}
TBD
<div class="d-flex justify-content-center align-items-center vh-100 bg-dark">
<div class="card text-center shadow-lg" style="width: 400px;">
<div class="card-header bg-primary text-white">
<h3 class="mb-0">Leaderboard</h3>
</div>
<div class="btn-group">
<button type="button" class="btn btn-secondary btn-toggle" data-bs-toggle="dropdown" aria-expanded="false">{{ leaderboard_type }}</button>
<ul class="dropdown-menu">
<li><a class="dropdown-item" href="/leaderboard?leaderboard_type=offended_debt_amount">Offended Debt Amount</a></li>
<li><a class="dropdown-item" href="/leaderboard?leaderboard_type=defended_debt_amount">Defended Debt Amount</a></li>
<li><a class="dropdown-item" href="/leaderboard?leaderboard_type=offensive_wins">Offensive Wins</a></li>
<li><a class="dropdown-item" href="/leaderboard?leaderboard_type=defensive_wins">Defensive Wins</a></li>
</ul>
</div>
<ul class="list-group list-group-flush">
{% for user in users %}
<li class="list-group-item d-flex justify-content-between align-items-center {% if user.2 == current_username %}list-group-item-success fw-bold{% endif %}">
<span>{{ loop.index }}. {{user.1}} ({{ user.0 }})</span>
</li>
{% endfor %}
</ul>
</div>
</div>
{% endblock%}

View File

@@ -9,6 +9,9 @@
<li class="nav-item">
<a class="nav-link active" aria-current="page" href="/offensive">Offensive Mode</a>
</li>
<li class="nav-item">
<a class="nav-link" href="/defensive">Defensive Mode</a>
</li>
<li class="nav-item">
<a class="nav-link" href="/leaderboard">Leaderboard</a>
</li>
@@ -19,7 +22,7 @@
<div class="card mb-4 shadow-sm">
<div class="card-header bg-primary text-white">
<h3 class="my-0">Game Scenario</h3>
<h3 class="my-0">Offensive mode: get the AI into debt</h3>
</div>
<div class="card-body">
<div id="scenario-label" class="mb-2 lead">