.-----.   .----.   .-----.  .-----.           .----.      .---.          .---..--------. 
/ ,-.   \ /  ..  \ / ,-.   \/ ,-.   \  .-')   /  ..  \    / .  |    .-') /_   ||   __   ' 
'-'  |  |.  /  \  .'-'  |  |'-'  |  |_(  OO) .  /  \  .  / /|  |  _(  OO) |   |`--' .  /  
   .'  / |  |  '  |   .'  /    .'  /(,------.|  |  '  | / / |  |_(,------.|   |    /  /   
 .'  /__ '  \  /  ' .'  /__  .'  /__ '------''  \  /  '/  '-'    |'------'|   |   .  /    
|       | \  `'  / |       ||       |         \  `'  / `----|  |-'        |   |  /  /     
`-------'  `---''  `-------'`-------'          `---''       `--'          `---' `--'      

Why is this entry so long? because of the import I did.

Python Halftones

I'm using python PIL/Pillow to draw halftone patterns in different rotations and dot sizes. You can check out the demo/src links to see what the output looks like.

I'm creating these patterns for another experiment where i'm playing with using halftons as the shading to vector drawings, and this saved me having to pay for a bunch of halftone patterns.

Bulk Leave Meetup Groups

Meetup.com makes it a pain to unsubscribe from groups. You have to click on each group, wait for the page to load, then click on the unsubscribe link, wait for the page to load, then click the unsubscribe link. Doesn't sound too horrible but when you have a bunch of groups it's pretty tedious. I can only assume that Meetup doesn't provide the functionality to do this because you being a member of a lot of groups is good for their metrics.

So to get around this, I created a grease monkey script that will quickly remove you from all the groups you select:

Just load this script into greasemonkey, and go to https://www.meetup.com/groups/. Give the page 2 seconds to load, and then scroll ALL the way to the bottom of the page and you should see a list of goups you can unsubscribe from.

// ==UserScript==
// @name     Meetup Unsubscriber
// @version  1
// @grant    none
// @namespace https://www.meetup.com
// @include https://www.meetup.com/*
// @run-at document-idle
// @require  http://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js
// ==/UserScript==


/*
1) go to https://www.meetup.com/groups/
2) wait 2 seconds
3) there will be a list at the very bottom of the page of all the groups on the page, click on the ones you want to leave.
*/

/*
Get an inital list of links, we'll use this later to filter out which links 
are groups
*/
var init_links=[];
var links = document.getElementsByTagName("a");
for(var i=0; i<links.length; i++) {
  init_links.push(  links[i].href );
}


function page_load() {
var links = document.querySelectorAll("a");
  console.log("checking");
    for(var i=0; i<links.length; i++) {
    // find all the links that aren't in the inital list at the top, and end in a /
    if (! init_links.includes( links[i].href)) {
        if (links[i].href.slice(-1) == "/") {

        var group_name = links[i].href.split("/").slice(-2)[0];

        // Add a button you can click at the bottom of the page to leave the group
        $("#main_footer").append ('<a id=' + group_name + '>Leave group ' + group_name + '</a><br>');

        $("#" + group_name).click ( function () {
          console.log("remove", this.id);

            var self = this;

            // to unsubscribe it requires an ID, so grab the ID off that page and then unsubscribe from the page.
            $.get("https://www.meetup.com/" + self.id + "/unsubscribe/", function( data ) {

                              var token = data.match('name="token" value="(.*)"')[1];
                //console.log("token:", token);
                //console.log(self.id);
                $("#" + self.id).remove();
                $.post( "/" + self.id + "/unsubscribe/", {"exit_comment": "", "op":"submit", "token": token} );


                        });
        });

        }
    }   
    }

}

// give the page time to populate all the data on the page.

setTimeout(page_load, 2000);

A Pattern Language

The goal of this project is to create a very simple and concise language that I can use to create complex patterns which can then be sent to various machines to be processed (so I need to output in some sort of vector format.)

Before even starting the DSL portion of the project, I spent a lot of time experimenting with different ways to build patterns using python output to some sort of machine readable format. I started using DXF but it was weird and new (to me) and I didn't really like how much work it took to do anything in it. Then I switched over to using svg which is nice since it handles a lot of the transformations for me. Once I got some python code working that could output vector patterns, I moved on to making the DSL to control it.

