klenwell information services : SpecialCocktailNapkin

online cocktail napkin

links and notes for later organization

Internet of Things

https://news.ycombinator.com/item?id=8237952

Stack Overflow Query I'd Like to Run

A Python script: https://gist.github.com/klenwell/16dd32f4438c53042b6e

SELECT
    question.id,
    question.url,
    question.text,
    question.createdat
    user.karma
FROM
    questions question
JOIN
    users user ON user.id = question.user_id
WHERE
    question.accepted = FALSE               AND
    question.answers <= 1                   AND
    user.karma > 20                         AND
    question.createdat < NOW() - 4 HOURS    AND
    'ajax' IN question.tags
ORDER BY
    question.votes DESC, question.created_at ASC


Mathematics as Daily Routine

http://steve-yegge.blogspot.ca/2006/03/math-for-programmers.html

Unpublished Comment

https://news.ycombinator.com/item?id=7925474

Envy and the need for social status are part of the evolutionary hard-wiring for human beings. It is in many respects a zero-sum game.

It seems to me that those who are prepared to defend unchecked economic inequality, or robber baronhood in the abstract, are just underlining their own kind of envy and deference to social status. They offer their admiration for an elite ruling class that is nakedly ambitious and unapologetic greedy as a corrective against another criteria that they find exclusionary or unfair.

Minify

Grunt: http://stackoverflow.com/questions/19664662/
App Engine Page Speed: https://developers.google.com/appengine/docs

Wikka New User

INSERT INTO users SET name='NewUser', email='NewUser@delete.me', password=MD5('password'), signuptime = NOW();


jQuery Validator

http://jsfiddle.net/8JDqZ/2/

<!DOCTYPE html>
<html>
  <head>
	<meta charset="utf-8">
	<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
	<title>jQuery Validator</title>
	<meta name="description" content="">
	<meta name="viewport" content="width=device-width">
	<link rel="stylesheet"
	  href="//maxcdn.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap.min.css">
  </head>
  <body>

	<!-- Start HTML -->

	<form class="cmxform" id="commentForm" method="get" action="">
	  <fieldset>
		<legend>Comment Form</legend>
		<p>
		  <label for="name">Name</label>
		  <input id="name" name="name" type="text" required/>
		</p>
		<p>
		  <label for="email">E-Mail</label>
		  <input id="email" type="email" name="email" required/>
		</p>
		<p>
		  <label for="curl">URL (optional)</label>
		  <input id="curl" type="url" name="url"/>
		</p>
		<p>
		  <label for="comment">Your comment</label>
		  <textarea id="comment" name="comment" required></textarea>
		</p>
		<p>
		  <input class="submit" type="submit" value="Submit"/>
		</p>
	  </fieldset>
	</form>

	<!-- End HTML -->

	<!-- Javascript Here -->
	<script
	  src="//code.jquery.com/jquery-2.1.1.min.js">
	</script>
	<script
	  src="//ajax.aspnetcdn.com/ajax/jquery.validate/1.12.0/jquery.validate.min.js">
	</script>
	<script
	  src="//maxcdn.bootstrapcdn.com/bootstrap/3.1.1/js/bootstrap.min.js">
	</script>
	<script src="fiddle.js"></script>
  </body>
</html>


fiddle.js
$(document).ready(function() {
  $("#commentForm").validate({
    rules: form_rules,
    messages: form_messages,
    submitHandler: function(form) {
      console.debug('submitHandler', form);
      return false;
    },
    invalidHandler: function(event, validator) {
      console.debug("INVALID:", validator.numberOfInvalids(), "errors");
    },
  });
  console.debug('document ready');
});

$('input.submit').on('click', function() {
  var is_valid = $("#commentForm").valid();
  console.debug('form valid?', is_valid);
  if ( is_valid ) alert('form ready for submission');
  return false;
});

var form_rules = {
  name: {
    required: true,
    minlength: 2
  },
  email: {
    email: true
  },
  comment: {
    minlength: 5
  },
};

var form_messages = {
  name: {
    required: "Please enter a name",
    minlength: "Your name is not long enough"
  },
  email: {},
  comment: {
    minlength: "Please add a little meat to your comment"
  },
};


Php Closures

class Enclosure {
   
    public $closures = array();
    public $foo = '';
   
    function add_closure($closure) {
        $this->closures[] = $closure;
    }
   
    function run() {
        foreach( $this->closures as $closure ) {
            $closure($this);
        }
    }
   
