Java, 1106 bytes
import java.io.*;import java.util.regex.*;()->{String u="",y="",z="",s,t;float h=0,a,l=0,d;int i=-1,k=-1;Matcher m;Pattern p=null;while(i<=k){try(BufferedReader g=new BufferedReader(new InputStreamReader(new java.net.URL("https://codegolf.stackexchange.com/users"+(k==-1?"?tab=NewUsers&sort=creationdate":"/"+i+"/?tab=topactivity")).openStream()));){while((s=g.readLine())!=null){Integer v=0;if(k==-1&s.contains("users/")&!s.contains("profile-me")){m=p.compile("(?<=users/)(\\d+)").matcher(s);if(m.find()){k=v.parseInt(m.group());break;}}if(s.contains("User")){m=p.compile("(?<=User )(.*)(?= - P)").matcher(s);if(m.find())u=m.group();}if(s.contains("Cast")){m=p.compile("(?<=\\>\\().*(?=\\)\\<)").matcher(s);if(m.find()&&(v=v.parseInt(m.group().replace(",","")))>1000){while(1>0){s=g.readLine();m=p.compile("(\\d*,?\\d+)(?=\\<.*\\>)").matcher(s);if(m.find()){if((t=g.readLine()).contains("up")&&(a=0f+v.parseInt(m.group().replace(",",""))/v)>h){y=""+u;h=a;}if(t.contains("down")){if((d=0f+v.parseInt(m.group().replace(",",""))/v)>l){z=""+u;l=d;}break;}}}}}}}catch(Exception e){}}System.out.print(y+"\n"+z);}
As a full class:
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.URL;
import java.util.regex.*;
public class C {
public static void main(String[] args) throws Exception {
String u="", y="", z="", s, t;
float h = 0, a, l = 0, d;
int i = -1, k = -1;
Matcher m;
Pattern p = null;
while (i < k) {
// System.out.println(i);
try (BufferedReader br = new BufferedReader(new InputStreamReader(new URL("https://codegolf.stackexchange.com/users" + (k == -1 ? "?tab=NewUsers&sort=creationdate" : "/" + i + "/?tab=topactivity")).openStream()));) {
while ((s = br.readLine()) != null) {
Integer v = 0;
if (k == -1 && s.contains("users/") && !s.contains("profile-me")) {
m = p.compile("(?<=users/)(\\d+)").matcher(s);
if (m.find()) {
k = v.parseInt(m.group());
break;
}
}
if (s.contains("User")) {
m = p.compile("(?<=User )(.*)(?= - P)").matcher(s);
if (m.find())
u = m.group();
}
if (s.contains("Cast")) {
m = p.compile("(?<=\\>\\().*(?=\\)\\<)").matcher(s);
if (m.find() && (v = v.parseInt(m.group().replace(",",""))) > 1000) {
while (true) {
s = br.readLine();
m = p.compile("(\\d*,?\\d+)(?=\\<.*\\>)").matcher(s);
if (m.find()) {
if ((t = br.readLine()).contains("up") && (a = 0f + v.parseInt(m.group().replace(",",""))/v)>h) {
y = ""+u;
h = a;
}
if (t.contains("down")) {
if ((d=0f + v.parseInt(m.group().replace(",",""))/v)>l) {
z = ""+u;
l = d;
}
break;
}
}
}
}
}
}
} catch (Exception e) {}
}
System.out.print(y+"\n"+z);
}
}
One word: Damn.
I mean, I've always wanted to do a challenge like this, but boy was it a doozy.
I didn't use the Stack Exchange API (don't know what it is, where to access it, or how to use it :P), so I basically had to do everything on my own; having the program crawl through each of the nearly 60,000 PPCG users' profile pages for the right data, looking up the HTML scripts and accounting for how the vote totals were laid out differently for different users1, and debugging (which was, perhaps unsurprisingly, a huge pain). And let me just say, this code could probably use some serious optimization. It takes well over two hours for the program to finish running on my machine, though most of the time is probably used opening the connections to the sites.
So here's a quick rundown of how it works:
- Create
String
variables to hold the upvotingest and downvotingest users on PPCG.
- Figure out the total number of active (and deleted/nonexistent) user accounts there are on the site. The program visits https://codegolf.stackexchange.com/users?tab=NewUsers&sort=creationdate and looks for the first user on the page, who happens to be the most recent addition to the community, and as such has the highest ID number. This ID number is set to be the total number of iterations for the loop.
- Start at ID 1 and visit https://codegolf.stackexchange.com/users/#, where the pound symbol represents the ID. Parse the HTML code (with regex͠,̰ nőͣ l͇̪e̐̃s̸͖̚͜͝s̡͍̲̫̋ͯ
) and collect the user's username, vote total, upvote total, and downvote total.
- Check to see if the upvotes to total votes ratio is larger than the current largest ratio, and set the current ratio to the new ratio if necessary. Do the same for the downvotes to total votes ratio, and also set the upvotingest and downvotingest user names when needed.
- Do steps 3 and 4 another (near) 60,000 times, incrementing the ID each time. (This takes care of the event when there is a tie.) If the user doesn't exist, either nothing matches or an Exception is thrown, and move on.
- Print the upvotingest and downvotingest users.
Yes, there are quite a few places where I can shave off a few bytes (especially on the strings where I use the contains
method), but I'll save that for later... maybe.
If you decide to run this program, be prepared to wait a couple hours for it to finish execution.
Here's a screenshot of the output:
![Output of the program](../../I/static/images/c1ef0c0e309ec29e554f4e7c04367e5692ef9f982d15504e8b81ce3383e00191.png)
In case it's difficult to read, at the bottom it says...
gnat
Peter Taylor
...and the total time it took for the program to finish: a whopping two hours, forty-eight minutes, and twenty-three seconds!
1 The instance on which this occurred had to do with how recently the user voted. If the user voted at least once within the past week or month, two(?) additional stats showing how many times they voted over the past week or month appear on their activity page.
10Easy: Conor O'Brien and Geobits, respectively. Where's my prize? :P – Mego – 2016-09-08T20:50:37.530
You should specify that submissions have to access the SE API (and only the SE API) – Nathan Merrill – 2016-09-08T20:51:43.703
Votes cast seem to be private to the user only. – Copper – 2016-09-08T21:05:27.030
Individual votes are private, but vote counts aren't. They're on the user profile. – Geobits – 2016-09-08T21:10:18.473
1
@Mego Contrary to popular belief... ;) http://data.stackexchange.com/codegolf/query/466199/top-downvoters
– Geobits – 2016-09-08T21:13:47.6631
@Mego Also contrary to popular belief... ;) http://data.stackexchange.com/codegolf/query/536416/top-upvoters
– ETHproductions – 2016-09-08T21:35:05.9337@ETHproductions makes me where wonder how bad the post had to be that alephalpha cast their only ever downvote on it. :D – Martin Ender – 2016-09-08T21:51:05.543
2@MartinEnder I accidentally downvoted a post once and realized after the grace period :D – ThreeFx – 2016-09-08T22:05:40.133
So http://codegolf.stackexchange.com/users is also off limits?
– Dennis – 2016-09-08T22:57:19.607@Dennis Uhh no, I shouldn't have limited the question to the API only – Beta Decay – 2016-09-08T23:00:04.803
Am I allowed to use
http://data.stackexchange.com/codegolf/csv/678543
so that I don't have to register for the API? – Daniel – 2016-09-09T16:55:13.8031Kind of scary that I'm 23rd in downvotes but not even near top 100 upvotes. I guess I'm just that evil – Blue – 2016-09-10T20:49:56.903