added cosmic, added passcode

This commit is contained in:
Dustella 2025-01-18 22:00:26 +08:00
parent f80f93a9b3
commit 52deafb19f
17 changed files with 275 additions and 51 deletions

2
auto-imports.d.ts vendored
View File

@ -9,6 +9,7 @@ declare global {
const EffectScope: typeof import('vue')['EffectScope'] const EffectScope: typeof import('vue')['EffectScope']
const asyncComputed: typeof import('@vueuse/core')['asyncComputed'] const asyncComputed: typeof import('@vueuse/core')['asyncComputed']
const autoResetRef: typeof import('@vueuse/core')['autoResetRef'] const autoResetRef: typeof import('@vueuse/core')['autoResetRef']
const baseFetch: typeof import('./src/composables/fetch')['baseFetch']
const computed: typeof import('vue')['computed'] const computed: typeof import('vue')['computed']
const computedAsync: typeof import('@vueuse/core')['computedAsync'] const computedAsync: typeof import('@vueuse/core')['computedAsync']
const computedEager: typeof import('@vueuse/core')['computedEager'] const computedEager: typeof import('@vueuse/core')['computedEager']
@ -309,6 +310,7 @@ declare module 'vue' {
readonly EffectScope: UnwrapRef<typeof import('vue')['EffectScope']> readonly EffectScope: UnwrapRef<typeof import('vue')['EffectScope']>
readonly asyncComputed: UnwrapRef<typeof import('@vueuse/core')['asyncComputed']> readonly asyncComputed: UnwrapRef<typeof import('@vueuse/core')['asyncComputed']>
readonly autoResetRef: UnwrapRef<typeof import('@vueuse/core')['autoResetRef']> readonly autoResetRef: UnwrapRef<typeof import('@vueuse/core')['autoResetRef']>
readonly baseFetch: UnwrapRef<typeof import('./src/composables/fetch')['baseFetch']>
readonly computed: UnwrapRef<typeof import('vue')['computed']> readonly computed: UnwrapRef<typeof import('vue')['computed']>
readonly computedAsync: UnwrapRef<typeof import('@vueuse/core')['computedAsync']> readonly computedAsync: UnwrapRef<typeof import('@vueuse/core')['computedAsync']>
readonly computedEager: UnwrapRef<typeof import('@vueuse/core')['computedEager']> readonly computedEager: UnwrapRef<typeof import('@vueuse/core')['computedEager']>

View File

@ -107,11 +107,23 @@ const data = {
isActive: true, isActive: true,
items: [ items: [
{ {
title: '波动', title: '行星波月统计',
url: '/tidi/waves', url: '/tidi/waves',
}, },
], ],
}, },
{
title: 'COSMIC',
url: '#',
icon: 'mdi:telescope',
isActive: true,
items: [
{
title: '行星波月统计',
url: '/cosmic/stats',
},
],
},
], ],
关于: [ 关于: [

111
src/components/CoolBack.vue Normal file
View File

@ -0,0 +1,111 @@
<script setup lang="ts">
import type { P5I } from 'p5i'
import { p5i } from 'p5i'
import { onMounted, onUnmounted, ref } from 'vue'
const el = ref<HTMLCanvasElement | null>(null)
const {
mount,
unmount,
createCanvas,
background,
noFill,
stroke,
noise,
noiseSeed,
resizeCanvas,
cos,
sin,
TWO_PI,
} = p5i()
let w = window.innerWidth
let h = window.innerHeight
const offsetY = window.scrollY
const SCALE = 200
const LENGTH = 10
const SPACING = 15
function getForceOnPoint(x: number, y: number, z: number) {
// https://p5js.org/reference/#/p5/noise
return (noise(x / SCALE, y / SCALE, z) - 0.5) * 2 * TWO_PI
}
const existingPoints = new Set<string>()
const points: { x: number, y: number, opacity: number }[] = []
function addPoints() {
for (let x = -SPACING / 2; x < w + SPACING; x += SPACING) {
for (let y = -SPACING / 2; y < h + offsetY + SPACING; y += SPACING) {
const id = `${x}-${y}`
if (existingPoints.has(id))
continue
existingPoints.add(id)
points.push({ x, y, opacity: Math.random() * 0.5 + 0.5 })
}
}
}
function setup() {
createCanvas(w, h)
background('#ffffff')
stroke('#ccc')
noFill()
noiseSeed(+new Date())
addPoints()
}
function draw({ circle }: P5I) {
background('#ffffff')
const t = +new Date() / 10000
for (const p of points) {
const { x, y } = p
const rad = getForceOnPoint(x, y, t)
const length = (noise(x / SCALE, y / SCALE, t * 2) + 0.5) * LENGTH
const nx = x + cos(rad) * length
const ny = y + sin(rad) * length
stroke(180, 180, 180, (Math.abs(cos(rad)) * 0.5 + 0.5) * p.opacity * 255)
circle(nx, ny - offsetY, 1)
}
}
function restart() {
if (el.value)
mount(el.value, { setup, draw })
}
onMounted(() => {
restart()
useEventListener('resize', () => {
w = window.innerWidth
h = window.innerHeight
resizeCanvas(w, h)
addPoints()
})
// Uncomment to enable scroll-based animation
// Tho there is some lag when scrolling, not sure if it's solvable
// useEventListener('scroll', () => {
// offsetY = window.scrollY
// addPoints()
// }, { passive: true })
})
onUnmounted(() => {
unmount()
})
</script>
<template>
<!-- <Paper> -->
<div relative h-100 class="overflow-hidden">
<div ref="el" pointer-events-none overflow-hidden />
</div>
<!-- </Paper> -->
</template>

21
src/composables/fetch.ts Normal file
View File

@ -0,0 +1,21 @@
import { createFetch } from '@vueuse/core'
import { API_BASE_URL } from '~/CONSTANT'
export const baseFetch = createFetch({
baseUrl: API_BASE_URL,
options: {
async beforeFetch({ options }) {
const code = '0101'
options.headers = {
...options.headers,
Authorization: `${code}`,
}
return { options }
},
},
fetchOptions: {
mode: 'cors',
},
})

View File

@ -1 +1,2 @@
export * from './dark' export * from './dark'
export * from './fetch'

View File

@ -35,11 +35,12 @@ const form = useForm()
const stagedDates = ref<string[]>([]) const stagedDates = ref<string[]>([])
onMounted(async () => { onMounted(async () => {
await fetch(`${API_BASE_URL}/balloon/metadata`).then(resp => resp.json()).then((data) => { await baseFetch<string []>(`${API_BASE_URL}/balloon/metadata`).json().then(({ data }) => {
stagedDates.value = data const das = data.value!
stagedDates.value = das
formSchema.value = z.object({ formSchema.value = z.object({
selectedMode: z.enum(modes).describe('选择一个模式'), selectedMode: z.enum(modes).describe('选择一个模式'),
selectedDate: z.enum(data.map((d: string) => { selectedDate: z.enum(das.map((d: string) => {
const datePattern = /_\d{8}T\d{6}/ const datePattern = /_\d{8}T\d{6}/
if (!datePattern.test(d)) { if (!datePattern.test(d)) {
return '' return ''
@ -51,7 +52,7 @@ onMounted(async () => {
return capture[0] return capture[0]
})), })),
}).describe('选择一个日期') }).describe('选择一个日期')
form.setFieldValue('selectedDate', data[0]) form.setFieldValue('selectedDate', data.value![0])
form.setFieldValue('selectedMode', modes[0]) form.setFieldValue('selectedMode', modes[0])
}) })
}) })
@ -60,8 +61,9 @@ async function get_image(
selectedMode: string, selectedMode: string,
selectedDate: string, selectedDate: string,
) { ) {
const resp = await fetch(`${API_BASE_URL}/balloon/render/single?mode=${encodeURIComponent(selectedMode)}&path=${encodeURIComponent(selectedDate)}`) const { response } = await baseFetch(`${API_BASE_URL}/balloon/render/single?mode=${encodeURIComponent(selectedMode)}&path=${encodeURIComponent(selectedDate)}`)
// check for MIME Type, check if is png // check for MIME Type, check if is png
const resp = response.value!
const isPng = resp.headers.get('Content-Type') === 'image/png' const isPng = resp.headers.get('Content-Type') === 'image/png'
if (!isPng) { if (!isPng) {
imageResult.result = 'error' as const imageResult.result = 'error' as const

View File

@ -44,8 +44,8 @@ const modes = [
async function refreshImage() { async function refreshImage() {
const url = `${API_BASE_URL}/balloon/render/year?mode=${encodeURIComponent(selectedMode.value)}&start_year=${startYear.value}&end_year=${endYear.value}` const url = `${API_BASE_URL}/balloon/render/year?mode=${encodeURIComponent(selectedMode.value)}&start_year=${startYear.value}&end_year=${endYear.value}`
const resp = await fetch(url) const { data } = await baseFetch(url).arrayBuffer()
const blob = await resp.blob() const blob = new Blob([data.value!])
const u = URL.createObjectURL(blob) const u = URL.createObjectURL(blob)
imageResult.result = 'success' imageResult.result = 'success'
imageResult.imageUrl = u imageResult.imageUrl = u

View File

@ -0,0 +1,64 @@
<route lang="json">
{"meta":{
"title":"COSMIC",
"description":"行星波月统计",
"group":"COSMIC",
"item_name":"行星波月统计"
}}
</route>
<script setup lang="ts">
import type { ImageResult } from '~/components/ImageContainer.vue'
import DenseFramework from '~/components/DenseFramework.vue'
import { API_BASE_URL } from '~/CONSTANT'
const imageResult = reactive<ImageResult>({
result: 'idle',
imageUrl: '',
message: '',
})
const selectedT = ref<'5' | '10' | '16'>('5')
const fetchUrl = computed(() => {
const query = new URLSearchParams()
query.set('T_', selectedT.value)
return `${API_BASE_URL}/cosmic/temp_render?${query}`
})
const { onFetchResponse, isFetching, execute } = baseFetch(fetchUrl, {
immediate: false,
})
watch(isFetching, (isFetching) => {
if (isFetching) {
imageResult.result = 'pending'
}
})
onFetchResponse(async (resp) => {
const blob = await resp.blob()
const url = URL.createObjectURL(blob)
imageResult.result = 'success'
imageResult.imageUrl = url
})
</script>
<template>
<DenseFramework :image-result="imageResult" @submit="execute">
<Label for="T_range">滑动窗口</Label>
<Tabs id="T_range" v-model="selectedT" default-value="5">
<TabsList class="grid grid-cols-3 w-full">
<TabsTrigger value="5">
5
</TabsTrigger>
<TabsTrigger value="10">
10
</TabsTrigger>
<TabsTrigger value="16">
16
</TabsTrigger>
</TabsList>
</Tabs>
</DenseFramework>
</template>

View File

@ -13,7 +13,7 @@
import type { ImageResult } from '~/components/ImageContainer.vue' import type { ImageResult } from '~/components/ImageContainer.vue'
import { API_BASE_URL } from '~/CONSTANT' import { API_BASE_URL } from '~/CONSTANT'
const selectedMode = ref('潮汐波') const selectedMode = ref('2日行星波')
const selectedWave = ref('潮汐波') const selectedWave = ref('潮汐波')
const selectedDateType = ref('day') const selectedDateType = ref('day')
const selectedStation = ref('武汉左岭镇站') const selectedStation = ref('武汉左岭镇站')
@ -68,7 +68,7 @@ const queryUrl = computed(() => {
return path return path
}) })
const { onFetchResponse, isFetching, execute } = useFetch(queryUrl, { immediate: false }) const { onFetchResponse, isFetching, execute } = baseFetch(queryUrl, { immediate: false })
onFetchResponse(async (resp) => { onFetchResponse(async (resp) => {
const blob = await resp.blob() const blob = await resp.blob()
@ -84,8 +84,8 @@ watch(isFetching, (fetching) => {
}) })
onMounted(async () => { onMounted(async () => {
const resp = await fetch(`${API_BASE_URL}/radar/metadata`) const resp = await baseFetch(`${API_BASE_URL}/radar/metadata`).json()
const data = await resp.json() const data = await resp.data.value
// use regex to extract the year from the path, // use regex to extract the year from the path,
// ./radar/data\\\\2017\\ZLT_MET01_DLL_L21_01D_20170316.txt // ./radar/data\\\\2017\\ZLT_MET01_DLL_L21_01D_20170316.txt
const station_pattern = /data\/(.*?)\// const station_pattern = /data\/(.*?)\//
@ -109,6 +109,12 @@ onMounted(async () => {
paths.value = data paths.value = data
}) })
watch(selectedYear, (newV) => {
selectedDate.value = Array.from(dates.value).filter(
d => d.startsWith(newV),
)[0]
})
</script> </script>
<template> <template>
@ -128,7 +134,7 @@ onMounted(async () => {
</Tabs> </Tabs>
<div v-if="selectedWave === '行星波'"> <div v-if="selectedWave === '行星波'">
<Label>行星波类型</Label> <Label>行星波类型</Label>
<Tabs v-model="selectedMode" default-value="uwind"> <Tabs v-model="selectedMode" default-value="2日行星波">
<TabsList class="grid grid-cols-4 w-full"> <TabsList class="grid grid-cols-4 w-full">
<TabsTrigger v-for="m in modes" :key="m" :value="m"> <TabsTrigger v-for="m in modes" :key="m" :value="m">
{{ m.replace("行星波", "") }} {{ m.replace("行星波", "") }}

View File

@ -47,7 +47,7 @@ const queryUrl = computed(() => {
return path return path
}) })
const { onFetchResponse, isFetching, execute } = useFetch(queryUrl, { immediate: false }) const { onFetchResponse, isFetching, execute } = baseFetch(queryUrl, { immediate: false })
onFetchResponse(async (resp) => { onFetchResponse(async (resp) => {
const blob = await resp.blob() const blob = await resp.blob()
@ -63,8 +63,8 @@ watch(isFetching, (fetching) => {
}) })
onMounted(async () => { onMounted(async () => {
const resp = await fetch(`${API_BASE_URL}/radar/metadata`) const resp = await baseFetch(`${API_BASE_URL}/radar/metadata`).json()
const data = await resp.json() const data = await resp.data.value!
// use regex to extract the year from the path, // use regex to extract the year from the path,
// ./radar/data\\\\2017\\ZLT_MET01_DLL_L21_01D_20170316.txt // ./radar/data\\\\2017\\ZLT_MET01_DLL_L21_01D_20170316.txt
const station_pattern = /data\/(.*?)\// const station_pattern = /data\/(.*?)\//

View File

@ -32,7 +32,7 @@ const urll = computed(() => {
const query = `path=${path}&day=${day}&cycle_no=${selected.cycle_no}` const query = `path=${path}&day=${day}&cycle_no=${selected.cycle_no}`
return `${API_BASE_URL}/saber/render/day_cycle_power_wave_plot?${query}` return `${API_BASE_URL}/saber/render/day_cycle_power_wave_plot?${query}`
}) })
const { onFetchResponse, isFetching, execute } = useFetch( const { onFetchResponse, isFetching, execute } = baseFetch(
urll, urll,
{ immediate: false }, { immediate: false },
) )
@ -50,20 +50,23 @@ onFetchResponse(async (resp) => {
imageResult.imageUrl = url imageResult.imageUrl = url
}) })
onMounted(() => { onMounted(async () => {
refreshPath() await refreshPath()
selected.path = saberPaths.value[0] selected.path = saberPaths.value[0]
}) })
watch(() => selected.path, () => { watch(() => selected.path, async () => {
refreshCurrentSaberDays(selected.path) if (selected.path === '') {
if (selected.day === '') { return
}
await refreshCurrentSaberDays(selected.path)
if (selected.day === '' && currentSaberDays.value.length > 0) {
selected.day = currentSaberDays.value[0] selected.day = currentSaberDays.value[0]
} }
}) })
function renderPath(path: string) { function renderPath(path: string) {
const yearPattern = /\/data\\(\d{4})/ const yearPattern = /\/data\/(\d{4})/
const year = path.match(yearPattern)?.[1] const year = path.match(yearPattern)?.[1]
const monthPattern = /Temp_O3_(.*)(\d{4})/ const monthPattern = /Temp_O3_(.*)(\d{4})/
const month = path.match(monthPattern)?.[1] const month = path.match(monthPattern)?.[1]

View File

@ -32,7 +32,7 @@ const urll = computed(() => {
const query = `path=${path}&day=${day}&cycle_no=${selected.cycle_no}` const query = `path=${path}&day=${day}&cycle_no=${selected.cycle_no}`
return `${API_BASE_URL}/saber/render/day_fft_ifft_plot?${query}` return `${API_BASE_URL}/saber/render/day_fft_ifft_plot?${query}`
}) })
const { onFetchResponse, isFetching, execute } = useFetch( const { onFetchResponse, isFetching, execute } = baseFetch(
urll, urll,
{ immediate: false }, { immediate: false },
) )
@ -50,20 +50,20 @@ onFetchResponse(async (resp) => {
imageResult.imageUrl = url imageResult.imageUrl = url
}) })
onMounted(() => { onMounted(async () => {
refreshPath() await refreshPath()
selected.path = saberPaths.value[0] selected.path = saberPaths.value[0]
}) })
watch(() => selected.path, () => { watch(() => selected.path, async () => {
refreshCurrentSaberDays(selected.path) await refreshCurrentSaberDays(selected.path)
if (selected.day === '') { if (selected.day === '') {
selected.day = currentSaberDays.value[0] selected.day = currentSaberDays.value[0]
} }
}) })
function renderPath(path: string) { function renderPath(path: string) {
const yearPattern = /\/data\\(\d{4})/ const yearPattern = /\/data\/(\d{4})/
const year = path.match(yearPattern)?.[1] const year = path.match(yearPattern)?.[1]
const monthPattern = /Temp_O3_(.*)(\d{4})/ const monthPattern = /Temp_O3_(.*)(\d{4})/
const month = path.match(monthPattern)?.[1] const month = path.match(monthPattern)?.[1]

View File

@ -29,7 +29,7 @@ const urll = computed(() => {
const query = `path=${path}` const query = `path=${path}`
return `${API_BASE_URL}/saber/render/month_power_wave_plot?${query}` return `${API_BASE_URL}/saber/render/month_power_wave_plot?${query}`
}) })
const { onFetchResponse, execute, isFetching } = useFetch( const { onFetchResponse, execute, isFetching } = baseFetch(
urll, urll,
{ immediate: false }, { immediate: false },
) )
@ -47,13 +47,13 @@ onFetchResponse(async (resp) => {
imageResult.imageUrl = url imageResult.imageUrl = url
}) })
onMounted(() => { onMounted(async () => {
refreshPath() await refreshPath()
selected.path = saberPaths.value[0] selected.path = saberPaths.value[0]
}) })
function renderPath(path: string) { function renderPath(path: string) {
const yearPattern = /\/data\\(\d{4})/ const yearPattern = /\/data\/(\d{4})/
const year = path.match(yearPattern)?.[1] const year = path.match(yearPattern)?.[1]
const monthPattern = /Temp_O3_(.*)(\d{4})/ const monthPattern = /Temp_O3_(.*)(\d{4})/
const month = path.match(monthPattern)?.[1] const month = path.match(monthPattern)?.[1]

View File

@ -32,7 +32,7 @@ const urll = computed(() => {
const query = `path=${path}&day=${day}&height=${selected.height_no}` const query = `path=${path}&day=${day}&height=${selected.height_no}`
return `${API_BASE_URL}/saber/render/plot_wave_fitting?${query}` return `${API_BASE_URL}/saber/render/plot_wave_fitting?${query}`
}) })
const { onFetchResponse, execute, isFetching } = useFetch( const { onFetchResponse, execute, isFetching } = baseFetch(
urll, urll,
{ immediate: false }, { immediate: false },
) )
@ -50,20 +50,20 @@ onFetchResponse(async (resp) => {
imageResult.imageUrl = url imageResult.imageUrl = url
}) })
onMounted(() => { onMounted(async () => {
refreshPath() await refreshPath()
selected.path = saberPaths.value[0] selected.path = saberPaths.value[0]
}) })
watch(() => selected.path, () => { watch(() => selected.path, async () => {
refreshCurrentSaberDays(selected.path) await refreshCurrentSaberDays(selected.path)
if (saberPaths.value.length > 0) { if (saberPaths.value.length > 0) {
selected.path = saberPaths.value[0] selected.path = saberPaths.value[0]
} }
}) })
function renderPath(path: string) { function renderPath(path: string) {
const yearPattern = /\/data\\(\d{4})/ const yearPattern = /\/data\/(\d{4})/
const year = path.match(yearPattern)?.[1] const year = path.match(yearPattern)?.[1]
const monthPattern = /Temp_O3_(.*)(\d{4})/ const monthPattern = /Temp_O3_(.*)(\d{4})/
const month = path.match(monthPattern)?.[1] const month = path.match(monthPattern)?.[1]

View File

@ -6,15 +6,15 @@ const currentSaberDays = ref<string>('')
async function refreshPath() { async function refreshPath() {
if (saberPaths.value.length) if (saberPaths.value.length)
return return
const resp = await fetch(`${API_BASE_URL}/saber/metadata`) const resp = await baseFetch<string[]>(`${API_BASE_URL}/saber/metadata`).json()
const data = await resp.json() const data = resp.data.value
saberPaths.value = data saberPaths.value = data!
} }
async function refreshCurrentSaberDays(path: string) { async function refreshCurrentSaberDays(path: string) {
const resp = await fetch(`${API_BASE_URL}/saber/metadata/list_days?path=${path}`) const resp = await baseFetch<string>(`${API_BASE_URL}/saber/metadata/list_days?path=${path}`).json()
const data = await resp.json() const data = resp.data.value
currentSaberDays.value = data currentSaberDays.value = data!
} }
export { currentSaberDays, refreshCurrentSaberDays, refreshPath, saberPaths } export { currentSaberDays, refreshCurrentSaberDays, refreshPath, saberPaths }

View File

@ -15,7 +15,7 @@ const selectedYear = ref('2017')
// const k = [ -4,-3,-2,-1,0,1,2,3,4] // const k = [ -4,-3,-2,-1,0,1,2,3,4]
const selectedK = ref(0) const selectedK = ref(0)
const selectedT = ref(15) const selectedT = ref('5')
const queryUrl = computed(() => { const queryUrl = computed(() => {
const query = new URLSearchParams() const query = new URLSearchParams()
@ -26,7 +26,7 @@ const queryUrl = computed(() => {
return `${API_BASE_URL}/tidi/render/wave?${query}` return `${API_BASE_URL}/tidi/render/wave?${query}`
}) })
const { execute, onFetchResponse, isFetching } = useFetch(queryUrl, { immediate: false }) const { execute, onFetchResponse, isFetching } = baseFetch(queryUrl, { immediate: false })
watch(isFetching, (fetching) => { watch(isFetching, (fetching) => {
if (fetching) { if (fetching) {
@ -42,13 +42,14 @@ onFetchResponse(async (resp) => {
}) })
onMounted(async () => { onMounted(async () => {
const metas = await fetch(`${API_BASE_URL}/tidi/metadata`).then(resp => resp.json()) const metas = await baseFetch<{ path: string [] }>(`${API_BASE_URL}/tidi/metadata`).json()
const _years = metas.path.map((a: string) => { const _years = metas.data.value.path.map((a: string) => {
const year_pattern = /data\/(\d{4})\// const year_pattern = /data\/(\d{4})\//
return a.match(year_pattern)?.[1] return a.match(year_pattern)?.[1]
}) })
_years.sort() _years.sort()
years.value = Array.from(new Set(_years)) years.value = Array.from(new Set(_years))
selectedYear.value = years.value[0]
}) })
</script> </script>
@ -100,8 +101,8 @@ onMounted(async () => {
<TabsTrigger value="10"> <TabsTrigger value="10">
10 10
</TabsTrigger> </TabsTrigger>
<TabsTrigger value="15"> <TabsTrigger value="16">
15 16
</TabsTrigger> </TabsTrigger>
</TabsList> </TabsList>
</Tabs> </Tabs>

1
typed-router.d.ts vendored
View File

@ -22,6 +22,7 @@ declare module 'vue-router/auto-routes' {
'/[...all]': RouteRecordInfo<'/[...all]', '/:all(.*)', { all: ParamValue<true> }, { all: ParamValue<false> }>, '/[...all]': RouteRecordInfo<'/[...all]', '/:all(.*)', { all: ParamValue<true> }, { all: ParamValue<false> }>,
'/balloon/single': RouteRecordInfo<'/balloon/single', '/balloon/single', Record<never, never>, Record<never, never>>, '/balloon/single': RouteRecordInfo<'/balloon/single', '/balloon/single', Record<never, never>, Record<never, never>>,
'/balloon/year': RouteRecordInfo<'/balloon/year', '/balloon/year', Record<never, never>, Record<never, never>>, '/balloon/year': RouteRecordInfo<'/balloon/year', '/balloon/year', Record<never, never>, Record<never, never>>,
'/cosmic/stats': RouteRecordInfo<'/cosmic/stats', '/cosmic/stats', Record<never, never>, Record<never, never>>,
'/radar/v1': RouteRecordInfo<'/radar/v1', '/radar/v1', Record<never, never>, Record<never, never>>, '/radar/v1': RouteRecordInfo<'/radar/v1', '/radar/v1', Record<never, never>, Record<never, never>>,
'/radar/v2': RouteRecordInfo<'/radar/v2', '/radar/v2', Record<never, never>, Record<never, never>>, '/radar/v2': RouteRecordInfo<'/radar/v2', '/radar/v2', Record<never, never>, Record<never, never>>,
'/saber/day_cycle_power_wave_plot': RouteRecordInfo<'/saber/day_cycle_power_wave_plot', '/saber/day_cycle_power_wave_plot', Record<never, never>, Record<never, never>>, '/saber/day_cycle_power_wave_plot': RouteRecordInfo<'/saber/day_cycle_power_wave_plot', '/saber/day_cycle_power_wave_plot', Record<never, never>, Record<never, never>>,