Peter Stuifzand

Power law tag size

Wij vervelen ons is my social concert calendar. It’s a calendar where people can put their favorite concerts. A few weeks ago I added a tag cloud. The tag cloud looked really nice because the tag with the most concerts was bigger than other tags. I hadn’t thought this thing out, so there was a hand coded 12-line if block that gave each tag a nice size and padding. This block didn’t use the max count of concerts so there was a possibility that that more tags got the huge size.

The actual code (this is really bad code):

if ($count >= 1 and $count <= 4) {
    $cloud .= qq{<a style='color:#66f;padding:1px;'
          href="tags?action=show&amp;tag=$tag">$tag</a>\n};
}
elsif ($count >= 6 and $count <= 9) {
    $cloud .= qq{<a style='font-size:11pt;padding:2px;'
          href="tags?action=show&amp;tag=$tag">$tag</a>\n};
}
elsif ($count >= 10 and $count <= 13) {
    $cloud .= qq{<a style='font-size:13pt;padding:3px;'
          href="tags?action=show&amp;tag=$tag">$tag</a>\n};
}
elsif ($count > 14) {
    $cloud .= qq{<a style='font-size:15pt;padding:4px;'
          href="tags?action=show&amp;tag=$tag">$tag</a>\n};
}

So I thought of how to do it the right way (of course this has been done before):

sub power_law {
    my ($x, $a, $k) = @_;
    return $a * $x ** $k;
}

sub power_law_proportion {
    my ($x, $maxx, $a, $k) = @_;
    return power_law($x,$a,$k) / power_law($maxx, $a, $k);
}

sub power_law_distributed_number {
    my (%args) = @_;
    return $args{from} + int(power_law_proportion($args{count},
                  $args{max_count}, 1, 2) * ($args{to}-$args{from}));
}

In the html generation code:

my $font_size = power_law_distributed_number(
                  count => $count, max_count => $max_count,
                  from => 10, to => 16);
my $padding   = power_law_distributed_number(
                  count => $count, max_count => $max_count,
                  from => 1, to => 4);

$cloud .= qq{<a style='font-size:${font_size}pt;padding:${padding}px;'
  href="tags?action=show&amp;tag=$tag">$tag</a>\n};

This will work when the number of concerts changes.

© 2023 Peter Stuifzand