Monthly Archives: August 2014

Gradients in gnuplot

gradient.py:

import argparse
import sys

def parseArgs():
    parser = argparse.ArgumentParser(description = "Generate gradient data suitable for use in gnuplot.")
    parser.add_argument("xMin", metavar = "X_MIN", type = float, help = "minimum x-coordinate")
    parser.add_argument("xMax", metavar = "X_MAX", type = float, help = "maximum x-coordinate")
    parser.add_argument("yMin", metavar = "Y_MIN", type = float, help = "minimum y-coordinate")
    parser.add_argument("yMax", metavar = "Y_MAX", type = float, help = "maximum y-coordinate")
    parser.add_argument("stepCount", metavar = "STEPS", type = int, help = "number of steps")
    axis = parser.add_mutually_exclusive_group(required = True)
    axis.add_argument("-x", action = "store_true", default = False, help = "grade along x-axis")
    axis.add_argument("-y", action = "store_true", default = False, help = "grade along y-axis")
    return parser.parse_args()

def grade(min, max, step, stepCount):
    return min + step * (max - min) / stepCount

def write(x, y, z):
    sys.stdout.write("{0} {1} {2}\n".format(x, y, z))

args = parseArgs()
for step in range(args.stepCount + 1):
    if args.x:
        x1 = x2 = grade(args.xMin, args.xMax, step, args.stepCount)
        y1 = args.yMin
        y2 = args.yMax
    elif args.y:
        x1 = args.xMin
        x2 = args.xMax
        y1 = y2 = grade(args.yMin, args.yMax, step, args.stepCount)
    z = step / args.stepCount
    write(x1, y1, z)
    write(x2, y2, z)
    sys.stdout.write("\n")

gradient.plt:

set terminal png size 640,480
set output 'gradient.png'
set xrange [-5:5]
set yrange [-5:5]
set cbrange [0:1]
unset colorbox
unset key
set palette gray negative
set object 1 rectangle from 1,-10 to 10,10 behind fillcolor rgb 'black' fillstyle noborder
plot '< python gradient.py -x -1 1 -10 10 64' with image

gradient.png:

GIMP Script: script-fu-highlight

(define (script-fu-highlight image
                             drawable
                             padding
                             shadow)
  (if (= (car (gimp-selection-is-empty image)) TRUE)
      (gimp-message "Select an area to highlight.")
      (let ((selection 0))
        (gimp-undo-push-group-start image)
        (set! selection (car (gimp-selection-save image)))
        (gimp-selection-grow image (/ padding 2))
        (gimp-selection-feather image padding)
        (gimp-selection-invert image)
        (gimp-levels drawable HISTOGRAM-VALUE 0 255 1 0 shadow)
        (gimp-image-select-item image CHANNEL-OP-REPLACE selection)
        (gimp-image-remove-channel image selection)
        (gimp-undo-push-group-end image)
        (gimp-displays-flush))))

