A statisztikák már egy másik kóddal készülnek!

Az eredeti kód forrása és leírása: en:Wikipedia:List of Wikipedians by number of edits/How to generate the lists

java -Xmx1000m -Dbegin.date=2009-01-01 -Dend.date=2009-01-31 -Dlimit=250 WikipediansByNumberOfRecentEdits_hu huwiki-20090215-stub-meta-history.xml.gz huwiki-20090215-user_groups.sql.gz > result.txt
java -Xmx1000m -Dbegin.date=2009-01-01 -Dend.date=2009-01-31 -Dlimit=500 WikipediansByNumberOfEdits_hu huwiki-20090215-stub-meta-history.xml.gz huwiki-20090215-user_groups.sql.gz > result.txt

AnonymousUsers.java

import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
 
class AnonymousUsers {
 
        private Map<String, String> users = new HashMap<String, String>();
 
        private static final String INPUT_FILE_NAME = "anonymous.txt";
 
        public void initialize() throws FileNotFoundException, IOException {
                BufferedReader reader = null;
                try {
                        reader = new BufferedReader(new FileReader(INPUT_FILE_NAME));
                        final Pattern pattern = Pattern.compile("^\\s*\\d*\\.?\\s*User:");
                        while (true) {
                                final String line = reader.readLine();
                                if (line == null || line.length() == 0) {
                                        break;
                                }
                                final Matcher matcher = pattern.matcher(line);
                                final String user = matcher.replaceFirst("");
                                users.put(user, user);
                        }
                } finally {
                        if (reader != null) {
                                reader.close();
                        }
                }
        }
 
        public boolean contains(String user) {
                return users.containsKey(user);
        }
 
        public String toString() {
                return users.toString();
        }
 
}

Namespaces.java

import java.util.HashMap;
import java.util.Map;
 
class Namespaces {
 
        public static final int MAIN_NAMESPACE = 0;
 
        private final Map<String, Integer> map = new HashMap<String, Integer>();
 
        public void add(String key, int ns) {
                map.put(key, ns);
        }
 
        public int ns(String text) {
                final String NAMESPACE_SEPARATOR = ":";
                if (!text.contains(NAMESPACE_SEPARATOR)) {
                        return MAIN_NAMESPACE;
                }
                Integer ns = map.get(text.split(NAMESPACE_SEPARATOR)[0]);
                if (ns == null) {
                        return MAIN_NAMESPACE;
                }
                return ns;
        }
 
}

UnflaggedBots.java

import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
 
public class UnflaggedBots {
 
        private Map<String, String> users = new HashMap<String, String>();
 
        private static final String INPUT_FILE_NAME = "unflagged-bots.txt";
 
        public void initialize() throws FileNotFoundException, IOException {
                BufferedReader reader = null;
                try {
                        reader = new BufferedReader(new FileReader(INPUT_FILE_NAME));
                        final Pattern pattern = Pattern.compile("^\\s*\\d*\\.?\\s*");
                        while (true) {
                                final String line = reader.readLine();
                                if (line == null || line.length() == 0) {
                                        break;
                                }
                                final Matcher matcher = pattern.matcher(line);
                                final String user = matcher.replaceFirst("");
                                users.put(user, user);
                        }
                } finally {
                        if (reader != null) {
                                reader.close();
                        }
                }
        }
 
        public boolean contains(String user) {
                return users.containsKey(user);
        }
 
        public String toString() {
                return users.toString();
        }
 
}

User.java

import java.util.Date;

class User {
  private int id = 0;
  private String text = null;
  private int edits = 0;
  private int editsInRecentDays = 0;
  private int editsMain = 0;
  private int editsMainInRecentDays = 0;
  private Date firstEdit = null;
  private Date lastEdit = null;
  
  public int getId() {
    return id;
  }
  
  public void setId(int id) {
    this.id = id;
  }
  
  public Date getFirstEdit() {
    return firstEdit;
  }

  public void setFirstEdit(Date fe) {
    firstEdit = fe;
  }