The Tech Stack

The DSL

I'm using ANTLR to write the parser for the language, one of the nice features is that it can output and work with multiple languages, so if I want to switch to javascript down the road (better vect or support) at least the parser code will be easy to port over. ANTLR is also well documented (it has a boo k.) which makes le arning it pretty easy. I also put together this ANTLR python quickstart document.

Sample

ga = ((E20,20 T10,0 C0 )(RS4), (E15,15 T10,0 C1 )(RS4), (E8,4 T13,0 C0)(RS4));
mrgrid = GRID60,60,10,10,60,ga;
gb = (R10,10 RT45 C0);
tmp  = GRID90,90,9,9,60,gb;
RENDER(mrgrid, tmp);

Basic overview of what is above: ( full grammar )

Where I'm going from Here?

What I have now is a good proof of concept, but I really want to implment CSG functionality into it (so I can get cleaner/smaller output to work with), which means i'll probablly need to scrap most of the way i'm currently doing things. Also, I need to scrap the idea of using "shapes" and just make everything a ploygon, which will make working with the CSG libraries and converting back to svg much easier.

Easily write Haikus

A simple web-app to help you write Haikus, give it a try: * demo

Minimum Molecule Testing

Molecule is the default testing environment for ansible, unfortunately it requires a lot of boiler plate just to make it work (all I want it to do is just run my test and tell me if it worked!) This page is my attempt to strip down the amount of boiler plate code required to do testing with Molecule and do everything as DRY as possible.

The Setup

This setup assumes you are sane person using a mono-repo that contains all your roles. If you are breaking all your roles out into separate repos you've already set yourself up for a life of pain and misery; enjoy!

Directory layout

This is what your directory layout should look like. The roles_dir is the directory that contains all of your ansible roles. The my_role is the sample role we will be adding testing to.

roles_dir
  molecule_base
    default.yml
  my_role
    molecule
      default
        converge.yml
        verify.yml
        molecule.yml

The files

molecule_base/default.yml

This is the default config for molecule. In this example I'll be setting docker up to use docker with a cent7 image to test the role:

 ---
dependency:
  name: galaxy
driver:
  name: docker
platforms:
  - name: cent7
    image: docker.io/pycontribs/centos:7
    pre_build_image: true
provisioner:
  name: ansible
verifier:
  name: ansible
lint: |
  set -e
  yamllint .
  ansible-lint .

my_role/molecule/default/converge.yml

More boiler plate code required to run molecule, this is just telling molecule to run the role of the directory we are in.

 ---
- name: Converge
  hosts: all
  roles:
   - role: "{{ lookup('env', 'MOLECULE_PROJECT_DIRECTORY') | basename }}"

my_role/molecule/default/verify.yml

This file contains all the testing you want to do after you run your role. Because this file is ansible code which isn't very well suited for "testing", it can get very long and complicated to do simple things (like check if a file exists)

 ---
- name: Verify
  hosts: all
  gather_facts: false
  tasks:

  - name: include defaults
    include_vars:
      file: ../../defaults/main.yml

  - name: stat file
    stat:
      path: "{{ file_name }}"
    register: file_exist_check

  - name:
    assert:
      that:
        - file_exist_check.stat.exists == True
      success_msg: "{{ file_name }} exists pass"
      fail_msg: "{{ file_name }} does not exist fail"

my_role/molecule/default/molecule.yml

this file just needs to exist and be blank (yay more boiler plate)

Running Molecule

Now that you have your files setup, it's time to run molecule.

Other fun molecule commands

Note that m test will delete the docker instance at the end of the run, so if you want to login and poke around, you'll need to manually stand the instance up as shown in the command list above.

What is TPL

Tpl is a tool that creates boilerplate code for projects. I know there are other tools out there that can do this sort of thing, but they always seem huge and overly complicated; I just need to create a few files for a project so I can get moving. This also allows me to keep a library of templates that can be used to build projects that I can then build on top of, instead of always starting from scratch each time.

The tool, tpl, can be installed by just cloning the github repo into ~/.tpl and then creating a link from ~/.tpl/tpl to /usr/local/bin/tpl. After that, you can just run tpl from any directory and have it create content (tpl list to see what kind of content it knows about). Ways of storing information

