wip: working on support for posts and migrating old posts
parent
29f0316b44
commit
508c7f9af0
|
@ -1,3 +1,9 @@
|
||||||
baseURL = 'http://example.org/'
|
baseURL = 'https://kindrobot.ca/'
|
||||||
languageCode = 'en-ca'
|
languageCode = 'en-ca'
|
||||||
title = 'kindrobot.ca'
|
title = 'kindrobot.ca'
|
||||||
|
|
||||||
|
enableEmoji = true
|
||||||
|
[markup]
|
||||||
|
[markup.goldmark]
|
||||||
|
[markup.goldmark.renderer]
|
||||||
|
unsafe = true
|
|
@ -0,0 +1,201 @@
|
||||||
|
---
|
||||||
|
|
||||||
|
layout: post
|
||||||
|
title: "Arch on a Lenovo ThinkPad x140e"
|
||||||
|
date: 2014-12-26 22:37:00
|
||||||
|
categories: linux
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
Recently at work I had been virtualizing Arch Linux on a MacBook Pro using
|
||||||
|
VirtualBox. While there were many perks (easy backups, no hardware issues),
|
||||||
|
when I left that assignment (and had to give back the Mac), I couldn't justify
|
||||||
|
spending a grand on a Mac which would spend most of its time running Linux in a
|
||||||
|
virtual machine, so I set out to find a cheap, modern, Linux compatible laptop.
|
||||||
|
Ultimately, I landed on the Lenovo Thinkpad x140e which was [certified by
|
||||||
|
Canonical to run Ubuntu][canonical certification]. Unfortunately, for Arch
|
||||||
|
Linux, much of the hardware did not work out of the box. This post covers the
|
||||||
|
modifications I performed to get all of the hardware working including:
|
||||||
|
|
||||||
|
- graphics
|
||||||
|
- network adapters (wired and wireless)
|
||||||
|
- input devices (trackpad and trackpoint)
|
||||||
|
- sound
|
||||||
|
- Fn keys for volume and brightness
|
||||||
|
|
||||||
|
<!--more-->
|
||||||
|
|
||||||
|
This guide assumes that you've gone through all of the steps in the [Arch
|
||||||
|
installation guide][arch install]. For what it's worth, this guide is window
|
||||||
|
manager agnostic (or even atheist if you're just in terminal), though I'm using
|
||||||
|
[Awesome].
|
||||||
|
|
||||||
|
**Graphics**
|
||||||
|
|
||||||
|
The integrated Radeon HD 8330 card is supported by the proprietary driver,
|
||||||
|
`catalyst` (not recommended) or the open source `xf86-video-ati` driver. If
|
||||||
|
using the latter, also install the `mesa-libgq` for 3D acceleration and
|
||||||
|
`mesa-vdpau` for accelerated video decoding.
|
||||||
|
|
||||||
|
**Internet**
|
||||||
|
|
||||||
|
The ethernet card is supported by a driver in the kernel, you'll just need to
|
||||||
|
install a dhcp client (e.g. [dhcpcd]) to handle getting your computer to talk to
|
||||||
|
the router.
|
||||||
|
|
||||||
|
Wireless is a little tougher, the Broadcom chipset used is not yet supported by
|
||||||
|
any of the open source drivers, and so you'll need to follow the instructions
|
||||||
|
for [installing broadcom-wl drivers][wl]. Namely:
|
||||||
|
|
||||||
|
1. install `broadcom-wl` from the AUR
|
||||||
|
2. create a blacklist file named something like `/etc/modprobe.d/wireless.conf`
|
||||||
|
with the following:
|
||||||
|
|
||||||
|
```
|
||||||
|
blacklist brcm80211
|
||||||
|
blacklist b43
|
||||||
|
blacklist ssb
|
||||||
|
```
|
||||||
|
|
||||||
|
3. create a `modules-load.d` file named something like
|
||||||
|
`/etc/modules-load.d/wireless.conf` with:
|
||||||
|
|
||||||
|
```
|
||||||
|
wl
|
||||||
|
```
|
||||||
|
|
||||||
|
4. restart the machine.
|
||||||
|
|
||||||
|
You should then be able to connect to wireless through `wifi-menu` and `netctl`.
|
||||||
|
|
||||||
|
**Trackpad and Trackpoint**
|
||||||
|
|
||||||
|
I personally am not a fan of the track pad, but if you'd like yours to work
|
||||||
|
install `xf86-input-synaptics` and
|
||||||
|
[configure it to your liking][configure synaptics].
|
||||||
|
|
||||||
|
Trackpoint should work out of the box, though if you'd like middle button
|
||||||
|
scrolling, add the file `/etc/X11/xorg.conf.d/20-thinkpad.conf` with:
|
||||||
|
|
||||||
|
```
|
||||||
|
Section "InputClass"
|
||||||
|
Identifier "Trackpoint Wheel Emulation"
|
||||||
|
MatchProduct "TPPS/2 IBM TrackPoint|DualPoint Stick|Synaptics Inc. Composite TouchPad / TrackPoint|ThinkPad USB Keyboard with TrackPoint|USB Trackpoint pointing device"
|
||||||
|
MatchDevicePath "/dev/input/event*"
|
||||||
|
Option "EmulateWheel" "true"
|
||||||
|
Option "EmulateWheelButton" "2"
|
||||||
|
Option "Emulate3Buttons" "false"
|
||||||
|
Option "XAxisMapping" "6 7"
|
||||||
|
Option "YAxisMapping" "4 5"
|
||||||
|
EndSection
|
||||||
|
```
|
||||||
|
|
||||||
|
and restart.
|
||||||
|
|
||||||
|
**Sound**
|
||||||
|
|
||||||
|
While the integrated sound card is supported out of the box, the system will
|
||||||
|
most likely set the wrong default card and so you won't be able to hear
|
||||||
|
anything, you can correct this by disabling the other sound device (which is
|
||||||
|
actually just a virtual device exposed by `thinkpad_acpi` to represent the
|
||||||
|
volume and mute buttons, and is not really needed — see below) by adding a file
|
||||||
|
`/etc/modprobe.d/alsa-base.conf` with
|
||||||
|
|
||||||
|
```
|
||||||
|
options snd_hda_intel 1 enable=1 index=0
|
||||||
|
options snd_hda_intel 2 enable=0 index=1
|
||||||
|
```
|
||||||
|
|
||||||
|
and restarting. You'll still need to unmute all the channels using something
|
||||||
|
like `alsamixer`. Install `alsa-utils` through pacman and use `alsamixer` to
|
||||||
|
unmute the channels and adjust the volume.
|
||||||
|
|
||||||
|
**ACPI Events (volume and brightness keys)**
|
||||||
|
|
||||||
|
In the past I've configured the window manager to handle volume and brightness
|
||||||
|
function keys. However, using the Linux [ACPI daemond][acpid] allows your
|
||||||
|
machine to handle these keys strokes before you even start X! First install
|
||||||
|
`acpid` through pacman, and `start` and `enable` `acpid` using `systemctl`.
|
||||||
|
Next, you'll be making the events for the brightness and volume key presses.
|
||||||
|
|
||||||
|
`/etc/acpi/events/bl_d`
|
||||||
|
|
||||||
|
```
|
||||||
|
event=video/brightnessdown
|
||||||
|
action=/etc/acpi/handlers/bl -
|
||||||
|
```
|
||||||
|
|
||||||
|
`/etc/acpi/events/bl_u`
|
||||||
|
|
||||||
|
```
|
||||||
|
event=video/brightnessup
|
||||||
|
action=/etc/acpi/handlers/bl +
|
||||||
|
```
|
||||||
|
|
||||||
|
`/etc/acpi/events/vol_u`
|
||||||
|
|
||||||
|
```
|
||||||
|
event=button/volumedown
|
||||||
|
action=/etc/acpi/handlers/vol -
|
||||||
|
```
|
||||||
|
|
||||||
|
`/etc/acpi/events/vol_d`
|
||||||
|
|
||||||
|
```
|
||||||
|
event=button/volumeup
|
||||||
|
action=/etc/acpi/handlers/vol +
|
||||||
|
```
|
||||||
|
|
||||||
|
`/etc/acpi/events/mute`
|
||||||
|
|
||||||
|
```
|
||||||
|
event=button/mute
|
||||||
|
action=/usr/bin/amixer set Master toggle
|
||||||
|
```
|
||||||
|
|
||||||
|
Next make the directory `/etc/acpi/handlers`, in which create the following
|
||||||
|
files:
|
||||||
|
|
||||||
|
`/etc/acpi/events/bl`
|
||||||
|
|
||||||
|
```
|
||||||
|
#!/bin/sh
|
||||||
|
bl_dev=/sys/class/backlight/radeon_bl0
|
||||||
|
step=5
|
||||||
|
case $1 in
|
||||||
|
-) echo $(($(< $bl_dev/brightness) - $step)) >$bl_dev/brightness;;
|
||||||
|
+) echo $(($(< $bl_dev/brightness) + $step)) >$bl_dev/brightness;;
|
||||||
|
esac
|
||||||
|
```
|
||||||
|
|
||||||
|
`/etc/acpi/events/vol`
|
||||||
|
|
||||||
|
```
|
||||||
|
#!/bin/sh
|
||||||
|
step=5
|
||||||
|
case $1 in
|
||||||
|
-) amixer set Master $step-;;
|
||||||
|
+) amixer set Master $step+;;
|
||||||
|
esac
|
||||||
|
```
|
||||||
|
|
||||||
|
... and make these files executable with `sudo chmod 755 /etc/acpi/handlers/*`.
|
||||||
|
|
||||||
|
_Note that the `vol` handler require `amixer` which is part of the `alsa-utils`
|
||||||
|
package._
|
||||||
|
|
||||||
|
**Conclusion**
|
||||||
|
|
||||||
|
That's about it. There's always more to be done, from customizing your wifi to
|
||||||
|
auto-connect, to setting up external displays, to installing an configuring a
|
||||||
|
window manager, but after following these steps, all of your hardware should be
|
||||||
|
up and running properly.
|
||||||
|
|
||||||
|
|
||||||
|
[canonical certification]: http://www.ubuntu.com/certification/hardware/201309-14195/
|
||||||
|
[arch install]: https://wiki.archlinux.org/index.php/Installation_guide
|
||||||
|
[Awesome]: https://wiki.archlinux.org/index.php/Awesome
|
||||||
|
[dhcpcd]: https://wiki.archlinux.org/index.php/dhcpcd
|
||||||
|
[wl]: https://wiki.archlinux.org/index.php/Broadcom_wireless#broadcom-wl
|
||||||
|
[configure synaptics]: https://wiki.archlinux.org/index.php/Synaptics
|
||||||
|
[acpid]: https://wiki.archlinux.org/index.php/acpid
|
|
@ -0,0 +1,57 @@
|
||||||
|
---
|
||||||
|
|
||||||
|
layout: post
|
||||||
|
title: "Getting Candle Wax Off an LCD Monitor"
|
||||||
|
date: 2015-01-03 22:16:00
|
||||||
|
categories: life
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
First you might ask, "How does one get wax on their monitor?" A valid question.
|
||||||
|
In my case, I had a taper candle on my desk, and I blew it out right before bed.
|
||||||
|
When I awoke, I found a splatter of wax from the candle in the bottom left
|
||||||
|
corner of my LCD. This post will talk about the steps I took to safely remove
|
||||||
|
the wax from the monitor without damaging the surface or liquid crystals of the
|
||||||
|
display.
|
||||||
|
|
||||||
|
_Note that this guide is intended for soft-surface LCD monitors (the kind that
|
||||||
|
are not glass/plastic covered and make distorted colors when you press on the
|
||||||
|
screen.)_
|
||||||
|
|
||||||
|
<!--more-->
|
||||||
|
|
||||||
|
**Inspired by Mom**
|
||||||
|
|
||||||
|
A tried-and-proven method of removing wax from fabric is to put a paper towel on
|
||||||
|
top of the stained area and then apply a hot iron onto the paper towel. This
|
||||||
|
melts the wax which is absorbed into the towel. While this does work wonders on
|
||||||
|
fabric, there are some hopefully obvious reasons why this is a bad idea with an
|
||||||
|
LCD screen.
|
||||||
|
|
||||||
|
**Steps to Safely Remove Wax**
|
||||||
|
|
||||||
|
You will need:
|
||||||
|
|
||||||
|
- a hair dryer
|
||||||
|
- a screen safe cloth
|
||||||
|
- screen cleaner, glasses cleaner, or distiled water
|
||||||
|
|
||||||
|
It's a pretty straight forward process:
|
||||||
|
|
||||||
|
1. pre-wet the cloth with the screen safe cleaner (or distiled water)
|
||||||
|
1. remove the base of the monitor (if possible) and place the monitor flat
|
||||||
|
on the ground, screen-side up
|
||||||
|
1. turn on the hair dryer to low and hold tip about three inches from the
|
||||||
|
surface of the monitor aimed at the wax
|
||||||
|
1. keep holding the dryer in place for about thirty seconds
|
||||||
|
1. while still aiming the dryer at the wax, with your other hand, begin wiping
|
||||||
|
the affected area gently with the moist rag
|
||||||
|
1. keep wiping the area gently, re-wetting the cloth if it dries out, until all
|
||||||
|
the wax has been cleared
|
||||||
|
|
||||||
|
That's it, pretty simple! Do not rush by turning the dryer up to high or wiping
|
||||||
|
harder as the LCD screen is fragile and high heat could damage the crystals in
|
||||||
|
the monitor.
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,97 @@
|
||||||
|
---
|
||||||
|
|
||||||
|
layout: post
|
||||||
|
title: "Connecting to University of Cincinnati's Securewireless with netctl"
|
||||||
|
date: 2015-01-13 17:14:00
|
||||||
|
categories: linux
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
If you've set-up an Arch Linux installation, and you've used `wifi-menu` then
|
||||||
|
you've used [netctl][netctl] before and didn't even know it. `netctl` is
|
||||||
|
|
||||||
|
> ... a CLI-based tool used to configure and manage network connections via
|
||||||
|
> profiles. It is a native Arch Linux project for network configuration.
|
||||||
|
|
||||||
|
I used to think that the `wifi-menu` dialouge was a cute little installer helper
|
||||||
|
program, but I learned later, that it can be used to automatically generate
|
||||||
|
profiles in `/etc/netctl` that you can subsequently use to reconnect to network
|
||||||
|
later with
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# netctl start INTERFACE-SSID
|
||||||
|
```
|
||||||
|
|
||||||
|
... where *INTERFACE* is the name of your wireless interface device (see below)
|
||||||
|
and *SSID* is the "name" of the network.
|
||||||
|
|
||||||
|
I was a little disappointed (but not too shocked) when `wifi-menu` failed to
|
||||||
|
connect to the University of Cincinnati's `Securewireless` network. This short
|
||||||
|
guide will discuss the steps needed to connect to `Securewireless` using
|
||||||
|
`netctl`, and discuss why these extra steps are needed.
|
||||||
|
|
||||||
|
<!--more-->
|
||||||
|
|
||||||
|
**Connect to Securewireless — _tl;dr_**
|
||||||
|
|
||||||
|
Create and edit the file `/etc/netctl/INTERFACE-Securewireless` as root (using
|
||||||
|
`sudo`). Note that _INTERFACE_ should be the name of your wireless interface.
|
||||||
|
Use `ip link` to find out what it is. While the interface prefix is not
|
||||||
|
mandatory, it does help you stay organized, `wifi-menu` adds it by default, and
|
||||||
|
you'll need it below.
|
||||||
|
|
||||||
|
```
|
||||||
|
Connection='wireless'
|
||||||
|
Interface=INTERFACE
|
||||||
|
Security='wpa-configsection'
|
||||||
|
Description="UC eduroam-like network"
|
||||||
|
IP='dhcp'
|
||||||
|
TimeoutWPA=30
|
||||||
|
WPAConfigSection=(
|
||||||
|
'ssid="Securewireless"'
|
||||||
|
'key_mgmt=WPA-EAP'
|
||||||
|
'identity="UC_USER_NAME"'
|
||||||
|
'password="UC_CENTRAL_LOGIN_PASSWORD"'
|
||||||
|
)
|
||||||
|
```
|
||||||
|
|
||||||
|
Where *`INTERFACE`* is your wireless interface as described above,
|
||||||
|
*`UC_USER_NAME`* is your 6+2 user name without the domain suffix (e.g. smithbb1
|
||||||
|
**not** smithbb1@mail.uc.edu), and *`UC_CENTRAL_LOGIN_PASSWORD`* is the central
|
||||||
|
login password that you use for all of your UC services. (Leave in the quotes
|
||||||
|
around the actual username and password.)
|
||||||
|
|
||||||
|
**Details**
|
||||||
|
|
||||||
|
The magic is in the `wpa-configsection`/`WPAConfigSection`. This allows you to
|
||||||
|
step outside of simple WEP/WPA/WPA2 shared passphrase paradigm and set the
|
||||||
|
security stack exactly how you need as if you were setting up `wpa_supplicant`
|
||||||
|
by hand. There's a lot you can do here, like connect to an [eduroam][eduroam]
|
||||||
|
network or use another pre-agreed upon security certificate, but UC's setup is
|
||||||
|
pretty simple. If you need to see all of the settings you can put in the
|
||||||
|
WPAConfigSection, see the manual page for `wpa_supplicant` or look at a [sample
|
||||||
|
wpa_supplicant.conf][wpa_supplicant example].
|
||||||
|
|
||||||
|
University of Cincinnati uses WPA Enterprise much like other universities.
|
||||||
|
According to [UC's IT Handbook (last page)][uc_it_handbook](pdf), `Securewireless`
|
||||||
|
uses:
|
||||||
|
|
||||||
|
* WPA2 Enterprise Security
|
||||||
|
* Protected Extensible Authentication Protocol (PEAP)
|
||||||
|
* No enterprise security certificate
|
||||||
|
|
||||||
|
Through trial and error, I found the simplest `WPAConfigSection` needed to
|
||||||
|
successfully connect. `ssid` is set to `Securewireless`, the name of UC's
|
||||||
|
network. `key_mgmt=WPA-EAP` tells the WPA supplicant to use and `identity` and
|
||||||
|
`password` through (Protected) Extensible Authentication Protocol to connect to
|
||||||
|
the network.
|
||||||
|
|
||||||
|
I hope that this either helps you connect to `Securewireless` at UC or points
|
||||||
|
you in the right direction for creating a profile to connect to your WPA
|
||||||
|
Enterprise network at your school/work.
|
||||||
|
|
||||||
|
|
||||||
|
[netctl]: https://wiki.archlinux.org/index.php/netctl
|
||||||
|
[eduroam]: https://wiki.archlinux.org/index.php/WPA2_Enterprise#netctl
|
||||||
|
[wpa_supplicant example]: http://w1.fi/cgit/hostap/plain/wpa_supplicant/wpa_supplicant.conf
|
||||||
|
[uc_it_handbook]: http://ucdirectory.uc.edu/studentplanner/ITHandbook.pdf
|
|
@ -0,0 +1,81 @@
|
||||||
|
---
|
||||||
|
|
||||||
|
layout: post
|
||||||
|
title: "Idea for Part-time Agile Development Shop"
|
||||||
|
date: 2015-02-25 10:34:00
|
||||||
|
categories: life
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
Agile software development is awesome, but there's more to life than writing
|
||||||
|
code, developing software, and becoming the next successful start-up. People
|
||||||
|
might like to work part-time so that they can devote the rest of their time to
|
||||||
|
other things like school, research, theirs kids, or what-have-you in a
|
||||||
|
sustainable way. Unfortunately part-timer employees at full-time Agile shops can
|
||||||
|
create friction. Web search "agile part time employee" and you'll see a wash of
|
||||||
|
people trying to hammer out the problem of how to coordinate fragmented,
|
||||||
|
part-time, and/or remote teams in an agile work place. The problem, I think, is
|
||||||
|
that it's not possible, or at least it's very hard. Think: trying to jam a large
|
||||||
|
rectangular prism through a small circular hole. You might make it work, but
|
||||||
|
you're probably not going to like it.
|
||||||
|
|
||||||
|
But that's only thinking about the problem with the 8 hour work week as a
|
||||||
|
constant. Read on to see a proposed way to work agile, part-time.
|
||||||
|
|
||||||
|
<!--more-->
|
||||||
|
|
||||||
|
Agile Buy In
|
||||||
|
------------
|
||||||
|
Agile works when everyone buys into it 100%. You're going to partner all the
|
||||||
|
time, you're going all to test drive your code. You're all going to have small
|
||||||
|
teams (2-6) working on a sole project that stand-up and retrospect. You're going
|
||||||
|
to cycle your pairs within your team and the members of your team. Web search
|
||||||
|
"Agile the Pivotal Way" and watch [any of][AtPW1] [those videos][AtPW2] and
|
||||||
|
you'll get a good idea of what a well-running 100% agile/XP/alternative
|
||||||
|
development shop looks like.
|
||||||
|
|
||||||
|
[AtPW1]: https://vimeo.com/52923973
|
||||||
|
[AtPW2]: http://pivotallabs.com/103-agile-the-pivotal-way/
|
||||||
|
|
||||||
|
Being Part Time Isn't Lazy
|
||||||
|
--------------------------
|
||||||
|
Somehow, we've got it in our heads that working 8 hours a week (or more) at a
|
||||||
|
single job is needed. However, most people are self-admittedly multi-faceted.
|
||||||
|
They might want to pursue a graduate degree, learn about another subject
|
||||||
|
entirely, volunteer, be a Batista at a coffee house, home school their kids. The
|
||||||
|
exact motivation could be anything, let's merely acknowledge that it could be
|
||||||
|
awesome to split up your day, and flex your brain and body in different ways
|
||||||
|
throughout the day.
|
||||||
|
|
||||||
|
A Solution
|
||||||
|
----------
|
||||||
|
So you can see where the rub is, right? How do you get 100% Agile buy in and
|
||||||
|
let people work part-time? My proposed solution is to have everyone buy in to a
|
||||||
|
part-time development cycle. An example of your company's schedule could be
|
||||||
|
this:
|
||||||
|
|
||||||
|
00:00 - 12:00 - Company members live their lives away from work
|
||||||
|
12:00 - 13:00 - all Company members come to office, have lunch, and chat
|
||||||
|
13:00 - 13:30 - Company stands up, Company splits into teams
|
||||||
|
team stands up, split into pairs
|
||||||
|
13:30 - 18:00 - pairs program
|
||||||
|
~30 minutes is used in this block for one break big or multiple small breaks
|
||||||
|
18:00 - XX:XX - reform into Company, have drinks, unwind
|
||||||
|
XX:XX - 24:00 - Company members live their lives away from work
|
||||||
|
|
||||||
|
The formula is (approximately): one hour for lunch, half hour for stand-ups,
|
||||||
|
four-and-a-half hours for programing (with a half-hours worth of
|
||||||
|
break time sprinkled in), unwind, and go do whatever. *Optionally* (and I stress
|
||||||
|
**optionally**) company members can come together before work or after work and
|
||||||
|
have talks, perform research in groups, just hang out, but the important thing
|
||||||
|
is it is truly *their time*.
|
||||||
|
|
||||||
|
For me, the problem is right now is to find some people (at least one) to start
|
||||||
|
this crazy idea with. I am thinking of taking the summer and working
|
||||||
|
(full-time) for an agile shop or coaching a company into getting to agile, so
|
||||||
|
that I can get into that well-tested full-time agile groove and then in the fall
|
||||||
|
of 2015 coming together with a person/team form a Company doing part-time agile.
|
||||||
|
|
||||||
|
Are you crazy enough to give this a try this with me? Drop me a line:
|
||||||
|
<apocryphalauthor@gmail.com>.
|
||||||
|
|
|
@ -0,0 +1,46 @@
|
||||||
|
---
|
||||||
|
|
||||||
|
layout: post
|
||||||
|
title: "Hexaflexago: the friendly hexaflexagon template generator"
|
||||||
|
date: 2017-05-25 12:05:00
|
||||||
|
categories: projects
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
I was originally turned on to [hexaflexagons] while watching a [video by
|
||||||
|
vihart]. I’ve since become a tad obsessed. My partner, [Jane Meredith], and I
|
||||||
|
created [Hexaflexago], a hexaflexagon template generator.
|
||||||
|
|
||||||
|
[![Hexaflexago screenshot](/images/hexaflexago.png)](http://hexaflexago.motevets.com/)
|
||||||
|
|
||||||
|
# Features
|
||||||
|
- Generates a printable trihexaflexagon template
|
||||||
|
- Upload up the three images; Hexaflexago splices them into the template for
|
||||||
|
you
|
||||||
|
|
||||||
|
# Technical Notes
|
||||||
|
|
||||||
|
Written with:
|
||||||
|
- React.js using [create-react-app]
|
||||||
|
- the vanilla [SVG standard]
|
||||||
|
|
||||||
|
# What’s Next?
|
||||||
|
|
||||||
|
There are some improvements I’d like to make to Hexaflexago eventually.
|
||||||
|
- enable users to crop added images *(currently Hexaflexago letterboxes images
|
||||||
|
that are not regular hexagons)*
|
||||||
|
- add documentation on how to fold the hexaflexagon template
|
||||||
|
- support adding six images to make hexahexaflexagons
|
||||||
|
|
||||||
|
I’m also currently working with [Littoral Press] to make hexaflexagon business
|
||||||
|
cards. Here’s a prototype:
|
||||||
|
|
||||||
|
![Hexaflexagon business cards](/images/hexaflexagon_business_cards.jpg)
|
||||||
|
|
||||||
|
[Jane Meredith]: https://jane.biz/
|
||||||
|
[hexaflexagons]: http://vihart.com/hexaflexagons/
|
||||||
|
[video by vihart]: https://www.youtube.com/watch?v=VIVIegSt81k
|
||||||
|
[Hexaflexago]: http://hexaflexago.motevets.com/
|
||||||
|
[create-react-app]: https://github.com/facebook/create-react-app
|
||||||
|
[Littoral Press]: http://littoralpress.com/
|
||||||
|
[SVG standard]: https://developer.mozilla.org/en-US/docs/Web/SVG
|
|
@ -0,0 +1,33 @@
|
||||||
|
---
|
||||||
|
|
||||||
|
layout: post
|
||||||
|
title: "🦆.to"
|
||||||
|
date: 2017-05-25 12:05:00
|
||||||
|
categories: projects
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
[![un moment](/images/duck_loading.png)](http://🦆.to)
|
||||||
|
|
||||||
|
Though ICANN has disallowed emojis in domain names<sup>[1]</sup>, some ccTLD (country code top-level domain) registrars have gone rouge and permit (and even encourage) the purchase of emoji domains. One of the first ccTLDs to do this was .ws which is the TLD for Samoa. Normally when a new ccTLD announces that they are selling emoji domains, the single emoji domains sell out fast. When I found that .to was selling emoji domains, almost every single emoji domain was gone when I got there. Luckily there's nothing stopping you from registering emoji domains for emoji that haven't been implemented by most phones and OSes yet. This is how I came to own 🦆.to.
|
||||||
|
|
||||||
|
I waited for a while for most people to have 🦆 on their emoji keyboard, but even well after that, I didn't know what to do with my new domain. One weekend, I had some spare time, and decided to make what I thought would be a temporary parking space, but which turned out to be a labor of love that I am very proud to introduce to you here.
|
||||||
|
|
||||||
|
[🦆.to] first brings up a loading screen with an adorable animated duck and then shows a random duck GIF from [giphy.com].
|
||||||
|
|
||||||
|
[![Ce n'est pas un canard.](/images/ducks.gif)](http://🦆.to)
|
||||||
|
|
||||||
|
Some things that I personally learned in this project are:
|
||||||
|
- registering an emoji domain using [punycode]
|
||||||
|
- using the new-ish [`fetch` API] to [make asynchronous API calls to the giphy API](https://github.com/motevets/duck/blob/78bd1ea492fc5018307e4c7b7d6647a762023f7f/index.html#L13)
|
||||||
|
- making a modest responsive web page by:
|
||||||
|
- using [`vmin`] to [scale the font size](https://github.com/motevets/duck/blob/78bd1ea492fc5018307e4c7b7d6647a762023f7f/index.html#L74)
|
||||||
|
- setting the [`viewport`] so that the site looks consistent on mobile browsers without using media queries
|
||||||
|
|
||||||
|
[1]: https://features.icann.org/ssac-advisory-use-emoji-domain-names
|
||||||
|
[giphy.com]: http://giphy.com
|
||||||
|
[🦆.to]: http://🦆.to/
|
||||||
|
[`fetch` API]: https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API
|
||||||
|
[`vmin`]: https://css-tricks.com/simple-little-use-case-vmin/
|
||||||
|
[`viewport`]: https://developer.mozilla.org/en-US/docs/Mozilla/Mobile/Viewport_meta_tag
|
||||||
|
[punycode]: https://en.wikipedia.org/wiki/Punycode
|
|
@ -0,0 +1,51 @@
|
||||||
|
---
|
||||||
|
|
||||||
|
layout: post
|
||||||
|
title: "mintwise"
|
||||||
|
date: 2020-06-08 12:05:00
|
||||||
|
categories: projects
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
[![mintwise logo](/images/mintwise_logo.svg)][mintwise]
|
||||||
|
|
||||||
|
So imagine this scenario: you move in with your partner and you want to start splitting rent, utilities, groceries, dining out, vacation expenses, home goods expenses, etc. "Don't worry," you say, "there's an app for that, [Splitwise]!"
|
||||||
|
|
||||||
|
Great! Now all you have to do is comb through all of your credit card expenses at the end of the month and put them in Splitwise... and put the right date... and the right category...
|
||||||
|
|
||||||
|
"No problem," you say, "I'll just put in the expenses into the Splitwise app as I pay for them." Well, except you forget to put a few expenses in at the time you're purchasing them. Now it's the end of the month, and you're still going through your credit card statement _and_ deduping the ones you've already put in.
|
||||||
|
|
||||||
|
"There has to be a better way," you say, "I know! I'm a software engineer. If there's anything I'm good at, it's over engineering a solution to a minor annoyance!"
|
||||||
|
|
||||||
|
Enter **[mintwise]**, a command line interface to pull the transactions from all of your credit cards out of [Mint] and put them into [Splitwise]. Mint is a free<sup>1</sup> webapp that aggregates all of the transactions from all of your provided financial institutions to show you a snapshot of your finances. It also employs machine learning to categorize your expenses, to help you track how you're spending your money. Because I already use Mint, I thought it would be convenient if I could export selected expenses from Mint into Splitwise. Unfortunately, Mint does not have a public API, but luckily, there's an open-source Javascript SDK for scraping your transactions off of the Mint webapp, [pepper-mint]. On the other hand, Splitwise _does_ have [a public API][splitwise-api], so once I had a way to export all of my credit card transactions from Mint, importing them into Splitwise was straightforward.
|
||||||
|
|
||||||
|
## Some ways that this was totally over engineered
|
||||||
|
|
||||||
|
mintwise offers the following features:
|
||||||
|
- shows you your expenses one-by-one and allows you to select whether or not you want to split them
|
||||||
|
- automatically translates Mint categories into Splitwise categories (if it doesn't know the mapping, it'll ask you and then save it)
|
||||||
|
- allows you to specify a date range from which to pull expenses
|
||||||
|
- lets you specify which accounts are in Canadian dollars (because thats something [Mint doesn't track for some reason][mint-usd-cad])
|
||||||
|
- offers alternate import experience where you export your Mint transactions as a CSV, and use that to import transactions into Splitwise
|
||||||
|
|
||||||
|
While I didn't write any tests for mintwise, in order to make it easier to refactor, I used type checking in Node.js using [Flow's comment syntax] (so that I didn't have to introduce Webpack to strip out annotations.) I also tried my hand at using the MVC (Model, View, Controller) pattern for a CLI app.
|
||||||
|
|
||||||
|
## Conclusion
|
||||||
|
|
||||||
|
In the end, I have probably spent way more time writing mintwise than I ever would have manually entering expenses into Splitwise. My partner has a much simpler solution, just use one credit card for shared expenses.
|
||||||
|
|
||||||
|
However, I had a really good time working on mintwise. When I am working my day job, I have to be careful not to fall in the trap of over engineering a solution and pushing back the deliverable from what the team estimated. So it's nice to come home, put on my cowboy hat, and ride off into the sunset.
|
||||||
|
|
||||||
|
[Try out mintwise for yourself.][mintwise]
|
||||||
|
|
||||||
|
-----------
|
||||||
|
1: Mint is provided for free from Intuit, who makes money by [anonymizing, packing up, and selling your financial data to third parties][mint-business-strategy].
|
||||||
|
|
||||||
|
[Splitwise]: https://splitwise.com
|
||||||
|
[mintwise]: https://github.com/motevets/mintwise
|
||||||
|
[Mint]: https://mint.com
|
||||||
|
[mint-business-strategy]: https://www.investopedia.com/articles/personal-finance/082216/how-mintcom-makes-money-intu.asp
|
||||||
|
[pepper-mint]: https://github.com/dhleong/pepper-mint
|
||||||
|
[splitwise-api]: https://dev.splitwise.com/#introduction
|
||||||
|
[mint-usd-cad]: https://www.reddit.com/r/PersonalFinanceCanada/comments/4vom5o/mint_with_usd_and_cad_accounts/
|
||||||
|
[Flow's comment syntax]: https://flow.org/en/docs/types/comments/
|
|
@ -0,0 +1,45 @@
|
||||||
|
---
|
||||||
|
author: "lee.so"
|
||||||
|
title: "Emoji Support"
|
||||||
|
date: "2019-03-05"
|
||||||
|
description: "Guide to emoji usage in Hugo"
|
||||||
|
tags:
|
||||||
|
- emoji
|
||||||
|
---
|
||||||
|
|
||||||
|
Emoji can be enabled in a Hugo project in a number of ways.
|
||||||
|
<!--more-->
|
||||||
|
The [`emojify`](https://gohugo.io/functions/emojify/) function can be called directly in templates or [Inline Shortcodes](https://gohugo.io/templates/shortcode-templates/#inline-shortcodes).
|
||||||
|
|
||||||
|
To enable emoji globally, set `enableEmoji` to `true` in your site's [configuration](https://gohugo.io/getting-started/configuration/) and then you can type emoji shorthand codes directly in content files; e.g.
|
||||||
|
|
||||||
|
<p><span class="nowrap"><span class="emojify">🙈</span> <code>:see_no_evil:</code></span> <span class="nowrap"><span class="emojify">🙉</span> <code>:hear_no_evil:</code></span> <span class="nowrap"><span class="emojify">🙊</span> <code>:speak_no_evil:</code></span></p>
|
||||||
|
<br>
|
||||||
|
|
||||||
|
The [Emoji cheat sheet](http://www.emoji-cheat-sheet.com/) is a useful reference for emoji shorthand codes.
|
||||||
|
|
||||||
|
***
|
||||||
|
|
||||||
|
**N.B.** The above steps enable Unicode Standard emoji characters and sequences in Hugo, however the rendering of these glyphs depends on the browser and the platform. To style the emoji you can either use a third party emoji font or a font stack; e.g.
|
||||||
|
|
||||||
|
{{< highlight html >}}
|
||||||
|
.emoji {
|
||||||
|
font-family: Apple Color Emoji, Segoe UI Emoji, NotoColorEmoji, Segoe UI Symbol, Android Emoji, EmojiSymbols;
|
||||||
|
}
|
||||||
|
{{< /highlight >}}
|
||||||
|
|
||||||
|
{{< css.inline >}}
|
||||||
|
<style>
|
||||||
|
.emojify {
|
||||||
|
font-family: Apple Color Emoji, Segoe UI Emoji, NotoColorEmoji, Segoe UI Symbol, Android Emoji, EmojiSymbols;
|
||||||
|
font-size: 2rem;
|
||||||
|
vertical-align: middle;
|
||||||
|
}
|
||||||
|
@media screen and (max-width:650px) {
|
||||||
|
.nowrap {
|
||||||
|
display: block;
|
||||||
|
margin: 25px 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
{{< /css.inline >}}
|
|
@ -5,7 +5,7 @@
|
||||||
<title>{{ block "title" . }}
|
<title>{{ block "title" . }}
|
||||||
{{ .Site.Title }}
|
{{ .Site.Title }}
|
||||||
{{ end }}</title>
|
{{ end }}</title>
|
||||||
<link rel="stylesheet" type="text/css" href="style.css">
|
<link rel="stylesheet" type="text/css" href="/style.css">
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<!-- Code that all your templates share, like a header -->
|
<!-- Code that all your templates share, like a header -->
|
||||||
|
|
|
@ -0,0 +1,20 @@
|
||||||
|
{{ define "main" }}
|
||||||
|
<style>
|
||||||
|
.li-flex {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
margin-bottom: 0.25em;
|
||||||
|
}
|
||||||
|
.li-flex a {
|
||||||
|
width: 70%;
|
||||||
|
}
|
||||||
|
.li-flex .meta {
|
||||||
|
width: 20%;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<li>
|
||||||
|
<div class="li-flex">
|
||||||
|
<a href="{{ .Permalink }}">{{ .Title }}</a> <span class="meta">{{ .Date.Format "02 Jan 2006" }}</span>
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
{{ end }}
|
|
@ -0,0 +1,10 @@
|
||||||
|
{{ define "main" }}
|
||||||
|
<main id="main">
|
||||||
|
<div>
|
||||||
|
<h1 id="title">{{ .Title }}</h1>
|
||||||
|
{{ range .Pages }}
|
||||||
|
{{ .Render "summary"}}
|
||||||
|
{{ end }}
|
||||||
|
</div>
|
||||||
|
</main>
|
||||||
|
{{ end }}
|
|
@ -0,0 +1,9 @@
|
||||||
|
{{ define "main" }}
|
||||||
|
<main id="main">
|
||||||
|
<div>
|
||||||
|
<h1 id="title">{{ .Title }}</h1>
|
||||||
|
|
||||||
|
{{.Content}}
|
||||||
|
</div>
|
||||||
|
</main>
|
||||||
|
{{ end }}
|
|
@ -0,0 +1,12 @@
|
||||||
|
{{ define "main" }}
|
||||||
|
<article class="post">
|
||||||
|
<header>
|
||||||
|
<h2><a href='{{ .Permalink }}'> {{ .Title }}</a> </h2>
|
||||||
|
<div class="post-meta">{{ .Date.Format "Mon, Jan 2, 2006" }} - {{ .FuzzyWordCount }} Words </div>
|
||||||
|
</header>
|
||||||
|
{{ .Summary }}
|
||||||
|
<footer>
|
||||||
|
<a href='{{ .Permalink }}'><nobr>Read more →</nobr></a>
|
||||||
|
</footer>
|
||||||
|
</article>
|
||||||
|
{{ end }}
|
|
@ -13,10 +13,13 @@
|
||||||
<div class="homepage-content">
|
<div class="homepage-content">
|
||||||
{{.Content}}
|
{{.Content}}
|
||||||
</div>
|
</div>
|
||||||
|
<hr/>
|
||||||
<div>
|
<div>
|
||||||
|
<ul>
|
||||||
{{ range first 10 .Site.RegularPages }}
|
{{ range first 10 .Site.RegularPages }}
|
||||||
{{ .Render "summary"}}
|
{{ .Render "li" }}
|
||||||
{{ end }}
|
{{ end }}
|
||||||
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
<hr/>
|
<hr/>
|
||||||
<div id="tilde_ring" style="background-color:slategray; text-align:center; border-radius:10px;">
|
<div id="tilde_ring" style="background-color:slategray; text-align:center; border-radius:10px;">
|
||||||
|
|
Loading…
Reference in New Issue