Showing posts with label level. Show all posts
Showing posts with label level. Show all posts

2015-05-20

Level Up - Ruby on Rails: How to create a very minimal blog website (two different ways)

As I was refreshing myself with Ruby on Rails, I've decided to share these notes. To follow these steps, you don't actually need to know any Ruby or Rails, but you should have them installed already. I'm using Ruby 2.1.5p273, Rails 4.2.0, Windows 8.1, but these steps are simple enough to do on any version.

I show two different ways to create a very code minimal blog. It also demonstrates the power of of Rails scaffolding.

Using scaffold


1. Just run the following commands one after another:

    rails new quick-blog
    cd quick-blog
    rails generate scaffold post title:string body:text
    rails generate scaffold comment post_id:integer body:text
    rake db:migrate

2. To create a post or comment, make sure that the `rails server` is started. Then, in browser, navigate to `/posts/new` or `/comments`.
3. Done


Without using scaffold


1. Run `rails new very-minimal-blog`
2. Run `cd very-minimal-blog`, then `rake db:create`
3. Create the model for the posts: Run `rails generate model Post title:string body:text`
4. Run `rake db:migrate`
5. Create a controller for the posts: Run `rails generate controller Posts`
6. In that controller that was just created in `app/controllers/posts_controller.rb`, add some code so that it looks like the following:

    class PostsController < ApplicationController
      def index
        @posts = Post.all
      end

      def show
        @post = Post.find(params[:id])
      end
    end

7. In `app/views/posts/`, create a new file called `index.html.erb` and add the following code:

   

Very Minimal Blog


    <% @posts.each do |post| %>
     

<%= post.title %>


      <%= link_to "Read me", post_path(post) %>
    <% end %>

8. Create a way to get to the posts. In `config/routes.rb` add, `resources :posts`
9. In `app/views/posts/`, create a new file called `show.html.erb` and add the following code:

   

<%= @post.title %>


    <%= @post.body %>

10. Done. :)


## To create a blog post ##
1. Open Rails console by running `rails console`
2. Run `Post.create(title: "My Title", body: "This is my awesome blog post!")`


## To view the blog ##
1. Start the Rails server by running `rails server`
2. Navigate to `localhost:3000/posts`


~ Danial Goodwin ~



2015-03-02

Level Up - Android Dev: How to get started with Robolectric (Android testing)

I'm finally getting around to trying out a few different libraries that claim to make testing Android apps easier. First up is Robolectric.

For this quick walkthrough, I'm going to show how to start from scratch. You'll need no prior knowledge except for how to make a regular Android app.

In my GitHub repo: How to get started with Robolectric

~ Danial Goodwin ~



2015-02-13

Level Up - Android Dev: OneTimeAlertDialog = Android AlertDialog that only shows once for a given key

Every single one of my apps need something like this. It's boring to explain in more details what's traditionally needed to make sure an AlertDialog is only shown once. Now, with this OneTimeAlertDialog.java, it's much easier to create new AlertDialogs that are only shown once.

/** Prompt that is only shown once to user. */
OneTimeAlertDialog.Builder(this, "my_dialog_key")
        .setTitle("My Title")
        .setMessage("My Message")
        .show();

For something I use so often, I was surprised to not find a similar project on GitHub. So, I've added it: Android OneTimeAlertDialog


~ Danial Goodwin ~



2015-02-12

Level Up - Web Dev: How to get started with Polymer

Polymer:

  • A wrapper with syntactic sugar for the new HTML WebComponents W3C spec.
  • Allows easy modularization and reuse of HTML/CSS/JS code.
  • Creates more readable source files.
  • Being actively developed by Google.

The purpose of this article is to provide the basic information needed for the easiest way to get started with Polymer, including downloading creating a custom Polymer element, and reusing other elements. This article probably could have been split into three separate smaller ones, but I'm opting for a single page that can be used as a "cheat sheet". Most of this information is from the official site, but the difference is that this is shorter guide with many deletions, a few additions, and different organization.


Getting Started For The First Time

This is a quick walkthrough for how to get started with Polymer from scratch.

