Skip to content

Commit

Permalink
Clout types are now associated with tagnames, with getTagnameidClid as
Browse files Browse the repository at this point in the history
the method to determine a tagname's clid.  addCloutsToTagArrayref now
uses the particular clout type on a per-tagname basis, which is a pretty
fundamental change but it works retroactively with tag history and all
tagboxes' calculations.  Vars define which clout to use for "don't know."
  • Loading branch information
jamiemccarthy committed Feb 28, 2008
1 parent c7f546f commit befa763
Show file tree
Hide file tree
Showing 5 changed files with 157 additions and 62 deletions.
204 changes: 146 additions & 58 deletions plugins/Tags/Tags.pm
Expand Up @@ -565,14 +565,79 @@ sub getTagsByGlobjid {
return $ar;
}

# Given a tagnameid, return what clid type should be used for it
# (0 = unknown).

{ # closure
my($reason_names, $upvoteid, $downvoteid) = (undef, undef, undef);
sub getTagnameidClid {
my($self, $tagnameid) = @_;
if ($tagnameid !~ /^\d+$/) {
warn "non-numeric tagnameid passed to getTagnameCloutType: $tagnameid";
return 0;
}
my $constants = getCurrentStatic();

my $mcd = $self->getMCD();
my $mcdkey = undef;
if ($mcd) {
$mcdkey = "$self->{_mcd_keyprefix}:tanc:";
my $value = $mcd->get("$mcdkey$tagnameid");
return $value if defined $value;
}

my $clid = 0;
my $tn_data = undef;
my $types = $self->getCloutTypes();

# Is it a vote?
if ($types->{vote}) {
if (!$clid) {
$upvoteid ||= $self->getTagnameidCreate($constants->{tags_upvote_tagname} || 'nod');
$clid = $types->{vote} if $tagnameid == $upvoteid;
}
if (!$clid) {
$downvoteid ||= $self->getTagnameidCreate($constants->{tags_downvote_tagname} || 'nix');
$clid = $types->{vote} if $tagnameid == $downvoteid;
}
}

# Is it descriptive?
if ($types->{describe} && !$clid) {
$tn_data = $self->getTagnameDataFromId($tagnameid);
$clid = $types->{describe} if $tn_data->{descriptive};
}

# Is it a moderation?
if ($types->{moderate} && $constants->{m1} && $constants->{m1_pluginname}) {
if (!$clid) {
if (!$reason_names) {
my $mod_db = getObject("Slash::$constants->{m1_pluginname}", { db_type => 'reader' });
my $reasons = $mod_db->getReasons();
$reason_names = {
map { (lc($reasons->{$_}{name}), 1) }
keys %$reasons
};
}
$tn_data ||= $self->getTagnameDataFromId($tagnameid);
$clid = $types->{moderate} if $reason_names->{ $tn_data->{tagname} };
}
}

$mcd->set("$mcdkey$tagnameid", $clid, $constants->{memcached_exptime_tags}) if $mcd;

return $clid;
}
} # end closure

# Given an arrayref of hashrefs representing tags, such as that
# returned by getTagsByNameAndIdArrayref, add three fields to each
# hashref: tag_clout, tagname_clout, user_clout. Values default
# to 1. "Rounded" means round to 3 decimal places.

