GCJ の解法をページ内に表示する

  • /*
     * @title GCJ の解法をページ内に表示する
     * @description 解法をダウンロードすることなくページ内に表示できます。Google Code Jam 公式ページ( https://code.google.com/codejam/ )のスコアボード(ただし https は不可)、Code Jam Language Stats ( http://www.go-hero.net/jam/ ) の参加者別ページで利用できます。IE、Chrome ではセキュリティの関係で動作しなくなっているようなので、Firefox でご利用ください。
     * @include http://code.google.com/codejam/contest/scoreboard?*
     * @include http://www.go-hero.net/jam/*/name/*
     * @license MIT License
     * @require 
     */
    
    // loadScript
    // - based on http://www.nczonline.net/blog/2009/07/28/the-best-way-to-load-external-javascript/
    // - replaced appendChild to insertBefore, see http://www.stevesouders.com/blog/2010/05/11/appendchild-vs-insertbefore/
    function loadScript(url, callback){
        var script = document.createElement("script")
        script.type = "text/javascript";
    
        if (script.readyState){  //IE
            script.onreadystatechange = function(){
                if (script.readyState == "loaded" ||
                        script.readyState == "complete"){
                    script.onreadystatechange = null;
                    callback();
                }
            };
        } else {  //Others
            script.onload = function(){
                callback();
            };
        }
    
        script.src = url;
        var head = document.getElementsByTagName ("head")[0] || document.documentElement;
        head.insertBefore(script, head.firstChild);
    }
    
    function prepareToShow() {
        // prepare for google-code-prettify
        if (!window.prettyPrint) {
            var script = document.createElement("script");
            script.type = "text/javascript";
            script.src = "http://google-code-prettify.googlecode.com/svn/trunk/src/prettify.js";
            document.body.appendChild(script);
    
            var link = document.createElement("link");
            link.rel = "stylesheet";
            link.type = "text/css"
            link.href = "http://google-code-prettify.googlecode.com/svn/trunk/src/prettify.css";
            document.body.appendChild(link);
    
            var style = document.createElement("style");
            style.type = "text/css"
            style.appendChild(document.createTextNode("pre { word-wrap: break-word; }"));
            document.body.appendChild(style);
        }
    
        // prepare for zip.js
        if (!window.Zip) {
            loadScript(
                "https://github.com/miau/zipjs/raw/master/zip.min.js",
                function() {
                    var files = document.createElement("ul");
                    files.id = "files";
                    files.innerHTML = "<li>(files)</li>";
                    if (window.GCJ) {
                        document.getElementById("scb-rank-div").appendChild(files);
                    } else {
                        document.getElementById("content").appendChild(files);
                    }
    
                    addShowLinks();
                }
            );
        } else {
            addShowLinks();
        }
    }
    
    function addShowLinks() {
        if (window.GCJ) {
            var thead = document.getElementById('scb-table-header1');
            var tdIndexToProblem= [];
            var tdIndex = 0;
            for (var i = 0, th; th = thead.childNodes[i]; i++) {
                var colspan = th.getAttribute('colspan');
                for (var j = 0; j < colspan; j++) {
                    tdIndexToProblem[tdIndex++] = [i - 1, j];
                }
            }
            var elems = goog$dom$getElementsByTagNameAndClass("img", "scb-views-file", document);
            for (var i = 0, elem; elem = elems[i]; i++) {
                var td = elem.parentNode;
                var tdIndex = getChildIndex(td);
                var username = goog$dom$getElementsByTagNameAndClass("td", "scb-player-name", td.parentNode)[0].innerHTML.replace(/\s*<.*>\s*/g, '');
                var url =
                    GCJ.base_url +
                    "/scoreboard/do?cmd=GetSourceCode&contest=" + GCJ.contestId +
                    "&problem=" + GCJ.problems[tdIndexToProblem[tdIndex][0] | 0].id +
                    "&io_set_id=" + (tdIndexToProblem[tdIndex][1]) +
                    "&username=" + username;
                appendShowLink(elem, url);
            }
        } else {
            var elems = document.getElementsByTagName("a");
            for (var i = 0, elem; elem = elems[i]; i++) {
                if (elem.href.match(/GetSourceCode/)) {
                    appendShowLink(elem, elem.href);
                }
            }
        }
    }
    
    function getChildIndex(target) {
        for (var i = 0, elem; elem = target.parentNode.childNodes[i]; i++) {
            if (elem == target) {
                return i;
            }
        }
    }
    
    function appendShowLink(elem, url) {
        var showLink = document.createElement("a");
        showLink.href = "#";
        showLink.innerHTML = "Show";
        showLink.setAttribute("onclick", "showContents(this.url); return false;");
        showLink.url = url;
        elem.parentNode.appendChild(document.createTextNode(" - "));
        elem.parentNode.appendChild(showLink);
    }
    
    function showContents(orgUrl) {
        var url = isSameOrigin(document.URL, orgUrl)
            ? orgUrl
            : "http://allow-any-origin.appspot.com/" + orgUrl;
        Zip.inflate_file(url, function(zip) {
            var files = document.getElementById("files");
            files.innerHTML = "";
    
            // extract inner zip files
            for (var i in zip.files) {
                var file = zip.files[i];
                if (file.name.match(/\.zip$/)) {
                    var fileData = file.inflate();
                    var innerZip = Zip.inflate(fileData);
                    for (var j in innerZip.files) {
                        zip.files[i + "/" + j] = innerZip.files[j];
                    }
                    delete zip.files[i];
                }
            }
    
            for (var i in zip.files) {
                var file = zip.files[i];
                var item = document.createElement("li");
                var contents = file.inflate();
                for (var j = 0, str = ''; j < contents.length; j++) {
                    str += String.fromCharCode(contents[j]);
                }
                item.innerHTML =
                    "<h2>" + i + "</h2>" +
                    "<pre class='prettyprint'>" +
                    str.replace(/</g, "&lt;") +
                    "</pre>";
                files.appendChild(item);
            }
            prettyPrint();
        });
    }
    
    function isSameOrigin(docUrl, targetUrl) {
        if (targetUrl.match(RegExp("^/"))) {
            return true;
        }
        return getOrigin(docUrl) == getOrigin(targetUrl);
    }
    
    function getOrigin(url) {
        return url.match(RegExp("^https?://[^/]+")).shift();
    }
    
    // copied from Closure Library
    goog$dom$getElementsByTagNameAndClass = function(opt_tag, opt_class, opt_el) {
      return goog$dom$getElementsByTagNameAndClass_(document, opt_tag, opt_class,
                                                    opt_el);
    };
    
    goog$dom$getElementsByTagNameAndClass_ = function(doc, opt_tag, opt_class,
                                                      opt_el) {
      var parent = opt_el || doc;
      var tagName = (opt_tag && opt_tag != '*') ? opt_tag.toUpperCase() : '';
    
      if (goog$dom$canUseQuerySelector_(parent) &&
          (tagName || opt_class)) {
        var query = tagName + (opt_class ? '.' + opt_class : '');
        return parent.querySelectorAll(query);
      }
    
      // Use the native getElementsByClassName if available, under the assumption
      // that even when the tag name is specified, there will be fewer elements to
      // filter through when going by class than by tag name
      if (opt_class && parent.getElementsByClassName) {
        var els = parent.getElementsByClassName(opt_class);
    
        if (tagName) {
          var arrayLike = {};
          var len = 0;
    
          // Filter for specific tags if requested.
          for (var i = 0, el; el = els[i]; i++) {
            if (tagName == el.nodeName) {
              arrayLike[len++] = el;
            }
          }
          arrayLike.length = len;
    
          return arrayLike;
        } else {
          return els;
        }
      }
    
      var els = parent.getElementsByTagName(tagName || '*');
    
      if (opt_class) {
        var arrayLike = {};
        var len = 0;
        for (var i = 0, el; el = els[i]; i++) {
          var className = el.className;
          // Check if className has a split function since SVG className does not.
          if (typeof className.split == 'function' &&
              goog.array.contains(className.split(/\s+/), opt_class)) {
            arrayLike[len++] = el;
          }
        }
        arrayLike.length = len;
        return arrayLike;
      } else {
        return els;
      }
    };
    
    goog$dom$canUseQuerySelector_ = function(parent) {
      return !!(parent.querySelectorAll && parent.querySelector);
    };
    
    prepareToShow();
  • Permalink
    このページへの個別リンクです。
    RAW
    書かれたコードへの直接のリンクです。
    Packed
    文字列が圧縮された書かれたコードへのリンクです。
    Userscript
    Greasemonkey 等で利用する場合の .user.js へのリンクです。
    Loader
    @require やソースコードが長い場合に多段ロードする Loader コミのコードへのリンクです。
    Metadata
    コード中にコメントで @xxx と書かれたメタデータの JSON です。