  public Date getLastEdit() {
    return lastEdit;
  }

  public void setLastEdit(Date fe) {
    lastEdit = fe;
  }
  
  public String getText() {
    return text;
  }

  public void setText(String text) {
    this.text = text;
  }

  public int getEdits() {
    return edits;
  }

  public int getEditsInRecentDays() {
    return editsInRecentDays;
  }

  public int getEditsMain() {
    return editsMain;
  }

  public int getEditsMainInRecentDays() {
    return editsMainInRecentDays;
  }

  public void incrementEdits(){
    edits++;
  }

  public void incrementEditsInRecentDays(){
    editsInRecentDays++;
  }

  public void incrementEditsMain(){
    editsMain++;
  }

  public void incrementEditsMainInRecentDays(){
    editsMainInRecentDays++;
  }

  public User(){
  }

  public User(int id, String text){
    this.id = id;
    this.text = text;
  }

  public boolean isIpAddress(){
    return id == 0;
  }

  public String toString() {
    return "id: " + id
         + ", text: " + text
         + ", edits: " + edits
         + ", editsRecentDays: " + editsInRecentDays;
  }

}

UserGroups.java

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.HashMap;
import java.util.Map;
import java.util.StringTokenizer;
import java.util.regex.Pattern;
import java.util.zip.GZIPInputStream;
 
class UserGroups {
 
        public static final String SYSOP = "sysop";
        public static final String BOT = "bot";
        public static final String FILE_NAME_SUFFIX = "user_groups.sql.gz";
 
        private final Map<Integer, Integer> sysops = new HashMap<Integer, Integer>();
        private final Map<Integer, Integer> bots = new HashMap<Integer, Integer>();
 
        public void initialize(InputStream inputStream) throws IOException {
                BufferedReader reader = null;
                reader = new BufferedReader(new InputStreamReader(new GZIPInputStream(inputStream)));
                final Pattern lineStartPattern = Pattern.compile("^INSERT INTO `user_groups` VALUES \\(");
                while(true){
                        String line = reader.readLine();
                        if (line == null) {
                                break;
                        }
                        if (!lineStartPattern.matcher(line).find()){
                                continue;
                        }
                        line = lineStartPattern.matcher(line).replaceFirst("");
                        line = Pattern.compile("\\);$").matcher(line).replaceFirst("");
                        final String[] userGroupStrings = line.split("\\),\\(");
                        for (String userGroupString : userGroupStrings) {
                                final StringTokenizer userGroupTokenizer = new StringTokenizer(userGroupString, ",");
                                final int user = Integer.parseInt(userGroupTokenizer.nextToken());
                                final String group = userGroupTokenizer.nextToken();
                                if (group.equals("'" + SYSOP + "'")) {
                                        sysops.put(user, user);
                                } else if (group.equals("'" + BOT + "'")) {
                                        bots.put(user, user);
                                }
                        }
                }
        }
 
        public String group(int user) {
                if (sysops.containsKey(user)) {
                        return SYSOP;
                } else if (bots.containsKey(user)) {
                        return BOT;
                } else {
                        return "";
                }
        }
 
}

WikipediansByNumberOfEdits.java

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.EmptyStackException;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.Stack;
import java.util.TimeZone;
import java.util.zip.GZIPInputStream;

import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParserFactory;

import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;

public abstract class WikipediansByNumberOfEdits {

  private static final String YEARMONTH_FORMAT_STRING = "yyyy-MM";
  private static final String DATE_FORMAT_STRING = YEARMONTH_FORMAT_STRING + "-dd";
  public static final DateFormat DATE_FORMAT = new SimpleDateFormat(DATE_FORMAT_STRING);
  private static final String TIME_FORMAT_STRING = "HH:mm:ss";

  private final Date dateStarted =  new Date();

  private static final String LIMIT_PROPERTY_KEY = "limit";
  private int limit = 0;