sub addRoundedCloutsToTagArrayref {
my($self, $ar, $clout_type) = @_;
$self->addCloutsToTagArrayref($ar, $clout_type);
my($self, $ar) = @_;
$self->addCloutsToTagArrayref($ar);
for my $tag_hr (@$ar) {
$tag_hr->{tag_clout} = sprintf("%.3f", $tag_hr->{tag_clout});
$tag_hr->{tagname_clout} = sprintf("%.3f", $tag_hr->{tagname_clout});
Expand All @@ -582,10 +647,9 @@ sub addRoundedCloutsToTagArrayref {
}

sub addCloutsToTagArrayref {
my($self, $ar, $clout_type) = @_;
my($self, $ar) = @_;

if (!$clout_type) { use Carp; Carp::cluck("no clout_type for addCloutsToTagArrayref"); }
return if !$ar || !@$ar || !$clout_type;
return if !$ar || !@$ar;
my $constants = getCurrentStatic();

# Pull values from tag params named 'tag_clout'
Expand All @@ -596,64 +660,51 @@ if (!$clout_type) { use Carp; Carp::cluck("no clout_type for addCloutsToTagArray
"tagid IN ($tagids_in_str) AND name='tag_clout'");

# Pull values from tagname params named 'tag_clout'
my $tagname_clout_hr = { };
my %tagnameid = map { ($_->{tagnameid}, 1) } @$ar;
my @tagnameids = sort { $a <=> $b } keys %tagnameid;
my $tagnameids_in_str = join(',', @tagnameids);
my $tagname_clout_hr = $self->sqlSelectAllKeyValue(
'tagnameid, value', 'tagname_params',
"tagnameid IN ($tagnameids_in_str) AND name='tag_clout'");
for my $tagnameid (keys %tagnameid) {
my $tn_data = $self->getTagnameDataFromId($tagnameid);
$tagname_clout_hr->{$tagnameid} = $tn_data->{tag_clout} || 1;
}

# Record which clout type each tagname uses
my $tagname_clid_hr = { };
for my $tagnameid (keys %tagnameid) {
my $clid = $self->getTagnameidClid($tagnameid);
$tagname_clid_hr->{$tagnameid} = $clid;
}

# Pull values from users_clout
# Tagnames with unspecified clout type get a reduced form
# of some other clout type.
my $default_clout_clid = $constants->{tags_unknowntype_default_clid} || 1;
my $default_clout_mult = $constants->{tags_unknowntype_default_mult} || 0.3;

# Get clouts for all users referenced.
my $user_clout_hr = { };
my %uid = map { ($_->{uid}, 1) } @$ar;
my @uids = sort { $a <=> $b } keys %uid;
my $uids_in_str = join(',', @uids);
my $clid = $self->getCloutTypes()->{$clout_type};
if (!$clid) { use Carp; Carp::cluck("no clid for addCloutsToTagArrayref '$clout_type'"); }
my $clout_info = $self->getCloutInfo()->{$clid};
if (!$clout_info) { use Carp; Carp::cluck("getCloutInfo returned false for clid=$clid") }
my $uid_info_hr = $self->sqlSelectAllHashref(
'uid',
'users.uid AS uid, seclev, karma, tag_clout,
UNIX_TIMESTAMP(created_at) AS created_at_ut,
clout',
"users,
users_info LEFT JOIN users_clout
ON (users_info.uid=users_clout.uid AND clid=$clid)",
"users.uid=users_info.uid AND users.uid IN ($uids_in_str)");
#print STDERR "uids_in_str='$uids_in_str'\n";

my $uid_clout_hr = { };
for my $uid (keys %$uid_info_hr) {
if (defined $uid_info_hr->{$uid}{clout}) {
$uid_clout_hr->{$uid} = $uid_info_hr->{$uid}{clout};
} else {
# There's a default clout for users who don't have
# the clout type in question. Use it.
my %user_stub = %{ $uid_info_hr->{$uid} };
# my $user_stub = {
# uid => $uid,
# seclev => $uid_info_hr->{$uid}{seclev},
# karma => $uid_info_hr->{$uid}{karma},
# tag_clout => $uid_info_hr->{$uid}{tag_clout},
# created_at_ut => $uid_info_hr->{$uid}{created_at_ut},
# }
# XXX this stub is good enough for now but we may
# need the whole actual getUser() user at some
# future time
my $clout = getObject($clout_info->{class}, { db_type => 'reader' });
$uid_clout_hr->{$uid} = $clout->getUserClout(\%user_stub);
}
for my $uid (keys %uid) {
# XXX getUser($foo, 'clout') does not work at the moment,
# so getUser($foo)->{clout} is used instead
$user_clout_hr->{$uid} = $self->getUser($uid)->{clout};
}


my $clout_types = $self->getCloutTypes();
for my $tag_hr (@$ar) {
$tag_hr->{tag_clout} = defined($tag_clout_hr ->{$tag_hr->{tagid}})
? $tag_clout_hr ->{$tag_hr->{tagid}}
: 1;
$tag_hr->{tagname_clout} = defined($tagname_clout_hr->{$tag_hr->{tagnameid}})
? $tagname_clout_hr->{$tag_hr->{tagnameid}}
: 1;
$tag_hr->{user_clout} = $uid_clout_hr ->{$tag_hr->{uid}};
#print STDERR "uc='$tag_hr->{user_clout}' for uid '$tag_hr->{uid}' for " . Dumper($tag_hr) if !defined $tag_hr->{user_clout};
my $mult = 1;
my $tagname_clid = $tagname_clid_hr->{$tag_hr->{tagnameid}};
if (!$tagname_clid) {
$mult = $default_clout_mult;
$tagname_clid = $default_clout_clid;
}
my $tagname_clout_name = $clout_types->{ $tagname_clid };
$tag_hr->{user_clout} = $mult * $user_clout_hr ->{$tag_hr->{uid}}{$tagname_clout_name};
$tag_hr->{total_clout} = $tag_hr->{tag_clout} * $tag_hr->{tagname_clout} * $tag_hr->{user_clout};
}
}
Expand Down Expand Up @@ -787,7 +838,7 @@ sub getUidsUsingTagname {
}

sub getAllObjectsTagname {
my($self, $name, $clout_type, $options) = @_;
my($self, $name, $options) = @_;
# my $mcd = undef;
# my $mcdkey = undef;
# if (!$options->{include_private}) {
Expand All @@ -807,7 +858,7 @@ sub getAllObjectsTagname {
"tagnameid=$id AND inactivated IS NULL $private_clause",
'ORDER BY tagid');
$self->addGlobjEssentialsToHashrefArray($hr_ar);
$self->addCloutsToTagArrayref($hr_ar, $clout_type);
$self->addCloutsToTagArrayref($hr_ar);
# if ($mcd) {
# my $constants = getCurrentStatic();
# my $secs = $constants->{memcached_exptime_tags_brief} || 300;
Expand All @@ -824,6 +875,29 @@ sub getTagnameParams {
"tagnameid=$tagnameid");
}

sub getWorstAdminCmdtype {
my($self, $tagnameid, $globjid) = @_;
$globjid ||= 0;
my $ar = $self->getTagnameAdmincmds($tagnameid, $globjid);
my $worst = '';
my $worst_count = 0;
for my $hr (@$ar) {
my $cmdtype = $hr->{cmdtype};
if ($cmdtype eq '_' && $worst_count == 0) {
$worst = '_';
} elsif ($cmdtype =~ /^[*)]$/ && $worst eq '') {
$worst = $cmdtype;
} elsif ($cmdtype =~ /^\#+$/) {
my $count = $cmdtype =~ tr/#/#/;
if ($count > $worst_count) {
$worst = $cmdtype;
$worst_count = $count;
}
}
}
return $worst;
}

sub getTagnameAdmincmds {
my($self, $tagnameid, $globjid) = @_;
return [ ] if !$tagnameid;
Expand Down Expand Up @@ -1255,7 +1329,21 @@ sub ajaxTagHistory {
$summ->{n_viewed} = scalar grep { $_->{tagname} eq $viewed_tagname } @$tags_ar;
$tags_ar = [ grep { $_->{tagname} ne $viewed_tagname } @$tags_ar ];

$tags_reader->addRoundedCloutsToTagArrayref($tags_ar, 'describe');
$tags_reader->addRoundedCloutsToTagArrayref($tags_ar);

my $clout_types = $tags_reader->getCloutTypes();
for my $tag (@$tags_ar) {
my $clid = $tags_reader->getTagnameidClid($tag->{tagnameid});
$tag->{clout_code} = $clid
? uc( substr( $clout_types->{$clid}, 0, 1) )
: '';
my $cmd = $tags_reader->getWorstAdminCmdtype($tag->{tagnameid}, $tag->{globjid});
if (!$tag->{clout_code}) {
$tag->{clout_code} = $cmd;
} elsif ($cmd) {
$tag->{clout_code} = "$tag->{clout_code} $cmd";
}
}

my $tagboxdb = getObject('Slash::Tagbox');
if (@$tags_ar && $globjid && $tagboxdb) {
Expand Down Expand Up @@ -1593,7 +1681,7 @@ sub listTagnamesAll {
}

sub listTagnamesActive {
my($self, $clout_type, $options) = @_;
my($self, $options) = @_;
my $constants = getCurrentStatic();
my $max_num = $options->{max_num} || 100;
my $seconds = $options->{seconds} || (3600*6);
Expand Down Expand Up @@ -1643,7 +1731,7 @@ sub listTagnamesActive {
AND IF(tagname_params.value IS NULL, 1, tagname_params.value) > 0
$slice_where_clause");
return [ ] unless $ar && @$ar;
$self->addCloutsToTagArrayref($ar, $clout_type);
$self->addCloutsToTagArrayref($ar);

# Sum up the clout for each tagname, and the median time it
# was seen within the interval in question.
Expand Down Expand Up @@ -1701,7 +1789,7 @@ sub listTagnamesActive {
}

sub listTagnamesRecent {
my($self, $clout_type, $options) = @_;
my($self, $options) = @_;
my $constants = getCurrentStatic();
my $seconds = $options->{seconds} || (3600*6);
my $include_private = $options->{include_private} || 0;
Expand Down Expand Up @@ -1904,7 +1992,7 @@ sub getRecentTagnamesOfInterest {
'tags',
"tagnameid IN ($tagnameids_of_interest_str)
AND created_at >= DATE_SUB(NOW(), INTERVAL $secsback SECOND)");
$self->addCloutsToTagArrayref($tags_ar, 'describe');
$self->addCloutsToTagArrayref($tags_ar);
my %tagnameid_weightsum = ( );
my %t_globjid_weightsum = ( );
# Admins will care less about new tagnames applied to data types other
Expand Down
2 changes: 2 additions & 0 deletions plugins/Tags/mysql_dump.sql
Expand Up @@ -23,6 +23,8 @@ INSERT INTO vars (name, value, description) VALUES ('tags_stories_examples', '',
INSERT INTO vars (name, value, description) VALUES ('tags_stories_lastscanned', '0', 'The last tagid scanned to update stories');
INSERT INTO vars (name, value, description) VALUES ('tags_stories_top_minscore', '2', 'Minimum score a tag must have to make it into the top tags for a story');
INSERT INTO vars (name, value, description) VALUES ('tags_udc_daysback', '182', 'Days back to crunch numbers for tags_udc related tables, should be a multiple of 7');
INSERT INTO vars (name, value, description) VALUES ('tags_unknowntype_default_clid', '1', 'For tags of unknown type, which clout id do we pretend they are?');
INSERT INTO vars (name, value, description) VALUES ('tags_unknowntype_default_mult', '0.3', 'For tags of unknown type, what multiplier do we give to the tagging user clout or type tags_unknowntype_default_clid?');
INSERT INTO vars (name, value, description) VALUES ('tags_urls_examples_pre', 'plus minus binspam', 'Example tags for urls');
INSERT INTO vars (name, value, description) VALUES ('tags_urls_examples', '', 'Example tags for urls');
INSERT INTO vars (name, value, description) VALUES ('tags_urls_lastscanned', '0', 'The last tagid scanned to update urls');
Expand Down
7 changes: 4 additions & 3 deletions plugins/Tags/templates/taghistory;misc;default
Expand Up @@ -27,16 +27,17 @@ __template__
<table class="data">
[% toggle = 1 %]
[% IF tags.size > 0 %]
<tr class="data_hl0"><td colspan="6">Viewed by [% summary.n_viewed %]</td></tr>
<tr class="data_hl0"><td colspan="6">
<tr class="data_hl0"><td colspan="7">Viewed by [% summary.n_viewed %]</td></tr>
<tr class="data_hl0"><td colspan="7">
[% constants.tags_upvote_tagname %]: [% summary.up_count %] [% summary.up_pop %]
(ed: [% summary.up_count_ed %])</td></tr>
<tr class="data_hl0"><td colspan="6">
<tr class="data_hl0"><td colspan="7">
[% constants.tags_downvote_tagname %]: [% summary.down_count %] [% summary.down_pop %]
(ed: [% summary.down_count_ed %])</td></tr>
[% FOREACH tag = tags %]
<tr class="data_hl[% toggle %]">
[% nickname = Slash.db.getUser(tag.uid, "nickname") %]
<td align=left>[% tag.clout_code %]</td>
<td>[% tag.tagname %]</td>
<td align=left>[% tag.tag_clout %]</td>
<td align=left>[% tag.tagname_clout %]</td>
Expand Down
4 changes: 4 additions & 0 deletions sql/mysql/upgrades
Expand Up @@ -5149,3 +5149,7 @@ UPDATE vars SET value = 'T_2_5_0_195' WHERE name = 'cvs_tag_currentcode';

# SLASHCODE/USEPERL LAST UPDATED HERE

# for plugins/Tags
INSERT INTO vars (name, value, description) VALUES ('tags_unknowntype_default_clid', '1', 'For tags of unknown type, which clout id do we pretend they are?');
INSERT INTO vars (name, value, description) VALUES ('tags_unknowntype_default_mult', '0.3', 'For tags of unknown type, what multiplier do we give to the tagging user clout or type tags_unknowntype_default_clid?');

2 changes: 1 addition & 1 deletion tagboxes/Top/Top.pm
Expand Up @@ -161,7 +161,7 @@ sub run {
$options->{days_back} = $days_back;
}
my $tag_ar = $tagsdb->getTagsByGlobjid($affected_id, $options);
$tagsdb->addCloutsToTagArrayref($tag_ar, 'describe');
$tagsdb->addCloutsToTagArrayref($tag_ar);
main::tagboxLog("Top->run called for $affected_id, " . scalar(@$tag_ar) . " tags");

# Generate the space-separated list of the top 5 scoring tags.
Expand Down

0 comments on commit befa763

Please sign in to comment.