Initial Commit

This commit is contained in:
ddnthemc 2025-04-21 18:33:12 +02:00
commit b499bd0890
9 changed files with 347 additions and 0 deletions

3
.idea/.gitignore generated vendored Normal file
View file

@ -0,0 +1,3 @@
# Default ignored files
/shelf/
/workspace.xml

8
.idea/CheitMaps.iml generated Normal file
View file

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="PYTHON_MODULE" version="4">
<component name="NewModuleRootManager">
<content url="file://$MODULE_DIR$" />
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>

View file

@ -0,0 +1,6 @@
<component name="InspectionProjectProfileManager">
<settings>
<option name="USE_PROJECT_PROFILE" value="false" />
<version value="1.0" />
</settings>
</component>

7
.idea/misc.xml generated Normal file
View file

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="Black">
<option name="sdkName" value="Python 3.11" />
</component>
<component name="ProjectRootManager" version="2" project-jdk-name="Python 3.11" project-jdk-type="Python SDK" />
</project>

8
.idea/modules.xml generated Normal file
View file

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/.idea/CheitMaps.iml" filepath="$PROJECT_DIR$/.idea/CheitMaps.iml" />
</modules>
</component>
</project>

6
.idea/vcs.xml generated Normal file
View file

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$" vcs="Git" />
</component>
</project>

198
main.py Normal file
View file

@ -0,0 +1,198 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
# backend/main.py
from fastapi import FastAPI, Request
from fastapi.responses import HTMLResponse
from fastapi.staticfiles import StaticFiles
from fastapi.templating import Jinja2Templates
import uvicorn
from pathlib import Path
app = FastAPI()
# Mount static folder to serve images, PDFs, JS if needed
app.mount("/static", StaticFiles(directory="static"), name="static")
# Set up template rendering
templates = Jinja2Templates(directory="templates")
# Sample map data
MapsFolder = Path('./static/maps')
maps = [
{
"id": 2,
"name": "DaisyRevedins",
"latitude": 44.480829598869185,
"longitude": 11.352026314262476,
'stem': 'San Mamolo-JoNotte',
"description": "From the grass to the church while visiting the Hospital"
},
{
"id": 3,
"name": "CastelWeak",
"latitude": 44.49959787027563,
"longitude": 11.27473782212433,
'stem': 'Casteldebole_2024_05_15',
"description": "Totally Flat"
},
{
"id": 4,
"name": "Golinelli",
"latitude": 44.50847170695366,
"longitude": 11.308195638402232,
"stem": "Norwegian Sprint",
"description": "Jo Noche"
},
{
"id": 5,
"name": "SwordVille",
"latitude": 44.49119622583157,
"longitude": 11.308122673834362,
"stem": "A3-Pellegrino",
"description": "San Pellegrino night"
},
{
"id": 5,
"name": "Small Heaven",
"latitude": 44.375066657656234,
"longitude": 11.247854195489277,
"stem": "Piccolo Paradiso_small",
"description": "Fucked Dogs & Owners"
},
{
"id": 6,
"name": "Marzab8",
"latitude": 44.340876557519195,
"longitude": 11.208385117204514,
"stem": "Marzabotto-O-Training",
"description": "Marzabotto Greto Fiume"
},
{
"id": 7,
"name": "Bazzano",
"latitude": 44.506688577284855,
"longitude": 11.084856756615434,
'stem': 'Pro Mel',
"description": "Bazzano Pro Mel"
},
{
"id": 8,
"name": "Battindarno",
'coord': (44.495505920730935, 11.288849376526782),
'stem': 'JoNotte.2022.1',
"description": "Battindarno 2022-1"
},
{
"id": 9,
"name": "Daisy Gardens",
"latitude": 44.480829598869185,
"longitude": 11.3525,
'stem': 'Revedinmargherita',
"description": "Giardini e Revedin"
},
{
"id": 10,
"name": "Pontecchio",
"coord": (44.431200464913914, 11.269902531675038),
'stem': 'Pontecchio_night bo 2020',
"description": "Occhio al custode di villa Grifone"
},
{
"id": 11,
"name": "Sasso Marconi",
"coord": (44.398978299870166, 11.25642430653767),
'stem': 'night_bo_13_02_20',
"description": "Cà de Testi e Sasso"
},
{
"id": 12,
"name": "Croce e Funivia",
"coord": (44.48620778951313, 11.283029683468458),
'stem': '1802',
"description": "Da Casalatch alla Funivia"
},
{
"id": 13,
"name": "CastelWeakRiverBank",
"coord": (44.50400435370321, 11.283098136577783),
'stem': '11 febbraio',
"description": "Casteldebole e lungo fiume"
},
{
"id": 14,
"name": "ZanardiPark",
"coord": (44.48890188652948, 11.28842972160338),
'stem': 'ParcoZanardi',
"description": "Parco Zanardi, Casalatch"
},
{
"id": 15,
"name": "The Monster",
"coord": (44.47603075768931, 11.262382357503611),
'stem': 'EremoELITE',
"description": "Eremo di Tizzano / Mostro"
},
{
"id": 16,
"name": "Villa Angeletti",
"coord": (44.510693796692124, 11.333109723632031),
'stem': 'Night BO Villa Angeletti-Night 1',
"description": "Villa Angeletti 2020"
},
{
"id": 17,
"name": "Navile",
"coord": (44.536246247660856, 11.354504683188482),
'stem': 'NightBO_Navile_20022020',
"description": "Navile, Nightbo 2020"
},
]
for m in maps:
if 'stem' in m:
base = m['stem']
m['pdf'] = f'/static/maps/{base}.pdf'
for suffix in ('.jpg', '.png'):
fn = MapsFolder / f'{base}_small{suffix}'
if fn.is_file():
m['thumbnail'] = f'/static/maps/{fn.name}'
fn = MapsFolder / f'{base}_big{suffix}'
if fn.is_file():
m['full_size'] = f'/static/maps/{fn.name}'
if 'coord' in m:
lat, long = m.get('coord')
m['latitude'] = lat
m['longitude'] = long
# Serve the main map page
@app.get("/", response_class=HTMLResponse)
async def index(request: Request):
return templates.TemplateResponse("index.html", {"request": request})
# JSON endpoint to get map data
@app.get("/api/maps")
async def get_maps():
return maps
# Detailed map page
@app.get("/map/{map_id}", response_class=HTMLResponse)
async def map_detail(request: Request, map_id: int):
map_data = next((m for m in maps if m["id"] == map_id), None)
if not map_data:
return HTMLResponse(content="Map not found", status_code=404)
return templates.TemplateResponse("map_detail.html", {"request": request, "map": map_data})
def main():
pass
if __name__ == '__main__':
uvicorn.run(app, host="127.0.0.1", port=8000)