  protected void execute(String[] args) {

    try {
      final int VALID_ARGUMENT_LENGTH = 2;
      if (args.length < VALID_ARGUMENT_LENGTH) {
        printUsage();
        System.exit(1);
      }
      System.err.println("Started. " + dateStarted);
      String limitText = System.getProperty(LIMIT_PROPERTY_KEY, "5000");
      limit = Integer.parseInt(limitText);
      final File dumpFile = new File(args[0]);
      fileNameCheck(dumpFile);
      final File userGroupsFile = new File(args[1]); 
      fileNameCheck(userGroupsFile);
      final PrintWriter writer = new PrintWriter(new OutputStreamWriter(System.out, "UTF-8"));
      final UserGroups userGroups = new UserGroups();
      InputStream userGroupsInputStream = null;
      try {
        userGroups.initialize(new FileInputStream(userGroupsFile));
      } finally {
        if (userGroupsInputStream != null) {
          try {
            userGroupsInputStream.close();
          } catch (IOException e) {
            e.printStackTrace();
          }
        }
      }
      final DumpHandler dumpHandler = new DumpHandler();
      dumpHandler.setIpAddressesAreToBeCounted(getIpAddressesAreToBeCounted());
      InputStream dumpInputStream = null;
      try {
        dumpInputStream = new GZIPInputStream(new FileInputStream(dumpFile));
        SAXParserFactory.newInstance().newSAXParser().parse(dumpInputStream, dumpHandler);
      } finally {
        if (dumpInputStream != null) {
          try {
            dumpInputStream.close();
          } catch (IOException e) {
            e.printStackTrace();
          }
        }
      }
      final WikipediansPrinter[] printers = createPrinters();
      for (WikipediansPrinter printer : printers) {
        printer.setWriter(writer);
        printer.setBeginTimestamp(dumpHandler.getBeginTimestamp());
        printer.setEndTimestamp(dumpHandler.getEndTimestamp());
        printer.setTotalEdits(dumpHandler.getRevisionCounter());
        printer.setTotalEditsInPeriod(dumpHandler.getRevisionInPeriodCounter());
        printer.print(dumpHandler.getUsers(), userGroups, limit);
        if (!printer.equals(printers[printers.length - 1])) {
          writer.println();
        }
      }
    } catch (NumberFormatException e) {
      System.err.println("The specified system property \"" + LIMIT_PROPERTY_KEY + "\" is not a valid integer.");
      System.err.println(e);
      System.exit(1);
    } catch (FileNotFoundException e) {
      System.err.println(e);
      System.exit(1);
    } catch (ParserConfigurationException e) {
      e.printStackTrace();
      System.exit(1);
    } catch (SAXException e) {
      if (e.getCause() instanceof ParseException) {
        System.err.println(e);
      } else {
        e.printStackTrace();
      }
      System.exit(1);
    } catch (IOException e) {
      e.printStackTrace();
      System.exit(1);
    } finally {
      final Date dateEnded = new Date();
      System.err.println("Ended. " + dateEnded);
      final SimpleDateFormat dateFormat = new SimpleDateFormat(TIME_FORMAT_STRING);
      dateFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
      System.err.println("Elapsed: " + dateFormat.format(new Date(dateEnded.getTime() - dateStarted.getTime())));
    }

  }

  private void printUsage() {
    System.err.print("Usage (example): java -Xmx500m -Dbegin.date=2008-05-01 -Dend.date=2008-05-31 -Dlimit=500");
    System.err.print(" " + getClass().getName());
    System.err.print(" " + getWikiName() + "-20080614-stub-meta-history.xml.gz");
    System.err.print(" " + getWikiName() + "-20080614-" + UserGroups.FILE_NAME_SUFFIX);
    System.err.print(" > result.txt");
    System.err.println();
  }

  private void fileNameCheck(File file) {
    if (!file.getName().startsWith(getWikiName())) {
      System.err.println("WARNING: The specified file name '" + file.getName() + "' does not start with '" + getWikiName() + "'.");
      try {
        Thread.sleep(5000);
      } catch(InterruptedException e) {
      }
    }
  }

  protected abstract String getWikiName();

  protected abstract WikipediansPrinter[] createPrinters();

