From 17f78b86f4e1370138add90b32037ce46d72c1c5 Mon Sep 17 00:00:00 2001 From: Leo dev Date: Sat, 31 Jan 2026 13:02:22 +0100 Subject: [PATCH 1/7] Implemented access cell for component and view --- Cargo.toml | 1 + src/component/context.rs | 58 ++++++++++++++++++++++++---------------- 2 files changed, 36 insertions(+), 23 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 6aec650..277c50a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -23,6 +23,7 @@ path = "src/main.rs" cc = "1.0" [dependencies] +access-cell = "0.1.3" crossterm = "0.28.1" figlet-rs = "0.1.5" osui-macros = { path = "macros" } diff --git a/src/component/context.rs b/src/component/context.rs index 0a1a75d..17c7a17 100644 --- a/src/component/context.rs +++ b/src/component/context.rs @@ -4,6 +4,8 @@ use std::{ sync::{Arc, Mutex}, }; +use access_cell::AccessCell; + use crate::{ component::EventHandler, engine::{Command, CommandExecutor}, @@ -15,9 +17,9 @@ use crate::{ use super::{scope::Scope, Component, ComponentImpl}; pub struct Context { - component: Mutex, + component: AccessCell, + view: AccessCell, event_handlers: Mutex>>, - view: Mutex, pub(crate) scopes: Mutex>>, executor: Arc, } @@ -28,45 +30,55 @@ impl Context { executor: Arc, ) -> Arc { Arc::new(Self { - component: Mutex::new(Arc::new(component)), + component: AccessCell::new(Arc::new(component)), + view: AccessCell::new(Arc::new(|_| {})), event_handlers: Mutex::new(HashMap::new()), - view: Mutex::new(Arc::new(|_| {})), scopes: Mutex::new(Vec::new()), executor, }) } pub fn refresh(self: &Arc) { - let s = self.clone(); - - std::thread::spawn({ - move || { - s.event_handlers.lock().unwrap().clear(); - let c = s.component.lock().unwrap().clone(); - *s.view.lock().unwrap() = c.call(&s); + self.event_handlers.lock().unwrap().clear(); + self.component.access({ + let s = self.clone(); + move |component| { + let component = component.clone(); + s.view.access({ + let s = s.clone(); + move |view| *view = component.call(&s) + }) } }); } - pub fn refresh_atomic(self: &Arc) -> Arc> { - let s = self.clone(); - let done = Arc::new(Mutex::new(false)); + pub fn refresh_sync(self: &Arc) { + self.event_handlers.lock().unwrap().clear(); - std::thread::spawn({ - let done = done.clone(); - move || { - s.event_handlers.lock().unwrap().clear(); - let c = s.component.lock().unwrap().clone(); - *s.view.lock().unwrap() = c.call(&s); - *done.lock().unwrap() = true; + let (tx, rx) = std::sync::mpsc::channel::<()>(); + + self.component.access({ + let s = self.clone(); + move |component| { + let component = component.clone(); + + s.view.access({ + let s = s.clone(); + let tx = tx.clone(); + move |view| { + *view = component.call(&s); + let _ = tx.send(()); // signal completion + } + }); } }); - done + // BLOCK until view closure finishes + let _ = rx.recv(); } pub fn get_view(self: &Arc) -> View { - self.view.lock().unwrap().clone() + self.view.access_ref().clone() } pub fn on_event, &T) + Send + Sync + 'static>( From ec320e47fd50cd83c546bd187252c103aac5392f Mon Sep 17 00:00:00 2001 From: Leo dev Date: Sat, 31 Jan 2026 14:19:37 +0100 Subject: [PATCH 2/7] Access cell in event handlers --- src/component/context.rs | 77 +++++++++++++++++++++++----------------- src/state.rs | 5 +-- 2 files changed, 48 insertions(+), 34 deletions(-) diff --git a/src/component/context.rs b/src/component/context.rs index 17c7a17..b8751f5 100644 --- a/src/component/context.rs +++ b/src/component/context.rs @@ -19,7 +19,7 @@ use super::{scope::Scope, Component, ComponentImpl}; pub struct Context { component: AccessCell, view: AccessCell, - event_handlers: Mutex>>, + event_handlers: AccessCell>>, pub(crate) scopes: Mutex>>, executor: Arc, } @@ -32,14 +32,15 @@ impl Context { Arc::new(Self { component: AccessCell::new(Arc::new(component)), view: AccessCell::new(Arc::new(|_| {})), - event_handlers: Mutex::new(HashMap::new()), + event_handlers: AccessCell::new(HashMap::new()), scopes: Mutex::new(Vec::new()), executor, }) } pub fn refresh(self: &Arc) { - self.event_handlers.lock().unwrap().clear(); + self.event_handlers + .access(|event_handlers| event_handlers.clear()); self.component.access({ let s = self.clone(); move |component| { @@ -53,10 +54,11 @@ impl Context { } pub fn refresh_sync(self: &Arc) { - self.event_handlers.lock().unwrap().clear(); - let (tx, rx) = std::sync::mpsc::channel::<()>(); + self.event_handlers + .access(|event_handlers| event_handlers.clear()); + self.component.access({ let s = self.clone(); move |component| { @@ -85,30 +87,37 @@ impl Context { self: &Arc, handler: F, ) { - self.event_handlers - .lock() - .unwrap() - .entry(TypeId::of::()) - .or_insert_with(|| Vec::new()) - .push(Arc::new(Mutex::new( - move |ctx: &Arc, event: &dyn Any| { - if let Some(e) = event.downcast_ref::() { - (handler)(ctx, e); - } - }, - ))); + let new_handler: EventHandler = Arc::new(Mutex::new( + move |ctx: &Arc, event: &dyn Any| { + if let Some(e) = event.downcast_ref::() { + (handler)(ctx, e); + } + }, + )); + self.event_handlers.access(|event_handlers| { + event_handlers + .entry(TypeId::of::()) + .or_insert_with(Vec::new) + .push(new_handler); + }); } - pub fn emit_event(self: &Arc, event: &E) { - if let Some(v) = self.event_handlers.lock().unwrap().get(&TypeId::of::()) { - for i in v { - (i.lock().unwrap())(self, event); - } + pub fn emit_event(self: &Arc, event: E) { + let event = Arc::new(event); + let handlers_to_call: Vec = { + let guard = self.event_handlers.access_ref(); + guard + .get(&TypeId::of::()) + .cloned() + .unwrap_or_default() + }; + for h in &handlers_to_call { + (h.lock().unwrap())(self, event.as_ref()); } for scope in self.scopes.lock().unwrap().iter() { for (child, _) in scope.children.lock().unwrap().iter() { - child.emit_event(event); + child.emit_event(event.clone()); } } } @@ -117,15 +126,19 @@ impl Context { self: &Arc, event: &E, ) { - if let Some(v) = self.event_handlers.lock().unwrap().get(&TypeId::of::()) { - for i in v { - let i = i.clone(); - let event = event.clone(); - let s = self.clone(); - std::thread::spawn(move || { - (i.lock().unwrap())(&s, &event); - }); - } + let handlers_to_call: Vec = { + let guard = self.event_handlers.access_ref(); + guard + .get(&TypeId::of::()) + .cloned() + .unwrap_or_default() + }; + for h in handlers_to_call { + let event = event.clone(); + let s = self.clone(); + std::thread::spawn(move || { + (h.lock().unwrap())(&s, &event); + }); } for scope in self.scopes.lock().unwrap().iter() { diff --git a/src/state.rs b/src/state.rs index fae81c6..15f7631 100644 --- a/src/state.rs +++ b/src/state.rs @@ -192,7 +192,7 @@ pub fn use_sync_state< pub fn use_sync_effect< T: Send + Sync + 'static, - Ev: 'static, + Ev: Send + Sync + 'static, E: Fn(&State) -> Ev + Send + Sync + 'static, >( cx: &Arc, @@ -205,7 +205,8 @@ pub fn use_sync_effect< let state = state.clone(); let cx = cx.clone(); move || { - cx.emit_event(&encoder(&state)); + let ev = encoder(&state); + cx.emit_event(ev); } }, deps, From 8685cdde2af7ff794713ed40206be0a827cc5780 Mon Sep 17 00:00:00 2001 From: Leo dev Date: Sat, 31 Jan 2026 14:32:49 +0100 Subject: [PATCH 3/7] Scopes with AccessCell --- src/component/context.rs | 86 +++++++++++++++++++++++++--------------- src/frontend.rs | 2 +- 2 files changed, 54 insertions(+), 34 deletions(-) diff --git a/src/component/context.rs b/src/component/context.rs index b8751f5..41f0f77 100644 --- a/src/component/context.rs +++ b/src/component/context.rs @@ -20,7 +20,7 @@ pub struct Context { component: AccessCell, view: AccessCell, event_handlers: AccessCell>>, - pub(crate) scopes: Mutex>>, + scopes: AccessCell>>, executor: Arc, } @@ -33,7 +33,7 @@ impl Context { component: AccessCell::new(Arc::new(component)), view: AccessCell::new(Arc::new(|_| {})), event_handlers: AccessCell::new(HashMap::new()), - scopes: Mutex::new(Vec::new()), + scopes: AccessCell::new(Vec::new()), executor, }) } @@ -87,13 +87,12 @@ impl Context { self: &Arc, handler: F, ) { - let new_handler: EventHandler = Arc::new(Mutex::new( - move |ctx: &Arc, event: &dyn Any| { + let new_handler: EventHandler = + Arc::new(Mutex::new(move |ctx: &Arc, event: &dyn Any| { if let Some(e) = event.downcast_ref::() { (handler)(ctx, e); } - }, - )); + })); self.event_handlers.access(|event_handlers| { event_handlers .entry(TypeId::of::()) @@ -106,20 +105,19 @@ impl Context { let event = Arc::new(event); let handlers_to_call: Vec = { let guard = self.event_handlers.access_ref(); - guard - .get(&TypeId::of::()) - .cloned() - .unwrap_or_default() + guard.get(&TypeId::of::()).cloned().unwrap_or_default() }; for h in &handlers_to_call { (h.lock().unwrap())(self, event.as_ref()); } - for scope in self.scopes.lock().unwrap().iter() { - for (child, _) in scope.children.lock().unwrap().iter() { - child.emit_event(event.clone()); + self.scopes.access(move |scopes| { + for scope in scopes { + for (child, _) in scope.children.lock().unwrap().iter() { + child.emit_event(event.clone()); + } } - } + }); } pub fn emit_event_threaded( @@ -128,10 +126,7 @@ impl Context { ) { let handlers_to_call: Vec = { let guard = self.event_handlers.access_ref(); - guard - .get(&TypeId::of::()) - .cloned() - .unwrap_or_default() + guard.get(&TypeId::of::()).cloned().unwrap_or_default() }; for h in handlers_to_call { let event = event.clone(); @@ -141,16 +136,23 @@ impl Context { }); } - for scope in self.scopes.lock().unwrap().iter() { - for (child, _) in scope.children.lock().unwrap().iter() { - child.emit_event_threaded(event); + let event = event.clone(); + self.scopes.access(move |scopes| { + for scope in scopes { + for (child, _) in scope.children.lock().unwrap().iter() { + child.emit_event_threaded(&event); + } } - } + }); } pub fn scope(self: &Arc) -> Arc { let scope = Scope::new(self.executor.clone()); - self.scopes.lock().unwrap().push(scope.clone()); + + self.scopes.access({ + let scope = scope.clone(); + move |scopes| scopes.push(scope) + }); scope } @@ -161,7 +163,11 @@ impl Context { dependencies: &[&dyn HookDependency], ) -> Arc { let scope = Scope::new(self.executor.clone()); - self.scopes.lock().unwrap().push(scope.clone()); + + self.scopes.access({ + let scope = scope.clone(); + move |scopes| scopes.push(scope) + }); drawer(&scope); @@ -178,18 +184,32 @@ impl Context { scope } - pub fn draw_children(self: &Arc, ctx: &mut DrawContext) { - for scope in self.scopes.lock().unwrap().iter() { - for (child, view_wrapper) in scope.children.lock().unwrap().iter() { - let view = child.get_view(); + pub fn add_scope(self: &Arc, scope: Arc) { + self.scopes.access(|scopes| scopes.push(scope)); + } - if let Some(view_wrapper) = view_wrapper { - view_wrapper(ctx, view) - } else { - ctx.draw_view(ctx.area.clone(), view); + pub fn draw_children(self: &Arc, ctx: &mut DrawContext) { + let mut c = ctx.clone(); + + let (tx, rx) = std::sync::mpsc::channel::(); + + self.scopes.access(move |scopes| { + for scope in scopes { + for (child, view_wrapper) in scope.children.lock().unwrap().iter() { + let view = child.get_view(); + + if let Some(view_wrapper) = view_wrapper { + view_wrapper(&mut c, view) + } else { + c.draw_view(c.area.clone(), view); + } + + tx.send(c.clone()).expect("Failed transmitting DrawContext"); } } - } + }); + + *ctx = rx.recv().expect("Failed receiving DrawContext"); } pub fn get_executor(self: &Arc) -> Arc { diff --git a/src/frontend.rs b/src/frontend.rs index 2689f75..df66c54 100644 --- a/src/frontend.rs +++ b/src/frontend.rs @@ -50,7 +50,7 @@ impl Rsx { RsxScope::Static(scope_fn) => { let scope = Scope::new(executor.clone()); (scope_fn)(&scope); - context.scopes.lock().unwrap().push(scope) + context.add_scope(scope) } RsxScope::Dynamic(drawer, dependencies) => { let drawer = drawer.clone(); From d8173b8ab35d5ed1be339915f47358a45dd82489 Mon Sep 17 00:00:00 2001 From: Leo dev Date: Sat, 31 Jan 2026 14:44:28 +0100 Subject: [PATCH 4/7] Scope children with AccessCell --- src/component/context.rs | 39 ++++++++++++++++++++++++--------------- src/component/scope.rs | 13 ++++++++----- 2 files changed, 32 insertions(+), 20 deletions(-) diff --git a/src/component/context.rs b/src/component/context.rs index 41f0f77..e5ff55a 100644 --- a/src/component/context.rs +++ b/src/component/context.rs @@ -113,9 +113,12 @@ impl Context { self.scopes.access(move |scopes| { for scope in scopes { - for (child, _) in scope.children.lock().unwrap().iter() { - child.emit_event(event.clone()); - } + let event = event.clone(); + scope.children.access(move |children| { + for (child, _) in children { + child.emit_event(event.clone()); + } + }); } }); } @@ -139,9 +142,12 @@ impl Context { let event = event.clone(); self.scopes.access(move |scopes| { for scope in scopes { - for (child, _) in scope.children.lock().unwrap().iter() { - child.emit_event_threaded(&event); - } + let event = event.clone(); + scope.children.access(move |children| { + for (child, _) in children { + child.emit_event_threaded(&event); + } + }); } }); } @@ -189,23 +195,26 @@ impl Context { } pub fn draw_children(self: &Arc, ctx: &mut DrawContext) { - let mut c = ctx.clone(); + let c = ctx.clone(); let (tx, rx) = std::sync::mpsc::channel::(); self.scopes.access(move |scopes| { for scope in scopes { - for (child, view_wrapper) in scope.children.lock().unwrap().iter() { - let view = child.get_view(); + let mut c = c.clone(); + let tx = tx.clone(); + scope.children.access(move |children| { + for (child, view_wrapper) in children { + let view = child.get_view(); - if let Some(view_wrapper) = view_wrapper { - view_wrapper(&mut c, view) - } else { - c.draw_view(c.area.clone(), view); + if let Some(view_wrapper) = view_wrapper { + view_wrapper(&mut c, view) + } else { + c.draw_view(c.area.clone(), view); + } } - tx.send(c.clone()).expect("Failed transmitting DrawContext"); - } + }); } }); diff --git a/src/component/scope.rs b/src/component/scope.rs index 6cfe6e5..1a80575 100644 --- a/src/component/scope.rs +++ b/src/component/scope.rs @@ -1,18 +1,20 @@ -use std::sync::{Arc, Mutex}; +use std::sync::Arc; + +use access_cell::AccessCell; use crate::{engine::CommandExecutor, View, ViewWrapper}; use super::{context::Context, ComponentImpl}; pub struct Scope { - pub children: Mutex, Option)>>, + pub children: AccessCell, Option)>>, executor: Arc, } impl Scope { pub fn new(executor: Arc) -> Arc { Arc::new(Self { - children: Mutex::new(Vec::new()), + children: AccessCell::new(Vec::new()), executor, }) } @@ -26,7 +28,8 @@ impl Scope { ctx.refresh(); - self.children.lock().unwrap().push((ctx, view_wrapper)); + self.children + .access(|children| children.push((ctx, view_wrapper))); } pub fn view(self: &Arc, view: View) { @@ -34,6 +37,6 @@ impl Scope { ctx.refresh(); - self.children.lock().unwrap().push((ctx, None)); + self.children.access(|children| children.push((ctx, None))); } } From 2faac93944149e173b4d8712f409f8b6a258587e Mon Sep 17 00:00:00 2001 From: Leo dev Date: Sat, 31 Jan 2026 14:52:05 +0100 Subject: [PATCH 5/7] Abstracted children in scope --- src/component/context.rs | 6 +++--- src/component/scope.rs | 24 ++++++++++++++++++------ 2 files changed, 21 insertions(+), 9 deletions(-) diff --git a/src/component/context.rs b/src/component/context.rs index e5ff55a..de08664 100644 --- a/src/component/context.rs +++ b/src/component/context.rs @@ -114,7 +114,7 @@ impl Context { self.scopes.access(move |scopes| { for scope in scopes { let event = event.clone(); - scope.children.access(move |children| { + scope.access_children(move |children| { for (child, _) in children { child.emit_event(event.clone()); } @@ -143,7 +143,7 @@ impl Context { self.scopes.access(move |scopes| { for scope in scopes { let event = event.clone(); - scope.children.access(move |children| { + scope.access_children(move |children| { for (child, _) in children { child.emit_event_threaded(&event); } @@ -203,7 +203,7 @@ impl Context { for scope in scopes { let mut c = c.clone(); let tx = tx.clone(); - scope.children.access(move |children| { + scope.access_children(move |children| { for (child, view_wrapper) in children { let view = child.get_view(); diff --git a/src/component/scope.rs b/src/component/scope.rs index 1a80575..83201ce 100644 --- a/src/component/scope.rs +++ b/src/component/scope.rs @@ -1,13 +1,12 @@ +use super::{context::Context, ComponentImpl}; +use crate::{engine::CommandExecutor, View, ViewWrapper}; +use access_cell::AccessCell; use std::sync::Arc; -use access_cell::AccessCell; - -use crate::{engine::CommandExecutor, View, ViewWrapper}; - -use super::{context::Context, ComponentImpl}; +pub type ScopeChildren = Vec<(Arc, Option)>; pub struct Scope { - pub children: AccessCell, Option)>>, + children: AccessCell, executor: Arc, } @@ -39,4 +38,17 @@ impl Scope { self.children.access(|children| children.push((ctx, None))); } + + pub fn view_wrapper(self: &Arc, view: View, view_wrapper: Option) { + let ctx = Context::new(view, self.executor.clone()); + + ctx.refresh(); + + self.children + .access(|children| children.push((ctx, view_wrapper))); + } + + pub fn access_children(self: &Arc, f: impl FnOnce(&mut ScopeChildren) + Send + 'static) { + self.children.access(f); + } } From 4e2636360faab32cf18ffd523eb9ec051da945e1 Mon Sep 17 00:00:00 2001 From: Leo dev Date: Sat, 31 Jan 2026 14:56:41 +0100 Subject: [PATCH 6/7] Fixed rsx emit with new AccessCell --- macros/src/emit.rs | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/macros/src/emit.rs b/macros/src/emit.rs index 60884ca..bd31d80 100644 --- a/macros/src/emit.rs +++ b/macros/src/emit.rs @@ -76,13 +76,15 @@ fn emit_node_scope(node: &RsxNode) -> TokenStream { { #deps_emit r.dynamic_scope(move |scope| { - if #cond { - if scope.children.lock().unwrap().is_empty() { - #(#kids)* + scope.access_children(|children| { + if #cond { + if children.is_empty() { + #(#kids)* + } + } else { + .children.clear(); } - } else { - scope.children.lock().unwrap().clear(); - } + }) }, #deps_vec_emit); } } @@ -103,7 +105,7 @@ fn emit_node_scope(node: &RsxNode) -> TokenStream { #deps_emit #[allow(unused_parens)] r.dynamic_scope(move |scope| { - scope.children.lock().unwrap().clear(); + scope.access_children(|children| children.clear()); for #pat in #expr { #(#kids)* } From dd7c53c9c132550a03382e59cc43c1e2f5256a73 Mon Sep 17 00:00:00 2001 From: Leo dev Date: Sat, 31 Jan 2026 15:00:16 +0100 Subject: [PATCH 7/7] Benchmarked --- benchmark.csv | 452 +++++++++++++++++++++++++------------------------- 1 file changed, 226 insertions(+), 226 deletions(-) diff --git a/benchmark.csv b/benchmark.csv index 6abd7b0..65d5940 100644 --- a/benchmark.csv +++ b/benchmark.csv @@ -1,227 +1,227 @@ Iterx72,Nestingx72,Time µs -14,14,21945 -2,0,625 -13,3,1177 -0,13,581 -13,13,1134 -12,6,1266 -0,14,530 -8,11,1003 -12,1,1147 -8,10,1060 -14,12,1142 -6,12,1136 -10,6,1057 -13,1,1182 -8,13,1230 -3,6,1165 -11,4,17474 -6,11,1050 -7,5,1155 -11,11,1322 -12,7,1094 -12,8,1045 -10,11,1079 -5,8,1142 -2,1,1038 -3,0,638 -1,9,1027 -0,11,522 -4,13,1049 -3,9,1079 -11,5,1111 -1,12,1037 -9,7,1106 -4,11,1172 -2,9,1226 -8,3,1124 -8,7,1123 -4,0,744 -10,10,1146 -10,2,1184 -7,2,1813 -10,13,1113 -14,9,1925 -2,14,3131 -9,11,1112 -11,9,1069 -1,14,1137 -5,13,1097 -4,6,3971 -14,6,1603 -7,0,1663 -3,12,1205 -10,12,1083 -0,0,1429 -0,4,687 -4,2,1504 -3,13,1190 -7,3,1402 -6,14,1047 -2,2,1133 -4,12,1099 -10,3,3732 -6,10,1193 -4,14,1457 -5,12,1716 -3,1,1130 -13,12,1157 -6,13,1201 -6,5,1693 -12,10,1045 -7,10,2915 -14,8,1831 -3,2,1142 -9,9,7308 -7,7,6848 -12,12,1053 -8,14,1144 -10,5,1117 -11,13,1056 -0,9,524 -7,4,1888 -7,13,1136 -0,10,522 -12,4,2243 -0,3,812 -2,6,1721 -0,1,1237 -6,4,1187 -1,3,559 -11,0,1186 -1,8,1068 -2,11,1147 -11,1,1006 -7,12,1183 -12,13,1214 -2,3,1149 -8,4,1135 -9,2,1030 -13,4,858 -3,8,1163 -13,0,1392 -4,3,1170 -8,2,2436 -5,10,3718 -13,5,3525 -5,0,1120 -5,11,4088 -10,8,1205 -4,10,1032 -10,4,1072 -6,7,1394 -3,5,3701 -12,11,1012 -7,6,1110 -11,10,2031 -14,4,1088 -13,2,2757 -7,9,1647 -11,2,1225 -9,0,1117 -14,0,1063 -4,1,1204 -12,2,1098 -0,7,599 -3,3,1366 -14,5,1161 -10,14,1130 -4,4,1057 -9,3,1085 -6,1,1092 -11,7,1168 -13,9,1214 -14,3,889 -2,8,1329 -9,6,1104 -14,7,2015 -9,10,1102 -2,13,1177 -4,5,2013 -2,5,1099 -1,7,1083 -1,1,812 -1,13,892 -7,11,1310 -6,6,5371 -8,8,1164 -3,7,2720 -14,11,1263 -14,14,1111 -5,9,1105 -1,5,982 -10,1,3444 -12,5,1016 -2,10,1120 -9,1,1865 -4,7,4106 -1,0,648 -3,4,1566 -5,3,1112 -11,8,951 -2,4,1134 -3,10,1430 -6,0,727 -7,14,1216 -13,14,1940 -9,12,1322 -6,2,1115 -9,4,1129 -4,9,4591 -2,7,1120 -3,14,2022 -6,3,1107 -14,13,1028 -6,8,6169 -7,8,1256 -12,3,1042 -8,1,1500 -6,9,1069 -12,14,1044 -13,7,21445 -10,7,1166 -0,2,808 -12,9,1067 -8,12,1182 -13,10,1615 -1,6,1091 -9,8,1183 -8,6,1090 -10,9,1130 -5,2,1382 -12,0,1302 -1,11,984 -10,0,1070 -1,4,1162 -7,1,1454 -8,9,1125 -4,8,3043 -14,1,1119 -5,4,1077 -5,14,1345 -11,14,1040 -0,6,604 -9,13,2238 -13,8,1379 -11,6,1041 -11,3,5384 -3,11,1130 -9,14,859 -0,12,525 -14,2,1527 -8,0,1137 -14,10,6363 -0,5,686 -11,12,1118 -5,6,3832 -5,7,1065 -5,1,1082 -1,10,990 -0,8,609 -1,2,1036 -9,5,1046 -13,6,3712 -13,11,1184 -2,12,1164 -5,5,3398 -8,5,1119 \ No newline at end of file +14,14,14236 +11,8,10608 +8,13,7793 +13,7,12073 +11,6,10495 +5,2,5135 +6,12,6144 +6,3,6341 +12,7,11304 +11,5,10622 +0,9,497 +3,2,3303 +5,1,5186 +10,8,9781 +1,11,1358 +2,9,2341 +10,11,9788 +14,5,13036 +9,1,8807 +4,12,4249 +8,1,8306 +14,4,12985 +5,0,419 +4,13,4234 +10,1,9793 +3,13,3255 +0,4,625 +7,6,7066 +8,12,7954 +10,12,9876 +8,11,8015 +6,8,6104 +0,11,514 +2,10,2373 +8,2,7891 +2,14,2337 +2,13,2337 +7,12,7006 +3,10,3300 +11,10,10772 +4,5,4299 +10,14,9909 +12,5,11532 +9,10,8809 +12,12,11954 +14,11,13452 +8,8,7965 +4,0,449 +5,6,5127 +7,8,6921 +4,4,4244 +1,10,1370 +5,9,5122 +1,7,1369 +0,3,844 +8,3,7937 +9,9,8777 +13,6,12476 +9,3,8961 +2,5,2368 +1,12,1363 +5,12,5075 +13,11,12363 +6,13,5963 +0,8,484 +2,12,2370 +8,5,7946 +14,9,13504 +12,1,11839 +12,2,11601 +2,6,2329 +10,10,9602 +7,3,6970 +14,6,13394 +0,7,628 +6,9,6100 +12,13,11391 +0,12,458 +1,14,1370 +12,10,11719 +9,8,8807 +4,7,4235 +1,0,462 +3,11,3538 +11,7,10786 +11,13,10710 +11,2,10394 +3,9,3315 +4,6,4174 +13,8,12538 +9,11,8710 +12,14,11814 +13,2,12647 +8,7,8019 +3,1,3287 +4,8,4591 +4,3,4197 +6,10,5985 +5,7,5171 +12,9,11579 +10,4,9714 +12,4,11811 +2,3,2391 +8,9,7997 +9,7,8853 +11,1,10700 +11,11,10798 +13,4,12644 +6,4,6290 +6,2,5916 +2,0,427 +2,8,2355 +10,2,9637 +6,5,6069 +6,11,6048 +12,11,11921 +9,4,8754 +5,4,5111 +13,10,12518 +8,14,7837 +5,8,5127 +8,10,8085 +0,2,1028 +2,1,2400 +0,13,408 +6,14,6027 +12,8,11785 +2,2,2326 +1,2,1394 +4,1,4251 +1,1,1446 +3,0,433 +10,13,9693 +9,0,432 +1,3,1441 +9,13,8858 +9,14,8795 +11,9,10632 +12,0,417 +7,1,7013 +6,1,6097 +10,7,10114 +10,9,9876 +10,5,9802 +2,4,2363 +11,12,10781 +11,14,10677 +3,7,3262 +6,7,6201 +4,9,4380 +3,8,3345 +13,9,12485 +0,14,419 +1,6,1347 +4,2,4216 +4,14,4209 +7,9,6976 +13,0,458 +0,1,361 +5,14,5204 +14,2,13169 +5,10,5096 +1,5,1370 +8,0,431 +6,6,6031 +8,4,7809 +9,12,11983 +3,4,3276 +12,6,11921 +6,0,485 +1,13,1375 +4,11,4237 +0,10,481 +13,13,12545 +14,12,13253 +3,5,3210 +5,5,5158 +7,7,6992 +5,11,5076 +7,13,7056 +11,3,10584 +3,3,3302 +14,13,13280 +13,3,12771 +14,0,429 +7,5,7065 +7,14,6952 +8,6,7835 +2,7,2334 +2,11,2367 +11,4,10606 +7,11,6845 +14,8,13736 +0,5,844 +1,9,1333 +10,6,9721 +9,6,8769 +7,10,6998 +10,3,9810 +14,7,13311 +14,14,13481 +11,0,426 +5,3,5102 +1,4,1457 +13,14,12431 +12,3,11717 +13,5,12523 +14,10,13457 +0,6,705 +3,14,3335 +13,12,12714 +7,4,6951 +3,6,3247 +9,5,8713 +3,12,3401 +14,1,13199 +4,10,4260 +10,0,428 +5,13,5103 +0,0,421 +14,3,13070 +9,2,8816 +7,0,451 +7,2,6974 +1,8,1363 +13,1,12699 \ No newline at end of file