50

Can anybody muster up a query on Data Explorer that will show me my progress towards the Generalist badge?

5
  • 6
    I think this is verging on spam.
    – nb69307
    May 23, 2010 at 10:10
  • 13
    @Neil, what now how? Can you explain to me what is spammy and how to fix it? More unicorns perhaps?
    – waffles
    May 23, 2010 at 10:46
  • 2
    +1: Enquiring minds would like to know... May 23, 2010 at 11:44
  • 1
    After reading the blog I came to ask the exact same question, so I'm happy someone beat me to it.
    – Ether
    May 24, 2010 at 0:10
  • 1
    @Neil - You only say that because you got one. ;-D
    – Pollyanna
    May 25, 2010 at 14:12

5 Answers 5

40

Another try: https://data.stackexchange.com/stackoverflow/q/734

declare @temp table (id int identity(1,1), TagName char(128), score int);

with tags40 as (
  select top 40 tagid from posttags group by tagid order by count(*) desc
),

answers as (
  select score, id, parentId from posts  -- find responses of questions
  where communityowneddate is null   -- which are non-comm-wiki
  and posttypeid = 2                 -- answers
  and owneruserid = ##UserId##       -- by you
)

insert @temp(TagName, score)
select t.TagName, sum(a.score) as score from answers a
inner join posttags pt on pt.postid = a.parentId -- find tags of your answers
inner join tags40 f on f.tagid = pt.tagid        -- which are one of the top 40s
inner join tags t on f.tagid = t.id
group by t.tagname
order by score desc

select *, case when score >= 15 then '' else '!' end from @temp
3
  • This looks correct for me. +1
    – YOU
    May 23, 2010 at 13:55
  • +1, seems to return the same as my approach.
    – Peter Lang
    May 23, 2010 at 13:59
  • I'm accepting this, the id and ! mark are a nice touch, and it seems to run plenty fast
    – waffles
    May 24, 2010 at 2:29
7

Unfortunately there is no way to tell when you are going to get the badge :)

However, this should show your progress with the top 40 tags:

With topTags As (
  Select Top 40 t.tagId
  From postTags t
  Group By t.tagId
  Order By Count(*) Desc
)
Select
  t.TagName,
  Sum( a.score ) As Score,
  Sum( Case When Sum( a.score ) >= 15 Then 1 Else 0 End ) Over ( ) As ReachedTags
From topTags tt
Join postTags pt On ( pt.tagId = tt.tagId )
Join tags t On ( t.id = tt.tagId )
Join posts q On (     q.id = pt.postId
                  And q.postTypeId = 1             -- only questions have tags
                  And q.communityOwnedDate Is Null -- community
)
Join posts a On ( a.parentId = q.id and a.communityOwnedDate is null)
Where a.ownerUserId = ##UserId##
Group By t.tagName
Order By score Desc
18
  • This can't be right: cloudexchange.cloudapp.net/stackoverflow/q/593 Also, are you filtering wiki posts?
    – Kobi
    May 23, 2010 at 11:17
  • @Kobi: Thanks, I was missing the multiplication (10 for answers, 5 for questions) and the wiki post filtering. Fixed that now.
    – Peter Lang
    May 23, 2010 at 11:28
  • Still weird - I have tons of regex and jquery questions, but none in the query: cloudexchange.cloudapp.net/stackoverflow/q/606 . Questions are not counted for this badge. This is a though one...
    – Kobi
    May 23, 2010 at 11:31
  • No, you should not multiplicate the score. The p.Score is already exactly what the badge is checking on.
    – user138231
    May 23, 2010 at 11:32
  • @BalusC: Thanks for clarifying, reverted that change.
    – Peter Lang
    May 23, 2010 at 11:38
  • Thanks for your patience, that's my first time working with this model. I was only counting question score instead of answer score, please retry :)
    – Peter Lang
    May 23, 2010 at 11:47
  • something is still off with this query... debugging
    – waffles
    May 23, 2010 at 12:54
  • @waffles: Much better, but something is still off .. In my case, I count 18 tags with >=15 score while I already have the Generalist badge. Edit: ach of course, your dump is almost 1 month old yet.
    – user138231
    May 23, 2010 at 13:24
  • @BalusC: I was checking for the ownerUserId of the question instead of the answer. waffles current approach sums the score of the questions instead of the answers, once this is fixed our queries return the same now. Still, this is not the same as the score I see in my profile...
    – Peter Lang
    May 23, 2010 at 13:28
  • @Peter: the current dump is almost 1 month old. I needed only 3/5 more votes for 2 tags to get it and I can confirm this in my history.
    – user138231
    May 23, 2010 at 13:30
  • @waffles I still think it is off. It shows me as -3 for CSS where as I am sure I have at least 12.
    – HAL 9000
    May 23, 2010 at 13:36
  • This is a bit better there was a typo there cloudexchange.cloudapp.net/stackoverflow/q/731 keep in mind as others said, the data dump is almost a month old
    – waffles
    May 23, 2010 at 13:38
  • @Yacoby: Both waffles' and my query seem to return 12 for CSS for your user...
    – Peter Lang
    May 23, 2010 at 13:42
  • This appears wrong; Jon Skeet looks very far away from the generalist badge and I doubt he got all his missing votes in the last 23 days. May 23, 2010 at 16:02
  • @Kop: What are you talking about? Jon Skeet has more than enough votes there to get the badge. Remember, it's 20 tags, 15 upvotes on each.
    – Aarobot
    May 23, 2010 at 17:00