  protected boolean getIpAddressesAreToBeCounted() {
    return true;
  }

  private static class DumpHandler extends DefaultHandler {

    private final Namespaces namespaces = new Namespaces(); 

    private final Stack<String> elementStack = new Stack<String>();

    private Date beginTimestamp = null;
    private Date endTimestamp = null;

    public Date getBeginTimestamp() {
      return beginTimestamp;
    }

    public Date getEndTimestamp() {
      return endTimestamp;
    }

    private static final DateFormat TIMESTAMP_DUMP_FORMAT
    = new SimpleDateFormat(DATE_FORMAT_STRING + "'T'" + TIME_FORMAT_STRING + "'Z'z");

    private static final String BEGIN_DATE_PROPERTY_KEY = "begin.date";
    private static final String END_DATE_PROPERTY_KEY = "end.date";

    private boolean ipAddressesAreToBeCounted = true;

    public void setIpAddressesAreToBeCounted(boolean ipAddressesAreToBeCounted) {
      this.ipAddressesAreToBeCounted = ipAddressesAreToBeCounted;
    }

    private int editsInLastMonth = 0;
    private Calendar beginCalendar = Calendar.getInstance();
    private Set<String> usersEditedInLastMonth = new HashSet<String>();

    public void startDocument() throws SAXException {
      beginTimestamp = getDateProperty(BEGIN_DATE_PROPERTY_KEY);
      final Calendar endTimestampCalendar = Calendar.getInstance();
      endTimestampCalendar.setTime(getDateProperty(END_DATE_PROPERTY_KEY));
      endTimestampCalendar.add(Calendar.HOUR, 23);
      endTimestampCalendar.add(Calendar.MINUTE, 59);
      endTimestampCalendar.add(Calendar.SECOND, 59);
      endTimestamp = endTimestampCalendar.getTime();
      beginCalendar.setTime(beginTimestamp);
    }

    public void endDocument() throws SAXException {
      System.err.println("Processed: " + revisionCounter);
      System.err.println("Az adott hónapban"
      + " (" + new SimpleDateFormat(YEARMONTH_FORMAT_STRING).format(beginTimestamp) + ")"
      + " a magyar Wikipédiában átlagosan napi "
      + (int)(editsInLastMonth / beginCalendar.getActualMaximum(Calendar.DATE))
      + " szerkesztés történt, botokkal együtt pedig "
      + usersEditedInLastMonth.size()
      + " regisztrált felhasználó szerkesztett.");
      //                    System.err.println("Timestamp ParseException: " + timestampParseExceptionCount + " occured.");
      //                    System.err.println("User ID error: " + userIdErrorCount + " occured.");
      System.err.flush();
    }

    private static Date getDateProperty(String key) throws SAXException {
      String property = System.getProperty(key);
      try {
        return DATE_FORMAT.parse(property);
      } catch (ParseException e) {
        throw new SAXException(e);
      }
    }

    public void startElement(String uri, String localName, String qName, Attributes atts) throws SAXException {
      String name = localName.equals("") ? qName : localName;
      elementStack.push(name);
      if (name.equals("namespace")) {
        String key = "";
        try {
          key = atts.getValue("key");
          ns = Integer.parseInt(key);
        } catch (NumberFormatException e) {
          throw new SAXException("ns: " + key, e);
        }
      }
    }

    private int revisionCounter = 0;

    int getRevisionCounter() {
      return revisionCounter;
    }

    private int revisionInPeriodCounter = 0;

    int getRevisionInPeriodCounter() {
      return revisionInPeriodCounter;
    }

    private int ns = 0;
    private String namespace = "";

    private String pageTitle = "";

    private int userId = 0;
    private String userIdString = "";
    private String userText = "";
    private Date timestamp = null;
    private String timestampString = "";

    private boolean ignoreRevision = false;

    private Map<String, User> map = new HashMap<String, User>();

    public User[] getUsers() {
      return map.values().toArray(new User[map.size()]);
    }

    private int timestampParseExceptionCount = 0;
    private int userIdErrorCount = 0;