82
templates/index.html Normal file
View file

@ -0,0 +1,82 @@
<!-- backend/templates/index.html -->
<!DOCTYPE html>
<html>
<head>
<title>Orienteering Map Viewer</title>
<meta charset="utf-8" />
<link href="https://fonts.googleapis.com/css2?family=Poppins:wght@400;700&display=swap" rel="stylesheet">
<link href="https://fonts.googleapis.com/css2?family=Roboto:wght@400;700&display=swap" rel="stylesheet">
<link rel="stylesheet" href="https://unpkg.com/leaflet/dist/leaflet.css" />
<style>
#map { height: 100vh; margin: 0; }
.popup-img { width: 250px; cursor: pointer; }
body, html {
font-family: 'Roboto', sans-serif;
margin: 0;
padding: 0;
height: 100%;
}
#map {
height: 100vh;
}
#title-overlay {
font-family: 'Poppins', sans-serif;
position: absolute;
top: 20px;
left: 50%;
transform: translateX(-50%);
background-color: rgba(255, 255, 255, 0.8);
padding: 10px 20px;
border-radius: 12px;
font-size: 24px;
font-weight: bold;
z-index: 1000;
box-shadow: 0 2px 6px rgba(0,0,0,0.2);
}
</style>
</head>
<body>
<div id="map"></div>
<div id="title-overlay">Super Cheit Orienteering Maps<img src="/static/face.jog" style="width: 50px;" />
</div>
<div id="map"></div>
<script src="https://unpkg.com/leaflet/dist/leaflet.js"></script>
<script>
const map = L.map('map'); // Initialize without setting center and zoom yet
const flag = L.icon({ iconUrl: '/static/O_Flag_.svg', iconSize: [64, 80] , iconAnchor: [32, 79]})
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
attribution: '&copy; OpenStreetMap contributors'
}).addTo(map);
fetch("/api/maps")
.then(res => res.json())
.then(maps => {
const bounds = [];
maps.forEach(m => {
const latlng = [m.latitude, m.longitude];
bounds.push(latlng);
const marker = L.marker(latlng, {icon: flag}).addTo(map);
const popup = `
<strong>${m.name}</strong><br>
${m.description}<br>
<img class="popup-img" src="${m.thumbnail}" onclick="window.location='/map/${m.id}'" />
`;
marker.bindPopup(popup);
});
if (bounds.length > 0) {
map.fitBounds(bounds, { padding: [50, 50] });
} else {
// Fallback if no maps
map.setView([45, 9], 5); // Default view
}
});
</script>
</body>
</html>

29
templates/map_detail.html Normal file
View file

@ -0,0 +1,29 @@
<!-- backend/templates/map_detail.html -->
<!DOCTYPE html>
<html>
<head>
<title>{{ map.name }}</title>
<style>
body, html {
font-family: 'Roboto', sans-serif;
margin: 0;
padding: 0;
height: 100%;
}
</style>
</head>
<body>
<h1>{{ map.name }}</h1>
<p>{{ map.description }}</p>
<br>
<a href="{{ map.pdf }}" download>Download PDF</a>
<br>
<br>
<a href="https://www.google.com/maps?q={{ map.latitude }},{{ map.longitude }} "target="_blank">Parking Lot coordinates</a>
<br><br>
<a href="/">← Back to Map</a>
<br>
<br>
<img src="{{ map.full_size }}" style="width: 100vw;" />
</body>
</html>