1. There are a few different ways to get Polymer, but the easiest is with Bower, which is a package and dependency manager for many web libraries. So, install Bower if you don't already have it.
2. Create a new directory for your web project, then run `bower init` in it using a console. There will be a few questions, in which  you can just press Enter if you don't know what to do yet. This initialization just produces a `bower.json` file, which has settings that can easily be changed later.
3. Install Polymer for the project by running `bower install --save Polymer/polymer`. This will create and fill a new directory `bower_components` with Polymer and its dependencies. Using `--save` will update the `bower.json` file by listing Polymer as a dependency. (Sidenote: To update the components in bower_components, just run `bower update`.)

Now, you can use Polymer in your project. See the section on [How To Create A Polyment Element] for a quick walkthrough on getting a simple app working.


How To Create A Polymer Element

In this quick walkthrough, you'll create and implement a simple Polymer element called `my-element`.

1. Create a new file called `my-element.html` and add the following code. Make sure the import is pointing to the valid location within the bower_components directory that was created in the previous walkthrough.



2. Use your element in `index.html`. Here's a minimal example. Note: The above `my-elements.html` was put in an `elements` directory for some organization.



3. Run the app from a web server so that the [HTML Imports](https://www.polymer-project.org/platform/html-imports.html) work correctly. For example, to run on localhost instead of remote, if you have Python 2, then you can run `python -m SimpleHTTPServer`. If you have Python 3, then you can run `python -m http.server`.

Notes about Polymer elements:

  • The name of the element must have at least one dash `-` in it. (Reason: It's part of the web component spec as to not interfere with official HTML tags.)
  • The `noscript` attribute used in the above sample code indicates that it's a simple element with no script, which allows it to be registered automatically.



How To Reuse Other Polymer Elements

First, find some elements with Bower by running `bower search Polymer`. This will show most of the elements that the Polymer team as created. For a curated list of custom elements, check out customelements.io/. For a scrape of GitHub of all the projects that mention "web component", see Component Kitchen. These instructions work for both Polymer elements and regular web components as long as they are registered with Bower, otherwise they'll have to be installed manually.

1. Install the element for your web project, for example: `bower install --save Polymer/core-ajax`. The `--save` flag is used to add that element as a dependency to the `bower.json` file. After the optional `save`, the pattern is `/`. The element will be installed to the `bower_components` directory.
2. Use that element in your layout or custom element. An import statement must also be included, for example, to edit the custom `my-element` created in the last section:



3. Run the project and enjoy how easy it is to create modular web apps and site now. If you don't see anything on the page, then make sure that all your imports are pointing to the correct place.

The best way I've found to learn about using new elements is to see the demos and look at the source code for the ones that you like.

There's plenty more details that I haven't included in this article because they weren't vital to the setup process. So, if you have any questions, the official Polymer website is a great resource or I'll be happy to try to answer any questions.

:)
~ Danial Goodwin ~



2015-01-18

Level Up - Blogger: How to add formatted code to post (with highlighting)

In many of my posts, I like to add code snippets. Blogger doesn't have good native support for displaying code with syntax and line highlighting, so I found a way to add that feature using GitHub Gists and gist-embed project on GitHub.

The following steps can mostly be used with any blog.

Step 1: Include jQuery and gist-embed within your header tags.

<head>
  ...
  <script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
  <script type="text/javascript" src="//cdnjs.cloudflare.com/ajax/libs/gist-embed/2.0/gist-embed.min.js"></script>
</head>


Step 2: Add a code element to where you want your Gist code to appear.

<code data-gist-id=""></code>


Example:



Source:
<code data-gist-file="PrimeNumbers.cppdata-gist-hide-footer="true"
   data-gist-highlight-line="9,12,35-42" data-gist-id="5789439"></code>


Nice features also included, but not shown above:

  • Ability to show GitHub footer
  • Remove line numbers
  • Load multiple files from a Gist
  • Load a signal file from a Gist
  • Show only certain lines from a file


This article was mainly written for myself in the future, but I hope others can benefit from it, as well.

Links:



~ Danial Goodwin ~



2015-01-17

Level Up - Android Dev: How to get started with AndroidAnnotations (easy) (and build Chuck Norris app)

AndroidAnnotations is an open source framework for Android. Basically, you provide Java annotations for things, and the framework will auto-generate the necessary boilerplate code so you don't have to write it yourself. Runs at compile-time! (Read: No reflection or startup time impact) And, there's a lot of code AndroidAnnotations saves you from writing manually.

For example, want to run something in a background thread? Annotate the method with `@Background`. Want to run something in the main/UI thread? (rub some bacon on it) Annotate the method with `@UiThread`.

In this article, I provide a quick walkthrough for creating a very simple Chuck Norris facts app. I'll assume that you already have basic Android knowledge (and using Android Studio + Gradle). Then, at the end, I'll explain in more details some issues/gotchas I ran into while using AndroidAnnotations for the first time, and mention other goodies.

Getting started..

2014-12-06

Level Up - Android Dev: The default emulator is horrendously slow, use Genymotion!

Many years back when I built and published my first Android apps, I only tested them on the default emulator provided by Google. And, even now, the default emulator is still too slow for my liking. It doesn't allow me to properly test apps. So, I purchased physical devices so that I would never have to touch the Android emulator again.

Genymotion provides a different take on the Android emulator. I've known about it for at least a year, but never got around to trying it because of my really bad experience with the default emulator. I've always heard that it was much faster than Google's implementation, but I didn't think an Android emulator could ever be fast enough for me compared to my physical devices.

I'm always learning something new, and today was finally time for me to learn more about Genymotion and test just how much better it is.

Results: Excellent! So much of a great experience that I had to write this blog post about it! I should have tried Genymotion when I first heard about it, and this is my message to all Android devs to also try it out now!

Sidenote: I was going to compare the default emulator with the Genymotion emulator side-by-side, but it was taking too long to load for me, whereas Genymotion startup was a breeze of fresh air. It runs without any lag. It runs faster than my old API 17 device.

Another great benefit is that Genymotion provides system images for many of the most popular devices, including Samsung Galaxy, Samsung Note, HTC One, Nexus, and more. And, they have a very convenient plugin for Android Studio to launch the emulator.

TLDR: It's fast. I have to make sure I stress that because I didn't believe how fast it would be. Genymotion's Android emulator is much faster and better experience than the default Android emulator.



Here, I even saved enough time to write a quick walkthrough for getting started. ;)


  1. Go to Genymotion.com, click "Get Genymotion".
  2. Download the free version, you'll have to sign up and confirm your email. (It's quick and it's worth it!)
  3. Install it along with VirtualBox. For Windows users, they can bundle the two together in the download. For other, you'll have to install VirtualBox separately.
  4. If you try to run it now, you might get an error that says "genymotion virtualization engine not found. Unable to load VirtualBox engine". So, just restart your computer and that fixed it for me. Some others had to enable the virtualization feature in the BIOS.
  5. Run! Fast!
  6. Now, you can click run in Android Studio and you will see an option to load the app in the Genymotion emulator that is running.

