├── API.md ├── README.md ├── entries └── README.md └── starters └── javascript ├── noopbots.js ├── vexbot.html └── vexbot.js /API.md: -------------------------------------------------------------------------------- 1 | ## Vexbot 2 | 3 | ### Get a single vector 4 | 5 | `GET /vexbot` 6 | 7 | `HTTP 200` 8 | 9 | ``` 10 | { 11 | "vectors": [ 12 | { 13 | "a": { 14 | "x": 743, 15 | "y": 147 16 | }, 17 | "b": { 18 | "x": 60, 19 | "y": 601 20 | }, 21 | "speed": 71 22 | } 23 | ] 24 | } 25 | ``` 26 | 27 | 28 | ### Get multiple vectors 29 | 30 | `GET /vexbot?count=5` 31 | 32 | `HTTP 200` 33 | 34 | ``` 35 | { 36 | "vectors": [ 37 | { 38 | "a": { 39 | "x": 720, 40 | "y": 894 41 | }, 42 | "b": { 43 | "x": 686, 44 | "y": 748 45 | }, 46 | "speed": 30 47 | }, 48 | { 49 | "a": { 50 | "x": 744, 51 | "y": 514 52 | }, 53 | "b": { 54 | "x": 505, 55 | "y": 948 56 | }, 57 | "speed": 4 58 | }, 59 | { 60 | "a": { 61 | "x": 109, 62 | "y": 8 63 | }, 64 | "b": { 65 | "x": 935, 66 | "y": 949 67 | }, 68 | "speed": 91 69 | }, 70 | { 71 | "a": { 72 | "x": 618, 73 | "y": 442 74 | }, 75 | "b": { 76 | "x": 428, 77 | "y": 437 78 | }, 79 | "speed": 31 80 | }, 81 | { 82 | "a": { 83 | "x": 815, 84 | "y": 647 85 | }, 86 | "b": { 87 | "x": 918, 88 | "y": 168 89 | }, 90 | "speed": 63 91 | } 92 | ] 93 | } 94 | ``` 95 | 96 | 97 | ### Constrain vector to bounds 98 | 99 | `GET /vexbot?count=4&width=10&height=10` 100 | 101 | `HTTP 200` 102 | 103 | ``` 104 | { 105 | "vectors": [ 106 | { 107 | "a": { 108 | "x": 7, 109 | "y": 2 110 | }, 111 | "b": { 112 | "x": 6, 113 | "y": 4 114 | }, 115 | "speed": 41 116 | }, 117 | { 118 | "a": { 119 | "x": 4, 120 | "y": 9 121 | }, 122 | "b": { 123 | "x": 3, 124 | "y": 0 125 | }, 126 | "speed": 95 127 | }, 128 | { 129 | "a": { 130 | "x": 0, 131 | "y": 0 132 | }, 133 | "b": { 134 | "x": 7, 135 | "y": 1 136 | }, 137 | "speed": 27 138 | }, 139 | { 140 | "a": { 141 | "x": 1, 142 | "y": 1 143 | }, 144 | "b": { 145 | "x": 4, 146 | "y": 2 147 | }, 148 | "speed": 80 149 | } 150 | ] 151 | } 152 | ``` 153 | 154 | 155 | ### Require vectors to connect 156 | 157 | `GET /vexbot?count=4&connected=1` 158 | 159 | `HTTP 200` 160 | 161 | ``` 162 | { 163 | "vectors": [ 164 | { 165 | "a": { 166 | "x": 77, 167 | "y": 304 168 | }, 169 | "b": { 170 | "x": 560, 171 | "y": 35 172 | }, 173 | "speed": 85 174 | }, 175 | { 176 | "a": { 177 | "x": 560, 178 | "y": 35 179 | }, 180 | "b": { 181 | "x": 827, 182 | "y": 886 183 | }, 184 | "speed": 21 185 | }, 186 | { 187 | "a": { 188 | "x": 827, 189 | "y": 886 190 | }, 191 | "b": { 192 | "x": 788, 193 | "y": 722 194 | }, 195 | "speed": 93 196 | }, 197 | { 198 | "a": { 199 | "x": 788, 200 | "y": 722 201 | }, 202 | "b": { 203 | "x": 491, 204 | "y": 525 205 | }, 206 | "speed": 82 207 | } 208 | ] 209 | } 210 | ``` 211 | 212 | 213 | ### Change magnitude of vectors 214 | 215 | `GET /vexbot?count=4&magnitude=4` 216 | 217 | `HTTP 200` 218 | 219 | ``` 220 | { 221 | "vectors": [ 222 | { 223 | "a": { 224 | "x": 495, 225 | "y": 198 226 | }, 227 | "b": { 228 | "x": 492, 229 | "y": 196 230 | }, 231 | "speed": 14 232 | }, 233 | { 234 | "a": { 235 | "x": 819, 236 | "y": 833 237 | }, 238 | "b": { 239 | "x": 817, 240 | "y": 832 241 | }, 242 | "speed": 49 243 | }, 244 | { 245 | "a": { 246 | "x": 51, 247 | "y": 9 248 | }, 249 | "b": { 250 | "x": 50, 251 | "y": 10 252 | }, 253 | "speed": 84 254 | }, 255 | { 256 | "a": { 257 | "x": 582, 258 | "y": 812 259 | }, 260 | "b": { 261 | "x": 584, 262 | "y": 813 263 | }, 264 | "speed": 73 265 | } 266 | ] 267 | } 268 | ``` -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | ![vexbot](https://user-images.githubusercontent.com/212941/59231505-bb48a900-8b95-11e9-9ed0-acd620feaf76.png) 3 | 4 | # 👋 Meet Vexbot 5 | 6 | Ah, Vexbot. It's not really vexing—just very orderly. With every request, Vexbot will send you up to a thousand lines—two pairs of coordinates and a speed. 7 | 8 | ## ↗ What can you do? 9 | 10 | Just lines? Sure, you could just draw one line... 11 | 12 | ![single-line](https://user-images.githubusercontent.com/212941/58451645-2475ea00-80c9-11e9-9823-80732512dcac.png) 13 | 14 | But when you draw a thousand it starts to get interesting... 15 | 16 | ![many-lines](https://user-images.githubusercontent.com/212941/58451643-2475ea00-80c9-11e9-846f-7dfba6fc1182.png) 17 | 18 | And when you start layering them... 19 | 20 | ![lines-buildup](https://user-images.githubusercontent.com/212941/58450916-12467c80-80c6-11e9-95ca-ade8288500a4.gif) 21 | 22 | Or you could ask the nice Vexbot to connect all the lines for you... 23 | 24 | ![connected-lines](https://user-images.githubusercontent.com/212941/58451245-86355480-80c7-11e9-9fb7-72d1429b1a5c.png) 25 | 26 | And we haven't even gotten into what happens when you animate lines individually... 27 | 28 | What's next? That's up to you! 29 | 30 | ## ✨ A few ideas 31 | There are millions of things you can do with Vexbot, but here are a few ideas to get you started: 32 | 33 | - **Bring it to life:** With the connected parameter turned on, our little Vexbot gives you a thousand-jointed creature you can makewriggle across your screen. 34 | - **Pickup Sticks:** Ever play the [game](https://en.wikipedia.org/wiki/Pick-up_sticks)? Now's your chance to build it. 35 | - **Don't touch the lines:** Add a hero whom you navigate around the lines to a destination. 36 | 37 | Have an idea of your own? Create an issue and we'll add it to the list. 38 | 39 | ## 🤖 API basics 40 | 41 | You can request up to 1,000 pairs of coordinates, specify the magnitude and whether you want your lines connected, and set maximum *x* and *y* boundaries. 42 | 43 | There's a single endpoint: `api.noopschallenge.com/vexbot` 44 | 45 | The endpoint accepts five parameters, all optional: 46 | 47 | - **count** *(optional, numeric)*: Between 1 and 1000. Number of lines to return. 48 | - **magnitude** *(optional, numeric)*: Between 1 and 100,000. Maximum length of lines. 49 | - **connected** *(optional, numeric boolean)*: 1 or 0. If `connected===1`, then the `b` coordinate of each line will be the `a` coordinate of the next. 50 | - **width** *(optional, numeric)*: Between 10 and 100,000. Maximum width of returned points. 51 | - **height** *(optional, numeric)*: Between 10 and 100,000. Maximum height of returned points. 52 | 53 | The endpoint returns a JSON object with an array named `vectors` of *n* length. Each item in the `vectors` has three properties: `a`, `b`, and `speed`. 54 | 55 | Example return for a single line: 56 | 57 | ``` 58 | { 59 | "vectors": [ 60 | { 61 | "a": { 62 | "x": 743, 63 | "y": 147 64 | }, 65 | "b": { 66 | "x": 60, 67 | "y": 601 68 | }, 69 | "speed": 71 70 | } 71 | ] 72 | } 73 | ``` 74 | 75 | Read the [complete API documentation](./API.md). 76 | 77 | More about Vexbot here: https://noopschallenge.com/challenges/vexbot 78 | -------------------------------------------------------------------------------- /entries/README.md: -------------------------------------------------------------------------------- 1 | ## 👀 Show us what you're working on. 2 | Post a README and screenshots in `/entries/{username}`. 3 | 4 | In your README, include everything someone would need to access your project. 5 | 6 | If your project is very simple only has a few files, you can include your code in your entry so other challengers can see it. Otherwise you can link to your repository (if you'd like to share your code). 7 | 8 | ## How to submit a PR 9 | - Create a folder here with your GitHub username (i.e. `/entries/{username}`) 10 | - Add a README with instructions for viewing your project. 11 | - If applicable, add a screenshot of the project. 12 | -------------------------------------------------------------------------------- /starters/javascript/noopbots.js: -------------------------------------------------------------------------------- 1 | const API_BASE = 'https://api.noopschallenge.com'; 2 | 3 | function NOOPBOT_START() { 4 | console.log(`Noop Noop! 🤖🤖🤖🤖🤖`); 5 | if (window.start_app) { 6 | start_app(); 7 | } else { 8 | console.error('start_app not defined'); 9 | } 10 | } 11 | 12 | function NOOPBOT_FETCH(options, onComplete) { 13 | 14 | if (!options.API) { 15 | console.error('API not set'); 16 | return; 17 | } 18 | 19 | if (!onComplete) { 20 | console.warn('onComplete not set, nothing will happen.'); 21 | } 22 | 23 | let params = []; 24 | Object.keys(options).forEach(key => params.push(`${key}=${options[key]}`)) 25 | let url = `${API_BASE}/${options.API}?` + params.join('&'); 26 | 27 | window.fetch(url) 28 | .then(function(response) { 29 | return response.json(); 30 | }).then(function(responseJson) { 31 | onComplete(responseJson) 32 | }); 33 | } 34 | 35 | function NOOPBOT_SETUP_CANVAS(options) { 36 | 37 | if (!options) { 38 | console.error("No options provided to SETUP_CANVAS"); 39 | return; 40 | } 41 | 42 | if (!canvas || !options.canvas.getContext) { 43 | console.error("No canvas, we're in for a bad time..."); 44 | return; 45 | } 46 | 47 | let width = options.width || window.innerWidth; 48 | let height = options.height || window.innerHeight; 49 | 50 | let ctx = options.canvas.getContext('2d'); 51 | 52 | ctx.canvas.width = width; 53 | ctx.canvas.height = height; 54 | 55 | ctx.fillStyle = options.bgColor || '#f1f1f1'; 56 | ctx.fillRect(0, 0, width, height); 57 | return ctx 58 | } 59 | 60 | function NOOPBOT_TICK_SETUP(onTick, interval) { 61 | return setInterval(onTick, interval); 62 | } 63 | 64 | function NOOPBOT_TICK_STOP(intervalId) { 65 | clearInterval(intervalId); 66 | } 67 | 68 | function NOOPBOT_DECIDE(set) { 69 | if (!set || !set.length) { 70 | return null; 71 | } 72 | return set[Math.floor(Math.random()*set.length)]; 73 | } 74 | 75 | function NOOPBOT_DECIDE_POINT(width, height) { 76 | return { 77 | x: NOOPBOT_RANDOM(0, width), 78 | y: NOOPBOT_RANDOM(0, height) 79 | }; 80 | } 81 | 82 | function NOOPBOT_RANDOM(min, max) { 83 | return min + Math.floor(Math.random()*(max-min)); 84 | } 85 | 86 | window.onload = function (event) { 87 | NOOPBOT_START(); 88 | }; 89 | -------------------------------------------------------------------------------- /starters/javascript/vexbot.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Vexbot Starter 5 | 6 | 7 | 8 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /starters/javascript/vexbot.js: -------------------------------------------------------------------------------- 1 | let canvas; 2 | let ctx; 3 | let appWidth; 4 | let appHeight; 5 | 6 | //let colors = ['#ff00a2']; //try just one color 7 | let colors = ['#ff00a2','#00baff','#ff6c00', '#f1f1f1']; //try a few colors 8 | 9 | // called by NOOPBOT on window.onload 10 | function start_app() { 11 | 12 | // size canvas to window 13 | sizeCanvas(); 14 | 15 | //set up a ticker to refresh page automatically. 16 | let speed = 600; // how often screen refreshes, in milliseconds. 17 | let ticker = NOOPBOT_TICK_SETUP(draw, speed); 18 | 19 | //fire a draw event. 20 | draw(); 21 | 22 | //redraw when canvas is clicked. 23 | canvas.addEventListener('click', draw); 24 | } 25 | 26 | function sizeCanvas() { 27 | appWidth = window.innerWidth; 28 | appHeight = window.innerHeight; 29 | canvas = document.getElementById('canvas'); 30 | ctx = NOOPBOT_SETUP_CANVAS( { canvas: canvas, bgColor:'#f1f1f1' }); 31 | } 32 | 33 | function draw() { 34 | //get the data! 35 | NOOPBOT_FETCH({ 36 | API: 'vexbot', 37 | count: 500, 38 | width: appWidth, 39 | height: appHeight, 40 | magnitude: 24, 41 | connected: 1 42 | }, drawSet); 43 | } 44 | 45 | function drawSet(responseJson) { 46 | //clean the canvas. comment out to let them build up. 47 | //NOOPBOT_SETUP_CANVAS({ canvas: canvas, bgColor:NOOPBOT_DECIDE(colors) }); 48 | 49 | let { vectors } = responseJson; 50 | vectors.forEach(function(vector) { 51 | drawVector(ctx, vector); 52 | }) 53 | } 54 | 55 | function drawVector(ctx, points) { 56 | 57 | // randomly choose fill color and alpha 58 | ctx.strokeStyle = NOOPBOT_DECIDE(colors); 59 | ctx.globalAlpha = NOOPBOT_RANDOM(0,100)/100; 60 | ctx.lineWidth = NOOPBOT_RANDOM(1,2); 61 | let {a, b} = points; 62 | 63 | // draw line 64 | ctx.beginPath(); 65 | ctx.moveTo(a.x, a.y); 66 | ctx.lineTo(b.x, b.y); 67 | 68 | // stroke line 69 | ctx.stroke(); 70 | 71 | } 72 | 73 | // listen if browser changes size. 74 | window.onresize = function(event){ 75 | sizeCanvas(); 76 | draw(); 77 | }; 78 | --------------------------------------------------------------------------------