1- import { useState } from 'react'
2- import reactLogo from './assets/react.svg'
3- import viteLogo from '/vite.svg'
4- import './App.css'
1+ import { useMemo , useState } from 'react' ;
52
6- function App ( ) {
7- const [ count , setCount ] = useState ( 0 )
3+ const DATA = {
4+ letters : {
5+ O : { name : 'Blue' , drive : 'Indium' , desc : 'Hottest, rarest, exotic planets.' , color : 'text-indigo-400' , bg : 'bg-indigo-900/20' , border : 'border-indigo-500' } ,
6+ B : { name : 'Blue-White' , drive : 'Indium' , desc : 'Very hot, high-value resources.' , color : 'text-blue-300' , bg : 'bg-blue-900/20' , border : 'border-blue-500' } ,
7+ A : { name : 'White' , drive : 'Cadmium' , desc : 'Hot, standard distribution.' , color : 'text-slate-100' , bg : 'bg-slate-700/20' , border : 'border-slate-400' } ,
8+ F : { name : 'Yellow-White' , drive : 'None' , desc : 'Warm, high chance of Lush biomes.' , color : 'text-yellow-100' , bg : 'bg-yellow-600/10' , border : 'border-yellow-200' } ,
9+ G : { name : 'Yellow' , drive : 'None' , desc : 'Temperate, Earth-like probability.' , color : 'text-yellow-400' , bg : 'bg-yellow-500/10' , border : 'border-yellow-500' } ,
10+ K : { name : 'Yellow-Orange' , drive : 'Emeril' , desc : 'Cool, diverse desert/arid types.' , color : 'text-orange-400' , bg : 'bg-orange-900/20' , border : 'border-orange-500' } ,
11+ M : { name : 'Red' , drive : 'Emeril' , desc : 'Coolest, common, many dead moons.' , color : 'text-red-400' , bg : 'bg-red-900/20' , border : 'border-red-500' } ,
12+ E : { name : 'Green' , drive : 'Viridium' , desc : 'Exotic/Glitch planet specialist.' , color : 'text-green-400' , bg : 'bg-green-900/20' , border : 'border-green-500' } ,
13+ } ,
14+ suffixes : {
15+ p : { label : 'Peculiar' , note : 'Likely contains Anomalous/Glitch planets.' } ,
16+ f : { label : 'Fresh' , note : 'Water present. Look for oceans.' } ,
17+ m : { label : 'Metallic' , note : 'Increased yield of rare metals.' } ,
18+ e : { label : 'Emission' , note : 'High radiation / Rare element spikes.' } ,
19+ v : { label : 'Variable' , note : 'Unstable star; chaotic weather patterns.' } ,
20+ }
21+ } ;
22+
23+ export default function App ( ) {
24+ const [ code , setCode ] = useState ( '' ) ;
25+
26+ const analysis = useMemo ( ( ) => {
27+ const cleaned = code . trim ( ) ;
28+ const match = cleaned . match ( / ^ ( [ O B A F G K M E ] ) ( [ 0 - 9 ] ) ( [ a - z ] + ) ? $ / i) ;
29+ if ( ! match ) return null ;
30+
31+ const [ _ , char , tempStr , suffStr ] = match ;
32+ const starLetter = char . toUpperCase ( ) ;
33+ const tempDigit = parseInt ( tempStr ) ;
34+ const suffixes = ( suffStr || '' ) . toLowerCase ( ) ;
35+
36+ const star = DATA . letters [ starLetter ] ;
37+ const traits = suffixes . split ( '' ) . filter ( s => DATA . suffixes [ s ] ) . map ( s => DATA . suffixes [ s ] ) ;
38+
39+ // Resource & Biome Logic
40+ const isExtreme = suffixes . includes ( 'e' ) ;
41+ const mainMetal = star . drive === 'None' ? 'Copper' : star . drive ;
42+
43+ let primaryBiome = "Balanced" ;
44+ if ( tempDigit <= 3 ) primaryBiome = "Scorched / Desert" ;
45+ else if ( tempDigit >= 7 ) primaryBiome = "Frozen / Tundra" ;
46+ else primaryBiome = "Lush / Tropical" ;
47+
48+ return {
49+ star,
50+ temp : tempDigit ,
51+ traits,
52+ projections : {
53+ primaryBiome,
54+ commonMetal : isExtreme ? `Activated ${ mainMetal } ` : mainMetal ,
55+ specialty : suffixes . includes ( 'f' ) ? "Salt / Cyto-phosphate" : "Carbon / Ferrite"
56+ }
57+ } ;
58+ } , [ code ] ) ;
859
960 return (
10- < >
11- < div >
12- < a href = "https://vite.dev" target = "_blank" >
13- < img src = { viteLogo } className = "logo" alt = "Vite logo" />
14- </ a >
15- < a href = "https://react.dev" target = "_blank" >
16- < img src = { reactLogo } className = "logo react" alt = "React logo" />
17- </ a >
18- </ div >
19- < h1 > Vite + React</ h1 >
20- < div className = "card" >
21- < button onClick = { ( ) => setCount ( ( count ) => count + 1 ) } >
22- count is { count }
23- </ button >
24- < p >
25- Edit < code > src/App.jsx</ code > and save to test HMR
26- </ p >
61+ < div className = "min-h-screen bg-black text-slate-300 font-mono p-4 flex flex-col items-center justify-center" >
62+ < div className = "w-full max-w-md" >
63+ < header className = "mb-8 text-center" >
64+ < h1 className = "text-xs uppercase tracking-[0.3em] text-cyan-500 mb-2" > Stellar Analyzer v1.1</ h1 >
65+ < div className = "h-1 w-12 bg-cyan-500 mx-auto" > </ div >
66+ </ header >
67+
68+ < input
69+ type = "text"
70+ maxLength = { 6 }
71+ placeholder = "ENTER CLASS (e.g. B5pf)"
72+ className = "w-full bg-slate-900 border-b-2 border-slate-700 p-4 text-2xl text-center outline-none focus:border-cyan-500 transition-colors uppercase tracking-widest text-white placeholder:opacity-20"
73+ onChange = { ( e ) => setCode ( e . target . value ) }
74+ value = { code }
75+ />
76+
77+ { analysis ? (
78+ < div className = { `mt-8 p-6 border-l-4 rounded-r-lg ${ analysis . star . bg } ${ analysis . star . border } animate-in fade-in slide-in-from-bottom-4 duration-500` } >
79+ { /* Header Section */ }
80+ < div className = "flex justify-between items-start mb-4" >
81+ < div >
82+ < h2 className = { `text-3xl font-black uppercase ${ analysis . star . color } ` } > { analysis . star . name } </ h2 >
83+ < p className = "text-sm opacity-70" > Hyperdrive: < span className = "text-white font-bold" > { analysis . star . drive } </ span > </ p >
84+ </ div >
85+ < div className = "text-right" >
86+ < span className = "text-4xl font-light" > { analysis . temp } </ span >
87+ < p className = "text-[10px] uppercase opacity-50" > Heat Index</ p >
88+ </ div >
89+ </ div >
90+
91+ < p className = "mb-6 text-sm italic border-b border-white/5 pb-4" > "{ analysis . star . desc } "</ p >
92+
93+ { /* Traits List */ }
94+ < div className = "space-y-4 mb-6" >
95+ { analysis . traits . length > 0 ? analysis . traits . map ( t => (
96+ < div key = { t . label } className = "flex items-start gap-3" >
97+ < div className = "mt-1 h-2 w-2 bg-cyan-400 rotate-45" />
98+ < div >
99+ < p className = "text-xs font-bold uppercase tracking-tighter text-cyan-400" > { t . label } </ p >
100+ < p className = "text-xs opacity-80" > { t . note } </ p >
101+ </ div >
102+ </ div >
103+ ) ) : (
104+ < p className = "text-[10px] uppercase opacity-40 italic font-bold" > No standard peculiarities detected</ p >
105+ ) }
106+ </ div >
107+
108+ { /* Projection Grid */ }
109+ < div className = "pt-6 border-t border-white/10" >
110+ < h3 className = "text-[10px] uppercase tracking-widest text-cyan-500 mb-3 font-bold" > Surface Scan Projections</ h3 >
111+ < div className = "grid grid-cols-2 gap-3" >
112+ < div className = "bg-black/40 p-3 rounded border border-white/5" >
113+ < p className = "text-[9px] uppercase opacity-50 mb-1" > Dominant Biome</ p >
114+ < p className = "text-xs text-white font-bold" > { analysis . projections . primaryBiome } </ p >
115+ </ div >
116+ < div className = "bg-black/40 p-3 rounded border border-white/5" >
117+ < p className = "text-[9px] uppercase opacity-50 mb-1" > Primary Mineral</ p >
118+ < p className = { `text-xs font-bold ${ analysis . star . color } ` } >
119+ { analysis . projections . commonMetal }
120+ </ p >
121+ </ div >
122+ </ div >
123+ < p className = "mt-3 text-[9px] opacity-40 text-center uppercase" > System potential: { analysis . projections . specialty } sources detected</ p >
124+ </ div >
125+ </ div >
126+ ) : (
127+ < div className = "mt-12 text-center" >
128+ < p className = "text-xs opacity-40 animate-pulse uppercase tracking-tighter" > Awaiting valid spectral coordinates...</ p >
129+ < div className = "flex justify-center gap-2 mt-4 opacity-20" >
130+ { [ 'O' , 'B' , 'A' , 'F' , 'G' , 'K' , 'M' , 'E' ] . map ( l => < span key = { l } className = "text-[10px]" > { l } </ span > ) }
131+ </ div >
132+ </ div >
133+ ) }
27134 </ div >
28- < p className = "read-the-docs" >
29- Click on the Vite and React logos to learn more
30- </ p >
31- </ >
32- )
33- }
34-
35- export default App
135+ </ div >
136+ ) ;
137+ }
0 commit comments