All checks were successful
Build & Deploy / 🔍 Prepare (push) Successful in 44s
Build & Deploy / 🧪 QA (push) Successful in 1m4s
Build & Deploy / 🏗️ Build (push) Successful in 1m54s
Build & Deploy / 🚀 Deploy (push) Successful in 28s
Build & Deploy / 🧪 Post-Deploy Verification (push) Successful in 43s
Build & Deploy / 🔔 Notify (push) Successful in 2s
71 lines
2.2 KiB
TypeScript
71 lines
2.2 KiB
TypeScript
import metadataJson from '../public/assets/image-metadata.json';
|
|
|
|
export interface ImageMeta {
|
|
file: string;
|
|
category: 'pv' | 'wind' | 'fiber' | 'power' | 'battery' | 'unknown';
|
|
environment: 'freies_feld' | 'urban' | 'wald' | 'indoor' | 'unknown';
|
|
quality_score: number;
|
|
description: string;
|
|
}
|
|
|
|
const metadata = metadataJson as Record<string, ImageMeta>;
|
|
|
|
// Create a deterministic pseudo-random number based on a string
|
|
function hashString(str: string): number {
|
|
let hash = 0;
|
|
for (let i = 0; i < str.length; i++) {
|
|
const char = str.charCodeAt(i);
|
|
hash = (hash << 5) - hash + char;
|
|
hash = hash & hash; // Convert to 32bit integer
|
|
}
|
|
return Math.abs(hash);
|
|
}
|
|
|
|
/**
|
|
* Returns a fitting, highly-rated image for a specific project type.
|
|
* It is deterministic based on the seed (e.g. project ID).
|
|
*/
|
|
export function getImageForProject(seed: string, category: string): string {
|
|
const allImages = Object.values(metadata);
|
|
|
|
// 1. Filter by category
|
|
let candidates = allImages.filter(img => img.category === category);
|
|
|
|
// If no candidates for category, fallback to fiber (Kabeltiefbau is safe default for ETIB)
|
|
if (candidates.length === 0) {
|
|
candidates = allImages.filter(img => img.category === 'fiber');
|
|
}
|
|
|
|
// Still empty? Just get anything highly rated
|
|
if (candidates.length === 0) {
|
|
candidates = allImages;
|
|
}
|
|
|
|
// 2. Sort by quality score (descending)
|
|
candidates.sort((a, b) => b.quality_score - a.quality_score);
|
|
|
|
// 3. For PV and Wind, strongly prefer 'freies_feld'
|
|
if (category === 'pv' || category === 'wind') {
|
|
const fieldCandidates = candidates.filter(img => img.environment === 'freies_feld' && img.quality_score >= 6);
|
|
if (fieldCandidates.length > 0) {
|
|
candidates = fieldCandidates;
|
|
}
|
|
} else {
|
|
// For others, just take top 30% quality to have some variation
|
|
candidates = candidates.filter(img => img.quality_score >= 6);
|
|
if (candidates.length === 0) {
|
|
candidates = allImages.filter(img => img.category === category);
|
|
}
|
|
}
|
|
|
|
if (candidates.length === 0) {
|
|
return '/assets/logo.png'; // Ultimate fallback
|
|
}
|
|
|
|
// 4. Deterministically pick one based on the seed
|
|
const hash = hashString(seed);
|
|
const index = hash % candidates.length;
|
|
|
|
return candidates[index].file;
|
|
}
|