Task

Sort most popular programming languages based on the number of users on Rosetta Code.

Show the languages with at least 100 users.



A method to solve the task

Users of a computer programming language   X   are those referenced in the page:

 https://rosettacode.org/wiki/Category:X_User,     or preferably: 
 https://rosettacode.org/mw/index.php?title=Category:X_User&redirect=no to avoid re-directions. 

In order to find the list of such categories,   it's possible to first parse the entries of:

 http://rosettacode.org/mw/index.php?title=Special:Categories&limit=5000. 

Then download and parse each computer language   users   category to find the number of users of that computer language.



Sample output on 18 February 2019:

Language             Users
--------------------------
C                      391
Java                   276
C++                    275
Python                 262
JavaScript             238
Perl                   171
PHP                    167
SQL                    138
UNIX Shell             131
BASIC                  120
C sharp                118
Pascal                 116
Haskell                102
A Rosetta Code user usually declares using a language with the mylang template. This template is expected to appear on the User page. However, in some cases it appears in a user Talk page. It's not necessary to take this into account. For instance, among the 373 C users in the table above, 3 are actually declared in a Talk page.




import algorithm, httpclient, json, strformat, strscans, strutils
 
const
  Action = "action=query"
  Format = "format=json"
  FormatVersion = "formatversion=2"
  Generator = "generator=categorymembers"
  GcmTitle = "gcmtitle=Category:Language%20users"
  GcmLimit = "gcmlimit=500"
  Prop = "prop=categoryinfo"
 
  Page = "http://rosettacode.org/mw/api.php?"  &
         [Action, Format, Formatversion, Generator, GcmTitle, GcmLimit, Prop].join("&")
 
type Counts = tuple[lang: string, count: int]
 
proc cmp(a, b: Counts): int =
  ## Compare two count tuples. Place the one with greater count field first and when
  ## count fields are equal, place the one with the first name in alphabetic order.
  result = cmp(b.count, a.count)
  if result == 0: result = cmp(a.lang, b.lang)
 
var client = newHttpClient()
var counts: seq[Counts]
var url = Page
 
while true:
 
  # Access to the page and load the JSON representation.
  let response = client.get(url)
  if response.status != $Http200: break
  let root = response.body.parseJson()
 
  # Extract language names and number of users.
  for node in root{"query", "pages"}:
    var lang: string
    if node["title"].getStr().scanf("Category:$+ User", lang):
      let count = node{"categoryinfo", "size"}.getInt()
      counts.add (lang, count)
  if "continue" notin root: break
 
  # Load continuation page.
  let gcmcont = root{"continue", "gcmcontinue"}.getStr()
  let cont = root{"continue", "continue"}.getStr()
  url = Page & fmt"&gcmcontinue={gcmcont}&continue={cont}"
 
# Sort and display.
counts.sort(cmp)
var rank, lastCount = 0
for i, (lang, count) in counts:
  if count != lastCount:
    rank = i + 1
    lastCount = count
  echo &"{rank:3} {count:4} - {lang}"