History

  1. 2014/04/14 01:03:18 - 2014-04-14
  2. 2013/04/14 19:33:35 - 2013-04-14
  3. 2013/04/14 19:33:15 - 2013-04-14
  4. 2013/04/14 19:32:53 - 2013-04-14
  5. 2013/04/14 19:32:26 - 2013-04-14
  6. 2013/04/14 19:32:13 - 2013-04-14
  7. 2013/04/14 12:07:10 - 2013-04-14
  8. 2013/04/14 11:47:51 - 2013-04-14
  9. 2013/04/14 11:39:01 - 2013-04-14
  10. 2013/04/14 11:37:29 - 2013-04-14
  11. 2012/05/08 10:41:37 - 2012-05-08
  12. 2012/05/06 04:29:26 - 2012-05-06
  13. 2012/05/06 04:22:10 - 2012-05-06
  14. 2012/04/17 00:56:26 - 2012-04-17
  15. 2012/04/16 00:38:37 - 2012-04-16
  16. 2012/04/15 23:48:16 - 2012-04-15
  17. 2012/04/14 11:17:23 - 2012-04-14
  18. 2011/05/04 19:03:52 - 2011-05-04
  19. 2011/05/04 19:02:18 - 2011-05-04
  20. 2011/05/04 18:10:41 - 2011-05-04
  21. 2011/05/04 17:50:44 - 2011-05-04
  22. 2011/05/04 08:05:48 - 2011-05-04