<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:sy="http://purl.org/rss/1.0/modules/syndication/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" version="2.0">
  <channel>
    <title>Bulkan Evcimen</title>
    <link>http://localhost/</link>
    <atom:link href="http://localhost/feed.xml" rel="self" type="application/rss+xml"/>
    <description>Read about programming, music, photography and generative art.</description>
    <lastBuildDate>Sat, 19 Sep 2026 00:58:43 GMT</lastBuildDate>
    <language>en</language>
    <generator>Lume 3.3.1</generator>
    <item>
      <title>⨺ Delaunay dreams: t-shirt inspired p5.js adventure</title>
      <link>http://localhost/delaunay-dreams/</link>
      <guid isPermaLink="false">http://localhost/delaunay-dreams/</guid>
      <content:encoded>
        <![CDATA[<p>Ever since February 17th, 2020, I've been on a quest to implement a p5.js sketch to replicate the pattern on my t-shirt. Since I got interested in generative art, I got fascinated by the way that the diagonal lines create a dynamic and visually appealing effect.</p>
<p>I wanted to see if I could recreate this pattern using code, and to learn more about the underlying algorithm(s).</p>
<p>In my mind, there were two problems that I had to solve. First, I needed to figure out how to create the cells in a square canvas then fill the cells with varying diagonals.</p>
<p>My initial thought was to divide the edges of the inner frame into equally spaced points. Then, starting from a random point along this edge (call this <code>A</code>), find another random point within the inner square <code>B</code>, and connect this back to a point adjacent to <code>A</code>. Then, <code>A</code> would have been removed from the list of &quot;active points&quot;.</p>
<p>Running this algorithm on paper, I realised it would create a few triangles and not necessarily pack the canvas with it. There was something I was missing. For some reason I had a hunch that &quot;creating random triangles&quot; was a solved problem and after some research I found about Delaunay triangulation.</p>
<p>Given a set of points, Delaunay triangulation helps you draw triangles between these points that follow these rules;</p>
<ol>
<li>No point is inside the circle that goes through the three corners of any triangle.</li>
<li>You use as few triangles as possible.</li>
</ol>
<p>In simple terms, Delaunay triangulation is a way to create triangles from a given set of points while making sure that no point is in the center of the circle, that passes through all three points of the traingle.</p>
<p>With this knowledge in mind I was to find this library</p>
<p><a href="https://www.npmjs.com/package/delaunay-triangulate">delaunay-triangulate</a></p>
<blockquote>
<p>Delaunay triangulations in any dimension. Latest version: 1.1.6, last published: 9 years ago. Start using delaunay-triangulate in your project by running <code>npm i delaunay-triangulate</code>. There are 31 other projects in the npm registry using delaunay-triangulate.</p>
</blockquote>
<p>With this library I was able to solve the first part by creating random points within a square, ensuring that the corner points of this square was added and then passing these to the <code>delaunay-triangulate</code> library which returns an array of triangles vertices.</p>
<p>Afterwards, I moved onto drawing the lines within each triangle. My first few ideas was drawing horizontal and vertical lines from the longest side of the triangle to the shortest side. Using the area of each cell as value to then <a href="https://p5js.org/reference/#/p5/map">map</a> into the amount of lines to draw.</p>
<p>I spent quite a few hours watching videos on trigonometry to re-remember how to calculate area of triangle and how to finding angles within to then classify a cell as a &quot;skinny triangle&quot;.</p>
<p>Unfortunately my ideas at that time never worked in replicating the design I on the t-shirt. You can see a live example below</p>
<iframe alt="https://zigzag.bulkan.dev" height="700px" src="https://zigzag.bulkan.dev/"></iframe>
<p>The code is available here</p>
<p><a href="https://github.com/bulkan/zigzag">GitHub - bulkan/zigzag</a></p>
<blockquote>
<p>Contribute to bulkan/zigzag development by creating an account on GitHub.</p>
</blockquote>
<p>Yet again, I was missing something that I couldn't quite put my finger on.</p>
<h2 id="%F0%9F%91%B6-fast-forward-to-september-2023" tabindex="-1"><a href="http://localhost/delaunay-dreams/#%F0%9F%91%B6-fast-forward-to-september-2023" class="header-anchor">👶 Fast forward to September 2023</a></h2>
<p>During the second half of my parental leave, I was finding time in between our baby's naps and I was getting bored with Fifa 23. This is when I started watching videos on Flow Fields, Particles and how to implement them using p5.js.</p>
<p>At the same time I had started solving some LeetCode problems (I was bored 🤷‍♂️) but that got boring after a while.</p>
<p><a href="https://www.youtube.com/watch?v=BjoM9oKOAKY">Coding Challenge #24: Perlin Noise Flow Field</a></p>
<blockquote>
<p>In this coding challenge, I use Perlin noise to create a two-dimensional flow field with the p5.js library. Code: https://thecodingtrain.com/challenges/24-pe…</p>
</blockquote>
<p>With the flow fields I had idea of updating this implementation of <a href="https://mira.bulkan.dev/">Mira-Gumowski fractal</a> that I had created to use flow fields but that idea is a different topic for another day.</p>
<p>As I was going through my notes on generative sketch ideas to see if there was something else I can work on, I ended up reading my notes on replicating the design on this t-shirt.</p>
<p>It was a problem that I wanted to solve. I also noticed that, not each cell was a triangle rather a polygon !</p>
<p>In my initial explanation of Delaunay triangulation I intentionally omitted the relationship to Voronoi diagrams, which I was aware when I had initially come across Delaunay triangulation.</p>
<p>With that in mind I found the following d3 implementation that also had a way of creating a Voronoi diagram.</p>
<p><a href="https://github.com/d3/d3-delaunay">GitHub - d3/d3-delaunay: Compute the Voronoi diagram of a set of two-dimensional points.</a></p>
<blockquote>
<p>Compute the Voronoi diagram of a set of two-dimensional points. - GitHub - d3/d3-delaunay: Compute the Voronoi diagram of a set of two-dimensional points.</p>
</blockquote>
<p>Here is a an example Voronoi diagram.</p>
<img src="https://upload.wikimedia.org/wikipedia/commons/thumb/5/54/Euclidean_Voronoi_diagram.svg/1920px-Euclidean_Voronoi_diagram.svg.png" srcset="https://upload.wikimedia.org/wikipedia/commons/thumb/5/54/Euclidean_Voronoi_diagram.svg/500px-Euclidean_Voronoi_diagram.svg.png 500w, https://upload.wikimedia.org/wikipedia/commons/thumb/5/54/Euclidean_Voronoi_diagram.svg/960px-Euclidean_Voronoi_diagram.svg.png 960w, https://upload.wikimedia.org/wikipedia/commons/thumb/5/54/Euclidean_Voronoi_diagram.svg/1280px-Euclidean_Voronoi_diagram.svg.png 1280w, https://upload.wikimedia.org/wikipedia/commons/thumb/5/54/Euclidean_Voronoi_diagram.svg/1920px-Euclidean_Voronoi_diagram.svg.png 1920w" sizes="(min-width: 720px) 720px, 100vw" alt="" loading="lazy" decoding="async">
<p><em>https://en.wikipedia.org/wiki/Voronoi_diagram#/media/File:Euclidean_Voronoi_diagram.svg</em></p>
<p>A Voronoi diagram can be created by having random points, then dividing these points into polygons, one polygon for each point that is nearest to the centre of this cell compared to any other point.</p>
<p>A Voronoi diagram can be generated after a Delaunay triangulation is done as the centre point of the circles that passes through all three points (vertices) of the triangle form the edges of the Voronoi diagram.</p>
<p>The diagrams on <a href="https://en.wikipedia.org/wiki/Delaunay_triangulation#Relationship_with_the_Voronoi_diagram">Wikipedia illustrate</a> this much better than I can articulate</p>
<img src="https://upload.wikimedia.org/wikipedia/commons/thumb/1/1f/Delaunay_circumcircles_centers.svg/1920px-Delaunay_circumcircles_centers.svg.png" srcset="https://upload.wikimedia.org/wikipedia/commons/thumb/1/1f/Delaunay_circumcircles_centers.svg/500px-Delaunay_circumcircles_centers.svg.png 500w, https://upload.wikimedia.org/wikipedia/commons/thumb/1/1f/Delaunay_circumcircles_centers.svg/960px-Delaunay_circumcircles_centers.svg.png 960w, https://upload.wikimedia.org/wikipedia/commons/thumb/1/1f/Delaunay_circumcircles_centers.svg/1280px-Delaunay_circumcircles_centers.svg.png 1280w, https://upload.wikimedia.org/wikipedia/commons/thumb/1/1f/Delaunay_circumcircles_centers.svg/1920px-Delaunay_circumcircles_centers.svg.png 1920w" sizes="(min-width: 720px) 720px, 100vw" alt="" loading="lazy" decoding="async">
<p><em>Delaunay triangulation with all the circumcircles and their centers (in red).</em></p>
<img src="https://upload.wikimedia.org/wikipedia/commons/thumb/5/56/Delaunay_Voronoi.svg/1920px-Delaunay_Voronoi.svg.png" srcset="https://upload.wikimedia.org/wikipedia/commons/thumb/5/56/Delaunay_Voronoi.svg/500px-Delaunay_Voronoi.svg.png 500w, https://upload.wikimedia.org/wikipedia/commons/thumb/5/56/Delaunay_Voronoi.svg/960px-Delaunay_Voronoi.svg.png 960w, https://upload.wikimedia.org/wikipedia/commons/thumb/5/56/Delaunay_Voronoi.svg/1280px-Delaunay_Voronoi.svg.png 1280w, https://upload.wikimedia.org/wikipedia/commons/thumb/5/56/Delaunay_Voronoi.svg/1920px-Delaunay_Voronoi.svg.png 1920w" sizes="(min-width: 720px) 720px, 100vw" alt="" loading="lazy" decoding="async">
<p><em>Connecting the centers of the circumcircles produces the <a href="https://en.wikipedia.org/wiki/Voronoi_diagram">Voronoi diagram</a> (in red).</em></p>
<p>Coming back to the t-shirt design, as I've mentioned the cells aren't just triangle but polygons and Voronoi diagrams was what I should've used instead of triangles.</p>
<p>After a three year hiatus I restarted this project again using <a href="https://github.com/d3/d3-delaunay">d3-delaunay</a>. Creating a Voronoi diagram and using it with p5.js is simple, here is an example using the p5.js editor which you might need to open in a new tab.</p>
<iframe height="500px" src="https://editor.p5js.org/bulkan/full/qbbxZzm4v"></iframe>
<p>In the above example, all that is happening is;</p>
<ul>
<li>Creating an array of random points within the <code>width</code> and <code>height</code> of the canvas plus some arbitrary <code>MARGIN</code></li>
<li>Using Delaunay triangulation for these vertices</li>
<li>Then creating a Voronoi diagram from the triangulation with a specific <code>bounds</code>.</li>
</ul>
<p>Next step was to fill in the lines within each cell. I initially tried drawing equally spaced lines from the longest edge to shortest edge but that ended up drawing horizontal lines.</p>
<p>I was stuck yet again. I started researching when I by chance came across something called the Scan Line Algorithm.</p>
<p>It is an algorithm that is used in (low-level) graphics programming to fill in triangles and polygons, by finding lines that intersect with the polygon. Once you find a line that intersects, you have access to all pixel co-ordinates to be able to fill it.</p>
<p>Here are two videos that helped me a lot in understanding.</p>
<iframe width="200" height="113" src="https://www.youtube.com/embed/wzXp57F13GI?feature=oembed" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen="" title="(Unit 3) Drawing Primitives 5: Filling Polygons"></iframe>
<p><em>Polygon filling</em></p>
<iframe width="200" height="113" src="https://www.youtube.com/embed/j-sI3DweFdI?feature=oembed" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen="" title="Scan Line Polygon Fill Algorithm | CG Lab Program – 9 | OpenGL Programming"></iframe>
<ul>
<li>Start by casting an imaginary line from the minimum <code>y</code> position of the polygons vertices to its maximum <code>y</code> position</li>
<li>Check if this line intersects with any of the edges of the polygon</li>
<li>If they do, add the <code>(x, y)</code> coordinates of the intersection points to a list</li>
</ul>
<p>Using this I was able to fill the cells with lines.</p>
<img src="http://localhost/content/images/2023/09/Screenshot-2023-09-22-at-10.05.59-pm.png" srcset="/content/images/size/w600/2023/09/Screenshot-2023-09-22-at-10.05.59-pm.png 600w, /content/images/size/w1000/2023/09/Screenshot-2023-09-22-at-10.05.59-pm.png 1000w, /content/images/size/w1600/2023/09/Screenshot-2023-09-22-at-10.05.59-pm.png 1600w, /content/images/2023/09/Screenshot-2023-09-22-at-10.05.59-pm.png 2250w" sizes="(min-width: 720px) 720px, 100vw" width="2000" height="1988" alt="" loading="lazy" decoding="async">
<p><em>Voronoi diagram with horizontal equally spaced lines</em></p>
<p>But they all ended up being horizontal lines and I can't believe I didn't notice this before hand 🤦‍♂️.</p>
<p>I was close ! All I had to was just find the intersection points with the polygon using a diagonal line instead of a horizontal line.</p>
<p>I spent hours trying to get the maths right but something wasn't clicking and still hasn't. If my wife who, is a graphic designer hadn't said that I should just draw the lines in another layer and layer it into the polygons, I would've parked this yet again.</p>
<p>Instead, I remembered the existence of the <a href="https://p5js.org/reference/#/p5.Graphics">p5.Graphics</a> class which allows you to create a new offscreen graphics buffer. I wasn't certain at this stage if it supported masking and clipping which I looked up and found the following video.</p>
<iframe width="200" height="113" src="https://www.youtube.com/embed/Wdz71QzcdyY?feature=oembed" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen="" title="Placing shapes and images inside of shapes - Clipping masks in p5.js"></iframe>
<p><em>p5.js clipping masks</em></p>
<p>It shows how to draw a polygon into a Graphics buffer, then use that shape as a clipping mask to an image. Using this as an example I was able to update my sketch and draw the Voronoi cells into a seperate graphics buffer that then was copied into the main canvas.</p>
<p>Next I used a seperate graphics buffer with the same width and height of the polygon buffer to draw lines starting from <code>x=0</code> until <code>width * 2</code> this ensures that there are enough lines even after rotating it.</p>
<p>Then all I had to was use the copy the lines from this new graphics instance into the graphics instance with the polygon and then clip polygon.</p>
<p>Et voilà!</p>
<img src="http://localhost/content/images/2023/09/Screenshot-2023-09-19-at-3.12.54-pm-3.png" srcset="/content/images/size/w600/2023/09/Screenshot-2023-09-19-at-3.12.54-pm-3.png 600w, /content/images/size/w1000/2023/09/Screenshot-2023-09-19-at-3.12.54-pm-3.png 1000w, /content/images/size/w1600/2023/09/Screenshot-2023-09-19-at-3.12.54-pm-3.png 1600w, /content/images/2023/09/Screenshot-2023-09-19-at-3.12.54-pm-3.png 1991w" sizes="(min-width: 720px) 720px, 100vw" width="1991" height="1998" alt="" loading="lazy" decoding="async">
<p>You can see a live version embedded down below. If you're on mobile, sorry it's best viewed on a desktop at <a href="https://polylines.bulkan.dev/">https://polylines.bulkan.dev</a></p>
<iframe height="500px" src="https://polylines.bulkan.dev/"></iframe>
<p>If you're interested the code is here</p>
<p><a href="https://github.com/bulkan/polylines">GitHub - bulkan/polylines: Polylines</a></p>
<blockquote>
<p>Polylines. Contribute to bulkan/polylines development by creating an account on GitHub.</p>
</blockquote>
<p>After three years from initial idea I was able to finally implement this sketch. There are still a few things in this implementation that I would like to work.</p>
<ul>
<li>If the angle to rotate the graphics instance with the lines is more than <code>90</code> degrees then for some cells the lines start from the middle</li>
<li>Creating a new graphics instance for each polygon isn't ideal but it seems necessary because of <code>clip</code></li>
<li>Lastly, need to go back and work out the maths when using a diagonal scan line. Going back to principals of the equation for a straight line <code>y = mx + c</code> and finding an intersection point of two lines when we only know the <code>vertices</code> (I believe <code>m</code> was missing in my calculations).</li>
</ul>
<p>I will continue playing around with this sketch and see if I can come up with different ideas for more interesting artwork.</p>
<p>💡</p>
<p>If you read this far thank you.</p>
]]>
      </content:encoded>
      <category>p5.js</category>
      <category>generative art</category>
      <pubDate>Sun, 24 Sep 2023 00:00:00 GMT</pubDate>
    </item>
    <item>
      <title>How to use Bun with p5.js</title>
      <link>http://localhost/bun-p5js/</link>
      <guid isPermaLink="false">http://localhost/bun-p5js/</guid>
      <content:encoded>
        <![CDATA[<p>Now that <a href="https://bun.sh/blog/bun-v1.0">Bun 1.0</a> has been released I tried using it with p5.js. I will be writing this post as I go along.</p>
<p>In other posts I've shown how to use <a href="http://localhost/using_parceljs_typescript_p5js/">parcel, typescript and p5js</a> but these required other dependencies to be installed.</p>
<p>I want to try Bun, as you don't need to install anything else other Bun itself.</p>
<blockquote>
<p>Bun is a fast, all-in-one toolkit for running, <strong>building</strong>, testing, and debugging JavaScript and TypeScript, from a single file to a full-stack application.</p>
</blockquote>
<p>After installing I scaffolded a new project</p>
<pre><code class="language-Bash">mkdir p5-project
cd p5-project
bun create .
</code></pre>
<p>As Bun is also a package manager I was able install <code>p5</code>.</p>
<pre><code class="language-Bash">bun install p5 @types/p5
</code></pre>
<p>As Bun has support for TypeScript I also installed <code>@types/p5</code> as I want to still use TS.</p>
<p>Now I created a <code>index.ts</code> file and import <code>p5</code> and created a simple sketch.</p>
<pre><code class="language-TypeScript">import p5 from &quot;p5&quot;;

const sketch = function (p: p5) {
  p.setup = function () {
    p.createCanvas(p.windowWidth, p.windowHeight);
    p.background(&quot;black&quot;);
    p.noLoop();
  };

  p.draw = function () {
    p.strokeWeight(5);
    p.fill(&quot;red&quot;);
    p.rect(p.width / 2, p.height / 2, 100, 100);
  };
};

new p5(sketch);
</code></pre>
<p>To start building I ran the following</p>
<pre><code class="language-Bash">bun build --watch index.ts --outdir ./public
</code></pre>
<p>As of writing this article I'm not able to find a way to start a development server like <code>webpack-dev-server</code> and it seems this will arrive in &quot;next couple of months&quot; with something described as <a href="https://bun.sh/blog/bun-bundler#sneak-peek-bun-app">Bun.App</a>.</p>
<p><a href="https://bun.sh/blog/bun-bundler#sneak-peek-bun-app">The Bun Bundler | Bun Blog</a></p>
<blockquote>
<p>The Bun toolkit gets a new addition. Bun’s fast native bundler is now in beta.</p>
</blockquote>
<p>In the meantime we can use Bun itself to create a small webserver to serve the bundled JavaScript, but first I created a <code>index.html</code> file</p>
<pre><code class="language-HTML">&lt;!doctype html&gt;
&lt;html lang=&quot;en&quot;&gt;

&lt;head&gt;
  &lt;meta charset=&quot;UTF-8&quot; /&gt;
  &lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1.0&quot; /&gt;
  &lt;style&gt;
    body {
      margin: 0;
      height: 100vh;
    }
  &lt;/style&gt;
  &lt;title&gt;Bun &amp; p5js&lt;/title&gt;
&lt;/head&gt;

&lt;body&gt;
  &lt;script type=&quot;module&quot; src=&quot;./src/index.ts&quot;&gt;&lt;/script&gt;
&lt;/body&gt;

&lt;/html&gt;
</code></pre>
<p>index.html</p>
<p>Notice that <code>./src/index.ts</code> won't work as is so I created a <code>devServer.ts</code> that  combines <code>Bun.build</code> with <code>Bun.serve</code> into a single module. It bundles the above code in <code>index.ts</code> and then creates a HTTP server to serve the files.</p>
<p>As Bun uses <code>hash</code> in the naming of the output assests, I had to dynamically replace the <code>src/index.js</code> value in <code>index.html</code> with what Bun generates.</p>
<p>This was possible as <code>Bun.build</code> returns a result object with all assets.</p>
<pre><code class="language-TypeScript">const build = await Bun.build({
  entrypoints: [&quot;./src/index.ts&quot;],
  outdir: &quot;./dist&quot;,
  naming: &quot;[dir]/[name]-[hash].[ext]&quot;,
  sourcemap: &quot;inline&quot;,
});

build.outputs.forEach((i) =&gt; console.log(i.path));

const hash = build.outputs.find((i) =&gt; i.kind == &quot;entry-point&quot;)?.hash;

const inputHtml = Bun.file(&quot;index.html&quot;);
const outputHtml = Bun.file(&quot;dist/index.html&quot;);
let indexHtmlContent = await inputHtml.text();
indexHtmlContent = indexHtmlContent.replace(&quot;src/index.ts&quot;, `index-${hash}.js`);
await Bun.write(outputHtml, indexHtmlContent);

Bun.serve({
  development: true,
  port: 3000, // This is the default
  fetch(req) {
    const path = new URL(req.url).pathname;
    if (path === &quot;/&quot;) {
      return new Response(Bun.file(&quot;./dist/index.html&quot;));
    }

    const file = Bun.file(`dist${path}`);
    return new Response(file);
  },
});

</code></pre>
<p>devServer.ts</p>
<p>Then visiting <code>http://localhost:3000</code> I can see the p5 canvas with a single red rectangle in the center.</p>
<img src="http://localhost/content/images/2023/09/Screenshot-2023-09-12-at-6.29.43-pm.png" srcset="/content/images/size/w600/2023/09/Screenshot-2023-09-12-at-6.29.43-pm.png 600w, /content/images/size/w1000/2023/09/Screenshot-2023-09-12-at-6.29.43-pm.png 1000w, /content/images/2023/09/Screenshot-2023-09-12-at-6.29.43-pm.png 1232w" sizes="(min-width: 720px) 720px, 100vw" width="1232" height="1028" alt="" loading="lazy" decoding="async">
<p>Unfortunately every time I update <code>index.ts</code> I have to restart the <code>devServer.ts</code> as the <code>--watch</code> option only watches for changes in <code>devServer.ts</code>.</p>
<p>There doesn't seem to a config option for <code>Bun.build</code> to watch for changes in files configured in <code>entrypoints</code> to then retrigger build.</p>
<p>I could split <code>Bun.build</code> into a seperate file an run it via <code>bun run --watch build.ts</code> but then I won't have access to the <code>BuildOutput</code> in <code>devServer.ts</code> 🤷</p>
<p>Bun has me excited with the future of the JavaScript ecosystem.</p>
]]>
      </content:encoded>
      <category>p5.js</category>
      <category>javascript</category>
      <category>bun</category>
      <pubDate>Tue, 12 Sep 2023 00:00:00 GMT</pubDate>
    </item>
    <item>
      <title>Why useReducer is better at managing interdependent states</title>
      <link>http://localhost/usestate-vs-usereducer/</link>
      <guid isPermaLink="false">http://localhost/usestate-vs-usereducer/</guid>
      <content:encoded>
        <![CDATA[<p>When working with <a href="https://react.dev/learn/sharing-state-between-components#controlled-and-uncontrolled-components">uncontrolled components</a> that involve multiple interdependent state variables, employing <code>useReducer</code> proves to be a superior approach for managing these states compared to the conventional use of multiple variables created with <code>useState</code>. This method offers greater control, organization and testability when handling complex state interactions.</p>
<p>Interdependent states refer to situations where updating one variable necessitates the update of another. For example, in a Todo app with undo support, deleting a todo requires tracking the deleted todo in another state variable</p>
<p>In such scenarios, using <code>useReducer</code> to centralise the management of interdependent state logic into a single reducer function makes code more predictable, readable and above all easier to test, as it eliminates the need for DOM interactions typically required when dealing with multiple <code>useState</code> variables. It's worth noting that even with <code>useReducer</code>, you can still test components using DOM interactions when necessary.l.</p>
<h2 id="usestate" tabindex="-1"><a href="http://localhost/usestate-vs-usereducer/#usestate" class="header-anchor">useState</a></h2>
<p>To demonstrate lets visit a Todo app that supports adding, deleting and undoing the deletion of the todos. To implement this the code will need three states like so.</p>
<pre><code class="language-typescript">import { useState } from &quot;react&quot;;

const App = () =&gt; {
  const [inputText, setUserInput] = useState(&quot;&quot;);
  const [todoList, setTodoList] = useState([]);
  const [undoHistory, setUndoHistory] = useState([]);
}
</code></pre>
<p>useState</p>
<ul>
<li><code>[inputText, setUserInput]</code> will be used to keep track of the todo text from the <code>&lt;input&gt;</code> field. When the user clicks add (or hits <code>enter</code>) this field will be cleared.</li>
<li><code>[todoList, setTodoList]</code> is used to track the todos as an array.</li>
<li><code>[undoHistory, setUndoHistory]</code> is used to support undo history so when a todo is deleted, the deleted todo will be added here.</li>
</ul>
<p>Let me start by describing the operations needed for adding a new todo;</p>
<ul>
<li>Update the <code>todoList</code> by calling <code>setTodoList([...todoList, {id, text: input}])</code> in which <code>id</code> is unique</li>
<li>Reset input text by calling <code>setUserInput(&quot;&quot;)</code></li>
</ul>
<p>To add a new todo the code has to interact with two state variables to achieve this.</p>
<p>Here is the operations needed when deleting a todo;</p>
<ul>
<li>Find the todo to be deleted from <code>todoList</code></li>
<li>Add this todo to <code>undoHistory</code> by calling <code>setUndoHistory([...undoHistory, todoToBeDeleted])</code></li>
<li>Remove the todo from <code>todoList</code> by calling <code>setTodoList((currentTodos) =&gt; currentTodos.filter((todo) =&gt; todo.id !== id));</code></li>
</ul>
<p>In the complete implementation below, it's evident that every state change operation necessitates updates to two state variables simultaneously. This tight interdependence between state variables underscores the disadvance of using <code>useState</code> as there is higher mental load on the developer to keep track of state.</p>
<iframe src="https://codesandbox.io/embed/usestate-2cx7m4?fontsize=14&amp;hidenavigation=1&amp;module=%2Fsrc%2FApp.tsx&amp;theme=dark&amp;view=editor" style="height:600px; border:0; border-radius: 4px; overflow:hidden;" title="useState" allow="accelerometer; ambient-light-sensor; camera; encrypted-media; geolocation; gyroscope; hid; microphone; midi; payment; usb; vr; xr-spatial-tracking" sandbox="allow-forms allow-modals allow-popups allow-presentation allow-same-origin allow-scripts"></iframe>
<p>To write tests for this implementation, we can utilise React Testing Library to simulate user interactions with the DOM. This includes actions like adding text and submitting the form or clicking the delete and undo buttons, mirroring real user behavior for comprehensive testing.</p>
<h2 id="usereducer" tabindex="-1"><a href="http://localhost/usestate-vs-usereducer/#usereducer" class="header-anchor">useReducer</a></h2>
<p>In the updated Todo application further down, state management is handled through <code>useReducer</code> with the help of a <code>todoReducer.ts</code> file that has the reducer function. The default state for <code>todoReducer</code> comprises three key variables:</p>
<ol>
<li><strong>inputText:</strong> This variable tracks the todo text entered in the <code>&lt;input&gt;</code> field.</li>
<li><strong>todos:</strong> An array that maintains a record of all the todos.</li>
<li><strong>undoHistory:</strong> Another array dedicated to tracking deleted todos.</li>
</ol>
<p>This version provides a clear and concise overview of the state variables managed by <code>todoReducer</code>.</p>
<p>Instead of describing the order of operations for adding a new todo I will describe what the next state is when adding todo.</p>
<ul>
<li><code>inputText</code> is reset to an empty string</li>
<li><code>todos</code> is now updated to include all the current <code>todos</code> and the new one from the <code>action.payload</code></li>
<li><code>undoHistory</code> is the current one from <code>state</code></li>
</ul>
<p>When deleting a todo;</p>
<ul>
<li>find the <code>todo</code> that is to be deleted</li>
<li><code>todos</code> is now all the current todos except the todo to be deleted</li>
<li><code>undoHistory</code> is now the current <code>undoHistory</code> and todo to be deleted.</li>
<li><code>inputText</code> is still the current one from <code>state</code></li>
</ul>
<p>With <code>useReducer</code>, each state update is a single operation, in contrast to the two operations required when using <code>useState</code>. This not only simplifies state management but also streamlines the testing process for <code>todoReducer</code>.</p>
<p>It's a straightforward function that takes the current state and an action as input, returning the next state, making testing in <code>todoReducer.test.ts</code> a straightforward and efficient task</p>
<iframe src="https://codesandbox.io/embed/usereducer-vvh88c?fontsize=14&amp;hidenavigation=1&amp;theme=dark&amp;view=editor?module=%2Fsrc%2FtodoReducer.test.ts" style="height:600px; border:0; border-radius: 4px; overflow:hidden;" title="useReducer" allow="accelerometer; ambient-light-sensor; camera; encrypted-media; geolocation; gyroscope; hid; microphone; midi; payment; usb; vr; xr-spatial-tracking" sandbox="allow-forms allow-modals allow-popups allow-presentation allow-same-origin allow-scripts"></iframe>
<h2 id="conclusion" tabindex="-1"><a href="http://localhost/usestate-vs-usereducer/#conclusion" class="header-anchor">Conclusion</a></h2>
<p>When dealing with uncontrolled components that involve multiple interdependent states, <code>useReducer</code> offers a significantly more manageable approach to state management. Furthermore, it enables the adoption of a Test-Driven Development (TDD) approach, making the development process more structured and efficient.</p>
]]>
      </content:encoded>
      <category>typescript</category>
      <category>react</category>
      <pubDate>Sat, 09 Sep 2023 00:00:00 GMT</pubDate>
    </item>
    <item>
      <title>Using Vuejs with Parcel and p5.js</title>
      <link>http://localhost/using-vuejs-parceljs-p5js/</link>
      <guid isPermaLink="false">http://localhost/using-vuejs-parceljs-p5js/</guid>
      <content:encoded>
        <![CDATA[<p>This is part two of a two part series. In <a href="http://localhost/using_parceljs_typescript_p5js">part one</a> I showed you how you can setup a project using parcel &amp; TypeScript to create <code>p5.js</code> works. I recommend that you read part one first, especially if you’re following along.</p>
<p>Now we’re going to integrate <code>p5.js</code> within a Vue component. Using a framework like Vue will help you create more complex works with p5.js. You can handle application state in <code>vue.js</code> and do routing. I’ve used this in creating a site with multiple p5.js works in which the random seed &amp; the <a href="https://grid-art.bulkan.dev/squiggles?seed=35655&amp;pid=78">selected palette</a> id is updated in the URL so you can permalink to it.</p>
<p>First we start off with the same two files as before <code>index.html</code> and a <code>index.ts</code> but we need to make some changes. First add a new <code>div</code> to the <code>index.html</code>;</p>
<pre><code class="language-html">&lt;html&gt;
&lt;body&gt;
  &lt;div id=“app”&gt;&lt;/div&gt;
  &lt;script src=&quot;./index.ts&quot;&gt;&lt;/script&gt;
&lt;/body&gt;
&lt;/html&gt;
</code></pre>
<p>Then rename <code>index.ts</code> to <code>art.ts</code> and update it like so;</p>
<pre><code class="language-typescript">import p5 from &quot;p5&quot;;

const sketch = function(p: p5) {
  const CELL_COUNT = 20;

  const rect = (x: number, y: number, width: number, color: p5.Color) =&gt; {
    const cellWidth = width / CELL_COUNT; 

    for (let col=0; col&lt;CELL_COUNT; col++) {
      for (let row=0; row&lt;CELL_COUNT; row++) {
        const alpha = p.noise(row, col) * 255;
        color.setAlpha(alpha);
        p.fill(color);
        p.rect(x + cellWidth * row, y + cellWidth * col, cellWidth, cellWidth);
      }
    }
  }

  p.setup = function() {
    p.createCanvas(420, 420);
    p.noLoop();
    p.noStroke();
  };

  p.draw = function() {
    p.background(0);
    const color = p.color('red');
    rect(0, 0, 420, color);
  };
};

export const makeArt = (node: HTMLElement) =&gt; {
  new p5(sketch, node);
}
</code></pre>
<p>We’re exporting a new function <code>makeArt</code> that receives a <code>DOM</code> node (<code>HTMLElement</code>) which we pass to <code>p5</code> along with the <code>sketch</code> function when instantiating. We will call <code>makeArt</code> in the Vue layer.</p>
<p>We have to recreate the <code>index.ts</code>.</p>
<pre><code class="language-typescript">import Vue from 'vue';

new Vue({
  render: createElement =&gt; createElement('h1', 'hello world')
}).$mount('#app');
</code></pre>
<p>You might need to restart the <code>parcel</code> development server via <code>yarn run parcel index.html</code> and you should notice that it will install Vue.</p>
<p>If you navigate to the URL that parcel prints out which is usually http://localhost:1234 you will see the page with the text <code>hello world</code>. Nothing fancy but it means things are working.</p>
<p>Now letscreate a component to help us wrap the p5.js code. Create a file named <code>Art.vue</code> next to <code>index.ts</code>;</p>
<pre><code class="language-typescript">&lt;template&gt;
  &lt;div ref=“canvasOutlet”&gt;&lt;/div&gt;
&lt;/template&gt;

&lt;script&gt;
import Vue from &quot;vue&quot;;
import { makeArt } from &quot;./art.ts&quot;;

export default Vue.extend({
  mounted() {
    setTimeout(() =&gt; makeArt(this.$refs.canvasOutlet));
  }
});
&lt;/script&gt;
</code></pre>
<p>This is creating a Vue component that just renders a <code>div</code> to be used as the DOM node to render the <code>canvas</code> into. We pass a <strong>ref</strong>erence to this all the way down to the <code>p5</code> instantiation. This is done in the <code>mounted</code> lifecycle to make sure the DOM is completely rendered.</p>
<p>We’re not using this component just yet, so lets update <code>index.ts</code> and register the component. The updated file should look like this;</p>
<pre><code class="language-typescript">import Vue from 'vue';
import Art from './Art.vue';

new Vue({
  render: createElement =&gt; createElement(Art)
}).$mount('#app');
</code></pre>
<p>Finally should see the following;</p>
<img src="http://localhost/content/images/2023/08/image.png" srcset="/content/images/size/w600/2023/08/image.png 600w, /content/images/2023/08/image.png 840w" sizes="(min-width: 720px) 720px, 100vw" width="840" height="839" alt="" loading="lazy" decoding="async">
<p>Thats all for this post. Hope this inspires you to experiment.</p>
<p>Thank you for reading.</p>
]]>
      </content:encoded>
      <category>typescript</category>
      <category>vue</category>
      <category>p5.js</category>
      <pubDate>Sun, 23 Aug 2020 00:00:00 GMT</pubDate>
    </item>
    <item>
      <title>Using Parcel, TypeScript with p5.js</title>
      <link>http://localhost/using-parceljs-typescript-p5js/</link>
      <guid isPermaLink="false">http://localhost/using-parceljs-typescript-p5js/</guid>
      <content:encoded>
        <![CDATA[<p>This is part one of a two part series and you can read <a href="http://localhost/using_vuejs_parceljs_p5js">Part two</a>.</p>
<p><a href="http://p5js.org/">p5.js</a> is already great at being able to be used immediately either with the <a href="https://editor.p5js.org/">official editor</a> or loading it in via a <code>&lt;script&gt;</code> tag from a <a href="https://cdnjs.com/libraries/p5.js">cdn</a>.</p>
<p>For more complex projects I find that using a bundler like <a href="https://parceljs.org/">Parcel</a> with TypeScript helps with code organisation. Not to mention all the benefits of having types and modern JavaScript features.</p>
<p>So lets start by installing <a href="https://parceljs.org/">Parcel</a> .</p>
<pre><code class="language-bash">yarn init -y # This just creates a package.json with some defaults.
yarn add parcel-bundler
</code></pre>
<p>I’ve used <a href="https://parceljs.org/getting_started.html">yarn</a> here but you can also use <code>npm</code>.</p>
<p>With parcel we will first need to create an <code>index.html</code> file as a entry point when we run it.</p>
<pre><code class="language-html">&lt;html&gt;
&lt;body&gt;
  &lt;script src=&quot;./index.js&quot;&gt;&lt;/script&gt;
&lt;/body&gt;
&lt;/html&gt;
</code></pre>
<p>The above also references an <code>index.js</code> so create one next to the <code>index.html</code>. Parcel uses the <code>&lt;script&gt;</code> tag within the <code>html</code> file to find the entry point into the JavaScript.</p>
<pre><code class="language-html">document.body.innerHTML = '&lt;b&gt;test&lt;/b&gt;';
</code></pre>
<p>Don’t worry about the contents in the above snippet, we’re going to change it soon.</p>
<p>To run parcel use the following and then open up the url that parcel will output.</p>
<pre><code class="language-bash">yarn run parcel index.html
</code></pre>
<p>You should see something like the following which means we have parcel working.</p>
<img src="http://localhost/content/images/2023/08/image-1.png" width="418" height="136" alt="" loading="lazy" decoding="async">
<p>Now onto p5js. If you’ve ever used p5 or Processing before you will highly likely be familiar with the global API in which all the functions are available globally. In the case of p5 that means it’s on the <code>window</code> object.</p>
<p>With the following approach we will be using what is called the <a href="https://p5js.org/examples/instance-mode-instantiation.html">Instance Mode</a>.</p>
<p>Update your <code>index.js</code> file like so;</p>
<pre><code class="language-typescript">import p5 from 'p5';

let sketch = function(p) {
  let x = 100;
  let y = 100;

  p.setup = function() {
    p.createCanvas(700, 410);
  };

  p.draw = function() {
    p.background(0);
    p.fill(255);
    p.rect(x, y, 50, 50);
  };
};

let myp5 = new p5(sketch);
</code></pre>
<p>Once you save this file you should notice the parcel development server fetch the required dependencies, in this case it should’ve installed p5js and updated <code>package.json</code>.</p>
<p>In addition to the that the page you loaded before should’ve have reloaded and it should look like the following screenshot.</p>
<img src="http://localhost/content/images/2023/08/image-2.png" srcset="/content/images/size/w600/2023/08/image-2.png 600w, /content/images/size/w1000/2023/08/image-2.png 1000w, /content/images/2023/08/image-2.png 1400w" sizes="(min-width: 720px) 720px, 100vw" width="1400" height="818" alt="" loading="lazy" decoding="async">
<p>Lastly to convert this into TypeScript first we need to rename the <code>index.js</code> to <code>index.ts</code> making sure to update the <code>&lt;script&gt;</code> tag in the <code>index.html</code> file.</p>
<p>Afterwards restart the development server. Notice again how <code>parcel</code> installed typescript? There shouldn’t be any visual changes to what is drawn.</p>
<p>Lets create a typed function that redraws the square by dividing it a grid and use <a href="https://www.youtube.com/watch?v=8ZEMLCnn8v0">noise</a> to update the alpha value of each “cell”.</p>
<pre><code class="language-typescript">import p5 from 'p5';

const sketch = function(p) {
  const CELL_COUNT = 4;

  const rect = (x: number, y: number, width: number, color: p5.Color) =&gt; {
    const cellWidth = width / CELL_COUNT; 

    for (let col=0; col&lt;CELL_COUNT; col++) {
      for (let row=0; row&lt;CELL_COUNT; row++) {
        const alpha = p.noise(row, col) * 255;
        color.setAlpha(alpha);
        p.fill(color);
        p.rect(x + cellWidth * row, y + cellWidth * col, cellWidth, cellWidth);
      }
    }
  }

  p.setup = function() {
    p.createCanvas(700, 410);
    p.noLoop();
    p.noStroke();
  };

  p.draw = function() {
    p.background(0);
    const color = p.color('red');
    rect(100, 100, 240, color);
  };
};

const myp5 = new p5(sketch);
</code></pre>
<p>Notice the new <code>rect</code> function? It’s a simple way of dividing a square into rows and columns and then drawing a smaller square.</p>
<p>You should see the squares look like the following now.</p>
<img src="http://localhost/content/images/2023/08/image-3.png" srcset="/content/images/size/w600/2023/08/image-3.png 600w, /content/images/size/w1000/2023/08/image-3.png 1000w, /content/images/2023/08/image-3.png 1398w" sizes="(min-width: 720px) 720px, 100vw" width="1398" height="817" alt="" loading="lazy" decoding="async">
<p>With this setup you can get fast feedback. For example changing the <code>CELL_COUNT</code> to a bigger number like <code>50</code> and updating the canvas size and positioning you can results like this.</p>
<img src="http://localhost/content/images/2023/08/image-4.png" srcset="/content/images/size/w600/2023/08/image-4.png 600w, /content/images/2023/08/image-4.png 840w" sizes="(min-width: 720px) 720px, 100vw" width="840" height="839" alt="" loading="lazy" decoding="async">
<p>That is all for now. You can download a zip file of this <a href="http://localhost/efe7990579027ba4f94546a28959a79d/p5-parcel-typescript.zip">here</a>.</p>
<p>You can also read <a href="http://localhost/using_vuejs_parceljs_p5js">part two here</a>.</p>
]]>
      </content:encoded>
      <pubDate>Mon, 10 Aug 2020 00:00:00 GMT</pubDate>
    </item>
    <item>
      <title>Photo a day challenge - Two months</title>
      <link>http://localhost/photo-a-day-challenge-two-months/</link>
      <guid isPermaLink="false">http://localhost/photo-a-day-challenge-two-months/</guid>
      <content:encoded>
        <![CDATA[<p>Another year and another attempt at this challenge. Today was the 63rd day of taking photos 63 days consecutively.</p>
<p>When I had attempted this challenge last year with my X100T, I struggled during the autumn and winter periods because Melbourne is in two states; bone dry cold with gale force winds or pouring down rain. My excuse for not going out was that my X100T wasn’t weather sealed.</p>
<p>Well this year I have two secret weapons; a weather sealed X-T2 and the <a href="https://www.photoblog.com/learn/365-shooting-prompt-challenge-2017">PhotoBlog365 calendar</a>.</p>
<p>So far, I have enjoyed capturing a nice summer with blue skies. I’m glad to say that the first two months has been a very productive and creative in my photography.</p>
<p>The theme calendar has been very helpful for those days in which I’ve gone out during my lunch break with no idea on what to shoot. The daily themes have become that tiny spark in triggering my the creative thinking.</p>
<p>For example the following photo was taken on day 18 in which the theme was <code>C is for...</code> and in Melbourne C is for Coffee;</p>
<blockquote>
<p>[</p>
<p>View this post on Instagram</p>
<p>](https://www.instagram.com/p/BPbmvS6BaYg/?utm_source=ig_embed&amp;utm_campaign=loading)</p>
<p><a href="https://www.instagram.com/p/BPbmvS6BaYg/?utm_source=ig_embed&amp;utm_campaign=loading">A post shared by bulks (@bulks.e)</a></p>
</blockquote>
<p>On the other hand I’ve struggled to find the time to get out of the office. As a full time worker, the only free time I have is during my lunch breaks. This means that I can’t venture out too far away, as I need to get back in time. Thus I keep walking the same places/streets and finding interesting compositions has been really difficult.</p>
<p>Some days I feel like I’ve cheated by taking shots with low depth of field at f1.4 on my XF-16mm. Does this show that, technically I’ve learnt what will make an interesting picture ?</p>
<blockquote>
<p>[</p>
<p>View this post on Instagram</p>
<p>](https://www.instagram.com/p/BP1Wr83lKit/?utm_source=ig_embed&amp;utm_campaign=loading)</p>
<p><a href="https://www.instagram.com/p/BP1Wr83lKit/?utm_source=ig_embed&amp;utm_campaign=loading">A post shared by bulks (@bulks.e)</a></p>
</blockquote>
<h2 id="challenge-yourself" tabindex="-1"><a href="http://localhost/photo-a-day-challenge-two-months/#challenge-yourself" class="header-anchor"><strong>Challenge yourself</strong></a></h2>
<p>There is a reason why its called the 365 day <strong>challenge</strong>. It’s hard to take an interesting photo everyday to share with the world. To challenge myself further I’m not using the ACROS film simulation on the X-T2 or converting my photos to black and white.</p>
<blockquote>
<p>[</p>
<p>View this post on Instagram</p>
<p>](https://www.instagram.com/p/BPJlQG6BjQW/?utm_source=ig_embed&amp;utm_campaign=loading)</p>
<p><a href="https://www.instagram.com/p/BPJlQG6BjQW/?utm_source=ig_embed&amp;utm_campaign=loading">A post shared by bulks (@bulks.e)</a></p>
</blockquote>
<p>Also, as a night owl, I find it hard to wake up early and to keep the ‘challenge yourself’ going I made it one of my goals to wake up before sunrise to catch the golden hour.</p>
<p>That being said I’m not a morning person yet and I need to do more of this.</p>
<blockquote>
<p>[</p>
<p>View this post on Instagram</p>
<p>](https://www.instagram.com/p/BPAN0N3B9hN/?utm_source=ig_embed&amp;utm_campaign=loading)</p>
<p><a href="https://www.instagram.com/p/BPAN0N3B9hN/?utm_source=ig_embed&amp;utm_campaign=loading">A post shared by bulks (@bulks.e)</a></p>
</blockquote>
<h2 id="don%E2%80%99t-do-too-many-things" tabindex="-1"><a href="http://localhost/photo-a-day-challenge-two-months/#don%E2%80%99t-do-too-many-things" class="header-anchor"><strong>Don’t do too many things</strong></a></h2>
<p>I need to just go out to take a photo and try not to hit two birds with one stone. Some days I will have errands to run during my lunch break, which eats into my photo time giving less time to look around for amazing compositions.</p>
<h2 id="street-photography" tabindex="-1"><a href="http://localhost/photo-a-day-challenge-two-months/#street-photography" class="header-anchor"><strong>Street photography</strong></a></h2>
<p>I find that taking pictures of people walking along the street and making them interesting is hard. The resulting images feel like they’re not telling any story. There are already plenty of photos out there of people looking angry because someone is taking their photo.</p>
<p>The way I’ve used people in my pictures has been as a secondary element using them as motion.</p>
<blockquote>
<p>[</p>
<p>View this post on Instagram</p>
<p>](https://www.instagram.com/p/BPB2zgcBUqS/?utm_source=ig_embed&amp;utm_campaign=loading)</p>
<p><a href="https://www.instagram.com/p/BPB2zgcBUqS/?utm_source=ig_embed&amp;utm_campaign=loading">A post shared by bulks (@bulks.e)</a></p>
</blockquote>
<h2 id="forcing-creativity" tabindex="-1"><a href="http://localhost/photo-a-day-challenge-two-months/#forcing-creativity" class="header-anchor"><strong>Forcing creativity</strong></a></h2>
<p>There has been a few days in which I’ve left the whole taking a photo a day challenge to the very end of the day.</p>
<p>Creativity takes time ! I need to stop doing this.</p>
<blockquote>
<p>[</p>
<p>View this post on Instagram</p>
<p>](https://www.instagram.com/p/BRF5S1oDRxo/?utm_source=ig_embed&amp;utm_campaign=loading)</p>
<p><a href="https://www.instagram.com/p/BRF5S1oDRxo/?utm_source=ig_embed&amp;utm_campaign=loading">A post shared by bulks (@bulks.e)</a></p>
</blockquote>
<p>63 days down only 302 days to go.</p>
]]>
      </content:encoded>
      <category>photography</category>
      <pubDate>Sat, 18 Feb 2017 00:00:00 GMT</pubDate>
    </item>
    <item>
      <title>Broccoli and Angular.js</title>
      <link>http://localhost/broccoli-and-angularjs/</link>
      <guid isPermaLink="false">http://localhost/broccoli-and-angularjs/</guid>
      <content:encoded>
        <![CDATA[<h3 id="warning" tabindex="-1"><a href="http://localhost/broccoli-and-angularjs/#warning" class="header-anchor"><strong>Warning</strong></a></h3>
<p>This post was initially written on 2014-05-28 and not published. Things will have changed.</p>
<p><a href="https://www.solitr.com/blog/2014/02/broccoli-first-release/">Broccoli</a> is a relatively new asset builder. It is based on doing operations on a trees of files.</p>
<p>Here is how I used it to concatenate front end dependencies installed via bower and an angular.js app.</p>
<p><strong>Bower</strong></p>
<p>First, let me show you the two files you need for bower.</p>
<h3 id="bower.json" tabindex="-1"><a href="http://localhost/broccoli-and-angularjs/#bower.json" class="header-anchor">bower.json</a></h3>
<p>Here is an example <code>bower.json</code> that lists the frontend dependencies. Note the <code>resolutions</code> property.</p>
<pre><code class="language-json">{
  &quot;dependencies&quot;: {
    &quot;angular-ui-router&quot;: &quot;0.2.11&quot;,
  },
  &quot;resolutions&quot;: {
    &quot;angular&quot;: &quot;~1.3.0&quot;
  }
}
</code></pre>
<h2 id=".bowerrc" tabindex="-1"><a href="http://localhost/broccoli-and-angularjs/#.bowerrc" class="header-anchor"><strong>.bowerrc</strong></a></h2>
<p>This is relative to your project and tells bower where to put the dependencies.</p>
<pre><code class="language-json">{
    &quot;directory&quot;: &quot;public/vendor&quot;
}
</code></pre>
<h2 id="broccoli" tabindex="-1"><a href="http://localhost/broccoli-and-angularjs/#broccoli" class="header-anchor"><strong>Broccoli</strong></a></h2>
<p>Now we need to install broccoli. I’ve installed the <code>broccoli-cli</code> globally and as per the <a href="https://github.com/broccolijs/broccoli#installation">installation guide</a>.</p>
<pre><code class="language-bash">npm install --save-dev broccoli
npm install --global broccoli-cli
</code></pre>
<p>We also need to install plugins for broccoli;</p>
<p><code>npm install --saveDev broccoli-concat</code></p>
<h2 id="brocfile.js" tabindex="-1"><a href="http://localhost/broccoli-and-angularjs/#brocfile.js" class="header-anchor"><strong>Brocfile.js</strong></a></h2>
<p>Like all <strong>task</strong> runners broccoli has its own file format to define its operations, though its not really a <strong>task</strong> runner but rather a build tool.</p>
<p>Here is the <code>brocfile.js</code> to concatenate all of the above bower dependencies</p>
<pre><code class="language-javascript">var broccoli = require('broccoli');
var concat = require('broccoli-concat');

var concatenated = concat('public/',  {
  inputFiles: [
    'vendor/jquery/jquery.min.js',
    'vendor/angular/angular.js',
    'vendor/angular-ui-router/release/angular-ui-router.min.js',
    'js/**/*.js',
  ],
  outputFile: '/assets/app.js',
  separator: '\n', // (optional, defaults to \n)
  wrapInEval: false // (optional, defaults to false)
});

module.exports = concatenated;
</code></pre>
<p>We explicitly define the order of concatenation to the <code>concat</code> function. This way we have jQuery loading before angular, and angular loading before ui-router and our app code (which is assumed to exist in <code>public/js</code>).</p>
<p>Now running <code>broccoli serve</code> will start a http server on port 4200 and the concatenated Javascript will be available at <strong>https://localhost:4200/assets/app.js</strong>.</p>
<p>Hope that helps.</p>
]]>
      </content:encoded>
      <category>javascript</category>
      <pubDate>Tue, 16 Feb 2016 00:00:00 GMT</pubDate>
    </item>
    <item>
      <title>Using Bluebird With Angular Protractor</title>
      <link>http://localhost/using-bluebird-with-angular-protractor/</link>
      <guid isPermaLink="false">http://localhost/using-bluebird-with-angular-protractor/</guid>
      <content:encoded>
        <![CDATA[<h2 id="async-control-flow" tabindex="-1"><a href="http://localhost/using-bluebird-with-angular-protractor/#async-control-flow" class="header-anchor"><strong>Async control flow</strong></a></h2>
<p>There are few places where you would want to use a promise. Protractor supports Promises in the <code>onPrepare</code> function but the <a href="https://github.com/angular/protractor/blob/master/spec/onPreparePromiseConf.js">example</a> uses Q.</p>
<p>That example <code>onPrepare</code> written using Bluebird looks like this;</p>
<pre><code class="language-javascript">var Promise = require('bluebird');

onPrepare: function(){
  return Promise.delay(2000);
    .then(function(){
      browser.params.password = '12345';
    });
}
</code></pre>
<p>A better example is that the <code>onPrepare</code> function can be used to perform some async setup task like creating a fake User in your database to be able to login.</p>
<pre><code class="language-javascript">var User = require('./models/User');

onPrepare: function() {
  // returns a Promise
  return User.create({
    username: 'bulkan',
    password': 'igotdis'
  });
}
</code></pre>
<h3 id="test-structure" tabindex="-1"><a href="http://localhost/using-bluebird-with-angular-protractor/#test-structure" class="header-anchor"><strong>Test structure</strong></a></h3>
<p>Protractor uses <a href="https://github.com/juliemr/minijasminenode">Jasmine 1.3</a> and has updated it to <a href="https://angular.github.io/protractor/#/control-flow">automatically resolve Promises</a>.</p>
<pre><code class="language-javascript">describe('Home page', function(){
  it('should have username input', function(){
    var username = element(by.css('#username'));
    expect(username.getText()).not.toBeNull();
  });
});
</code></pre>
<p><code>expect</code> automatically resolves the Promise so there is no need to do the following</p>
<pre><code class="language-javascript">username.getText().then(function(text){
    expect(text).toEqual('bulkan');
});
</code></pre>
<p>Here is another example test that will verify that the home page is rendering Post titles. This time we have to chain onto the <code>.then</code> of the Promises.</p>
<pre><code class="language-javascript">var Promise = require('bluebird');
var Posts = require('./models/Posts');

describe('Home Page', function(){
  it('should have a list of posts', function(done){
    browser.get('/');

    var posts = element(by.repeater('post in posts').column('post.title'));

    Promise.cast(posts.map(function(elm){
        return elm.getInnerHtml();
    }))
    .then(function(titles){
        return titles.sort();
    })
    .then(function(titles){
        return Posts.findAll({attributes: 'title', order: 'title'})
          .tap(function(_titles){
            expect(titles).toEqual(_titles);
          })
    })
    .nodeify(done);
  });
});
</code></pre>
<p>We need to <code>Promise.cast</code> the <code>posts.map</code> as we call <code>.nodeify</code> which is a bluebird function. <code>nodeify</code> helps simplify tests by not needing to explicitly call <code>done</code> in the last <code>then</code> and in a <code>catch</code></p>
<p>Jasmine supports asynchronous tests by passing in a callback function to an <code>it</code>, just like in Mocha. In the test above we find elements by the repeater. The template used might look like;</p>
<pre><code class="language-angularjs">&lt;div ng-repeat=&quot;post in posts&quot;&gt;
    &lt;h1&gt; {{::post.title}} &lt;/h1&gt;
&lt;/div&gt;
</code></pre>
<p>There might be an easier/simpler way to do this so please do let me know by commenting below.</p>
]]>
      </content:encoded>
      <category>javascript</category>
      <pubDate>Tue, 11 Nov 2014 00:00:00 GMT</pubDate>
    </item>
    <item>
      <title>Using Express Router instead of express-namespace</title>
      <link>http://localhost/using-express-router-instead-of-express-namespace/</link>
      <guid isPermaLink="false">http://localhost/using-express-router-instead-of-express-namespace/</guid>
      <content:encoded>
        <![CDATA[<p>express 4.0 has been out for a while and it seems people are still using <a href="https://www.npmjs.org/package/express-namespace">express-namespace</a>. According to npm it had 183 downloads on the 8th of June.</p>
<p>express-namespace hasnt been updated in nearly two years and it can now be replaced with the Router that comes with express 4.</p>
<p>Also I’ve found that the middleware mounting on namespace roots would mount it at the the application level. This is else that the router solves as it allows you to seperate out <strong>routes</strong> into different modules with its own middleware.</p>
<p>Here is the example from express-namespace written using the Router in express 4.0.</p>
<pre><code class="language-javascript">var express = require('express'),
    forumRouter = express.Router(),
    threadRouter = express.Router(),
    app = express();

forumRouter.get('/:id/((view)?)', function(req, res){
  res.send('GET forum ' + req.params.id);
});

forumRouter.get('/:id/edit', function(req, res){
  res.send('GET forum ' + req.params.id + ' edit page');
});


forumRouter.delete('/:id', function(req, res){
  res.send('DELETE forum ' + req.params.id);
});

app.use('/forum', forumRouter);

threadRouter.get('/:id/thread/:tid', function(req, res){
  res.send('GET forum ' + req.params.id + ' thread ' + req.params.tid);
});

forumRouter.use('/', threadRouter);

app.listen(3333);
</code></pre>
<p>A little bit more typing but easier to explain to others and no monkey patching weirdness of express-namespace.</p>
<p>The routes are more little more explicitly defined.</p>
<p>Hope this helps.</p>
]]>
      </content:encoded>
      <category>javascript</category>
      <pubDate>Thu, 09 Oct 2014 00:00:00 GMT</pubDate>
    </item>
    <item>
      <title>Writing a Linked List using Go - part one</title>
      <link>http://localhost/writing-a-linked-list-using-go-part-one/</link>
      <guid isPermaLink="false">http://localhost/writing-a-linked-list-using-go-part-one/</guid>
      <content:encoded>
        <![CDATA[<p>In this article series I will briefly talk about Linked Lists then go about implementing one using <a href="https://golang.org/">Go</a>. This is both a learning exercise for me to get comfortable using Go and to possibly help other developers transition into becoming a Go programmer. That being said please bear in mind I am still learning Go so excuse the code.</p>
<p>Also, Go already has a <a href="https://golang.org/pkg/container/list/">linked list</a> implemented so better use that in your production code.</p>
<p>Lets begin with a quick refresher on linked lists and for a more detailed analysis read this <a href="https://cslibrary.stanford.edu/103/LinkedListBasics.pdf">PDF</a> by Stanford University.</p>
<p>That being said have a look at the following diagram.</p>
<img src="http://localhost/static/238b5401b53f17c2ddd22ef560ff9631/876a9/ll.jpg" width="2926" height="780" alt="" loading="lazy" decoding="async">
<p>A linked list is a simple data structure that is used as the basis for other complex data structures. They are comprised of <em>nodes</em> each containing some <em>data</em> field and a reference field to the next node in the list. In the diagram above our nodes contain an integer field as the data. With this information let us write out the code for a node.</p>
<p>If we were using an Object Oriented language like Python then we could just create a class to represent the node. But Go is a procedural language and it does not have classes. That being said it does have a something similar called <a href="https://golang.org/ref/spec#Struct_types">struct type</a> which we can use to encapsulate the fields of a node.</p>
<pre><code class="language-go">type node struct {
    data int
    next *node
}
</code></pre>
<p>Here we define a new struct with a <code>data</code> field of type <code>int</code>. The <code>next</code> field has a type of a <code>pointer to a node</code>. Remember pointers store the memory address of the type it is pointing too.</p>
<p>Next up we, need to write the functions to insert and remove nodes into the list. Like I wrote previously Go does not have classes hence you would assume that there wont be methods, but you would be surprisingly wrong. Go has a feature of being able to associate functions with structs <a href="https://gobyexample.com/methods">methods</a>.</p>
<p>Here is what I mean.</p>
<h2 id="edit" tabindex="-1"><a href="http://localhost/writing-a-linked-list-using-go-part-one/#edit" class="header-anchor">EDIT</a></h2>
<p>Ive simplified the <code>AddToHead</code> method</p>
<pre><code class="language-go">type LinkedList struct {
    head *node
}

func (ll *LinkedList) AddToHead(data int) {
    ll.head = &amp;node{data: data, next: ll.head}
}
</code></pre>
<p>We first create a new struct with a field that is the pointer to the beginning of the linked list. All linked lists need this first reference to able to do any operations on it.</p>
<p>Then we create a method called <code>AddToHead</code> and associate it with the <code>LinkedList</code> struct. This method will create a <code>node</code> with the <code>data</code> that is passed in and then add this node to head of the list. What happens;</p>
<ul>
<li>when the list is empty ?</li>
<li>when there is at least one node in the list (its not a empty list) ?</li>
</ul>
<p>We handle the first case by checking if the head of the list <code>ll.head</code> is <code>nil</code> which is the <a href="https://golang.org/doc/effective_go.html#allocation_new">zeroed</a> value for a pointer in Go. If <code>ll.head</code> is <code>nil</code> we can just assign <code>ll.head</code> to our <code>tmp</code> node.</p>
<p>If <code>ll.head</code> is not <code>nil</code> we have at least one node in the linked list so we cant just just assign <code>tmp</code> to <code>ll.head</code> as we would lose the references to the rest of the linked list and all of the data. First we have to set the <code>tmp</code> nodes <code>next</code> reference to <code>ll.head</code> to not lose this reference, then reassign <code>ll.head</code> to <code>tmp</code>.</p>
<p>I hope this makes sense. Ive pushed this code onto a repository on GitHub called <a href="https://github.com/bulkan/goll">goll</a>. Once you clone the repository run the following command to checkout the branch containing the code in this article.</p>
<p><code>git checkout -b part_one</code></p>
<p>Once this is branch is checked out look at the tests in <code>ll_test.go</code></p>
<p>In the next post we will look at removing nodes from our linked list and possibly adding another method to insert in sort order.</p>
]]>
      </content:encoded>
      <pubDate>Sat, 31 May 2014 00:00:00 GMT</pubDate>
    </item>
  </channel>
</rss>