feat: transformation buttons
This commit is contained in:
@@ -23,21 +23,37 @@ impl Pattern {
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn apply_transformation(&self, transformation: Transformation) -> Self {
|
||||
let mut holds = self.clone();
|
||||
if transformation.shift_right > 0 {
|
||||
holds = holds.shift_right(transformation.shift_right);
|
||||
pub fn shift_left(&self, shift: u64) -> Option<Self> {
|
||||
// Out of bounds check
|
||||
if let Some(min_col) = self.pattern.iter().map(|(hold_position, _)| hold_position.col).min() {
|
||||
if shift > min_col {
|
||||
return None;
|
||||
}
|
||||
}
|
||||
if transformation.mirror {
|
||||
holds = holds.mirror();
|
||||
}
|
||||
holds
|
||||
|
||||
let pattern: BTreeMap<HoldPosition, HoldRole> = self
|
||||
.pattern
|
||||
.iter()
|
||||
.map(|(hold_position, hold_role)| {
|
||||
let mut hold_position = hold_position.clone();
|
||||
hold_position.col -= shift;
|
||||
(hold_position, *hold_role)
|
||||
})
|
||||
.collect();
|
||||
|
||||
Some(Self { pattern })
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn shift_right(&self, shift: u64) -> Self {
|
||||
let mut pattern = self.clone();
|
||||
pattern.pattern = pattern
|
||||
pub fn shift_right(&self, wall_dimensions: WallDimensions, shift: u64) -> Option<Self> {
|
||||
// Out of bounds check
|
||||
if let Some(max_col) = self.pattern.iter().map(|(hold_position, _)| hold_position.col).max() {
|
||||
if max_col + shift >= wall_dimensions.cols {
|
||||
return None;
|
||||
}
|
||||
}
|
||||
|
||||
let pattern: BTreeMap<HoldPosition, HoldRole> = self
|
||||
.pattern
|
||||
.iter()
|
||||
.map(|(hold_position, hold_role)| {
|
||||
@@ -46,7 +62,8 @@ impl Pattern {
|
||||
(hold_position, *hold_role)
|
||||
})
|
||||
.collect();
|
||||
pattern
|
||||
|
||||
Some(Self { pattern })
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
|
||||
@@ -187,7 +187,6 @@ fn View() -> impl IntoView {
|
||||
<Separator />
|
||||
|
||||
<div class="flex flex-row justify-around">
|
||||
<Transformations />
|
||||
<NextProblemButton />
|
||||
</div>
|
||||
</Section>
|
||||
@@ -196,7 +195,8 @@ fn View() -> impl IntoView {
|
||||
|
||||
<Section title="Current problem">
|
||||
{move || ctx.problem.get().map(|problem| view! { <ProblemInfo problem /> })}
|
||||
<Separator /> <AttemptRadioGroup /> <Separator /> <History />
|
||||
<Separator /> <Transformations /> <Separator /><AttemptRadioGroup />
|
||||
<Separator /> <History />
|
||||
</Section>
|
||||
</div>
|
||||
|
||||
@@ -214,25 +214,49 @@ fn Transformations() -> impl IntoView {
|
||||
|
||||
let ctx = use_context::<Context>().unwrap();
|
||||
|
||||
let on_left = Callback::new(move |()| {
|
||||
tracing::debug!("left");
|
||||
let left = Signal::derive(move || {
|
||||
let mut problem = ctx.problem.get()?;
|
||||
let new_pattern = problem.pattern.shift_left(1)?;
|
||||
problem.pattern = new_pattern;
|
||||
Some(problem)
|
||||
});
|
||||
let on_mirror = Callback::new(move |()| {
|
||||
|
||||
let right = Signal::derive(move || {
|
||||
let mut problem = ctx.problem.get()?;
|
||||
let wall_dimensions = ctx.wall.read().wall_dimensions;
|
||||
let new_pattern = problem.pattern.shift_right(wall_dimensions, 1)?;
|
||||
problem.pattern = new_pattern;
|
||||
Some(problem)
|
||||
});
|
||||
|
||||
let on_click_left = Callback::new(move |()| {
|
||||
tracing::debug!("left");
|
||||
if let Some(problem) = left.get() {
|
||||
ctx.cb_set_problem.run(problem);
|
||||
}
|
||||
});
|
||||
let on_click_mirror = Callback::new(move |()| {
|
||||
tracing::debug!("mirror");
|
||||
if let Some(mut problem) = ctx.problem.get() {
|
||||
problem.pattern = problem.pattern.mirror();
|
||||
ctx.cb_set_problem.run(problem);
|
||||
}
|
||||
});
|
||||
let on_right = Callback::new(move |()| {
|
||||
let on_click_right = Callback::new(move |()| {
|
||||
tracing::debug!("right");
|
||||
if let Some(problem) = right.get() {
|
||||
ctx.cb_set_problem.run(problem);
|
||||
}
|
||||
});
|
||||
|
||||
let left_disabled = Signal::derive(move || left.read().is_none());
|
||||
let right_disabled = Signal::derive(move || right.read().is_none());
|
||||
|
||||
view! {
|
||||
<div class="flex flex-row gap-2 justify-center">
|
||||
<Button icon=Icon::ChevronLeft disabled=true on_click=on_left />
|
||||
<Button icon=Icon::CodeBracketSquare on_click=on_mirror />
|
||||
<Button icon=Icon::ChevronRight on_click=on_right />
|
||||
<Button icon=Icon::ChevronLeft disabled=left_disabled on_click=on_click_left />
|
||||
<Button icon=Icon::CodeBracketSquare on_click=on_click_mirror />
|
||||
<Button icon=Icon::ChevronRight disabled=right_disabled on_click=on_click_right />
|
||||
</div>
|
||||
}
|
||||
}
|
||||
@@ -261,7 +285,7 @@ fn NextProblemButton() -> impl IntoView {
|
||||
let ctx = use_context::<Context>().unwrap();
|
||||
|
||||
let on_click = Callback::new(move |_| ctx.cb_next_problem.run(()));
|
||||
view! { <Button icon=Icon::ArrowPath text="Next problem" on_click color=Gradient::PurpleBlue /> }
|
||||
view! { <Button icon=Icon::ArrowPath text="Randomize" on_click color=Gradient::PurpleBlue /> }
|
||||
}
|
||||
|
||||
#[component]
|
||||
|
||||
Reference in New Issue
Block a user