2

Works now, all's cool

Peter Lang's script doesn't work for me: I'm posting the comment here, CWified, so that I can format the error message:

Error: System.InvalidCastException: Unable to cast object of type 'System.Int32' to type 'System.String'. at
 System.Data.Linq.IdentityManager.StandardIdentityManager.SingleKeyManager`2.TryCreateKeyFromValues(Object[] values, V& v)
 at System.Data.Linq.IdentityManager.StandardIdentityManager.IdentityCache`2.Find(Object[] keyValues) at System.Data.Linq.ChangeProcessor.GetOtherItem(MetaAssociation assoc, Object instance)
 at System.Data.Linq.ChangeProcessor.BuildEdgeMaps()
 at System.Data.Linq.ChangeProcessor.SubmitChanges(ConflictMode failureMode)
 at System.Data.Linq.DataContext.SubmitChanges(ConflictMode failureMode)
 at CloudOverflowWeb.Helpers.QueryRunner.ExecuteNonCached(ParsedQuery parsedQuery, Site site, User user)
 in C:\Users\sam\Desktop\Source\cloudoverflow\CloudOverflow\CloudOverflowWeb\Helpers\QueryRunner.cs:line 141
 at CloudOverflowWeb.Helpers.QueryRunner.GetJson(ParsedQuery parsedQuery, Site site, User user)
 in C:\Users\sam\Desktop\Source\cloudoverflow\CloudOverflow\CloudOverflowWeb\Helpers\QueryRunner.cs:line 171
 at CloudOverflowWeb.Controllers.QueryController.Execute(String sql, Int32 siteId)
 in C:\Users\sam\Desktop\Source\cloudoverflow\CloudOverflow\CloudOverflowWeb\Controllers\QueryController.cs:line 110

Should I fix it? I'm so far from being a generalist, I don't even recognise what language it is written in... No, wait! I've got it: those insert/join/seclects mean it's some sort of query language, right? And the errors have some funny four-letter word "Linq" in them: I've seen that at Lambda the Ultimate: could that be the name of the language? Ha! [linq] isn't a top-40 tag, I'm fine. Phew, another technology I don't have to learn to become a generalist...

2
  • No repro. Both Peter's and my script work find with your user id.
    – kennytm
    May 24, 2010 at 12:32
  • Don't get me started, LinqToSQL goes ape-crabs when you give it and non int primary keys, just discovered this now, will fix tomorrow.
    – waffles
    May 24, 2010 at 12:52
1

