?

Log in

[theme] - [expressive] - [tagspage: limited list of tags] - S2 Layers [entries|archive|friends|userinfo]
S2 Layers

[ website | advanced customization ]
[ userinfo | livejournal userinfo ]
[ archive | journal archive ]

Links
[Links:| how to post tags page ]
[affiliated communities| fblayers ]

[theme] - [expressive] - [tagspage: limited list of tags] [Mar. 2nd, 2007|01:52 pm]
S2 Layers

s2layers

[kunzite1]
[Tags|, , ]

in response to wasd's s2expressive post.

class MyClass {
  function quicksort(string[] list, int start, int end) : string[];
  function quicksort(string[] list)                     : string[];
}

###############
# <quicksort> #
###############
#// These two functions perform sorting capabilities
#//
#// Credit goes to 'Tony Chang <tychang1 [at] uiuc [dot] edu>'
#// See: http://www.livejournal.com/customize/advanced/layersource.bml?id=54714
#// % Partitions then recursively calls.
#// % Tested up to 172 sortable elements in a string array
function MyClass::quicksort(string[] list, int start, int end) : string[] {
  if ($end <= $start) {
    return $list;
  }
  
  #// Pick a pivot and move to the front
  var int pivot  = rand($start, $end);
  var string tmp = $list[$start];
  $list[$start]  = $list[$pivot];
  $list[$pivot]  = $tmp;
  
  #// Now Partition
  var int left  = ($start + 1);
  var int right = $end;
  
  foreach var int i ($start .. ($end - 2)) {
    if ($list[$left] > $list[$start]) {
      #// Swap the left and the right, then move the right back
      $tmp          = $list[$left];
      $list[$left]  = $list[$right];
      $list[$right] = $tmp;
      $right--;
    } else {
      $left++;
    }
  }

  # put the pivot back in the middle
  if ($list[$start] < $list[$left]) {
    #// Swap $start and ($left - 1)
    $tmp               = $list[$start];
    $list[$start]      = $list[($left - 1)];
    $list[($left - 1)] = $tmp;
    $pivot             = ($left - 1);
  } else {
    #// Swap $start and $left
    $tmp          = $list[$start];
    $list[$start] = $list[$left];
    $list[$left]  = $tmp;
    $pivot        = $left;
  }
  
  #// Sort either side of the pivot
  $list = $this->quicksort($list, $start,       ($pivot - 1));
  $list = $this->quicksort($list, ($pivot + 1), $end);
  
  return $list;
}

#// Recursing Function
function MyClass::quicksort(string[] list) : string[] {
  return $this->quicksort($list, 0, size $list - 1);
}
################
# </quicksort> #
################

function TagsPage::print_body() {
  var TagDetail[]   tags      = $this->visible_tag_list(); # get available tags
  var TagDetail[]{} my_tags   = {};                        # repackage tags, group by use count
  var string{}{}    cloud     = {};                        # final package for individual tags
  var string[]      tag_names = [];                        # keep track of tag names that are in final set
  var int           max_count = 0;                         # keep track of max number of uses for any tag
  var int           max_list  = 20;                        # max number of tags to list

  # print opening to Expressive's TagsPage
  print safe """<h2 class="asset-name page-header2">$*text_tags_page_header</h2>""";

  # cycle thru tags
  foreach var TagDetail t ($tags) {
    # get highest count
    if($t.use_count > $max_count) {
      $max_count = $t.use_count;
    }

    # get existing set of tags for this use count
    var TagDetail[] array  = $my_tags{$t.use_count};

    # add this tag
    $array[size($array)]   = $t;

    # save
    $my_tags{$t.use_count} = $array;
  }

  # cycle thru sorted tags
  foreach var int i (0 .. $max_count) {
    # get tag group by use count
    var TagDetail[] ts = $my_tags{$max_count - $i};

    # if this use count has tags
    if($ts) {
      # cycle thru tags with this use count
      foreach var TagDetail t ($ts) {
        var string{} hash = {};
        $hash{"url"}                 = $t.url;            # copy url
        $hash{"uses"}                = $t.use_count + ""; # copy use count
        $hash{"sec"}                 = $t.visibility;     # copy security/visibility
        $hash{"size"}                = ($t.use_count > 1) ? (((($t.use_count * 16) / $max_count) + 7) + "") : "7"; # calculate font size
        $cloud{$t.name}              = $hash;   # add hash to cloud
        $tag_names[size($tag_names)] = $t.name; # add tag name to final set record

        # decrement max list var because we've added a tag to the final set
        $max_list--;

        # if we're at the end of the list, stop adding more
        if($max_list <= 0) {
          break;
        }
      }
    }

    # if we're at the end of the list, stop adding more
    if($max_list <= 0) {
      break;
    }
  }

  # instantiate MyClass object
  var MyClass mc = new MyClass;

  # sort tag names
  $tag_names = $mc->quicksort($tag_names);

  # cycle thru final set
  foreach var string name ($tag_names) {
    var string{} hash = $cloud{$name}; # get tag data
    var string   url  = $hash{"url"};  # get url
    var string   uses = $hash{"uses"}; # get uses
    var string   sec  = $hash{"sec"};  # get security/visibility
    var string   size = $hash{"size"}; # get font size
    var string   alt  = $uses + " use" + (int($uses) != 1 ? "s" : "") + ", " + $sec; # built alt string

    # put it all together
    """<a href="$url" alt="$alt" title="$alt" style="font-size: ${size}px;">$name</a> """;
  }
}
linkReply