    public void endElement(String uri, String localName, String qName) throws SAXException {
      final String name = elementStack.pop();
      if (name.equals("namespace")) {
        namespaces.add(namespace, ns);
        ns = 0;
        namespace = "";
      } else if (name.equals("page")) {
        pageTitle = "";
      } else if (name.equals("timestamp")) {
        ignoreRevision = false;
        try {
          timestamp = TIMESTAMP_DUMP_FORMAT.parse(timestampString + "UTC");
          timestampString = "";
        } catch (ParseException e) {
          timestampParseExceptionCount++;
          ignoreRevision = true;
        }
      } else if (name.equals("revision")) {
        if (!userIdString.equals("")) {
          try {
            userId = Integer.parseInt(userIdString);
          } catch (NumberFormatException e) {
            ignoreRevision = true;
          }
        }
        if (ignoreRevision) {
          return;
        }
        User user = null;
        if (ipAddressesAreToBeCounted || userId != 0) {
          user = map.get(userText);
          if (user == null) {
            user = new User(userId, userText);
            map.put(userText, user);
          }
          if (user.getId() < userId) {
            user.setId(userId);
          }
          if (user.getId() != userId) {
            userIdErrorCount++;
          }
          if (timestampBeroreOrEquals(timestamp)) {
            user.incrementEdits();
            if (user.getFirstEdit() == null || user.getFirstEdit().after(timestamp)) {
              user.setFirstEdit(timestamp); 
            }
            if (user.getLastEdit() == null || user.getLastEdit().before(timestamp)) {
              user.setLastEdit(timestamp); 
            }
            if (timestampIsInPeriod(timestamp)) {
              user.incrementEditsInRecentDays();
            }
            if (namespaces.ns(pageTitle) == Namespaces.MAIN_NAMESPACE) {
              user.incrementEditsMain();
              if (timestampIsInPeriod(timestamp)) {
                user.incrementEditsMainInRecentDays();
              }
            }
          }
        }
        final Calendar calendar = Calendar.getInstance();
        calendar.setTime(timestamp);
        if (calendar.get(Calendar.YEAR) == beginCalendar.get(Calendar.YEAR)
            && calendar.get(Calendar.MONTH) == beginCalendar.get(Calendar.MONTH)) {
          editsInLastMonth ++;
          if (user != null) {
            usersEditedInLastMonth.add(user.getText());
          }
        }
        if (timestampIsInPeriod(timestamp)) {
          revisionInPeriodCounter ++;
        }
        userId = 0;
        userIdString = "";
        userText = "";
        timestamp = null;
        revisionCounter++;
        final int LOG_INTERVAL = 10000;
        if (revisionCounter % LOG_INTERVAL == 0) {
          System.err.println("Processed: " + revisionCounter);
        }
      }
    }

    private boolean timestampIsInPeriod(Date timestamp) {
      return ( timestamp.equals(beginTimestamp) || timestamp.after(beginTimestamp) )
      && timestampBeroreOrEquals(timestamp);
    }

    private boolean timestampBeroreOrEquals(Date timestamp) {
      return ( timestamp.before(endTimestamp) || timestamp.equals(endTimestamp) );
    }

    public void characters (char[] ch, int start, int length) {
      try {
        final String elementName = elementStack.peek();
        final String parentElementName = elementStack.elementAt(elementStack.size() - 2);
        final String string = new String(ch, start, length);
        if (elementName.equals("namespace")) {
          namespace += string;
        }
        if (elementName.equals("title")) {
          pageTitle += string;
        }
        if (elementName.equals("timestamp")) {
          timestampString += string;
          //                                    if (revisionCounter % 10000 == 0) {
          //                                            System.err.println(ch.length);
          //                                    }
        } else if (parentElementName.equals("contributor")) {
          if (elementName.equals("id")) {
            userIdString += string;
          } else if (elementName.equals("username")) {
            userText += string;
          } else if (userText.equals("") && elementName.equals("ip")) {
            userId = 0;
            userText += string;
          }
        }
      } catch (EmptyStackException e) {
        // NOP
      } catch (IndexOutOfBoundsException e) {
        // NOP
      }
    }

  }

}