    function println($m) {
        printf("%s\n", $m);
    }
}

$o = new Enclosure();
$o->add_closure(function($self) {
    $self->println('closure #1');
});
$o->add_closure(function($self) {
    $self->println('closure #2: set foo and dump');
    $self->foo = 'bar';
    var_dump($self->foo);
});
$o->run();


Wikka Forms

class WikkaForm {

    public function __construct() {}
    public function open() {}
    public function close() {}
    public function input_text() {}
    public function input_checkbox() {}
    public function add_validator() {}
    public function is_valid() {}
    public function set_template() {}
    public function render() {}
    protected function validates() {}
}


class WikkaFormField {

    public function __construct() {}
    public function add_validator() {}
    public function validates() {}
    public function set_template() {}
    public function render() {}
}


        # Load form
        $this->form = new WikkaForm();
        $this->form->open();
        $this->form->input_text('mysql_host', 'MySQL Host',
            $this->get_config_value('mysql_host'),
            $this->help_text['mysql_host']);
        $this->form->hidden_text();
        $this->form->close(TRUE);
       
        # Process form request
        if ( $this->form->is_submitted() ) {
            $this->config = array_merge($this->config, $this->form->values());
         
            if ( $this->form->is_valid() ) {
                # Update Session data
                $_SESSION['install']['config'] = $this->config;

                # Change State
                return $this->change_state('wiki_settings_form');
            }
        }


PHP: Dynamic Method Call

class Calculator {
    function add($a, $b) { return $a + $b; }
    function subtract($a, $b) { return $a - $b; }
    function square_of($a) { return sqrt($a); }
   
}

class User {    
    function __construct() {
        $this->calc = new Calculator();
    }
   
    function input($command) {        
        list($method, $args) = $command;
        return call_user_func_array(array($this->calc, $method), $args);
    }
}


$user = new User();

$commands = array(
    array('add', array(10, 10)),
    array('subtract', array(0, 10)),
    array('square_of', array(64)),
);

foreach ($commands as $command) {
    $output = $user->input($command);
    var_dump($command);
    var_dump($output);
}


PDO

#
# Connection
#
$pdo = new PDO(sprintf('mysql:host=%s;dbname=%s', $host, $db_name),
    $user_name, $user_pass);
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
var_dump($pdo->getAttribute(PDO::ATTR_CONNECTION_STATUS));


