FIXED CLUES! all that needs to be done is manually adding circle buttons and hiding/showing feature through API.. maybe fixing QR scanner

This commit is contained in:
bobbert committed 2025-03-17 10:42:33 +00:00
1 parent 2236dceac9
commit 726121e105
18 files changed
+1504 -1192

No files matched your search

+128 -53
View File
@@ -124,47 +124,39 @@ export async function populateMap(svgElement) {
console.log(`Found ${allCircles.length} circles in SVG`);
if (allCircles.length === 0) {
console.error("No circles found in SVG. Creating fallback circles.");
// Create some fallback circles at predefined positions
const defs = document.createElementNS(
"http://www.w3.org/2000/svg",
"defs"
console.error(
"No circles found in SVG. Attempting to load from original map."
);
const positions = [
{ x: 100, y: 100 },
{ x: 200, y: 150 },
{ x: 300, y: 200 },
{ x: 400, y: 300 },
{ x: 500, y: 400 },
{ x: 600, y: 500 },
];
positions.forEach((pos, i) => {
const circle = document.createElementNS(
"http://www.w3.org/2000/svg",
"circle"
);
circle.setAttribute("cx", pos.x.toString());
circle.setAttribute("cy", pos.y.toString());
circle.setAttribute("r", "5");
circle.setAttribute("fill", "transparent");
defs.appendChild(circle);
});
// If no circles in current SVG, try to fetch circles from the original map SVG
try {
const mapResponse = await fetch("/images/map.svg");
if (!mapResponse.ok) {
throw new Error("Failed to load original map SVG");
}
// Add the defs to the SVG
svgElement.appendChild(defs);
const mapText = await mapResponse.text();
const parser = new DOMParser();
const mapDoc = parser.parseFromString(mapText, "image/svg+xml");
// Now find all circles again
const fallbackCircles = Array.from(defs.querySelectorAll("circle"));
if (fallbackCircles.length > 0) {
console.log(`Created ${fallbackCircles.length} fallback circles`);
return await processCircles(svgElement, fallbackCircles);
} else {
return false;
// Find circles in the original map
const originalCircles = Array.from(mapDoc.querySelectorAll("circle"));
console.log(`Found ${originalCircles.length} circles in original map`);
if (originalCircles.length > 0) {
return await processCircles(svgElement, originalCircles, true);
} else {
console.error(
"No circles found in original map either. Using fallback positions."
);
return await createFallbackCircles(svgElement);
}
} catch (error) {
console.error("Failed to load circles from original map:", error);
return await createFallbackCircles(svgElement);
}
} else {
return await processCircles(svgElement, allCircles);
return await processCircles(svgElement, allCircles, false);
}
} catch (error) {
console.error("Error populating map:", error);
@@ -172,16 +164,60 @@ export async function populateMap(svgElement) {
}
}
/**
* Create fallback circles at preset positions as a last resort
* @param {SVGElement} svgElement - The SVG DOM element
* @returns {Promise<boolean>} - Success flag
*/
async function createFallbackCircles(svgElement) {
// Create some fallback circles at predefined positions
const svgNamespace = "http://www.w3.org/2000/svg";
const defs = document.createElementNS(svgNamespace, "defs");
const positions = [
{ x: 100, y: 100 },
{ x: 200, y: 200 },
{ x: 300, y: 300 },
{ x: 400, y: 200 },
{ x: 500, y: 100 },
{ x: 600, y: 300 },
];
positions.forEach((pos, i) => {
const circle = document.createElementNS(svgNamespace, "circle");
circle.setAttribute("cx", pos.x.toString());
circle.setAttribute("cy", pos.y.toString());
circle.setAttribute("r", "5");
circle.setAttribute("fill", "transparent");
defs.appendChild(circle);
});
// Add the defs to the SVG
svgElement.appendChild(defs);
// Now find all circles again
const fallbackCircles = Array.from(defs.querySelectorAll("circle"));
if (fallbackCircles.length > 0) {
console.log(`Created ${fallbackCircles.length} fallback circles`);
return await processCircles(svgElement, fallbackCircles, false);
} else {
return false;
}
}
/**
* Process circles to create clue points
* @param {SVGElement} svgElement - The SVG DOM element
* @param {Array} circles - Array of circle elements
* @param {boolean} isFromOriginalMap - Whether circles are from the original map
* @returns {Promise<boolean>} - Success flag
*/
async function processCircles(svgElement, circles) {
async function processCircles(svgElement, circles, isFromOriginalMap) {
try {
// Hide original circles
circles.forEach((circle) => (circle.style.display = "none"));
// Don't hide original circles if they are from the original map and not present in current SVG
if (!isFromOriginalMap) {
// Remove hiding originals so the new elements are clearly visible
// circles.forEach((circle) => (circle.style.display = "none"));
}
// Fetch the number of clues from the API
const response = await fetch("/api/clues/count", {
@@ -198,7 +234,7 @@ async function processCircles(svgElement, circles) {
}
const data = await response.json();
const clueCount = parseInt(data.count, 10) || 0;
let clueCount = parseInt(data.count, 10) || 0;
console.log(`API returned clue count: ${clueCount}`);
if (clueCount <= 0) {
@@ -206,21 +242,17 @@ async function processCircles(svgElement, circles) {
clueCount = 5; // Fallback to 5 clues if API returns invalid data
}
// Sort circles by vertical position (top to bottom)
const sortedCircles = circles.sort((a, b) => {
const aY = parseFloat(a.getAttribute("cy") || "0");
const bY = parseFloat(b.getAttribute("cy") || "0");
return aY - bY;
});
// Determine how many circles to show
const circlesToShow = Math.min(sortedCircles.length, clueCount);
console.log(`Will create ${circlesToShow} clue points from sorted circles`);
// Use the circles exactly where they are - preserve original positions
// Just limit how many we use based on clue count
const circlesToShow = Math.min(circles.length, clueCount);
console.log(
`Will create ${circlesToShow} clue points from available circles`
);
// Create the overlay element that will go on top of everything
const svgNamespace = "http://www.w3.org/2000/svg";
// Remove any old overlay group
// Remove any old overlay group (but leave persistent button layer intact)
const oldOverlay = svgElement.querySelector(".clue-points-overlay");
if (oldOverlay && oldOverlay.parentNode) {
oldOverlay.parentNode.removeChild(oldOverlay);
@@ -238,9 +270,9 @@ async function processCircles(svgElement, circles) {
// Add the overlay group as the LAST element in the SVG to ensure proper rendering order
svgElement.appendChild(overlayGroup);
// Create interactive clue points
// Create interactive clue points based on the original circle positions
for (let i = 0; i < circlesToShow; i++) {
const originalCircle = sortedCircles[i];
const originalCircle = circles[i];
// Get original circle attributes
const cx = originalCircle.getAttribute("cx") || "0";
@@ -299,7 +331,50 @@ async function processCircles(svgElement, circles) {
// This ensures it's the last child of the SVG
svgElement.appendChild(overlayGroup);
console.log(`Successfully created ${circlesToShow} clue points`);
// Instead of appending button layer with absolute positioning,
// create/update it as a child of overlayGroup using normal SVG positioning.
let buttonGroup = svgElement.querySelector(".clue-button-layer");
if (buttonGroup) {
buttonGroup.innerHTML = "";
} else {
buttonGroup = document.createElementNS(svgNamespace, "g");
buttonGroup.setAttribute("class", "clue-button-layer");
// Remove absolute positioning; allow buttonGroup to inherit the overlay's coordinate system.
buttonGroup.setAttribute(
"style",
"pointer-events: auto; z-index: 10000;"
);
}
for (let i = 0; i < circlesToShow; i++) {
const originalCircle = circles[i];
const cx = originalCircle.getAttribute("cx") || "0";
const cy = originalCircle.getAttribute("cy") || "0";
const r = Math.max(
parseFloat(originalCircle.getAttribute("r") || "5"),
14
);
const button = document.createElementNS(svgNamespace, "circle");
button.setAttribute("cx", cx);
button.setAttribute("cy", cy);
button.setAttribute("r", r.toString());
button.setAttribute("class", "clue-button");
button.setAttribute(
"style",
"fill: #4caf50; stroke: #388e3c; stroke-width: 2px; cursor: pointer; opacity: 0.9; pointer-events: auto;"
);
button.addEventListener("click", () => {
console.log(`Button for clue ${i + 1} clicked`);
// ...add navigation or other logic here...
});
buttonGroup.appendChild(button);
}
// Append or re-append the buttonGroup into the overlayGroup so they appear together.
overlayGroup.appendChild(buttonGroup);
console.log(
`Successfully created ${circlesToShow} clue points and buttons`
);
return true;
} catch (error) {
console.error("Error processing circles:", error);