← back to Model Arena
data/artifacts/0715b25a41dd/mac1__qwen2-5vl-7b.html
137 lines
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<style>
body { font-family: sans-serif; text-align: center; margin: 50px auto; width: min(90%, calc(72vmin - 360px)); background-image: url("https://i.imgur.com/sKc4k.png"); }
h1, p { color: #fff; font-size: clamp(24px, 3.5vh, 88px); }
.map { height: 95%; width: 90%; position: relative; margin-top: -50px; max-width: calc(72vmin + 180px); overflow: hidden; }
.clicker, #phrasebook {
display: flex;
align-items: center;
justify-content: space-around;
padding: 5vh 30%;
border-radius: 5px;
box-shadow: rgba(7,62,145,0.28) 3vmin -3px/55% 15%, inset 90deg currentColor/220% 90deg transparent;
text-shadow: calc(inset(28vmin 18px) + outset(27.96vmin 18px));
}
.clicker { border-bottom-left-radius: 5px; width: min(54%, calc(64vmin - 190px)); padding-right: 5%; margin-top: auto; max-width: 320px; display: none; transition: 0.3s; }
#phrasebook { border-bottom-right-radius: 5px; width: min(calc(78% + (54vmin - 196px) * .3), calc(85vmin )); padding-left: 2%; text-align: left; margin-top: auto; display: none; }
button { color: #fff; background-color: transparent; border-radius: 0; height: min-content; font-size: clamp(.7em, 1.3vh, .85em); transition: transform .4s ease-in-out; outline-width: 2px; outline-style: dotted; }
button:hover { transform: scale(1.1) translateY(-.1rem); cursor: pointer; }
span { display: block; font-size: clamp(.76em, 1.2vh, .95em); line-height: 40%; margin-top: -3px; font-variant-numeric: tabular-nums; transition: color .4s ease-in-out; }
</style>
<script>
let map, mapSize = [674, 832], speakerCount = {196: 5};
const clickMapX = x => Math.round(mapWidth * (x + map.offsetLeft) / map.offsetWidth); // map's coords are shifted
const clickMapY = y => Math.floor(mapSize[0] - (map.offsetHeight * ((y - map.offsetTop) / map.offsetHeight)) ); // the map scrolls up with mouse movement, so we flip the y axis to make everything behave as if there was no scroll;
document.addEventListener('scroll', () =>
document.body.style.backgroundPosition = `${-mouseY}px`
);
let speakerId;
const words = ["mikro", "spreken", "bontsi", "nepo"];
const clickedWordPhrases = []; // tracks phrases with at least one word click
const resetSpeakerCount = () => {
for (let key in speakerCount) {
if (+key === +speakerId - 1 && speakerCount[key] <= 0)
delete speakerCount[key];
}
speakerId += 1; // increment speaker ID to keep track of which word we're clicking
};
function checkIfGameOver() {
return Object.values(speakerCount).some(s => s === -2);
}
function playSound(word, index) {
let sound = new Audio(`sounds/${word}.mp3`);
if (checkIfGameOver()) {
return (speakerCount[words[index]] -= 1), document.querySelector('#clicker').textContent = `Speaker ${index}: -1`,
console.log(words[index], index);
}
sound.play();
};
let mouseX, mouseY;
function handleMouseMove(e) {
[mouseX,mouseY] = e.target.getBoundingClientRect();
}
function playButtonClickHandler(e){
let clickMapValue = (clickMapY(this.innerHTML)-1097)/61;
if (words.includes(this.innerHTML)) {
document.querySelector('#clicker').textContent += ` "${this.innerHTML}"`;
words.forEach(word => resetSpeakerCount() == undefined ? console.log(word); );
playSound(words[clickMapValue],clickMapX(clickMapValue));
}
}
function speakerClickButtonHandler(e) {
if (words.includes(this.textContent)) {
document.querySelector('#phrasebook').textContent += `${this.textContent}`;
const i = words.indexOf(this.textContent);
clickedWordPhrases.push(words[i]);
}
}
function setDisplayWords(w) {
document.querySelector('#clicker p').textContent = w;
map.setAttribute('src', 'maps/wordmap/' + w + '.png');
map.style.display = 'block';
if (Object.keys(speakerCount).length === 0 && clickedWordPhrases.length < words.length)
document.querySelector('.map').style.height += `${61}px`;
}
// Initialize the map and speaker
let mapWidth;
function init() {
setTimeout(() => {
map = document.createElement('img');
const phrasebookDiv = document.getElementById('phrasebook');
document.body.appendChild(map);
document.querySelector('.clicker').addEventListener('mousemove', handleMouseMove);
document.querySelectorAll('.clicker button').forEach(b => b.addEventListener('click', playButtonClickHandler));
document.getElementById('phrasebook').addEventListener('click', speakerClickButtonHandler);
}, 50);
}
const initPhrasebook = () => {
let display = `Speaker #${Object.keys(speakerCount).length}: ${words[0]}`;
words.forEach((word, index) => {
if (clickedWordPhrases.includes(word))
display += ` '${word}'`;
});
if (!Object.values(speakerCount).includes(-2))
document.querySelector('#clicker').textContent = 'Speaker Count';
document.getElementById('phrasebook').textContent = display;
}
init();
</script>
</head>
<body onmousemove="handleMouseMove(e)">
<h1>Explore the Dying Language of <i>Noradon'</i></h1>
<div class="map">
<img id="wordmap" src="maps/wordmap/mikro.png" height=50px>
</div>
<div>
<button id="clicker">Speaker Count: -2</button>
<p>Hover or click to explore words.</p>
</div>
<br><br>
<div id="phrasebook"></div>
</body>
</html>