#
# Raw SQL
#
$sql = <<<ENDSQL
CREATE TABLE pdo_test(
  `id` INT(10) unsigned NOT NULL AUTO_INCREMENT,
  `name` varchar(50) COLLATE utf8_unicode_ci DEFAULT NULL,
  `foo` varchar(50) DEFAULT NULL,
  `created_at` timestamp DEFAULT CURRENT_TIMESTAMP,
  PRIMARY KEY (`id`),
  UNIQUE KEY `unique` (`name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;

ENDSQL;

$rows_affected = $pdo->exec($sql);
var_dump($rows_affected);


#
# Insert (with statement preparation)
#
$users = array('alovelace', 'bgates', 'sjobs');
$sql = 'INSERT INTO pdo_test (name) VALUES (?)';

$stmt = $pdo->prepare($sql);

foreach ( $users as $user ) {
    $stmt->execute(array($user));
}


#
# Select (with query)
#
$sql = "SELECT * FROM pdo_test";

$rows = $pdo->query($sql);
$first_row = $rows->fetch();

foreach ( $rows as $row ) {
    var_dump($row);
}
var_dump($rows->rowCount());


#
# Update
#
$sql = "UPDATE pdo_test SET foo='bar'";

$rows_updated = $pdo->exec($sql);
var_dump($rows_updated);


#
# Drop
#
$sql = "DROP TABLE pdo_test";
$rows_affected = $pdo->exec($sql);
var_dump($rows_affected);


Wikka Migrations

require_once('libs/install/migrator.php')

$migrator = new WikkaMigrator($migrations_file);
$migrator->run_migrations();


$old_version = $config;
$new_version = CONSTANT;

$active = FALSE;
$logged = array();

foreach ( $migrations as $v => $statements ) {
    if ( $active ) {
        # SQL Migrations
        foreach ( $statements as $sql ) {
            $sql = prep_sql($sql);
            $result = run_sql($sql);
            log_sql_migration($sql, $result);
        }
       
        # Config Migrations
        if ( isset($config_migrations[$v]) ) {
            foreach ( $config_migrations[$v] as $instruction ) {
                update_config(instruction);
                log_config_migration($instruction, $result);
            }            
        }
    }
   
    # Found old version, start applying migrations with next migration
    if ( $v == $old_version ) {
        $apply = TRUE;
    }
   
    # Found current version, stop applying migrations
    if ( $v == $new_version ) {
        break;
    }
}


Install WikkaWiki From Git

Set Up
cd ~/projects
git clone https://github.com/wikkawik/WikkaWiki.git ww-git
ln -sv ~/projects/ww-git /var/www

mysqladmin -uroot -p create ww_git

http://localhost/ww-git

'mysql_database' => 'ww_git',
'mysql_user' => 'root',
'mysql_password' => '<pass>'

chmod -v 777 /var/www/ww-git/config
touch /var/www/ww-git/wikka.config.php ; chmod 666 /var/www/ww-git/wikka.config.php


Tear Down
mysqladmin -uroot -p drop ww_git
rm -Rf ~/projects/ww-git
rm -vf /var/www/ww-git


Reminder


Wikka Handler Refactor

    public function process_request($request) {
        $route = $this->route_request($request);
        $response = $this->run_wikka_handler($route['page'], $route['handler']);
       
        $response->set_header('Cache-Control', 'no-cache');
        $response->set_header('ETag', md5($content));
        $response->set_header('Content-Length:', strlen($content));
       
        return $response;
    }
   
    private function run_wikka_handler($page_name, $handler_name) {
        $wikka = new WikkaBlob($this->config);
        $wikka->connect_to_db();
        $wikka->save_session_to_db();
        $wikka->validate_handler_name($handler_name);
       
        if ( $wikka->is_new_style_handler($handler_name) ) {
            $handler = $wikka->load_handler_class($handler_name);
            $response = $handler->handle();
            return $response;
        }
        else {
            return $this->run_old_style_handler($page_name, $handler_name);
        }
    }
   
    private function run_old_style_handler($page_name, $handler_name) {
        $wikka = new WikkaBlob($this->config);
        $wikka->globalize_this_as_wakka_var();
        $wikka->open_buffer();        
        $wikka->Run($page_name, $handler_name);
        $content = $wikka->close_buffer();
       
        # create response object
        $response = new WikkaResponse($content, 200);
        $response->set_header('Content-Type', 'text/html; charset=utf-8');
       
        # Set header for response object from headers list
        $headers = headers_sent();        
        foreach ($headers as $header) {
            list($key, $value) = explode(':', $header, 1);
            $response->set_header($key, $value);
        }

        return $response;
    }


Wikka Install Exception

try {
    $request = $webservice->prepare_request();
    $webservice->start_session();
    $webservice->set_csrf_token();
    $webservice->raise_exception_if_install_required();
    $response = $webservice->process_request($request);
}
catch (WikkaInstallException $e) {
    $response = $webservice->process_installer($request);
}
catch (Exception $e) {
    $response = $webservice->process_error($e);
}


Unpublished Comment

In response to https://news.ycombinator.com/item?id=7341400:

I get this impression with a lot of libertarian social ideas, e.g. socialized health coverage or newfangled food supplements.

It seems to be one area where recapitulation theory[1] applies. Only by seeing ontogeny recapitulate phylogeny for themselves will some people -- strike that, most people -- appreciate the hoary inefficient logic behind long-established conventions and institution.

[1] http://en.wikipedia.org/wiki/Recapitulation_theory


Test Local Site on Android Chrome Attached by USB

Full instructions here:
https://developers.google.com/chrome-developer-tools/docs/remote-debugging

DESKTOP: local machine where you doing your development
PHONE: Android device connection to DESKTOP by USB

1. On DESKTOP: Get network IP address
- Open terminal
- Run: ifconfig
- Copy inet addr for eth0 (e.g., inet addr:192.168.1.101)

2. On DESKTOP: Set up port forwarding for Chrome
- In address bar, enter: about:inspect
- Check checkbox for Discover USB devices
- Click Port Forwarding button
- In pop-up for Port Forwarding Settings, enter:
8080 <IP ADDRESS>:80

For example:
8080 192.168.1.101:80

3. On PHONE: Go to website
- In address bar, enter: 192.168.1.101:80*

* Note: This can also be done in the inspect tab by using Open tab with url
field. Just enter same value there and if Chrome is open on your phone, it
will automatically load that page.


2014 Cocktail Napkin

Happy New Year!



CategorySpecial
Comments [Hide comments/form]
There are no comments.