Bonus: How to Install the Genymotion Plugin for Android Studio (and, the first time you click on the installed plugin button, you'll have to add the path to where you installed it. Windows default is "C:\Program Files\Genymobile\Genymotion". Mac default is "/Applications/Genymotion.app")
~ Danial Goodwin ~



2014-12-05

Level Up - Android Studio: How to Boost Productivity By Auto-Generating Getters and Setters

A best practice in Java is to encapsulate field variables by making them private and creating a "getter" and "setter" for each of them, as needed. Doing this with many fields can be a lot of boilerplate code to write. But, thankfully, modern IDEs, like Android Studio provide ways to auto-generate code so that you don't have to manually write it.

For example, if you have a class like the following:

public class MyClass {
    private int mId;
    private String mName;
}

Instead of manually writing each accessor (getter) and mutator (setter), go to the menu and click Code->Generate.. (hotkey `alt+insert), then choose the "Getter and Setter" option.

Done. That was fast. And, it will be just as fast with 20+ fields also.

But, wait! By default, Android Studio will include that "m" prefix (stands for "member" variable) in each of the generated method names, so you'll have method names like "setmId" and "getmId". There is a quick permanent fix for this also!

Go to File->Settings->Code Style->Java->Code Generation, then type a single "m" into the "Field", "Name prefix" field. Hit apply, then you are gone. All future code generations will take those "m" prefixes for field into account. Here's a screenshot to what this sentence means visually.

So easy to save a lot of time with Android Studio

That's it for this post. There are lots of other useful code generators also. If you are doing mindless work, it's probably been automated (or should be). ;)

~ Danial Goodwin ~



2014-11-17

Level Up - Android: How to Root Nexus 4 on Android Lollipop 5.0 (Easy)

In my last post, I explained how to flash Android Lollipop 5.0 system image to Nexus 4. After I did that to my own device, the next thing I did was root it, using fewer steps than that other post. ;)

Rooted Nexus 4 on Android Lollipop 5.0

This will be a quick walk-through for the steps I took to root my Nexus 4. These directions are extended from the site with the great "CF-Auto-Root" tool that we will use.

Prerequisites:

  1. I assume that your bootloader is unlocked. If not, please see my previous post for how to unlock the bootloader.
  2. I assume you have `adb` added to your environment variable PATH. If not, please see my previous post.
  3. I assume you are running Windows, but Max and Linux users will be able to use these general directions also.


Walk-though for rooting the Nexus 4:


  1. Download the LGE Nexus 4 Android 5.0 file from http://autoroot.chainfire.eu/#fastboot
  2. Unzip the file. You should see two folders and three files in that folder, one should be called "root-windows.bat".
  3. Connect your Nexus 4 device to computer, then run `adb reboot-bootloader` in your computer's terminal. This will bring your device to the "fastboot" mode.
  4. Make sure again that your bootloader is unlocked before proceeding (label found at bottom-left).
  5. Open your computer's terminal to where you downloaded and unzipped the file, and run `root-windows` (Mac and Linux users use your own variant). You should see a red Android if the process is working.

Congrats! When the script is done, it will reboot your device and your Nexus 4 will be rooted!

This process will install the Root Check app so that you can verify a successful root.

More info:
  • I didn't have any trouble using these directions for rooting my Nexus 4, so if you have any troubles with the steps, then I'll try to help in my limited capacity.
  • Previously, when I was running Android 4.4 rooted, I used ES File Explorer to browse the root directories. But, it didn't work in Android 5.0, so instead I am now using the Root Browser app successfully.

~ Danial Goodwin ~



Level Up - Android: How to Flash (Upgrade) Nexus 4 to Android Lollipop 5.0 (Easy)

If you have a Nexus 4, then you can have Android Lollipop now! Google recently released the factory image, and I'm now successfully running it (with root, which will be explained in a later post).

Nexus 4 running Android Lollipop 5.0
This will be a short walk-through because I assume you already have the tools needed, but just need the steps to get the flash done. If you have any questions, then please write a comment and I will update as necessary.

  1. Download Android Lollipop 5.0 factory image: https://developers.google.com/android/nexus/images#occam
  2. Uncompress the file, possibly twice. I used 7-zip. You should see six files there, including a zip, which you do not have to unzip.
  3. Make sure `adb` is in your PATH environment variable, which can be found in %android-sdk%/platform-tools/. Also, you will need `fastboot.exe` from that same folder in your PATH. (I assume you already have the Android SDK and you know what I mean by "Advanced system settings"->Environment Variables->PATH.)
  4. Connect your Nexus 4 device to computer, then run `adb reboot-bootloader` in your computer's terminal. This will bring your device to the "fastboot" mode.
  5. At the very bottom-left, you should be able to see whether your bootloader is locked or unlocked. It must be unlocked to flash a new system image. If unlocked, you're good, go to the next step. If locked, then run `fastboot oem unlock`. WARNING: Unlocking will erase all data.
  6. Open your computer's terminal to where you downloaded and uncompressed the files, and run `flash-all`. That command will run the "flash-all.bat" script which will setup the new system image for you!

Congrats! When the script is done, it will reboot your device and Lollipop will be running. It may take a bit for it to boot the first time.

More info: There sure is a lot more information you could read about this entire process, but that's not what this post is for. These are the minimal instructions (with appropriate warning) for most people wanting to do this. If anybody has some good resources to share, then please add them to the comments.

Now, are you ready to root your Nexus 4?

:)
~ Danial Goodwin ~



2014-11-13

Level Up - Java: What is Vararg?

I like to remember vararg as "variable-length arguments". You may see them parameterized as "foo(Object... objects)" or "foo(int... ints)" or maybe "main(String... args)". The triple-dot signifies the vararg, and the method that has them uses it as an array.

Example code:

/** Returns input as a comma-separated list. If input if null
  * or empty, then this returns an empty string. */
public static String convertToString(Object... objects) {
    if (objects == null || objects.length == 0) { return ""; }
    StringBuilder sb = new StringBuilder();
    for (Object object : objects) {
        sb.append(object.toString()).append(", ");
    }
   return sb.substring(0, sb.length() - 2).

2014-08-30

Level Up - Android: Speed up your Gradle build times with one-line!

Whether or not you are using Android Studio, Gradle build times are slow (especially when you don't have continuous automated builds (another discussion)).

Here's one way to improve the speed Gradle commands like `assembleRelease` is to enable the Gradle daemon. I've sped up my release builds by about 20%!

2014-08-26

Level Up - Paint.NET & Android: How to create new color palettes for Android Holo and Material design

If you work in Android and Paint.NET, here's some quick tips and resources to make both easier to work with. When designing graphics in Paint.NET, it would be really useful to have direct access to all of the Android design guide colors. So, here's how to save and load different color palettes in Paint.NET:

2014-08-18

Level Up - Android: How to get started with Unit Testing in Android Studio

Recently, I finally got around to implementing the native unit testing that is provided within Android Studio (not third-party programs like Robolectric). So, after reading a few different sources, the following is the bare minimum that I would have needed in order to add the basic testing features.

2014-08-13

Level Up - Android: How to get started with Android Wear and the Wearables Emulator

Recently, I started working on Android Wear for the first time. It's been fun playing around with the new platform and form factor. And, of course, the official Android docs that I read could be condensed further for absolute newcomers. So, in the typical fashion, I've created myself a cheat sheet that I would use next time I would want to learn the easiest way for how to best create Wearable apps.

I've open sourced all my code so far on GitHub. It includes how to first set up the virtual Wear device, connect to the handheld device, and how to have the app send and open a notification on the wearable.

https://github.com/danialgoodwin/android-wear

~ Danial Goodwin ~



2014-07-02

Level Up - Dev: Modular Code

Modular code means that the code is easily reusable; It does not mean that the code has to all be in one file. That's what modules and libraries are for. ;)

~ Danial Goodwin ~



2014-06-27

Level Up - Dev: Codestyle Quote

    "Any fool can write code that a computer can understand.
    Good programmers write code that humans can understand."
    
      --- Martin Fowler, Refactoring: Improving the Design of Existing Code

~ Danial Goodwin ~



2014-06-18

Level Up - Dev: Integer Overflow Not Overflowing

An integer overflow (or wraparound) occurs when a number larger than the max integer value or smaller than the min integer value is tried to be stored in the integer's memory. You could imagine a circular number line.

Ex: If you have an integer at the max positive value and add one, then the integer will wraparound and be set to the most negative value (if using a signed int. An unsigned int will wraparound to 0). And, vise-versa.

Today, I experienced a bug where I wanted to get a (signed) integer overflow, but unfortunately the int value was just going to zero instead of going to the negative numbers. Thankfully, I knew the memory/bit representation of int and was able to figure out what was going on.

Here is some simplified code, with only one small change:

    // Test #1 - has wraparound
    int wrap = 1;
    for (int i = 0; i < 34; i++) {
        print(i + ": wrap: " + wrap);
        wrap = wrap * 3;
    }

    // Test #2 - no wraparound
    int wrap = 1;
    for (int i = 0; i < 34; i++) {
        print(i + ": wrap: " + wrap);
        wrap = wrap * 2;
    }

Here is the relevant output from running the code above:

// Test #1 - has wraparound
...
13: wrap: 1594323
14: wrap: 4782969
15: wrap: 14348907
16: wrap: 43046721
17: wrap: 129140163
18: wrap: 387420489
19: wrap: 1162261467
20: wrap: -808182895
21: wrap: 1870418611
22: wrap: 1316288537
23: wrap: -346101685
24: wrap: -1038305055
25: wrap: 1180052131
26: wrap: -754810903
27: wrap: 2030534587
28: wrap: 1796636465
29: wrap: 1094942099
30: wrap: -1010140999
31: wrap: 1264544299
32: wrap: -501334399
33: wrap: -1504003197

// Test #2 - no wraparound
...
20: wrap: 1048576
21: wrap: 2097152
22: wrap: 4194304
23: wrap: 8388608
24: wrap: 16777216
25: wrap: 33554432
26: wrap: 67108864
27: wrap: 134217728
28: wrap: 268435456
29: wrap: 536870912
30: wrap: 1073741824
31: wrap: -2147483648
32: wrap: 0

33: wrap: 0

If test #1 were to continue, then the values would keep wrapping. If test #2 were to continue, then the values would stay the same at 0.

The easiest way for me to make sense of this experiment was to know that multiplying by a power of 2 (2, 4, 8, 16, 32..) is the exact same as a bit shift in the binary computer. And, the bits that made up the int were all just getting pushed out of memory in test #2 until there were no more set bits to manipulate. In test #1, more int memory bits are being flipped in order to continue the wraparound.

I would explain this at a lower level, but there are already many great resources for "bit representation of integer".


~ Danial Goodwin ~

ps - This post was mainly for myself and written quickly. If there are any questions about this, then I'd be happy to elaborate.



2014-03-22

Level Up!: Do Users Need To Click "I Agree" to TOS Button To Give Consent?

(TLDR: No. Courts decide these cases simply by whether the person had reasonable notice of the Terms & Conditions. If you have a website/app and plan on collecting personal info or just have customers in general, the I highly suggest you read more about this topic. Disclaimer: IANYL.)


As a UX designer, I try to make things that are as simple and painless as possible for users to use. One pain (and protection) that almost every product/app needs is a Terms of Service (TOS) agreement, aka Terms of Use (TOU), aka Terms And Conditions (T&C), aka End User License Agreement (EULA).

The current "best practice" for showing TOS to users is by providing a clear link near the "continue to use app" button (which could be a register or purchase button). This is so that most users don't have to go through the extra step of clicking "I Agree" to something that they likely didn't read. Also, having the TOS pop-up interrupts users' flow (and can sometimes be quite scary-looking).

But, unfortunately, before today, I never really thought about the legal consequences of the different methods to show users the terms and conditions. I just used methods that I noticed many other great UX designers and companies using. So, I wasn't able to explain the legal-ness (to my satisfaction) to concerned client.

I took it upon myself to take the time to do some research around this area and organize it into this post, with sources and references cited.

In my research, I have found that the courts also know that most users don't read the TOS, and clicking "I agree" doesn't mean that the user has read it. What the courts look for is mainly that the user has had the easy opportunity to find and read the TOS, if they wanted to.

There are two main ways that users "agree" to TOS:

  • Click-wrap Agreement, aka "click-through agreement": This means that users must take some sort of action that signifies their consent to the TOS. This action could be a button that says "I Agree". Also, near the call to action, it is sufficient to say "By [continuing], you agree to our Terms of Service", with the TOS having a direct link.
  • Browse-wrap Agreement, aka "not a contract": Basically, saying users agree to TOS by browsing website/app, and the link to TOS is not extremely easy to find in regular use. A link at the bottom of the website could be considered hard to find, especially when there are many other links down there too.


My Summary (Just from my research (links below), though more can always be done.)

  • If your app collects or uses personal information, then use the click-through (clickwrap) agreement.
  • Remove any clauses about unilaterally editing contract at any time.
  • Add ability for company to modify terms, with prior notice. [More research needed for exact words to use]
  • Add ability for users to reject TOS, e.g. by terminating account. 



A few sources I read, in order of my recommended readings (Yes, there is a "Good" before "Great", just because of what this post was supposed to be about):
 - Great: How Zappos' User Agreement Failed In Court and Left Zappos Legally Naked (Forbes)
 - Great: The Clicks That Bind: Ways Users "Agree" to Online Terms of Service (EFF)
 - Good: Terms Of Use And Privacy Policy Best Practices (UpCounsel)
 - Great: Website Terms and Conditions: Some Best Practices (JDSupra)
 - Miscellaneous, but good: Terms of Service; Didn't Read (TOSDR)
 - Good: Browse wrap (Wikipedia)
 - Okay: Clickwrap / Browsewrap Agreements: It’s the Notice, Stupid!

Further Reading:
 - Terms of Use and the Digital Millennium Copyright Act (DCMA)
 - Search "Clickwrap vs browsewrap"


Disclaimer: I am not your lawyer (IANYL). This post's only intention is to help point readers in the right direction to learn more about this topic.

~ Danial Goodwin ~


ps - Bonus info! The terms "click-wrap" and "browse-wrap" come from physical goods/software that was "shrink-wrapped". Manufacturers had license agreements that basically said users agree to TOS by removing the shrink-wrap. (Source: Wikipedia)



2014-03-08

Level Up - Puzzles: Connect a 4x4 Grid of Dots With 6 Contiguous Lines (5x5 w/8, 6x6 w/10)

(TLDR: After solving a 3x3, try to solve a 4x4, 5x5, etc. I have proof that all of them have a solution.)

A common brain teaser is to connect a 3 by 3 grid of dots with four straight lines without picking up the pencil. See image below: