Commits

Maciej Fijalkowski  committed ff4aac6

progress. basic key insertion works

  • Participants
  • Parent commits 7f79457

Comments (0)

Files changed (10)

File codeviewer/conftest.py

+
+import os
+
+jstests_browser_specs = {
+    'supported': ['google-chrome'],
+    #'supported': ['firefox'],
+}
+
+class jstests_setup:
+    staticDirs = {
+        '/js': os.path.join(os.path.dirname(__file__), 'js')
+    }
+    jsRepos = ['/js']

File codeviewer/file.jinja

    <script type="text/javascript" src="js/jquery.scrollTo-1.4.2-min.js"></script>
    <script type="text/javascript" src="js/jquery.viewport.mini.js"></script>
    <script type="text/javascript" src="js/jquery.timer.js"></script>
+   <script type="text/javascript" src="js/libbasic.js"></script>
    <script type="text/javascript" src="js/files.js"></script>
    <script type="text/javascript" src="js/libkeys.js"></script>
    <script type="text/javascript" src="js/basic.js"></script>

File codeviewer/js/basic.js

 function EditorStatus()
 {
     var self = this;
-    self.line_position = 0;
-    self.col_position = 0;
-    self.saved_col_position = 0;
 
     self.MIN_LINE_POSITION = 100;
 
-    self.move_line_relative = function(offset) {
-        offset = Math.round(offset);
-        var new_pos = self.line_position + offset;
-        if (new_pos < 0) {
-            new_pos = 0;
-        } else if (new_pos >= self.last_no - 1) {
-            new_pos = self.last_no;
-        }
-        if (self.line_position != new_pos) {
-            self.activate(new_pos);
-        }
-        self._check_max_column(true);
-    };
-
-    self._check_max_column = function (moved_line) {
-        var max_co = self.columns[self.line_position].length;
-        if (self.col_position >= max_co) {
-            self.col_position = max_co;
-            if (moved_line)
-                self._update_cursor();
-        } else if (moved_line && self.col_position < self.saved_col_position) {
-            self.col_position = Math.min(max_co, self.saved_col_position);
-            self._update_cursor();
-        }
-    };
-
-    self.move_column = function(offset) {
-        self.col_position += offset;
-        if (self.col_position <= 0) {
-            self.col_position = 0;
-        }
-        self._check_max_column(false);
-        self._update_cursor();
-        self.saved_col_position = self.col_position;
-    };
-
-    self._update_cursor = function() {
-        $("#cursor").css("left", (self.col_position * self.single_element_width) + self.start_left);
+    self.update_cursor = function() {
+        $("#cursor").css("left", (self.grid.col_position *
+                                  self.single_element_width) + self.start_left);
         $("#cursor").toggle(true);
     };
 
+    self.insert_letter = function(letter) {
+        var line_mapping = self.grid.line_mapping[self.grid.line_position];
+        var elem = $("#" + (self.grid.line_position + 1));
+        var html = elem.html();
+        var letter = keys.key_mapping[letter];
+        html = insert_str(html, line_mapping[self.grid.col_position],
+                          letter);
+        self.grid.insert_letter(letter);
+        elem.html(html);
+        self.update_cursor();
+    };
+
     self.move_page = function(offset) {
-        self.move_line_relative(offset * $(window).height() /
-                                self.single_element_height);
+        // move up or down a page
+        self.grid.move_line_relative(offset * $(window).height() /
+                                     self.single_element_height);
     };
 
     self.activate = function(no) {
+        // activate a single line given number no
         var prev_elem = $(".active");
         if (prev_elem) {
             prev_elem.children().css("background-color", prev_style);
         var elem = $("#w-" + (no + 1));
         $("#cursor").css("top", elem.position().top);
         var prev_style = elem.children().css("background-color");
-        self.line_position = no;
         elem.children().css("background-color", "");
         elem.toggleClass('active');
         var pos = elem.position().top - document.body.scrollTop;
         }
     };
 
-    self.initialize = function(columns) {
-        self.columns = columns;
-        self.last_no = $(".wrapper").length;
+    self.initialize = function(sourcelines, line_mapping) {
+        self.grid = new GridManager(self, sourcelines, line_mapping);
         self.single_element_height = $("#w-1").height();
         $("#w-1").append('<span id="tmp">a</span>');
         self.single_element_width = $("#tmp").width();
 editor_status = new EditorStatus();
 
 keyset = {};
-keyset["UP"] = function () { editor_status.move_line_relative(-1); };
-keyset["DOWN"] = function () { editor_status.move_line_relative(+1); };
+keyset["UP"] = function () { editor_status.grid.move_line_relative(-1); };
+keyset["DOWN"] = function () { editor_status.grid.move_line_relative(+1); };
 keyset["PAGE_UP"] = function () { editor_status.move_page(-1); };
 keyset["PAGE_DOWN"] = function () { editor_status.move_page(+1); };
-keyset["LEFT"] = function () { editor_status.move_column(-1); };
-keyset["RIGHT"] = function () { editor_status.move_column(+1); };
+keyset["LEFT"] = function () { editor_status.grid.move_column(-1); };
+keyset["RIGHT"] = function () { editor_status.grid.move_column(+1); };
 
 $(document).ready(function ()
 {
     keys.bind_multiple(keyset);
-    load_file("x", function(columns) {
+    keys.bind_alphanumeric(editor_status.insert_letter);
+    load_file("x", function(data) {
         editor_status.activate(0);
-        editor_status.initialize(columns);
+        editor_status.initialize(data.codelines, data.line_mapping);
     });
 });
 

File codeviewer/js/files.js

 {
     $.get(basename + ".html", "", function (data) {
         $("#main-source").html(data).ready(function () {
-            $.getJSON(basename + ".json", "", when_loaded);
+            $.getJSON(basename + ".json?x=" + Math.random(), "", when_loaded);
         });
     });
 }

File codeviewer/js/libbasic.js

+
+function insert_str(orig, position, what)
+{
+    return (orig.substr(0, position) + what +
+            orig.substr(position, orig.length - position));
+}
+
+function insert_into_columns() {
+}
+
+function GridManager(editor, sourcelines, line_mapping) {
+    var self = this;
+    // properties of the file
+    self.line_mapping = line_mapping;
+    self.sourcelines = sourcelines;
+
+    // editor for hooks (and tests)
+    self.editor = editor;
+
+    // current position
+    self.line_position = 0;
+    self.col_position = 0;
+
+    // saved position for the case of short lines (so when we land at a long
+    // line, we can jump back to the correct column)
+    self.saved_col_position = 0;
+
+    self.move_line_relative = function(offset) {
+        // move up or down a line
+        offset = Math.round(offset);
+        var new_pos = self.line_position + offset;
+        if (new_pos < 0) {
+            new_pos = 0;
+        } else if (new_pos >= self.sourcelines.length - 1) {
+            new_pos = self.sourcelines.length - 1;
+        }
+        if (self.line_position != new_pos) {
+            self.editor.activate(new_pos);
+            self.line_position = new_pos;
+        }
+        self._check_max_column(true);
+    };
+
+    self.move_column = function(offset) {
+        // move left or right by offset
+        self.col_position += offset;
+        if (self.col_position <= 0) {
+            self.col_position = 0;
+        }
+        self._check_max_column(false);
+        self.editor.update_cursor();
+        self.saved_col_position = self.col_position;
+    };
+
+    self.insert_letter = function (letter) {
+        var line_mapping = self.line_mapping[self.line_position];
+        self.sourcelines[self.line_position] = insert_str(
+            self.sourcelines[self.line_position], self.col_position,
+            letter);
+        // update the line_mapping itself
+        var stop = line_mapping.length;
+        for (var i = stop; i > self.col_position; i--) {
+            line_mapping[i] = line_mapping[i - 1] + 1;
+        }
+        console.log(line_mapping);
+        self.col_position += 1;
+    };
+
+    // private helpers
+
+    self._check_max_column = function (moved_line) {
+        var max_co = self.sourcelines[self.line_position].length;
+        if (self.col_position >= max_co) {
+            self.col_position = max_co;
+            if (moved_line)
+                self.editor.update_cursor();
+        } else if (moved_line && self.col_position < self.saved_col_position) {
+            self.col_position = Math.min(max_co, self.saved_col_position);
+            self.editor.update_cursor();
+        }
+    };
+}

File codeviewer/js/libkeys.js

     self.CTRL      = 17;
     self.PAGE_UP   = 33;
     self.PAGE_DOWN = 34;
-    self.F = 70;
-    self.L = 76;
     self.ALT = 18;
-    // mooooooore
+    
+    // init letters
+    self.key_mapping = new Array(255);
+    var a = "a".charCodeAt(0);
+    var A = "A".charCodeAt(0);
+    for (var i = 65; i <= 90; i++) {
+        self[String.fromCharCode(i)] = i;
+        self.key_mapping[i] = String.fromCharCode(i + a - A);
+    }
 
     self.bindings = {};
     self.bindings_ctrl = {};
     self.bindings_alt = {};
 
     self.is_arrow = function(key) {
-        return key == self.DOWN || key == self.UP;
+        return key === self.DOWN || key === self.UP;
     };
 
     self.is_page_key = function(key) {
-        return key == self.PAGE_UP || key == self.PAGE_DOWN;
+        return key === self.PAGE_UP || key === self.PAGE_DOWN;
+    };
+
+    self.bind_alphanumeric = function(func, modifiers) {
+        for (var i = 65; i <= 90; i++) {
+            self.bind(i, func, modifiers);
+        }
     };
 
     self.ev_down = function(ev) {
+        e = ev;
         var mapping;
         if (self.ctrl_pressed) {
             mapping = self.bindings_ctrl;
         }
         var func = mapping[ev.keyCode];
         if (func) {
-            func();
+            func(ev.keyCode);
             ev.preventDefault();
         }
     };
 
     self.ev_up = function(ev) {
         // special keys only for now
-        if (ev.keyCode == self.CTRL) {
+        if (ev.keyCode === self.CTRL) {
             self.ctrl_pressed = false;
-        } else if (ev.keyCode == self.ALT) {
+        } else if (ev.keyCode === self.ALT) {
             self.alt_pressed = false;
         }
     };
     self.alt_pressed = false;
     
     self.bind = function(key, func, modifiers) {
-        if (modifiers == "ctrl") {
+        if (modifiers === "ctrl") {
             self.bindings_ctrl[key] = func;
-        } else if (modifiers == "alt") {
+        } else if (modifiers === "alt") {
             self.bindings_alt[key] = func;
         } else {
             self.bindings[key] = func;

File codeviewer/main.html

    <script type="text/javascript" src="js/jquery.scrollTo-1.4.2-min.js"></script>
    <script type="text/javascript" src="js/jquery.viewport.mini.js"></script>
    <script type="text/javascript" src="js/jquery.timer.js"></script>
+   <script type="text/javascript" src="js/libbasic.js"></script>
    <script type="text/javascript" src="js/files.js"></script>
    <script type="text/javascript" src="js/libkeys.js"></script>
    <script type="text/javascript" src="js/basic.js"></script>

File codeviewer/test/jstest_libbasic_supported.js

+
+OpenEnd.require("/js/jquery.min.js");
+OpenEnd.require("/js/libbasic.js");
+
+function MockEditor() {
+    var self = this;
+    self.update_cursor = function() {};
+    self.activate = function() {};
+}
+
+var basic_file = [
+    "line 1", "line 2", "long line line", "short"]
+
+Tests = {
+    test_insert_str: function() {
+        ais(insert_str("abcd", 2, "xyz"), "abxyzcd");
+    },
+    test_move_line_relative: function() {
+        var grid = new GridManager(new MockEditor(), basic_file, []);
+        grid.move_line_relative(1);
+        ais(grid.line_position, 1);
+    }
+};

File codeviewer/x.json

-["# based on a Java version:", "#  Based on original version written in BCPL by Dr Martin Richards", "#  in 1981 at Cambridge University Computer Laboratory, England", "#  and a C++ version derived from a Smalltalk version written by", "#  L Peter Deutsch.", "#  Java version:  Copyright (C) 1995 Sun Microsystems, Inc.", "#  Translation from C++, Mario Wolczko", "#  Outer loop added by Alex Jacoby", "", "# Task IDs", "I_IDLE = 1", "I_WORK = 2", "I_HANDLERA = 3", "I_HANDLERB = 4", "I_DEVA = 5", "I_DEVB = 6", "", "# Packet types", "K_DEV = 1000", "K_WORK = 1001", "", "# Packet", "", "BUFSIZE = 4", "", "BUFSIZE_RANGE = range(BUFSIZE)", "", "class Packet(object):", "    def __init__(self,l,i,k):", "        self.link = l", "        self.ident = i", "        self.kind = k", "        self.datum = 0", "        self.data = [0] * BUFSIZE", "", "    def append_to(self,lst):", "        self.link = None", "        if lst is None:", "            return self", "        else:", "            p = lst", "            next = p.link", "            while next is not None:", "                p = next", "                next = p.link", "            p.link = self", "            return lst", "", "# Task Records", "", "class TaskRec(object):", "    pass", "", "class DeviceTaskRec(TaskRec):", "    def __init__(self):", "        self.pending = None", "", "class IdleTaskRec(TaskRec):", "    def __init__(self):", "        self.control = 1", "        self.count = 10000", "", "class HandlerTaskRec(TaskRec):", "    def __init__(self):", "        self.work_in = None", "        self.device_in = None", "", "    def workInAdd(self,p):", "        self.work_in = p.append_to(self.work_in)", "        return self.work_in", "", "    def deviceInAdd(self,p):", "        self.device_in = p.append_to(self.device_in)", "        return self.device_in", "", "class WorkerTaskRec(TaskRec):", "    def __init__(self):", "        self.destination = I_HANDLERA", "        self.count = 0", "# Task", "", "class TaskState(object):", "    def __init__(self):", "        self.packet_pending = True", "        self.task_waiting = False", "        self.task_holding = False", "", "    def packetPending(self):", "        self.packet_pending = True", "        self.task_waiting = False", "        self.task_holding = False", "        return self", "", "    def waiting(self):", "        self.packet_pending = False", "        self.task_waiting = True", "        self.task_holding = False", "        return self", "", "    def running(self):", "        self.packet_pending = False", "        self.task_waiting = False", "        self.task_holding = False", "        return self", "        ", "    def waitingWithPacket(self):", "        self.packet_pending = True", "        self.task_waiting = True", "        self.task_holding = False", "        return self", "        ", "    def isPacketPending(self):", "        return self.packet_pending", "", "    def isTaskWaiting(self):", "        return self.task_waiting", "", "    def isTaskHolding(self):", "        return self.task_holding", "", "    def isTaskHoldingOrWaiting(self):", "        return self.task_holding or (not self.packet_pending and self.task_waiting)", "", "    def isWaitingWithPacket(self):", "        return self.packet_pending and self.task_waiting and not self.task_holding", "", "", "", "", "", "tracing = False", "layout = 0", "", "def trace(a):", "    global layout", "    layout -= 1", "    if layout <= 0:", "        print", "        layout = 50", "    print a,", "", "", "TASKTABSIZE = 10", "", "class TaskWorkArea(object):", "    def __init__(self):", "        self.taskTab = [None] * TASKTABSIZE", "", "        self.taskList = None", "", "        self.holdCount = 0", "        self.qpktCount = 0", "", "taskWorkArea = TaskWorkArea()", "", "class Task(TaskState):", "", "", "    def __init__(self,i,p,w,initialState,r):", "        self.link = taskWorkArea.taskList", "        self.ident = i", "        self.priority = p", "        self.input = w", "", "        self.packet_pending = initialState.isPacketPending()", "        self.task_waiting = initialState.isTaskWaiting()", "        self.task_holding = initialState.isTaskHolding()", "", "        self.handle = r", "", "        taskWorkArea.taskList = self", "        taskWorkArea.taskTab[i] = self", "", "    def fn(self,pkt,r):", "        raise NotImplementedError", "", "", "    def addPacket(self,p,old):", "        if self.input is None:", "            self.input = p", "            self.packet_pending = True", "            if self.priority > old.priority:", "                return self", "        else:", "            p.append_to(self.input)", "        return old", "", "", "    def runTask(self):", "        if self.isWaitingWithPacket():", "            msg = self.input", "            self.input = msg.link", "            if self.input is None:", "                self.running()", "            else:", "                self.packetPending()", "        else:", "            msg = None", "", "        return self.fn(msg,self.handle)", "", "", "    def waitTask(self):", "        self.task_waiting = True", "        return self", "", "", "    def hold(self):", "        taskWorkArea.holdCount += 1", "        self.task_holding = True", "        return self.link", "", "", "    def release(self,i):", "        t = self.findtcb(i)", "        t.task_holding = False", "        if t.priority > self.priority:", "            return t", "        else:", "            return self", "", "", "    def qpkt(self,pkt):", "        t = self.findtcb(pkt.ident)", "        taskWorkArea.qpktCount += 1", "        pkt.link = None", "        pkt.ident = self.ident", "        return t.addPacket(pkt,self)", "", "", "    def findtcb(self,id):", "        t = taskWorkArea.taskTab[id]", "        if t is None:", "            raise Exception(\"Bad task id %d\" % id)", "        return t", "            ", "", "# DeviceTask", "", "", "class DeviceTask(Task):", "    def __init__(self,i,p,w,s,r):", "        Task.__init__(self,i,p,w,s,r)", "", "    def fn(self,pkt,r):", "        d = r", "        assert isinstance(d, DeviceTaskRec)", "        if pkt is None:", "            pkt = d.pending", "            if pkt is None:", "                return self.waitTask()", "            else:", "                d.pending = None", "                return self.qpkt(pkt)", "        else:", "            d.pending = pkt", "            if tracing: trace(pkt.datum)", "            return self.hold()", "", "", "", "class HandlerTask(Task):", "    def __init__(self,i,p,w,s,r):", "        Task.__init__(self,i,p,w,s,r)", "", "    def fn(self,pkt,r):", "        h = r", "        assert isinstance(h, HandlerTaskRec)", "        if pkt is not None:", "            if pkt.kind == K_WORK:", "                h.workInAdd(pkt)", "            else:", "                h.deviceInAdd(pkt)", "        work = h.work_in", "        if work is None:", "            return self.waitTask()", "        count = work.datum", "        if count >= BUFSIZE:", "            h.work_in = work.link", "            return self.qpkt(work)", "", "        dev = h.device_in", "        if dev is None:", "            return self.waitTask()", "", "        h.device_in = dev.link", "        dev.datum = work.data[count]", "        work.datum = count + 1", "        return self.qpkt(dev)", "", "# IdleTask", "", "", "class IdleTask(Task):", "    def __init__(self,i,p,w,s,r):", "        Task.__init__(self,i,0,None,s,r)", "", "    def fn(self,pkt,r):", "        i = r", "        assert isinstance(i, IdleTaskRec)", "        i.count -= 1", "        if i.count == 0:", "            return self.hold()", "        elif i.control & 1 == 0:", "            i.control /= 2", "            return self.release(I_DEVA)", "        else:", "            i.control = i.control/2 ^ 0xd008", "            return self.release(I_DEVB)", "            ", "", "# WorkTask", "", "", "A = ord('A')", "", "class WorkTask(Task):", "    def __init__(self,i,p,w,s,r):", "        Task.__init__(self,i,p,w,s,r)", "", "    def fn(self,pkt,r):", "        w = r", "        assert isinstance(w, WorkerTaskRec)", "        if pkt is None:", "            return self.waitTask()", "", "        if w.destination == I_HANDLERA:", "            dest = I_HANDLERB", "        else:", "            dest = I_HANDLERA", "", "        w.destination = dest", "        pkt.ident = dest", "        pkt.datum = 0", "", "        for i in BUFSIZE_RANGE: # xrange(BUFSIZE)", "            w.count += 1", "            if w.count > 26:", "                w.count = 1", "            pkt.data[i] = A + w.count - 1", "", "        return self.qpkt(pkt)", "", "import time", "", "def schedule():", "    t = taskWorkArea.taskList", "    while t is not None:", "        pkt = None", "", "        if tracing:", "            print \"tcb =\",t.ident", "", "        if t.isTaskHoldingOrWaiting():", "            t = t.link", "        else:", "            if tracing: trace(chr(ord(\"0\")+t.ident))", "            t = t.runTask()", "", "class Richards(object):", "", "    def run(self, iterations):", "        for i in xrange(iterations):", "            taskWorkArea.holdCount = 0", "            taskWorkArea.qpktCount = 0", "", "            IdleTask(I_IDLE, 1, 10000, TaskState().running(), IdleTaskRec())", "", "            wkq = Packet(None, 0, K_WORK)", "            wkq = Packet(wkq , 0, K_WORK)", "            WorkTask(I_WORK, 1000, wkq, TaskState().waitingWithPacket(), WorkerTaskRec())", "", "            wkq = Packet(None, I_DEVA, K_DEV)", "            wkq = Packet(wkq , I_DEVA, K_DEV)", "            wkq = Packet(wkq , I_DEVA, K_DEV)", "            HandlerTask(I_HANDLERA, 2000, wkq, TaskState().waitingWithPacket(), HandlerTaskRec())", "", "            wkq = Packet(None, I_DEVB, K_DEV)", "            wkq = Packet(wkq , I_DEVB, K_DEV)", "            wkq = Packet(wkq , I_DEVB, K_DEV)", "            HandlerTask(I_HANDLERB, 3000, wkq, TaskState().waitingWithPacket(), HandlerTaskRec())", "", "            wkq = None;", "            DeviceTask(I_DEVA, 4000, wkq, TaskState().waiting(), DeviceTaskRec());", "            DeviceTask(I_DEVB, 5000, wkq, TaskState().waiting(), DeviceTaskRec());", "            ", "            schedule()", "", "            if taskWorkArea.holdCount == 9297 and taskWorkArea.qpktCount == 23246:", "                pass", "            else:", "                return False", "", "        return True", "", "def entry_point(iterations):", "    r = Richards()", "    startTime = time.time()", "    result = r.run(iterations)", "    endTime = time.time()", "    return result, startTime, endTime", "", "def main(entry_point = entry_point, iterations = 10):", "    print \"Richards benchmark (Python) starting... [%r]\" % entry_point", "    result, startTime, endTime = entry_point(iterations)", "    if not result:", "        print \"Incorrect results!\"", "        return -1", "    print \"finished.\"", "    total_s = endTime - startTime", "    print \"Total time for %d iterations: %.2f secs\" %(iterations,total_s)", "    print \"Average time per iteration: %.2f ms\" %(total_s*1000/iterations)", "    return 42", "", "if __name__ == '__main__':", "    import sys", "    if len(sys.argv) >= 2:", "        main(iterations = int(sys.argv[1]))", "    else:", "        main()"]
+{"codelines": ["# based on a Java version:", "#  Based on original version written in BCPL by Dr Martin Richards", "#  in 1981 at Cambridge University Computer Laboratory, England", "#  and a C++ version derived from a Smalltalk version written by", "#  L Peter Deutsch.", "#  Java version:  Copyright (C) 1995 Sun Microsystems, Inc.", "#  Translation from C++, Mario Wolczko", "#  Outer loop added by Alex Jacoby", "", "# Task IDs", "I_IDLE = 1", "I_WORK = 2", "I_HANDLERA = 3", "I_HANDLERB = 4", "I_DEVA = 5", "I_DEVB = 6", "", "# Packet types", "K_DEV = 1000", "K_WORK = 1001", "", "# Packet", "", "BUFSIZE = 4", "", "BUFSIZE_RANGE = range(BUFSIZE)", "", "class Packet(object):", "    def __init__(self,l,i,k):", "        self.link = l", "        self.ident = i", "        self.kind = k", "        self.datum = 0", "        self.data = [0] * BUFSIZE", "", "    def append_to(self,lst):", "        self.link = None", "        if lst is None:", "            return self", "        else:", "            p = lst", "            next = p.link", "            while next is not None:", "                p = next", "                next = p.link", "            p.link = self", "            return lst", "", "# Task Records", "", "class TaskRec(object):", "    pass", "", "class DeviceTaskRec(TaskRec):", "    def __init__(self):", "        self.pending = None", "", "class IdleTaskRec(TaskRec):", "    def __init__(self):", "        self.control = 1", "        self.count = 10000", "", "class HandlerTaskRec(TaskRec):", "    def __init__(self):", "        self.work_in = None", "        self.device_in = None", "", "    def workInAdd(self,p):", "        self.work_in = p.append_to(self.work_in)", "        return self.work_in", "", "    def deviceInAdd(self,p):", "        self.device_in = p.append_to(self.device_in)", "        return self.device_in", "", "class WorkerTaskRec(TaskRec):", "    def __init__(self):", "        self.destination = I_HANDLERA", "        self.count = 0", "# Task", "", "class TaskState(object):", "    def __init__(self):", "        self.packet_pending = True", "        self.task_waiting = False", "        self.task_holding = False", "", "    def packetPending(self):", "        self.packet_pending = True", "        self.task_waiting = False", "        self.task_holding = False", "        return self", "", "    def waiting(self):", "        self.packet_pending = False", "        self.task_waiting = True", "        self.task_holding = False", "        return self", "", "    def running(self):", "        self.packet_pending = False", "        self.task_waiting = False", "        self.task_holding = False", "        return self", "        ", "    def waitingWithPacket(self):", "        self.packet_pending = True", "        self.task_waiting = True", "        self.task_holding = False", "        return self", "        ", "    def isPacketPending(self):", "        return self.packet_pending", "", "    def isTaskWaiting(self):", "        return self.task_waiting", "", "    def isTaskHolding(self):", "        return self.task_holding", "", "    def isTaskHoldingOrWaiting(self):", "        return self.task_holding or (not self.packet_pending and self.task_waiting)", "", "    def isWaitingWithPacket(self):", "        return self.packet_pending and self.task_waiting and not self.task_holding", "", "", "", "", "", "tracing = False", "layout = 0", "", "def trace(a):", "    global layout", "    layout -= 1", "    if layout <= 0:", "        print", "        layout = 50", "    print a,", "", "", "TASKTABSIZE = 10", "", "class TaskWorkArea(object):", "    def __init__(self):", "        self.taskTab = [None] * TASKTABSIZE", "", "        self.taskList = None", "", "        self.holdCount = 0", "        self.qpktCount = 0", "", "taskWorkArea = TaskWorkArea()", "", "class Task(TaskState):", "", "", "    def __init__(self,i,p,w,initialState,r):", "        self.link = taskWorkArea.taskList", "        self.ident = i", "        self.priority = p", "        self.input = w", "", "        self.packet_pending = initialState.isPacketPending()", "        self.task_waiting = initialState.isTaskWaiting()", "        self.task_holding = initialState.isTaskHolding()", "", "        self.handle = r", "", "        taskWorkArea.taskList = self", "        taskWorkArea.taskTab[i] = self", "", "    def fn(self,pkt,r):", "        raise NotImplementedError", "", "", "    def addPacket(self,p,old):", "        if self.input is None:", "            self.input = p", "            self.packet_pending = True", "            if self.priority > old.priority:", "                return self", "        else:", "            p.append_to(self.input)", "        return old", "", "", "    def runTask(self):", "        if self.isWaitingWithPacket():", "            msg = self.input", "            self.input = msg.link", "            if self.input is None:", "                self.running()", "            else:", "                self.packetPending()", "        else:", "            msg = None", "", "        return self.fn(msg,self.handle)", "", "", "    def waitTask(self):", "        self.task_waiting = True", "        return self", "", "", "    def hold(self):", "        taskWorkArea.holdCount += 1", "        self.task_holding = True", "        return self.link", "", "", "    def release(self,i):", "        t = self.findtcb(i)", "        t.task_holding = False", "        if t.priority > self.priority:", "            return t", "        else:", "            return self", "", "", "    def qpkt(self,pkt):", "        t = self.findtcb(pkt.ident)", "        taskWorkArea.qpktCount += 1", "        pkt.link = None", "        pkt.ident = self.ident", "        return t.addPacket(pkt,self)", "", "", "    def findtcb(self,id):", "        t = taskWorkArea.taskTab[id]", "        if t is None:", "            raise Exception(\"Bad task id %d\" % id)", "        return t", "            ", "", "# DeviceTask", "", "", "class DeviceTask(Task):", "    def __init__(self,i,p,w,s,r):", "        Task.__init__(self,i,p,w,s,r)", "", "    def fn(self,pkt,r):", "        d = r", "        assert isinstance(d, DeviceTaskRec)", "        if pkt is None:", "            pkt = d.pending", "            if pkt is None:", "                return self.waitTask()", "            else:", "                d.pending = None", "                return self.qpkt(pkt)", "        else:", "            d.pending = pkt", "            if tracing: trace(pkt.datum)", "            return self.hold()", "", "", "", "class HandlerTask(Task):", "    def __init__(self,i,p,w,s,r):", "        Task.__init__(self,i,p,w,s,r)", "", "    def fn(self,pkt,r):", "        h = r", "        assert isinstance(h, HandlerTaskRec)", "        if pkt is not None:", "            if pkt.kind == K_WORK:", "                h.workInAdd(pkt)", "            else:", "                h.deviceInAdd(pkt)", "        work = h.work_in", "        if work is None:", "            return self.waitTask()", "        count = work.datum", "        if count >= BUFSIZE:", "            h.work_in = work.link", "            return self.qpkt(work)", "", "        dev = h.device_in", "        if dev is None:", "            return self.waitTask()", "", "        h.device_in = dev.link", "        dev.datum = work.data[count]", "        work.datum = count + 1", "        return self.qpkt(dev)", "", "# IdleTask", "", "", "class IdleTask(Task):", "    def __init__(self,i,p,w,s,r):", "        Task.__init__(self,i,0,None,s,r)", "", "    def fn(self,pkt,r):", "        i = r", "        assert isinstance(i, IdleTaskRec)", "        i.count -= 1", "        if i.count == 0:", "            return self.hold()", "        elif i.control & 1 == 0:", "            i.control /= 2", "            return self.release(I_DEVA)", "        else:", "            i.control = i.control/2 ^ 0xd008", "            return self.release(I_DEVB)", "            ", "", "# WorkTask", "", "", "A = ord('A')", "", "class WorkTask(Task):", "    def __init__(self,i,p,w,s,r):", "        Task.__init__(self,i,p,w,s,r)", "", "    def fn(self,pkt,r):", "        w = r", "        assert isinstance(w, WorkerTaskRec)", "        if pkt is None:", "            return self.waitTask()", "", "        if w.destination == I_HANDLERA:", "            dest = I_HANDLERB", "        else:", "            dest = I_HANDLERA", "", "        w.destination = dest", "        pkt.ident = dest", "        pkt.datum = 0", "", "        for i in BUFSIZE_RANGE: # xrange(BUFSIZE)", "            w.count += 1", "            if w.count > 26:", "                w.count = 1", "            pkt.data[i] = A + w.count - 1", "", "        return self.qpkt(pkt)", "", "import time", "", "def schedule():", "    t = taskWorkArea.taskList", "    while t is not None:", "        pkt = None", "", "        if tracing:", "            print \"tcb =\",t.ident", "", "        if t.isTaskHoldingOrWaiting():", "            t = t.link", "        else:", "            if tracing: trace(chr(ord(\"0\")+t.ident))", "            t = t.runTask()", "", "class Richards(object):", "", "    def run(self, iterations):", "        for i in xrange(iterations):", "            taskWorkArea.holdCount = 0", "            taskWorkArea.qpktCount = 0", "", "            IdleTask(I_IDLE, 1, 10000, TaskState().running(), IdleTaskRec())", "", "            wkq = Packet(None, 0, K_WORK)", "            wkq = Packet(wkq , 0, K_WORK)", "            WorkTask(I_WORK, 1000, wkq, TaskState().waitingWithPacket(), WorkerTaskRec())", "", "            wkq = Packet(None, I_DEVA, K_DEV)", "            wkq = Packet(wkq , I_DEVA, K_DEV)", "            wkq = Packet(wkq , I_DEVA, K_DEV)", "            HandlerTask(I_HANDLERA, 2000, wkq, TaskState().waitingWithPacket(), HandlerTaskRec())", "", "            wkq = Packet(None, I_DEVB, K_DEV)", "            wkq = Packet(wkq , I_DEVB, K_DEV)", "            wkq = Packet(wkq , I_DEVB, K_DEV)", "            HandlerTask(I_HANDLERB, 3000, wkq, TaskState().waitingWithPacket(), HandlerTaskRec())", "", "            wkq = None;", "            DeviceTask(I_DEVA, 4000, wkq, TaskState().waiting(), DeviceTaskRec());", "            DeviceTask(I_DEVB, 5000, wkq, TaskState().waiting(), DeviceTaskRec());", "            ", "            schedule()", "", "            if taskWorkArea.holdCount == 9297 and taskWorkArea.qpktCount == 23246:", "                pass", "            else:", "                return False", "", "        return True", "", "def entry_point(iterations):", "    r = Richards()", "    startTime = time.time()", "    result = r.run(iterations)", "    endTime = time.time()", "    return result, startTime, endTime", "", "def main(entry_point = entry_point, iterations = 10):", "    print \"Richards benchmark (Python) starting... [%r]\" % entry_point", "    result, startTime, endTime = entry_point(iterations)", "    if not result:", "        print \"Incorrect results!\"", "        return -1", "    print \"finished.\"", "    total_s = endTime - startTime", "    print \"Total time for %d iterations: %.2f secs\" %(iterations,total_s)", "    print \"Average time per iteration: %.2f ms\" %(total_s*1000/iterations)", "    return 42", "", "if __name__ == '__main__':", "    import sys", "    if len(sys.argv) >= 2:", "        main(iterations = int(sys.argv[1]))", "    else:", "        main()"], "line_mapping": [[16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42], [16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82], [16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79], [16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80], [16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35], [16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75], [16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54], [16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50], [0], [16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26], [16, 17, 18, 19, 20, 21, 29, 46, 54, 72, 73], [16, 17, 18, 19, 20, 21, 29, 46, 54, 72, 73], [16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 33, 50, 58, 76, 77], [16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 33, 50, 58, 76, 77], [16, 17, 18, 19, 20, 21, 29, 46, 54, 72, 73], [16, 17, 18, 19, 20, 21, 29, 46, 54, 72, 73], [0], [16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30], [16, 17, 18, 19, 20, 28, 45, 53, 71, 72, 73, 74, 75], [16, 17, 18, 19, 20, 21, 29, 46, 54, 72, 73, 74, 75, 76], [0], [16, 17, 18, 19, 20, 21, 22, 23, 24], [0], [16, 17, 18, 19, 20, 21, 22, 30, 47, 55, 73, 74], [0], [16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 36, 53, 61, 79, 80, 81, 82, 83, 107, 131, 132, 133, 134, 135, 136, 137, 161, 162], [0], [16, 17, 18, 19, 20, 28, 46, 47, 48, 49, 50, 51, 75, 100, 101, 102, 103, 104, 105, 129, 130, 131], [0, 1, 2, 3, 20, 21, 22, 30, 48, 49, 50, 51, 52, 53, 54, 55, 79, 104, 105, 106, 107, 131, 155, 179, 203, 227, 251, 275, 276, 277], [0, 1, 2, 3, 4, 5, 6, 7, 25, 26, 27, 28, 52, 76, 77, 78, 79, 87, 104, 112, 129, 130], [0, 1, 2, 3, 4, 5, 6, 7, 25, 26, 27, 28, 52, 76, 77, 78, 79, 80, 88, 105, 113, 130, 131], [0, 1, 2, 3, 4, 5, 6, 7, 25, 26, 27, 28, 52, 76, 77, 78, 79, 87, 104, 112, 129, 130], [0, 1, 2, 3, 4, 5, 6, 7, 25, 26, 27, 28, 52, 76, 77, 78, 79, 80, 88, 105, 113, 131, 132], [0, 1, 2, 3, 4, 5, 6, 7, 25, 26, 27, 28, 52, 76, 77, 78, 79, 87, 104, 112, 129, 154, 178, 186, 203, 211, 228, 229, 230, 231, 232, 233, 234, 235], [0], [0, 1, 2, 3, 20, 21, 22, 30, 48, 49, 50, 51, 52, 53, 54, 55, 56, 80, 105, 106, 107, 108, 132, 156, 157, 158, 182, 183, 184], [0, 1, 2, 3, 4, 5, 6, 7, 25, 26, 27, 28, 52, 76, 77, 78, 79, 87, 104, 112, 130, 131, 132, 133, 134], [0, 1, 2, 3, 4, 5, 6, 7, 24, 25, 33, 50, 51, 52, 60, 78, 79, 87, 105, 106, 107, 108, 132, 133], [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 28, 29, 30, 31, 32, 33, 41, 59, 60, 61, 62, 63], [0, 1, 2, 3, 4, 5, 6, 7, 24, 25, 26, 27, 51, 52], [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 28, 36, 53, 61, 78, 79, 80, 81], [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 29, 30, 31, 32, 40, 57, 65, 82, 106, 130, 131, 132, 133, 134], [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 28, 29, 30, 31, 32, 40, 58, 59, 60, 61, 69, 87, 88, 96, 114, 115, 116, 124, 142, 143, 144, 145, 169, 170], [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 32, 40, 57, 65, 83, 84, 85, 86, 87], [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 33, 34, 35, 36, 44, 61, 69, 86, 110, 134, 135, 136, 137, 138], [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 28, 52, 76, 77, 78, 79, 87, 104, 112, 130, 131, 132, 133, 134], [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 28, 29, 30, 31, 32, 33, 41, 58, 59, 60, 61], [0], [16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30], [0], [16, 17, 18, 19, 20, 28, 46, 47, 48, 49, 50, 51, 52, 76, 101, 102, 103, 104, 105, 106, 130, 131, 132], [0, 1, 2, 3, 20, 21, 22, 23, 24], [0], [16, 17, 18, 19, 20, 28, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 82, 106, 107, 108, 109, 110, 111, 112, 136, 137, 138], [0, 1, 2, 3, 20, 21, 22, 30, 48, 49, 50, 51, 52, 53, 54, 55, 79, 104, 105, 106, 107, 131, 132, 133], [0, 1, 2, 3, 4, 5, 6, 7, 25, 26, 27, 28, 52, 76, 77, 78, 79, 80, 81, 82, 90, 107, 115, 133, 134, 135, 136, 137], [0], [16, 17, 18, 19, 20, 28, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 80, 104, 105, 106, 107, 108, 109, 110, 134, 135, 136], [0, 1, 2, 3, 20, 21, 22, 30, 48, 49, 50, 51, 52, 53, 54, 55, 79, 104, 105, 106, 107, 131, 132, 133], [0, 1, 2, 3, 4, 5, 6, 7, 25, 26, 27, 28, 52, 76, 77, 78, 79, 80, 81, 82, 90, 107, 115, 133, 134], [0, 1, 2, 3, 4, 5, 6, 7, 25, 26, 27, 28, 52, 76, 77, 78, 79, 80, 88, 105, 113, 131, 132, 133, 134, 135, 136], [0], [16, 17, 18, 19, 20, 28, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 83, 107, 108, 109, 110, 111, 112, 113, 137, 138, 139], [0, 1, 2, 3, 20, 21, 22, 30, 48, 49, 50, 51, 52, 53, 54, 55, 79, 104, 105, 106, 107, 131, 132, 133], [0, 1, 2, 3, 4, 5, 6, 7, 25, 26, 27, 28, 52, 76, 77, 78, 79, 80, 81, 82, 90, 107, 115, 133, 134, 135, 136, 137], [0, 1, 2, 3, 4, 5, 6, 7, 25, 26, 27, 28, 52, 76, 77, 78, 79, 80, 81, 82, 83, 84, 92, 109, 117, 135, 136, 137, 138, 139], [0], [0, 1, 2, 3, 20, 21, 22, 30, 48, 49, 50, 51, 52, 53, 54, 55, 56, 80, 105, 106, 107, 108, 132, 156, 180, 181, 182], [0, 1, 2, 3, 4, 5, 6, 7, 25, 26, 27, 28, 52, 76, 77, 78, 79, 80, 81, 82, 90, 107, 115, 132, 156, 180, 181, 182, 183, 184, 185, 186, 187, 188, 212, 237, 238, 239, 240, 264, 288, 289, 290, 291, 292, 293, 294, 318, 319], [0, 1, 2, 3, 4, 5, 6, 7, 24, 25, 26, 27, 28, 29, 37, 55, 56, 57, 58, 82, 106, 107, 108, 109, 110, 111, 112, 113], [0], [0, 1, 2, 3, 20, 21, 22, 30, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 82, 107, 108, 109, 110, 134, 158, 182, 183, 184], [0, 1, 2, 3, 4, 5, 6, 7, 25, 26, 27, 28, 52, 76, 77, 78, 79, 80, 81, 82, 83, 84, 92, 109, 117, 134, 158, 182, 183, 184, 185, 186, 187, 188, 189, 190, 214, 239, 240, 241, 242, 266, 290, 291, 292, 293, 294, 295, 296, 297, 298, 322, 323], [0, 1, 2, 3, 4, 5, 6, 7, 24, 25, 26, 27, 28, 29, 37, 55, 56, 57, 58, 82, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115], [0], [16, 17, 18, 19, 20, 28, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 82, 106, 107, 108, 109, 110, 111, 112, 136, 137, 138], [0, 1, 2, 3, 20, 21, 22, 30, 48, 49, 50, 51, 52, 53, 54, 55, 79, 104, 105, 106, 107, 131, 132, 133], [0, 1, 2, 3, 4, 5, 6, 7, 25, 26, 27, 28, 52, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 94, 111, 119, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146], [0, 1, 2, 3, 4, 5, 6, 7, 25, 26, 27, 28, 52, 76, 77, 78, 79, 80, 88, 105, 113, 131, 132], [16, 17, 18, 19, 20, 21, 22], [0], [16, 17, 18, 19, 20, 28, 46, 47, 48, 49, 50, 51, 52, 53, 54, 78, 103, 104, 105, 106, 107, 108, 132, 133, 134], [0, 1, 2, 3, 20, 21, 22, 30, 48, 49, 50, 51, 52, 53, 54, 55, 79, 104, 105, 106, 107, 131, 132, 133], [0, 1, 2, 3, 4, 5, 6, 7, 25, 26, 27, 28, 52, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 97, 114, 122, 140, 141, 142, 143, 144], [0, 1, 2, 3, 4, 5, 6, 7, 25, 26, 27, 28, 52, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 95, 112, 120, 138, 139, 140, 141, 142, 143], [0, 1, 2, 3, 4, 5, 6, 7, 25, 26, 27, 28, 52, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 95, 112, 120, 138, 139, 140, 141, 142, 143], [0], [0, 1, 2, 3, 20, 21, 22, 30, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 84, 109, 110, 111, 112, 136, 137, 138], [0, 1, 2, 3, 4, 5, 6, 7, 25, 26, 27, 28, 52, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 97, 114, 122, 140, 141, 142, 143, 144], [0, 1, 2, 3, 4, 5, 6, 7, 25, 26, 27, 28, 52, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 95, 112, 120, 138, 139, 140, 141, 142, 143], [0, 1, 2, 3, 4, 5, 6, 7, 25, 26, 27, 28, 52, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 95, 112, 120, 138, 139, 140, 141, 142, 143], [0, 1, 2, 3, 4, 5, 6, 7, 24, 25, 26, 27, 28, 29, 37, 55, 56, 57, 58, 59], [0], [0, 1, 2, 3, 20, 21, 22, 30, 48, 49, 50, 51, 52, 53, 54, 78, 103, 104, 105, 106, 130, 131, 132], [0, 1, 2, 3, 4, 5, 6, 7, 25, 26, 27, 28, 52, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 97, 114, 122, 140, 141, 142, 143, 144, 145], [0, 1, 2, 3, 4, 5, 6, 7, 25, 26, 27, 28, 52, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 95, 112, 120, 138, 139, 140, 141, 142], [0, 1, 2, 3, 4, 5, 6, 7, 25, 26, 27, 28, 52, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 95, 112, 120, 138, 139, 140, 141, 142, 143], [0, 1, 2, 3, 4, 5, 6, 7, 24, 25, 26, 27, 28, 29, 37, 55, 56, 57, 58, 59], [0], [0, 1, 2, 3, 20, 21, 22, 30, 48, 49, 50, 51, 52, 53, 54, 78, 103, 104, 105, 106, 130, 131, 132], [0, 1, 2, 3, 4, 5, 6, 7, 25, 26, 27, 28, 52, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 97, 114, 122, 140, 141, 142, 143, 144, 145], [0, 1, 2, 3, 4, 5, 6, 7, 25, 26, 27, 28, 52, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 95, 112, 120, 138, 139, 140, 141, 142, 143], [0, 1, 2, 3, 4, 5, 6, 7, 25, 26, 27, 28, 52, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 95, 112, 120, 138, 139, 140, 141, 142, 143], [0, 1, 2, 3, 4, 5, 6, 7, 24, 25, 26, 27, 28, 29, 37, 55, 56, 57, 58, 59], [0, 1, 2, 3, 4, 5, 6, 7, 8], [0, 1, 2, 3, 20, 21, 22, 30, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 88, 113, 114, 115, 116, 140, 141, 142], [0, 1, 2, 3, 4, 5, 6, 7, 25, 26, 27, 28, 52, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 97, 114, 122, 140, 141, 142, 143, 144], [0, 1, 2, 3, 4, 5, 6, 7, 25, 26, 27, 28, 52, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 95, 112, 120, 138, 139, 140, 141, 142], [0, 1, 2, 3, 4, 5, 6, 7, 25, 26, 27, 28, 52, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 95, 112, 120, 138, 139, 140, 141, 142, 143], [0, 1, 2, 3, 4, 5, 6, 7, 24, 25, 26, 27, 28, 29, 37, 55, 56, 57, 58, 59], [0, 1, 2, 3, 4, 5, 6, 7, 8], [0, 1, 2, 3, 20, 21, 22, 30, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 86, 111, 112, 113, 114, 138, 139, 140], [0, 1, 2, 3, 4, 5, 6, 7, 24, 25, 26, 27, 28, 29, 37, 55, 56, 57, 58, 82, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120], [0], [0, 1, 2, 3, 20, 21, 22, 30, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 84, 109, 110, 111, 112, 136, 137, 138], [0, 1, 2, 3, 4, 5, 6, 7, 24, 25, 26, 27, 28, 29, 37, 55, 56, 57, 58, 82, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118], [0], [0, 1, 2, 3, 20, 21, 22, 30, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 84, 109, 110, 111, 112, 136, 137, 138], [0, 1, 2, 3, 4, 5, 6, 7, 24, 25, 26, 27, 28, 29, 37, 55, 56, 57, 58, 82, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118], [0], [0, 1, 2, 3, 20, 21, 22, 30, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 93, 118, 119, 120, 121, 145, 146, 147], [0, 1, 2, 3, 4, 5, 6, 7, 24, 25, 26, 27, 28, 29, 37, 55, 56, 57, 58, 82, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 125, 143, 144, 152, 169, 194, 195, 196, 204, 222, 223, 224, 225, 249, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 294, 312, 313, 314, 322, 340, 341, 342, 343, 367, 391, 392, 393, 394, 395, 396, 397, 398, 399, 400, 401, 402, 426, 427], [0], [0, 1, 2, 3, 20, 21, 22, 30, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 90, 115, 116, 117, 118, 142, 143, 144], [0, 1, 2, 3, 4, 5, 6, 7, 24, 25, 26, 27, 28, 29, 37, 55, 56, 57, 58, 82, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 127, 145, 146, 147, 155, 173, 174, 175, 176, 200, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 243, 261, 262, 263, 271, 289, 290, 291, 299, 317, 318, 319, 320, 344, 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, 379, 380], [0], [0], [0], [0], [0], [16, 17, 18, 19, 20, 21, 22, 30, 47, 55, 73, 74, 75, 76, 77, 78], [16, 17, 18, 19, 20, 21, 29, 46, 54, 72, 73], [0], [16, 17, 18, 26, 44, 45, 46, 47, 48, 72, 96, 120, 121, 122], [0, 1, 2, 3, 20, 21, 22, 23, 24, 25, 33, 50, 51, 52, 53, 54, 55, 56], [0, 1, 2, 3, 20, 21, 22, 23, 24, 25, 33, 50, 51, 59, 77, 78], [0, 1, 2, 3, 20, 21, 29, 46, 47, 48, 49, 50, 51, 59, 79, 80, 88, 106, 130, 131], [0, 1, 2, 3, 4, 5, 6, 7, 24, 25, 26, 27, 28, 29], [0, 1, 2, 3, 4, 5, 6, 7, 24, 25, 26, 27, 28, 29, 37, 54, 62, 80, 81, 82], [0, 1, 2, 3, 20, 21, 22, 23, 24, 32, 49, 73, 74], [0], [0], [16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 34, 51, 59, 77, 78, 79], [0], [16, 17, 18, 19, 20, 28, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 81, 106, 107, 108, 109, 110, 111, 135, 136, 137], [0, 1, 2, 3, 20, 21, 22, 30, 48, 49, 50, 51, 52, 53, 54, 55, 79, 104, 105, 106, 107, 131, 132, 133], [0, 1, 2, 3, 4, 5, 6, 7, 25, 26, 27, 28, 52, 76, 77, 78, 79, 80, 81, 82, 90, 107, 115, 132, 157, 158, 159, 160, 184, 192, 209, 217, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245], [0], [0, 1, 2, 3, 4, 5, 6, 7, 25, 26, 27, 28, 52, 76, 77, 78, 79, 80, 81, 82, 83, 91, 108, 116, 134, 135, 136, 137, 138], [0], [0, 1, 2, 3, 4, 5, 6, 7, 25, 26, 27, 28, 52, 76, 77, 78, 79, 80, 81, 82, 83, 84, 92, 109, 117, 135, 136], [0, 1, 2, 3, 4, 5, 6, 7, 25, 26, 27, 28, 52, 76, 77, 78, 79, 80, 81, 82, 83, 84, 92, 109, 117, 135, 136], [0], [16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 35, 52, 60, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 112, 113, 114], [0], [16, 17, 18, 19, 20, 28, 46, 47, 48, 49, 73, 97, 98, 99, 100, 101, 102, 103, 104, 105, 129, 130, 131], [0], [0], [0, 1, 2, 3, 20, 21, 22, 30, 48, 49, 50, 51, 52, 53, 54, 55, 79, 104, 105, 106, 107, 131, 155, 179, 203, 227, 251, 275, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 334, 358, 382, 383, 384], [0, 1, 2, 3, 4, 5, 6, 7, 25, 26, 27, 28, 52, 76, 77, 78, 79, 87, 104, 112, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 164, 188, 189, 190, 191, 192, 193, 194, 195, 196], [0, 1, 2, 3, 4, 5, 6, 7, 25, 26, 27, 28, 52, 76, 77, 78, 79, 80, 88, 105, 113, 130, 131], [0, 1, 2, 3, 4, 5, 6, 7, 25, 26, 27, 28, 52, 76, 77, 78, 79, 80, 81, 82, 83, 91, 108, 116, 133, 134], [0, 1, 2, 3, 4, 5, 6, 7, 25, 26, 27, 28, 52, 76, 77, 78, 79, 80, 88, 105, 113, 130, 131], [0], [0, 1, 2, 3, 4, 5, 6, 7, 25, 26, 27, 28, 52, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 97, 114, 122, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 174, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 236, 237, 238], [0, 1, 2, 3, 4, 5, 6, 7, 25, 26, 27, 28, 52, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 95, 112, 120, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 172, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 232, 233, 234], [0, 1, 2, 3, 4, 5, 6, 7, 25, 26, 27, 28, 52, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 95, 112, 120, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 172, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 232, 233, 234], [0], [0, 1, 2, 3, 4, 5, 6, 7, 25, 26, 27, 28, 52, 76, 77, 78, 79, 80, 81, 89, 106, 114, 131, 132], [0], [0, 1, 2, 3, 4, 5, 6, 7, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 59, 83, 84, 85, 86, 87, 88, 89, 90, 98, 115, 123, 141, 142, 143, 144, 145], [0, 1, 2, 3, 4, 5, 6, 7, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 59, 83, 84, 85, 86, 87, 88, 89, 113, 137, 161, 169, 186, 194, 212, 213, 214, 215, 216], [0], [0, 1, 2, 3, 20, 21, 22, 30, 48, 49, 73, 98, 99, 100, 101, 125, 149, 150, 151, 175, 199, 223, 224, 225], [0, 1, 2, 3, 4, 5, 6, 7, 24, 25, 26, 27, 28, 36, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73], [0], [0], [0, 1, 2, 3, 20, 21, 22, 30, 48, 49, 50, 51, 52, 53, 54, 55, 56, 80, 105, 106, 107, 108, 132, 156, 180, 204, 205, 206, 230, 231, 232], [0, 1, 2, 3, 4, 5, 6, 7, 24, 25, 33, 51, 52, 53, 54, 78, 102, 103, 104, 105, 106, 114, 132, 133, 141, 159, 160, 161, 162, 186, 187], [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 29, 30, 31, 32, 56, 80, 81, 82, 83, 84, 92, 109, 117, 134, 135], [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 29, 30, 31, 32, 56, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 101, 118, 126, 144, 145, 146, 147, 148], [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 28, 29, 37, 55, 56, 57, 58, 82, 106, 107, 108, 109, 110, 111, 112, 113, 121, 141, 149, 166, 167, 168, 192, 216, 217, 218, 219, 220, 221, 222, 223, 247, 248], [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 32, 33, 34, 35, 36, 37, 45, 63, 64, 65, 66, 67], [0, 1, 2, 3, 4, 5, 6, 7, 24, 25, 26, 27, 51, 52], [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 28, 52, 76, 77, 78, 79, 80, 81, 82, 83, 84, 108, 133, 134, 135, 136, 160, 184, 185, 186, 187, 188, 212, 213], [0, 1, 2, 3, 4, 5, 6, 7, 24, 25, 26, 27, 28, 29, 37, 54, 55, 56, 57], [0], [0], [0, 1, 2, 3, 20, 21, 22, 30, 48, 49, 50, 51, 52, 53, 54, 78, 103, 104, 105, 106, 130, 131, 132], [0, 1, 2, 3, 4, 5, 6, 7, 24, 25, 33, 51, 52, 53, 54, 78, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 144, 145, 146, 147], [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 28, 29, 30, 38, 55, 63, 81, 82, 83, 84, 108, 132, 133, 134, 135, 136, 137], [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 29, 30, 31, 32, 56, 80, 81, 82, 83, 84, 92, 109, 117, 134, 135, 136, 160, 184, 185, 186, 187, 188], [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 28, 29, 37, 55, 56, 57, 58, 82, 106, 107, 108, 109, 110, 118, 136, 137, 145, 163, 164, 165, 166, 190, 191], [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 33, 34, 35, 36, 60, 84, 85, 86, 87, 88, 89, 90, 114, 115, 116], [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 28, 29, 30, 31, 55, 56], [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 33, 34, 35, 36, 60, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 120, 121, 122], [0, 1, 2, 3, 4, 5, 6, 7, 24, 25, 26, 27, 51, 52], [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 28, 29, 30, 38, 55, 63, 81, 82, 83, 84, 85], [0], [0, 1, 2, 3, 4, 5, 6, 7, 24, 25, 26, 27, 28, 29, 37, 55, 56, 57, 58, 82, 106, 107, 131, 155, 156, 157, 181, 206, 207, 208, 209, 233, 257, 258, 259, 260, 261, 262, 286, 287], [0], [0], [0, 1, 2, 3, 20, 21, 22, 30, 48, 49, 50, 51, 52, 53, 54, 55, 79, 104, 105, 106, 107, 131, 132, 133], [0, 1, 2, 3, 4, 5, 6, 7, 25, 26, 27, 28, 52, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 95, 112, 120, 138, 139, 140, 141, 142], [0, 1, 2, 3, 4, 5, 6, 7, 24, 25, 26, 27, 28, 29, 37, 55, 56, 57, 58, 59], [0], [0], [0, 1, 2, 3, 20, 21, 22, 30, 48, 49, 50, 51, 75, 100, 101, 102, 103, 127, 128, 129], [0, 1, 2, 3, 4, 5, 6, 7, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 59, 83, 84, 85, 86, 87, 88, 89, 90, 91, 99, 116, 117, 125, 143, 144], [0, 1, 2, 3, 4, 5, 6, 7, 25, 26, 27, 28, 52, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 95, 112, 120, 138, 139, 140, 141, 142], [0, 1, 2, 3, 4, 5, 6, 7, 24, 25, 26, 27, 28, 29, 37, 55, 56, 57, 58, 82, 106, 107, 108, 109, 110], [0], [0], [0, 1, 2, 3, 20, 21, 22, 30, 48, 49, 50, 51, 52, 53, 54, 78, 103, 104, 105, 106, 130, 154, 178, 179, 180], [0, 1, 2, 3, 4, 5, 6, 7, 24, 32, 49, 57, 75, 76, 77, 78, 102, 126, 127, 128, 129, 130, 131, 132, 156, 180, 204, 205], [0, 1, 2, 3, 4, 5, 6, 7, 24, 48, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 91, 108, 116, 134, 135, 136, 137, 138, 139], [0, 1, 2, 3, 4, 5, 6, 7, 24, 25, 33, 50, 74, 98, 99, 100, 101, 102, 103, 104, 105, 113, 133, 141, 159, 160, 161, 162, 186, 210, 211, 212, 213, 214, 215, 216, 217, 241, 242], [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 28, 29, 30, 31, 32, 33, 41, 58, 59], [0, 1, 2, 3, 4, 5, 6, 7, 24, 25, 26, 27, 51, 52], [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 28, 29, 30, 31, 32, 33, 41, 59, 60, 61, 62, 63], [0], [0], [0, 1, 2, 3, 20, 21, 22, 30, 48, 49, 50, 51, 75, 100, 101, 102, 103, 127, 151, 152, 153, 177, 178, 179], [0, 1, 2, 3, 4, 5, 6, 7, 24, 32, 49, 57, 75, 76, 77, 78, 102, 126, 127, 128, 129, 130, 131, 132, 156, 180, 181, 182, 206, 230, 231, 232, 233, 234, 258, 259], [0, 1, 2, 3, 4, 5, 6, 7, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 59, 83, 84, 85, 86, 87, 88, 89, 90, 91, 99, 116, 117, 125, 143, 144], [0, 1, 2, 3, 4, 5, 6, 7, 24, 25, 26, 50, 74, 75, 76, 77, 85, 102, 110, 128, 129, 130, 131, 132], [0, 1, 2, 3, 4, 5, 6, 7, 24, 25, 26, 50, 74, 75, 76, 77, 78, 86, 103, 111, 129, 130, 131, 132, 156, 180, 181, 182, 183, 184, 185], [0, 1, 2, 3, 4, 5, 6, 7, 24, 25, 26, 27, 28, 29, 37, 54, 78, 102, 103, 104, 105, 106, 107, 108, 109, 110, 134, 158, 159, 160, 184, 209, 210, 211, 212, 236, 237], [0], [0], [0, 1, 2, 3, 20, 21, 22, 30, 48, 49, 50, 51, 52, 53, 54, 78, 103, 104, 105, 106, 130, 155, 156, 180, 181, 182], [0, 1, 2, 3, 4, 5, 6, 7, 24, 32, 49, 57, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 109, 133, 134, 135, 136, 137, 138, 139, 163, 188, 189, 213, 214], [0, 1, 2, 3, 4, 5, 6, 7, 24, 25, 33, 50, 58, 76, 77, 85, 103, 104, 105, 106, 130, 131], [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 28, 29, 30, 31, 32, 40, 58, 59, 60, 61, 62, 63, 64, 65, 66, 90, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 156, 157, 186, 194, 211, 219, 237, 238, 262, 263], [0, 1, 2, 3, 4, 5, 6, 7, 24, 25, 26, 27, 28, 29, 37, 54, 55], [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12], [0], [16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28], [0], [0], [16, 17, 18, 19, 20, 28, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 79, 103, 104, 105, 106, 130, 131, 132], [0, 1, 2, 3, 20, 21, 22, 30, 48, 49, 50, 51, 52, 53, 54, 55, 79, 104, 105, 106, 107, 131, 155, 179, 203, 227, 251, 275, 299, 323, 347, 371, 372, 373], [0, 1, 2, 3, 4, 5, 6, 7, 24, 25, 26, 27, 51, 75, 76, 77, 78, 79, 80, 81, 82, 106, 131, 132, 133, 134, 158, 182, 206, 230, 254, 278, 302, 326, 350, 374, 398, 399], [0], [0, 1, 2, 3, 20, 21, 22, 30, 48, 49, 73, 98, 99, 100, 101, 125, 149, 150, 151, 175, 199, 223, 224, 225], [0, 1, 2, 3, 4, 5, 6, 7, 24, 32, 49, 57, 74, 75], [0, 1, 2, 3, 4, 5, 6, 7, 24, 25, 26, 27, 28, 29, 37, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 88, 112, 136, 144, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 197, 198], [0, 1, 2, 3, 4, 5, 6, 7, 24, 25, 33, 50, 51, 52, 60, 78, 79, 87, 105, 106, 107, 108, 132, 133], [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 28, 29, 30, 38, 55, 63, 80, 104, 128, 129, 130, 131, 132, 133, 134, 135], [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 28, 29, 37, 54, 55, 56, 64, 82, 83, 91, 109, 110, 111, 112, 136, 137], [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 32, 33, 34, 35, 36, 37, 45, 63, 64, 65, 66, 90, 114, 115, 116, 117, 118, 119, 120, 121, 145, 146, 147], [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 28, 29, 30, 31, 55, 56], [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 32, 56, 80, 81, 82, 83, 84, 85, 86, 94, 111, 119, 137, 138, 139, 140, 141], [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 32, 33, 34, 35, 36, 37, 45, 63, 64, 65, 66, 90, 114, 115, 116, 117, 141, 165, 166, 167, 191, 192], [0, 1, 2, 3, 4, 5, 6, 7, 24, 25, 26, 27, 51, 52], [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 28, 52, 76, 77, 78, 79, 80, 81, 82, 90, 107, 115, 132, 133, 134, 135], [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 28, 29, 37, 54, 55, 56, 57, 58, 59, 60, 84, 92, 109, 110, 111, 112, 113, 137, 161, 162, 163, 187, 211, 212, 213, 214, 215, 239, 240], [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 28, 29, 30, 31, 32, 33, 41, 59, 60, 61, 62, 86, 110, 111, 112, 113, 137, 138, 139], [0], [0], [0], [16, 17, 18, 19, 20, 28, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 80, 104, 105, 106, 107, 131, 132, 133], [0, 1, 2, 3, 20, 21, 22, 30, 48, 49, 50, 51, 52, 53, 54, 55, 79, 104, 105, 106, 107, 131, 155, 179, 203, 227, 251, 275, 299, 323, 347, 371, 372, 373], [0, 1, 2, 3, 4, 5, 6, 7, 24, 25, 26, 27, 51, 75, 76, 77, 78, 79, 80, 81, 82, 106, 131, 132, 133, 134, 158, 182, 206, 230, 254, 278, 302, 326, 350, 374, 398, 399], [0], [0, 1, 2, 3, 20, 21, 22, 30, 48, 49, 73, 98, 99, 100, 101, 125, 149, 150, 151, 175, 199, 223, 224, 225], [0, 1, 2, 3, 4, 5, 6, 7, 24, 32, 49, 57, 74, 75], [0, 1, 2, 3, 4, 5, 6, 7, 24, 25, 26, 27, 28, 29, 37, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 88, 112, 136, 144, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 198, 199], [0, 1, 2, 3, 4, 5, 6, 7, 24, 25, 33, 50, 51, 52, 60, 78, 79, 87, 105, 106, 107, 115, 133, 134, 135, 136, 160, 161], [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 28, 29, 37, 54, 55, 56, 80, 104, 105, 106, 107, 115, 132, 133, 141, 158, 159, 160, 161, 162, 163, 187, 188], [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 32, 56, 80, 81, 82, 83, 84, 85, 86, 87, 88, 112, 136, 137, 138, 162, 163], [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 28, 29, 30, 31, 55, 56], [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 32, 56, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 114, 138, 139, 140, 164, 165], [0, 1, 2, 3, 4, 5, 6, 7, 24, 25, 26, 27, 35, 52, 60, 77, 101, 125, 126, 127, 128, 129, 130, 131, 132], [0, 1, 2, 3, 4, 5, 6, 7, 24, 25, 33, 50, 51, 52, 53, 61, 79, 80, 88, 106, 107, 108, 109, 133, 134], [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 28, 29, 30, 31, 32, 33, 41, 59, 60, 61, 62, 86, 110, 111, 112, 113, 114, 115, 116, 117, 141, 142, 143], [0, 1, 2, 3, 4, 5, 6, 7, 24, 25, 26, 27, 28, 36, 53, 61, 78, 79, 80, 81, 105, 129, 130, 131, 132, 133, 134], [0, 1, 2, 3, 4, 5, 6, 7, 24, 25, 33, 50, 51, 52, 53, 54, 62, 82, 83, 91, 108, 109, 110, 111, 112, 113, 114, 138, 139], [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 28, 52, 76, 77, 78, 79, 80, 81, 82, 90, 107, 115, 132, 133, 134, 135, 159, 183, 184, 185, 186, 187], [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 28, 29, 30, 31, 32, 33, 41, 59, 60, 61, 62, 86, 110, 111, 112, 113, 137, 161, 162, 163, 164, 188, 189], [0], [0, 1, 2, 3, 4, 5, 6, 7, 24, 25, 26, 34, 51, 59, 76, 100, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133], [0, 1, 2, 3, 4, 5, 6, 7, 24, 25, 33, 50, 51, 52, 60, 78, 79, 87, 105, 106, 107, 108, 132, 133], [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 28, 29, 30, 31, 32, 33, 41, 59, 60, 61, 62, 86, 110, 111, 112, 113, 114, 115, 116, 117, 141, 142, 143], [0], [0, 1, 2, 3, 4, 5, 6, 7, 24, 48, 72, 73, 74, 75, 76, 77, 78, 79, 80, 88, 105, 113, 130, 131, 132, 156, 180, 181, 182, 183, 184], [0, 1, 2, 3, 4, 5, 6, 7, 24, 25, 26, 50, 74, 75, 76, 77, 78, 86, 103, 111, 128, 129, 130, 131, 155, 179, 180, 181, 182, 206, 230, 231, 232, 233, 234, 258, 259], [0, 1, 2, 3, 4, 5, 6, 7, 24, 25, 26, 27, 51, 75, 76, 77, 78, 79, 87, 104, 112, 129, 130, 131, 132, 133, 141, 158, 166, 184, 185], [0, 1, 2, 3, 4, 5, 6, 7, 24, 25, 26, 27, 28, 29, 37, 55, 56, 57, 58, 82, 106, 107, 108, 109, 133, 157, 158, 159, 183, 184], [0], [16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26], [0], [0], [16, 17, 18, 19, 20, 28, 46, 47, 48, 49, 50, 51, 52, 53, 77, 101, 102, 103, 104, 128, 129, 130], [0, 1, 2, 3, 20, 21, 22, 30, 48, 49, 50, 51, 52, 53, 54, 55, 79, 104, 105, 106, 107, 131, 155, 179, 203, 227, 251, 275, 299, 323, 347, 371, 372, 373], [0, 1, 2, 3, 4, 5, 6, 7, 24, 25, 26, 27, 51, 75, 76, 77, 78, 79, 80, 81, 82, 106, 131, 132, 133, 134, 158, 182, 206, 231, 255, 280, 281, 282, 283, 307, 331, 355, 379, 403, 404], [0], [0, 1, 2, 3, 20, 21, 22, 30, 48, 49, 73, 98, 99, 100, 101, 125, 149, 150, 151, 175, 199, 223, 224, 225], [0, 1, 2, 3, 4, 5, 6, 7, 24, 32, 49, 57, 74, 75], [0, 1, 2, 3, 4, 5, 6, 7, 24, 25, 26, 27, 28, 29, 37, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 88, 112, 136, 144, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 195, 196], [0, 1, 2, 3, 4, 5, 6, 7, 24, 48, 72, 73, 74, 75, 76, 84, 101, 102, 110, 128, 129], [0, 1, 2, 3, 4, 5, 6, 7, 24, 25, 33, 50, 74, 98, 99, 100, 101, 102, 110, 127, 128, 136, 154, 178, 179], [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 28, 29, 30, 31, 32, 33, 41, 59, 60, 61, 62, 86, 110, 111, 112, 113, 137, 138, 139], [0, 1, 2, 3, 4, 5, 6, 7, 24, 25, 26, 27, 35, 52, 76, 100, 101, 102, 103, 104, 105, 106, 114, 135, 143, 161, 169, 186, 187, 195, 213, 237, 238], [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 28, 52, 76, 77, 78, 79, 80, 81, 82, 90, 107, 108, 116, 134, 135], [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 28, 29, 30, 31, 32, 33, 41, 59, 60, 61, 62, 86, 110, 111, 112, 113, 114, 115, 116, 140, 164, 165, 166, 167, 168, 169, 193, 194], [0, 1, 2, 3, 4, 5, 6, 7, 24, 25, 26, 27, 51, 52], [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 28, 52, 76, 77, 78, 79, 80, 81, 82, 90, 107, 115, 132, 156, 180, 181, 182, 183, 184, 185, 186, 210, 235, 243, 260, 268, 286, 287, 288, 289, 290, 291, 292], [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 28, 29, 30, 31, 32, 33, 41, 59, 60, 61, 62, 86, 110, 111, 112, 113, 114, 115, 116, 140, 164, 165, 166, 167, 168, 169, 193, 194], [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12], [0], [16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26], [0], [0], [16, 24, 41, 49, 67, 68, 69, 93, 121, 122, 127, 151, 152], [0], [16, 17, 18, 19, 20, 28, 46, 47, 48, 49, 50, 51, 52, 53, 77, 101, 102, 103, 104, 128, 129, 130], [0, 1, 2, 3, 20, 21, 22, 30, 48, 49, 50, 51, 52, 53, 54, 55, 79, 104, 105, 106, 107, 131, 155, 179, 203, 227, 251, 275, 299, 323, 347, 371, 372, 373], [0, 1, 2, 3, 4, 5, 6, 7, 24, 25, 26, 27, 51, 75, 76, 77, 78, 79, 80, 81, 82, 106, 131, 132, 133, 134, 158, 182, 206, 230, 254, 278, 302, 326, 350, 374, 398, 399], [0], [0, 1, 2, 3, 20, 21, 22, 30, 48, 49, 73, 98, 99, 100, 101, 125, 149, 150, 151, 175, 199, 223, 224, 225], [0, 1, 2, 3, 4, 5, 6, 7, 24, 32, 49, 57, 74, 75], [0, 1, 2, 3, 4, 5, 6, 7, 24, 25, 26, 27, 28, 29, 37, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 88, 112, 136, 144, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 197, 198], [0, 1, 2, 3, 4, 5, 6, 7, 24, 25, 33, 50, 51, 52, 60, 78, 79, 87, 105, 106, 107, 108, 132, 133], [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 28, 29, 30, 31, 32, 33, 41, 59, 60, 61, 62, 86, 110, 111, 112, 113, 114, 115, 116, 117, 141, 142, 143], [0], [0, 1, 2, 3, 4, 5, 6, 7, 24, 25, 33, 50, 74, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 116, 133, 134, 142, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 192, 193], [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 28, 29, 30, 31, 39, 56, 64, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91], [0, 1, 2, 3, 4, 5, 6, 7, 24, 25, 26, 27, 51, 52], [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 28, 29, 30, 31, 39, 56, 64, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91], [0], [0, 1, 2, 3, 4, 5, 6, 7, 24, 48, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 90, 107, 115, 132, 133, 134, 135, 136], [0, 1, 2, 3, 4, 5, 6, 7, 24, 25, 26, 50, 74, 75, 76, 77, 78, 86, 103, 111, 128, 129, 130, 131, 132], [0, 1, 2, 3, 4, 5, 6, 7, 24, 25, 26, 50, 74, 75, 76, 77, 78, 86, 103, 111, 129, 130], [0], [0, 1, 2, 3, 4, 5, 6, 7, 24, 25, 26, 34, 51, 59, 77, 78, 86, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 139, 147, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181], [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 28, 52, 76, 77, 78, 79, 80, 88, 105, 106, 114, 132, 133], [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 28, 29, 37, 54, 78, 102, 103, 104, 105, 106, 114, 134, 142, 160, 161, 185, 186], [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 32, 56, 80, 81, 82, 83, 84, 92, 109, 117, 135, 136], [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 28, 29, 30, 54, 78, 79, 80, 81, 105, 129, 153, 161, 178, 186, 203, 211, 228, 236, 253, 277, 301, 302, 303, 304, 305, 313, 330, 338, 356, 357], [0], [0, 1, 2, 3, 4, 5, 6, 7, 24, 25, 26, 27, 28, 29, 37, 55, 56, 57, 58, 82, 106, 107, 108, 109, 133, 157, 158, 159, 183, 184], [0], [17, 18, 19, 20, 21, 22, 30, 48, 49, 50, 51, 52], [0], [16, 17, 18, 26, 44, 45, 46, 47, 48, 49, 50, 51, 75, 76, 77, 78], [0, 1, 2, 3, 20, 28, 45, 53, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 105, 129, 130, 131, 132, 133, 134, 135, 136, 137], [0, 1, 2, 3, 20, 21, 22, 23, 24, 32, 49, 57, 75, 76, 84, 102, 103, 104, 112, 130, 131, 132, 133, 157, 158], [0, 1, 2, 3, 4, 5, 6, 7, 24, 25, 26, 34, 51, 59, 77, 78, 79, 80, 81], [0], [0, 1, 2, 3, 4, 5, 6, 7, 24, 25, 33, 50, 51, 52, 53, 54, 55, 56, 80, 81], [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 28, 29, 30, 31, 32, 40, 62, 63, 64, 65, 66, 67, 73, 97, 121, 145, 169, 170, 171, 172, 173, 174], [0], [0, 1, 2, 3, 4, 5, 6, 7, 24, 25, 33, 50, 74, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 143, 144, 145, 146], [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 28, 36, 53, 61, 78, 102, 126, 127, 128, 129, 130], [0, 1, 2, 3, 4, 5, 6, 7, 24, 25, 26, 27, 51, 52], [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 28, 29, 37, 54, 55, 56, 57, 58, 59, 60, 84, 92, 109, 110, 111, 112, 113, 137, 162, 163, 164, 188, 213, 214, 215, 239, 268, 269, 275, 299, 323, 347, 371, 395, 396, 397, 398, 399, 423, 424, 425], [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 28, 36, 53, 61, 78, 102, 126, 127, 128, 129, 130, 131, 132, 156, 157, 158], [0], [16, 17, 18, 19, 20, 28, 46, 47, 48, 49, 50, 51, 52, 53, 77, 102, 103, 104, 105, 106, 107, 131, 132, 133], [0], [0, 1, 2, 3, 20, 21, 22, 30, 48, 49, 50, 74, 99, 100, 101, 102, 126, 134, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 184, 185, 186], [0, 1, 2, 3, 4, 5, 6, 7, 24, 25, 26, 34, 51, 59, 77, 78, 86, 104, 105, 106, 107, 108, 109, 133, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 190, 191, 192], [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 63, 87, 88, 89, 90, 91, 92, 93, 94, 95, 103, 120, 128, 146, 147], [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 63, 87, 88, 89, 90, 91, 92, 93, 94, 95, 103, 120, 128, 146, 147], [0], [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 28, 29, 30, 31, 32, 33, 34, 35, 59, 83, 84, 85, 86, 87, 88, 112, 120, 138, 162, 170, 188, 189, 190, 191, 192, 216, 224, 241, 242, 243, 244, 245, 246, 247, 248, 249, 273, 274, 298, 322, 323, 324, 325, 326, 327, 328, 352, 353, 354, 362, 379, 380, 381, 382, 383, 384, 385, 386, 387, 388, 389, 413, 414, 415, 416], [0], [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 28, 29, 30, 38, 55, 63, 80, 81, 82, 83, 84, 85, 109, 134, 135, 136, 137, 161, 169, 187, 211, 219, 236, 237, 238, 239, 240, 241, 265, 266], [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 28, 29, 30, 38, 55, 63, 80, 81, 82, 83, 84, 85, 109, 133, 134, 135, 143, 160, 168, 186, 210, 218, 235, 236, 237, 238, 239, 240, 264, 265], [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 28, 29, 30, 31, 32, 33, 34, 35, 59, 83, 84, 85, 86, 87, 88, 112, 120, 138, 139, 140, 141, 165, 173, 190, 191, 192, 216, 224, 241, 242, 243, 244, 245, 246, 247, 248, 249, 273, 274, 298, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 362, 363, 364, 372, 389, 390, 391, 392, 393, 394, 395, 396, 397, 398, 399, 400, 401, 425, 426, 427, 428], [0], [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 28, 29, 30, 38, 55, 63, 80, 81, 82, 83, 84, 85, 109, 134, 135, 136, 137, 161, 169, 186, 187, 188, 189, 190, 191, 215, 223, 240, 241, 242, 243, 244, 268, 269], [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 28, 29, 30, 38, 55, 63, 80, 81, 82, 83, 84, 85, 109, 133, 134, 135, 143, 160, 168, 185, 186, 187, 188, 189, 190, 214, 222, 239, 240, 241, 242, 243, 267, 268], [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 28, 29, 30, 38, 55, 63, 80, 81, 82, 83, 84, 85, 109, 133, 134, 135, 143, 160, 168, 185, 186, 187, 188, 189, 190, 214, 222, 239, 240, 241, 242, 243, 267, 268], [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 62, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 119, 127, 145, 146, 147, 148, 172, 180, 197, 198, 199, 223, 231, 248, 249, 250, 251, 252, 253, 254, 255, 256, 280, 281, 305, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 369, 370, 371, 379, 396, 397, 398, 399, 400, 401, 402, 403, 404, 405, 406, 407, 408, 409, 433, 434, 435, 436], [0], [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 28, 29, 30, 38, 55, 63, 80, 81, 82, 83, 84, 85, 109, 134, 135, 136, 137, 161, 169, 186, 187, 188, 189, 190, 191, 215, 223, 240, 241, 242, 243, 244, 268, 269], [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 28, 29, 30, 38, 55, 63, 80, 81, 82, 83, 84, 85, 109, 133, 134, 135, 143, 160, 168, 185, 186, 187, 188, 189, 190, 214, 222, 239, 240, 241, 242, 243, 267, 268], [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 28, 29, 30, 38, 55, 63, 80, 81, 82, 83, 84, 85, 109, 133, 134, 135, 143, 160, 168, 185, 186, 187, 188, 189, 190, 214, 222, 239, 240, 241, 242, 243, 267, 268], [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 62, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 119, 127, 145, 146, 147, 148, 172, 180, 197, 198, 199, 223, 231, 248, 249, 250, 251, 252, 253, 254, 255, 256, 280, 281, 305, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 369, 370, 371, 379, 396, 397, 398, 399, 400, 401, 402, 403, 404, 405, 406, 407, 408, 409, 433, 434, 435, 436], [0], [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 28, 29, 30, 38, 55, 63, 81, 82, 83, 84, 108, 109], [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 61, 85, 86, 87, 88, 89, 90, 114, 122, 140, 141, 142, 143, 167, 175, 192, 193, 194, 218, 226, 243, 244, 245, 246, 247, 248, 249, 250, 251, 275, 276, 300, 324, 325, 326, 327, 328, 329, 330, 354, 355, 356, 364, 381, 382, 383, 384, 385, 386, 387, 388, 389, 390, 391, 392, 393, 417, 418, 419, 420, 421], [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 61, 85, 86, 87, 88, 89, 90, 114, 122, 140, 141, 142, 143, 167, 175, 192, 193, 194, 218, 226, 243, 244, 245, 246, 247, 248, 249, 250, 251, 275, 276, 300, 324, 325, 326, 327, 328, 329, 330, 354, 355, 356, 364, 381, 382, 383, 384, 385, 386, 387, 388, 389, 390, 391, 392, 393, 417, 418, 419, 420, 421], [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12], [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 28, 29, 30, 31, 32, 33, 34, 35, 59, 60, 61], [0], [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 28, 29, 37, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 89, 113, 114, 115, 116, 117, 118, 119, 120, 121, 129, 146, 147, 155, 173, 174, 175, 176, 184, 202, 203, 204, 212, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 264, 288, 289, 290, 291, 292, 293, 294, 295, 296, 304, 321, 322, 330, 348, 349, 350, 351, 352, 376, 377], [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 32, 33, 34, 35, 36], [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 28, 29, 30, 31, 55, 56], [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 32, 33, 34, 35, 36, 37, 45, 63, 64, 65, 66, 67, 68], [0], [0, 1, 2, 3, 4, 5, 6, 7, 24, 25, 26, 27, 28, 29, 37, 55, 56, 57, 58, 59], [0], [16, 17, 18, 26, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 78, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 135, 136, 137], [0, 1, 2, 3, 20, 28, 45, 53, 70, 71, 72, 73, 74, 75, 76, 77, 101, 102, 103], [0, 1, 2, 3, 20, 21, 22, 23, 24, 25, 26, 27, 28, 36, 53, 61, 78, 79, 80, 81, 105, 129, 130, 131, 132, 156, 157, 158], [0, 1, 2, 3, 20, 21, 22, 23, 24, 25, 33, 50, 58, 75, 99, 123, 124, 125, 149, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 206, 207], [0, 1, 2, 3, 20, 21, 22, 23, 24, 25, 26, 34, 51, 59, 76, 77, 78, 79, 103, 127, 128, 129, 130, 154, 155, 156], [0, 1, 2, 3, 20, 21, 22, 23, 24, 25, 33, 50, 51, 52, 53, 54, 55, 79, 87, 104, 105, 106, 107, 108, 109, 110, 111, 112, 136, 144, 161, 162, 163, 164, 165, 166, 167, 168], [0], [16, 17, 18, 26, 44, 45, 46, 47, 71, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 113, 130, 138, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 189, 197, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 231, 248, 256, 274, 275, 299, 300, 301], [0, 1, 2, 3, 20, 21, 22, 23, 24, 32, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 120, 121, 145, 151, 159, 176, 184, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212], [0, 1, 2, 3, 20, 21, 22, 23, 24, 25, 49, 57, 74, 75, 76, 77, 78, 79, 80, 81, 82, 106, 114, 131, 132, 133, 134, 135, 136, 137, 145, 162, 170, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 221, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 278, 279], [0, 1, 2, 3, 20, 21, 29, 47, 48, 49, 57, 74, 75, 76, 77, 78, 79, 103, 104], [0, 1, 2, 3, 4, 5, 6, 7, 24, 25, 26, 27, 28, 36, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 82, 83], [0, 1, 2, 3, 4, 5, 6, 7, 24, 25, 26, 27, 28, 29, 37, 54, 79, 80], [0, 1, 2, 3, 20, 21, 22, 23, 24, 32, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 69, 70], [0, 1, 2, 3, 20, 21, 22, 23, 24, 25, 26, 34, 51, 59, 76, 77, 78, 79, 80, 81, 82, 90, 107, 115, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141], [0, 1, 2, 3, 20, 21, 22, 23, 24, 32, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 94, 95, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 156, 157, 158, 159, 183, 184, 185, 186, 187, 193, 201, 218, 242, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 299, 323, 324, 325, 326, 327, 328, 329, 353, 354], [0, 1, 2, 3, 20, 21, 22, 23, 24, 32, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 107, 108, 109, 110, 134, 135, 136, 142, 150, 167, 191, 215, 216, 217, 218, 219, 220, 221, 245, 270, 271, 272, 273, 297, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 354, 355], [0, 1, 2, 3, 20, 21, 22, 23, 24, 25, 33, 51, 52, 53], [0], [16, 17, 25, 42, 43, 44, 45, 46, 47, 48, 49, 57, 74, 75, 83, 104, 105, 106, 107, 108, 109, 110, 111, 112, 117, 141, 142], [0, 1, 2, 3, 21, 22, 23, 24, 25, 26, 34, 52, 53, 54, 55], [0, 1, 2, 3, 20, 21, 29, 47, 48, 49, 73, 97, 98, 99, 123, 147, 148, 149, 150, 174, 182, 202, 203, 211, 229, 253, 254], [0, 1, 2, 3, 4, 5, 6, 7, 24, 25, 26, 27, 51, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 92, 109, 117, 135, 136, 137, 161, 185, 186, 187, 211, 235, 236, 237, 238, 262, 287, 311, 312, 313, 314], [0, 1, 2, 3, 20, 21, 22, 23, 47, 48], [0, 1, 2, 3, 4, 5, 6, 7, 24, 25, 26, 27, 51, 52, 53]]}

File codeviewer/xdemo.py

 from pygments import highlight
 from pygments.lexers import PythonLexer
-from pygments.formatters import HtmlFormatter
+from pygments.formatters.html import HtmlFormatter, _escape_html_table
 from jinja2 import Template
 import json
 
     def __init__(self, codelines):
         self.codelines = codelines
         HtmlFormatter.__init__(self)
-    
+        self.mapping = [[]]
+
+    def _consider_html(self, p):
+        if len(p):
+            self.mapping[-1].append((False, len(p)))
+        return p
+
+    def _consider_txt(self, p):
+        if len(p):
+            if p.find("&") != -1:
+                assert p.endswith(";")
+                self.mapping[-1].append((False, len(p) - 1))
+                self.mapping[-1].append((True, 1))
+            else:
+                self.mapping[-1].append((True, len(p)))
+        return p
+
+    def _reset_line(self):
+        self.mapping.append([])
+
+    def _format_lines(self, tokensource):
+        """
+        Just format the tokens, without any wrapping tags.
+        Yield individual lines.
+
+        XXX a hack, copied from pygments directly
+        """
+        nocls = self.noclasses
+        lsep = self.lineseparator
+        # for <span style=""> lookup only
+        getcls = self.ttype2class.get
+        c2s = self.class2style
+        escape_table = _escape_html_table
+
+        lspan = ''
+        line = ''
+        for ttype, value in tokensource:
+            if nocls:
+                cclass = getcls(ttype)
+                while cclass is None:
+                    ttype = ttype.parent
+                    cclass = getcls(ttype)
+                cspan = cclass and '<span style="%s">' % c2s[cclass][0] or ''
+            else:
+                cls = self._get_css_class(ttype)
+                cspan = cls and '<span class="%s">' % cls or ''
+
+            parts = value.translate(escape_table).split('\n')
+
+            # for all but the last line
+            for part in parts[:-1]:
+                if line:
+                    if lspan != cspan:
+                        before = (lspan and '</span>') + cspan
+                        after = (cspan and '</span>') + lsep
+                        self._consider_html(before)
+                        self._consider_txt(part)
+                        self._consider_html(after)
+                        line += before + part + after
+                    else: # both are the same
+                        self._consider_txt(part)
+                        after = (lspan and '</span>') + lsep
+                        self._consider_html(after)
+                        line += part + after
+                    yield 1, line
+                    self._reset_line()
+                    line = ''
+                elif part:
+                    yield 1, (self._consider_html(cspan) +
+                              self._consider_text(part) +
+                              self._consider_html(cspan and '</span>') + lsep)
+                    self._reset_line()
+                else: 
+                    yield 1, self._consider_html(lsep)
+                    self._reset_line()
+            # for the last line
+            if line and parts[-1]:
+                if lspan != cspan:
+                    line += (self._consider_html((lspan and '</span>') +
+                                                cspan) +
+                             self._consider_txt(parts[-1]))
+                    lspan = cspan
+                else:
+                    line += self._consider_txt(parts[-1])
+            elif parts[-1]:
+                line = (self._consider_html(cspan) +
+                        self._consider_txt(parts[-1]))
+                lspan = cspan
+            # else we neither have to open a new span nor set lspan
+
+        if line:
+            yield 1, line + (lspan and '</span>') + lsep
+            self._reset_line()
+
     def wrap(self, source, outfile):
         total = 1
         for i, t in HtmlFormatter.wrap(self, source, outfile):
             else:
                 yield i, t
 
+
 FNAME = '/home/fijal/src/pypy/pypy/translator/goal/richards.py'
 code = open(FNAME, 'r').read()
 with open('pygments.css', 'w') as f:
 with open('main.html', 'w') as f:
     f.write(Template(open("file.jinja").read()).render())
 with open("x.html", "w") as f:
-    source = highlight(code, PythonLexer(), CustomHtmlFormatter(code.splitlines()))
+    cf = CustomHtmlFormatter(code.splitlines())
+    source = highlight(code, PythonLexer(), cf)
+    sourcelines = source.splitlines()
     f.write(source)
 with open("x.json", "w") as f:
-    json.dump(code.splitlines(), f)
+    codelines = code.splitlines()
+    assert len(codelines) == len(cf.mapping) - 1
+    for ii, (cl, map) in enumerate(zip(codelines, cf.mapping)):
+        assert sum([i for (k, i) in map if k]) == len(cl), (map, cl, sourcelines[ii])
+    # we need to create a mapping for each character
+    line_mapping = []
+    for line, map in zip(codelines, cf.mapping):
+        new_line = []
+        counter = 0
+        last_good_counter = 0
+        for flag, lgt in map:
+            if not flag:
+                counter += lgt
+            else:
+                for i in range(lgt):
+                    new_line.append(counter)
+                    counter += 1
+                    last_good_counter = counter
+        new_line.append(last_good_counter)
+        line_mapping.append(new_line)
+    json.dump({'codelines': codelines,
+               'line_mapping': line_mapping}, f)