diff --git a/public/index.html b/public/index.html
index 8f1a647..9a8f14b 100644
--- a/public/index.html
+++ b/public/index.html
@@ -549,16 +549,92 @@
return { data, loading };
};
- const useBandConditions = () => {
- const [data, setData] = useState([
- { band: '160m', condition: 'FAIR' }, { band: '80m', condition: 'GOOD' },
- { band: '40m', condition: 'GOOD' }, { band: '30m', condition: 'GOOD' },
- { band: '20m', condition: 'GOOD' }, { band: '17m', condition: 'GOOD' },
- { band: '15m', condition: 'FAIR' }, { band: '12m', condition: 'FAIR' },
- { band: '10m', condition: 'POOR' }, { band: '6m', condition: 'POOR' },
- { band: '2m', condition: 'GOOD' }, { band: '70cm', condition: 'GOOD' }
- ]);
- const [loading, setLoading] = useState(false);
+ const useBandConditions = (spaceWeather) => {
+ const [data, setData] = useState([]);
+ const [loading, setLoading] = useState(true);
+
+ useEffect(() => {
+ if (!spaceWeather?.solarFlux) {
+ setLoading(true);
+ return;
+ }
+
+ const sfi = parseInt(spaceWeather.solarFlux) || 100;
+ const kIndex = parseInt(spaceWeather.kIndex) || 3;
+ const hour = new Date().getUTCHours();
+
+ // Determine if it's day or night (simplified - assumes mid-latitudes)
+ const isDaytime = hour >= 6 && hour <= 18;
+ const isGrayline = (hour >= 5 && hour <= 7) || (hour >= 17 && hour <= 19);
+
+ // Calculate band conditions based on SFI, K-index, and time
+ const calculateCondition = (band) => {
+ let score = 50; // Base score
+
+ // SFI impact (higher SFI = better high bands, less impact on low bands)
+ const sfiImpact = {
+ '160m': (sfi - 100) * 0.05,
+ '80m': (sfi - 100) * 0.1,
+ '60m': (sfi - 100) * 0.15,
+ '40m': (sfi - 100) * 0.2,
+ '30m': (sfi - 100) * 0.25,
+ '20m': (sfi - 100) * 0.35,
+ '17m': (sfi - 100) * 0.4,
+ '15m': (sfi - 100) * 0.45,
+ '12m': (sfi - 100) * 0.5,
+ '10m': (sfi - 100) * 0.55,
+ '6m': (sfi - 100) * 0.6,
+ '2m': 0, // VHF not affected by HF propagation
+ '70cm': 0
+ };
+ score += sfiImpact[band] || 0;
+
+ // K-index impact (geomagnetic storms hurt propagation)
+ // K=0-1: bonus, K=2-3: neutral, K=4+: penalty
+ if (kIndex <= 1) score += 15;
+ else if (kIndex <= 2) score += 5;
+ else if (kIndex >= 5) score -= 40;
+ else if (kIndex >= 4) score -= 25;
+ else if (kIndex >= 3) score -= 10;
+
+ // Time of day impact
+ const timeImpact = {
+ '160m': isDaytime ? -30 : 25, // Night band
+ '80m': isDaytime ? -20 : 20, // Night band
+ '60m': isDaytime ? -10 : 15,
+ '40m': isGrayline ? 20 : (isDaytime ? 5 : 15), // Good day & night
+ '30m': isDaytime ? 15 : 10,
+ '20m': isDaytime ? 25 : -15, // Day band
+ '17m': isDaytime ? 25 : -20,
+ '15m': isDaytime ? 20 : -25, // Day band
+ '12m': isDaytime ? 15 : -30,
+ '10m': isDaytime ? 15 : -35, // Day band, needs high SFI
+ '6m': isDaytime ? 10 : -40, // Sporadic E, mostly daytime
+ '2m': 10, // Local/tropo - always available
+ '70cm': 10
+ };
+ score += timeImpact[band] || 0;
+
+ // High bands need minimum SFI to open
+ if (['10m', '12m', '6m'].includes(band) && sfi < 100) score -= 30;
+ if (['15m', '17m'].includes(band) && sfi < 80) score -= 15;
+
+ // Convert score to condition
+ if (score >= 65) return 'GOOD';
+ if (score >= 40) return 'FAIR';
+ return 'POOR';
+ };
+
+ const bands = ['160m', '80m', '60m', '40m', '30m', '20m', '17m', '15m', '12m', '10m', '6m', '2m'];
+ const conditions = bands.map(band => ({
+ band,
+ condition: calculateCondition(band)
+ }));
+
+ setData(conditions);
+ setLoading(false);
+ }, [spaceWeather?.solarFlux, spaceWeather?.kIndex]);
+
return { data, loading };
};
@@ -2217,7 +2293,7 @@
};
const spaceWeather = useSpaceWeather();
- const bandConditions = useBandConditions();
+ const bandConditions = useBandConditions(spaceWeather.data);
const potaSpots = usePOTASpots();
const dxCluster = useDXCluster();
const contests = useContests();