Because of the tag “info” page, we have a faster up-to-date value of total tag score.

To run, go to any page in Stack Overflow, then paste the following into Firebug:

$.get('/tags', function(html) {
 var votes = [];

 console.log('Gathering data, please wait for 40 seconds...');

 $("a.post-tag", html).slice(0, 40).each(function(index, a) {
  var tagname = $(a).text();
  var href = '/tags/' + encodeURIComponent(tagname) + '/info';
  setTimeout(function(){
   $.get(href, function(infoHtml) {
    var upvotes = $("#score-for-tag span", infoHtml).text();
    console.log(tagname, '->', upvotes);
    votes.push([+upvotes, tagname]);
    if (votes.length == 40) {
     votes.sort(function(x,y){return y[0]-x[0]});
     var res = ['<html><head><title>Generalist report</title></head><body><table><tr><th>Index</th><th>Tag</th><th colspan="2">Upvotes</th></tr>'];
     for (var l = 0; l < 40; ++ l) {
      res.push('<tr><td>');
      res.push(l+1);
      res.push('</td><td>');
      res.push(votes[l][1]);
      res.push('</td><td>');
      res.push(votes[l][0]);
      res.push('</td><td>');
      if (votes[l][0] < 15)
       res.push('!');
      res.push('</td></tr>');
     }
     res.push('</table></body></html>');
     document.open('text/html');
     document.write(res.join(''));
     document.close();
    }
   });
  }, 1000*(index+1));
 });


});

After you run it, the page will be replaced by a table summarizing the total upvotes of the top 40 tags. I think it's easy to convert into GreaseMonkey script but I'm lazy :)


Edit: Updated because the tag-wiki format is changed. Now it is accurate because the info page now shows the score instead of upvotes.

1

The KennyTM javascript version doesn't work for me (there is no score for tags where I have enough rights to edit the wiki), so here is my own version. Lazily I implemented it so you must run it from the Tags Page:

You also must change the user in the first line.

On the plus side: my version works, it shows some status updates (even without the firebug console) and it also displays gold, silver or bronze backgrounds according to the badge you already have for an individual tag:

// begin configure
var user = 'seanizer'; // your user name here
var mx = 5; // maximum ajax requests at any given time
// end configure

if ($('#result').size() == 0) {
    $(document.body).append($(
            '<div id="result" class="answer" '
            + 'style="text-align:left;width:30ex;position:absolute;top:0;left:0;bottom:0;'
            + 'margin:0;padding:1em;background:#ccc"></div>'
    ));
}
$('#result').html('<p>Loading Tags...</p><ul></ul>');
var dt = [], tg = []; // data, tags
var bs = 0; // number of current requests
$('.post-tag:lt(40)').each(function(index, el) {
    tg.push($(el).text().trim());
});
var dp; // dispatcher function
var ds = function() {
    var s = '<table style="background:white;">';
    dt.sort(function(a, b) {
        return (b[0] - a[0]);
    });
    $.each(
        dt,
        function(index, item) {
            var k = item[1], v = item[0];
            s = s + '<tr><td>'
            + k + '</td><td style="'
            + (v >= 1000 ? 'background:gold'
            : (v >= 400 ? 'background:silver'
            : (v >= 100 ? 'background:#A67D3D'
            : '')))
            + '">' + v + '</td><td>'
            + (v > 14 
            ? '<span style="color:green;font-weight:bold">&#x2713;</span>'
            : "") + "</td></tr>\n" + (index == 19 
            ? '<tr><td colspan="3"><b>You need 15 points in each row above'
                + ' this one to get the Generalist Badge</b></td></tr>'
            : '');
        }
    );
    s = s + "</table>";
    $('#result').html(s).find('td').css( {
        'padding' : '.3em',
        'text-align' : 'left'
    });
};
dp = function() { // dispatcher function
    if (bs < mx && tg.length > 0) {
        fs(tg.pop());
    }
    if (tg.length === 0 && bs === 0) {
        ds();
    } else {
        window.setTimeout(dp, 200);
    }
};
var fs = function(tag) { // find tag score
    bs++;
    $.get(
        'https://stackoverflow.com/tags/' + tag + '/stats',
        function(response) {
            var score = $(response)
                .find("#questions .fl:eq(1) a:contains(" + user + ")")
                .closest("tr").find("span").first().contents().text().trim();
            dt.push( [ !!score ? parseInt(score.replace(',','')) : 0, tag ]);
            $('#result').find("ul").append(
                $('<li>Loaded: <b>' + tag + "</b></li>")
            );
            bs--;
        }
    );
};
dp(); // start dispatcher

