array_unique javascript snippet

function array_unique(a)
{
    return a.reduce(function(u, e)
    {
        if(!(e in u))
            u.push(e);

        return u;
    }, []);
}

Posted on

Sacred Shield vs Aura

I’m not sure how correct this is, but I thought it would be fun to compared how much Sacred Shield can absorb against a regular source of raid damage (in this case Sapphiron’s frost aura in Naxx25)

The mechanics of SS is a little strange, best to read up on the skill on WoWHead, or WoWWiki

  • Each tick of Sacred Shield absorbs, 500 + 0.75% of your Spell power.
  • Each tick has a 6 second cooldown, and the buff lasts for 30 seconds
  • We are using Sapphiron’s frost aura in Naxx25 for this example. 1600 frost damage every two seconds, to ever member of the raid
  • Our paladin also has has 2000 spell power (which works out to be 2000 absorbed each tick)

Example time line (2 ticks):

00  SS Cast

01  Take   1600   SS Up (2000 left)
02  --
03  Absorb 1600   SS Up (400 left)
04  --
05  Absorb 400    SS Down
    Take   1200
06  --

07  Take   1600   SS Up (2000 left)
08  --
09  Absorb 1600   SS Up (400 Left)
10  --
11  Absorb 400    SS Down
    Take   1200  
12  --

This gives us our base numbers

  • Every 6s, absorb 2000, miss 2800
  • Each cast, absorb 10,000, missing 14,000
  • With 25 people in a raid and a 1.4s cast time (all GCD)
  • SS can kept up on 21 people (1.4 * 21 = 29.4) at a cost of 445 per cast
  • Every 6 seconds: Absorbs 42,000 damage (miss 58,800 damage)
  • Every 30 seconds: Absorbs 210,000 damage (miss 294,000 damage) and costs 9345 mana
  • This results in a very reasonable 7000 damage absorbed per second, at a cost of 1500MP5

Sounds like something fun to test next raid

Updated: Blizzard nerfed SS in 3.1 allowing it to be only cast on one person at a time. Everything above is now as useless as SS itself.

Posted on

Divine Plea returns in WoW

Divine Plea is one of a Holy Paladins two main sources of mana regen (along with illumination). The spell is on a one minute cool down and returns 25% of your total (maximum) mana over 15 seconds while reducing healing done by 20%. Because the spell is based off total mana, it scales with intellect, and raid buffs (Mark, Kings and AI).

Note, when considering to stack Int, remember that each point also gives a small amount of spell crit and spell power (which is not considered here).

Int Mana DP MP5 (60s CD) MP5 (90s CD)
1500 28510 7127 594 396
1400 26785 6696 558 372
1300 25060 6265 522 348
1200 23335 5834 486 324
1100 21610 5402 450 300
1000 19885 4971 414 276
900 18160 4540 378 252
800 16435 4109 342 228
700 14710 3677 306 204

Returns on Divine Plea by character intellect

Per Int Mana DP MP5 (60s CD) MP5 (90s CD)
1 17.25 4.31 0.36 0.24
3 51.75 12.94 1.08 0.72
10 172.50 43.12 3.59 2.40
20 345.00 86.25 7.19 4.79
30 517.50 129.38 10.78 7.19
50 862.50 215.62 17.97 11.98

Returns on Divine Plea per point on intellect

Notes

Total mana from character intellect = 4394 + (15 * (Intellect – 102) * 1.15)

4394 is the base mana, and 102 is the base intellect of a level 80 Paladin. Intellect after the base amount gives 15 mana per point, then multiplied by 15% from holy talents.

Posted on

obsessed with anonymous functions

Any normal person would just live without anonymous functions in PHP, they are buggy and non trivial ones are pain to write and read. I’m not sure why I seam to obsess over them.

At the very least, the below code will test unicode in your dev tools

Edit: Of course after I wrote that I discovered that WordPress was ignoring the λ character. A little fix from here and everything is working again.