WikipediansByNumberOfEdits_hu.java

import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.Comparator;
import java.util.Locale;
import java.text.SimpleDateFormat;

public class WikipediansByNumberOfEdits_hu extends WikipediansByNumberOfEdits {

  private static AnonymousUsers ANONYMOUS_USERS = null;
  private static UnflaggedBots UNFLAGGED_BOTS = null;

  /**
   * The main() method for this application.
   * @param args command-line arguments
   */
  public static void main(String[] args) {

    ANONYMOUS_USERS = new AnonymousUsers();
    UNFLAGGED_BOTS = new UnflaggedBots();
    try {
      ANONYMOUS_USERS.initialize();
      UNFLAGGED_BOTS.initialize();
      new WikipediansByNumberOfEdits_hu().execute(args);
    } catch (FileNotFoundException e) {
      e.printStackTrace();
      System.exit(1);
    } catch (IOException e) {
      e.printStackTrace();
      System.exit(1);
    }

  }

  protected String getWikiName() {
    return "huwiki";
  }

  protected boolean getIpAddressesAreToBeCounted() {
    return false;
  }

  protected WikipediansPrinter[] createPrinters() {
    final Printer printer = new Printer();
    printer.setAnonymousUsers(ANONYMOUS_USERS);
    printer.setUnflaggedBots(UNFLAGGED_BOTS);
    return new WikipediansPrinter[]{printer};
  }

  private static class Printer extends WikipediansPrinter {

      private AnonymousUsers anonymousUsers = null;
      private UnflaggedBots unflaggedBots = null;
      SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd HH:mm");
      //private SimpleDateFormat sdf = new SimpleDateFormat("YYYY. MMMM d., HH:mm:ss",
      //    new Locale("hu"));
      
      public void setAnonymousUsers(AnonymousUsers anonymousUsers) {
        this.anonymousUsers = anonymousUsers;
      }

      public void setUnflaggedBots(UnflaggedBots unflaggedBots) {
        this.unflaggedBots = unflaggedBots;
      }

      protected int getTargetEdits(User user) {
        return user.getEdits();
      }

      protected int getTargetTotalEdits() {
        return getTotalEdits();
      }

      protected String getTableHeader() {
        return "No. !! Szerkesztő !! Szerkesztésszám !! Szsz. szócikknévtérben !! Szsz. az adott hónapban !! Szsz. szócikknévtérben az adott hónapban !! Első szerkesztés !! Utolsó szerkesztés";
      }

      protected String getSpecialText() {
        return "Special";
      }

      protected String getUserText() {
        return "Szerkesztő";
      }

      protected String getSortable() {
        return SORTABLE;
      }

      protected void processAnonymous(User user) {
        if (anonymousUsers.contains(user.getText())) {
          user.setText("Névtelen");
        }
      }

      protected String getGroup(User user, String group) {
        if (group.equals("") && unflaggedBots.contains(user.getText())) {
          return UserGroups.BOT;
        } else {
          return group;
        }
      }

      protected Comparator<User> createComparator() {
        return new UsersComparator();
      }

      private static class UsersComparator implements Comparator<User> {
        public int compare(User user1, User user2) {
          if (user1.getEdits() != user2.getEdits()) {
            return user2.getEdits() - user1.getEdits(); 
          } else {
            return user2.getEditsInRecentDays() - user1.getEditsInRecentDays();
          }
        }
      }

      protected void printEdits(User user) {
        getWriter().print(" || " + user.getEdits());
        getWriter().print(" || " + user.getEditsMain());
        getWriter().print(" || " + user.getEditsInRecentDays());
        getWriter().print(" || " + user.getEditsMainInRecentDays());
        getWriter().print(" || " + sdf.format(user.getFirstEdit()));
        getWriter().print(" || " + sdf.format(user.getLastEdit()));
      }

  }

}

WikipediansByNumberOfRecentEdits_hu.java

