<?xml version="1.0" encoding="UTF-8" standalone="no"?><rss xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:itunes="http://www.itunes.com/dtds/podcast-1.0.dtd" xmlns:media="http://search.yahoo.com/mrss/" version="2.0"><channel><title>GuyDotDev</title><description>Work. Life. Code. Game. Lather. Rinse. Repeat.</description><link>https://guy.dev</link><language>en-us</language><item><title>A First Look at Vector Sets</title><link>https://guy.dev/2025/04/15/a-first-look-at-vector-sets</link><guid isPermaLink="true">https://guy.dev/2025/04/15/a-first-look-at-vector-sets</guid><pubDate>Tue, 15 Apr 2025 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Last week, &lt;a href="https://redis.io/blog/announcing-vector-sets-a-new-redis-data-type-for-vector-similarity/"&gt;Redis announced vector sets&lt;/a&gt;—a new data structure coming in Redis 8. They also released &lt;a href="https://hub.docker.com/_/redis"&gt;Redis 8 RC1&lt;/a&gt;, which means we get to play with this new feature right now. And that's exactly what we're going to do!&lt;/p&gt;
&lt;p&gt;We’ll explore vector sets through a real-world example: a user’s photo album. I picked this example because it shows off where vector sets really shine. Why does it work so well? Stick around to the end to find out.&lt;/p&gt;
&lt;h1&gt;Before We Get Started&lt;/h1&gt;
&lt;p&gt;Two big caveats before we dive into the details:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Even though they are part of Redis 8, &lt;em&gt;vector sets are in beta&lt;/em&gt;. They could change or even be removed from future versions of Redis. So, think about that before you ship code to production.&lt;/li&gt;
&lt;li&gt;This post isn't intended to be an introduction to vectors, vector search, and embeddings. I'm going to assume that you have at least an inkling of what these things are. If you don't, watch &lt;a href="https://www.youtube.com/watch?v=Ybva5RiRBKQ"&gt;this talk&lt;/a&gt; that I gave at &lt;a href="https://www.jfokus.se/"&gt;Jfokus&lt;/a&gt; where I explain it in detail.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Disclaimer delivered. Now, on with the fun!&lt;/p&gt;
&lt;h1&gt;What's a Vector Set?&lt;/h1&gt;
&lt;p&gt;A vector set is a lot like other sets in Redis like the &lt;a href="https://redis.io/docs/latest/develop/data-types/sorted-sets/"&gt;sorted set&lt;/a&gt; or the &lt;a href="https://redis.io/docs/latest/develop/data-types/sets/"&gt;plain old set&lt;/a&gt;. However, a vector set contains labeled points in a multi-dimensional space—think X-Y coordinates but with more axes. The labels themselves are just simple strings. The points are a series of numbers—the coordinates in the multi-dimensional space. These numbers &lt;em&gt;are&lt;/em&gt; the vector.&lt;/p&gt;
&lt;p&gt;I can add vectors to a vector set using the &lt;a href="https://redis.io/docs/latest/commands/vadd/"&gt;VADD&lt;/a&gt; command. In this example I'm adding 512-dimensional embeddings of photos for a user named Alice. The &lt;code&gt;photoId&lt;/code&gt; is being used as the label and the &lt;code&gt;embedding&lt;/code&gt; returned from the call to &lt;code&gt;embedPhoto&lt;/code&gt; are the vector:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-typescript"&gt;async function addPhotoToVectorSet(userId: string, photoId: string, pathToPhoto: string) {
  const embedding: number[] = await embedPhoto(pathToPhoto)
  const key = `user:${userId}:photos`
  const values: string[] = embedding.map(v =&amp;gt; v.toString())
  const dims = embedding.length.toString()

  await redis.sendCommand(['VADD', key, 'VALUES', dims, ...values, photoId])
}

await addPhotoToVectorSet('alice', 'photo:42', '/photos/IMG_0042.png')
await addPhotoToVectorSet('alice', 'photo:23', '/photos/IMG_0023.png')
await addPhotoToVectorSet('alice', 'photo:13', '/photos/IMG_0013.png')
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Note that I am using TypeScript here and &lt;a href="https://github.com/redis/node-redis"&gt;Node Redis&lt;/a&gt;, but this should translate nicely to whatever tool you're using. Vector sets are so bleeding edge that the client libraries don't even support them yet. So, we have to use the lower-level &lt;code&gt;.sendCommand()&lt;/code&gt; function which accepts a &lt;code&gt;string[]&lt;/code&gt;. Your client library of choice will have some variation of this.&lt;/p&gt;
&lt;p&gt;Also, the &lt;code&gt;.embedPhoto()&lt;/code&gt; function is, effectively, pseudocode. Your magic embedding code goes in there. If you want to take a peek at that magic, check out my &lt;a href="https://github.com/guyroyse/modern-problems-require-modern-solutions"&gt;meme twin finding example&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;So, a vector set is—surprise—a set of vectors. In most real-world use cases, those vectors will be embeddings, like the ones you’d generate from an image, a chunk of text, or even audio.&lt;/p&gt;
&lt;h1&gt;Using a Vector Set&lt;/h1&gt;
&lt;p&gt;Once you have vectors in a vector set, you can manipulate them:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-typescript"&gt;const key = `user:${userId}:photos`

// removes a photo from the set
await redis.sendCommand(['VREM', key, 'photo:42'])

// the cardinality of the set
await redis.sendCommand(['VCARD', key])

// the number of dimensions the vectors in the set have, 512 in our case
await redis.sendCommand(['VDIM', key])
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This isn't exactly complex code—it just invokes the commands and the comment tells you what they do. There are lots of &lt;em&gt;other&lt;/em&gt; commands as well. The full details for all of them are in &lt;a href="https://redis.io/docs/latest/develop/data-types/vector-sets/"&gt;the docs&lt;/a&gt; which I encourage you to peruse.&lt;/p&gt;
&lt;p&gt;The command at the heart of vector sets is &lt;a href="https://redis.io/docs/latest/commands/vsim/"&gt;VSIM&lt;/a&gt;—it lets you search for vectors that are the most similar to a provided one. There are two main ways that you provide one—by value and by element.&lt;/p&gt;
&lt;p&gt;Providing a vector &lt;em&gt;by value&lt;/em&gt; is simply providing the vector as part of the command to Redis. This is the classic semantic search use case:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-typescript"&gt;async function searchPhotos(userId: string, query: string): string[] {
  const embedding: number[] = await embedText(query)
  const key = `user:${userId}:photos`
  const dims = embedding.length.toString()
  const values: string[] = embedding.map(v =&amp;gt; v.toString())

  return await redis.sendCommand(['VSIM', key, 'VALUES', dims, ...values, 'COUNT', '3'])
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Providing a vector &lt;em&gt;by element&lt;/em&gt; is just using an existing vector in the vector set, referenced by its label. This is more of a recommendation pattern:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-typescript"&gt;async function similarPhotos(userId: string, photoId: string) {
  const key = `user:${userId}:photos`
  return await redis.sendCommand(['VSIM', key, 'ELE', photoId, 'COUNT', '3'])
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And, you can see how these might work nicely together:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-typescript"&gt;// returns photos matching the query
const foundPhotoIds: string[] = await searchPhotos('alice', 'Show me pictures of animals')

// returns photos similar to the first found photo
const firstFoundPhotoId = foundPhotoIds[0]
const similarPhotos: string[] = await similarPhotos('alice', firstFoundPhotoId)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And that's pretty much it for the code - at least enough for you to get started.&lt;/p&gt;
&lt;h1&gt;So What?&lt;/h1&gt;
&lt;p&gt;So, what's the big deal? I could do all of this with the &lt;a href="https://redis.io/docs/latest/develop/interact/search-and-query/"&gt;Redis Query Engine&lt;/a&gt;, right?&lt;/p&gt;
&lt;p&gt;Absolutely—and in many cases, Redis Query Engine is still the right choice. It supports hybrid search, rich document indexing, and can scale across shards in a Redis cluster. If you're doing full-text search, filtering on structured data, and searching across millions of vectors, Redis Query Engine is the way to go.&lt;/p&gt;
&lt;p&gt;Vector sets offer something different. They're simpler, easier to work with, and perfect for use cases where data is naturally scoped—to a user, a device, a region, or a moment in time. You don’t need to define a schema. You don’t need to manage an index. You just add vectors and search them.&lt;/p&gt;
&lt;p&gt;Of course, this simplicity comes with trade-offs. Vector sets are all about the vector—that’s their focus. It’s in the name!. You won’t get rich document indexing or hybrid queries. &lt;a href="https://redis.io/docs/latest/develop/data-types/vector-sets/filtered-search/"&gt;JSON-based filtering&lt;/a&gt; is supported, but it’s not as flexible as what Redis Query Engine provides. And &lt;a href="https://redis.io/docs/latest/develop/data-types/vector-sets/scalability/"&gt;scaling across a cluster&lt;/a&gt;? Absolutely possible, but you’ll have to manage that in code yourself.&lt;/p&gt;
&lt;p&gt;So while there’s overlap in what you can build, the way you build it—and the trade-offs you make—are different. It’s not about better or worse. It’s about using the right tool for the job.&lt;/p&gt;
&lt;h1&gt;Conclusion&lt;/h1&gt;
&lt;p&gt;If your application needs rich filtering, hybrid search, and global indexing, Redis Query Engine is the clear choice. But if you're building lightweight, fast, and highly scoped similarity search—especially for things like user-specific data or ephemeral sessions—vector sets can be a great fit.&lt;/p&gt;
&lt;p&gt;That’s why the photo album example works so well. Each user has their own vector set, which naturally avoids clustering issues and performance bottlenecks. You can quickly find similar photos, search by description, and build real-time recommendations—all without the overhead of Redis Query Engine.&lt;/p&gt;
&lt;p&gt;Vector sets are still in beta, but they’re already looking like a powerful addition to the Redis toolbox. I’m definitely going to keep tinkering—seeing where they work and where they don’t.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;Got ideas? Weird use cases? Built something cool? If you have, tag me on &lt;a href="https://bsky.app/profile/guy.dev"&gt;Bluesky&lt;/a&gt;, &lt;a href="https://www.linkedin.com/in/groyse/"&gt;LinkedIn&lt;/a&gt;, or &lt;a href="https://x.com/guyroyse"&gt;X&lt;/a&gt;. I’d love to see what you're doing with vector sets.&lt;/p&gt;
</content:encoded><media:thumbnail>https://guy.dev/images/photomosaic.jpg</media:thumbnail><author>guy@guyroyse.com (Guy Royse)</author></item><item><title>Finding Bigfoot with Async Generators + TypeScript</title><link>https://guy.dev/2025/04/01/finding-bigfoot-with-async-generators-and-typescript</link><guid isPermaLink="true">https://guy.dev/2025/04/01/finding-bigfoot-with-async-generators-and-typescript</guid><pubDate>Tue, 01 Apr 2025 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Lately, I've been messing about with generators—of the synchronous and asynchronous varieties—using TypeScript. They're not something I've used much and I thought it'd be a good idea to get a little more well acquainted with them. And, of course, I like to share what I learn. So, let's commence with the sharing.&lt;/p&gt;
&lt;h1&gt;Generators in TypeScript&lt;/h1&gt;
&lt;p&gt;Generators are special functions that generate a sequence of values and return &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Iterator"&gt;iterators&lt;/a&gt;. For stand-alone functions, you define them by putting a &lt;code&gt;*&lt;/code&gt; immediately after the &lt;code&gt;function&lt;/code&gt; keyword. For functions in a class, including static ones, you put it right before the function name itself.&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-typescript"&gt;function* someNumbers(): Generator&amp;lt;number&amp;gt; {...}