<?php

    // Create an 'anonymous' function without specifying arguments.
    // Arguments are considered to be named $a to $z
    function λ($body)
    {
        $args = '';
        if(preg_match_all('#(\$[a-z])\b#', $body, $matches, PREG_SET_ORDER) !== 0)
        {
            $allArgs = array();
            foreach($matches as $match)
            {
                $allArgs[] = $match[1];
            }
            $allArgs = array_unique($allArgs);
            sort($allArgs);
            $args = implode(',', $allArgs);
        }

        // Make sure it's terminated (we don't care about extra trailing ';')
        return create_function($args, $body . ';');
    }


    // Creating
    $multiply = λ('return $a * $b');
    echo "23 * 65 = " . $multiply(23, 65) . "\n";

    // Only $a to $z are reserved
    $bSquaredByA = λ('$unused = "Hello"; $b_square = $b * $b; return $b_square * $a');
    echo "8 * 6^2 = " . $bSquaredByA(8, 6) . "\n";

    // Embedding in strings
    $square      = λ('return $a * $a');
    $numbers     = array(2,4,8);
    foreach($numbers as $num)
    {
      echo "$num * $num = {$square($num)}\n";
    }

    // Note you don't have to use $a for your first argument, and $b for your second.  They just
    // Need to be in the right order
    $print_two_things = λ('echo "Second: " . $y . "\n"; echo "First: " . $d . "\n";');
    $print_two_things("Hello", "World!");

    // Practical use
    $numbers     = array(1,1,1,2,2,3,3,3,4,5,5,6,7,8,9);
    $above_three = array_filter($numbers, λ('return $x > 3;'));
    echo "Numbers above three =  " . implode(", ", $above_three) . "\n";    

?>

Posted on

Javascript map-sort

I’m sure sorting method has a real name, but I’ve had no luck searching for it.

function mapSort(array, mapFunction, sortFunction)
{
    // Store both original value, and transformed value
    var mapData = array.map(function(e)
    {
        return [e, mapFunction(e)];
    });

    // Sort the data using the second element of each array item (the mapped one)
    var sortedData = mapData.sort(function(a, b)
    {
        return sortFunction(a[1], b[1]);
    });

    // Remove the extra transformed value from the sorted array
    return sortedData.map(function(e)
    {
        return e[0];
    });
}

// Example

var data = ["a", "b", "A", "B", "C", "c"];
var cmp  = function(a, b) { return a > b; };
var map  = function(ch) { return ch.toLowerCase(); };

print("Normal:   " + data.sort(cmp));
print("Map Sort: " + mapSort(data, map, cmp));

// Normal:   A,B,C,a,b,c
// Map Sort: a,A,B,b,c,C

Posted on

I hate working with dates

This little snippet gets all the days in a month, and groups them by week.

<?php

    error_reporting(E_ALL);

    // Return an array of all the days in a month grouped by week number
    // (Sunday is considered to be the first day of the week)
    function weeksInMonth($month, $year)
    {
        $firstDay    = mktime(0, 0, 0, $month, 1, $year);
        $daysInMonth = date('t', $firstDay);

        $week        = 1;
        $breakdown   = array();

        for($i = 1; $i <= $daysInMonth; $i++)
        {
            $date = mktime(0, 0, 0, $month, $i, $year);
            $day  = date('l', $date);

            // Sunday triggers the start of a new week, except if it's
            // also the first day of the month.
            if(($day == 'Sunday') && ($i != 1))
            {
                $week++;
            }

            $breakdown[$week][] = $date;
        }

        return $breakdown;
    }


    $results = monthToWeek(6, 2008);

    printf("There are %d weeks in June 2008\n\n", count($results));

    foreach($results as $weekNumber => $days)
    {
        printf("Week %d\n", $weekNumber);

        foreach($days as $day)
        {
            printf("%10s  %s\n", date("l", $day), date("Y-m-d", $day));
        }

        printf("\n");
    }

/*
There are 5 weeks in June 2008

Week 1
    Sunday  2008-06-01
    Monday  2008-06-02
   Tuesday  2008-06-03
 Wednesday  2008-06-04
  Thursday  2008-06-05
    Friday  2008-06-06
  Saturday  2008-06-07

Week 2
    Sunday  2008-06-08
    Monday  2008-06-09
   Tuesday  2008-06-10
 Wednesday  2008-06-11
  Thursday  2008-06-12
    Friday  2008-06-13
  Saturday  2008-06-14

Week 3
    Sunday  2008-06-15
    Monday  2008-06-16
   Tuesday  2008-06-17
 Wednesday  2008-06-18
  Thursday  2008-06-19
    Friday  2008-06-20
  Saturday  2008-06-21

Week 4
    Sunday  2008-06-22
    Monday  2008-06-23
   Tuesday  2008-06-24
 Wednesday  2008-06-25
  Thursday  2008-06-26
    Friday  2008-06-27
  Saturday  2008-06-28

Week 5
    Sunday  2008-06-29
    Monday  2008-06-30
*/
?>

Posted on

K100D Gallery Added

Just added a couple of quick photos to the k100d gallery. Really wish I could have spent longer watching the surfers near The Spit