import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.Comparator;
 
public class WikipediansByNumberOfRecentEdits_hu extends WikipediansByNumberOfEdits {
 
        private static AnonymousUsers ANONYMOUS_USERS = null;
 
        private static UnflaggedBots UNFLAGGED_BOTS = null;
 
        /**
         * The main() method for this application.
         * @param args command-line arguments
         */
        public static void main(String[] args) {
 
                ANONYMOUS_USERS = new AnonymousUsers();
                UNFLAGGED_BOTS = new UnflaggedBots();
                try {
                        ANONYMOUS_USERS.initialize();
                        UNFLAGGED_BOTS.initialize();
                        new WikipediansByNumberOfRecentEdits_hu().execute(args);
                } catch (FileNotFoundException e) {
                        e.printStackTrace();
                        System.exit(1);
                } catch (IOException e) {
                        e.printStackTrace();
                        System.exit(1);
                }
 
        }
 
        protected String getWikiName() {
                return "huwiki";
        }
 
        protected boolean getIpAddressesAreToBeCounted() {
                return false;
        }
 
        protected WikipediansPrinter[] createPrinters() {
                final Printer printer = new Printer();
                printer.setAnonymousUsers(ANONYMOUS_USERS);
                printer.setUnflaggedBots(UNFLAGGED_BOTS);
                return new WikipediansPrinter[]{printer};
        }
 
        private static class Printer extends WikipediansPrinter {
 
                private AnonymousUsers anonymousUsers = null;
 
                public void setAnonymousUsers(AnonymousUsers anonymousUsers) {
                        this.anonymousUsers = anonymousUsers;
                }
 
                private UnflaggedBots unflaggedBots = null;
 
                public void setUnflaggedBots(UnflaggedBots unflaggedBots) {
                        this.unflaggedBots = unflaggedBots;
                }
 
                protected int getTargetEdits(User user) {
                        return user.getEditsInRecentDays();
                }
 
                protected String getTableHeader() {
                        return "No. !! Szerkesztő !! Szerkesztésszám !! Szsz. szócikknévtérben !! Szsz. az adott hónapban !! Szsz. szócikknévtérben az adott hónapban";
                }
 
                protected String getSpecialText() {
                        return "Special";
                }
 
                protected String getUserText() {
                        return "Szerkesztő";
                }
 
                protected String getSortable() {
                        return SORTABLE;
                }
 
                protected void printHeader() {
                        getWriter().print("Period: "
                                        + DATE_FORMAT.format(getBeginTimestamp())
                                        + " &mdash; "
                                        + DATE_FORMAT.format(getEndTimestamp())
                                        + " (UTC)");
                        getWriter().println();
                        getWriter().println();
                }
 
                protected void processAnonymous(User user) {
                        if (anonymousUsers.contains(user.getText())) {
                                user.setText("Névtelen");
                        }
                }
 
                protected String getGroup(User user, String group) {
                        if (group.equals("") && unflaggedBots.contains(user.getText())) {
                                return UserGroups.BOT;
                        } else {
                                return group;
                        }
                }
 
                protected Comparator<User> createComparator() {
                        return new UsersComparator();
                }
 
                private static class UsersComparator implements Comparator<User> {
                        public int compare(User user1, User user2) {
                                if (user1.getEditsInRecentDays() != user2.getEditsInRecentDays()) {
                                        return user2.getEditsInRecentDays() - user1.getEditsInRecentDays();
                                } else {
                                        return user2.getEdits() - user1.getEdits(); 
                                }
                        }
                }
 
                protected void printEdits(User user) {
                        getWriter().print(" || " + user.getEdits());
						getWriter().print(" || " + user.getEditsMain());
                        getWriter().print(" || " + user.getEditsInRecentDays());
						getWriter().print(" || " + user.getEditsMainInRecentDays());
                }
        }
 
}

WikipediansPrinter.java

import java.io.PrintWriter;
import java.text.DecimalFormat;
import java.util.Arrays;
import java.util.Comparator;
import java.util.Date;

abstract class WikipediansPrinter {

