testjs / index.html
zshashz's picture
aaa
f75003b
raw
history blame
11.3 kB
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Shy Guy Simulator - AI Edition</title>
<style>
body {
font-family: Arial, sans-serif;
max-width: 800px;
margin: 20px auto;
padding: 20px;
background-color: #1a1a1a;
color: #fff;
}
#game-container {
background-color: #2a2a2a;
padding: 20px;
border-radius: 8px;
box-shadow: 0 0 10px rgba(0, 0, 0, 0.5);
}
.chat-container {
height: 400px;
overflow-y: auto;
margin: 20px 0;
padding: 10px;
background-color: #333;
border-radius: 4px;
}
.message {
margin: 10px 0;
padding: 10px;
border-radius: 4px;
word-wrap: break-word;
}
.wingman {
background-color: #2c5282;
margin-right: 20%;
}
.shyguy {
background-color: #4a5568;
margin-left: 20%;
}
.error {
background-color: #c53030;
text-align: center;
}
#input-container {
display: flex;
gap: 10px;
margin-top: 20px;
}
#user-input {
flex-grow: 1;
padding: 10px;
border: none;
border-radius: 4px;
background-color: #4a4a4a;
color: white;
}
button {
padding: 10px 20px;
background-color: #4299e1;
color: white;
border: none;
border-radius: 4px;
cursor: pointer;
}
button:hover {
background-color: #3182ce;
}
#stats {
margin-top: 20px;
padding: 10px;
background-color: #333;
border-radius: 4px;
display: flex;
justify-content: space-between;
}
.typing {
font-style: italic;
color: #718096;
}
#api-key-container {
margin-bottom: 20px;
}
</style>
</head>
<body>
<div id="game-container">
<h1>Shy Guy Simulator - AI Edition</h1>
<div id="api-key-container">
<input type="password" id="api-key" placeholder="Enter your Mistral API key" style="width: 100%; padding: 10px; margin-bottom: 10px;">
<button onclick="initializeGame()" id="start-button">Start Game</button>
</div>
<div id="game-content" style="display: none;">
<div id="stats">
<span>Confidence: <span id="confidence">0</span>%</span>
<span>Anxiety: <span id="anxiety">100</span>%</span>
<span>Time: <span id="time">8:00 PM</span></span>
</div>
<div class="chat-container" id="chat-container"></div>
<div id="input-container">
<input type="text" id="user-input" placeholder="Type your encouragement as wingman...">
<button onclick="handleUserInput()">Send</button>
</div>
</div>
</div>
<script>
let game;
class ShyGuySimulator {
constructor(apiKey) {
this.apiKey = apiKey;
this.state = {
confidence: 0,
anxiety: 100,
time: new Date(2024, 0, 1, 20, 0),
location: 'entrance',
hasSpokenToGirl: false,
isProcessing: false
};
this.context = [
{
role: 'system',
content: `You are roleplaying as a shy and anxious guy at a homecoming party.
You're standing near the entrance, and the girl you like is across the room.
Your responses should reflect your social anxiety and reluctance to approach her.
Keep responses concise (max 2-3 sentences) and natural.
Express hesitation, worry, and self-doubt while reacting to the wingman's encouragement.`
}
];
this.initialize();
}
initialize() {
this.addMessage("Hey! I'll be your wingman tonight. I see that girl you like over there - let's help you talk to her!", 'wingman');
this.addMessage("I... I don't know about this. Maybe I should just go home...", 'shyguy');
this.updateStats();
}
async handleInput(userInput) {
if (this.state.isProcessing) return;
this.state.isProcessing = true;
try {
if (!userInput.trim()) throw new Error("Please enter some text");
this.addMessage(userInput, 'wingman');
this.addLoadingMessage();
const currentState = `Current confidence: ${this.state.confidence}%, anxiety: ${this.state.anxiety}%, location: ${this.state.location}`;
this.context.push({
role: 'user',
content: `${userInput}\n\n${currentState}`
});
const response = await this.callMistralAPI();
this.removeLoadingMessage();
this.addMessage(response, 'shyguy');
this.updateGameState(response);
this.context.push({
role: 'assistant',
content: response
});
if (this.context.length > 10) {
this.context = [
this.context[0],
...this.context.slice(-4)
];
}
} catch (error) {
this.removeLoadingMessage();
this.addMessage(`Error: ${error.message}`, 'error');
console.error('Error:', error);
} finally {
this.state.isProcessing = false;
}
}
async callMistralAPI() {
try {
const response = await fetch('https://api.mistral.ai/v1/chat/completions', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${this.apiKey}`
},
body: JSON.stringify({
model: 'mistral-large-latest',
messages: this.context,
max_tokens: 150,
temperature: 0.7
})
});
if (!response.ok) {
const error = await response.json();
throw new Error(error.error?.message || 'API request failed');
}
const data = await response.json();
return data.choices[0].message.content;
} catch (error) {
if (error.message.includes('API key')) {
throw new Error('Invalid API key. Please check your API key and try again.');
}
throw new Error('Failed to get response from AI. Please try again.');
}
}
updateGameState(response) {
const lowerResponse = response.toLowerCase();
// Update confidence
if (lowerResponse.includes('okay') || lowerResponse.includes('maybe') || lowerResponse.includes('right')) {
this.state.confidence = Math.min(100, this.state.confidence + 10);
this.state.anxiety = Math.max(0, this.state.anxiety - 5);
} else if (lowerResponse.includes('no') || lowerResponse.includes('can\'t') || lowerResponse.includes('scared')) {
this.state.confidence = Math.max(0, this.state.confidence - 5);
this.state.anxiety = Math.min(100, this.state.anxiety + 10);
}
// Advance time
this.state.time = new Date(this.state.time.getTime() + 5 * 60000);
this.updateStats();
}
updateStats() {
document.getElementById('confidence').textContent = this.state.confidence;
document.getElementById('anxiety').textContent = this.state.anxiety;
document.getElementById('time').textContent =
this.state.time.toLocaleTimeString('en-US', { hour: 'numeric', minute: '2-digit' });
}
addMessage(text, type) {
const chat = document.getElementById('chat-container');
const messageDiv = document.createElement('div');
messageDiv.className = `message ${type}`;
messageDiv.textContent = text;
chat.appendChild(messageDiv);
chat.scrollTop = chat.scrollHeight;
}
addLoadingMessage() {
const chat = document.getElementById('chat-container');
const loadingDiv = document.createElement('div');
loadingDiv.className = 'message shyguy typing';
loadingDiv.id = 'loading-message';
loadingDiv.textContent = 'Thinking...';
chat.appendChild(loadingDiv);
chat.scrollTop = chat.scrollHeight;
}
removeLoadingMessage() {
const loadingMessage = document.getElementById('loading-message');
if (loadingMessage) {
loadingMessage.remove();
}
}
}
function initializeGame() {
const apiKey = document.getElementById('api-key').value.trim();
if (!apiKey) {
alert('Please enter your Mistral API key');
return;
}
document.getElementById('api-key-container').style.display = 'none';
document.getElementById('game-content').style.display = 'block';
game = new ShyGuySimulator(apiKey);
}
async function handleUserInput() {
if (!game) return;
const input = document.getElementById('user-input');
const text = input.value.trim();
if (text) {
await game.handleInput(text);
input.value = '';
}
}
document.getElementById('user-input')?.addEventListener('keypress', function(e) {
if (e.key === 'Enter') {
handleUserInput();
}
});
</script>
</body>
</html>