Monday, July 17, 2017

OpenSCAD -- calculating a chord segment

Given chord length c and segment height m (this is called a "sagitta"),

radius = (m^2 + (c^2)/4) / (2 m)

In OpenSCAD:

c=20;
m=5;
radius=(pow(m,2) + pow(c,2)/4)/(2*m);



https://softsolder.com/2013/08/02/making-finger-grip-dents-the-chord-equation
https://en.wikipedia.org/wiki/Circle#Sagitta

blogodex = {"idx": ["openSCAD", "circle"]};

Wednesday, May 10, 2017

Keys, Primary and Foreign

Welcome to the Bank

Suppose we have an oversimplified banking system, with two tables.

create table balances(name string, balance number);
create table transactions(tid number, from string, to string, amount number);

This allows us to populate a table of people with balances, and transactions where people give money to each other.

    balances
    name | balance
    -----+--------
    ann  | 200
    bob  | 150
    leo  | 300

    transactions
    tid | from | to  | amount
    ----+------+-----+-------
    1   | ann  | bob | 25
    2   | bob  | leo | 50

We can imagine traversing the transaction table something like this pseudocode:

    for (from, to, amount) in select("select from,to,amount
                                        from transactions
                                       order by tid")
        begin transaction
           update balances set balance = balance - amount where name = from;
           update balances set balance = balance + amount where name = to;
        commit;

(note that sql implementations all vary slightly in how tables and indexes are creates.  Everything following is pseudocode.)

Some Data Problems?

Here's a couple of problems we've got in the present system.

  1. We can have empty (null) fields.  For example, a transaction of insert (3,bob,NULL,NULL).
  2. We can have duplicate people in the balance table.  Note that it's OK if balances are duplicated (you and I can have the same amount of money!) but each person must be unique.
  3. We are going to be performing lookups keyed by transactions.tid and balances.name.  We better make that efficient if we're going to grow to be a bank with millions of users and transactions!

Some Data Solutions

1. Let's specify all fields that are required.

    create table balances(name string not null, balance number not null);
    create table transactions(tid number not null, from string not null,
                              to string not null, amount number not null);

Now a transaction will fail if we insert a row with a null column.  This  is nice, because now our code can safely assume we have good non-null data).

2. Specify we can't have duplicate names.

    create table balances(name string unique not null, balance number not null);

This will cause an error if we ever

    insert into balances(name, balance) values('bob', 100);
    insert into balances(name, balance) values('bob', 200);

3. Create some indexes on our key search columns.

    create index balances_name_ix on balances(name);
    create index transactions_tid_ix on transactions(tid);

Primary Keys

When we look at our tables, we notice that each has a column which serves as the main identifier of a row.

  - balances are "owned" by name
  - transactions are identified (and ordered) by tid.