Edit:

And here is a minimized bookmarklet version:

javascript:var user='seanizer';eval(function(p,a,c,k,e,d){e=function(c){return(c<a?'':e(parseInt(c/a)))+((c=c%a)>35?String.fromCharCode(c+29):c.toString(36))};if(!''.replace(/^/,String)){while(c--){d[e(c)]=k[c]||e(c)}k=[function(e){return d[e]}];e=function(){return'\\w+'};c=1};while(c--){if(k[c]){p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c])}}return p}('2 I=5;u($(\'#9\').17()==0){$(18.1a).J($(\'<z 1b="9" 16="13" \'+\'g="f-B:t;Z:10;11:12;1c:0;t:0;1d:0;\'+\'1k:0;F:1l;c:#1m"></z>\'))}$(\'#9\').A(\'<p>1n 1j...</p><q></q>\');2 h=[],8=[];2 d=0;$(\'.Y-e:1e(1f)\').r(6(m,E){8.M($(E).f().L())});2 i;2 D=6(){2 s=\'<K g="c:1g;">\';h.1h(6(a,b){1o(b[0]-a[0])});$.r(h,6(m,o){2 k=o[1],v=o[0];s=s+\'<7><4>\'+k+\'</4><4 g="\'+(v>=U?\'c:S\':(v>=V?\'c:W\':(v>=R?\'c:#X\':\'\')))+\'">\'+v+\'</4><4>\'+(v>14?\'<l g="Q:T;O-P:N">✓</l>\':"")+"</4></7>\\n"+(m==19?\'<7><4 1i="3"><b>1Q 1R 15 1P 1O r 1L 1T\'+\' 1N 1S 1W x 1U 1p 1V</b></4></7>\':\'\')});s=s+"</K>";$(\'#9\').A(s).j(\'4\').1X({\'F\':\'.1M\',\'f-B\':\'t\'})};i=6(){u(d<I&&8.C>0){G(8.1J())}u(8.C===0&&d===0){D()}1w{1K.1x(i,1y)}};2 G=6(e){d++;$.x(\'1v://1u.1q/1r/\'+e+\'/1s\',6(H){2 w=$(H).j("#1t .1z:1A(1) a:1G("+1H+")").1I("7").j("l").1F().1E().f().L();h.M([!!w?1B(w.1C(\',\',\'\')):0,e]);$(\'#9\').j("q").J($(\'<y>1D: <b>\'+e+"</b></y>"));d--})};i();',62,122,'||var||td||function|tr|tg|result|||background|bs|tag|text|style|dt|dp|find||span|index||item||ul|each||left|if||score|get|li|div|html|align|length|ds|el|padding|fs|response|mx|append|table|trim|push|bold|font|weight|color|100|gold|green|1000|400|silver|A67D3D|post|width|30ex|position|absolute|answer|||class|size|document||body|id|top|bottom|lt|40|white|sort|colspan|Tags|margin|1em|ccc|Loading|return|Generalist|com|tags|stats|questions|stackoverflow|http|else|setTimeout|200|fl|eq|parseInt|replace|Loaded|contents|first|contains|user|closest|pop|window|row|3em|this|in|points|You|need|one|above|the|Badge|to|css'.split('|'),0,{}));void(0)

Just create a new bookmark and paste this code into the URL (just change your user name). Remember: it only works from the tags page.

Edit: fixed a bug for huge scores containing a comma. Sorry, I ain't there yet :-)

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .