use crate::land::FLAG_SVG;
use crate::nav::CyberiaNav;
use crate::signal::{
emit_signal, find_word, links_touching, mint_word, neuron, word_particle, Link,
};
use leptos::prelude::*;
pub struct SpeciesDef {
pub latin: &'static str,
pub common: &'static str,
pub category: &'static str,
pub products: &'static [&'static str],
pub blurb: &'static str,
pub price: f64,
pub unit: &'static str,
}
pub const SPECIES: &[SpeciesDef] = &[
SpeciesDef {
latin: "Musa acuminata",
common: "banana",
category: "tree",
products: &["banana", "banana-leaf"],
blurb: "The valley staple β fruit in bunches, leaves as plates and wrap.",
price: 2.0,
unit: "seedling",
},
SpeciesDef {
latin: "Persea americana",
common: "avocado",
category: "tree",
products: &["avocado"],
blurb: "Fat of the land β slow tree, rich yield.",
price: 5.0,
unit: "seedling",
},
SpeciesDef {
latin: "Coffea arabica",
common: "arabica coffee",
category: "tree",
products: &["coffee-cherry", "coffee"],
blurb: "Highland cash crop β cherry to bean to cup.",
price: 3.0,
unit: "seedling",
},
SpeciesDef {
latin: "Theobroma cacao",
common: "cacao",
category: "tree",
products: &["cacao-pod", "cacao"],
blurb: "Food of the gods β pod, nib, chocolate.",
price: 4.0,
unit: "seedling",
},
SpeciesDef {
latin: "Cocos nucifera",
common: "coconut palm",
category: "tree",
products: &["coconut", "copra", "coco-fiber"],
blurb: "The tree of a thousand uses β water, flesh, oil, fiber, timber.",
price: 3.0,
unit: "seedling",
},
SpeciesDef {
latin: "Mangifera indica",
common: "mango",
category: "tree",
products: &["mango"],
blurb: "Canopy fruit β shade above, sugar below.",
price: 4.0,
unit: "seedling",
},
SpeciesDef {
latin: "Carica papaya",
common: "papaya",
category: "tree",
products: &["papaya"],
blurb: "Fast fruiter β months from seed to harvest.",
price: 1.0,
unit: "seedling",
},
SpeciesDef {
latin: "Bambusa vulgaris",
common: "bamboo",
category: "tree",
products: &["bamboo-pole", "bamboo-shoot"],
blurb: "The building material that grows itself β a meter a day.",
price: 1.5,
unit: "culm",
},
SpeciesDef {
latin: "Oryza sativa",
common: "rice",
category: "crop",
products: &["rice"],
blurb: "The terrace grain β water, mud, sun.",
price: 2.0,
unit: "kg seed",
},
SpeciesDef {
latin: "Ananas comosus",
common: "pineapple",
category: "crop",
products: &["pineapple"],
blurb: "Ground bromeliad β sweet armor.",
price: 0.5,
unit: "crown",
},
SpeciesDef {
latin: "Zingiber officinale",
common: "ginger",
category: "herb",
products: &["ginger"],
blurb: "Rhizome heat β kitchen and medicine both.",
price: 1.0,
unit: "rhizome",
},
SpeciesDef {
latin: "Curcuma longa",
common: "turmeric",
category: "herb",
products: &["turmeric"],
blurb: "Golden root β jamu's backbone.",
price: 1.0,
unit: "rhizome",
},
SpeciesDef {
latin: "Vanilla planifolia",
common: "vanilla",
category: "herb",
products: &["vanilla-pod"],
blurb: "The orchid you hand-pollinate β patience priced by the gram.",
price: 8.0,
unit: "cutting",
},
SpeciesDef {
latin: "Ovis aries",
common: "sheep",
category: "animal",
products: &["wool", "sheep-milk", "mutton"],
blurb: "The flock β wool, milk, meat, and mowed grass.",
price: 90.0,
unit: "head",
},
SpeciesDef {
latin: "Capra hircus",
common: "goat",
category: "animal",
products: &["goat-milk", "goat-meat"],
blurb: "The browser β thrives where lawns fail.",
price: 70.0,
unit: "head",
},
SpeciesDef {
latin: "Gallus gallus domesticus",
common: "chicken",
category: "bird",
products: &["egg", "chicken-meat"],
blurb: "The daily layer β eggs in, scraps out.",
price: 8.0,
unit: "head",
},
SpeciesDef {
latin: "Anas platyrhynchos domesticus",
common: "duck",
category: "bird",
products: &["duck-egg", "duck-meat"],
blurb: "The paddy patrol β eats the pests rice can't.",
price: 10.0,
unit: "head",
},
SpeciesDef {
latin: "Apis cerana",
common: "eastern honey bee",
category: "insect",
products: &["honey", "beeswax"],
blurb: "The pollination engine β every orchard's silent partner.",
price: 60.0,
unit: "colony",
},
SpeciesDef {
latin: "Pleurotus ostreatus",
common: "oyster mushroom",
category: "fungus",
products: &["mushroom"],
blurb: "Grows on what everything else throws away.",
price: 2.0,
unit: "kg spawn",
},
];
pub const CATEGORIES: &[&str] = &["tree", "crop", "herb", "animal", "bird", "insect", "fungus"];
fn category_color(cat: &str) -> &'static str {
match cat {
"tree" => "var(--cyber-green)",
"crop" => "var(--cyber-yellow)",
"herb" => "var(--cyber-cyan)",
"animal" => "var(--cyber-orange)",
"bird" => "var(--cyber-magenta, #d36ee0)",
"insect" => "var(--cyber-red)",
_ => "#9a86e0",
}
}
fn seeded(latin: &str) -> bool {
find_word(&word_particle("species", latin)).is_some()
}
fn buy_species(def: &SpeciesDef) -> Result<String, String> {
use crate::wallet::{debit_cx, load_balance, load_profile, push_intent, stock_add};
if load_balance().cx + 1e-9 < def.price {
return Err(format!(
"{:.1} CX needed β you hold {:.1}",
def.price,
load_balance().cx
));
}
if !seeded(def.latin) {
seed_species(def)?;
}
let me = neuron().bech32;
debit_cx(def.price, "genetics", &format!("1 {} {}", def.unit, def.common));
stock_add(def.common, 1.0);
let handle = load_profile().handle;
let you = mint_word("person", &handle, "YOU", &me, false);
let sp = word_particle("species", def.latin);
let rel = mint_word("relation", "buys", "market acquisition", "", true);
emit_signal(
vec![Link {
from: you,
rel,
to: sp,
weight: 1.0,
note: format!("-{:.1} CX Β· 1 {}", def.price, def.unit),
}],
&format!("buy 1 {} {}", def.unit, def.common),
)?;
push_intent(&handle, "gen_buy", &format!("{} 1 {}", def.common, def.unit));
Ok(format!(
"bought 1 {} {} Β· -{:.1} CX",
def.unit, def.common, def.price
))
}
fn seed_species(def: &SpeciesDef) -> Result<String, String> {
let me = neuron().bech32;
let sp = mint_word("species", def.latin, def.common, &me, false);
let produces = mint_word(
"relation",
"produces",
"genetic yield β species produces good",
"",
true,
);
let links: Vec<Link> = def
.products
.iter()
.map(|p| Link {
from: sp.clone(),
rel: produces.clone(),
to: mint_word("coin", p, "", &me, false),
weight: 1.0,
note: def.common.into(),
})
.collect();
emit_signal(links, &format!("genome seed Β· {}", def.latin))?;
Ok(sp)
}
#[component]
pub fn GeneticsPage() -> impl IntoView {
let cat_filter = RwSignal::new(String::new());
let tick = RwSignal::new(0u32);
let msg = RwSignal::new(None::<(bool, String)>);
Effect::new(move |_| {
document().set_title("Cyberia β genetics");
crate::erp::ensure_erp_boot();
crate::signal::ensure_graph_boot();
});
view! {
<div class="page-shell cities-shell">
<div class="site-chrome cyberia-chrome">
<div class="chrome-inner">
<div class="header-row1">
<div class="logo-zone">
<h1 class="logo">
<a href="/cities" class="brand-flag" title="home" inner_html=FLAG_SVG></a>
<span style="color: var(--cyber-green);">"cyber"</span>
<span style="color: var(--cyber-green); margin: 0 1px;">"β’"</span>
<span style="color: #fff;">"ia"</span>
</h1>
</div>
<div class="cyberia-phase-pill">
<span class="phase-dot"></span>
{format!("GENOME Β· {} SPECIES", SPECIES.len())}
</div>
<CyberiaNav active="genetics" />
</div>
</div>
</div>
<div class="cities-stage">
<div class="cities-hero">
<div>
<div class="cities-kicker">"THE LIVING LAYER"</div>
<h2 class="cities-title">"Genetics"</h2>
<p class="cities-lead">
"Species are their own fundamental entity β not elements, not products, but the genomes that produce them. Seed one into the graph and it becomes a word: plots grow it, it produces coins, signals carry the assertions."
</p>
</div>
</div>
{move || msg.get().map(|(ok, t)| view! {
<div class=if ok { "eco-msg ok" } else { "eco-msg err" }>{t}</div>
})}
<div class="list-filters" style="margin-bottom:14px;">
<button class=move || if cat_filter.get().is_empty() { "chip chip-on" } else { "chip" }
on:click=move |_| cat_filter.set(String::new())>"ALL"</button>
{CATEGORIES.iter().map(|c| {
let c2 = c.to_string();
let c3 = c.to_string();
view! {
<button class=move || if cat_filter.get() == c3 { "chip chip-on" } else { "chip" }
on:click=move |_| cat_filter.set(c2.clone())>{c.to_uppercase()}</button>
}
}).collect_view()}
</div>
<div class="studio-list">
{move || {
let _ = tick.get();
let f = cat_filter.get();
let list: Vec<&SpeciesDef> = SPECIES
.iter()
.filter(|s| f.is_empty() || s.category == f)
.collect();
view! {
{list.into_iter().map(|def| {
let particle = word_particle("species", def.latin);
let in_graph = seeded(def.latin);
let n_links = if in_graph { links_touching(&particle).len() } else { 0 };
let word_href = format!("/world/word/{particle}");
let grow_href = format!("/world/links/new?to={particle}");
let latin = def.latin;
let held = crate::wallet::stock_qty(def.common);
let seed = move |_| {
match seed_species(def) {
Ok(_) => msg.set(Some((true, format!("{latin} seeded β genome in the graph, produces links committed")))),
Err(e) => msg.set(Some((false, e))),
}
tick.update(|n| *n += 1);
};
let buy = move |_| {
match buy_species(def) {
Ok(t) => msg.set(Some((true, t))),
Err(e) => msg.set(Some((false, e))),
}
tick.update(|n| *n += 1);
};
view! {
<div class="studio-row">
<div class="studio-row-main">
<span class="studio-kind" style=format!("color:{};border-color:{};", category_color(def.category), category_color(def.category))>
{def.category.to_uppercase()}
</span>
<div>
<div class="studio-title">
<span style="font-style: italic;">{def.latin}</span>
<span style="color:#667; margin-left:8px; font-style:normal;">{def.common}</span>
</div>
<div class="studio-meta">{def.blurb}</div>
<div class="list-filters" style="margin-top:6px;">
<span style="color:#556; font-size:10px; letter-spacing:1px;">"PRODUCES"</span>
{def.products.iter().map(|p| view! {
<span class="chip" style="pointer-events:none;">{*p}</span>
}).collect_view()}
</div>
</div>
</div>
<div class="studio-row-acts">
{(held > 0.0).then(|| view! {
<span class="sys-tag">{format!("{held:.0} {}", def.unit)}</span>
})}
<button class="chip chip-on" on:click=buy>
{format!("BUY Β· {:.1} CX/{}", def.price, def.unit)}
</button>
{if in_graph {
view! {
<span class="sys-tag">{format!("IN GRAPH Β· {n_links}")}</span>
<a class="chip" href=word_href>"WORD β"</a>
<a class="chip" href=grow_href>"GROW ON PLOT"</a>
}.into_any()
} else {
view! {
<button class="chip" on:click=seed>"SEED β GRAPH"</button>
}.into_any()
}}
</div>
</div>
}
}).collect_view()}
}
}}
</div>
<p class="bank-footnote">
"Seeding commits one signed signal per species: species βproducesβ its coins. Then link plots to genomes: plot βgrowsβ species. The lexicon ranks what the valley actually lives on."
</p>
</div>
</div>
}
}