Comments:
[User Picture]From: av8rmike
2007-03-03 02:31 am (UTC)
That's not quite the way I envisioned the algorithm, but I'd trust your experience.
(Reply) (Thread)
[User Picture]From: kunzite1
2007-03-03 03:34 am (UTC)
which? the quicksort was provided by someone else.

i came up with the rest with some ripping of the tagcloud fontsize code.

do you have a different idea that might be more efficient? if so, i'm willing to take a look at it.

feel free to take this code, refine it, and comment with your changes.
(Reply) (Parent) (Thread)
[User Picture]From: av8rmike
2007-03-04 12:57 am (UTC)
Hmmm, can you do a heap sort or merge sort with S2? ;)

I was going to suggest sorting tags by usage first, selecting the top 20, then re-sorting. However, it's probably not efficient to do so much sorting, and I see that quicksort function works only on string arrays.
(Reply) (Parent) (Thread)
[User Picture]From: kunzite1
2007-03-04 03:35 am (UTC)
you can do heap or merge if you can simplify it into s2 functions. :P

this is what i do:
  1. run through TagDetails (Page::visible_tag_list()) to get highest use count while making a hash of TagDetails based on TagDetail.use_count
  2. run through hash while copying TagDetail data, calculating font size, and creating an array of tag names (strings), then stop when max amount of list items has been reached
  3. quicksort tag names (strings) so that we know which order to print them in
  4. run through tag names (strings) and print tag links based on saved information (strings) in hash
what you seem to be proposing is:
  1. sort linear array of TagDetails (Page::visible_tag_list()) by usage (TagDetail.use_count), but stop when max amount of list items is reached
  2. sort resulting array into alpha order by tag name (TagDetail.name)
  3. run through array and print tag links based on information in TagDetail objects
your design definitely seems simpler. but it uses more function calls and your sorting algorithms might be hard to implement in s2 depending on all the functions that they would need.

with quicksort, i think the following lines could be changed to make it work:

- function quicksort(string[] list, int start, int end) : string[];
- function quicksort(string[] list)                     : string[];
+ function quicksort(TagDetail[] list, int start, int end) : TagDetail[];
+ function quicksort(TagDetail[] list)                     : TagDetail[];

- if ($list[$left] > $list[$start]) {
+ if ($list[$left].name > $list[$start].name) {

- if ($list[$start] < $list[$left]) {
+ if ($list[$start].name < $list[$left].name) {
(Reply) (Parent) (Thread)
[User Picture]From: wasd
2007-03-03 05:56 am (UTC)
i'm newbie in all that stuff, there should i write this in order to make the cloud work the way i want?
(Reply) (Thread)
[User Picture]From: kunzite1
2007-03-03 01:15 pm (UTC)
if you have a custom layer you'd be putting this code in there.

it'd be easier for me to give more specific instructions if you made your layer(s) publically viewable and gave me the layerid numbers.
(Reply) (Parent) (Thread)
[User Picture]From: wasd
2007-03-03 02:40 pm (UTC)
I'm not using a custom layer, the cloud is already in s2expressive, in the sidebar thingie.

Also I dont know how to make my layers publically viewable :(
(Reply) (Parent) (Thread)
[User Picture]From: kunzite1
2007-03-03 10:11 pm (UTC)
yes, the cloud is in the sidebar thingy but you wanted to alter the TagsPage to have a cloud but only include the 20 most used tags. that takes some alteration of the code.

and i forgot to check one thing that would make or break this. you need a paid/permanent account to use custom layers. :\
(Reply) (Parent) (Thread)
(Deleted comment)
[User Picture]From: kunzite1
2007-05-08 05:22 am (UTC)
i... don't quite understand what you're looking for.

a lot of the code contained in this entry is there because of how hash tables work. if i iterate over the hash, it won't be in alpha order. it'd be in the order as defined by the hash function.

do you want a <ul> of tag links? do you want a comma- or space-separated list?

the idea that i'm getting of what you want would be much much simpler than the code here.
(Reply) (Parent) (Thread)