(script-fu-register "script-fu-highlight"
                    "_Highlight..."
                    "Highlight the current selection"
                    "Steven Williams"
                    "Steven Williams"
                    "2014"
                    "RGB* GRAY*"
                    SF-IMAGE "Image" 0
                    SF-DRAWABLE "Layer" 0
                    SF-ADJUSTMENT "Padding" '(10 0 100 1 10 0 SF-SPINNER)
                    SF-ADJUSTMENT "Shadow" '(127 0 255 1 10 0 SF-SLIDER))
(script-fu-menu-register "script-fu-highlight" "<Image>/Filters/Light and Shadow/Light")

Output:

Underscore.php Mixin: multisort

<?php
    __()->mixin([
        "reindex" => function ($items, $indices) {
            return __($indices)->map(function ($index) use ($items) { return $items[$index]; });
        },
        
        "multisort" => function ($items, $keys) {
            if (count($items) <= 1) {
                return $items;
            }
            $__items = __($items);
            $args = [];
            foreach ($keys as $key) {
                if (!is_array($key)) {
                    $key = [$key];
                }
                $property = array_shift($key);
                $args[] = $__items->pluck($property);
                $args = array_merge($args, $key);
            }
            $indices = __()->range($__items->size());
            $args[] = &$indices;
            call_user_func_array("array_multisort", $args);
            return $__items->reindex($indices);
        }
    ]);
    
    function format($president) {
        return sprintf(
            "%d: %s %s (%s)",
            $president["order"],
            $president["firstName"],
            $president["lastName"],
            $president["party"]);
    }
    
    function display($presidents) {
        print_r(__($presidents)->invoke("format"));
    }
    
    $presidents = __([
        ["order" => 1, "firstName" => "George", "lastName" => "Washington", "party" => "None"],
        ["order" => 2, "firstName" => "John", "lastName" => "Adams", "party" => "Federalist"],
        ["order" => 3, "firstName" => "Thomas", "lastName" => "Jefferson", "party" => "Democratic-Republican"],
        ["order" => 4, "firstName" => "James", "lastName" => "Madison", "party" => "Democratic-Republican"],
        ["order" => 5, "firstName" => "James", "lastName" => "Monroe", "party" => "Democratic-Republican"],
        ["order" => 6, "firstName" => "John Quincy", "lastName" => "Adams", "party" => "Democratic-Republican"],
        ["order" => 7, "firstName" => "Andrew", "lastName" => "Jackson", "party" => "Democratic"],
        ["order" => 8, "firstName" => "Martin", "lastName" => "Van Buren", "party" => "Democratic"],
        ["order" => 9, "firstName" => "William Henry", "lastName" => "Harrison", "party" => "Whig"],
        ["order" => 10, "firstName" => "John", "lastName" => "Tyler", "party" => "Whig"]
    ]);
    
    display($presidents->multisort(["firstName"]));
    display($presidents->multisort([["lastName", SORT_DESC]]));
    display($presidents->multisort(["party", ["order", SORT_DESC]]));
?>

Output:

Array
(
    [0] => 7: Andrew Jackson (Democratic)
    [1] => 1: George Washington (None)
    [2] => 4: James Madison (Democratic-Republican)
    [3] => 5: James Monroe (Democratic-Republican)
    [4] => 2: John Adams (Federalist)
    [5] => 10: John Tyler (Whig)
    [6] => 6: John Quincy Adams (Democratic-Republican)
    [7] => 8: Martin Van Buren (Democratic)
    [8] => 3: Thomas Jefferson (Democratic-Republican)
    [9] => 9: William Henry Harrison (Whig)
)
Array
(
    [0] => 1: George Washington (None)
    [1] => 8: Martin Van Buren (Democratic)
    [2] => 10: John Tyler (Whig)
    [3] => 5: James Monroe (Democratic-Republican)
    [4] => 4: James Madison (Democratic-Republican)
    [5] => 3: Thomas Jefferson (Democratic-Republican)
    [6] => 7: Andrew Jackson (Democratic)
    [7] => 9: William Henry Harrison (Whig)
    [8] => 2: John Adams (Federalist)
    [9] => 6: John Quincy Adams (Democratic-Republican)
)
Array
(
    [0] => 8: Martin Van Buren (Democratic)
    [1] => 7: Andrew Jackson (Democratic)
    [2] => 6: John Quincy Adams (Democratic-Republican)
    [3] => 5: James Monroe (Democratic-Republican)
    [4] => 4: James Madison (Democratic-Republican)
    [5] => 3: Thomas Jefferson (Democratic-Republican)
    [6] => 2: John Adams (Federalist)
    [7] => 1: George Washington (None)
    [8] => 10: John Tyler (Whig)
    [9] => 9: William Henry Harrison (Whig)
)

Underscore.php Mixin: sort

<?php
    __()->mixin([
        "sort" => function ($items, $ascending = true) {
            if ($ascending) {
                sort($items);
            } else {
                rsort($items);
            }
            return $items;
        }
    ]);
    
    $numbers = __()->chain()->range(10)->shuffle()->value();
    print_r($numbers);
    print_r(__($numbers)->sort());
    print_r(__($numbers)->sort(false));
    print_r($numbers);
?>

Output:

Array
(
    [0] => 5
    [1] => 1
    [2] => 3
    [3] => 0
    [4] => 6
    [5] => 8
    [6] => 4
    [7] => 9
    [8] => 7
    [9] => 2
)
Array
(
    [0] => 0
    [1] => 1
    [2] => 2
    [3] => 3
    [4] => 4
    [5] => 5
    [6] => 6
    [7] => 7
    [8] => 8
    [9] => 9
)
Array
(
    [0] => 9
    [1] => 8
    [2] => 7
    [3] => 6
    [4] => 5
    [5] => 4
    [6] => 3
    [7] => 2
    [8] => 1
    [9] => 0
)
Array
(
    [0] => 5
    [1] => 1
    [2] => 3
    [3] => 0
    [4] => 6
    [5] => 8
    [6] => 4
    [7] => 9
    [8] => 7
    [9] => 2
)

Fixing Underscore.php

@@ -176,7 +176,7 @@ all: Wrap return value
     $__ = new self;
     if(!is_null($iterator)) $collection = $__->map($collection, $iterator);
     $collection = (array) $collection;
-    if(count($collection) === 0) return true;
+    if(count($collection) === 0) return self::_wrap(true);
     
     return self::_wrap(is_bool(array_search(false, $collection, false)));
   }
@@ -191,8 +191,8 @@ filter: Pass key to iterator
     $collection = self::_collection($collection);
     
     $return = array();
-    foreach($collection as $val) {
-      if(call_user_func($iterator, $val)) $return[] = $val;
+    foreach($collection as $k=>$v) {
+      if(call_user_func($iterator, $v, $k, $collection)) $return[] = $v;
     }
     return self::_wrap($return);
   }
@@ -205,8 +205,8 @@ reject: Pass key to iterator
     $collection = self::_collection($collection);
     
     $return = array();
