diff --git a/delta_q/models.txt b/delta_q/models.txt index 8ff6caf..6415527 100644 --- a/delta_q/models.txt +++ b/delta_q/models.txt @@ -37,4 +37,28 @@ validateEB: CDF[(1, 1)] validateIB: -CDF[(3, 1)] \ No newline at end of file +CDF[(3, 1)] + +4 -- better modelling of Leios (in format for import into editor) + +-- diffusion of one IB (assuming 1MB) +diffuseIB := hopIB 0.6<>99.4 ((hopIB ->- hopIB) 8.58<>90.82 (((hopIB ->- hopIB) ->- hopIB) 65.86<>24.96 (((hopIB ->- hopIB) ->- hopIB) ->- hopIB))) +-- diffusion of one EB (assuming 64kB) +diffuseEB := hopEB 0.6<>99.4 ((hopEB ->- hopEB) 8.58<>90.82 (((hopEB ->- hopEB) ->- hopEB) 65.86<>24.96 (((hopEB ->- hopEB) ->- hopEB) ->- hopEB))) + +-- single link latencies across continents +far := CDF[(0.268, 1)] +farL := CDF[(0.531, 1)] +farXL := CDF[(1.598, 1)] +-- single link latencies between data centers within a continent +mid := CDF[(0.069, 1)] +midL := CDF[(0.143, 1)] +midXL := CDF[(0.404, 1)] +-- single link latencies within a data center +near := CDF[(0.012, 1)] +nearL := CDF[(0.024, 1)] +nearXL := CDF[(0.078, 1)] + +-- a hop (for an IB or EB) is a choice of near/mid/far with req-res-req-resLarge in each arm +hopIB := (((near ->- near) ->- near) ->- nearXL) 1<>2 ((((mid ->- mid) ->- mid) ->- midXL) 1<>1 (((far ->- far) ->- far) ->- farXL)) +hopEB := (((near ->- near) ->- near) ->- nearL) 1<>2 ((((mid ->- mid) ->- mid) ->- midL) 1<>1 (((far ->- far) ->- far) ->- farL)) diff --git a/delta_q/src/bin/editor-web.rs b/delta_q/src/bin/editor-web.rs index 2c37601..d0716fc 100644 --- a/delta_q/src/bin/editor-web.rs +++ b/delta_q/src/bin/editor-web.rs @@ -5,11 +5,12 @@ macro_rules! cloned { }}; } -use delta_q::{CalcCdf, DeltaQ, DeltaQComponent, DeltaQContext, EvaluationContext}; +use delta_q::{CalcCdf, DeltaQ, DeltaQComponent, DeltaQContext, EvalCtxAction, EvaluationContext}; use gloo_utils::window; use js_sys::Reflect; +use std::str::FromStr; use wasm_bindgen::{prelude::Closure, JsCast, JsValue}; -use web_sys::{HtmlInputElement, MessageEvent, MessageEventInit}; +use web_sys::{HtmlInputElement, HtmlTextAreaElement, MessageEvent, MessageEventInit}; use yew::{prelude::*, suspense::use_future_with}; use yew_agent::{oneshot::OneshotProvider, prelude::use_oneshot_runner}; use yew_hooks::use_local_storage; @@ -22,12 +23,57 @@ fn app_main() -> HtmlResult { ctx_handle.set((*ctx).clone()); } - let selected = use_state::, _>(|| None); - let select = cloned!(selected; Callback::from(move |n| selected.set(Some(n)))); - // epoch counter to trigger recomputation when the context changes let epoch = use_state(|| 0); + let ctx_popup = use_state(|| false); + let ctx_text = use_state(|| String::new()); + let ctx_text_status = use_state(|| "OK".to_owned()); + let ctx_text_ref = use_node_ref(); + + let ctx_text_input = Callback::from(cloned!(ctx_text, ctx_text_status; move |e: InputEvent| { + let text = e.target_unchecked_into::().value(); + match text.parse::() { + Ok(_) => ctx_text_status.set("OK".to_owned()), + Err(e) => ctx_text_status.set(e), + } + ctx_text.set(text); + })); + let ctx_popup_show = Callback::from(cloned!(ctx_popup, ctx_text, ctx; move |_: MouseEvent| { + ctx_popup.set(true); + ctx_text.set(ctx.to_string()); + })); + use_effect_with( + ctx_popup.clone(), + cloned!(ctx_text_ref, ctx_text, ctx_popup; move |popup| { + if **popup { + let Some(textarea) = ctx_text_ref.cast::() else { + return; + }; + textarea.focus().expect("focus failed"); + textarea.set_value(&*ctx_text); + let escape = Closure::::new(move |e: KeyboardEvent| if e.key() == "Escape" { + ctx_popup.set(false) + }).into_js_value(); + textarea.add_event_listener_with_callback("keydown", escape.unchecked_ref()).expect("listening on keydown failed"); + } + }), + ); + let ctx_popup_close = + Callback::from(cloned!(ctx_popup, ctx_text, epoch, ctx; move |save: bool| { + ctx_popup.set(false); + if !save { + return; + } + if let Ok(cx) = EvaluationContext::from_str(&*ctx_text) { + ctx.dispatch(EvalCtxAction::Set(cx)); + epoch.set(*epoch + 1); + } + })); + + let selected = use_state::, _>(|| None); + let select = cloned!(selected; Callback::from(move |n| selected.set(Some(n)))); + let agent_status = use_state(|| "".to_owned()); let agent = use_oneshot_runner::(); use_future_with( @@ -59,7 +105,11 @@ fn app_main() -> HtmlResult { let on_change = cloned!(ctx, epoch; Callback::from(move |(name, dq): (String, Option)| { - ctx.dispatch((name.clone(), dq.clone())); + if let Some(dq) = dq { + ctx.dispatch(EvalCtxAction::Put(name.clone(), dq)); + } else { + ctx.dispatch(EvalCtxAction::Remove(name)); + } epoch.set(*epoch + 1); }) ); @@ -101,7 +151,7 @@ fn app_main() -> HtmlResult { Ok(html! {
-

{ "context:" }

+

{ "context:" }

    { list_items }
@@ -115,6 +165,16 @@ fn app_main() -> HtmlResult {
}

{ "agent status: " }{ &*agent_status }

+ if *ctx_popup { +
+

+ + +

+