Camera is Pentax K100D 6MP with a Sigma 70-300 / Sigma 28-70 F2.8

Edit: 2022-04-10 - New Gallery link

Posted on

auth.log noise

Below are the top 50 login names when trying to gain access to this web server over the last 4 weeks

Name Attempts
root 3273
admin 119
mysql 44
test 110
guest 41
user 37
oracle 37
temp 25
sales 24
info 21
webmaster 21
dan 18
postgres 21
robert 18
student 17
ftpuser 17
ftp 17
richard 16
apache 16
web 15
adm 15
webadmin 15
john 15
paul 15
office 15
tony 14
james 14
postfix 13
michael 13
alex 13
david 13
amanda 13
adam 12
mike 12
staff 12
steven 12
recruit 12
jeff 12
pgsql 12
library 12
username 12
frank 12
susan 11
cyrus 11
dave 11
gast 10
postmaster 10
nagios 10
martin 10
admins 10

Note: No external connections are allowed to log in as root (of course)

Note2: After 5 failed login attempt, the IP address is temporary banned (fail2ban)

Posted on

import life

A console based implementation of Conway’s Game of Life in Python.

As fascinating as it is useless.

#!/usr/bin/python

import sys
import random
import time
import os
import copy

WIDTH = 32
HEIGHT = 16

class Grid:
    def __init__(self, width, height):
        self.width  = width
        self.height = height
        self.create_blank_grid()

    def create_blank_grid(self):
        self.grid = []

        for x in range(0, self.width):
            self.grid.append([0 for y in range(0, self.height)])

    def seed(self, chance = 0.4):
        for x in range(0, self.width):
            for y in range(0, self.height):
                if random.random() < chance:
                    self.grid[x][y] = 1
                else:
                    self.grid[x][y] = 0

    def add_glider(self):
        self.grid[1][0] = 1
        self.grid[2][1] = 1
        self.grid[0][2] = 1
        self.grid[1][2] = 1
        self.grid[2][2] = 1


    def __str__(self):
        buffer = ''

        for y in range(0, self.height):
            for x in range(0, self.width):
                str = ' '
                if self.grid[x][y] == 1:
                    str = '#'

                buffer += str
            buffer += '\n';
        buffer += '\n';

        return buffer

    def get_number_neighbours(self, x, y):

        def get_value(i,j):
            try:
                return self.grid[i][j]
            except:
                return 0

        number_neighbours = get_value(x-1, y-1) + get_value(x, y-1)   + get_value(x+1, y-1) +  \
                            get_value(x-1, y)   +                       get_value(x+1, y)   +  \
                            get_value(x-1, y+1) + get_value(x, y+1)   + get_value(x+1, y+1)

        return number_neighbours


    def tick(self):
        new_grid = copy.deepcopy(self.grid)

        for x in range(0, self.width):
            for y in range(0, self.height):

                number_neighbours = self.get_number_neighbours(x,y)

                if self.grid[x][y] == 1:
                    if number_neighbours < 2:
                        new_grid[x][y] = 0
                    elif number_neighbours > 3:
                        new_grid[x][y] = 0
                else:
                    if number_neighbours == 3:
                        new_grid[x][y] = 1

        self.grid = new_grid

if __name__ == "__main__":
    grid = Grid(WIDTH, HEIGHT)
    # chance for a cell to be 'alive'
    grid.seed(0.2)
    # grid.add_glider()

    # 100 generations
    for x in range(0, 100):
        os.system('clear')
        print grid
        grid.tick()
        time.sleep(1)

Posted on

Pretending PHP doesn’t suck

<?php

// Perhaps the simplest practical use of a fold?
//
// (While this is fairly consise (even in PHP) it calculates the length of a
// string 2n-2 times [which is n-2 times more than needed])
function getLongestWord($words)
{
  $fun = create_function('$a,$b', 'return (strlen($a) > strlen($b)) ? $a : $b;');

  return array_reduce($words, $fun);
}

// This looks a little better, but it loses a lot of the simplicity of the above
function getLongestWord_2($words)
{  
  $map  = create_function('$a', 'return array($a, strlen($a));');
  $fold = create_function('$a,$b', 'return ($a[1] > $b[1]) ? $a : $b;');

  $word = array_reduce(array_map($map, $words), $fold);

  return $word[0];
}

$words = array('a', 'bb', 'ccc', 'dd', 'eeee', 'fff', 'gg');

var_dump(getLongestWord($words));
// string(4) "eeee"

var_dump(getLongestWord_2($words));
// string(4) "eeee"

?>

Is there an even simpler way to find the longest string in an array?

Posted on