We notice three things about these columns.

  • they should never be null (because they identify the row)
  • they should be unique (because it doesn't make sense for them to be dupes)
  • practically, they should have an index (because we usually use them in where clauses).

The concept of a table having a main identifying column, and that column having the three attributes just listed, is so common that we give this a name:  That column is the primary key, and can be specified as such.

    create table balances(name string primary key, balance number not null);
    create table transactions(tid number primary, from string not null,
                              to string not null, amount number not null);

Declaring a column to be a primary key automatically sets the three things we noticed earlier.

  - primary keys are NOT NULL
  - primary keys are UNIQUE
  - there's an index automatically created for the PK

In addition, via notation we've specified that the row's "identifier" is a particular key... we don't have to guess or infer this information.

Foreign Keys

Let's consider a row in the transactions table:

    (1, "ann", "zoo", 50);

If we run this throught the pseudocode above, everything will work and no errors will be reported.  But there's a very big problem.  This statement is correct,

    update balances set balance = balance + amount where name = 'zoo'

but it loses the $50 ann is trying to transfer, since there's no row in balances where name is 'zoo'.

We can solve this in the database by specifying that transactions.from and transactions.to refer to balances.name.  Note that semantically this removes the requirement that we declare transactions.from and transactions.to as NOT NULL, since they are required to match balances.name.

    create table transactions(tid number primary,
                              from string references(balances.name),
                              to string references(balances.name),
     amount number not null);

With this in place, this insert will fail:

    insert into transactions values(1, 'ann', 'foo', 100);
    *** ERROR: foo does not exist in balances(name)

and this delete will fail:

    delete from balances where name = 'ann';
    *** ERROR: can't delete row with dependencies

There are various options when creating foreign keys, such as ON CASCADE DELETE.  In this case,

    delete from balances where name = 'ann';

would cause this statement to be implicitly executed as part of the transaction.

    delete from transactions where from = 'ann' or to = 'ann';

Caveats

Note that a lot of systems might document the foreign key relations are, but not enforce them in the database, relying instead on programming logic.  Sometimes this is done for efficiency (e.g. many inserts into the transactions table -- if you verify from and to are correct, you don't want to pay two lookups penalty on each insert).

A Common PK/FK Idiom

Splitting a potential Fat table into several smaller tables.  Sometimes it's for ease of use, sometimes it's for other reasons.  For example

    create table master_users(uid, Name);
    create table billing_info(uid, credit_card, expires, ...);
    create table contact_info(uid, address, email, phone, ...);
    create table lawsuit_info(uid, ...)

We might be legally required to protect lawsuit_info and not make it visible to people who can see contact info.

In any case, we would make uid a PK in all four tables, allowing us to

    # get everyone
    select m.name, b.email
      from master_users m, billing_info b
     where m.uid = b.uid;

    # get one person
    select m.name, b.email
      from master_users m, billing_info b
     where m.uid = b.uid and m.uid = 123;

And we could optionally add FK relationships from *_info.uid to master_users.uid.

Thursday, November 24, 2016

Arduino Stepper with ULN2003 driver

// stepper1 -- repeat 1 CW and CCW revolution
/*
https://arduino-info.wikispaces.com/SmallSteppers
5v 28YBJ-48 Stepper Motor with Gear Reduction
ULN2003 driver board
*/

#include

// internal motor steps per revolution in 4-step mode
#define STEPS_PER_MOTOR_REVOLUTION 32

// steps per OUTPUT SHAFT of gear reduction
#define STEPS_PER_OUTPUT_REVOLUTION (STEPS_PER_MOTOR_REVOLUTION*64)

//The pin connections need to be 4 pins connected
// to Motor Driver In1, In2, In3, In4  and then the pins entered
// here in the sequence 1-3-2-4 for proper sequencing
Stepper s(STEPS_PER_MOTOR_REVOLUTION, 8, 10, 9, 11);

void setup()
{
  s.setSpeed(500);  // 700 good max?
}

void loop()
{
  s.step(2 * STEPS_PER_OUTPUT_REVOLUTION);  // CW 1 turn
  s.step(-STEPS_PER_OUTPUT_REVOLUTION); // CCW 1 turn
  delay(500);
}

Friday, November 4, 2016

Perfect SSL Score with Go

Peter Lambert makes it look easy!

https://blog.bracelab.com/achieving-perfect-ssl-labs-score-with-go
https://gist.github.com/denji/12b3a568f092ab951456#perfect-ssl-labs-score-with-go

Arduino Encryption

I've been looking at encryption libraries that would run on an Arduino.  This looks like something worth looking into.
This library contains a cryptographic pseudo-random number generator, cryptographic hash and message authentication code (MAC) functions, can perform symmetric-key authenticated data encryption, and general-purpose functions for timing-safe comparison and wiping data from memory.
https://hackaday.io/project/8244-arduino-spritz-cipher-library
https://github.com/abderraouf-adjal/ArduinoSpritzCipher
https://people.csail.mit.edu/rivest/pubs/RS14.pdf

Monday, September 12, 2016

Vim + Go + Mac

There's a lot of notes written for getting Vim + Go up and running, but a lot of the notes assume you're already in modern Vim-land.  Here's what I did to get up and going from scratch.

0.  Start off with a totally clean vim configuration.

Save off your current files/setting if they're important to you.

    cd $HOME
    rm -rf .vim .vimrc .viminfo

1.  Install a vim with lua support.

I think the easiest way to do this is to install the latest macvim from Homebrew.  If you're a developer on Mac,  Homebrew is well worth looking into.

    brew install macvim --with-cscope --with-lua --override-system-vim
    brew linkapps macvim
    brew install vim --with-lua --override-system-vim

2.  Install Vundle

There's a couple of Vim package managers.  I don't know enough about Vim package management to recommend one over another, but Vundle seems to be pretty popular.

    git clone https://github.com/VundleVim/Vundle.vim ~/.vim/bundle/Vundle.vim

Here's the minimal .vimrc needed to get bootstrapped.

    set nocompatible              
    filetype off                  

    set rtp+=~/.vim/bundle/Vundle.vim

    call vundle#begin()
    Plugin 'VundleVim/Vundle.vim'
    "Plugin 'Valloric/YouCompleteMe'    reserve for step 3 below
    "Plugin 'fatih/vim-go'              <------- font="" nbsp="">reserve for step 4 below
    call vundle#end()            

    filetype plugin indent on    

Restart vim and install the plugins with the command

    :PluginInstall

3. Install YouCompleteMe

This require you install XCode from Apple.  Start off by installing cmake.

    brew install cmake

Install YouCompleteMe and pull in submodules.

    cd ~/.vim/bundle
    git clone git@github.com:Valloric/YouCompleteMe.git
    cd ~/.vim/bundle/YouCompleteMe
    git submodule update --init --recursive

Build YouCompleteMe

    cd ~/.vim/bundle/YouCompleteMe
    ./install.py --gocode-completer

Make sure ~/.vimrc has the line

Plugin 'Valloric/YouCompleteMe'

Restart vim and install the plugin as we did above


    :PluginInstall

4. Install Vim-Go

Download the latest release from https://github.com/fatih/vim-go/releases and untar it.

    cd /tmp
    curl -s https://codeload.github.com/fatih/vim-go/tar.gz/v1.8 | tar xf -

And move all the directories into .vim.  It seems there should be and easier way to do this... ping me if you know what it is!

    (cd /tmp/vim-go-1.8; tar cf - autoload compiler doc \
       ftdetect ftplugin gosnippets indent plugin scripts syntax t templates) |
      (cd ~/.vim; tar xf -)

Then add to .vimrc

    Plugin 'fatih/vim-go'

Restart vim and run

    :PluginInstall

Tuesday, August 30, 2016

Mapping Ctrl, CapsLock Tap to Esc

Now you can vi just as Bill Joy intended!  Here's an article that makes tapping the control key send an Esc.

Setting up ssh for github

On Mac and Linux, set up an ssh key in the usual way:

    ssh-keygen
    cat $HOME/.ssh/id_rsa.pub

Copy that into the github ssh keylist.

Linux:  start the ssh agent.  This will be good for the duration of the session.

    exec ssh-agent bash
    ssh-add

Mac: add the ssh key to the keychain. This only needs to be done once.

    ssh-add

To test your connection to github.

    ssh -T git@github.com

Thursday, June 23, 2016

GitHub based dotfiles

Not much new here, this is just my take on StreakyCobra's excellent work, with these differences:

  • I made two repos, one for dotfiles, one for scripts that go into $HOME/bin.
  • I made two commands dotf and binf that correspond to StreakyCobra's config.
  • incorporated github repos dotf and binf as noted.

# create github repo "dotf"
git init --bare $HOME/.dotf
alias dotf='/usr/bin/git --git-dir=$HOME/.dotf/ --work-tree=$HOME'
dotf config status.showUntrackedFiles no
dotf add .bash_profile

dotf commit -m "first import"
dotf remote add origin git@github.com:YOURNAME/dotf.git
dotf push -u origin master

# create github repo "binf"

git init --bare $HOME/.binf
alias binf='/usr/bin/git --git-dir=$HOME/.binf --work-tree=$HOME/bin'
# binf config status.showUntrackedFiles no  ## want to track unused files

cd $HOME/bin
dotf add some-file
dotf commit -m "first import"
binf remote add origin git@github.com:YOURNAME/binf.git
binf push -u origin master


Wednesday, June 15, 2016

Do you have a restless urge to program?

I finally found a scan advertising the Famous Programmers' School which originally appeared in the April 1982 of BYTE, page 384.

"Top down programming for the masses."

Friday, May 13, 2016

Adding a git commit template

So I find myself constantly forgetting to add the jira ticket number to commits that need them.

echo JIRA >~/txt/git-commit-template.txt

And one of these commands

git config commit.template ~/txt/git-commit-template.txt
git config --global commit.template ~/txt/git-commit-template.txt

or put in in .git/config (per repo) or $HOME/.gitconfig (global):

    [commit]
            template = /Users/mh/txt/git-commit-template.txt


Don't forget to manage your git commit template in git!

blogodex = {"toc" : "git", "idx" : "commit template"};

Friday, April 29, 2016

Python: virtualenv quickstart

Installation

pip install virtualenv

Usage

mkdir myproject
cd myproject
virtualenv foo
source foo/bin/activate
pip install hjson       # install packages...
./foo/bin/python
import hjson

Getting pip if necessary

curl -o get-pip.py https://bootstrap.pypa.io/get-pip.py
python get-pip



Getting ssl if necessary in order to get pip on your linux box

symptom:    ImportError: cannot import name HTTPSHandler

yum install openssl openssl-devel
or
apt-get install openssl openssl-devel


References
https://pip.pypa.io/en/stable/installing/
http://docs.python-guide.org/en/latest/dev/virtualenvs/

Wednesday, April 27, 2016

Encrypting UDP Game Traffic

not only encryption protects your players from classical attacks, it also protects your games against cheaters too.
As a side bonus, with proper encryption you can be sure that network errors which corrupt your packets are not going undetected (and with unencrypted UDP those 16-bit UDP checksums can detect only one out of 60’000 in-transit corruptions, which means that with all those millions of packets you’re sending out each second, some corruptions WILL go undetected, causing all kinds of trouble).

http://ithare.com/udp-for-games-security-encryption-and-ddos-protection/


Tuesday, April 19, 2016

Classic Programmer Paintings!

http://classicprogrammerpaintings.tumblr.com

My Favorite:




Hieronymus Bosch “A visual guide to the Scala language”  oil on oak panels, 1490-1510.

The left panel shows the functional features, the main one describes the type system, and the right the object oriented parts.

Friday, March 18, 2016

brewing mysql / binlog reader

Here's what I did to set up MySQL 5.6 on my Mac in binlog row mode, prepping to talk to Aurora.
+1 for brew services!

Install and Test

brew install mysql56
brew tap homebrew/services
brew services start mysql56

mysqladmin -uroot create mh
mysql -uroot

Find my.cnf

/usr/local/bin/mysqld --verbose --help 2>/dev/null | grep -A 1 "Default options" 
Default options are read from the following files in the given order:
/etc/my.cnf /etc/mysql/my.cnf /usr/local/etc/my.cnf ~/.my.cnf

Configuring binary logging

$ cat /usr/local/etc/my.cnf 
[mysqld]
log-bin=mysql-bin
binlog_format=row
server-id=1235

binlog status

Restart mysql and you can see the logs and current position.

mysql> show binary logs;
+------------------+-----------+
| Log_name         | File_size |
+------------------+-----------+
| mysql-bin.000001 |       143 |
| mysql-bin.000002 |       120 |

+------------------+-----------+
mysql> show master status;
+----------------+----------+-
| File           | Position | 
+----------------+----------+- . . . 
| mysql-bin.000002 |     1309 

+----------------+----------+-

Tailing the binlog


mysqlbinlog --read-from-remote-server --host=localhost  mysql-bin.000001 -uroot -v --stop-never

Insert some data like this

mysql> insert into t values(99);

and you'll see it come out like this

# at 1309
#160318 11:40:42 server id 1235 end_log_pos 1379 CRC32 0xaf303ba0 Query thread_id=7 exec_time=0 error_code=0
SET TIMESTAMP=1458326442/*!*/;
BEGIN
/*!*/;
# at 1379
#160318 11:40:42 server id 1235 end_log_pos 1421 CRC32 0xb302b235 Table_map: `mh`.`t` mapped to number 70
# at 1421
#160318 11:40:42 server id 1235 end_log_pos 1461 CRC32 0x4d9e5013 Write_rows: table id 70 flags: STMT_END_F

BINLOG '
qkvsVhPTBAAAKgAAAI0FAAAAAEYAAAAAAAEAAm1oAAF0AAEDAAE1sgKz
qkvsVh7TBAAAKAAAALUFAAAAAEYAAAAAAAEAAgAB//5jAAAAE1CeTQ==
'/*!*/;
### INSERT INTO `mh`.`t`
### SET
###   @1=99
# at 1461
#160318 11:40:42 server id 1235  end_log_pos 1492 CRC32 0x94dcc720 Xid = 73
COMMIT/*!*/;


blogodex = {"toc" : "MySQL binlog", "idx" : ["MySQL","binlog","configuration"]};

Thursday, March 17, 2016

brew services


You can use brew to interface with launchservices.  It's great!

Setup:

  • brew tap homebrew/services

Usage:
  • brew services list
  • brew services start etcd
  • brew services restart etcd
  • brew services stop etcd
Lots of details over at thoughtbot!

blogodex = {"toc" : "brew", "idx" : ["services", "launchd"]};