The other motivation for making this tool was to explore the idea of making things you learn more usable. When you learn something new, there are multiple ways you can store what you learn; some are useful and some are not:

1) Bookmarks: you have a link to a page that has the information you want to be able to recall at a later time. When that time comes, you'll need to first remember what that bookmark was called, and second hope the site is still there, and has the information you were looking for. Not the best system, -1. 2) Personal Wiki/Evernote: This is better; as you are learning new things, you are updating your personal information store, and when you need to reference it again, you just search your notes. Assuming you have added the correct information to the entry, you can hopefully find the information you wrote down about it. This is better, and even more so if you stored the information in a usable format (not just copy/paste from the source material). 3) Making a tool: This (I think) is the best solution. As you learn new things, you build tools that implement the things you learn. Now when it comes times to use this information, instead of searching for it, parsing it, and converting it to a format you can use, you just use the tool you created.

A simple example:

A child is learning to add:

1) As the child learns to add, they could link to the resources they are using to learn with. When they get suck in the future, they can search through all of these resources for help. 2) As the child learns to add, they could keep their own notes in a personal information store, Converting ideas to their own words and putting the data in themselves will make the data more accessible later when they need to come back and find it. 3) As the child learns to add, they could write a calculator application. Now when they get stuck in the future, they can use the calculate to solve the problem (or to just check their work along the way to make sure they are doing things correctly.)

In this example, you can see the tool that implements what the child learned is the fastest and most useful way to store knowledge, and as the child learns new concepts (subtraction, division, multiplication ...etc) the tool can be updated to include all of this.

A tool for Boilerplate code

Extending the previous idea, when you want to create boilerplate code you could:

1) find a link to the website that has the example code you want, and tweak it to what you need. Every time you do this, you need to go through these steps, and possible find different version each time. 2) you could keep these snippets of code in your personal information store, and when it comes time to use them, you just search for your store, and paste what you need. This kind of works, but if the projects need multiple files, or directories this could get tedious and might introduce errors. 3) you could write a tool that capture how to create different types of projects, and then when you need to create a new project, all you need to do is run the tool and get a consistent project created. And as you learn, you can update the tool for new projects, or you can update existing templates with new knowledge, instead of starting from scratch each time.

Slowchat is an experiment in making messaging more tangible, slower, and more offline while at the same time an experimenting with what you can accomplish with a simple QR code. The basic idea behind Slow Chat, is you write a message to your friend in and interface you would expect in any basic chat program online, but when you click send, the program generates a printable page of your message you will need to send to the other person through the postal system (or you could hand deliver it to them, or have a pigeon deliver it, or ... . .. ) When the Other person gets your message, they then scan the page in, and the chat interface updates with the message (as you would expect from any other chat program.)

You could just send messages back and forth this way, but why not expand on the message; you are already sending the person a letter in the mail, why not add other things to the envelope, or decorate the envelope. (wouldn't it be fun if you could decorate incoming and outgoing TCP packets... ... future experiement noted...) What if you wanted to include an animated GIF in your message? You could use something like this http://gifprint.com/, to convert your gif to a flipbook, and then include the flipbook in the letter to the other person.

How does it work?

On a more technical level, I'm using the qr-scanner library to scan in qr codes, the qrcode library to create the qrcodes, lockr to save data localy to disk, and bootstrap and jquery to make things look prety.

As a side note, the webcam support for the qr code scanning only works with sites that are running HTTPS (grumbles), but I installed lets encrypt's certbot, and it was really just a next, next, installed. It did all the configuration of nginx for me and setup all the background work to run certbot. I wish all security related products were actually this easy to use. clip

Web Acknowledge is a firefox plugin that is there for you to log every time you are working on something, and your brain is like, HEY! HEY!!! YOU NEED TO GO CHECK THIS OTHER THING OUT! You click on the little brain icon in your firefox toolbar, type in what you where doing at the time and what your brain wanted you to go check, then you go back to do what you were doing (sorry brain).

This is mostly an experiment to see what triggers those urges to go do something stupid instead of concentrating. I'm also hoping it makes a good tool to help increase your ability to concentrate.

👈 Prev Day - Home - Next Day 👉