  private PrintWriter writer = null;
  private Date beginTimestamp = null;
  private Date endTimestamp = null;
  private int totalEdits = 0;
  private int totalEditsInPeriod = 0;
  
  
  
  /* Getterek, setterek */

  public PrintWriter getWriter() {
    return writer;
  }

  public void setWriter(PrintWriter writer) {
    this.writer = writer;
  }
  
  public Date getBeginTimestamp() {
    return beginTimestamp;
  }

  public void setBeginTimestamp(Date beginTimestamp) {
    this.beginTimestamp = beginTimestamp;
  }

  public Date getEndTimestamp() {
    return endTimestamp;
  }

  public void setEndTimestamp(Date endTimestamp) {
    this.endTimestamp = endTimestamp;
  }

  public void setTotalEdits(int totalEdits) {
    this.totalEdits = totalEdits;
  }

  public int getTotalEdits() {
    return totalEdits;
  }

  public void setTotalEditsInPeriod(int totalEditsInPeriod) {
    this.totalEditsInPeriod = totalEditsInPeriod;
  }

  protected int getTargetTotalEdits() {
    return totalEditsInPeriod;
  }
  
  public void print(User[] users, UserGroups userGroups, int limit) {
    try {
      printHeader();
      Arrays.sort(users, createComparator());
      writer.print("{| class=\"wikitable" + getSortable() + "\"");
      writer.println();
      writer.print("! " + getTableHeader());
      writer.println();
      int rank = 0;
      int prevCount = 0;
      int sameRank = 0;
      int totalEditsByListedUsers = 0;
      int numberOfListedEditors = 0;
      for (User user : users) {
        final String group = getGroup(user, userGroups.group(user.getId()));
        final String groupText = (group.equals("") ? "" : " (" + group + ")");
        final String rankText;
        writer.print("|-");
        writer.println();
        if (!group.equals(UserGroups.BOT)) {
          if (rank == 0) {
            rank++;
            sameRank = 1;
          } else if (getTargetEdits(user) < prevCount) {
            rank += sameRank;
            sameRank = 1;
          } else {
            sameRank++;
          }
          if (rank > limit) {
            break;
          }
          rankText = Integer.toString(rank);
          numberOfListedEditors++;
          totalEditsByListedUsers += getTargetEdits(user);
          prevCount = getTargetEdits(user);
          writer.print("| " + rankText + ".");
        } else {
          writer.print("| ");
        }
        writer.print(" || ");
        processAnonymous(user);
        if (user.getId() == 0) {
          writer.print("[[" + getSpecialText() + ":Contributions/" + user.getText() + "|" + user.getText() + "]]");
        } else {
          writer.print("[[" + getUserText() + ":" + user.getText() + "|" + user.getText() + "]]");
        }
        writer.print(groupText);
        printEdits(user);
        writer.println();
      }
      writer.print("|}");
      writer.println();
      writer.print("A listában szereplő " + numberOfListedEditors + " szerkesztő összesen " + totalEditsByListedUsers + " szerkesztést tett,"
      + " ami szerkesztőnként átlagosan " + (int)(totalEditsByListedUsers / numberOfListedEditors) + " szerkesztést jelent. "
      + "Ez a magyar Wikipédia "  + getTargetTotalEdits() + " szerkesztésének "
      + new DecimalFormat("#0.0").format(((float)totalEditsByListedUsers / (float)getTargetTotalEdits()) * 100) + "%-a.");
    } finally {
      writer.flush();
      System.err.flush();
    }
  }

  protected abstract int getTargetEdits(User user);
  protected abstract String getTableHeader();
  protected abstract String getSpecialText();
  protected abstract String getUserText();
  protected abstract Comparator<User> createComparator();

  protected void printHeader() {
    return;
  }

  protected abstract void printEdits(User user);

  protected void processAnonymous(User user) {
    return;
  }

  protected String getGroup(User user, String group) {
    return group;
  }

  protected final String SORTABLE = " sortable";

  protected String getSortable() {
    return "";
  }

}