sky conditions chart

This commit is contained in:
2023-09-29 13:27:50 -04:00
parent 0b25745895
commit 1dd750fb5e
6 changed files with 113 additions and 11 deletions

View File

@@ -15,9 +15,9 @@ pub struct QualityControlFlags {
#[derive(Serialize, Deserialize, Debug)] #[derive(Serialize, Deserialize, Debug)]
pub struct SkyCondition { pub struct SkyCondition {
#[serde(rename = "@sky_cover")] #[serde(rename(deserialize = "@sky_cover"))]
pub sky_cover: String, pub sky_cover: String,
#[serde(rename = "@cloud_base_ft_agl")] #[serde(rename(deserialize = "@cloud_base_ft_agl"))]
pub cloud_base_ft_agl: Option<i32> pub cloud_base_ft_agl: Option<i32>
} }

27
ui/package-lock.json generated
View File

@@ -12,9 +12,11 @@
"@mantine/hooks": "^7.0.0", "@mantine/hooks": "^7.0.0",
"@mantine/modals": "^7.0.0", "@mantine/modals": "^7.0.0",
"axios": "^1.4.0", "axios": "^1.4.0",
"chart.js": "^4.4.0",
"leaflet": "^1.9.4", "leaflet": "^1.9.4",
"next": "^13.4.19", "next": "^13.4.19",
"react": "^18.2.0", "react": "^18.2.0",
"react-chartjs-2": "^5.2.0",
"react-dom": "^18.2.0", "react-dom": "^18.2.0",
"react-icons": "^4.11.0", "react-icons": "^4.11.0",
"react-leaflet": "^4.2.1", "react-leaflet": "^4.2.1",
@@ -196,6 +198,11 @@
"integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==", "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==",
"dev": true "dev": true
}, },
"node_modules/@kurkle/color": {
"version": "0.3.2",
"resolved": "https://registry.npmjs.org/@kurkle/color/-/color-0.3.2.tgz",
"integrity": "sha512-fuscdXJ9G1qb7W8VdHi+IwRqij3lBkosAm4ydQtEmbY58OzHXqQhvlxqEkoz0yssNVn38bcpRWgA9PP+OGoisw=="
},
"node_modules/@mantine/core": { "node_modules/@mantine/core": {
"version": "7.0.0", "version": "7.0.0",
"resolved": "https://registry.npmjs.org/@mantine/core/-/core-7.0.0.tgz", "resolved": "https://registry.npmjs.org/@mantine/core/-/core-7.0.0.tgz",
@@ -1219,6 +1226,17 @@
"url": "https://github.com/chalk/chalk?sponsor=1" "url": "https://github.com/chalk/chalk?sponsor=1"
} }
}, },
"node_modules/chart.js": {
"version": "4.4.0",
"resolved": "https://registry.npmjs.org/chart.js/-/chart.js-4.4.0.tgz",
"integrity": "sha512-vQEj6d+z0dcsKLlQvbKIMYFHd3t8W/7L2vfJIbYcfyPcRx92CsHqECpueN8qVGNlKyDcr5wBrYAYKnfu/9Q1hQ==",
"dependencies": {
"@kurkle/color": "^0.3.0"
},
"engines": {
"pnpm": ">=7"
}
},
"node_modules/client-only": { "node_modules/client-only": {
"version": "0.0.1", "version": "0.0.1",
"resolved": "https://registry.npmjs.org/client-only/-/client-only-0.0.1.tgz", "resolved": "https://registry.npmjs.org/client-only/-/client-only-0.0.1.tgz",
@@ -4042,6 +4060,15 @@
"node": ">=0.10.0" "node": ">=0.10.0"
} }
}, },
"node_modules/react-chartjs-2": {
"version": "5.2.0",
"resolved": "https://registry.npmjs.org/react-chartjs-2/-/react-chartjs-2-5.2.0.tgz",
"integrity": "sha512-98iN5aguJyVSxp5U3CblRLH67J8gkfyGNbiK3c+l1QI/G4irHMPQw44aEPmjVag+YKTyQ260NcF82GTQ3bdscA==",
"peerDependencies": {
"chart.js": "^4.1.1",
"react": "^16.8.0 || ^17.0.0 || ^18.0.0"
}
},
"node_modules/react-dom": { "node_modules/react-dom": {
"version": "18.2.0", "version": "18.2.0",
"resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.2.0.tgz", "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.2.0.tgz",

View File

@@ -13,9 +13,11 @@
"@mantine/hooks": "^7.0.0", "@mantine/hooks": "^7.0.0",
"@mantine/modals": "^7.0.0", "@mantine/modals": "^7.0.0",
"axios": "^1.4.0", "axios": "^1.4.0",
"chart.js": "^4.4.0",
"leaflet": "^1.9.4", "leaflet": "^1.9.4",
"next": "^13.4.19", "next": "^13.4.19",
"react": "^18.2.0", "react": "^18.2.0",
"react-chartjs-2": "^5.2.0",
"react-dom": "^18.2.0", "react-dom": "^18.2.0",
"react-icons": "^4.11.0", "react-icons": "^4.11.0",
"react-leaflet": "^4.2.1", "react-leaflet": "^4.2.1",

View File

@@ -1,3 +1,13 @@
export interface SkyCondition {
sky_cover: string;
cloud_base_ft_agl: number;
}
export interface QualityControlFlags {
auto: boolean;
auto_station: boolean;
}
export interface Metar { export interface Metar {
raw_text: string; raw_text: string;
station_id: string; station_id: string;
@@ -11,15 +21,9 @@ export interface Metar {
visibility_statute_mi: string; visibility_statute_mi: string;
altim_in_hg: number; altim_in_hg: number;
sea_level_pressure_mb: number; sea_level_pressure_mb: number;
quality_control_flags: { quality_control_flags: QualityControlFlags;
auto: boolean;
auto_station: boolean;
};
wx_string: string; wx_string: string;
sky_condition: { sky_condition: SkyCondition[];
sky_cover: string;
cloud_base_ft_agl: number;
}[];
flight_category: 'VFR' | 'MVFR' | 'LIFR' | 'IFR' | 'UNKN'; flight_category: 'VFR' | 'MVFR' | 'LIFR' | 'IFR' | 'UNKN';
three_hr_pressure_tendency_mb: number; three_hr_pressure_tendency_mb: number;
metar_type: string; metar_type: string;

View File

@@ -15,6 +15,7 @@ import {
import { useState } from 'react'; import { useState } from 'react';
import { Grid, Modal, Tooltip } from '@mantine/core'; import { Grid, Modal, Tooltip } from '@mantine/core';
import './metars.css'; import './metars.css';
import SkyConditions from './SkyConditions';
interface MetarModalProps { interface MetarModalProps {
airport: Airport; airport: Airport;
@@ -137,7 +138,9 @@ function MetarInfo({ metar }: { metar: Metar }) {
<span style={{ marginLeft: '0.5em' }}> <span style={{ marginLeft: '0.5em' }}>
{metar.wind_speed_kt != undefined && metar.wind_speed_kt > 0 ? `${metar.wind_speed_kt} KT` : 'CALM'} {metar.wind_speed_kt != undefined && metar.wind_speed_kt > 0 ? `${metar.wind_speed_kt} KT` : 'CALM'}
</span> </span>
{/* {metar.sky_condition != undefined && metar.sky_condition.map((skyCondition) => <>test</>)} */} </Grid.Col>
<Grid.Col className='gutter-row' span={6}>
<SkyConditions metar={metar} />
</Grid.Col> </Grid.Col>
<Grid.Col className='gutter-row' span={12}> <Grid.Col className='gutter-row' span={12}>
{metar.wx_string && metar.wx_string.split(' ').map((wx) => <MetarIcon wx={wx} />)} {metar.wx_string && metar.wx_string.split(' ').map((wx) => <MetarIcon wx={wx} />)}

View File

@@ -0,0 +1,66 @@
'use client';
import { Metar, SkyCondition } from '@/api/metar.types';
import {
Chart as ChartJS,
CategoryScale,
LinearScale,
PointElement,
LineElement,
Title,
Tooltip,
Filler,
Legend
} from 'chart.js';
import { Line } from 'react-chartjs-2';
ChartJS.register(CategoryScale, LinearScale, PointElement, LineElement, Title, Tooltip, Filler, Legend);
export default function SkyConditions({ metar }: { metar: Metar }) {
function skyConditionColor(skyCondition: SkyCondition) {
if (skyCondition.sky_cover == 'CLR') {
return '#FFFFFF';
} else if (skyCondition.sky_cover == 'FEW') {
return '#19c4e6';
} else if (skyCondition.sky_cover == 'SCT') {
return '#6119e6';
} else if (skyCondition.sky_cover == 'BKN') {
return '#e6c019';
} else if (skyCondition.sky_cover == 'OVC') {
return '#e68019';
} else {
return '#e6194b';
}
}
function createDataset(skyCondition: SkyCondition) {
return {
fill: true,
label: skyCondition.sky_cover,
data: [skyCondition.cloud_base_ft_agl, skyCondition.cloud_base_ft_agl],
backgroundColor: skyConditionColor(skyCondition)
};
}
if (metar.sky_condition && metar.sky_condition.length > 0) {
console.log(metar);
const options = {
responsive: true,
plugins: {
legend: {
display: false
},
title: {
display: true,
text: 'Sky Conditions'
}
}
};
const data = {
labels: ['', ''],
datasets: metar.sky_condition.map((skyCondition) => createDataset(skyCondition))
};
return <Line options={options} data={data} />;
} else {
return <></>;
}
}