class NumberGenerators {
  static *someNumbers(): Generator&amp;lt;number&amp;gt; {...}
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Generators then return data using the &lt;code&gt;yield&lt;/code&gt; keyword.&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-typescript"&gt;function* someNumbers(): Generator&amp;lt;number&amp;gt; {
  yield 1
  yield 2
  yield 3
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;You can then access these values just like any iterator by looping calls to &lt;code&gt;.next()&lt;/code&gt; or by using a &lt;code&gt;for...of&lt;/code&gt; loop.&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-typescript"&gt;const generator = someNumbers()

while (true) {
  const { value, done } = generator.next()
  if (done) break
  console.log(value)
}

for (const value of someNumbers()) {
  console.log(value)
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now, this might not sound all that interesting as, after all, you could do this by simply returning an array. However, the magic is in that &lt;code&gt;yield&lt;/code&gt; keyword. A generator isn't actually executed until you—or your &lt;code&gt;for...of&lt;/code&gt; loop—calls &lt;code&gt;.next()&lt;/code&gt;. Once you—or it—does, the code runs right up to the &lt;code&gt;yield&lt;/code&gt; statement, returns the value, and then pauses the execution until the next call to &lt;code&gt;.next()&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Generators don't have to end. They can just keep on going forever. For example, you could create a generator that returns numbers from 1 to infinity and just call &lt;code&gt;.next()&lt;/code&gt; until you're sick of it. Or, you can use a &lt;code&gt;for...of&lt;/code&gt; to create an infinite loop.&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-typescript"&gt;function* allNumbers(): Generator&amp;lt;number&amp;gt; {
  let i = 0
  while (true) yield i++
}

for (const value of allNumbers()) {
  console.log(value)
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h1&gt;Asynchronous Generators&lt;/h1&gt;
&lt;p&gt;Generators can also be asynchronous. This means that instead of yielding values they yield &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise"&gt;Promises&lt;/a&gt;. To make an asynchronous generator just mark your generator functions as &lt;code&gt;async&lt;/code&gt; and &lt;code&gt;yield&lt;/code&gt; Promises.&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-typescript"&gt;async function* allAsyncNumbers(): AsyncGenerator&amp;lt;number&amp;gt; {
  let i = 0
  while (true) yield Promise.resolve(i++)
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;To consume them, you can either call &lt;code&gt;.next()&lt;/code&gt; and &lt;code&gt;await&lt;/code&gt; the &lt;code&gt;Promise&lt;/code&gt; or use a &lt;code&gt;for await...of&lt;/code&gt; loop and not think about promises. Personally, I'm a fan of the latter.&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-typescript"&gt;const generator = allAsyncNumbers()
while (true) {
  const { value, done } = await generator.next()
  if (done) break
  console.log(value)
}

for await (const value of allAsyncNumbers()) {
  console.log(value)
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h1&gt;Doing Something Allegedly Useful&lt;/h1&gt;
&lt;p&gt;Of course, these examples are just toys. A more proper use for asynchronous generators is handling things like reading files, accessing network services, and calling slow running things like AI models. So, I'm going to use an asynchronous generator to access a networked service. That service is &lt;a href="https://redis.io"&gt;Redis&lt;/a&gt; and we'll be using &lt;a href="https://redis.io/docs/latest/develop/clients/nodejs/"&gt;Node Redis&lt;/a&gt; and &lt;a href="https://redis.io/docs/latest/develop/interact/search-and-query/"&gt;Redis Query Engine&lt;/a&gt; to find Bigfoot.&lt;/p&gt;
&lt;p&gt;I'm not gonna get into the details on connecting to Redis or on how to create a schema for Redis Query Engine. There's plenty out there about that already, some of it created by me. And, I have a &lt;a href="https://github.com/guyroyse/async-generators-search"&gt;repo with all the details&lt;/a&gt; anyhow.&lt;/p&gt;
&lt;p&gt;However, this is TypeScript so we are gonna start out by defining some types. First, the &lt;code&gt;BigfootSighting&lt;/code&gt; type. This type matches the &lt;a href="https://redis.io/docs/latest/develop/data-types/json/"&gt;JSON&lt;/a&gt; that we are getting out of Redis. It's just a bunch of carefully arranged strings.&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-typescript"&gt;type BigfootSighting = {
  id: string
  title: string
  account: string
  classification: string
  location: {
    county: string
    state: string
    lnglat: string
  }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The generator itself takes a Redis query, which is just a &lt;code&gt;string&lt;/code&gt; and, of course, returns the generator.&lt;/p&gt;
&lt;p&gt;Inside the generator, we start a loop that calls &lt;code&gt;.ft.search()&lt;/code&gt; until there are no more results. As each result has multiple JSON documents—&lt;em&gt;ahem&lt;/em&gt;—I mean Bigfoot sightings. Totally Bigfoot sightings. I cast it and everything.&lt;/p&gt;
&lt;p&gt;As each result has multiple &lt;em&gt;Bigfoot sightings&lt;/em&gt;, we need to loop over those too, yielding them as we go.&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-typescript"&gt;async function* fetchBigfootSightings(query: string): AsyncGenerator&amp;lt;BigfootSighting&amp;gt; {
  let offset = 0
  let hasMore = true

  while (hasMore) {
    /* Get a page of data. */
    const options: SearchOptions = {
      LIMIT: { from: offset, size: PAGE_SIZE },
      DIALECT: 4 // The latest dialect. Supports cool stuff like vector search.
    }

    const result = await redis.ft.search(INDEX_NAME, query, options)

    /* Loop over the resulting documents and yield them. */
    for (const document of result.documents) {
      /*
        There's only one value in the document and technically it's in a
        property named '0' but this looks better.
      */
      yield document.value[0] as BigfootSighting
    }

    /* Prepare for the next page. */
    hasMore = result.total &amp;gt; offset
    offset += PAGE_SIZE
  }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Remember, the code pauses execution after every yield. So, we won't make another network call until after we've consumed the first page of sightings. This is great, because if our code decides to not consume all the results, say by calling break in our &lt;code&gt;for await...of&lt;/code&gt; loop or just not calling &lt;code&gt;.next()&lt;/code&gt; again, we don't have to make another network call. Less is more.&lt;/p&gt;
&lt;p&gt;Another nice perk here is memory efficiency. Since we’re yielding one sighting at a time and waiting between calls, we’re not slurping the entire dataset into memory all at once. That means if there are thousands of Bigfoot sightings—and you know &lt;a href="https://bfro.net/GDB/"&gt;there are&lt;/a&gt;—we’re only dealing with them as needed. It’s lazy in the best possible way.&lt;/p&gt;
&lt;h1&gt;Wrapping Up&lt;/h1&gt;
&lt;p&gt;So, that's generators. Let's wrap up by wrapping up some calls to this generator to execute &amp;quot;meaningful&amp;quot; queries for your application. Here's a few that will help you find Bigfoot.&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-typescript"&gt;function fetchAll(): AsyncGenerator&amp;lt;BigfootSighting&amp;gt; {
  return fetchBigfootSightings('*')
}

function fetchByKeywords(keywords: string): AsyncGenerator&amp;lt;BigfootSighting&amp;gt; {
  return fetchBigfootSightings(keywords)
}

function fetchByClassification(classification: string): AsyncGenerator&amp;lt;BigfootSighting&amp;gt; {
  return fetchBigfootSightings(`@classification:{${classification}}`)
}

function fetchByState(state: string): AsyncGenerator&amp;lt;BigfootSighting&amp;gt; {
  return fetchBigfootSightings(`@state:${state}`)
}

function fetchByCountyAndState(county: string, state: string): AsyncGenerator&amp;lt;BigfootSighting&amp;gt; {
  return fetchBigfootSightings(`@county:${county} @state:${state}`)
}

function fetchByLocation(longitude: number, latitude: number, radiusInMiles: number): AsyncGenerator&amp;lt;BigfootSighting&amp;gt; {
  return fetchBigfootSightings(`@lnglat:[${longitude} ${latitude} ${radiusInMiles} mi]`)
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Happy hunting!&lt;/p&gt;
</content:encoded><media:thumbnail>https://guy.dev/images/bigfoot-flag.jpg</media:thumbnail><author>guy@guyroyse.com (Guy Royse)</author></item><item><title>Renaissance Guy's House Rules</title><link>https://guy.dev/2021/07/08/house-rules</link><guid isPermaLink="true">https://guy.dev/2021/07/08/house-rules</guid><pubDate>Thu, 08 Jul 2021 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;I created a tidy little one-pager of the house rules I use when I run 5th Edition Dungeons &amp;amp; Dragons. They're mostly cribbed from Index Card RPG by &lt;a href="https://www.runehammer.online/"&gt;Runehammer Games&lt;/a&gt;—which you should totally go out and &lt;a href="https://www.drivethrurpg.com/browse/pub/10923/RUNEHAMMER-GAMES"&gt;buy&lt;/a&gt;—but I included one from &lt;a href="https://slyflourish.com/"&gt;Sly Flourish&lt;/a&gt; as well.&lt;/p&gt;
&lt;p&gt;Download it &lt;a href="/downloads/renaissance-guys-house-rules.pdf"&gt;here&lt;/a&gt;.&lt;/p&gt;
</content:encoded><media:thumbnail>https://guy.dev/images/dice-so-nice.jpg</media:thumbnail><author>guy@guyroyse.com (Guy Royse)</author></item><item><title>Namelings, Namespaces, Nicknames, and Aliases</title><link>https://guy.dev/2019/08/27/nameling</link><guid isPermaLink="true">https://guy.dev/2019/08/27/nameling</guid><pubDate>Tue, 27 Aug 2019 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;I like words. Old words. New words. Obscure words. And, most interestingly, forgotten words. I'm not the only one who likes this sort of stuff as several years ago I found this site called the &lt;a href="http://phrontistery.info/clw.html"&gt;Compendium of Lost Words&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;One word I learned from it struck me as useful. That word: &lt;em&gt;nameling&lt;/em&gt;. A nameling is someone with whom you share a name. My name is Guy and I don't encounter namelings very often as my name is, shall we say, uncommon. However, you might have a more common name like Bill or George (anything but Sue) and know several namelings. Regardless, now that we have a word for it, we can talk easily about the idea.&lt;/p&gt;
&lt;p&gt;And, we can extend the idea of a nameling to other things. Things like software. Namelings occur all the time in software. We'll be creating some module for our project and realize that its name conflicts with an existing module from another library. Or maybe we'll have two libraries that have conflicting module names. Those modules are namelings.&lt;/p&gt;
&lt;p&gt;We typically solve this problem using namespaces and aliases.&lt;/p&gt;
&lt;p&gt;Namespaces provide a container, or &lt;em&gt;space&lt;/em&gt;, for names to exist inside of to alleviate the conflict caused by the namelings. Among humans, this is the purpose served by surnames.&lt;/p&gt;
&lt;p&gt;Aliases allow us to give namelings another name in a particular context. They are &lt;em&gt;nicknames&lt;/em&gt; for the namelings that we use when we need to work with namelings at the same time and find using the namespace burdensome. Among humans, we use nicknames to clearly talk to, with, and about namelings.&lt;/p&gt;
&lt;p&gt;I propose we change how we talk about our code in this regard. We should use these older words instead of inventing new one. So, we can talk about it like this:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Namespaces&lt;/strong&gt; are used to resolve &lt;strong&gt;namelings&lt;/strong&gt;. &lt;strong&gt;Nicknames&lt;/strong&gt; are given to &lt;strong&gt;namelings&lt;/strong&gt; when both are in the code together and we don't want to use &lt;strong&gt;namespaces&lt;/strong&gt;.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;This is way more fun than naming conflicts and aliases!&lt;/p&gt;
</content:encoded><media:thumbnail>https://guy.dev/images/inigo-montoya.jpg</media:thumbnail><author>guy@guyroyse.com (Guy Royse)</author></item><item><title>Northern Meetups</title><link>https://guy.dev/2018/12/05/northern-meetups</link><guid isPermaLink="true">https://guy.dev/2018/12/05/northern-meetups</guid><pubDate>Wed, 05 Dec 2018 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;I've got a couple of upcoming meetups in some of the more northerly states in the next week or so. Specifically, Michigan and Minnesota.&lt;/p&gt;
&lt;p&gt;I'll be giving &lt;a href="https://github.com/guyroyse/intro-to-webassembly"&gt;An Introduction to WebAssembly&lt;/a&gt; in Ann Arbor, Michigan on &lt;em&gt;Monday, December 10th&lt;/em&gt; at &lt;a href="https://www.meetup.com/SEM-JS/events/256735821/"&gt;Southeast Michigan JavaScript&lt;/a&gt;. WebAssembly allows you to write front-end web code in languages other than JavaScript by creating a virtual machine that runs in the browser. It's really neat stuff and I'll be diving into the low-level details. And, I'll be live-coding in WebAssembly Text Format so be prepared for epic failure!&lt;/p&gt;
&lt;p&gt;On &lt;em&gt;Wednesday, December 19th&lt;/em&gt; I'll be presenting what is one of my favorite talks: &lt;a href="https://github.com/guyroyse/deep-learning-like-a-viking"&gt;Deep Learning like a Viking&lt;/a&gt;. It's a talk about Vikings, Keras, and Convolutional Neural Networks. And how to combine these three amazing things into an application that recognizes hand-written runes from the &lt;a href="https://en.wikipedia.org/wiki/Younger_Futhark"&gt;Younger Futhark&lt;/a&gt;! The talk will be hosted by &lt;a href="https://www.meetup.com/JavaScriptMN/events/tqfvfqyxqbjc/"&gt;JavaScript MN&lt;/a&gt; in Minneapolis, Minnesota.&lt;/p&gt;
&lt;p&gt;So, if you &lt;a href="https://www.youtube.com/watch?v=5eHkjPCGXKQ"&gt;come from the land of the ice and snow&lt;/a&gt;, drop by and say hi!&lt;/p&gt;
</content:encoded><media:thumbnail>https://guy.dev/images/aaaaaaaaaaaaaaaaaaaaaaa.jpg</media:thumbnail><author>guy@guyroyse.com (Guy Royse)</author></item><item><title>Machine Learning for Developers: Lies, Truth, and Business Logic</title><link>https://guy.dev/2018/11/29/lies-truth-and-business-logic</link><guid isPermaLink="true">https://guy.dev/2018/11/29/lies-truth-and-business-logic</guid><pubDate>Thu, 29 Nov 2018 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;When I first heard about machine learning, my reaction was pretty much &amp;quot;meh&amp;quot;. I didn't care. I didn't see it affecting me or my job all that much. I was busy writing software. Software which was primarily focused on pulling data from some remote source, applying rules to that data, and putting it on a screen. Machine learning wasn't going to change that.&lt;/p&gt;
&lt;p&gt;Actually, that’s a bald-faced lie. I was terrified. There was this new technology out there that I had to master or I would be &amp;quot;left behind&amp;quot;. And this time, it wasn't just a new programming language or JavaScript framework. It was something completely different. I had no idea how it was going to affect the software I wrote, but it was going to be bad.&lt;/p&gt;
&lt;p&gt;Well, it turns out, I had it all backward. My bald-faced lie wasn’t a lie. Machine learning fit really well into what I was already doing and, while certainly different, it wasn't shockingly so and didn’t justify my terror. Let me explain with what may seem like a digression about &amp;quot;business logic&amp;quot;.&lt;/p&gt;
&lt;p&gt;Business logic is that bit of code that sits between the &amp;quot;presentation&amp;quot; (i.e. what the user sees) and the &amp;quot;data&amp;quot; (i.e. the information we have). It's a sort of two-way adapter that takes the data and presents it to the user in a meaningful way and takes meaningful input from the user and saves it in a technical way.&lt;/p&gt;
&lt;p&gt;For a simple application, there is often little to be had in the way of business logic. The data matches what the user wants to see and so these applications focus on just putting data on a screen (or perhaps a piece of paper). They tended to be easy to write and maintain because there's no significant logic to be had.&lt;/p&gt;
&lt;p&gt;Of course, eventually, you need a bit more. The user enters a particular value–notify them of a particular thing. The data has some special value–display some special thing. Rules like these are the business logic of the application. They start out simple and, for this reason, are often mistakenly put in the presentation or the data layers out of expediency or inexperience. But they rapidly get quite complex and you end up with a steaming plate of spaghetti code. Solution: give them their own layer.&lt;/p&gt;
&lt;p&gt;But that business logic layer itself can get quite complex as rules grow and expand. I spent a fair bit of my career working for an insurance company where I saw this firsthand. If the state is Ohio and the county is Cuyahoga and the EPA check of the vehicle is no older than 90 days, do one thing. But if the county is Franklin or Cuyahoga (but not any other counties) and the EPA check is no older than 60 days do some other thing. Craziness! Code like this can swiftly spiral out of control into a marinara covered pile of noodles.&lt;/p&gt;
&lt;p&gt;Often, the solution to this problem is a rules engine. Instead of writing a deeply nested set of hard to understand conditions, you define all your rules in an external piece of software and use that software to execute your rules. Rules engines are optimized for managing these rules and can even expose them to the business itself instead of just the developers. But sometimes even rules engines become difficult to manage and it becomes hard to understand how the rules are interacting within it. Eventually, instead of spaghetti code, you end up with a heaping portion of spaghetti rules with a side of meatballs.&lt;/p&gt;
&lt;p&gt;At this point, there is an important realization to make. All of these approaches fall down in the face of excessive complexity. They have differing thresholds, to be sure. But, with enough complexity, they all become unmanageable. Once you've implemented a rules engine have you've hit the end of the line?&lt;/p&gt;
&lt;p&gt;Oh. Hello there, machine learning.&lt;/p&gt;
&lt;p&gt;Machine learning is like a rules engine on steroids. It allows us to create rules that encapsulate complex patterns that would otherwise be nigh impossible. But instead of us using it to define our rules, it &lt;em&gt;finds&lt;/em&gt; the rules and then encodes them for us. All we have to provide it are examples and correct answers (i.e. features and labels) and it will create an abstraction we can use to exercise those rules (i.e. a model).&lt;/p&gt;
&lt;p&gt;That's a pretty neat trick!&lt;/p&gt;
&lt;p&gt;Does that mean models should replace all business logic? Of course not. Rules engines didn't replace all the business logic we coded. It augmented it. Sometimes a simple conditional in our code works just fine. And sometimes business logic is better managed with a rules engine. It's not a question of code vs. rules engines vs. machine learning. It's a menu from which we pick what we need. The business logic of our application, that layer between our data and our users, can be made of many things: simple rules in code, rules engines, and now machine learning models.&lt;/p&gt;
&lt;p&gt;Machine learning, it turns out, doesn't change what I'm doing. I'm still writing software which is primarily focused on pulling data from some remote source, applying rules to that data, and putting it on a screen. It's just that we found a new way to encapsulate rules that before were too complex for us to manage or, in some cases, even define.&lt;/p&gt;
&lt;p&gt;And that's not scary. That's empowering!&lt;/p&gt;
&lt;p&gt;&lt;em&gt;This post originally appeared on &lt;a href="https://blog.datarobot.com/machine-learning-for-developers-lies-truth-and-business-logic"&gt;DataRobot.com&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;
</content:encoded><media:thumbnail>https://guy.dev/images/toy-robot.jpg</media:thumbnail><author>guy@guyroyse.com (Guy Royse)</author></item><item><title>A Busy Week</title><link>https://guy.dev/2018/02/15/upcoming-talks</link><guid isPermaLink="true">https://guy.dev/2018/02/15/upcoming-talks</guid><pubDate>Thu, 15 Feb 2018 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Looks like I'll be busy next week. Monday, I'll be speaking at the &lt;a href="http://columbusrb.com/"&gt;Columbus Ruby Brigade&lt;/a&gt;. Wednesday, the &lt;a href="http://columbusjs.org/02-21-2018/guy-royse-machine-learning-for-fun.html"&gt;Columbus JavaScript Usergroup&lt;/a&gt;. And Thursday, I present at the &lt;a href="http://condg.org/2018/02/15/february-2018-machine-learning-for-fun/"&gt;Central Ohio .NET Developers Group&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;At the Columbus Ruby Brigade, I'll be presenting &amp;quot;Machine Learning for Gamers: Dungeon Forecasts &amp;amp; Dragon Regressions&amp;quot;. It introduces machine learning concepts using fun D&amp;amp;D examples!&lt;/p&gt;
&lt;p&gt;At the Columbus JavaScript Usergroup and the Central Ohio .NET Developers Group, the talk is &amp;quot;Machine Learning for Fun: Finding Bigfoot with the Nexosis API&amp;quot;. We'll predict the future number of Bigfoot sightings, measure the impact of the X-Files on sightings in the 90s, and explain the &lt;a href="http://guyroyse.com/bigfoot-classinator/site/"&gt;Bigfoot Classinator&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;You should come and check them out. Or tell your friends. Or both.&lt;/p&gt;
</content:encoded><media:thumbnail>https://guy.dev/images/sleeping-dragon.jpg</media:thumbnail><author>guy@guyroyse.com (Guy Royse)</author></item><item><title>Eat Sleep Code</title><link>https://guy.dev/2016/09/23/eat-sleep-code</link><guid isPermaLink="true">https://guy.dev/2016/09/23/eat-sleep-code</guid><pubDate>Fri, 23 Sep 2016 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;While at &lt;a href="http://www.musiccitycode.com/"&gt;Music City Code&lt;/a&gt; in Nashville last month I had the privilege of recording an
episode of the &lt;a href="http://developer.telerik.com/community/eat-sleep-code/"&gt;Eat Sleep Code Podcast&lt;/a&gt; with
&lt;a href="https://about.me/edcharbeneau"&gt;Ed Charbeneau&lt;/a&gt;. It's been posted to &lt;a href="https://soundcloud.com/esc-podcast/music-tdd-and-dd?in=esc-podcast/sets/season-2"&gt;SoundCloud&lt;/a&gt;
and you can check it out now. It should show up in iTunes and places like that in a couple of days.&lt;/p&gt;
&lt;p&gt;Apparently, I talked about Putting the D&amp;amp;D in TDD, refactoring, and all sorts of stuff. But, really, it's
all just a blur. Go check it out and tell me what I said! Thanks!&lt;/p&gt;
</content:encoded><author>guy@guyroyse.com (Guy Royse)</author></item><item><title>Prairie.Code() 2016 - Des Moines</title><link>https://guy.dev/2016/08/08/prairie-code</link><guid isPermaLink="true">https://guy.dev/2016/08/08/prairie-code</guid><pubDate>Mon, 08 Aug 2016 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;I have been selected to present &lt;a href="http://www.slideshare.net/GuyRoyse"&gt;jQuery &amp;amp; 10,000 Global Functions&lt;/a&gt; at
&lt;a href="http://prairiecode.amegala.com/"&gt;Prairie.Code()&lt;/a&gt; this year. And, &lt;a href="https://twitter.com/walterg2"&gt;George Walters&lt;/a&gt; and I
will be &lt;a href="https://github.com/PuttingTheDnDInTDD/EverCraft-Kata"&gt;Putting the D&amp;amp;D in TDD&lt;/a&gt; for a whole new mess of
Midwesterners.&lt;/p&gt;
&lt;p&gt;It's been a while since I've been to Des Moines and I'm really looking forward to it. I used to travel there quite a
bit when I worked for Nationwide. The food was great, the people were friendly, and the traffic was light. I'm
especially looking forward to checking out the
&lt;a href="http://www.officelovin.com/2016/04/24/a-tour-of-the-forge-by-pillar-in-des-moines/"&gt;The Forge&lt;/a&gt; that my employer,
&lt;a href="http://pillartechnology.com/"&gt;Pillar&lt;/a&gt;, has built there. Should be a good time.&lt;/p&gt;
&lt;p&gt;So, if you find yourself in the area or you're someone from back in the Nationwide days, look me up. I'm always happy
to chat!&lt;/p&gt;
</content:encoded><author>guy@guyroyse.com (Guy Royse)</author></item><item><title>Music City Code 2016 - Nashville</title><link>https://guy.dev/2016/07/16/music-city-code</link><guid isPermaLink="true">https://guy.dev/2016/07/16/music-city-code</guid><pubDate>Sat, 16 Jul 2016 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;&lt;a href="https://twitter.com/walterg2"&gt;George Walters&lt;/a&gt; and I will once again be
&lt;a href="https://github.com/PuttingTheDnDInTDD/EverCraft-Kata"&gt;Putting the D&amp;amp;D in TDD&lt;/a&gt;. This time it's at
&lt;a href="http://www.musiccitycode.com/"&gt;Music City Code&lt;/a&gt; in Nashville. We'll be presenting and facilitating all day on August
18th. If you're in the area, come and check it out.&lt;/p&gt;
</content:encoded><author>guy@guyroyse.com (Guy Royse)</author></item><item><title>jQuery &amp; 10,000 Global Functions</title><link>https://guy.dev/2016/06/23/jquery-and-10k-global-funcs</link><guid isPermaLink="true">https://guy.dev/2016/06/23/jquery-and-10k-global-funcs</guid><pubDate>Thu, 23 Jun 2016 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;I spoke at &lt;a href="http://stirtrek.com/"&gt;StirTrek&lt;/a&gt; a few weeks ago and they did me the service of recording my talk. It is
entitled &lt;em&gt;jQuery &amp;amp; 10,000 Global Functions: Working with Legacy JavaScript&lt;/em&gt; and I present it here for your perusal.&lt;/p&gt;
&lt;p&gt;The talk consists of a discussion on where legacy code comes from, some good strategies for dealing with it, some bad
strategies to avoid, and lots of specific techniques more specific to JavaScript.&lt;/p&gt;
&lt;p&gt;&amp;lt;iframe class=&amp;quot;youtube&amp;quot; src=&amp;quot;https://www.youtube.com/embed/c7wolG3rAKU?si=zf3a3mnOyD3_jj3q&amp;quot; title=&amp;quot;YouTube video player&amp;quot; frameborder=&amp;quot;0&amp;quot; allow=&amp;quot;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share&amp;quot; referrerpolicy=&amp;quot;strict-origin-when-cross-origin&amp;quot; allowfullscreen&amp;gt;&amp;lt;/iframe&amp;gt;&lt;/p&gt;
&lt;p&gt;The slides for this talk are on
&lt;a href="http://www.slideshare.net/GuyRoyse/jquery-10000-global-functions-working-with-legacy-javascript"&gt;SlideShare&lt;/a&gt;
and, given that there is a lot of code on them, they might be a handy reference. Check 'em out.&lt;/p&gt;
&lt;p&gt;In preparation for this talk I put together an exercise foolishly thinking I might have time during the talk to
actually do some coding to provide some more concrete examples. I ran out of time but
&lt;a href="https://github.com/guyroyse/10000-global-funcs"&gt;the exercise&lt;/a&gt; is still out there if you want to practice some of
these techniques.&lt;/p&gt;
&lt;p&gt;I also plan to record a series of screencasts where I show off some of these techniques against this repository. Watch
for those here or on my &lt;a href="https://www.youtube.com/channel/UCNt5SDc6LosO41E77jr59cQ"&gt;YouTube channel&lt;/a&gt;.&lt;/p&gt;
</content:encoded><author>guy@guyroyse.com (Guy Royse)</author></item><item><title>Installing RVM on Mavericks</title><link>https://guy.dev/2014/07/30/installing-rvm-on-mavericks</link><guid isPermaLink="true">https://guy.dev/2014/07/30/installing-rvm-on-mavericks</guid><pubDate>Wed, 30 Jul 2014 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;I find myself back in ruby land for a bit and it was time to help some of my
co-workers get RVM running on Mavericks. Having recently figured this out (and
needing to share it with more co-workers) I figured I'd share it with everyone.&lt;/p&gt;
&lt;p&gt;These instructions will show you how to install RVM on Mavericks for a single
user. And, it's all pretty easy so no worries. We can handle this.&lt;/p&gt;
&lt;p&gt;First off, make sure you don't already have RVM. Just look in your home
directory and make sure there is not a folder called .rvm.&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;$ ls ~/.rvm
ls: /Users/guy/.rvm: No such file or directory
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If there is a folder called, this you can either remove it (scorched earth,
baby!) rename it, or go find another blog post on how to repair it.&lt;/p&gt;
&lt;p&gt;Now, install RVM.&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;$ \curl -sSL https://get.rvm.io | bash -s stable
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Once this is done you can verify everything is installed by checking the .rvm
folder.&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;$ ls ~/.rvm
...lots of stuff...
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Hooray! It's installed. But it doesn't work. Well, that's because we ain't
done. You also need to add some stuff you the end -- and this is import --
&lt;strong&gt;the end&lt;/strong&gt; of your startup scripts. If RVM finds that it is not at the top of
the $PATH environment variable it'll work but nag you like an old lady. Just
put it as the end.&lt;/p&gt;
&lt;p&gt;I put them in .bashrc but you might put them in .bash_profile. Just make sure
they are the last thing to execute. Remember. Old lady.&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;[[-s &amp;quot;$HOME/.rvm/scripts/rvm&amp;quot;]] &amp;amp;&amp;amp; source &amp;quot;$HOME/.rvm/scripts/rvm&amp;quot;
PATH=$PATH:$HOME/.rvm/bin
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Once you do that, open a new terminal and install some rubies.&lt;/p&gt;
&lt;p&gt;Enjoy!&lt;/p&gt;
</content:encoded><author>guy@guyroyse.com (Guy Royse)</author></item><item><title>Coding in the Clink</title><link>https://guy.dev/2014/02/13/coding-in-the-clink</link><guid isPermaLink="true">https://guy.dev/2014/02/13/coding-in-the-clink</guid><pubDate>Thu, 13 Feb 2014 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;One of the people I have the distinct pleasure of working with at
&lt;a href="http://pillartechnology.com/"&gt;Pillar&lt;/a&gt; is &lt;a href="https://twitter.com/dnwiebe"&gt;Dan
Wiebe&lt;/a&gt;. He loves to code more than anyone I have
ever met. He is smart, focused, and just ever so slightly crazy.&lt;/p&gt;
&lt;p&gt;And every Tuesday evening Dan goes to prison.&lt;/p&gt;
&lt;p&gt;No, he's not on work release. He's there to teach about a dozen inmates how to
code. In all fairness, Dan isn't actually teaching them to code, they are doing
that themselves. However, he is there to provide direction, experience, and
wisdom. He is there to provide the perspective of the outside as it relates to
coding, to help give them a skill that they can use if and when they get out,
and -- I think -- more then anything to provide them some hope.&lt;/p&gt;
&lt;p&gt;Prisoners are people that much of the world wants to turn their back on. If
people think of them at all they assume that they are all &amp;quot;bad people&amp;quot; and they
deserve to be there. I can't refute the argument that they deserve to be there
as, in many cases, it is true. However, in my experience, there are no &amp;quot;bad
people&amp;quot;. There are only bad choices. And when you start to interact with
prisoners you quickly realize that the number of steps between you and them
really isn't that many. A bad choice or two and you could end up in the same
place as them.&lt;/p&gt;
&lt;p&gt;My father spent time in prison when I was a kid. He made plenty of bad choices
and I know for a fact that he deserved the time he spent in prison but I would
never say that he was a bad man. He wasn't even my biological father, but he
raised me as his own and cleaned up his life because of his love for me and my
sister.&lt;/p&gt;
&lt;p&gt;In most cases, prisoners will be released one day and they need to be able to
function in society. They will need a job. They will need to be able to work
with others. Technology may have passed them by while in prison and they will
need time and assistance in adjusting.&lt;/p&gt;
&lt;p&gt;My cousin spent ten years in prison. I remember when his sister and I first
picked him up. We gave him a cell phone so he could talk to his mother. He kept
moving the cell phone from his ear to his mouth and back again because he
didn't understand how the microphone could pick possibly up his voice without
being in front of his mouth. He had never used a phone without a handset.&lt;/p&gt;
&lt;p&gt;While in prison my father got sober and it helped to keep him that way. While
in prison my cousin studied horticulture and was able to get a job within weeks
of getting out. They were able to do this because people were willing to go
inside and help them.&lt;/p&gt;
&lt;p&gt;So, last month, I decided to help Dan and go to prison too.&lt;/p&gt;
&lt;p&gt;Fortunately, Dan has a good forum for introducing people to working with
prisoners. He calls it &amp;quot;Coding in the Clink&amp;quot;. In a sense it is like a
&lt;a href="http://coderetreat.org/"&gt;Coderetreat&lt;/a&gt; in prison. Lots of people gather for the
day to practice their skills. There is food provided. We test drive our code.
We pair.&lt;/p&gt;
&lt;p&gt;But the pairing is always aligned prisoner to visitor. The prisoners code with
each other all the time, they need an outside perspective. A visitor could pair
up with another visitor any time they wanted. There is no reason to come to
prison to pair with someone you could meet with at Panera.&lt;/p&gt;
&lt;p&gt;The format is also different. The coding is in Java for reasons Dan explains
&lt;a href="http://javaguys.wordpress.com/2010/10/19/why-java/"&gt;elsewhere&lt;/a&gt;. We normally
pair on a machine for an iteration and the next pair on that machine picks up
the code where it was left off instead of deleting and starting over. At the
end of the day we come back to our original machine with our original pairing
partner to see how the code we started changed over the course of the day.&lt;/p&gt;
&lt;p&gt;Also, we do not code the Game of Life as the longer format requires a longer
exercise. At the Coding in the Clink that I attended, I was quite please to be
working on the &lt;a href="https://github.com/guyroyse/evercraft-kata"&gt;Evercraft Kata&lt;/a&gt;
that &lt;a href="https://twitter.com/walterg2"&gt;George Walters&lt;/a&gt; (who was also in
attendance) and I put together a couple of years ago. That made this event a
little extra-special.&lt;/p&gt;
&lt;p&gt;But it wasn't the only special thing. &lt;a href="http://blog.8thlight.com/uncle-bob/2014/01/20/Marion_Correctional.html"&gt;Uncle
Bob&lt;/a&gt;
was there as well as his son Micah. They paired with the prisoners and provided
instructive feedback during the retrospectives. Muy cool!&lt;/p&gt;
&lt;p&gt;I personally paired with five prisoners that day. Three stand out in my mind.
One had been a programmer before he came to prison -- he was sharp and we wrote
much code. One had been programming for a week -- we spent our session teaching
him some basics. Another was studying electrical engineering at college when he
came to prison 20 years ago -- I worked with him last and we spent our session
refactoring a mess we had inherited.&lt;/p&gt;
&lt;p&gt;Lunch was pizza and pop, another way in which Coding in the Clink varies from a
Coderetreat. But we socialized for a good bit and talked about what we were
learning and teaching and doing. It felt like a Coderetreat as we were just
geeks discussing what we enjoy.&lt;/p&gt;
&lt;p&gt;Looking at all this from the point of view of the prisoners, this was a
wonderful day. They got to meet and pair directly with Uncle Bob, they had a
room full of visitors (some of them women -- woohoo!), they got to work on an
exercise with the folks who created it, and they got pizza and Mountain Dew for
lunch.&lt;/p&gt;
&lt;p&gt;From my point of view, the whole event wasn't about my kata, or Uncle Bob being
there, or hacking all day, or even pizza. Those things were cool and I enjoyed
myself very much. But really, I wasn't there for those reasons.&lt;/p&gt;
&lt;p&gt;I was there because there are no bad people just bad choices. I was there
because the people on the inside needed my help. I was there because they are
people.&lt;/p&gt;
&lt;p&gt;I'm going to continue going to prison with Dan. Others helped the people in my
life when they were in prison. People that I don't even know. People that
wanted to be part of the solution. I want to be part of the solution too.&lt;/p&gt;
</content:encoded><author>guy@guyroyse.com (Guy Royse)</author></item><item><title>Client-Side Session Handling</title><link>https://guy.dev/2011/03/10/client-side-session-handling</link><guid isPermaLink="true">https://guy.dev/2011/03/10/client-side-session-handling</guid><pubDate>Thu, 10 Mar 2011 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;OK. Let's say you've got some big, bulky, enterprisey application. This
application consists of an outer page (probably called index.jsp or something
like that) that never moves and assorted iframe tags for portlets and tabs.&lt;/p&gt;
&lt;p&gt;The first through you probably have is &amp;quot;Ewwww, iframes, really?&amp;quot; You're second
thought is probably that this is an application very much like the one Guy
works with. And, I hope, your third thought is one of sympathy for me since I
have to work on such an application. But I digress, como siempre.&lt;/p&gt;
&lt;p&gt;Also, this application has session data that needs to be shared between
portlets and tabs and across tabs and all other sorts of complex interactions.
And, you want to do this client side for performance reasons. How, pray tell,
can you do this without writing spaghetti code?&lt;/p&gt;
&lt;p&gt;If you're really smart (and you are, right?) you're probably just saying that I
should use &lt;a href="http://diveintohtml5.info/storage.html"&gt;HTML5 Local Storage&lt;/a&gt; and be
done with it. Great idea! I even wrote
&lt;a href="https://github.com/guyroyse/proton-db"&gt;ProtonDB&lt;/a&gt;, a framework to make this
sort of thing super-easy. But, alas, I'm stuck in Enterpriseland and HTML5 is
not permitted because it's new and we fear newness because it is fraught with
risk and uncertainty.&lt;/p&gt;
&lt;p&gt;But, I do have an elegant solution to the problem and the key lies in the fact
that the parent page doesn't move. And since it doesn't move it can simply hold
my session state in a JavaScript object. I can define this object with one line
of code and import the .js file in all HTML pages (i.e. each portlet, tab, and
the outer page)&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-javascript"&gt;var session = session || parent.session || {}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This code is simple and complex. Make sense of that! It assigns session if it
hasn't been assigned yet. Since the outer page loads first, it gets defined
there initially because session doesn't exist, and parent.session doesn't
exist. All of the iframes then evaluate this same code and session doesn't
exists but parent.session does. And, just in case someone &lt;em&gt;has&lt;/em&gt; defined this
already we'll always assign session to session if it exists.&lt;/p&gt;
&lt;p&gt;To use the code simply modify the session object. For example:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-javascript"&gt;session.foo = 'bar'
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now I like to know what I've put in session so that I have a feel for how big
it is. So I actually use a slightly more complex pattern. I define a session
object with explicit accessors so the code tells me what's stored there. And I
use a closure so no one can mess with my internal state and they have to go
through the defined session object. Here's the code:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-javascript"&gt;var session =
  session ||
  parent.session ||
  (function () {
    var sessionValues = {}
    return {
      setFoo: function (value) {
        sessionValues.foo = value
      },
      getFoo: function () {
        return sessionValues.foo
      }
    }
  })()
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In this case, you would use the code like this:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-javascript"&gt;session.setFoo('bar')
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;A little extra code, sure, but I think the value add is worth it.&lt;/p&gt;
&lt;p&gt;While I hope you don't have to use this pattern and can instead just enjoy
HTML5 goodness, if you need it, here it is. Enjoy!&lt;/p&gt;
</content:encoded><author>guy@guyroyse.com (Guy Royse)</author></item><item><title>Disconnected HTML5, JavaScript, the iPhone &amp; I</title><link>https://guy.dev/2011/02/23/disconnected-html5-javascript-the-iphone-and-i</link><guid isPermaLink="true">https://guy.dev/2011/02/23/disconnected-html5-javascript-the-iphone-and-i</guid><pubDate>Wed, 23 Feb 2011 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;I've been working on a simple test case for a disconnected HTML5 application
for the iPhone/iTouch off and on for the past couple of weeks. It's a points
calculator for a popular weight loss program who shall remain anonymous.
Anyhow, I thought this would be a handy tool for my wife and I and it would be
a nice and simple application to test a disconnected HTML5 application from the
iPhone.&lt;/p&gt;
&lt;p&gt;So, I present to you &lt;a href="http://files.guyroyse.com/puntos/"&gt;Puntos&lt;/a&gt;. Full &lt;a href="https://github.com/guyroyse/puntos"&gt;source
code&lt;/a&gt; is available on github but here's how
I wrote it.&lt;/p&gt;
&lt;h1&gt;Step #1: Write an HTML5 and JavaScript Application&lt;/h1&gt;
&lt;p&gt;The application I developed is not remarkable. In fact, it is a simple math
problem. Peruse the source if you want details on how it works. The important
part is that it has the following files:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;index.html&lt;/li&gt;
&lt;li&gt;calculator.js&lt;/li&gt;
&lt;li&gt;calculator.css&lt;/li&gt;
&lt;li&gt;jquery.js&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Just create the files for your application (or copy mine) and make it do what
it does. I'm assuming you know how to program in JavaScript and HTML.&lt;/p&gt;
&lt;h1&gt;Step #2: Make it iPhone Friendly&lt;/h1&gt;
&lt;p&gt;If you want it to be a cool iPhone HTML5 application, you have to provide an
icon from the iPhone desktop. You can do this by creating a file called
&lt;em&gt;iphone-icon.png&lt;/em&gt; and placing it in the root of you project. This little file
is the &lt;em&gt;favicon.ico&lt;/em&gt; of the Apple Mobile world. It is a 45 pixel by 45 pixel
PNG that your iPhone or iTouch will use if you decided to save a link to a
website on your desktop.&lt;/p&gt;
&lt;p&gt;So, just create this file with your favorite image editing program (I used
Gimp) and save it with the other files.&lt;/p&gt;
&lt;h1&gt;Step #3: Add the Caching Magic&lt;/h1&gt;
&lt;p&gt;Here's where the fun comes in. We can finally make the application
disconnected. The magic lies in an attribute on the html tag pointing the
browser to a cache.manifest file. This file then tells the browser which files
to cache and serve up when there isn't a network connection.&lt;/p&gt;
&lt;p&gt;So, simply add something like this to your HTML file.&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-html"&gt;&amp;lt;html manifest=&amp;quot;cache.manifest&amp;quot;&amp;gt;&amp;lt;/html&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This tells your browser to load up the file in the manifest attribute. The
filename can be anything but I would recommend having it end in .manifest as
this makes setting up the content type later much easier.&lt;/p&gt;
&lt;p&gt;The &lt;em&gt;cache.manifest&lt;/em&gt; is simplicity itself:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;CACHE MANIFEST
calculator.js
calculator.css
jquery.js
iphone-icon.png
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;It simple contains the words CACHE MANIFEST at the top and lists all the files
needed by the application.&lt;/p&gt;
&lt;p&gt;You might note that I did not include the &lt;em&gt;index.html&lt;/em&gt; and you would be
correct. This is because the browser will assume that the file you loaded in
the initial request is part of the &lt;em&gt;cache.manifest&lt;/em&gt;. No need to specify.
However, if you have several HTML files, you will need to specify them all in
your &lt;em&gt;cache.manifest&lt;/em&gt; as there is no way to know which file you entered the
application from.&lt;/p&gt;
&lt;h1&gt;Step #4: Serving Up text/cache-manifest&lt;/h1&gt;
&lt;p&gt;It turns out that the &lt;em&gt;cache.manifest&lt;/em&gt; file must be served up with a content
type of &lt;em&gt;text/cache-manifest&lt;/em&gt;. It also turns out that most web servers aren't
configured by default to do this since this is all bleeding edge and stuff.&lt;/p&gt;
&lt;p&gt;So, you need to add it yourself. If you are using an apache server you can add
the content type to your &lt;em&gt;.htaccess&lt;/em&gt; file. Add the following line and you
should be golden.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;AddType text/cache-manifest .manifest
&lt;/code&gt;&lt;/pre&gt;
&lt;h1&gt;Step #5: Access the Application from Your iPhone &amp;amp; Troubleshoot&lt;/h1&gt;
&lt;p&gt;Your application should now work. So go access it. Then turn on Airplane Mode
and refresh the application. I should reload gorgeously. If it doesn't, go back
and troubleshoot. But you knew that already.&lt;/p&gt;
&lt;p&gt;One caveat though. I had a hell of a time trying to get the application to work
disconnected until I rebooted my iTouch (I don't have an iPhone because I'm
lame). So, if everything looks like it should work but isn't then you might
want to try turning off your iPhone by pressing and holding the power button
until it shuts down completely.&lt;/p&gt;
&lt;p&gt;So, those are the steps I followed to get my first disconnected iPhone
application working with HTML5, JavaScript, and some &lt;em&gt;cache.manifest&lt;/em&gt; magic.
Now go out and write me a game or something.&lt;/p&gt;
&lt;p&gt;Also, for more information on HTML5 and disconnected applications check out
&lt;a href="http://diveintohtml5.info/offline.html"&gt;this fine website&lt;/a&gt;.&lt;/p&gt;
</content:encoded><author>guy@guyroyse.com (Guy Royse)</author></item><item><title>Fun With Windows</title><link>https://guy.dev/2011/02/03/fun-with-windows</link><guid isPermaLink="true">https://guy.dev/2011/02/03/fun-with-windows</guid><pubDate>Thu, 03 Feb 2011 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;OK. Just spent 3 hours of my life that I will never get back trying to
troubleshoot and issue with Windows 7 and USB devices that I was having.
Figured it out so I thought I would share the problem and solution.&lt;/p&gt;
&lt;h1&gt;The Problem&lt;/h1&gt;
&lt;p&gt;Whenever I would plug a new USB device in, it would not be detected by Windows.
Instead I would get a driver not found error and no amount of troubleshooting
on Windows' part would help. This affected a new keyboard and mouse I purchased
(Logitech MK520) and an old headset that I had lying around. It was also
affecting my iPod but I didn't realize that until after the fact.&lt;/p&gt;
&lt;p&gt;In the case of my mouse and keyboard I would see in Device Manager a device
names USB Receiver with an annoyed looking yellow icon resting upon it. No
amount of messing with the icon helped.&lt;/p&gt;
&lt;p&gt;All very frustrating because the hardware would detect the new keyboard and
mouse. When I booted the system and accessed the BIOS menu the keyboard worked.
The mouse was listed as detected. Everything seemed fine.&lt;/p&gt;
&lt;h1&gt;Troubleshooting&lt;/h1&gt;
&lt;p&gt;After much searching of the web in frustration. (Did I mention it was
frustrating) I finally found some people actually having the same problem. No
solutions, mind you, but the same problem. I determined from the gist of all
this posts that it was something to do with the USB drivers. Not the mouse
drivers or the keyboard drivers or the headset drivers but the core USB drivers
from Windows 7.&lt;/p&gt;
&lt;p&gt;So I removed them all in Device Manager and rebooted so they could be
reinstalled. This worked -- briefly. When the drivers were gone the mouse
started working. But Windows quickly fixed that and reinstalled the drivers and
I was back to a non-functioning mouse and keyboard.&lt;/p&gt;
&lt;h1&gt;The Solution&lt;/h1&gt;
&lt;p&gt;Finally I came across some forum posts suggesting that
&lt;a href="/downloads/usb.inf"&gt;usb.inf&lt;/a&gt; and
&lt;a href="/downloads/usb.pnf"&gt;usb.pnf&lt;/a&gt; should exist in Windows\inf
and if they didn't that would cause this issue. So, I Googled to find the files
and copied them in. Then I removed the annoyed USB Receiver driver and detected
new devices.&lt;/p&gt;
&lt;p&gt;Voila! It works.&lt;/p&gt;
&lt;p&gt;Hope this helps someone else.&lt;/p&gt;
</content:encoded><author>guy@guyroyse.com (Guy Royse)</author></item><item><title>The Rules of Code Club</title><link>https://guy.dev/2010/09/14/the-rules-of-code-club</link><guid isPermaLink="true">https://guy.dev/2010/09/14/the-rules-of-code-club</guid><pubDate>Tue, 14 Sep 2010 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;I hereby establish the rules of Code Club.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;The first rule of Code Club is, you always write tests first at Code Club.&lt;/li&gt;
&lt;li&gt;The second rule of Code Club is, you ALWAYS WRITE TESTS FIRST at Code Club.&lt;/li&gt;
&lt;li&gt;If someone says stop, gets stuck, gets bored, the pair switches.&lt;/li&gt;
&lt;li&gt;Two coders to a keyboard.&lt;/li&gt;
&lt;li&gt;One keyboard at a time.&lt;/li&gt;
&lt;li&gt;No mice, no copy and paste.&lt;/li&gt;
&lt;li&gt;Coding will go on as long as is has to.&lt;/li&gt;
&lt;li&gt;If this is your first time at Code Club, you have to code&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Carry on.&lt;/p&gt;
</content:encoded><author>guy@guyroyse.com (Guy Royse)</author></item><item><title>Site Update</title><link>https://guy.dev/2010/02/23/site-update</link><guid isPermaLink="true">https://guy.dev/2010/02/23/site-update</guid><pubDate>Tue, 23 Feb 2010 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;When I initially launched GuyRoyse.com I vacillated about the content I was
creating and writing about. Was this to be a blog about writing and games or
writing, games, and coding?&lt;/p&gt;
&lt;p&gt;Initially I decided to have it just be about writing and games. I wanted to
focus on my creative endeavors and frankly, figured most people wouldn't care
too much about the programming stuff. But, as it turns out, a lot of my
creative activity is focused around code and programming. This sort of leaked
in a posting I made a couple of months back updating everyone on the status of
[Corporate Raiders]({% post_url 2009-10-12-a-belated-corporate-raiders-update %}).&lt;/p&gt;
&lt;p&gt;So, I've decided to cave to my urges and put my code projects on here as well.
But, not only will I be including some of my coding project but I will also be
sharing some of my thoughts on technology and software engineering. So, if
you're a programmer or other geeky tech person, hopefully you'll find the
additional content enjoyable. And if your not, I won't be offended if you skip
over my more technical posts.&lt;/p&gt;
</content:encoded><author>guy@guyroyse.com (Guy Royse)</author></item><item><title>Let Him Who Hath Wisdom Reckon the Number of the Beast</title><link>https://guy.dev/2010/02/23/let-him-who-hath-wisdom-reckon-the-number-of-the-beast</link><guid isPermaLink="true">https://guy.dev/2010/02/23/let-him-who-hath-wisdom-reckon-the-number-of-the-beast</guid><pubDate>Tue, 23 Feb 2010 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;My latest project is something that I have written three times: The Antichrist
Detector.&lt;/p&gt;
&lt;p&gt;The Antichrist Detector was conceived about 10 years ago when I stumbled upon
the entertaining idea that Bill Gates was the Antichrist. The idea was simple
and ludicrous. If you take the ASCII values of the name Bill Gates (uppercase
only please as any good numerologist will tell you) they add up the 663.&lt;/p&gt;
&lt;p&gt;&amp;quot;But wait!&amp;quot;, you're saying, &amp;quot;That doesn't add up to 666?&amp;quot;&lt;/p&gt;
&lt;p&gt;Correct. But Bill Gates full name is William Henry Gates III. So, Bill Gates
plus three does equal 666. It's so obvious. How could you have not seen it?&lt;/p&gt;
&lt;p&gt;Anyhow, this whole idea gave me a slightly twisted thought. You could automate
this. Write a simple program and feed it the phone book and out pops a list of
potential Antichrist. Not having a digitized phonebook handy I had another more
practical (in as much as any of this is practical) idea. Why don't I put up a
website any let people enter their own names.&lt;/p&gt;
&lt;p&gt;So, in 2000, I did. It was very successful and a lot of fun. It didn't do much
but it generated a healthy amount of traffic and a lot of logs. In fact,
reading the logs was probably the best part about it. The emails I got,
however, were also very interesting. The vast majority of them were from
crackpots who thought I was serious. This greatly surprised but in hindsight,
it probably shouldn't have.&lt;/p&gt;
&lt;p&gt;My initial attempt was written in C++ and invoked via CGI. When I started
learning C# and .NET I decided to replatform it. So, version 2.0 was born.
Later, I moved to new hosting and no longer had .NET so I replatformed it again
and used it as an excuse to learn jQuery and PHP. 3.0 was born. In each
incarnation I added new features. 2.0 gained statistics. 3.0 gained an RSS
feed.&lt;/p&gt;
&lt;p&gt;So, I am now staring down the barrel of The Antichrist Detector 4.0. This time,
I am using it to learn Ruby, Google Appengine, and more advanced JavaScript
techniques. I plan to also add features to this one as well. Most notably, you
will now be able to issue Antichrist Detections via Twitter!&lt;/p&gt;
&lt;p&gt;Obviously, the Antichrist Detector has turned into a bit of a &amp;quot;Hello World&amp;quot;
application for me that I use to learn new technology. But, it's also fun and I
hope that you can enjoy it as well.&lt;/p&gt;
&lt;p&gt;I'll post the link to the new version once it is somewhat available.&lt;/p&gt;
</content:encoded><author>guy@guyroyse.com (Guy Royse)</author></item><item><title>Pairs of Ants Wager on Red and Black at AnCon</title><link>https://guy.dev/2009/10/16/pairs-of-ants-wager-on-red-and-black-at-ancon</link><guid isPermaLink="true">https://guy.dev/2009/10/16/pairs-of-ants-wager-on-red-and-black-at-ancon</guid><pubDate>Fri, 16 Oct 2009 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Saw this update a while ago from Super Dave, a fellow gamer and geek from my
college days, and thought I would share.&lt;/p&gt;
&lt;p&gt;Super Dave runs a regional gaming convention in North Eastern Ohio called
&lt;a href="http://www.anothergamecon.com/"&gt;AnCon&lt;/a&gt;. It is with great shame that I share
with you that I have never attended. But, word on the street is that it's a
lot of fun. I'd like to try to get up there in 2010. It runs from May 21
through May 23 next year. That's a Friday, Saturday, Sunday so getting off of
work should be easy for all of us corporate wage slaves. The price is only $25
for the entire weekend if you
&lt;a href="http://www.anothergamecon.com/fileadmin/pdf_store/AnCon2010Pre-reg05.pdf"&gt;pre-register&lt;/a&gt;
and apparently if you recruit others to come you'll get $5 for every person you
recruit. So, I would encourage you to check it out (and tell me about it so I
can claim my $5).&lt;/p&gt;
&lt;p&gt;But the really interesting thing--at least to me right now--is that he has
released some PDF games. Sounds familiar, doesn't it? Well, looking at his
release dates, I think he might have stolen my idea! But, since PDF boards
games like Zombie Stomp! at part of what I do here, I thought you might be
interested even if he leap-frogged me. Curse you and you're free time Super
Dave!&lt;/p&gt;
&lt;p&gt;The games are a dice game called &lt;a href="http://www.anothergamecon.com/Downloads/Pairs_and_Wagers.pdf"&gt;Pairs and
Wagers&lt;/a&gt; which
looks like it would be a lot of fun with the family and &lt;a href="http://www.anothergamecon.com/Downloads/Ants_Red_vs_Black.pdf"&gt;Ants: Red vs.
Black&lt;/a&gt;, a board
game which looks a little more involved than what might interest my wife. Which
means it's right up my alley! I haven't play either of them yet--hell, I've
hardly had time to update the blog--but I plan to.&lt;/p&gt;
</content:encoded><author>guy@guyroyse.com (Guy Royse)</author></item><item><title>A Belated Corporate Raiders Update</title><link>https://guy.dev/2009/10/12/a-belated-corporate-raiders-update</link><guid isPermaLink="true">https://guy.dev/2009/10/12/a-belated-corporate-raiders-update</guid><pubDate>Mon, 12 Oct 2009 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;So I haven't provided an update for y'all in quite some time but that doesn't
mean I haven't been busy working to build games and stories for your
consumption. It also doesn't mean that I have been busy working on games and
stories for your consumption. But I have.&lt;/p&gt;
&lt;p&gt;So, it's a &lt;a href="http://corporateraiders.hardboiledgeek.com/"&gt;Corporate Raiders&lt;/a&gt;
update today. I went on a bit of a code binge for a while and made a lot of
changes to get the application to be mash-up friendly. I also added lots of
JavaScript stuff to it as well. These sort of went hand in hand. The
significant update that you can actually see--an API.&lt;/p&gt;
&lt;p&gt;I've added APIs to lot you access the actual data of the game so that you can
code against it and extend it in ways that I don't foresee. Of course I also
plan to use this API to support other clients for the game. In fact, I am
already using it on the main page of &lt;a href="http://corporateraiders.hardboiledgeek.com/"&gt;Corporate
Raiders&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;If you want to check out the API for yourself you can access it using the following URLs:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;http://corporateraiders.hardboiledgeek.com/api/stock/{symbol}/{format}&lt;/li&gt;
&lt;li&gt;http://corporateraiders.hardboiledgeek.com/api/market/{format}&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Just replace &lt;em&gt;{symbol}&lt;/em&gt; with the stock symbol you care about. For &lt;em&gt;{format}&lt;/em&gt;
enter either &lt;em&gt;xml&lt;/em&gt; or &lt;em&gt;json&lt;/em&gt;. If you don't specify &lt;em&gt;{format}&lt;/em&gt;, it will default
to &lt;em&gt;json&lt;/em&gt;. For example...&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;http://corporateraiders.hardboiledgeek.com/api/stock/chch/xml&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;...will show you the info for &lt;a href="http://corporateraiders.hardboiledgeek.com/stock.jsp?stock=CHCH"&gt;Chthonic Chemicals
Corporation&lt;/a&gt;
in XML. Either of these urls...&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;http://corporateraiders.hardboiledgeek.com/api/stock/chch/json&lt;/li&gt;
&lt;li&gt;http://corporateraiders.hardboiledgeek.com/api/stock/chch&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;...would show you that same info in JSON.&lt;/p&gt;
&lt;p&gt;This API is ripe for consumption by fat client and portal device applications.
Got an &lt;a href="http://www.android.com/"&gt;Android Phone&lt;/a&gt; or an
&lt;a href="http://developer.apple.com/iphone/"&gt;iPhone&lt;/a&gt; and some spare time? How about an
&lt;a href="http://www.adobe.com/products/air/"&gt;Adobe Air&lt;/a&gt; client? This would be a good
place for you to play. And if you do something cool, tell me about it either
via &lt;a href="mailto:guy@guyroyse.com"&gt;email&lt;/a&gt; or by leaving a comment.&lt;/p&gt;
&lt;p&gt;Also, and perhaps more significantly, the market now moves. Right now the
algorithm is completely random day by day and the incrementals are very
predictable over the course of a given day. &lt;a href="http://en.wikipedia.org/wiki/E_pur_si_muove"&gt;Nonetheless, it
move&lt;/a&gt;. Next, the plan is to
swap out the core engine with something a little more random so we can start
letting people actually buy and sell stocks. Then, we'll add a more
event-based model so that we can have news items, rumors, and the like to
affect the stock price. Insider trading here we come!&lt;/p&gt;
&lt;p&gt;In the short term I plan to add users to the model as well as put some tasty
JavaScript stuff on the screen. Tabs and accordions are probably where I'll
start.&lt;/p&gt;
&lt;p&gt;So stay tuned. I'll post updates as I go so that you can watch the sausage
being made.&lt;/p&gt;
</content:encoded><author>guy@guyroyse.com (Guy Royse)</author></item><item><title>The Price of Admission</title><link>https://guy.dev/2009/09/05/the-price-of-admission</link><guid isPermaLink="true">https://guy.dev/2009/09/05/the-price-of-admission</guid><pubDate>Sat, 05 Sep 2009 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Part of the point of my efforts to make games and stories online is to prove
what one can do with very little. And by very little I mean a computer, the
Internet, and time.&lt;/p&gt;
&lt;p&gt;The stuff I am doing on this site is done with free software. I am using
&lt;a href="http://www.gimp.org/"&gt;GIMP&lt;/a&gt; to create the board for Zombie Stomp! I will use
&lt;a href="http://www.openoffice.org/"&gt;Open Office&lt;/a&gt; to write the rules and generate the
PDF for Zombie Stomp! &lt;a href="http://corporateraiders.hardboiledgeek.com/"&gt;Corporate
Raiders&lt;/a&gt; is being developed using
&lt;a href="http://www.eclipse.org/"&gt;Eclipse&lt;/a&gt; and &lt;a href="http://java.sun.com/"&gt;Java&lt;/a&gt;--both of
which are free. The writing I am doing for Big Time is with &lt;a href="http://www.openoffice.org/"&gt;Open
Office&lt;/a&gt;--again free. When I get around to
podcasting I plan to record with &lt;a href="http://audacity.sourceforge.net/"&gt;Audacity&lt;/a&gt;
which is also free.&lt;/p&gt;
&lt;p&gt;While I have a domain name and a hosting account, these items are not strictly
necessary. I could be at &lt;a href="http://guyroyse.blogspot.com/"&gt;guyroyse.blogspot.com&lt;/a&gt;
instead of &lt;a href="http://guyroyse.com/"&gt;guyroyse.com&lt;/a&gt; and I could host my images and
PDFs on free sites if I looked around. I choose to have a domain name and
hosting because I have the resources to do so. I have a day job that pays for
it. It is a luxury.&lt;/p&gt;
&lt;p&gt;The application hosting for &lt;a href="http://corporateraiders.hardboiledgeek.com/"&gt;Corporate
Raiders&lt;/a&gt; and the other games that
I will create, either through &lt;a href="http://hardboiledgeek.com/"&gt;Hard Boiled Geek&lt;/a&gt;
with Benjamin or on my own, are hosted with &lt;a href="http://code.google.com/appengine/"&gt;Google App
Engine&lt;/a&gt; which is also free up until a
certain point. A point which we will be well below for some time.&lt;/p&gt;
&lt;p&gt;This hardest part of doing this is the time. Many folks have lots of that.
Many don't. I fall into the latter category so I have chosen to sacrifice
television so that I can make these cool things and provide them to you. That
frees up more time than anything else I could possibly do.&lt;/p&gt;
&lt;p&gt;Folks, the point here is this--the price of admission is free. There are no
barriers to entry. Poor college students can do this. Retired folks on fixed
incomes can do this. My mom can do this. Anybody can do this. And I would
know because I am anybody.&lt;/p&gt;
&lt;p&gt;You should do it too.&lt;/p&gt;
</content:encoded><author>guy@guyroyse.com (Guy Royse)</author></item><item><title>Zombie Stomp! Work in Progress (Part 3)</title><link>https://guy.dev/2009/08/29/zombie-stomp-work-in-progress-part-3</link><guid isPermaLink="true">https://guy.dev/2009/08/29/zombie-stomp-work-in-progress-part-3</guid><pubDate>Sat, 29 Aug 2009 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Just a little update on the progress of the Zombie Stomp! gameboard.&lt;/p&gt;
&lt;p&gt;&lt;a href="/images/zombie-stomp/zombie-stomp-gameboard-wip-3.jpg"&gt;&lt;img src="/images/zombie-stomp/zombie-stomp-gameboard-wip-3-small.jpg" alt="Zombie Stomp! WIP 3"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;As you can see, the ship is pretty much done now. All that's left to do is
damage the ship up to match the sketch, add thrusters, and then add details in
the interior of the ship. After that, I can work on a nice, spacey background
and all the labels, lettering, and logos.&lt;/p&gt;
&lt;p&gt;Then, of course I still have to make it into a PDF complete with rules and all
that. But now that I think about it, the rules might be simple enough to just
put right on the gameboard. Or not, a summary of them at least.&lt;/p&gt;
&lt;p&gt;Enjoy!&lt;/p&gt;
</content:encoded><author>guy@guyroyse.com (Guy Royse)</author></item><item><title>Zombie Stomp! Work in Progress (Part 2)</title><link>https://guy.dev/2009/08/27/zombie-stomp-work-in-progress-part-2</link><guid isPermaLink="true">https://guy.dev/2009/08/27/zombie-stomp-work-in-progress-part-2</guid><pubDate>Thu, 27 Aug 2009 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;I thought that it might be a good idea to update you on the progress that has
been made on Zombie Stomp!. So, here it is.&lt;/p&gt;
&lt;p&gt;The board is progressing nicely but I have been running into barriers with my
general graphic design skill level--or lack thereof--and that is slowing me
down. Here's what we have so far.&lt;/p&gt;
&lt;p&gt;&lt;a href="/images/zombie-stomp/zombie-stomp-gameboard-wip-2.jpg"&gt;&lt;img src="/images/zombie-stomp/zombie-stomp-gameboard-wip-2-small.jpg" alt="Zombie Stomp! WIP 2"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;I'm actually rather proud of what I've made so far--although perhaps only in
the way a father can be. I know that it probably looks amateurish to the
professionals out there (you know who you are) but I'm impressed with what GIMP
is capable of doing for free and I'm having fun.&lt;/p&gt;
&lt;p&gt;The playtest that I planned to do this weekend has run into
life-schedule-conflict-stuff and I have to postpone. I'm thinking a couple more
weeks out so probably mid-September. In the meantime, I'll keep working on the
graphic and posting the results here for you to see.&lt;/p&gt;
</content:encoded><author>guy@guyroyse.com (Guy Royse)</author></item><item><title>Status Updated and Other Projects</title><link>https://guy.dev/2009/08/13/status-updated-and-other-projects</link><guid isPermaLink="true">https://guy.dev/2009/08/13/status-updated-and-other-projects</guid><pubDate>Thu, 13 Aug 2009 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;So I've been a little lax in reporting in of late. My family and I went on
vacation and the last few weeks have been really hectic. But, I haven't been
sitting on my laurels the entire time, I have been working.&lt;/p&gt;
&lt;p&gt;While on vacation I worked on my short story which has the working title of
&amp;quot;Big Time&amp;quot;. Big Time is the story of a small time reporter, Theodore Chang, who
has big dreams and an attitude to match. It takes place in a far future world
where man has long since colonized the stars and has built a massive network of
portals to connect all the planets into one metaworld that they call Pangaea.
Theo gets a chance to do an exclusive interview of Gigacity's most famous
serial killer--the Portal Killer. The Portal Killer had hacked his way into the
portal network and was using it to invade the homes of the rich and famous
through their private portals, killing them in their sleep. That is, until he
was caught. But then, why do people keep dying? Big Time should be a lot of fun
and hopefully a bit surprising.&lt;/p&gt;
&lt;p&gt;Zombie Stomp! is also moving forward. I plan to playtest the game at the end of
the month and hope to have the rules written before then so I can hand them out
at the playtest. I'll post them here first, of course. And the results of the
playtest afterwards too.&lt;/p&gt;
&lt;p&gt;And I've also been working with my friend Benjamin on a joint venture to
produce web-based computer games for your enjoyment under the brand &lt;a href="http://hardboiledgeek.com/"&gt;Hard
Boiled Geek&lt;/a&gt;. There's isn't much at our site
yet--actually there's nothing--but Benjamin is working on that.&lt;/p&gt;
&lt;p&gt;Our first game is a stock trading game called Corporate Raiders. If you want to
check out what the game has so far you can visit it at
&lt;a href="http://http://hardboiledgeek.com/"&gt;corporateraiders.hardboiledgeek.com&lt;/a&gt;. The
game is still pretty young right now. We just have the mechanism to display
the status of the market. Our next step is to actually make the market move.
Then we can start adding features to buy and sell and start adding players.&lt;/p&gt;
&lt;p&gt;Benajmin has a real knack for creating interesting companies for the fictitious
Atlantic Stock Exchange and reading the names and descriptions of these
companies can be a lot of fun. I encourage you to check it out and give us some
feedback on how it looks and the content. If we like you're feedback we might
even name a company after you! Once we get some more functionality up and
running we'll also want to start inviting some beta-test users. So if you're
interested drop me a line at guy@guyroyse.com.&lt;/p&gt;
&lt;p&gt;So, while I haven't been posting much of what I've been working on, you can
probably see that I've been a busy little beaver. And, I'm have a lot of fun
making all this content, even if there isn't much for you to see at the moment.
But when it comes, all these irons I have in the fire will be done at once. And
won't that be fun!&lt;/p&gt;
</content:encoded><author>guy@guyroyse.com (Guy Royse)</author></item><item><title>Zombie Stomp! Work in Progress</title><link>https://guy.dev/2009/07/20/zombie-stomp-work-in-progress</link><guid isPermaLink="true">https://guy.dev/2009/07/20/zombie-stomp-work-in-progress</guid><pubDate>Mon, 20 Jul 2009 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;I've been working hard on the Zombie Stomp! game-board and though I would share
a work in progress image so y'all knew I was working on something and hadn't
abandoned the project. So, here it is.&lt;/p&gt;
&lt;p&gt;&lt;a href="/images/zombie-stomp/zombie-stomp-gameboard-wip-1.jpg"&gt;&lt;img src="/images/zombie-stomp/zombie-stomp-gameboard-wip-1-small.jpg" alt="Zombie Stomp! WIP"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;As you can see, I have got the interior walls and structure in place and the
textures on the floor. I've also added doors but not any hatches yet. Exterior
walls, damage to the ship and large items inside of the ship are next. After
that, a nice spacey background and then details such as frost in the cryopods,
little yellow and black caution strips, maybe some blood splatters. That kinda
thing.&lt;/p&gt;
&lt;p&gt;I'm also thinking I will need some kind of logo for the game. If anyone had
some ideas for a logo, suggest them in the comments or email them to me
directly. Major props will go out for whomever puts a logo together for the
game and epic props for the one arbitrarily selected by yours truly.&lt;/p&gt;
&lt;p&gt;Once the board is done, I'll start working on the PDF. I'm planning on
including in the PDF detailed rules and the game-board—conveniently sized for
printing on card stock, cutting up, and spreading out on the gaming table—plus
cutout zombies and humans that can be folded as little triangles and used a
game pieces.&lt;/p&gt;
</content:encoded><author>guy@guyroyse.com (Guy Royse)</author></item><item><title>Zombie Stomp! Game Board Sketch</title><link>https://guy.dev/2009/07/07/zombie-stomp-game-board-sketch</link><guid isPermaLink="true">https://guy.dev/2009/07/07/zombie-stomp-game-board-sketch</guid><pubDate>Tue, 07 Jul 2009 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;So, as planned, here is the sketch for the Zombie Stomp! Gameboard.&lt;/p&gt;
&lt;p&gt;&lt;a href="/images/zombie-stomp/zombie-stomp-gameboard-sketch.jpg"&gt;&lt;img src="/images/zombie-stomp/zombie-stomp-gameboard-sketch-small.jpg" alt="Zombie Stomp! Game Board Sketch"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;There are a couple of things to note here:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Humans start with one pawn in Engineering, two on the Bridge, and three in Habitation.&lt;/li&gt;
&lt;li&gt;All eight zombies are split evenly between the two cryopods.&lt;/li&gt;
&lt;li&gt;Zombie are too stupid to use hatches (the little lens shaped things with T's on each side). Only humans can use them.&lt;/li&gt;
&lt;li&gt;The Port Cryopod, the Aft, and the outside of the ship are vacuum. Humans cannot enter these spaces unless they go through a hatch and suit up. Zombies can enter these areas just fine using regular doors. No significant depressurization of the ship occurs.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;I plan to work on a better board, making it real purdy-like and everything
using GIMP, over the next couple of weeks. Once it's ready I'll post it. I'll
probably post some preliminary stuff as well so you'll see the sausage being
made and too keep feeding y'all content.&lt;/p&gt;
&lt;p&gt;I also intent to work on the rules and play-test them over the next couple of
weeks. Expect those sooner as writing documents is easier than using GIMP. And
please, play-test the rules yourselves and give me your feedback. Either send
me an email at guy@guyroyse.com or drop your feedback in the comments on the
blog. The more data I have, the better.&lt;/p&gt;
&lt;p&gt;And, of course, if you give me play-test feedback you'll get props in the final
PDF. And who knows, maybe in an actual print version of the game some day.&lt;/p&gt;
&lt;p&gt;Once I get the game finished I may make new maps if their is interest. I'm
thinking that a classic dungeon for a nostalgic D&amp;amp;D feel might be fun or
perhaps a small town Main Street—complete with a theater showing a zombie
flick— for that real B-movie experience.&lt;/p&gt;
&lt;p&gt;This game will be released under a Creative Commons Attribution-Share Alike
license so that you and your friends can take this content, remix it, create
maps, expand the rules, or whatever. I heartily encourage you to do this. Right
now. Right this second. Go crazy! Just be sure to post links to your stuff in
the comments so everyone else can share in the fun.&lt;/p&gt;
</content:encoded><author>guy@guyroyse.com (Guy Royse)</author></item><item><title>Coming Soon: Zombie Stomp!</title><link>https://guy.dev/2009/07/02/coming-soon-zombie-stomp</link><guid isPermaLink="true">https://guy.dev/2009/07/02/coming-soon-zombie-stomp</guid><pubDate>Thu, 02 Jul 2009 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;&amp;quot;Hey! Hey! Do the Zombie Stomp!&amp;quot;&lt;/p&gt;
&lt;p&gt;Okay. So that's Ozzy but it's still a cool song. The Zombie Stomp never really
took off like the Monster Mash or the Transylvania Twist but don't short it.
It's damn cool. Cool enough to be a game. That's right. I've been inspired to
make a game, a board game, by Ozzy Osbourne himself.&lt;/p&gt;
&lt;p&gt;Actually, this is all a lie. Well, not all of it, just the Zombie Stomp! part.
It's still a game. But Zombie Stomp! has a much to do with Ozzy as Java (that's
a programming language for all those non-techies) does with coffee. The only
thing they have in common is the name.&lt;/p&gt;
&lt;p&gt;Imagine if you will a subluminal ship deep between the stars. A skeleton crew
mans the ship while the colonists slumber thoughtlessly in cryogenic
suspension. But, of course, something goes wrong. A strange artifact impacts
the ship and the folks in cryo wake up with a craving for
braaaaiiiiinnnnnssssss.&lt;/p&gt;
&lt;p&gt;Zombie Stomp! is a game of this particular space horror. Two players face
off—zombies vs. humans — on a game board that is the deck plans of a deep-space
colony ship. Pawns representing humans and zombies are placed across the board
as the players try to eliminate each other.&lt;/p&gt;
&lt;p&gt;The rules are simple:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Humans run two squares.&lt;/li&gt;
&lt;li&gt;Zombies shamble one square.&lt;/li&gt;
&lt;li&gt;Move one pawn per turn.&lt;/li&gt;
&lt;li&gt;Humans may move two pawns one square on a turn.&lt;/li&gt;
&lt;li&gt;An attack counts as one.&lt;/li&gt;
&lt;li&gt;Zombies go first since no one expects a zombie attack.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If there is an attack, each side rolls a six-sided die:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;High roll wins.&lt;/li&gt;
&lt;li&gt;Ties are just that: a tie. Try again next turn&lt;/li&gt;
&lt;li&gt;If the winner is a zombie, the human pawn becomes a zombie pawn.&lt;/li&gt;
&lt;li&gt;If the winner is a human, the zombie is removed.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I'm not sure how balanced this game is, so I plan to do some play-testing to
see who wins more often. If there is an imbalance, I'll give the zombies or the
humans the advantage of winning a tie and see what that does.&lt;/p&gt;
&lt;p&gt;I plan to produce a PDF containing the rules and the game-board once
play-testing is completed. There might be a few surprises in there. We'll see
what I can come up with for you.&lt;/p&gt;
&lt;p&gt;This game could easily be played on a chess board. Take eight white pawns and
place them at one end of the board. Take eight black for the other side and
just start playing. You'd need at most eight additional black pawns to play in
case the zombie get lucky.&lt;/p&gt;
&lt;p&gt;In fact, why don't you play some games on a chess board—or some other board of
your devising—with your buds and tell me about it in the comments. I'll
incorporate your feedback into the game, maybe include some of the boards, and
give props to everyone that helped.&lt;/p&gt;
</content:encoded><author>guy@guyroyse.com (Guy Royse)</author></item></channel></rss>