-    foreach($collection as $val) {
-      if(!call_user_func($iterator, $val)) $return[] = $val;
+    foreach($collection as $k=>$v) {
+      if(!call_user_func($iterator, $v, $k, $collection)) $return[] = $v;
     }
     return self::_wrap($return);
   }
@@ -220,8 +220,8 @@ find: Pass key to iterator and wrap return value
     
     $collection = self::_collection($collection);
     
-    foreach($collection as $val) {
-      if(call_user_func($iterator, $val)) return $val;
+    foreach($collection as $k=>$v) {
+      if(call_user_func($iterator, $v, $k, $collection)) return self::_wrap($v);
     }
     return self::_wrap(false);
   }
@@ -501,7 +501,7 @@ max: Wrap return value
     arsort($results);
     $__ = new self;
     $first_key = $__->first(array_keys($results));
-    return $collection[$first_key];
+    return self::_wrap($collection[$first_key]);
   }
   
   
@@ -549,7 +549,7 @@ groupBy: Wrap return value
       if(!array_key_exists($key, $result)) $result[$key] = array();
       $result[$key][] = $v;
     }
-    return $result;
+    return self::_wrap($result);
   }
   
   
@@ -588,7 +588,9 @@ toArray: Wrap arguments and return value
   
   // Return the collection as an array
   public function toArray($collection=null) {
-    return (array) $collection;
+    list($collection) = self::_wrapArgs(func_get_args(), 1);
+    
+    return self::_wrap((array) $collection);
   }
   
   
@@ -615,7 +617,7 @@ extend: Wrap return value
     $args = self::_wrapArgs(func_get_args(), 1);
     
     $num_args = func_num_args();
-    if($num_args === 1) return $object;
+    if($num_args === 1) return self::_wrap($object);
     
     $is_object = is_object($object);
     $array = (array) $object;
@@ -635,7 +637,7 @@ defaults: Wrap return value
     list($object) = $args;
     
     $num_args = count($args);
-    if($num_args === 1) return $object;
+    if($num_args === 1) return self::_wrap($object);
     
     $is_object = is_object($object);
     $array = (array) $object;
@@ -660,7 +662,7 @@ clon: Pass argument by value
   
   
   // Returns a shallow copy of the object
-  public function clon(&$object=null) {
+  public function clon($object=null) {
     list($object) = self::_wrapArgs(func_get_args(), 1);
     
     $clone = null;
@@ -858,7 +860,7 @@ __call: Wrap return value
   public function __call($name, $arguments) {
     $mixins =& self::getInstance()->_mixins;
     $arguments = self::_wrapArgs($arguments);
-    return call_user_func_array($mixins[$name], $arguments);
+    return self::_wrap(call_user_func_array($mixins[$name], $arguments));
   }
   
   
@@ -1045,7 +1047,7 @@ compose: Apply functions in reverse order
     
     return self::_wrap(function() use ($functions) {
       $args = func_get_args();
-      foreach($functions as $function) {
+      foreach(array_reverse($functions) as $function) {
         $args[0] = call_user_func_array($function, $args);
       }
       return $args[0];

Object-Oriented JavaScript

if (typeof Object.create !== "function") {
    Object.create = function (proto) {
        function Type() { }
        Type.prototype = proto;
        return new Type();
    };
}

function Animal(name) {
    var self = this;
    var energy = 100;  // Private
    self.name = name;  // Public
    
    // Private
    function log() {
        var status;
        if (energy >= 100) {
            status = "not tired";
        } else if (energy >= 50) {
            status = "somewhat tired";
        } else {
            status = "very tired";
        }
        console.log(self.name + " is " + status + ".");
    }
    
    // Privileged
    self.play = function () {
        console.log(self.name + " is playing.");
        energy -= 1;
        log();
    };
    
    // Privileged
    self.eat = function () {
        console.log(self.name + " is eating.");
        energy += 1;
        log();
        self.speak();
    };
}

// Public
Animal.prototype.speak = function () {
    console.log(this.name + " makes a noise.");
};

var alfa = new Animal("Alfa");
console.log(alfa.energy);
console.log(alfa.log);
console.log(alfa.name);
alfa.play();
alfa.eat();

function Dog(name) {
    var self = this;
    Animal.call(self, name);
}

Dog.prototype = Object.create(Animal.prototype);
Dog.prototype.constructor = Dog;

Dog.prototype.speak = function () {
    console.log(this.name + " barks.");
};

var bravo = new Dog("Bravo");
console.log(bravo instanceof Animal);
console.log(bravo instanceof Dog);
bravo.play();
bravo.eat();

Output:

undefined
undefined
Alfa
Alfa is playing.
Alfa is somewhat tired.
Alfa is eating.
Alfa is not tired.
Alfa makes a noise.
true
true
Bravo is playing.
Bravo is somewhat tired.
Bravo is eating.
Bravo is not tired.
Bravo barks.