silly little doodles
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

remove unused & add comments

nnuuvv 59ea1c13 0733b12b

+56 -67
+56 -60
src/doodler.gleam
··· 8 8 import lustre/element/svg 9 9 import lustre/event.{on_click} 10 10 11 + const point_spacing = 5 12 + 11 13 pub fn main() { 12 14 let app = lustre.simple(init, update, view) 13 15 let assert Ok(_) = lustre.start(app, "#app", Nil) ··· 33 35 34 36 type Msg { 35 37 UserClickedPoint(Point) 38 + // TODO: implement mirror toggle 39 + // For horizontal / vertical mirroring 40 + // TODO: implement 'shape verification mode' toggle 36 41 } 37 42 38 43 fn starting_points() { 39 44 set.from_list([ 45 + Point(0, 0), 46 + Point(0, 1), 40 47 Point(0, -1), 41 48 Point(-1, 0), 42 - Point(0, 0), 43 - Point(0, 1), 49 + Point(-1, -1), 44 50 Point(1, 0), 51 + Point(1, -1), 45 52 ]) 46 53 } 47 54 ··· 54 61 Model(points: _, edges:, selected: None) -> { 55 62 let points = 56 63 update_points(edges) 57 - |> add_point_siblings(clicked_point) 64 + |> add_point_neighbors(clicked_point) 58 65 59 66 Model(points:, edges:, selected: Some(clicked_point)) 60 67 } ··· 81 88 && points_equal(edge.b, first_point) 82 89 } 83 90 }) 84 - |> echo 85 91 86 92 let edges = case thing { 87 - // TODO: implement mirror toggle 88 - // For horizontal / vertical mirroring 89 93 // the new edge wasnt found in the existing ones, add it 90 94 #([], edges) -> [Edge(first_point, clicked_point), ..edges] 91 95 // the new edge was found in the existing ones, remove it ··· 95 99 // let points = model.points 96 100 97 101 Model(points:, edges:, selected: None) 98 - |> echo 99 102 } 100 103 } 101 104 } 102 105 } 103 106 } 104 107 105 - fn update_points(edges: List(Edge)) { 108 + /// generate points based on edges 109 + /// 110 + /// - all points used in drawn edges 111 + /// - all their neightbors 112 + fn update_points(edges: List(Edge)) -> Set(Point) { 106 113 edges 107 114 |> list.fold(set.new(), fn(points, edge) { 108 115 points 109 - |> add_point_siblings(edge.a) 110 - |> add_point_siblings(edge.b) 116 + |> add_point_neighbors(edge.a) 117 + |> add_point_neighbors(edge.b) 111 118 }) 112 - |> add_point_siblings(Point(0, 0)) 119 + |> add_point_neighbors(Point(0, 0)) 113 120 } 114 121 115 - fn add_point_siblings(point_set point_set, for_point for_point) { 122 + /// add all 8 neightbor points of the supplied point 123 + /// ( )( )( ) 124 + /// ( )(x)( ) 125 + /// ( )( )( ) 126 + /// 127 + fn add_point_neighbors( 128 + point_set point_set: Set(Point), 129 + for_point for_point: Point, 130 + ) -> Set(Point) { 116 131 let Point(x, y) = for_point 117 132 point_set 118 133 |> set.insert(Point(x, y)) ··· 126 141 |> set.insert(Point(x + 1, y + 1)) 127 142 } 128 143 144 + /// compare two points for equality 145 + /// 129 146 fn points_equal(first_point: Point, second_point: Point) -> Bool { 130 147 first_point.x == second_point.x && first_point.y == second_point.y 131 148 } 132 149 133 - @external(javascript, "./doodler.js", "viewport_height") 134 - pub fn viewport_height() -> Int 135 - 136 - @external(javascript, "./doodler.js", "viewport_width") 137 - pub fn viewport_width() -> Int 138 - 150 + /// get #(min_x, min_y, max_x, max_y) from a list of points 151 + /// 139 152 fn min_max(points) { 140 153 points 141 154 |> set.fold(#(0, 0, 0, 0), fn(counts, point) { ··· 150 163 151 164 #(min_x, min_y, max_x, max_y) 152 165 }) 153 - |> echo 154 166 } 155 167 156 - fn count_x_y(points: Set(Point)) -> #(Int, Int) { 157 - let #(x, y) = 158 - points 159 - |> set.fold(#(0, 0), fn(counts, point) { 160 - let #(max_x, max_y) = counts 161 - 162 - let x = int.absolute_value(point.x) 163 - let y = int.absolute_value(point.y) 164 - 165 - case x, y { 166 - x, y if x > max_x && y > max_y -> #(x, y) 167 - x, _y if x > max_x -> #(x, max_y) 168 - _x, y if y > max_y -> #(max_x, y) 169 - _, _ -> counts 170 - } 171 - }) 172 - 173 - #(x, y) 174 - } 175 - 168 + /// view 169 + /// 176 170 fn view(model: Model) { 177 - let #(x, y) = 178 - model.points 179 - |> count_x_y 180 - 181 - let buffer = 5 182 - 183 171 let #(min_x, min_y, max_x, max_y) = 184 172 model.points 185 173 |> min_max() 186 174 187 - let min_x = min_x * 5 - buffer 188 - let min_y = min_y * 5 - buffer 189 - let max_x = max_x * 5 + buffer 190 - let max_y = max_y * 5 + buffer 175 + let min_x = to_dispay_grid(min_x) - point_spacing 176 + let min_y = to_dispay_grid(min_y) - point_spacing 177 + let max_x = to_dispay_grid(max_x) + point_spacing 178 + let max_y = to_dispay_grid(max_y) + point_spacing 191 179 192 180 let viewbox = 193 181 int.to_string(min_x) ··· 217 205 ]) 218 206 } 219 207 208 + /// turn simple Point(x,y) grid coords into 'display grid' by appling point_spacing 209 + /// 210 + fn to_dispay_grid(a) { 211 + a * point_spacing 212 + } 213 + 214 + /// view the Option(Point) selected point if it exists 215 + /// 220 216 fn view_selected(selected: Option(Point)) { 221 217 case selected { 222 218 None -> div([], []) ··· 224 220 } 225 221 } 226 222 223 + /// view an edge 224 + /// 227 225 fn view_edge(edge: Edge) { 228 226 let Edge(a, b) = edge 229 227 svg.line([ 230 - attribute.attribute("x1", int.to_string(a.x * 5)), 231 - attribute.attribute("y1", int.to_string(a.y * 5)), 232 - attribute.attribute("x2", int.to_string(b.x * 5)), 233 - attribute.attribute("y2", int.to_string(b.y * 5)), 228 + attribute.attribute("x1", int.to_string(a.x |> to_dispay_grid())), 229 + attribute.attribute("y1", int.to_string(a.y |> to_dispay_grid())), 230 + attribute.attribute("x2", int.to_string(b.x |> to_dispay_grid())), 231 + attribute.attribute("y2", int.to_string(b.y |> to_dispay_grid())), 234 232 attribute.styles([ 235 233 #("stroke", "black"), 236 234 #("stroke-width", "1"), ··· 238 236 ]) 239 237 } 240 238 241 - fn view_point(point: Point, selected: Bool) { 239 + /// view a Point(x,y) *with_highlight* or without 240 + /// 241 + fn view_point(point point: Point, with_highlight selected: Bool) { 242 242 let selected_attrs = case selected { 243 243 False -> [ 244 244 attribute.attribute("fill", "black"), ··· 251 251 svg.circle([ 252 252 on_click(UserClickedPoint(point)), 253 253 attribute.attribute("r", "1"), 254 - attribute.attribute("cy", int.to_string(point.y * 5)), 255 - attribute.attribute("cx", int.to_string(point.x * 5)), 254 + attribute.attribute("cy", int.to_string(point.y |> to_dispay_grid())), 255 + attribute.attribute("cx", int.to_string(point.x |> to_dispay_grid())), 256 256 ..selected_attrs 257 257 ]) 258 258 } 259 - 260 - fn calculate_offset(size, coord, offset) { 261 - { size * coord } + offset 262 - }
-7
src/doodler.js
··· 1 - export function viewport_width() { 2 - return document.documentElement.clientWidth 3 - } 4 - 5 - export function viewport_height() { 6 - return document.documentElement.clientHeight 7 - }