Skip to content

Commit

Permalink
[delta_q] add full text export/import
Browse files Browse the repository at this point in the history
  • Loading branch information
rkuhn committed Oct 9, 2024
1 parent 85e8417 commit 452a350
Show file tree
Hide file tree
Showing 6 changed files with 131 additions and 21 deletions.
26 changes: 25 additions & 1 deletion delta_q/models.txt
Original file line number Diff line number Diff line change
Expand Up @@ -37,4 +37,28 @@ validateEB:
CDF[(1, 1)]

validateIB:
CDF[(3, 1)]
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))
82 changes: 73 additions & 9 deletions delta_q/src/bin/editor-web.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -22,12 +23,57 @@ fn app_main() -> HtmlResult {
ctx_handle.set((*ctx).clone());
}

let selected = use_state::<Option<String>, _>(|| 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::<HtmlInputElement>().value();
match text.parse::<EvaluationContext>() {
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::<HtmlTextAreaElement>() else {
return;
};
textarea.focus().expect("focus failed");
textarea.set_value(&*ctx_text);
let escape = Closure::<dyn Fn(KeyboardEvent)>::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::<Option<String>, _>(|| 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::<CalcCdf>();
use_future_with(
Expand Down Expand Up @@ -59,7 +105,11 @@ fn app_main() -> HtmlResult {

let on_change = cloned!(ctx, epoch;
Callback::from(move |(name, dq): (String, Option<DeltaQ>)| {
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);
})
);
Expand Down Expand Up @@ -101,7 +151,7 @@ fn app_main() -> HtmlResult {

Ok(html! {
<div>
<p>{ "context:" }</p>
<p>{ "context:" }<button onclick={ctx_popup_show}>{ "edit" }</button></p>
<ul>
{ list_items }
</ul>
Expand All @@ -115,6 +165,16 @@ fn app_main() -> HtmlResult {
</div>
}
<p>{ "agent status: " }{ &*agent_status }</p>
if *ctx_popup {
<div class={classes!("ctx_popup")}>
<p>
<button onclick={cloned!(ctx_popup_close; move |_| ctx_popup_close.emit(true))} disabled={&*ctx_text_status != "OK"} >{ "save" }</button>
<button onclick={cloned!(ctx_popup_close; move |_| ctx_popup_close.emit(false))} >{ "cancel" }</button>
</p>
<textarea oninput={ctx_text_input} rows={(ctx_text.lines().count() + 1).to_string()} cols="80" ref={ctx_text_ref} />
<pre>{ &*ctx_text_status }</pre>
</div>
}
</div>
})
}
Expand Down Expand Up @@ -157,6 +217,7 @@ struct EditExpressionProps {
#[function_component(EditExpression)]
fn edit_expression(props: &EditExpressionProps) -> HtmlResult {
let name = props.name.clone();
let orig = props.value.clone();
let on_change = props.on_change.clone();

let editing = use_state(|| false);
Expand Down Expand Up @@ -196,14 +257,17 @@ fn edit_expression(props: &EditExpressionProps) -> HtmlResult {
let field = use_node_ref();
use_effect_with(
editing.clone(),
cloned!(field; move |editing| {
cloned!(field, buffer; move |editing| {
if **editing {
let Some(field) = field.cast::<HtmlInputElement>() else {
return;
};
field.focus().expect("focus failed");
let escape = Closure::<dyn Fn()>::new(cloned!(editing; move || editing.set(false))).into_js_value();
let escape = Closure::<dyn Fn(KeyboardEvent)>::new(cloned!(editing; move |e: KeyboardEvent| if e.key() == "Escape" {
editing.set(false)
})).into_js_value();
field.add_event_listener_with_callback("keydown", escape.unchecked_ref()).expect("listening on keydown failed");
buffer.set(orig.to_string());
}
}),
);
Expand Down
10 changes: 9 additions & 1 deletion delta_q/src/delta_q.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::{cdf::DEFAULT_MAX_SIZE, CDFError, CompactionMode, CDF};
use crate::{cdf::DEFAULT_MAX_SIZE, parser::eval_ctx, CDFError, CompactionMode, CDF};
use smallstr::SmallString;
use std::{
collections::{BTreeMap, BTreeSet},
Expand Down Expand Up @@ -46,6 +46,14 @@ pub struct EvaluationContext {
mode: CompactionMode,
}

impl FromStr for EvaluationContext {
type Err = String;

fn from_str(s: &str) -> Result<Self, Self::Err> {
eval_ctx(s)
}
}

impl Default for EvaluationContext {
fn default() -> Self {
Self {
Expand Down
2 changes: 1 addition & 1 deletion delta_q/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,4 @@ mod render;
pub use agent::CalcCdf;
pub use cdf::{CDFError, CompactionMode, CDF};
pub use delta_q::{DeltaQ, EvaluationContext};
pub use render::{DeltaQComponent, DeltaQContext};
pub use render::{DeltaQComponent, DeltaQContext, EvalCtxAction};
30 changes: 21 additions & 9 deletions delta_q/src/render.rs
Original file line number Diff line number Diff line change
Expand Up @@ -453,16 +453,28 @@ fn branch(props: &BranchProps) -> Html {
}
}

pub enum EvalCtxAction {
Put(String, DeltaQ),
Remove(String),
Set(EvaluationContext),
}

impl Reducible for EvaluationContext {
type Action = (String, Option<DeltaQ>);

fn reduce(self: Rc<Self>, (name, dq): Self::Action) -> Rc<Self> {
let mut ctx = (*self).clone();
if let Some(dq) = dq {
ctx.put(name, dq);
} else {
ctx.remove(&name);
type Action = EvalCtxAction;

fn reduce(self: Rc<Self>, act: Self::Action) -> Rc<Self> {
match act {
EvalCtxAction::Put(name, delta_q) => {
let mut ret = (*self).clone();
ret.put(name, delta_q);
Rc::new(ret)
}
EvalCtxAction::Remove(name) => {
let mut ret = (*self).clone();
ret.remove(&name);
Rc::new(ret)
}
EvalCtxAction::Set(evaluation_context) => Rc::new(evaluation_context),
}
Rc::new(ctx)
}
}
2 changes: 2 additions & 0 deletions delta_q/styles.css
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@
.dq_edit input[type="text"] { width: 100%; }
.dq_show { margin-left: 16px; }
.result { max-height: 5em; overflow-y: scroll; }
.ctx_popup { z-index: 1; position: absolute; left: 20px; top: 20px; right: 20px; bottom: 20px; border: 1px solid black; background-color: lightgrey; }
.ctx_popup textarea { width: 100%; white-space: nowrap; }

.column { display: flex; flex-direction: column; }
.row { display: flex; flex-direction: row; }
Expand Down

0 comments on commit 452a350

Please sign in to comment.