refactoring: moved everything of the library to a "pygpibtoolkit" module.

Tue, 05 Feb 2008 18:59:29 +0100

author
David Douard <david.douard@logilab.fr>
date
Tue, 05 Feb 2008 18:59:29 +0100
changeset 40
1bbea188a7e5
parent 39
8becd52c2171
child 41
9a453b2479c5

refactoring: moved everything of the library to a "pygpibtoolkit" module.

HP3562A/__init__.py file | annotate | diff | comparison | revisions
HP3562A/coord_decoder.py file | annotate | diff | comparison | revisions
HP3562A/dump_datablock.py file | annotate | diff | comparison | revisions
HP3562A/enum_types.py file | annotate | diff | comparison | revisions
HP3562A/q3562A.py file | annotate | diff | comparison | revisions
HP3562A/q3562A.ui file | annotate | diff | comparison | revisions
HP3562A/state_decoder.py file | annotate | diff | comparison | revisions
HP3562A/trace_decoder.py file | annotate | diff | comparison | revisions
__init__.py file | annotate | diff | comparison | revisions
bin/dump_datablock file | annotate | diff | comparison | revisions
bin/qgpibplotter file | annotate | diff | comparison | revisions
bin/read_coord file | annotate | diff | comparison | revisions
bin/read_state file | annotate | diff | comparison | revisions
bin/read_trace file | annotate | diff | comparison | revisions
plotter/__init__.py file | annotate | diff | comparison | revisions
plotter/gpib_plotter.py file | annotate | diff | comparison | revisions
plotter/gpib_plotter_mockup.py file | annotate | diff | comparison | revisions
plotter/hpgl_mpl.py file | annotate | diff | comparison | revisions
plotter/hpgl_parser.py file | annotate | diff | comparison | revisions
plotter/hpgl_plotter_rc.py file | annotate | diff | comparison | revisions
plotter/hpgl_qt.py file | annotate | diff | comparison | revisions
plotter/qgpib_plotter.py file | annotate | diff | comparison | revisions
plotter/qhpgl_plotter.ui file | annotate | diff | comparison | revisions
prologix.py file | annotate | diff | comparison | revisions
pygpib.py file | annotate | diff | comparison | revisions
pygpibtoolkit/HP3562A/__init__.py file | annotate | diff | comparison | revisions
pygpibtoolkit/HP3562A/coord_decoder.py file | annotate | diff | comparison | revisions
pygpibtoolkit/HP3562A/dump_datablock.py file | annotate | diff | comparison | revisions
pygpibtoolkit/HP3562A/enum_types.py file | annotate | diff | comparison | revisions
pygpibtoolkit/HP3562A/q3562A.py file | annotate | diff | comparison | revisions
pygpibtoolkit/HP3562A/q3562A.ui file | annotate | diff | comparison | revisions
pygpibtoolkit/HP3562A/state_decoder.py file | annotate | diff | comparison | revisions
pygpibtoolkit/HP3562A/trace_decoder.py file | annotate | diff | comparison | revisions
pygpibtoolkit/__init__.py file | annotate | diff | comparison | revisions
pygpibtoolkit/plotter/__init__.py file | annotate | diff | comparison | revisions
pygpibtoolkit/plotter/gpib_plotter.py file | annotate | diff | comparison | revisions
pygpibtoolkit/plotter/gpib_plotter_mockup.py file | annotate | diff | comparison | revisions
pygpibtoolkit/plotter/hpgl_mpl.py file | annotate | diff | comparison | revisions
pygpibtoolkit/plotter/hpgl_parser.py file | annotate | diff | comparison | revisions
pygpibtoolkit/plotter/hpgl_plotter_rc.py file | annotate | diff | comparison | revisions
pygpibtoolkit/plotter/hpgl_qt.py file | annotate | diff | comparison | revisions
pygpibtoolkit/plotter/qgpib_plotter.py file | annotate | diff | comparison | revisions
pygpibtoolkit/plotter/qhpgl_plotter.ui file | annotate | diff | comparison | revisions
pygpibtoolkit/prologix.py file | annotate | diff | comparison | revisions
pygpibtoolkit/pygpib.py file | annotate | diff | comparison | revisions
pygpibtoolkit/qt4/icons/led_green.svg file | annotate | diff | comparison | revisions
pygpibtoolkit/qt4/icons/led_green_off.svg file | annotate | diff | comparison | revisions
pygpibtoolkit/qt4/icons/led_red.svg file | annotate | diff | comparison | revisions
pygpibtoolkit/qt4/icons/led_red_off.svg file | annotate | diff | comparison | revisions
pygpibtoolkit/qt4/qpreferences.py file | annotate | diff | comparison | revisions
pygpibtoolkit/qt4/qpreferences_dialog.ui file | annotate | diff | comparison | revisions
pygpibtoolkit/qt4/qpreferenceseditor.py file | annotate | diff | comparison | revisions
pygpibtoolkit/qt4/resources.qrc file | annotate | diff | comparison | revisions
pygpibtoolkit/tools.py file | annotate | diff | comparison | revisions
qt4/icons/led_green.svg file | annotate | diff | comparison | revisions
qt4/icons/led_green_off.svg file | annotate | diff | comparison | revisions
qt4/icons/led_red.svg file | annotate | diff | comparison | revisions
qt4/icons/led_red_off.svg file | annotate | diff | comparison | revisions
qt4/qpreferences.py file | annotate | diff | comparison | revisions
qt4/qpreferences_dialog.ui file | annotate | diff | comparison | revisions
qt4/resources.qrc file | annotate | diff | comparison | revisions
tools.py file | annotate | diff | comparison | revisions
--- a/HP3562A/__init__.py	Mon Feb 04 19:49:48 2008 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,242 +0,0 @@
-"""
-HP3562A
-=======
-
-Module for communicating with the HP 3562A Digital Signal Analyzer.
-
-Subpackages
------------
-
-
-Constants
----------
-
-"""
-import struct
-import re
-import pygpib as gpib
-import numpy
-
-########################################
-# HP3562A internal binary types decoders
-
-def decode_float(s):
-    if len(s) == 4:
-        i1, i2, e = struct.unpack('>hbb', s)
-        i2 = i2 * 2**(-23)
-        return (i1/32768. + i2)*2**e
-    else:
-        i1, i2, i3, i4, e = struct.unpack('>hhhbb', s)
-        if i2 < 0:
-            i2 = (i2+32768.)*2**(-15)
-        else:
-            i2 = i2*2**(-15)
-        if i3 < 0:
-            i3 = (i3+32768.)*2**(-30)
-        else:
-            i3 = i3*2**(-15)
-        i4 = i4 * 2**(-38)
-        return (i1+i2+i3+i4)*2**(e-15)
-        
-# def decode_float(s):
-#     assert len(s) in [4,8]
-#     # exponential term 
-#     e = ord(s[-1])
-#     if e & 0x80:
-#         e = e - 256
-
-#     # mantissa
-#     m = [ord(x) for x in s[:-1]]
-#     M = 0.
-#     for i in range(len(s)-1):
-#         #M += m[i]<<(i*8)
-#         M += float(m[i])/2**((i+1)*8)
-#     # XXX how do we deal negative numbers?
-#     #if m[0] & 0x80:
-#     #    M = M - 2^(len(s))
-#     return M * 2**(e+1)
-
-def decode_string(s):
-    nb = ord(s[0])
-    s = s[1:nb+2]
-    r = ""
-    # XXX why do we need to do this? It's not described in the manual...
-    for c in s:
-        r += chr(ord(c) & 0x7F)
-    return r
-
-
-###
-# Some useful functions
-def format_header(header, head_struct, columns=80):
-    """
-    Pretty print a data block (trace, state or coord) 
-    """
-    bool_re = re.compile(r'((?P<before>.*) )?(?P<flag>\w+/\w+)( (?P<after>.*))?')
-    
-    todisp = []
-    for row in head_struct:
-        key = row[0]
-        typ = row[1]
-        if typ is None:
-            continue
-        val = header.get(key, "N/A")
-        if isinstance(val, basestring):
-            val = repr(val)
-        elif typ is bool and isinstance(val, typ):
-            m = bool_re.match(key)
-            if m:
-                d = m.groupdict()
-                key = ""
-                if d['before']:
-                    key += d['before']
-                if d['after']:
-                    key += d['after']
-                key = key.capitalize()
-                val = d['flag'].split('/')[not val]
-            else:
-                val = str(val)
-        else:            
-            val = str(val)
-        todisp.append((key+":", val))
-    maxk = max([len(k) for k, v in todisp])
-    maxv = max([len(v) for k, v in todisp])
-    fmt = "%%-%ds %%-%ds"%(maxk, maxv)
-    w = maxk+maxv+4
-    ncols = columns/w
-    if ncols:
-        nrows = len(todisp)/ncols
-    else:
-        nrows = len(todisp)
-    res = ""
-    for i in range(nrows):
-        res += "| ".join([fmt%todisp[j*nrows+i] for j in range(ncols)]) + "\n"
-    return res
-
-def decode_header(data, header_struct, idx=0):    
-    d = data
-    if d[idx:].startswith('#'):
-        # we have a preliminary header here...
-        typ = d[idx:idx+2]
-        assert typ == "#A"
-        idx += 2
-        totlen = struct.unpack('>h', d[idx:idx+2])[0]
-        idx += 2
-    tt=0
-    header = {}
-    for i, (nam, dtype, fmt, nbytes) in enumerate(header_struct):
-        if dtype is None:
-            idx += nbytes
-            continue
-        elif dtype == str:
-            val = decode_string(d[idx:])
-        else:
-            if fmt:
-                v = struct.unpack('>'+fmt, d[idx: idx+nbytes])[0]
-                if isinstance(dtype, dict):
-                    val = dtype.get(int(v), "N/A")
-                else:
-                    val = dtype(v)
-            else:
-                val = dtype(d[idx: idx+nbytes])
-        header[nam] = val
-        idx += nbytes
-    return header, idx
-
-def read_trace(data, idx, nelts):
-    assert len(data[idx:]) >= (nelts*4), "data[idx:] is too small (%s for %s)"%(len(data[idx:]), (nelts*4))
-    resu = []
-    for i in range(nelts):
-        resu.append(decode_float(data[idx: idx+4]))
-        idx += 4
-    return numpy.array(resu, dtype=float)
-    
-#####################
-# HP3562A constants
-
-# GPIB buffer size is 3x80 characters lines
-class STATUS_BYTE(gpib.Constants):
-    # HP3562A Status Byte, as returned by a serial poll
-    _constants = [(0x40, "RQS", "Request Service"), # when sent in response to a serial poll
-                  (0x20, "ERR", "GPIB error"),
-                  (0x10, "RDY", "ready to accept GPIB commands"),
-                  ]
-
-    conditions = [(0, "NSR", "No service requested"),
-                  (1, "USRQ1", "User SRQ #1"),
-                  (2, "USRQ1", "User SRQ #2"),
-                  (3, "USRQ1", "User SRQ #3"),
-                  (4, "USRQ1", "User SRQ #4"),
-                  (5, "USRQ1", "User SRQ #5"),
-                  (6, "USRQ1", "User SRQ #6"),
-                  (7, "USRQ1", "User SRQ #7"),
-                  (8, "USRQ1", "User SRQ #8"),
-                  (9, "EOD", "End of disk action"),
-                  (10, "EOP", "End of plot action"),
-                  (11, "STCH", "Instrument status changed"), # any change in 
-                  # the status register sets this condition
-                  (12, "PWR", "Power on"),
-                  (13, "KEY", "Key pressed"),
-                  (14, "DCP", "Device clear plotter (listen)"),
-                  # ...
-                  ]
-    def __init__(self):
-        super(STATUS_BYTE, self).__init__()
-        self._conditions = dict([(x[0], x[1]) for x in self.conditions])
-        self._rev_conditions = dict([(x[1], x[0]) for x in self.conditions])
-        self._long_conditions = dict([(x[0], x[2]) for x in self.conditions])
-               
-    def byte_condition(self, byte):
-        byte = byte & 0x8F
-        return self._conditions.get(byte, "N/A")
-
-class IS_REGISTER(gpib.Constants):
-    _constants = [(0x01, "MEASP", "measeurement pause"),
-                  (0x02, "ASQP", "Auto sequence pause"),
-                  (0X04, "EOM", "End of measurement, capture or throughput"),
-                  (0x08, "EOAS", "End of auto sequence"),
-                  (0x10, "SWPR", "Sweep point ready"),
-                  (0x20, "CH1OV", "Channel 1 overrange"),
-                  (0x40, "CH2OV", "Channel 2 overrange"),
-                  (0X80, "CH1HR", "Channel 1 half range"),
-                  (0x100, "CH2HR", "Channel 2 half range"),
-                  (0x200, "SFALT", "Source falt"),
-                  (0x400, "RUNL", "Reference unlock"),
-                  (0x800, "RMKT", "Remote marker knob turn"),
-                  (0x1000, "REKT", "Remote entry knob turn"),
-                  (0x2000, "ASRC", "Asctive Status Register changed"),
-                  (0x4000, "PWRF", "Power-on test failed"),
-                  ]
-    
-class StatusQuery(gpib.Constants):
-    _command = "STA?"
-    _constants = [(0x01, "N/A", "Not used"),
-                  (0x02, "N/A", "Not used"),
-                  (0x04, "KEY", "Key pressed"),
-                  (0x08, "N/A", "Not used"),
-                  (0x10, "RDY", "Ready"),
-                  (0x20, "ERR", "Error"),
-                  (0x40, "RQS", "Request"),
-                  (0x80, "MOS", "Message on screen"),
-                  (0x100, "MEASP", "measeurement pause"),
-                  (0x200, "ASQP", "Auto sequence pause"),
-                  (0X400, "EOM", "End of measurement, capture or throughput"),
-                  (0x800, "EOAS", "End of auto sequence"),
-                  (0x1000, "SWPR", "Sweep point ready"),
-                  (0x2000, "CH1OV", "Channel 1 overrange"),
-                  (0x4000, "CH2OV", "Channel 2 overrange"),
-                  (0x8000, "MAOV", "Math overflow"),
-                  ]
-class ActivityStatysRegister(gpib.Constants):
-    _command = "AS?"
-    _constants = [(0x01, "CKFL", "Check fault log"),
-                  (0x02, "FITR", "Filling time record"),
-                  (0x04, "FLTR", "Filters settings"),
-                  (0x08, "CFTP", "Curve fir in progress"),
-                  (0x10, "MSSM", "Missed sample"),
-                  (0x20, "TMPR", "Timed preview"),
-                  (0x40, "ACDA", "Accept date"),
-                  #...
-                  ]
-
-    
--- a/HP3562A/coord_decoder.py	Mon Feb 04 19:49:48 2008 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,126 +0,0 @@
-# -*- coding: utf-8 -*-
-"""
-state_decoder
-=============
-
-Module for decoding the internal state of the HP3562A DSA, using the
-GPIB command "DSBN" (Dump State BiNary).
-
-This file can be exectued as a python script. Use '-h' for more informations. 
-"""
-
-from HP3562A import format_header, decode_float, decode_string, decode_header, read_trace
-from HP3562A.trace_decoder import decode_trace, HEADER as TRACE_HEADER
-from HP3562A.enum_types import *
-
-HEADER = [("Y coordinates", EYCOORD, 'h', 2),
-          ("# of disp elements", int, "h", 2),
-          ("First element", int, "h", 2),
-          ("Total elements", int, 'h', 2),
-          ("Display sampling", EDISPSMP, 'h', 2),
-          ("Scaling", ESCAL, 'h', 2),
-          ("Data pointer", long, 'l', 4),
-          ("In data", long, 'l', 4),
-          ("Log/linear x-axis", bool, 'h', 2),
-          ("Sampled display data", bool, 'h', 2),
-          ("Plot/Graph mode", bool, 'h', 2),
-          ("Phase wrap", bool, 'h', 2),
-          ("Not used", None, None, 36),
-          ("X scale factor", decode_float, None, 4),
-          ("Grid min Y scale", decode_float, None, 4),
-          ("Grid max Y scale", decode_float, None, 4),
-          ("/div", decode_float, None, 4),
-          ("Min value of data", decode_float, None, 4),
-          ("Max value of data", decode_float, None, 4),
-          ("Y cumulative min", decode_float, None, 4),
-          ("Y cumulative max", decode_float, None, 4),
-          ("Y scale factor", decode_float, None, 4),
-          ("Not used", None, None, 16),
-          ("Stop value", decode_float, None, 8),
-          ("Left grid", decode_float, None, 8),
-          ("Right grid", decode_float, None, 8),
-          ("Left data", decode_float, None, 8),
-          ("Right data", decode_float, None, 8),          
-    ]
-
-def decode_coord(data):
-    """
-    Decode the data (as generated by the HP3562A DSA in response to a
-    "DSBN" command), and returns a dict (header)
-
-    header is the dictionnary of the header of the dumped data block,
-    """
-    header, idx = decode_header(data, HEADER)
-    trace_header, idx = decode_header(data, TRACE_HEADER, idx)
-    trace = read_trace(data, idx, trace_header["Number of elements"])
-    return header, trace_header, trace
-    
-
-def main():
-    import sys
-    import optparse
-    import numpy
-    
-    opt = optparse.OptionParser("A simple tool for displaying dumped coord data block")
-    opt.add_option('-f', '--filename', default=None,
-                   dest='filename',
-                   help='Output filename. If not set, read from stdin')
-    opt.add_option('-m', '--mode', default='binary',
-                   dest='mode',
-                   help='Dumping mode (may be "binary" [default], "ascii" or "ansi")',
-                   )
-    opt.add_option('-d', '--display-header', default=False,
-                   action="store_true",
-                   dest="displayheader",
-                   help="Display the trace header")
-    opt.add_option('-P', '--noplot-trace', default=True,
-                   action="store_false",
-                   dest="plot",
-                   help="Do not display the plot of the trace")
-    opt.add_option('-x', '--xmode', default='lin',
-                   dest='xmode',
-                   help='X coordinate mode (may be "lin" [default] or "log")')
-    opt.add_option('-y', '--ymode', default='lin',
-                   dest='ymode',
-                   help='Y coordinate mode (may be "lin" [default], "log" or "db")')
-    
-    options, argv = opt.parse_args(sys.argv)
-
-
-    if options.filename is None:
-        print "Can't deal stdin for now..."
-        sys.exit(1)
-    try:
-        coord_header, header, data = decode_coord(open(options.filename, 'rb').read())
-    except Exception, e:
-        print "ERROR: can't read %s an interpret it as a HP3562 trace"%options.filename
-        print e
-        sys.exit(1)
-
-    if options.displayheader:
-        print format_header(coord_header, HEADER, 100)
-        print format_header(header, TRACE_HEADER, 100)
-    if options.plot:
-        f0 = header['Start freq value']
-        dx = header['Delta X-axis']
-        n = header['Number of elements']
-        x = numpy.linspace(f0, f0+dx*n, len(data)) 
-        y = data.copy()
-
-        ym = coord_header['Min value of data']
-        yM = coord_header['Max value of data']
-        ys = coord_header['Y scale factor']
-        
-        y[y<ym] = ym
-        y *= ys
-        
-        import pylab
-        pylab.ylabel(header['Amplitude units'])
-        pylab.grid()
-        pylab.plot(x, y)
-        pylab.xlabel('frequency (%s)'%header["X axis units"])
-        pylab.ylabel("%s (%s)"%(coord_header['Y coordinates'], header['Amplitude units']) )
-        pylab.show()
-    
-if __name__ == "__main__":
-    main()
--- a/HP3562A/dump_datablock.py	Mon Feb 04 19:49:48 2008 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,87 +0,0 @@
-import sys
-import time
-import gpib
-import prologix
-
-
-class HP3562dumper(prologix.GPIB):
-    """
-    Class dedicated to dump data blocks from HP3562A DSA (trace,
-    internal state or coordinate).
-    """
-    MODES = {'trace': 'DD',
-             'state': 'DS',
-             'coord': 'DC',
-             }
-    
-    FORMATS = {'binary': 'BN',
-               'ascii': 'AS',
-               'ansi': 'AN'}
-            
-    def __init__(self, device="/dev/ttyUSB0", baudrate=115200, timeout=0.1,
-                 address=0):
-        super(HP3562dumper, self).__init__(device, baudrate, timeout, address, mode=1)
-
-    def dump(self, mode='trace', format="binary"): 
-        """
-        Dump the required data block and return it as a raw string buffer.
-
-        'mode' can be 'trace' [default], 'state' or 'coord'.
-        'format' can be 'binary' [default], 'ascii' or 'ansi'.
-        """
-        format = format.lower()
-        mode = mode.lower()
-        assert mode in self.MODES
-        assert format in self.FORMATS
-        cmd = self.MODES[mode] + self.FORMATS[format]
-
-        res = ""
-        print "command = ", cmd
-        self._cnx.write('%s\r'%cmd)
-        i = 0
-        while i<self._retries:
-            l = self._cnx.readline()
-            if l.strip() == "":
-                i += 1
-                time.sleep(self._timeout)
-                continue
-            res += l 
-            i = 0
-        return res
-
-    
-
-def main():
-    import optparse
-    opt = optparse.OptionParser("A simple tool for dumping the current trace")
-    opt.add_option('-f', '--filename', default=None,
-                   dest='filename',
-                   help='Output filename. If not set, write to stdout')
-    opt.add_option('-d', '--device', default='/dev/ttyUSB0',
-                   dest='device',
-                   help='Device of the RS232 connection (default: /dev/ttyUSB0)',
-                   )
-    opt.add_option('-a', '--address', default=0,
-                   dest='address',
-                   help='GPIB address of the device',
-                   )
-    opt.add_option('-b', '--block', default='trace',
-                   dest='block',
-                   help='Data block to dump (may be "trace" [default], "state" or "coord")',
-                   )
-    opt.add_option('-m', '--mode', default='binary',
-                   dest='mode',
-                   help='Dumping mode (may be "binary" [default], "ascii" or "ansi")',
-                   )
-    options, argv = opt.parse_args(sys.argv)
-
-    cnx = HP3562dumper(device=options.device, address=int(options.address))
-    res = cnx.dump(mode=options.block, format=options.mode)
-    sys.stderr.write("read %s bytes\n"%(len(res)))
-    if options.filename:
-        open(options.filename, 'w').write(res)
-    else:
-        print res
-    
-if __name__=='__main__':
-    main()
--- a/HP3562A/enum_types.py	Mon Feb 04 19:49:48 2008 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,273 +0,0 @@
-# -*- coding: utf-8 -*-
-"""
-Constants used for HP3562A data block interpretation.
-"""
-
-EDSP = {0: "No data",
-        1: "Frequency response",
-        2: "Power spectrum 1",
-        3: "Power spectrum 2",
-        4: "Coherence",
-        5: "Cross spectrum",
-        6: "Input time 1",
-        7: "Input time 2",
-        8: "Input linear spectrum 1",
-        9: "Input linear spectrum 2",
-        10: "Impulse response",
-        11: "Cross correlation",
-        12: "Auto correlation 1",
-        13: "Auto correlation 2",
-        14: "Histogram 1",
-        15: "Histogram 2",
-        16: "Cumulative density function 1",
-        17: "Cumulative density function 2",
-        18: "Probability density function 1",
-        19: "Probability density function 2",
-        20: "Average linear spectrum 1",
-        21: "Average linear spectrum 2",
-        22: "Average time record 1",
-        23: "Average time record 2",
-        24: "Synthesis pole-zeros",
-        25: "Synthesis pole-residue",
-        26: "Synthesis polynomial",
-        27: "Synthesis constant",
-        28: "Windowed time record 1",
-        29: "Windowed time record 2",
-        30: "Windowed linear spectrum 1",
-        31: "Windowed linear spectrum 2",
-        32: "Filtered time record 1",
-        33: "Filtered time record 2",
-        34: "Filtered linear spectrum 1",
-        35: "Filtered linear spectrum 2",
-        36: "Time capture buffer",
-        37: "Captured linear spectrum",
-        38: "Captured time record",
-        39: "Throughput time record 1",
-        40: "Throughput time record 2",
-        41: "Curve fit",
-        42: "Weighted function",
-        43: "Not used",
-        44: "Orbits",
-        45: "Demodulation polar",
-        46: "Preview demod record 1",
-        47: "Preview demod record 2",
-        48: "Preview demod linear spectrum 1",
-        49: "Preview demod linear spectrum 2",
-        }
-
-ECH = {0: "Channel 1",
-       1: "Channel 2",
-       2: "Channel 1&2",
-       3: "No channel",
-       }
-
-EOVR = ECH
-
-EDOM = {0: 'Time',
-        1: 'Frequency',
-        2: 'Voltage (amplitude)',
-        }
-
-EVLT = {0: "Peak",
-        1: "RMS",
-        2: "Volt (indicates peak only)",
-        }
-
-EAMP = {0: u"Volts",
-        1: u"Volts²",
-        2: u"PSD (V²/Hz)",
-        3: u"ESD (V²s/Hz)",
-        4: u"PSD¹² (V/Hz¹²)",
-        5: u"No unit",
-        6: u"Unit volts",
-        7: u"Unit volts²",
-        }
-        
-EXAXIS= {0: u"No units",
-         1: u"Hertz",
-         2: u"RPM",
-         3: u"Orders",
-         4: u"Seconds",
-         5: u"Revs",
-         6: u"Degrees",
-         7: u"dB",
-         8: u"dBV",
-         9: u"Volts",
-         10: u"V\u221AHz",
-         11: u"Hz/s",
-         12: u"V/EU",
-         13: u"Vrms",
-         14: u"V²/Hz",
-         15: u"%",
-         16: u"Points",
-         17: u"Records",
-         18: u"Ohms",
-         19: u"Hertz/octave",
-         20: u"Pulse/Rev",
-         21: u"Decades",
-         22: u"Minutes",
-         23: u"V²s/Hz",
-         24: u"Octave",
-         25: u"Seconds/Decade",
-         26: u"Seconds/Octave",
-         27: u"Hz/Point",
-         28: u"Points/Sweep",
-         29: u"Points/Decade",
-         30: u"Points/Octave",
-         31: u"V/Vrms",
-         32: u"V²",
-         33: u"EU referenced to chan 1",
-         34: u"EU referenced to chan 2",
-         35: u"EU value",
-         }
-
-EMEAS = {0: "Linear resolution",
-         1: "Log resolution",
-         2: "Swept sine",
-         3: "Time capture",
-         4: "Linear resolution throughput",
-         }
-
-EDEMOD = {45: "AM",
-          46: "FM",
-          47: "PM",
-          }
-
-EAVG = {0: "No data",
-        1: "Not averaged",
-        2: "Averaged",}
-
-EWIN = {0: "N/A",
-        1: "Hann",
-        2: "Flat top",
-        3: "Uniforme",
-        4: "Exponential",
-        5: "Force",
-        6: "Force chan 1/expon chan 2",
-        7: "Expon chan 1/force chan 2",
-        8: "User",
-        }
-
-EMTYP = {0: "Frequency responce",
-         1: "Cross correlation",
-         2: "Power spectrum",
-         3: "Auto correlation",
-         4: "Histogram",
-         5: "No measurement",
-         }
-
-EWINTYP = { 11: "Hanning",
-            12: "Flat top",
-            13: "Uniform",
-            14: "User window",
-            15: "Force/Exponential",
-            }
-
-EFEXPW = { 0: "Force",
-           1: "Exponential",
-           }
-
-EAVGTYP = { 6: "Stable",
-            7: "Exponential",
-            8: "Peak",
-            9: "Continuous peak",
-            10: "Averaging off",
-            }
-
-ETRGTYP = { 18: "Free run",
-            19: "Channel 1",
-            20: "Channel 2",
-            21: "External",
-            22: "Source trigger",
-            23: "HP-IB trigger",
-            }
-
-ETRGSLP = { 16: "Positive",
-            17: "Negative",
-            }
-
-EPRVTYP = { 0: "Manual preview",
-            1: "Timed preview",
-            2: "Preview off",
-            }
-
-ESMPTYP = { 24: "Internal sample",
-            25: "External sample",
-            }
-
-ERNGUNT = EXAXIS
-
-ERNGTYP = { 26: "Auto range on",
-            27: "Auto range off",
-            28: "Auto range set",
-            }
-
-EINCPL = { 29: "AC",
-           30: "DC",
-           }
-
-ESRCTYP = { 31: "Source off",
-            32: "Random noise",
-            33: "Burst random",
-            34: "Periodic chirp",
-            35: "Burst chirp",
-            36: "Swept sine",
-            37: "Fixed sine",
-            }
-
-ESWPDIR = { 41: "Up",
-            42: "Sweep hold",
-            43: "Manual sweep",
-            44: "Down",
-            }
-
-ESWPMOD = { 39: "Linear sweep",
-            40: "Log sweep",
-            }
-
-EEXTSMPFREQUNT = EXAXIS
-
-EBNDUNT = EXAXIS
-
-ESWPRATEUNT = EXAXIS
-
-EAUGAINREFCH = { 0: "Channel 1",
-                 1: "Channel 2",
-                 2: "Not used",
-                 3: "No channel",
-                 }
-EDEMODCH = {  0: "Channel 1",
-              1: "Channel 2",
-              2: "Both channels",
-              3: "No channel",
-              }
-
-ESRCLVLUNT = EXAXIS
-
-ESRCDCOFFST = EXAXIS
-
-ETRGLVLUNT = EXAXIS
-
-ECPTLGHUNT = EXAXIS
-
-EYCOORD = { 1: "Real",
-            2: "Imaginary",
-            3: "Linear magnitude",
-            4: "Log magnitude",
-            5: "dB",
-            6: "Nyquist",
-            7: "Not used",
-            8: "Phase",
-            9: "Nichols",
-            10: "dBm",
-            }
-
-EDISPSMP = { 0: "Not sampled", # #displayed elements = total elements
-             1: "Half sampled", # #displayed elements = total elements/2
-             2: "Sampled", # #displayed elements < total elements
-            }
-ESCAL = { 0: "X and Y auto scale",
-          1: "X fixed, Y auto scale",
-          2: "X auto scale, Y fixed",
-          3: "X and Y fixed",
-          }
--- a/HP3562A/q3562A.py	Mon Feb 04 19:49:48 2008 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,346 +0,0 @@
-#
-
-import os, sys
-import time
-import glob
-
-from PyQt4 import QtGui, QtCore, uic
-from PyQt4.QtCore import SIGNAL, Qt
-
-if "-m" in sys.argv:
-    from dump_datablock_mockup import HP3562dumper
-else:
-    from dump_datablock import HP3562dumper
-import q3562A_rc
-
-ldir = os.path.abspath(os.path.dirname(__file__))
-sys.path.append(ldir)
-form_class, base_class = uic.loadUiType(os.path.join(ldir, "q3562A.ui"))
-
-from qpreferences import BaseItem, IntItem, UnicodeItem, ColorItem
-from qpreferences import PointItem, SizeItem, ByteArrayItem
-from qpreferences import AbstractPreferences
-from qpreferenceseditor import PreferencesEditor
-
-from tools import str_num_cmp
-
-class Preferences(AbstractPreferences):
-    ORGANISATION="Logilab"
-    APPLICATION="qgpib_plotter"
-
-    _pos = PointItem()
-    _size = SizeItem()
-    _appState = ByteArrayItem()
-
-    device = UnicodeItem(default='/dev/ttyUSB0',
-                         name=u'device',
-                         description=u'GPIB device',
-                         group="GPIB settings")
-    address = IntItem(default=5, min=0, max=16,
-                      name=u'GPIB address',
-                      group="GPIB settings")
-    
-    background = ColorItem(default=QtGui.QColor("white"),
-                           name="Background",
-                           group="Colors")
-    color0 = ColorItem(default=QtGui.QColor("black"),
-                       name="Pen #0",
-                       group="Colors")
-    color1 = ColorItem(default=QtGui.QColor("green"),
-                       name="Pen #1",
-                       group="Colors")
-    color2 = ColorItem(default=QtGui.QColor("red"),
-                       name="Pen #2",
-                       group="Colors")
-    color3 = ColorItem(default=QtGui.QColor("blue"),
-                       name="Pen #3",
-                       group="Colors")
-    color4 = ColorItem(default=QtGui.QColor("yellow"),
-                       name="Pen #4",
-                       group="Colors")
-    color5 = ColorItem(default=QtGui.QColor("cyan"),
-                       name="Pen #5",
-                       group="Colors")
-    color6 = ColorItem(default=QtGui.QColor("magenta"),
-                       name="Pen #6",
-                       group="Colors")
-    color7 = ColorItem(default=QtGui.QColor("darkred"),
-                       name="Pen #7",
-                       group="Colors")
-    
-class QtHPGLPlotter(QtGui.QMainWindow, form_class):
-    def __init__(self, parent=None):
-        QtGui.QMainWindow.__init__(self, parent)
-        self._plots = {}        
-        self._prefs = Preferences()
-        self.setupUi()
-        self.initializeGPIB()
-        if self._prefs._pos:
-            self.move(self._prefs._pos)
-        if self._prefs._size:
-            self.resize(self._prefs._size)
-        if self._prefs._appState:
-            self.restoreState(self._prefs._appState)
-        self.readPreferences()
-
-    def readPreferences(self):
-        bg = self._prefs.background
-        if bg and bg.isValid():
-            self.plotterWidget.qview.setBackgroundBrush(QtGui.QBrush(bg))
-        pen_colors = [self._prefs["color%d"%i] for i in range(8)]
-        self.plotterWidget.pen_colors = pen_colors
-        
-    def replotCurrent(self):
-        self.currentPlotChanged(self.plotsView.currentIndex())
-        
-    def setupUi(self):
-        form_class.setupUi(self, self) # call qtdesigner generated form creation        
-        # actions defined in designer
-        self.connect(self.actionPreferences, SIGNAL('triggered(bool)'),
-                     self.preferencesTriggered)
-        self.connect(self.actionQuit, SIGNAL('triggered(bool)'),
-                     self.quitTriggered)
-        self.actionQuit.setShortcut(QtGui.QKeySequence(u'Ctrl+Q'))
-        self.connect(self.actionOpen, SIGNAL('triggered(bool)'),
-                     self.openTriggered)
-        self.actionOpen.setShortcut(QtGui.QKeySequence(u'Ctrl+O'))
-        self.connect(self.actionSave, SIGNAL('triggered(bool)'),
-                     self.saveTriggered)
-        self.actionSave.setShortcut(QtGui.QKeySequence(u'Ctrl+S'))
-        self.connect(self.actionSaveAs, SIGNAL('triggered(bool)'),
-                     self.saveAsTriggered)
-
-        self.plotterWidget = QHPGLPlotterWidget(self)
-        self.setCentralWidget(self.plotterWidget)
-
-        self.connect(self.captureButton, SIGNAL("toggled(bool)"),
-                     self.captureToggled)
-
-        self._plots_list = QtGui.QStringListModel()
-        self.plotsView.setModel(self._plots_list)
-        self.connect(self.plotsView, SIGNAL('activated(const QModelIndex&)'),
-                     self.currentPlotChanged)
-        self.connect(self.plotsView.selectionModel(),
-                     SIGNAL('currentChanged(const QModelIndex&, const QModelIndex&)'),
-                     self.currentPlotChanged)
-
-    def currentPlotChanged(self, index, old_index=None):
-        if index.isValid():
-            value = unicode(self.plotsView.model().data(index, Qt.DisplayRole).toString())
-            
-            self.plotterWidget.clear()
-            self.plotterWidget.parse(self._plots[value])
-            
-    def preferencesTriggered(self, checked=False):
-        PreferencesEditor(self._prefs, self).exec_()
-        self.readPreferences()
-        self.replotCurrent()
-
-    def quitTriggered(self, checked=False):
-        self.close()
-
-    def closeEvent(self, event):
-        if 1:
-        #if self.promptForSave():
-            self._prefs._pos = self.pos()
-            self._prefs._size = self.size()
-            self._prefs._appState = self.saveState()
-            event.accept()
-        else:
-            event.ignore()
-        
-    def openTriggered(self, checked=False):
-        filenames = QtGui.QFileDialog.getOpenFileNames(self, "Open a HPGL file to display", '.', 'HPGL files (*.plt)\nAll files (*)')
-        self.openFiles(filenames)
-        self.displayFirst()
-        
-    def displayFirst(self):
-        if not self.plotsView.currentIndex().isValid():
-            self.plotsView.setCurrentIndex(self.plotsView.model().index(0, 0))
-        
-    def openFiles(self, filenames):
-        ok = False
-        for filename in filenames:
-            filename = str(filename)
-            if os.path.exists(filename):
-                data = open(filename).read()
-                name = os.path.basename(filename)
-                name = os.path.splitext(name)[0]
-                lst = self.plotsView.model().stringList()
-                lst.append(name)            
-                self._plots[name] = data
-                self.plotsView.model().setStringList(lst)
-                ok = True
-        return ok
-        
-    def plotReceived(self, num):
-        self._receiving = False
-        self.setReceivingLed()
-        plot, timestamp = self.captureThread.getPlot(num)
-        name = "plot_%s"%(num)
-        lst = self.plotsView.model().stringList()
-        lst.append(name)            
-        self._plots[name] = plot
-        self.plotsView.model().setStringList(lst)
-
-    def plotStarted(self):
-        self._receiving = True
-        self.setReceivingLed()
-        
-    def saveTriggered(self, checked=False):
-        print "save"
-        
-    def saveAsTriggered(self, checked=False):
-        index = self.plotsView.selectionModel().currentIndex()
-        if index.isValid():
-            filename = QtGui.QFileDialog.getSaveFileName(self, "Selecte a file name to save HPGL file", '.', 'HPGL files (*.plt)\nAll files (*)')
-            n = index.row()
-            value = unicode(self.plotsView.model().data(index, Qt.DisplayRole).toString())
-            open(filename, 'w').write(self._plots[value])
-            
-        
-    def initializeGPIB(self):
-        self._online = False
-        try:
-            self.gpib_plotter = QGPIBplotter(device=self._prefs.device,
-                                            address=self._prefs.address,
-                                            )
-            self.captureThread = GPIBReceiver(self.gpib_plotter)
-            self.connect(self.captureThread, SIGNAL('plotReceived(int)'),
-                         self.plotReceived)
-            self.connect(self.captureThread, SIGNAL('plotStarted()'),
-                         self.plotStarted)
-            self.captureThread.start()
-        except Exception, e:
-            #print e
-            self.gpib_plotter = None
-        self.setCaptureLed()
-
-    def captureToggled(self, state):
-        if state:
-            if self.gpib_plotter is None:
-                self.initializeGPIB()
-                if self.gpib_plotter is None:
-                    QtGui.QMessageBox.critical(self, self.tr("GPIB error"),
-                                               self.tr("<b>Unable to initialize GPIB connection</b>.<br>Please check your GPIB dongle and settings."))
-                    self._online = False
-                    self.setCaptureLed()
-                    return
-            self._online = True
-            self.captureThread.startCapture()
-        else:
-            if self.captureThread:
-                self.captureThread.stopCapture()
-            self._online = False
-        self.setCaptureLed()
-        
-    def setCaptureLed(self):
-        if self._online:
-            icn = QtGui.QIcon(':/icons/led_green.svg')
-        else:
-            icn = QtGui.QIcon(':/icons/led_green_off.svg')
-        self.captureButton.setIcon(icn)
-        self.captureButton.setChecked(self._online)
-
-    def setReceivingLed(self):
-        if self._receiving:
-            icn = QtGui.QIcon(':/icons/led_red.svg')
-        else:
-            icn = QtGui.QIcon(':/icons/led_red_off.svg')
-        self.receivingButton.setIcon(icn)
-
-class QGPIBplotter(GPIBplotter):
-    def __init__(self, device="/dev/ttyUSB0", baudrate=115200, timeout=0.1,
-                 address=5):
-        GPIBplotter.__init__(self, device, baudrate, timeout, address)        
-        self.emitter = None
-
-    def plotStarted(self):
-        if self.emitter:
-            self.emitter.emit(SIGNAL('plotStarted()'))
-            #self.emitter.msleep(1)
-        
-class GPIBReceiver(QtCore.QThread):
-    def __init__(self, cnx):
-        QtCore.QThread.__init__(self)
-        self.gpibplotter = cnx
-        self.gpibplotter.emitter = self
-        
-        self._cancelmutex = QtCore.QMutex()
-        self._cancel = False
-        #self._nreceived = 0
-        self._plotsmutex = QtCore.QMutex()
-        self._plots = []
-        self._startstopmutex = QtCore.QMutex()
-        self._startstop = QtCore.QWaitCondition()
-        self._capturing = False
-        
-    def cancel(self):
-        self._cancelmutex.lock()
-        self._cancel = True
-        self._cancelmutex.unlock()
-
-    def startCapture(self):
-        self._startstop.wakeOne()
-
-    def stopCapture(self):
-        self._startstopmutex.lock()
-        self._capturing = False
-        self._startstopmutex.unlock()
-
-    def run(self):
-        while 1:
-            self._cancelmutex.lock()
-            if self._cancel:
-                return
-            self._cancelmutex.unlock()
-            self._startstopmutex.lock()
-            if not self._capturing:
-                self._startstop.wait(self._startstopmutex)
-                self._capturing = True
-            self._startstopmutex.unlock()
-        
-            plot = self.gpibplotter.load_plot(wait_timeout=0.1)
-            timestamp = time.time()
-            if plot:
-                self._plotsmutex.lock()
-                self._plots.append((plot, timestamp))
-                n = len(self._plots)
-                self._plotsmutex.unlock()
-                self.emit(SIGNAL('plotReceived(int)'), n-1)
-            self.msleep(10)
-            
-    def getPlot(self, num):
-        self._plotsmutex.lock()
-        try:
-            return self._plots[num]
-        finally:
-            self._plotsmutex.unlock()
-
-def main():
-    import optparse
-    opt = optparse.OptionParser('A simple PyQt4 HP7470A GPIB plotter emulator for USB-GPIB bundle (ProLogix)')
-    opt.add_option('-m', '--mockup', default=False,
-                   action="store_true",
-                   dest='mockup',
-                   help='Use a pseudo GPIB connection (for test purpose)',
-                   )
-    opt.add_option('-v', '--verbose', default=False,
-                   action="store_true",
-                   dest="verbose",
-                   help="Verbose mode",)
-    
-    options, argv = opt.parse_args(sys.argv)
-
-    a = QtGui.QApplication(argv)
-    w = QtHPGLPlotter()
-    files = [f for f in argv[1:] if os.path.isfile(f)]
-    files.sort(cmp=str_num_cmp)
-    if w.openFiles(files):    
-        w.displayFirst()
-
-    w.show()
-    a.exec_()
-        
-if __name__ == '__main__':
-    main()
--- a/HP3562A/q3562A.ui	Mon Feb 04 19:49:48 2008 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,179 +0,0 @@
-<ui version="4.0" >
- <class>MainWindow</class>
- <widget class="QMainWindow" name="MainWindow" >
-  <property name="geometry" >
-   <rect>
-    <x>0</x>
-    <y>0</y>
-    <width>507</width>
-    <height>492</height>
-   </rect>
-  </property>
-  <property name="windowTitle" >
-   <string>MainWindow</string>
-  </property>
-  <widget class="QWidget" name="centralwidget" />
-  <widget class="QMenuBar" name="menubar" >
-   <property name="geometry" >
-    <rect>
-     <x>0</x>
-     <y>0</y>
-     <width>507</width>
-     <height>25</height>
-    </rect>
-   </property>
-   <widget class="QMenu" name="menu_File" >
-    <property name="title" >
-     <string>&amp;File</string>
-    </property>
-    <addaction name="actionOpen" />
-    <addaction name="actionSave" />
-    <addaction name="actionSaveAs" />
-    <addaction name="separator" />
-    <addaction name="actionQuit" />
-   </widget>
-   <widget class="QMenu" name="menuEdit" >
-    <property name="title" >
-     <string>Edit</string>
-    </property>
-    <addaction name="actionPreferences" />
-   </widget>
-   <addaction name="menu_File" />
-   <addaction name="menuEdit" />
-  </widget>
-  <widget class="QStatusBar" name="statusbar" />
-  <widget class="QDockWidget" name="plotsDock" >
-   <attribute name="dockWidgetArea" >
-    <number>1</number>
-   </attribute>
-   <widget class="QWidget" name="dockWidgetContents" >
-    <layout class="QVBoxLayout" >
-     <property name="spacing" >
-      <number>4</number>
-     </property>
-     <property name="leftMargin" >
-      <number>1</number>
-     </property>
-     <property name="topMargin" >
-      <number>4</number>
-     </property>
-     <property name="rightMargin" >
-      <number>1</number>
-     </property>
-     <property name="bottomMargin" >
-      <number>1</number>
-     </property>
-     <item>
-      <layout class="QHBoxLayout" >
-       <item>
-        <widget class="QToolButton" name="getTraceButton" >
-         <property name="minimumSize" >
-          <size>
-           <width>0</width>
-           <height>29</height>
-          </size>
-         </property>
-         <property name="text" >
-          <string>get trace</string>
-         </property>
-         <property name="icon" >
-          <iconset/>
-         </property>
-         <property name="iconSize" >
-          <size>
-           <width>16</width>
-           <height>16</height>
-          </size>
-         </property>
-         <property name="checkable" >
-          <bool>true</bool>
-         </property>
-         <property name="toolButtonStyle" >
-          <enum>Qt::ToolButtonTextBesideIcon</enum>
-         </property>
-        </widget>
-       </item>
-       <item>
-        <widget class="QToolButton" name="getStatusButton" >
-         <property name="minimumSize" >
-          <size>
-           <width>0</width>
-           <height>29</height>
-          </size>
-         </property>
-         <property name="text" >
-          <string>get status</string>
-         </property>
-         <property name="checkable" >
-          <bool>true</bool>
-         </property>
-        </widget>
-       </item>
-       <item>
-        <widget class="QToolButton" name="getCoordButton" >
-         <property name="minimumSize" >
-          <size>
-           <width>0</width>
-           <height>29</height>
-          </size>
-         </property>
-         <property name="text" >
-          <string>get coord</string>
-         </property>
-         <property name="checkable" >
-          <bool>true</bool>
-         </property>
-        </widget>
-       </item>
-       <item>
-        <spacer>
-         <property name="orientation" >
-          <enum>Qt::Horizontal</enum>
-         </property>
-         <property name="sizeHint" >
-          <size>
-           <width>40</width>
-           <height>20</height>
-          </size>
-         </property>
-        </spacer>
-       </item>
-      </layout>
-     </item>
-     <item>
-      <widget class="QListView" name="objectsView" />
-     </item>
-    </layout>
-   </widget>
-  </widget>
-  <action name="actionOpen" >
-   <property name="text" >
-    <string>&amp;Open</string>
-   </property>
-  </action>
-  <action name="actionSave" >
-   <property name="text" >
-    <string>&amp;Save</string>
-   </property>
-  </action>
-  <action name="actionSaveAs" >
-   <property name="text" >
-    <string>Save as...</string>
-   </property>
-  </action>
-  <action name="actionQuit" >
-   <property name="text" >
-    <string>&amp;Quit</string>
-   </property>
-  </action>
-  <action name="actionPreferences" >
-   <property name="text" >
-    <string>Preferences</string>
-   </property>
-  </action>
- </widget>
- <resources>
-  <include location="q3562A.qrc" />
- </resources>
- <connections/>
-</ui>
--- a/HP3562A/state_decoder.py	Mon Feb 04 19:49:48 2008 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,151 +0,0 @@
-# -*- coding: utf-8 -*-
-"""
-state_decoder
-=============
-
-Module for decoding the internal state of the HP3562A DSA, using the
-GPIB command "DSBN" (Dump State BiNary).
-
-This file can be exectued as a python script. Use '-h' for more informations. 
-"""
-from HP3562A import format_header, decode_float, decode_string, decode_header
-
-from HP3562A.enum_types import *
-
-HEADER = [("Measurement mode", EMEAS, 'h', 2),
-          ("Measurement 1", EMTYP, 'h', 2),
-          ("Measurement 2", EMTYP, 'h', 2),
-          ("Window type", EWINTYP, 'h', 2),
-          ("Force/Expon window 1", EFEXPW, 'h', 2),
-          ("Force/Expon window 2", EFEXPW, 'h', 2),
-          ("Average type", EAVGTYP, 'h', 2),
-          ("Overlap percentage", int, 'h', 2),
-          ("Number of averages", int, 'h', 2),
-          ("Sweep # of averages", int, 'h', 2),
-          ("Trigger type", ETRGTYP, 'h', 2),
-          ("Trigger slope", ETRGSLP, 'h', 2),
-          ("Preview type", EPRVTYP, 'h', 2),
-          ("Sample type", ESMPTYP, 'h', 2),
-          ("Range units chan 1", ERNGUNT, 'h', 2),
-          ("Range units chan 2", ERNGUNT, 'h', 2),
-          ("Range type 1", ERNGTYP, 'h', 2),
-          ("Range type 2", ERNGTYP, 'h', 2),
-          ("Input coupling 1", EINCPL, 'h', 2),
-          ("Input coupling 2", EINCPL, 'h', 2),
-          ("Source type", ESRCTYP, 'h', 2),
-          ("Chirp percent", int, 'h', 2),
-          ("Burst percent", int, 'h', 2),
-          ("Sweep direction", ESWPDIR, 'h', 2),
-          ("Sweep mode", ESWPMOD, 'h', 2),
-          ("Ext sample freq untis", EXAXIS, 'h', 2),
-          ("Bandwidth units", EXAXIS, 'h', 2),
-          ("Log span index", int, 'h', 2),
-          ("Log start index", int, 'h', 2),
-          ("Sweep rate units", EXAXIS, 'h', 2),
-          ("Auto gain ref chan", EDEMODCH, 'h', 2),
-          ("Demod channels", EDEMODCH, 'h', 2),
-          ("Demod type chan 1", EDEMOD, 'h', 2),
-          ("Demod type chan 2", EDEMOD, 'h', 2),
-          ("Source level units", EXAXIS, 'h', 2),
-          ("Source offset units", EXAXIS, 'h', 2),
-          ("Trigger level units", EXAXIS, 'h', 2),
-          ("Capt/thru length units", EXAXIS, 'h', 2),
-          ("EU label 1", str, 's', 6),
-          ("EU label 2", str, 's', 6),
-          ("Auto carrier on/off", bool, 'h', 2),
-          ("Time average on/off", bool, 'h', 2),
-          ("Auto/fixed resolution", bool, 'h', 2),
-          ("Auto gain on/off", bool, 'h', 2),
-          ("Auto/fixed integrate",bool, 'h', 2),
-          ("Fast average on/off", bool, 'h', 2),
-          ("Overload reject on/off", bool, 'h', 2),
-          ("Chan 1 float/ground", bool, 'h', 2),
-          ("Chan 2 float/ground", bool, 'h', 2),
-          ("Time throughput on/off", bool, 'h', 2),
-          ("Demodulation on/off", bool, 'h', 2),
-          ("EU/volts chan 1", bool, 'h', 2),
-          ("EU/volts chan 2", bool, 'h', 2),
-          ("Manual/auto arm", bool, 'h', 2),
-          ("Demod preview on/off", bool, 'h', 2),
-          ("Delete freq on/off", bool, 'h', 2),
-          ("Lin res Fstart pegged", bool, 'h', 2),
-          ("Swept Fstart pegged", bool, 'h', 2),
-          ("Force length chan 1", decode_float, None, 4),
-          ("Force length chan 2", decode_float, None, 4),
-          ("Expon time constant 1", decode_float, None, 4),
-          ("Expon time constant 2", decode_float, None, 4),
-          ("Sweep time", decode_float, None, 4),
-          ("Sweep rate", decode_float, None, 4),
-          ("Sweep resolution", decode_float, None, 4),
-          ("Sweep integrate time", decode_float, None, 4),
-          ("Auto gain level", decode_float, None, 4),
-          ("Auto gain limit", decode_float, None, 4),
-          ("Source level", decode_float, None, 4),
-          ("EU value chan 1", decode_float, None, 4),
-          ("EU value chan 2", decode_float, None, 4),
-          ("Trigger delay chan 1", decode_float, None, 4),
-          ("Trigger delay chan 2", decode_float, None, 4),
-          ("Integrate var thresh", decode_float, None, 4),
-          ("Capt/thru length", decode_float, None, 4),
-          ("Frequency span", decode_float, None, 4),
-          ("Time record length", decode_float, None, 4),
-          ("Frequency resolution", decode_float, None, 4),
-          ("Time resolution", decode_float, None, 4),
-          ("External sample rate", decode_float, None, 4),
-          ("Sample rate (actual)", decode_float, None, 4),
-          ("Range channel 1", decode_float, None, 4),
-          ("Range channel 2", decode_float, None, 4),
-          ("Preview time", decode_float, None, 4),
-          ("Trigger level", decode_float, None, 4),
-          ("Source dc offset", decode_float, None, 4),
-          ("Fixed sine frequency", decode_float, None, 8),
-          ("Start frequency", decode_float, None, 8),
-          ("Center frequency", decode_float, None, 8),
-          ("Sweep start", decode_float, None, 8),
-          ("Sweep end", decode_float, None, 8),
-          ("Carrier frequency", decode_float, None, 8),
-          ]
-          
-def decode_state(data):
-    """
-    Decode the data (as generated by the HP3562A DSA in response to a
-    "DSBN" command), and returns a dict (header)
-
-    header is the dictionnary of the header of the dumped data block,
-    """
-    header, idx = decode_header(data, HEADER)
-    return header
-    
-
-def main():
-    import sys
-    import optparse
-    opt = optparse.OptionParser("A simple tool for tracing a dumped trace")
-    opt.add_option('-f', '--filename', default=None,
-                   dest='filename',
-                   help='Output filename. If not set, read from stdin')
-    opt.add_option('-m', '--mode', default='binary',
-                   dest='mode',
-                   help='Dumping mode (may be "binary" [default], "ascii" or "ansi")',
-                   )
-    
-    options, argv = opt.parse_args(sys.argv)
-
-
-    if options.filename is None:
-        print "Can't deal stdin for now..."
-        sys.exit(1)
-    #try:
-    if 1:
-        header = decode_state(open(options.filename, 'rb').read())
-    else:
-    #except Exception, e:
-        print "ERROR: can't read %s an interpret it as a HP3562 trace"%options.filename
-        print e
-        sys.exit(1)
-
-    print format_header(header, HEADER, 100)
-    
-if __name__ == "__main__":
-    main()
-          
--- a/HP3562A/trace_decoder.py	Mon Feb 04 19:49:48 2008 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,139 +0,0 @@
-# -*- coding: utf-8 -*-
-"""
-trace_decoder
-=============
-
-Module for decoding a trace generated by the HP3562A DSA, using the
-GPIB command "DDBN" (Dump Data BiNary).
-
-This file can be exectued as a python script. Use '-h' for more informations. 
-"""
-import struct
-import numpy
-from HP3562A import format_header, decode_float, decode_string, decode_header, read_trace
-from HP3562A.enum_types import *
-
-
-HEADER = [ ("Display function", EDSP, 'h', 2),
-           ('Number of elements', int, 'h', 2),
-           ('Displayed elements', int, 'h', 2),
-           ('Number of averages', int, 'h', 2),
-           ('Channel selection', ECH, 'h', 2),
-           ('Overflow status', EOVR, 'h', 2),
-           ('Overlap percentage', int, 'h', 2),
-           ('Domain', EDOM, 'h', 2),
-           ('Volts peak/rms', EVLT, 'h', 2),
-           ('Amplitude units', EAMP, 'h', 2),
-           ('X axis units', EXAXIS, 'h', 2),
-           ('Auto math label', str, 's', 14),
-           ('Trace label', str, 's', 22),
-           ('EU label 1', str, 's', 6),
-           ('EU label 2', str, 's', 6),
-           ('Float/Interger', bool, 'h', 2),
-           ('Complex/Real', bool, 'h', 2),
-           ('Live/Recalled', bool, 'h', 2),
-           ('Math result', bool, 'h', 2),
-           ('Real/Complex input', bool, 'h', 2),
-           ('Log/Linear data', bool, 'h', 2),
-           ('Auto math', bool, 'h', 2),
-           ('Real time status', bool, 'h', 2),
-           ('Measurement mode', EMEAS, 'h', 2),
-           ('Window', EWIN, 'h', 2),
-           ('Demod type channel 1', EDEMOD, 'h', 2),
-           ('Demod type channel 2', EDEMOD, 'h', 2),
-           ('Demod active channel 1', bool, 'h', 2),
-           ('Demod active channel 2', bool, 'h', 2),
-           ('Average status', EAVG, 'h', 2),
-           ('Not used', int, 'hh', 4),
-           ('Samp freq/2 (real)', decode_float, None, 4),
-           ('Samp freq/2 (imag)', decode_float, None, 4),
-           ('Not used', decode_float, None, 4),
-           ('Delta X-axis', decode_float, None, 4),
-           ('Max range', decode_float, None, 4),
-           ('Start time value', decode_float, None, 4),
-           ('Expon wind const 1', decode_float, None, 4),
-           ('Expon wind const 2', decode_float, None, 4),
-           ('EU value chan 1', decode_float, None, 4),
-           ('EU value chan 2', decode_float, None, 4),
-           ('Trig delay chan 1', decode_float, None, 4),
-           ('Trig delay chan 2', decode_float, None, 4),
-           ('Start freq value', decode_float, None, 8),
-           ('Start data value', decode_float, None, 8),
-           ]
-
-def decode_trace(data, idx=0):
-    """
-    Decode the data (as generated by the HP3562A DSA in response to a
-    "DDBN" command), and returns a couple (header, values).
-
-    header is the dictionnary of the header of the dumped data block,
-    value is a numpy array holding the trace (vector of float or
-    complex values).
-    """
-    header, idx = decode_header(data, HEADER, idx)
-    return header, read_trace(data, idx, header["Number of elements"])
-
-def main():
-    import sys
-    import optparse
-    opt = optparse.OptionParser("A simple tool for tracing a dumped trace")
-    opt.add_option('-f', '--filename', default=None,
-                   dest='filename',
-                   help='Output filename. If not set, read from stdin')
-    opt.add_option('-m', '--mode', default='binary',
-                   dest='mode',
-                   help='Dumping mode (may be "binary" [default], "ascii" or "ansi")',
-                   )
-    opt.add_option('-d', '--display-header', default=False,
-                   action="store_true",
-                   dest="displayheader",
-                   help="Display the trace header")
-    opt.add_option('-P', '--noplot-trace', default=True,
-                   action="store_false",
-                   dest="plot",
-                   help="Do not display the plot of the trace")
-    opt.add_option('-x', '--xmode', default='lin',
-                   dest='xmode',
-                   help='X coordinate mode (may be "lin" [default] or "log")')
-    opt.add_option('-y', '--ymode', default='lin',
-                   dest='ymode',
-                   help='Y coordinate mode (may be "lin" [default], "log" or "db")')
-    
-    options, argv = opt.parse_args(sys.argv)
-
-
-    if options.filename is None:
-        print "Can't deal stdin for now..."
-        sys.exit(1)
-    try:
-        header, data = decode_trace(open(options.filename, 'rb').read())
-    except Exception, e:
-        print "ERROR: can't read %s an interpret it as a HP3562 trace"%options.filename
-        print e
-        sys.exit(1)
-
-    if options.displayheader:
-        print format_header(header, HEADER, 100)
-    if options.plot:
-        f0 = header['Start freq value']
-        dx = header['Delta X-axis']
-        n = header['Number of elements']
-        x = numpy.linspace(f0, f0+dx*n, len(data)) 
-        y = data.copy()
-
-        import pylab
-        if options.ymode != "lin":
-            minv = min(y[y>0])
-            y[y==0] = minv
-            y = numpy.log10(y)
-        if options.ymode == "db":
-            y = y*10
-            pylab.ylabel('db')
-        pylab.grid()
-        pylab.plot(x, y)
-        pylab.xlabel('frequency')
-        pylab.show()
-    
-          
-if __name__ == "__main__":
-    main()
--- a/bin/dump_datablock	Mon Feb 04 19:49:48 2008 +0100
+++ b/bin/dump_datablock	Tue Feb 05 18:59:29 2008 +0100
@@ -1,4 +1,9 @@
 #!/usr/bin/python
 
-from HP3562A.dump_datablock import main
+import sys, os
+try:
+    from pygpibtoolkit.HP3562A.dump_datablock import main
+except ImportError:
+    sys.path.append(os.path.join(os.path.dirname(os.path.abspath(__file__)), ".."))
+    from pygpibtoolkit.HP3562A.dump_datablock import main
 main()
--- a/bin/qgpibplotter	Mon Feb 04 19:49:48 2008 +0100
+++ b/bin/qgpibplotter	Tue Feb 05 18:59:29 2008 +0100
@@ -1,8 +1,8 @@
 #!/usr/bin/python
 import sys, os
 try:
-    from plotter.qgpib_plotter import main
+    from pygpibtoolkit.plotter.qgpib_plotter import main
 except ImportError:
     sys.path.append(os.path.join(os.path.dirname(os.path.abspath(__file__)), ".."))
-    from plotter.qgpib_plotter import main
+    from pygpibtoolkit.plotter.qgpib_plotter import main
 main()
--- a/bin/read_coord	Mon Feb 04 19:49:48 2008 +0100
+++ b/bin/read_coord	Tue Feb 05 18:59:29 2008 +0100
@@ -2,8 +2,8 @@
 
 import sys, os
 try:
-    from HP3562A.coord_decoder import main
+    from pygpibtoolkit.HP3562A.coord_decoder import main
 except ImportError:
     sys.path.append(os.path.join(os.path.dirname(os.path.abspath(__file__)), ".."))
-    from HP3562A.coord_decoder import main
+    from pygpibtoolkit.HP3562A.coord_decoder import main
 main()
--- a/bin/read_state	Mon Feb 04 19:49:48 2008 +0100
+++ b/bin/read_state	Tue Feb 05 18:59:29 2008 +0100
@@ -2,8 +2,8 @@
 
 import sys, os
 try:
-    from HP3562A.state_decoder import main
+    from pygpibtoolkit.HP3562A.state_decoder import main
 except ImportError:
     sys.path.append(os.path.join(os.path.dirname(os.path.abspath(__file__)), ".."))
-    from HP3562A.state_decoder import main
+    from pygpibtoolkit.HP3562A.state_decoder import main
 main()
--- a/bin/read_trace	Mon Feb 04 19:49:48 2008 +0100
+++ b/bin/read_trace	Tue Feb 05 18:59:29 2008 +0100
@@ -1,8 +1,8 @@
 #!/usr/bin/python
 import sys, os
 try:
-    from HP3562A.trace_decoder import main
+    from pygpibtoolkit.HP3562A.trace_decoder import main
 except ImportError:
     sys.path.append(os.path.join(os.path.dirname(os.path.abspath(__file__)), ".."))
-    from HP3562A.trace_decoder import main
+    from pygpibtoolkit.HP3562A.trace_decoder import main
 main()
--- a/plotter/gpib_plotter.py	Mon Feb 04 19:49:48 2008 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,139 +0,0 @@
-import sys, os
-import time
-import gpib
-
-import gpib
-from prologix import GPIB
-class GPIBplotter(GPIB):
-    _replies={
-        "OE": "0",
-        "OH": "0,0,10000,7500",
-        "OI": "7470A",
-        "OP": "0,0,10000,7500",
-        "OO": "0,1,0,0,0,0,0,0",
-        "OF": "40,40",
-        "OS": "24",
-        }
-    def __init__(self, device="/dev/ttyUSB0", baudrate=115200, timeout=0.1,
-                 address=5):
-        super(GPIBplotter, self).__init__(device, baudrate, timeout, address, mode=0)
-
-    def plotStarted(self):
-        pass
-
-    def load_plot(self, wait_timeout=0):
-        """
-        Make a full plot process.
-
-        'wait_timeout' is the first timeout. Same semantic as the
-        'timeout' property of a serial connection (if set to None, it
-        will block until the GPIB device actually perform a plot
-        command.)
-        """
-        res = ""
-        i=0
-        replies = self._replies.copy()
-        if wait_timeout is not None and not isinstance(wait_timeout, (float, int)):
-            raise TypeError, "wait_timeout (%s:%s) has wrong type"%(repr(wait_timeout), type(wait_timeout))
-        if wait_timeout<0:
-            raise ValueError
-        
-        self._cnx.timeout = wait_timeout
-        firstloop = True
-        newdata = False
-        while i<self._retries:
-            l = self._cnx.readline().strip()
-            if firstloop:
-                self._cnx.timeout = self._timeout
-                firstloop = False
-                self.plotStarted()
-            if l == "":
-                if i == 0:# > (self._retries/2):
-                    # ie. we just received new stuffs (i is reset in the else block)
-                    for k, v in replies.items():
-                        # check wether we should reply smthg
-                        eres = res.replace('\n', '').strip()
-                        if eres.endswith(k) or eres.endswith(k+';') or eres.endswith(k+';OE'):
-                            self._cnx.write("%s"%v)
-                            if k == "OS":
-                                replies[k] = "16"
-                            break
-                    self._cnx.write('\r')
-                    #time.sleep(0.1)
-                i += 1
-            else:
-                if not res:
-                    print "Plotting..."
-                res += l + '\n'
-                i = 0
-                #time.sleep(0.1)
-        if res:
-            print "DONE (received %d characters)"%len(res)
-        return res
-
-if __name__ == '__main__':
-    import optparse
-    opt = optparse.OptionParser('A simple HP7470A GPIB plotter emulator for USB-GPIB bundle (ProLogix)')
-    opt.add_option('-f', '--filename', default=None,
-                   dest='filename',
-                   help='Output filename. If not set, write to stdout')
-    opt.add_option('-d', '--device', default='/dev/ttyUSB0',
-                   dest='device',
-                   help='Device of the RS232 connection (default: /dev/ttyUSB0)',
-                   )
-    opt.add_option('-a', '--address', default=0,
-                   dest='address',
-                   help='GPIB address of the device',
-                   )
-    opt.add_option('-l', '--loop', default=False,
-                   action="store_true",
-                   dest="loop",
-                   help="Continuously wait for new plots. If set, filename must be set and files will be created with _n at the end")
-    opt.add_option('-v', '--verbose', default=False,
-                   action="store_true",
-                   dest="verbose",
-                   help="Verbose mode",)
-    
-    options, argv = opt.parse_args(sys.argv)
-
-    if options.loop and not options.filename:
-        opt.error('If loop is set, you *must* provide a filename')
-
-    if options.filename:        
-        outf = open(options.filename, "w")
-    else:
-        outf = sys.stdout
-
-
-    try:
-        plotter = GPIBplotter(device=options.device, address=int(options.address),
-                              timeout=0.06)
-    except (gpib.SerialException, gpib.ConnectionError), e:
-        sys.stderr.write('Connection error:\n\t' + '\n\t'.join([str(x) for x in e.args]) + '\n')
-        sys.stderr.write('Check your parameters\n')
-        sys.exit(1)
-    if options.verbose:
-        sys.stderr.write('connection established\n')
-
-    loop = True
-    nloop = 0
-    while loop:
-        plot = plotter.load_plot(wait_timeout=0.1)
-        if options.verbose:
-            sys.stderr.write('.')
-        if plot:
-            outf.write(plot)
-            if options.verbose:
-                sys.stderr.write('\n')
-            sys.stderr.write('Received a new plot (written to %s)\n'%outf.name) 
-            if not options.loop:
-                loop = False
-            else:
-                nloop += 1
-                fname, ext = os.path.splitext(options.filename)
-                outf = open(fname + "_%d"%nloop + ext, 'w')
-                
-        
-    
-
-
--- a/plotter/gpib_plotter_mockup.py	Mon Feb 04 19:49:48 2008 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,35 +0,0 @@
-import glob
-import os
-import time
-import random
-
-class GPIBplotter:#(GPIB):
-    """
-    A mockup thet will find in a directory some HPGL files and feed them randomly
-    """
-    def __init__(self, device="/dev/ttyUSB0", baudrate=115200, timeout=0.1,
-                 address=5):
-        self._timeout = timeout
-        self.filenames = glob.glob('examples/*.plt')
-        self._next = random.randint(10,50)
-        self._num = 0
-
-    def plotStarted(self):
-        pass
-        
-    def load_plot(self, wait_timeout=0):
-        if wait_timeout:
-            time.sleep(wait_timeout)
-        self._num += 1
-        if self._num > self._next:
-            ret = open(random.choice(self.filenames)).read()
-            if len(ret)>0:
-                self.plotStarted()
-                self._num = 0
-                self._next = random.randint(10,100)
-                time.sleep(random.randint(1,3))
-                return ret
-            return None
-        return None
-    
-        
--- a/plotter/hpgl_mpl.py	Mon Feb 04 19:49:48 2008 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,26 +0,0 @@
-# -*- coding: utf-8 -*-
-import numpy
-import pylab
-
-from hpgl_parser import HPGLParser
-
-class HPGLmplPlotter(HPGLParser):
-    pens = "krbgcmyw"
-    lines = ['-', ':', '--', '-.', '.', '-', '-', '-']
-    def __init__(self, data):        
-        super(HPGLmplPlotter, self).__init__(data)
-        pylab.show()
-        
-    def plot_symbols(self, points):
-        x, y = points.T
-        pylab.plot(x, y, 'o')
-
-    def plot_lines(self, points):
-        x, y = points.T
-        pylab.plot(x, y, self.pens[self.pen]+self.lines[self.line_type])
-        
-if __name__ == "__main__":
-    import sys
-    data = open(sys.argv[1]).read()
-    HPGLmplPlotter(data)
-    
--- a/plotter/hpgl_parser.py	Mon Feb 04 19:49:48 2008 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,451 +0,0 @@
-# -*- coding: utf-8 -*-
-
-import re
-import numpy
-
-vsplitter = re.compile('[ ,]')
-vextractor = re.compile('(?P<value>[^;\n\r\aA-DF-Za-df-z]*?)(?P<terminator>[;\n\r\a]+)', re.S+re.M) 
-
-class HPGLParser(object):
-    def __init__(self, data=None):
-        self.str_terminator = chr(0x03)
-        self.IN()
-        if data:
-            self.parse(data)
-
-    def parse(self, data):
-        self.data = data
-        self.idx = 0
-        self.IN()        
-        while self.idx<len(data):
-            while data[self.idx] in [';','\n','\r', '\a', ' ']:
-                self.idx += 1
-            if data[self.idx] == chr(0x03):
-                self.ESC()
-            else:
-                cmd = data[self.idx: self.idx+2].upper()
-                self.idx += 2
-                getattr(self, cmd)()
-            while self.idx<len(data) and data[self.idx] in [';','\n','\r', '\a', ' ']:
-                self.idx += 1
-
-    def user_to_abs(self, pos):
-        """
-        converts a position (x, y) given in user units to absolute
-        units
-        """
-        return pos #TODO
-        
-    def extract_value(self, raw=False):
-        m = vextractor.match(self.data[self.idx:])
-        if m:
-            val = m.group("value")
-            self.idx = self.idx + len(val) + len(m.group("terminator"))
-            val = vsplitter.split(val)
-            if not raw:
-                val = [eval(x) for x in val if x.strip()]
-            return val
-        return []
-
-    def extract_string(self):
-        idx2 = self.data.find(self.str_terminator, self.idx)
-        val = self.data[self.idx: idx2]
-        self.idx = idx2+1
-        return val
-
-    def polyline(self, values):
-        if (len(values)%2) == 1:
-            # this is a syntax error in the HPGL data
-            values = values[:-1]
-        values = numpy.array(values).reshape(-1, 2)
-        # TODO use scaling            
-        # do plots 
-        values = numpy.r_[[self.pos], values] #add self.pos as 1st value
-        if self.plot_mode == 'relative':
-            values = values.cumsum(axis=0)
-        if self.symbol_mode:
-            self.plot_symbols(values[1:])
-        if self.pen_state == "down":
-            self.plot_lines(values)
-        self.pos = values[-1]
-
-    def plot_string(self, s):
-        pass
-    
-    def get_window_for_paper(self):
-        return 0,100,0,100
-    def get_scaling_points_for_paper(self):
-        return 0,100,0,100
-        
-    # effective plot methods; to be defined in subclasses (backends)
-    def plot_symbols(self, points):
-        pass
-    def plot_lines(self, points):
-        pass
-        
-    # HPGL-related methods
-    def ESC(self):
-        #print "ESC"
-        self.idx += 1
-
-    def OE(self):
-        """ Output Error """
-        pass
-        
-    def EC(self):
-        """? what's this """
-        values = self.extract_value()
-
-    def OO(self):
-        """idem"""
-        pass
-
-    def OP(self):
-        """idem"""
-        pass
-
-    def VS(self):
-        """idem"""
-        pass
-        
-        
-    def DF(self):
-        """ Default """
-        self.pen = 0
-        self.pen_width = 1 # 1/300 inch
-        self.pos = 0,0
-        self.char_set = "std"
-        self.plot_mode = 'absolute'
-        self.char_direction = 1,0
-        self.line_type = 0 # 'solid'
-        self.pattern_len = 4 #percentage
-        self.window = self.get_window_for_paper()
-        self.char_size = 0.75, 1.5 #percentages
-        self.symbol_mode = False
-        self.tick_len = 0.5, 0.5 # %
-        self.std_char_set = 0
-        self.alt_char_set = 0
-        self.selected_char_set = 0
-        self.char_slant = 0 # degrees
-        self.scale = None
-        self.str_terminator = chr(0x03)
-        self.chord_ang = 5 #degrees
-        self.fill_type = 'bidirectionnal', 1
-        self.fill_distance = 1 # %
-        self.fill_slant = 0 # degrees
-        self.pen_thickness = 0.3 # mm
-
-    def IN(self):
-        """ Initialize """
-        self.DF()
-        self.pen_state = "up"
-        self.rotation = 0 #degrees
-        self.scaling_points = self.get_scaling_points_for_paper()
-
-    def IP(self):
-        """ Input Scale Point"""
-        values = self.extract_value()
-        if len(values) == 0:
-            self.scaling_points = self.get_scaling_points_for_paper()
-        elif len(values) == 2:
-            p1x, p1y, p2x, p2y = self.scaling_points
-            dx, dy = p2x-p1x, p2y-p1y
-            x, y = values
-            self.scaling = (x, y, x+dx, y+dy)
-        elif len(values) == 4:
-            self.values = tuple(values)
-            
-    def SC(self):
-        """ Scale """
-        values = self.extract_value()
-        if len(values) == 4:
-            self.scale = tuple(values)
-        else:
-            self.scale = None
-
-    def IW(self):
-        values = self.extract_value()
-        if len(values) == 0:
-            self.window = self.get_window_for_paper()
-        elif len(value) == 4:            
-            self.window = tuple(values)
-
-    def RO(self):
-        values = self.extract_value()
-        if len(values) == 0:
-            self.rotation = 0
-        elif len(values) == 1:
-            self.rotation = values[0]
-
-    def PG(self):
-        pass
-
-    def PU(self):
-        """ Pen Up"""
-        self.pen_state = "up"        
-        values = self.extract_value()
-        self.polyline(values)
-
-    def PD(self):
-        """ Pen Down """
-        self.pen_state = "down"        
-        values = self.extract_value()
-        self.polyline(values)
-
-    def PA(self):
-        """ Plot Absolute """
-        self.plot_mode = "absolute"        
-        values = self.extract_value()
-        self.polyline(values)
-
-    def PR(self):
-        """ Plot Relative """
-        self.plot_mode = "relative"        
-        values = self.extract_value()
-        self.polyline(values)
-
-    def AA(self):
-        """ Arc Absolute """
-        values = self.extract_value()
-        if len(values) in [3, 4]:
-            x, y, qc = values[:3]
-            if len(values)==4:
-                qd = values[-1]
-            else:
-                qd = self.chord_ang
-            # TODO : plot arc
-            print "plotting an arc"
-    def AR(self):
-        """ Arc Relative """
-        values = self.extract_value()
-        # TODO
-
-    def CI(self):
-        """ Circle Plot"""
-        values = self.extract_value()
-        # TODO
-
-    def EA(self):
-        """Edge Rectangle Absolute"""
-        values = self.extract_value()
-        # TODO
-
-    def ER(self):
-        """Edge Rectangle Relative"""
-        values = self.extract_value()
-        # TODO
-
-    def EW(self):
-        """ Edge Wedge """
-        values = self.extract_value()
-        # TODO
-
-    def RA(self):
-        """ Fill Rectangle Absolute """
-        values = self.extract_value()
-        # TODO
-
-    def RR(self):
-        """ Fill Rectangle Relative """
-        values = self.extract_value()
-        # TODO
-
-    def WG(self):
-        """ Fill Wedge """
-        values = self.extract_value()
-        # TODO
-
-    def FT(self):
-        """ Fill Type """
-        values = self.extract_value()
-        # TODO
-
-    def LT(self):
-        """ Line Type """
-        values = self.extract_value()
-
-        if len(values)==0:
-            self.line_type = 0 #'solid'
-        else:
-            self.line_type = values[0]
-            if len(values)>1:
-                self.pattern_len = values[1]
-
-    def PW(self):
-        """ Pen Width """
-        values = self.extract_value()
-        if len(values) == 1:
-            self.pen_thickness = values[0]
-
-    def SM(self):
-        """ Symbol Mode """
-        values = self.extract_value()
-        if len(values) == 0:
-            self.symbol_mode = False
-        elif len(values) == 1:
-            self.symbol_mode = values[0]
-
-    def SP(self):
-        """ Select Pen """
-        values = self.extract_value()
-        if len(values) == 1:
-            self.pen = values[0]
-
-    def TL(self):
-        """ Tick Len """
-        values = self.extract_value()
-        # TODO
-
-    def XT(self):
-        """ X-axis Tick """
-        # TODO
-        print "X ticks"
-
-    def YT(self):
-        """ X-axis Tick """
-        # TODO
-        print "Y ticks"
-
-    def PT(self):
-        """ Pen Thickness Select """
-        values = self.extract_value()
-        if len(values) == 0:
-            self.pen_thickness = 0.3
-        elif len(values) == 1:
-            self.pen_thickness = values[0]
-
-    def CS(self):
-        """ Standard Character Set """
-        values = self.extract_value()
-        if len(values) == 0:
-            self.std_char_set = 0
-        elif len(values) == 1:
-            self.std_char_set = values[0]
-
-    def CA(self):
-        """ Alternate Character Set """
-        values = self.extract_value()
-        if len(values) == 0:
-            self.alt_char_set = 0
-        elif len(values) == 1:
-            self.alt_char_set = values[0]
-        
-    def SS(self):
-        """ Select Standard Character Set """
-        self.char_set = "std"
-
-    def SA(self):
-        """ Select Alternate Character Set """
-        self.char_set = "alt"
-
-    def DT(self):
-        """ Define Label Terminator """
-        values = self.extract_value(raw=True)
-        if len(values) == 0:
-            self.str_terminator = chr(0x03)
-        elif len(values) == 1:
-            self.str_terminator = values[0]
-
-    def LB(self):
-        """ Character Plot """
-        values = self.extract_string()
-        self.plot_string(values)
-        x, y = self.pos
-        values = values.split('\n')
-        if self.char_size == "absolute":
-            x += len(values[-1]) * self.char_width *1016/2.54
-            y += (len(values)-1) * self.char_height *1016/2.54
-        else:
-            x0, x1, y0, y1 = self.scale
-            dx = x1-x0
-            dy = y1-y0
-            x += len(values[-1]) * self.char_width / 100.0 * dx
-            y += (len(values)-1) * self.char_height / 100.0 * dy
-            
-        #print "LB pos[%s] %s -> %s"%(repr(values), self.pos, (x,y))
-        self.pos = [x, y]
-
-    def get_char_size(self):
-        if self.char_size == "absolute":
-            x = self.char_width *1016/2.54
-            y = self.char_height *1016/2.54
-        else:
-            x0, x1, y0, y1 = self.scale
-            dx = x1-x0
-            dy = y1-y0
-            x = self.char_width / 100.0 * dx
-            y = self.char_height / 100.0 * dy
-        return x, y
-    
-    def DI(self):
-        """ Absolute Direction """
-        values = self.extract_value()
-        if len(values) == 0:
-            self.char_direction = 1.0, 0.0
-        elif len(values) == 2:
-            self.char_direction = values
-
-    def DR(self):
-        """ Relative Direction """
-        values = self.extract_value()
-        if len(values) == 0:
-            self.char_direction = 1.0, 0.0
-        elif len(values) == 2:
-            # TODO : compute as percentages
-            self.char_direction = values
-
-    def CP(self):
-        """ Character Plot """
-        values = self.extract_value()
-        # TODO
-        if len(values) == 0:
-            values = 0, 1
-        x, y = self.pos
-        if self.char_size == "absolute":
-            x += values[0] * self.char_width *1016/2.54
-            y += values[1] * self.char_height *1016/2.54
-        else:
-            x0, x1, y0, y1 = self.scale
-            dx = x1-x0
-            dy = y1-y0
-            x += values[0] * self.char_width / 100.0 * dx
-            y += values[1] * self.char_height / 100.0 * dy
-        #print "CB pos[%s] %s -> %s"%(repr(values), self.pos, (x,y))
-        self.pos = [x, y]
-
-    def SI(self):
-        """ Set Absolute Character Size """
-        values = self.extract_value()
-        self.char_size = "absolute"
-        if len(values) == 0:
-            self.char_width = 0.1879 # cm
-            self.char_height = 0.2690 # cm
-        elif len(values) == 2:
-            self.char_width, self.char_height = values
-
-    def SR(self):
-        """ Set Relative Character Size """
-        values = self.extract_value()
-        self.char_size = "relative"
-        if len(values) == 0:
-            self.char_width = 0.75 # percentage
-            self.char_height = 1.5 # id
-        elif len(values) == 2:
-            self.char_width, self.char_height = values
-        
-    def SL(self):
-        """ Character Slant """        
-        values = self.extract_value()
-        # TODO
-
-    def UC(self):
-        """ User Defined Character """
-        values = self.extract_value()
-        # TODO
-        
-if __name__ == '__main__':
-    import sys
-    data = open(sys.argv[1]).read()
-    
-    p = HPGLParser(data)
-    
--- a/plotter/hpgl_plotter_rc.py	Mon Feb 04 19:49:48 2008 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1318 +0,0 @@
-# -*- coding: utf-8 -*-
-
-# Resource object code
-#
-# Created: sam. janv. 26 11:14:20 2008
-#      by: The Resource Compiler for PyQt (Qt v4.3.2)
-#
-# WARNING! All changes made in this file will be lost!
-
-from PyQt4 import QtCore
-
-qt_resource_data = "\
-\x00\x00\x14\x97\
-\x3c\
-\x3f\x78\x6d\x6c\x20\x76\x65\x72\x73\x69\x6f\x6e\x3d\x22\x31\x2e\
-\x30\x22\x20\x65\x6e\x63\x6f\x64\x69\x6e\x67\x3d\x22\x55\x54\x46\
-\x2d\x38\x22\x20\x73\x74\x61\x6e\x64\x61\x6c\x6f\x6e\x65\x3d\x22\
-\x6e\x6f\x22\x3f\x3e\x0a\x3c\x21\x2d\x2d\x20\x43\x72\x65\x61\x74\
-\x65\x64\x20\x77\x69\x74\x68\x20\x49\x6e\x6b\x73\x63\x61\x70\x65\
-\x20\x28\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\x77\x2e\x69\x6e\x6b\
-\x73\x63\x61\x70\x65\x2e\x6f\x72\x67\x2f\x29\x20\x2d\x2d\x3e\x0a\
-\x3c\x73\x76\x67\x0a\x20\x20\x20\x78\x6d\x6c\x6e\x73\x3a\x64\x63\
-\x3d\x22\x68\x74\x74\x70\x3a\x2f\x2f\x70\x75\x72\x6c\x2e\x6f\x72\
-\x67\x2f\x64\x63\x2f\x65\x6c\x65\x6d\x65\x6e\x74\x73\x2f\x31\x2e\
-\x31\x2f\x22\x0a\x20\x20\x20\x78\x6d\x6c\x6e\x73\x3a\x63\x63\x3d\
-\x22\x68\x74\x74\x70\x3a\x2f\x2f\x77\x65\x62\x2e\x72\x65\x73\x6f\
-\x75\x72\x63\x65\x2e\x6f\x72\x67\x2f\x63\x63\x2f\x22\x0a\x20\x20\
-\x20\x78\x6d\x6c\x6e\x73\x3a\x72\x64\x66\x3d\x22\x68\x74\x74\x70\
-\x3a\x2f\x2f\x77\x77\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x31\x39\
-\x39\x39\x2f\x30\x32\x2f\x32\x32\x2d\x72\x64\x66\x2d\x73\x79\x6e\
-\x74\x61\x78\x2d\x6e\x73\x23\x22\x0a\x20\x20\x20\x78\x6d\x6c\x6e\
-\x73\x3a\x73\x76\x67\x3d\x22\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\
-\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x32\x30\x30\x30\x2f\x73\x76\
-\x67\x22\x0a\x20\x20\x20\x78\x6d\x6c\x6e\x73\x3d\x22\x68\x74\x74\
-\x70\x3a\x2f\x2f\x77\x77\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x32\
-\x30\x30\x30\x2f\x73\x76\x67\x22\x0a\x20\x20\x20\x78\x6d\x6c\x6e\
-\x73\x3a\x78\x6c\x69\x6e\x6b\x3d\x22\x68\x74\x74\x70\x3a\x2f\x2f\
-\x77\x77\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x31\x39\x39\x39\x2f\
-\x78\x6c\x69\x6e\x6b\x22\x0a\x20\x20\x20\x78\x6d\x6c\x6e\x73\x3a\
-\x73\x6f\x64\x69\x70\x6f\x64\x69\x3d\x22\x68\x74\x74\x70\x3a\x2f\
-\x2f\x73\x6f\x64\x69\x70\x6f\x64\x69\x2e\x73\x6f\x75\x72\x63\x65\
-\x66\x6f\x72\x67\x65\x2e\x6e\x65\x74\x2f\x44\x54\x44\x2f\x73\x6f\
-\x64\x69\x70\x6f\x64\x69\x2d\x30\x2e\x64\x74\x64\x22\x0a\x20\x20\
-\x20\x78\x6d\x6c\x6e\x73\x3a\x69\x6e\x6b\x73\x63\x61\x70\x65\x3d\
-\x22\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\x77\x2e\x69\x6e\x6b\x73\
-\x63\x61\x70\x65\x2e\x6f\x72\x67\x2f\x6e\x61\x6d\x65\x73\x70\x61\
-\x63\x65\x73\x2f\x69\x6e\x6b\x73\x63\x61\x70\x65\x22\x0a\x20\x20\
-\x20\x77\x69\x64\x74\x68\x3d\x22\x32\x37\x38\x2e\x32\x35\x32\x35\
-\x22\x0a\x20\x20\x20\x68\x65\x69\x67\x68\x74\x3d\x22\x32\x37\x38\
-\x2e\x32\x35\x32\x35\x22\x0a\x20\x20\x20\x69\x64\x3d\x22\x73\x76\
-\x67\x32\x22\x0a\x20\x20\x20\x73\x6f\x64\x69\x70\x6f\x64\x69\x3a\
-\x76\x65\x72\x73\x69\x6f\x6e\x3d\x22\x30\x2e\x33\x32\x22\x0a\x20\
-\x20\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x76\x65\x72\x73\x69\
-\x6f\x6e\x3d\x22\x30\x2e\x34\x35\x2e\x31\x22\x0a\x20\x20\x20\x73\
-\x6f\x64\x69\x70\x6f\x64\x69\x3a\x64\x6f\x63\x62\x61\x73\x65\x3d\
-\x22\x2f\x68\x6f\x6d\x65\x2f\x64\x61\x76\x69\x64\x2f\x45\x6c\x65\
-\x63\x74\x72\x6f\x6e\x69\x63\x2f\x48\x50\x33\x35\x36\x32\x2f\x69\
-\x63\x6f\x6e\x73\x22\x0a\x20\x20\x20\x73\x6f\x64\x69\x70\x6f\x64\
-\x69\x3a\x64\x6f\x63\x6e\x61\x6d\x65\x3d\x22\x6c\x65\x64\x5f\x72\
-\x65\x64\x5f\x6f\x66\x66\x2e\x73\x76\x67\x22\x0a\x20\x20\x20\x69\
-\x6e\x6b\x73\x63\x61\x70\x65\x3a\x6f\x75\x74\x70\x75\x74\x5f\x65\
-\x78\x74\x65\x6e\x73\x69\x6f\x6e\x3d\x22\x6f\x72\x67\x2e\x69\x6e\
-\x6b\x73\x63\x61\x70\x65\x2e\x6f\x75\x74\x70\x75\x74\x2e\x73\x76\
-\x67\x2e\x69\x6e\x6b\x73\x63\x61\x70\x65\x22\x0a\x20\x20\x20\x76\
-\x65\x72\x73\x69\x6f\x6e\x3d\x22\x31\x2e\x30\x22\x3e\x0a\x20\x20\
-\x3c\x64\x65\x66\x73\x0a\x20\x20\x20\x20\x20\x69\x64\x3d\x22\x64\
-\x65\x66\x73\x34\x22\x3e\x0a\x20\x20\x20\x20\x3c\x6c\x69\x6e\x65\
-\x61\x72\x47\x72\x61\x64\x69\x65\x6e\x74\x0a\x20\x20\x20\x20\x20\
-\x20\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x63\x6f\x6c\x6c\x65\
-\x63\x74\x3d\x22\x61\x6c\x77\x61\x79\x73\x22\x0a\x20\x20\x20\x20\
-\x20\x20\x20\x69\x64\x3d\x22\x6c\x69\x6e\x65\x61\x72\x47\x72\x61\
-\x64\x69\x65\x6e\x74\x34\x31\x31\x37\x22\x3e\x0a\x20\x20\x20\x20\
-\x20\x20\x3c\x73\x74\x6f\x70\x0a\x20\x20\x20\x20\x20\x20\x20\x20\
-\x20\x73\x74\x79\x6c\x65\x3d\x22\x73\x74\x6f\x70\x2d\x63\x6f\x6c\
-\x6f\x72\x3a\x23\x66\x66\x66\x66\x66\x66\x3b\x73\x74\x6f\x70\x2d\
-\x6f\x70\x61\x63\x69\x74\x79\x3a\x31\x3b\x22\x0a\x20\x20\x20\x20\
-\x20\x20\x20\x20\x20\x6f\x66\x66\x73\x65\x74\x3d\x22\x30\x22\x0a\
-\x20\x20\x20\x20\x20\x20\x20\x20\x20\x69\x64\x3d\x22\x73\x74\x6f\
-\x70\x34\x31\x31\x39\x22\x20\x2f\x3e\x0a\x20\x20\x20\x20\x20\x20\
-\x3c\x73\x74\x6f\x70\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x73\
-\x74\x79\x6c\x65\x3d\x22\x73\x74\x6f\x70\x2d\x63\x6f\x6c\x6f\x72\
-\x3a\x23\x66\x66\x66\x66\x66\x66\x3b\x73\x74\x6f\x70\x2d\x6f\x70\
-\x61\x63\x69\x74\x79\x3a\x30\x3b\x22\x0a\x20\x20\x20\x20\x20\x20\
-\x20\x20\x20\x6f\x66\x66\x73\x65\x74\x3d\x22\x31\x22\x0a\x20\x20\
-\x20\x20\x20\x20\x20\x20\x20\x69\x64\x3d\x22\x73\x74\x6f\x70\x34\
-\x31\x32\x31\x22\x20\x2f\x3e\x0a\x20\x20\x20\x20\x3c\x2f\x6c\x69\
-\x6e\x65\x61\x72\x47\x72\x61\x64\x69\x65\x6e\x74\x3e\x0a\x20\x20\
-\x20\x20\x3c\x6c\x69\x6e\x65\x61\x72\x47\x72\x61\x64\x69\x65\x6e\
-\x74\x0a\x20\x20\x20\x20\x20\x20\x20\x69\x64\x3d\x22\x6c\x69\x6e\
-\x65\x61\x72\x47\x72\x61\x64\x69\x65\x6e\x74\x33\x31\x33\x36\x22\
-\x3e\x0a\x20\x20\x20\x20\x20\x20\x3c\x73\x74\x6f\x70\x0a\x20\x20\
-\x20\x20\x20\x20\x20\x20\x20\x73\x74\x79\x6c\x65\x3d\x22\x73\x74\
-\x6f\x70\x2d\x63\x6f\x6c\x6f\x72\x3a\x23\x66\x66\x66\x66\x66\x66\
-\x3b\x73\x74\x6f\x70\x2d\x6f\x70\x61\x63\x69\x74\x79\x3a\x31\x3b\
-\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x6f\x66\x66\x73\x65\
-\x74\x3d\x22\x30\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x69\
-\x64\x3d\x22\x73\x74\x6f\x70\x33\x31\x33\x38\x22\x20\x2f\x3e\x0a\
-\x20\x20\x20\x20\x20\x20\x3c\x73\x74\x6f\x70\x0a\x20\x20\x20\x20\
-\x20\x20\x20\x20\x20\x73\x74\x79\x6c\x65\x3d\x22\x73\x74\x6f\x70\
-\x2d\x63\x6f\x6c\x6f\x72\x3a\x23\x61\x61\x30\x30\x30\x30\x3b\x73\
-\x74\x6f\x70\x2d\x6f\x70\x61\x63\x69\x74\x79\x3a\x30\x3b\x22\x0a\
-\x20\x20\x20\x20\x20\x20\x20\x20\x20\x6f\x66\x66\x73\x65\x74\x3d\
-\x22\x31\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x69\x64\x3d\
-\x22\x73\x74\x6f\x70\x33\x31\x34\x30\x22\x20\x2f\x3e\x0a\x20\x20\
-\x20\x20\x3c\x2f\x6c\x69\x6e\x65\x61\x72\x47\x72\x61\x64\x69\x65\
-\x6e\x74\x3e\x0a\x20\x20\x20\x20\x3c\x72\x61\x64\x69\x61\x6c\x47\
-\x72\x61\x64\x69\x65\x6e\x74\x0a\x20\x20\x20\x20\x20\x20\x20\x69\
-\x6e\x6b\x73\x63\x61\x70\x65\x3a\x63\x6f\x6c\x6c\x65\x63\x74\x3d\
-\x22\x61\x6c\x77\x61\x79\x73\x22\x0a\x20\x20\x20\x20\x20\x20\x20\
-\x78\x6c\x69\x6e\x6b\x3a\x68\x72\x65\x66\x3d\x22\x23\x6c\x69\x6e\
-\x65\x61\x72\x47\x72\x61\x64\x69\x65\x6e\x74\x33\x31\x33\x36\x22\
-\x0a\x20\x20\x20\x20\x20\x20\x20\x69\x64\x3d\x22\x72\x61\x64\x69\
-\x61\x6c\x47\x72\x61\x64\x69\x65\x6e\x74\x33\x31\x34\x32\x22\x0a\
-\x20\x20\x20\x20\x20\x20\x20\x63\x78\x3d\x22\x33\x32\x37\x2e\x34\
-\x31\x39\x32\x35\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x63\x79\x3d\
-\x22\x33\x34\x2e\x31\x30\x31\x39\x38\x32\x22\x0a\x20\x20\x20\x20\
-\x20\x20\x20\x66\x78\x3d\x22\x33\x32\x37\x2e\x34\x31\x39\x32\x35\
-\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x66\x79\x3d\x22\x33\x34\x2e\
-\x31\x30\x31\x39\x38\x32\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x72\
-\x3d\x22\x31\x33\x30\x2e\x31\x33\x32\x34\x22\x0a\x20\x20\x20\x20\
-\x20\x20\x20\x67\x72\x61\x64\x69\x65\x6e\x74\x55\x6e\x69\x74\x73\
-\x3d\x22\x75\x73\x65\x72\x53\x70\x61\x63\x65\x4f\x6e\x55\x73\x65\
-\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x67\x72\x61\x64\x69\x65\x6e\
-\x74\x54\x72\x61\x6e\x73\x66\x6f\x72\x6d\x3d\x22\x6d\x61\x74\x72\
-\x69\x78\x28\x32\x2e\x35\x36\x39\x35\x37\x30\x37\x65\x2d\x37\x2c\
-\x2d\x33\x2e\x32\x34\x36\x39\x38\x35\x38\x2c\x32\x2e\x32\x39\x36\
-\x32\x34\x35\x2c\x36\x2e\x38\x37\x30\x38\x39\x36\x39\x65\x2d\x36\
-\x2c\x33\x36\x36\x2e\x39\x31\x30\x34\x39\x2c\x31\x35\x30\x34\x2e\
-\x31\x38\x33\x29\x22\x20\x2f\x3e\x0a\x20\x20\x20\x20\x3c\x6c\x69\
-\x6e\x65\x61\x72\x47\x72\x61\x64\x69\x65\x6e\x74\x0a\x20\x20\x20\
-\x20\x20\x20\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x63\x6f\x6c\
-\x6c\x65\x63\x74\x3d\x22\x61\x6c\x77\x61\x79\x73\x22\x0a\x20\x20\
-\x20\x20\x20\x20\x20\x78\x6c\x69\x6e\x6b\x3a\x68\x72\x65\x66\x3d\
-\x22\x23\x6c\x69\x6e\x65\x61\x72\x47\x72\x61\x64\x69\x65\x6e\x74\
-\x34\x31\x31\x37\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x69\x64\x3d\
-\x22\x6c\x69\x6e\x65\x61\x72\x47\x72\x61\x64\x69\x65\x6e\x74\x34\
-\x31\x32\x33\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x78\x31\x3d\x22\
-\x32\x36\x30\x2e\x39\x35\x32\x34\x32\x22\x0a\x20\x20\x20\x20\x20\
-\x20\x20\x79\x31\x3d\x22\x31\x32\x31\x2e\x31\x38\x38\x34\x32\x22\
-\x0a\x20\x20\x20\x20\x20\x20\x20\x78\x32\x3d\x22\x34\x38\x38\x2e\
-\x36\x35\x39\x35\x35\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x79\x32\
-\x3d\x22\x33\x35\x31\x2e\x34\x38\x30\x36\x35\x22\x0a\x20\x20\x20\
-\x20\x20\x20\x20\x67\x72\x61\x64\x69\x65\x6e\x74\x55\x6e\x69\x74\
-\x73\x3d\x22\x75\x73\x65\x72\x53\x70\x61\x63\x65\x4f\x6e\x55\x73\
-\x65\x22\x20\x2f\x3e\x0a\x20\x20\x20\x20\x3c\x6c\x69\x6e\x65\x61\
-\x72\x47\x72\x61\x64\x69\x65\x6e\x74\x0a\x20\x20\x20\x20\x20\x20\
-\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x63\x6f\x6c\x6c\x65\x63\
-\x74\x3d\x22\x61\x6c\x77\x61\x79\x73\x22\x0a\x20\x20\x20\x20\x20\
-\x20\x20\x78\x6c\x69\x6e\x6b\x3a\x68\x72\x65\x66\x3d\x22\x23\x6c\
-\x69\x6e\x65\x61\x72\x47\x72\x61\x64\x69\x65\x6e\x74\x34\x31\x31\
-\x37\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x69\x64\x3d\x22\x6c\x69\
-\x6e\x65\x61\x72\x47\x72\x61\x64\x69\x65\x6e\x74\x34\x31\x32\x39\
-\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x67\x72\x61\x64\x69\x65\x6e\
-\x74\x55\x6e\x69\x74\x73\x3d\x22\x75\x73\x65\x72\x53\x70\x61\x63\
-\x65\x4f\x6e\x55\x73\x65\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x78\
-\x31\x3d\x22\x32\x36\x30\x2e\x39\x35\x32\x34\x32\x22\x0a\x20\x20\
-\x20\x20\x20\x20\x20\x79\x31\x3d\x22\x31\x32\x31\x2e\x31\x38\x38\
-\x34\x32\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x78\x32\x3d\x22\x34\
-\x38\x38\x2e\x36\x35\x39\x35\x35\x22\x0a\x20\x20\x20\x20\x20\x20\
-\x20\x79\x32\x3d\x22\x33\x35\x31\x2e\x34\x38\x30\x36\x35\x22\x0a\
-\x20\x20\x20\x20\x20\x20\x20\x67\x72\x61\x64\x69\x65\x6e\x74\x54\
-\x72\x61\x6e\x73\x66\x6f\x72\x6d\x3d\x22\x6d\x61\x74\x72\x69\x78\
-\x28\x31\x2e\x32\x34\x35\x37\x32\x32\x36\x2c\x30\x2c\x30\x2c\x31\
-\x2e\x32\x36\x31\x35\x38\x35\x34\x2c\x2d\x31\x37\x36\x2e\x37\x37\
-\x36\x38\x2c\x2d\x39\x30\x2e\x34\x39\x36\x35\x30\x38\x29\x22\x20\
-\x2f\x3e\x0a\x20\x20\x3c\x2f\x64\x65\x66\x73\x3e\x0a\x20\x20\x3c\
-\x73\x6f\x64\x69\x70\x6f\x64\x69\x3a\x6e\x61\x6d\x65\x64\x76\x69\
-\x65\x77\x0a\x20\x20\x20\x20\x20\x69\x64\x3d\x22\x62\x61\x73\x65\
-\x22\x0a\x20\x20\x20\x20\x20\x70\x61\x67\x65\x63\x6f\x6c\x6f\x72\
-\x3d\x22\x23\x66\x66\x66\x66\x66\x66\x22\x0a\x20\x20\x20\x20\x20\
-\x62\x6f\x72\x64\x65\x72\x63\x6f\x6c\x6f\x72\x3d\x22\x23\x36\x36\
-\x36\x36\x36\x36\x22\x0a\x20\x20\x20\x20\x20\x62\x6f\x72\x64\x65\
-\x72\x6f\x70\x61\x63\x69\x74\x79\x3d\x22\x31\x2e\x30\x22\x0a\x20\
-\x20\x20\x20\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x70\x61\x67\
-\x65\x6f\x70\x61\x63\x69\x74\x79\x3d\x22\x30\x2e\x30\x22\x0a\x20\
-\x20\x20\x20\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x70\x61\x67\
-\x65\x73\x68\x61\x64\x6f\x77\x3d\x22\x32\x22\x0a\x20\x20\x20\x20\
-\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x7a\x6f\x6f\x6d\x3d\x22\
-\x30\x2e\x39\x36\x31\x36\x34\x36\x31\x31\x22\x0a\x20\x20\x20\x20\
-\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x63\x78\x3d\x22\x33\x32\
-\x36\x2e\x33\x38\x33\x38\x32\x22\x0a\x20\x20\x20\x20\x20\x69\x6e\
-\x6b\x73\x63\x61\x70\x65\x3a\x63\x79\x3d\x22\x36\x39\x2e\x37\x31\
-\x35\x34\x39\x22\x0a\x20\x20\x20\x20\x20\x69\x6e\x6b\x73\x63\x61\
-\x70\x65\x3a\x64\x6f\x63\x75\x6d\x65\x6e\x74\x2d\x75\x6e\x69\x74\
-\x73\x3d\x22\x70\x78\x22\x0a\x20\x20\x20\x20\x20\x69\x6e\x6b\x73\
-\x63\x61\x70\x65\x3a\x63\x75\x72\x72\x65\x6e\x74\x2d\x6c\x61\x79\
-\x65\x72\x3d\x22\x6c\x61\x79\x65\x72\x31\x22\x0a\x20\x20\x20\x20\
-\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x77\x69\x6e\x64\x6f\x77\
-\x2d\x77\x69\x64\x74\x68\x3d\x22\x39\x39\x36\x22\x0a\x20\x20\x20\
-\x20\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x77\x69\x6e\x64\x6f\
-\x77\x2d\x68\x65\x69\x67\x68\x74\x3d\x22\x37\x31\x34\x22\x0a\x20\
-\x20\x20\x20\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x77\x69\x6e\
-\x64\x6f\x77\x2d\x78\x3d\x22\x31\x31\x22\x0a\x20\x20\x20\x20\x20\
-\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x77\x69\x6e\x64\x6f\x77\x2d\
-\x79\x3d\x22\x31\x33\x22\x20\x2f\x3e\x0a\x20\x20\x3c\x6d\x65\x74\
-\x61\x64\x61\x74\x61\x0a\x20\x20\x20\x20\x20\x69\x64\x3d\x22\x6d\
-\x65\x74\x61\x64\x61\x74\x61\x37\x22\x3e\x0a\x20\x20\x20\x20\x3c\
-\x72\x64\x66\x3a\x52\x44\x46\x3e\x0a\x20\x20\x20\x20\x20\x20\x3c\
-\x63\x63\x3a\x57\x6f\x72\x6b\x0a\x20\x20\x20\x20\x20\x20\x20\x20\
-\x20\x72\x64\x66\x3a\x61\x62\x6f\x75\x74\x3d\x22\x22\x3e\x0a\x20\
-\x20\x20\x20\x20\x20\x20\x20\x3c\x64\x63\x3a\x66\x6f\x72\x6d\x61\
-\x74\x3e\x69\x6d\x61\x67\x65\x2f\x73\x76\x67\x2b\x78\x6d\x6c\x3c\
-\x2f\x64\x63\x3a\x66\x6f\x72\x6d\x61\x74\x3e\x0a\x20\x20\x20\x20\
-\x20\x20\x20\x20\x3c\x64\x63\x3a\x74\x79\x70\x65\x0a\x20\x20\x20\
-\x20\x20\x20\x20\x20\x20\x20\x20\x72\x64\x66\x3a\x72\x65\x73\x6f\
-\x75\x72\x63\x65\x3d\x22\x68\x74\x74\x70\x3a\x2f\x2f\x70\x75\x72\
-\x6c\x2e\x6f\x72\x67\x2f\x64\x63\x2f\x64\x63\x6d\x69\x74\x79\x70\
-\x65\x2f\x53\x74\x69\x6c\x6c\x49\x6d\x61\x67\x65\x22\x20\x2f\x3e\
-\x0a\x20\x20\x20\x20\x20\x20\x3c\x2f\x63\x63\x3a\x57\x6f\x72\x6b\
-\x3e\x0a\x20\x20\x20\x20\x3c\x2f\x72\x64\x66\x3a\x52\x44\x46\x3e\
-\x0a\x20\x20\x3c\x2f\x6d\x65\x74\x61\x64\x61\x74\x61\x3e\x0a\x20\
-\x20\x3c\x67\x0a\x20\x20\x20\x20\x20\x69\x6e\x6b\x73\x63\x61\x70\
-\x65\x3a\x6c\x61\x62\x65\x6c\x3d\x22\x43\x61\x6c\x71\x75\x65\x20\
-\x31\x22\x0a\x20\x20\x20\x20\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\
-\x3a\x67\x72\x6f\x75\x70\x6d\x6f\x64\x65\x3d\x22\x6c\x61\x79\x65\
-\x72\x22\x0a\x20\x20\x20\x20\x20\x69\x64\x3d\x22\x6c\x61\x79\x65\
-\x72\x31\x22\x0a\x20\x20\x20\x20\x20\x74\x72\x61\x6e\x73\x66\x6f\
-\x72\x6d\x3d\x22\x74\x72\x61\x6e\x73\x6c\x61\x74\x65\x28\x2d\x31\
-\x37\x35\x2e\x39\x35\x38\x34\x37\x2c\x2d\x31\x37\x31\x2e\x37\x39\
-\x38\x39\x34\x29\x22\x3e\x0a\x20\x20\x20\x20\x3c\x72\x65\x63\x74\
-\x0a\x20\x20\x20\x20\x20\x20\x20\x79\x3d\x22\x31\x38\x30\x2e\x39\
-\x33\x39\x37\x34\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x78\x3d\x22\
-\x31\x38\x35\x2e\x30\x39\x39\x32\x37\x22\x0a\x20\x20\x20\x20\x20\
-\x20\x20\x68\x65\x69\x67\x68\x74\x3d\x22\x32\x35\x39\x2e\x39\x37\
-\x30\x38\x39\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x77\x69\x64\x74\
-\x68\x3d\x22\x32\x35\x39\x2e\x39\x37\x30\x38\x39\x22\x0a\x20\x20\
-\x20\x20\x20\x20\x20\x69\x64\x3d\x22\x72\x65\x63\x74\x33\x31\x33\
-\x34\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x73\x74\x79\x6c\x65\x3d\
-\x22\x6f\x70\x61\x63\x69\x74\x79\x3a\x31\x3b\x66\x69\x6c\x6c\x3a\
-\x75\x72\x6c\x28\x23\x72\x61\x64\x69\x61\x6c\x47\x72\x61\x64\x69\
-\x65\x6e\x74\x33\x31\x34\x32\x29\x3b\x66\x69\x6c\x6c\x2d\x6f\x70\
-\x61\x63\x69\x74\x79\x3a\x31\x3b\x66\x69\x6c\x6c\x2d\x72\x75\x6c\
-\x65\x3a\x6e\x6f\x6e\x7a\x65\x72\x6f\x3b\x73\x74\x72\x6f\x6b\x65\
-\x3a\x23\x66\x66\x66\x66\x66\x66\x3b\x73\x74\x72\x6f\x6b\x65\x2d\
-\x77\x69\x64\x74\x68\x3a\x30\x2e\x32\x39\x33\x39\x30\x36\x36\x36\
-\x3b\x73\x74\x72\x6f\x6b\x65\x2d\x6c\x69\x6e\x65\x63\x61\x70\x3a\
-\x62\x75\x74\x74\x3b\x73\x74\x72\x6f\x6b\x65\x2d\x6d\x69\x74\x65\
-\x72\x6c\x69\x6d\x69\x74\x3a\x34\x3b\x73\x74\x72\x6f\x6b\x65\x2d\
-\x64\x61\x73\x68\x61\x72\x72\x61\x79\x3a\x30\x2e\x32\x39\x33\x39\
-\x30\x36\x36\x36\x2c\x20\x30\x2e\x32\x39\x33\x39\x30\x36\x36\x36\
-\x3b\x73\x74\x72\x6f\x6b\x65\x2d\x64\x61\x73\x68\x6f\x66\x66\x73\
-\x65\x74\x3a\x30\x3b\x73\x74\x72\x6f\x6b\x65\x2d\x6f\x70\x61\x63\
-\x69\x74\x79\x3a\x31\x22\x20\x2f\x3e\x0a\x20\x20\x20\x20\x3c\x72\
-\x65\x63\x74\x0a\x20\x20\x20\x20\x20\x20\x20\x73\x74\x79\x6c\x65\
-\x3d\x22\x6f\x70\x61\x63\x69\x74\x79\x3a\x31\x3b\x66\x69\x6c\x6c\
-\x3a\x23\x61\x32\x30\x30\x30\x30\x3b\x66\x69\x6c\x6c\x2d\x6f\x70\
-\x61\x63\x69\x74\x79\x3a\x31\x3b\x66\x69\x6c\x6c\x2d\x72\x75\x6c\
-\x65\x3a\x6e\x6f\x6e\x7a\x65\x72\x6f\x3b\x73\x74\x72\x6f\x6b\x65\
-\x3a\x23\x66\x66\x66\x66\x66\x66\x3b\x73\x74\x72\x6f\x6b\x65\x2d\
-\x77\x69\x64\x74\x68\x3a\x30\x2e\x32\x39\x33\x39\x30\x36\x36\x36\
-\x3b\x73\x74\x72\x6f\x6b\x65\x2d\x6c\x69\x6e\x65\x63\x61\x70\x3a\
-\x62\x75\x74\x74\x3b\x73\x74\x72\x6f\x6b\x65\x2d\x6d\x69\x74\x65\
-\x72\x6c\x69\x6d\x69\x74\x3a\x34\x3b\x73\x74\x72\x6f\x6b\x65\x2d\
-\x64\x61\x73\x68\x61\x72\x72\x61\x79\x3a\x30\x2e\x32\x39\x33\x39\
-\x30\x36\x36\x36\x2c\x20\x30\x2e\x32\x39\x33\x39\x30\x36\x36\x36\
-\x3b\x73\x74\x72\x6f\x6b\x65\x2d\x64\x61\x73\x68\x6f\x66\x66\x73\
-\x65\x74\x3a\x30\x3b\x73\x74\x72\x6f\x6b\x65\x2d\x6f\x70\x61\x63\
-\x69\x74\x79\x3a\x31\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x69\x64\
-\x3d\x22\x72\x65\x63\x74\x32\x31\x36\x30\x22\x0a\x20\x20\x20\x20\
-\x20\x20\x20\x77\x69\x64\x74\x68\x3d\x22\x32\x35\x39\x2e\x39\x37\
-\x30\x38\x39\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x68\x65\x69\x67\
-\x68\x74\x3d\x22\x32\x35\x39\x2e\x39\x37\x30\x38\x39\x22\x0a\x20\
-\x20\x20\x20\x20\x20\x20\x78\x3d\x22\x31\x38\x35\x2e\x30\x39\x39\
-\x32\x37\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x79\x3d\x22\x31\x38\
-\x30\x2e\x39\x33\x39\x37\x34\x22\x20\x2f\x3e\x0a\x20\x20\x20\x20\
-\x3c\x72\x65\x63\x74\x0a\x20\x20\x20\x20\x20\x20\x20\x79\x3d\x22\
-\x31\x37\x36\x2e\x33\x38\x37\x34\x34\x22\x0a\x20\x20\x20\x20\x20\
-\x20\x20\x78\x3d\x22\x31\x38\x30\x2e\x35\x34\x36\x39\x37\x22\x0a\
-\x20\x20\x20\x20\x20\x20\x20\x68\x65\x69\x67\x68\x74\x3d\x22\x32\
-\x36\x39\x2e\x30\x37\x35\x35\x22\x0a\x20\x20\x20\x20\x20\x20\x20\
-\x77\x69\x64\x74\x68\x3d\x22\x32\x36\x39\x2e\x30\x37\x35\x35\x22\
-\x0a\x20\x20\x20\x20\x20\x20\x20\x69\x64\x3d\x22\x72\x65\x63\x74\
-\x32\x31\x36\x32\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x73\x74\x79\
-\x6c\x65\x3d\x22\x6f\x70\x61\x63\x69\x74\x79\x3a\x31\x3b\x66\x69\
-\x6c\x6c\x3a\x6e\x6f\x6e\x65\x3b\x66\x69\x6c\x6c\x2d\x6f\x70\x61\
-\x63\x69\x74\x79\x3a\x31\x3b\x66\x69\x6c\x6c\x2d\x72\x75\x6c\x65\
-\x3a\x6e\x6f\x6e\x7a\x65\x72\x6f\x3b\x73\x74\x72\x6f\x6b\x65\x3a\
-\x23\x39\x35\x30\x30\x30\x30\x3b\x73\x74\x72\x6f\x6b\x65\x2d\x77\
-\x69\x64\x74\x68\x3a\x39\x2e\x31\x37\x37\x30\x30\x30\x30\x35\x3b\
-\x73\x74\x72\x6f\x6b\x65\x2d\x6c\x69\x6e\x65\x63\x61\x70\x3a\x62\
-\x75\x74\x74\x3b\x73\x74\x72\x6f\x6b\x65\x2d\x6d\x69\x74\x65\x72\
-\x6c\x69\x6d\x69\x74\x3a\x34\x3b\x73\x74\x72\x6f\x6b\x65\x2d\x64\
-\x61\x73\x68\x61\x72\x72\x61\x79\x3a\x6e\x6f\x6e\x65\x3b\x73\x74\
-\x72\x6f\x6b\x65\x2d\x64\x61\x73\x68\x6f\x66\x66\x73\x65\x74\x3a\
-\x30\x3b\x73\x74\x72\x6f\x6b\x65\x2d\x6f\x70\x61\x63\x69\x74\x79\
-\x3a\x31\x22\x20\x2f\x3e\x0a\x20\x20\x20\x20\x3c\x70\x61\x74\x68\
-\x0a\x20\x20\x20\x20\x20\x20\x20\x73\x74\x79\x6c\x65\x3d\x22\x66\
-\x69\x6c\x6c\x3a\x75\x72\x6c\x28\x23\x6c\x69\x6e\x65\x61\x72\x47\
-\x72\x61\x64\x69\x65\x6e\x74\x34\x31\x32\x39\x29\x3b\x66\x69\x6c\
-\x6c\x2d\x6f\x70\x61\x63\x69\x74\x79\x3a\x31\x3b\x66\x69\x6c\x6c\
-\x2d\x72\x75\x6c\x65\x3a\x6e\x6f\x6e\x7a\x65\x72\x6f\x3b\x73\x74\
-\x72\x6f\x6b\x65\x3a\x6e\x6f\x6e\x65\x3b\x73\x74\x72\x6f\x6b\x65\
-\x2d\x77\x69\x64\x74\x68\x3a\x35\x3b\x73\x74\x72\x6f\x6b\x65\x2d\
-\x6c\x69\x6e\x65\x63\x61\x70\x3a\x62\x75\x74\x74\x3b\x73\x74\x72\
-\x6f\x6b\x65\x2d\x6d\x69\x74\x65\x72\x6c\x69\x6d\x69\x74\x3a\x34\
-\x3b\x73\x74\x72\x6f\x6b\x65\x2d\x64\x61\x73\x68\x6f\x66\x66\x73\
-\x65\x74\x3a\x30\x3b\x73\x74\x72\x6f\x6b\x65\x2d\x6f\x70\x61\x63\
-\x69\x74\x79\x3a\x31\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x64\x3d\
-\x22\x4d\x20\x31\x38\x35\x2e\x30\x39\x33\x37\x35\x2c\x31\x38\x30\
-\x2e\x39\x33\x37\x35\x20\x4c\x20\x31\x38\x35\x2e\x30\x39\x33\x37\
-\x35\x2c\x33\x35\x32\x2e\x35\x36\x32\x35\x20\x43\x20\x31\x39\x30\
-\x2e\x39\x33\x37\x35\x32\x2c\x33\x35\x32\x2e\x37\x39\x39\x38\x32\
-\x20\x31\x39\x36\x2e\x38\x33\x38\x35\x36\x2c\x33\x35\x32\x2e\x39\
-\x33\x37\x35\x20\x32\x30\x32\x2e\x37\x38\x31\x32\x35\x2c\x33\x35\
-\x32\x2e\x39\x33\x37\x35\x20\x43\x20\x33\x31\x32\x2e\x38\x30\x30\
-\x31\x34\x2c\x33\x35\x32\x2e\x39\x33\x37\x35\x20\x34\x30\x36\x2e\
-\x39\x35\x30\x34\x39\x2c\x33\x31\x31\x2e\x36\x31\x30\x34\x34\x20\
-\x34\x34\x35\x2e\x30\x36\x32\x35\x2c\x32\x35\x33\x2e\x32\x35\x20\
-\x4c\x20\x34\x34\x35\x2e\x30\x36\x32\x35\x2c\x31\x38\x30\x2e\x39\
-\x33\x37\x35\x20\x4c\x20\x31\x38\x35\x2e\x30\x39\x33\x37\x35\x2c\
-\x31\x38\x30\x2e\x39\x33\x37\x35\x20\x7a\x20\x22\x0a\x20\x20\x20\
-\x20\x20\x20\x20\x69\x64\x3d\x22\x70\x61\x74\x68\x33\x31\x34\x34\
-\x22\x20\x2f\x3e\x0a\x20\x20\x20\x20\x3c\x70\x61\x74\x68\x0a\x20\
-\x20\x20\x20\x20\x20\x20\x73\x6f\x64\x69\x70\x6f\x64\x69\x3a\x74\
-\x79\x70\x65\x3d\x22\x61\x72\x63\x22\x0a\x20\x20\x20\x20\x20\x20\
-\x20\x73\x74\x79\x6c\x65\x3d\x22\x6f\x70\x61\x63\x69\x74\x79\x3a\
-\x31\x3b\x66\x69\x6c\x6c\x3a\x6e\x6f\x6e\x65\x3b\x66\x69\x6c\x6c\
-\x2d\x6f\x70\x61\x63\x69\x74\x79\x3a\x31\x3b\x66\x69\x6c\x6c\x2d\
-\x72\x75\x6c\x65\x3a\x6e\x6f\x6e\x7a\x65\x72\x6f\x3b\x73\x74\x72\
-\x6f\x6b\x65\x3a\x23\x30\x30\x30\x30\x30\x30\x3b\x73\x74\x72\x6f\
-\x6b\x65\x2d\x77\x69\x64\x74\x68\x3a\x35\x3b\x73\x74\x72\x6f\x6b\
-\x65\x2d\x6c\x69\x6e\x65\x63\x61\x70\x3a\x62\x75\x74\x74\x3b\x73\
-\x74\x72\x6f\x6b\x65\x2d\x6d\x69\x74\x65\x72\x6c\x69\x6d\x69\x74\
-\x3a\x34\x3b\x73\x74\x72\x6f\x6b\x65\x2d\x64\x61\x73\x68\x61\x72\
-\x72\x61\x79\x3a\x6e\x6f\x6e\x65\x3b\x73\x74\x72\x6f\x6b\x65\x2d\
-\x64\x61\x73\x68\x6f\x66\x66\x73\x65\x74\x3a\x30\x3b\x73\x74\x72\
-\x6f\x6b\x65\x2d\x6f\x70\x61\x63\x69\x74\x79\x3a\x31\x22\x0a\x20\
-\x20\x20\x20\x20\x20\x20\x69\x64\x3d\x22\x70\x61\x74\x68\x33\x31\
-\x34\x36\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x73\x6f\x64\x69\x70\
-\x6f\x64\x69\x3a\x63\x78\x3d\x22\x33\x30\x33\x2e\x36\x34\x36\x22\
-\x0a\x20\x20\x20\x20\x20\x20\x20\x73\x6f\x64\x69\x70\x6f\x64\x69\
-\x3a\x63\x79\x3d\x22\x31\x32\x39\x2e\x39\x38\x35\x34\x34\x22\x0a\
-\x20\x20\x20\x20\x20\x20\x20\x73\x6f\x64\x69\x70\x6f\x64\x69\x3a\
-\x72\x78\x3d\x22\x30\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x73\x6f\
-\x64\x69\x70\x6f\x64\x69\x3a\x72\x79\x3d\x22\x37\x2e\x32\x37\x39\
-\x31\x38\x35\x33\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x64\x3d\x22\
-\x4d\x20\x33\x30\x33\x2e\x36\x34\x36\x20\x31\x32\x39\x2e\x39\x38\
-\x35\x34\x34\x20\x41\x20\x30\x20\x37\x2e\x32\x37\x39\x31\x38\x35\
-\x33\x20\x30\x20\x31\x20\x31\x20\x20\x33\x30\x33\x2e\x36\x34\x36\
-\x2c\x31\x32\x39\x2e\x39\x38\x35\x34\x34\x20\x41\x20\x30\x20\x37\
-\x2e\x32\x37\x39\x31\x38\x35\x33\x20\x30\x20\x31\x20\x31\x20\x20\
-\x33\x30\x33\x2e\x36\x34\x36\x20\x31\x32\x39\x2e\x39\x38\x35\x34\
-\x34\x20\x7a\x22\x20\x2f\x3e\x0a\x20\x20\x3c\x2f\x67\x3e\x0a\x3c\
-\x2f\x73\x76\x67\x3e\x0a\
-\x00\x00\x14\x96\
-\x3c\
-\x3f\x78\x6d\x6c\x20\x76\x65\x72\x73\x69\x6f\x6e\x3d\x22\x31\x2e\
-\x30\x22\x20\x65\x6e\x63\x6f\x64\x69\x6e\x67\x3d\x22\x55\x54\x46\
-\x2d\x38\x22\x20\x73\x74\x61\x6e\x64\x61\x6c\x6f\x6e\x65\x3d\x22\
-\x6e\x6f\x22\x3f\x3e\x0a\x3c\x21\x2d\x2d\x20\x43\x72\x65\x61\x74\
-\x65\x64\x20\x77\x69\x74\x68\x20\x49\x6e\x6b\x73\x63\x61\x70\x65\
-\x20\x28\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\x77\x2e\x69\x6e\x6b\
-\x73\x63\x61\x70\x65\x2e\x6f\x72\x67\x2f\x29\x20\x2d\x2d\x3e\x0a\
-\x3c\x73\x76\x67\x0a\x20\x20\x20\x78\x6d\x6c\x6e\x73\x3a\x64\x63\
-\x3d\x22\x68\x74\x74\x70\x3a\x2f\x2f\x70\x75\x72\x6c\x2e\x6f\x72\
-\x67\x2f\x64\x63\x2f\x65\x6c\x65\x6d\x65\x6e\x74\x73\x2f\x31\x2e\
-\x31\x2f\x22\x0a\x20\x20\x20\x78\x6d\x6c\x6e\x73\x3a\x63\x63\x3d\
-\x22\x68\x74\x74\x70\x3a\x2f\x2f\x77\x65\x62\x2e\x72\x65\x73\x6f\
-\x75\x72\x63\x65\x2e\x6f\x72\x67\x2f\x63\x63\x2f\x22\x0a\x20\x20\
-\x20\x78\x6d\x6c\x6e\x73\x3a\x72\x64\x66\x3d\x22\x68\x74\x74\x70\
-\x3a\x2f\x2f\x77\x77\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x31\x39\
-\x39\x39\x2f\x30\x32\x2f\x32\x32\x2d\x72\x64\x66\x2d\x73\x79\x6e\
-\x74\x61\x78\x2d\x6e\x73\x23\x22\x0a\x20\x20\x20\x78\x6d\x6c\x6e\
-\x73\x3a\x73\x76\x67\x3d\x22\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\
-\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x32\x30\x30\x30\x2f\x73\x76\
-\x67\x22\x0a\x20\x20\x20\x78\x6d\x6c\x6e\x73\x3d\x22\x68\x74\x74\
-\x70\x3a\x2f\x2f\x77\x77\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x32\
-\x30\x30\x30\x2f\x73\x76\x67\x22\x0a\x20\x20\x20\x78\x6d\x6c\x6e\
-\x73\x3a\x78\x6c\x69\x6e\x6b\x3d\x22\x68\x74\x74\x70\x3a\x2f\x2f\
-\x77\x77\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x31\x39\x39\x39\x2f\
-\x78\x6c\x69\x6e\x6b\x22\x0a\x20\x20\x20\x78\x6d\x6c\x6e\x73\x3a\
-\x73\x6f\x64\x69\x70\x6f\x64\x69\x3d\x22\x68\x74\x74\x70\x3a\x2f\
-\x2f\x73\x6f\x64\x69\x70\x6f\x64\x69\x2e\x73\x6f\x75\x72\x63\x65\
-\x66\x6f\x72\x67\x65\x2e\x6e\x65\x74\x2f\x44\x54\x44\x2f\x73\x6f\
-\x64\x69\x70\x6f\x64\x69\x2d\x30\x2e\x64\x74\x64\x22\x0a\x20\x20\
-\x20\x78\x6d\x6c\x6e\x73\x3a\x69\x6e\x6b\x73\x63\x61\x70\x65\x3d\
-\x22\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\x77\x2e\x69\x6e\x6b\x73\
-\x63\x61\x70\x65\x2e\x6f\x72\x67\x2f\x6e\x61\x6d\x65\x73\x70\x61\
-\x63\x65\x73\x2f\x69\x6e\x6b\x73\x63\x61\x70\x65\x22\x0a\x20\x20\
-\x20\x77\x69\x64\x74\x68\x3d\x22\x32\x37\x38\x2e\x32\x35\x32\x34\
-\x31\x22\x0a\x20\x20\x20\x68\x65\x69\x67\x68\x74\x3d\x22\x32\x37\
-\x38\x2e\x32\x35\x32\x34\x31\x22\x0a\x20\x20\x20\x69\x64\x3d\x22\
-\x73\x76\x67\x32\x22\x0a\x20\x20\x20\x73\x6f\x64\x69\x70\x6f\x64\
-\x69\x3a\x76\x65\x72\x73\x69\x6f\x6e\x3d\x22\x30\x2e\x33\x32\x22\
-\x0a\x20\x20\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x76\x65\x72\
-\x73\x69\x6f\x6e\x3d\x22\x30\x2e\x34\x35\x2e\x31\x22\x0a\x20\x20\
-\x20\x73\x6f\x64\x69\x70\x6f\x64\x69\x3a\x64\x6f\x63\x62\x61\x73\
-\x65\x3d\x22\x2f\x68\x6f\x6d\x65\x2f\x64\x61\x76\x69\x64\x2f\x45\
-\x6c\x65\x63\x74\x72\x6f\x6e\x69\x63\x2f\x48\x50\x33\x35\x36\x32\
-\x2f\x69\x63\x6f\x6e\x73\x22\x0a\x20\x20\x20\x73\x6f\x64\x69\x70\
-\x6f\x64\x69\x3a\x64\x6f\x63\x6e\x61\x6d\x65\x3d\x22\x6c\x65\x64\
-\x5f\x67\x72\x65\x65\x6e\x2e\x73\x76\x67\x22\x0a\x20\x20\x20\x69\
-\x6e\x6b\x73\x63\x61\x70\x65\x3a\x6f\x75\x74\x70\x75\x74\x5f\x65\
-\x78\x74\x65\x6e\x73\x69\x6f\x6e\x3d\x22\x6f\x72\x67\x2e\x69\x6e\
-\x6b\x73\x63\x61\x70\x65\x2e\x6f\x75\x74\x70\x75\x74\x2e\x73\x76\
-\x67\x2e\x69\x6e\x6b\x73\x63\x61\x70\x65\x22\x0a\x20\x20\x20\x76\
-\x65\x72\x73\x69\x6f\x6e\x3d\x22\x31\x2e\x30\x22\x3e\x0a\x20\x20\
-\x3c\x64\x65\x66\x73\x0a\x20\x20\x20\x20\x20\x69\x64\x3d\x22\x64\
-\x65\x66\x73\x34\x22\x3e\x0a\x20\x20\x20\x20\x3c\x6c\x69\x6e\x65\
-\x61\x72\x47\x72\x61\x64\x69\x65\x6e\x74\x0a\x20\x20\x20\x20\x20\
-\x20\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x63\x6f\x6c\x6c\x65\
-\x63\x74\x3d\x22\x61\x6c\x77\x61\x79\x73\x22\x0a\x20\x20\x20\x20\
-\x20\x20\x20\x69\x64\x3d\x22\x6c\x69\x6e\x65\x61\x72\x47\x72\x61\
-\x64\x69\x65\x6e\x74\x34\x31\x31\x37\x22\x3e\x0a\x20\x20\x20\x20\
-\x20\x20\x3c\x73\x74\x6f\x70\x0a\x20\x20\x20\x20\x20\x20\x20\x20\
-\x20\x73\x74\x79\x6c\x65\x3d\x22\x73\x74\x6f\x70\x2d\x63\x6f\x6c\
-\x6f\x72\x3a\x23\x66\x66\x66\x66\x66\x66\x3b\x73\x74\x6f\x70\x2d\
-\x6f\x70\x61\x63\x69\x74\x79\x3a\x31\x3b\x22\x0a\x20\x20\x20\x20\
-\x20\x20\x20\x20\x20\x6f\x66\x66\x73\x65\x74\x3d\x22\x30\x22\x0a\
-\x20\x20\x20\x20\x20\x20\x20\x20\x20\x69\x64\x3d\x22\x73\x74\x6f\
-\x70\x34\x31\x31\x39\x22\x20\x2f\x3e\x0a\x20\x20\x20\x20\x20\x20\
-\x3c\x73\x74\x6f\x70\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x73\
-\x74\x79\x6c\x65\x3d\x22\x73\x74\x6f\x70\x2d\x63\x6f\x6c\x6f\x72\
-\x3a\x23\x66\x66\x66\x66\x66\x66\x3b\x73\x74\x6f\x70\x2d\x6f\x70\
-\x61\x63\x69\x74\x79\x3a\x30\x3b\x22\x0a\x20\x20\x20\x20\x20\x20\
-\x20\x20\x20\x6f\x66\x66\x73\x65\x74\x3d\x22\x31\x22\x0a\x20\x20\
-\x20\x20\x20\x20\x20\x20\x20\x69\x64\x3d\x22\x73\x74\x6f\x70\x34\
-\x31\x32\x31\x22\x20\x2f\x3e\x0a\x20\x20\x20\x20\x3c\x2f\x6c\x69\
-\x6e\x65\x61\x72\x47\x72\x61\x64\x69\x65\x6e\x74\x3e\x0a\x20\x20\
-\x20\x20\x3c\x6c\x69\x6e\x65\x61\x72\x47\x72\x61\x64\x69\x65\x6e\
-\x74\x0a\x20\x20\x20\x20\x20\x20\x20\x69\x64\x3d\x22\x6c\x69\x6e\
-\x65\x61\x72\x47\x72\x61\x64\x69\x65\x6e\x74\x33\x31\x33\x36\x22\
-\x3e\x0a\x20\x20\x20\x20\x20\x20\x3c\x73\x74\x6f\x70\x0a\x20\x20\
-\x20\x20\x20\x20\x20\x20\x20\x73\x74\x79\x6c\x65\x3d\x22\x73\x74\
-\x6f\x70\x2d\x63\x6f\x6c\x6f\x72\x3a\x23\x66\x66\x66\x66\x66\x66\
-\x3b\x73\x74\x6f\x70\x2d\x6f\x70\x61\x63\x69\x74\x79\x3a\x31\x3b\
-\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x6f\x66\x66\x73\x65\
-\x74\x3d\x22\x30\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x69\
-\x64\x3d\x22\x73\x74\x6f\x70\x33\x31\x33\x38\x22\x20\x2f\x3e\x0a\
-\x20\x20\x20\x20\x20\x20\x3c\x73\x74\x6f\x70\x0a\x20\x20\x20\x20\
-\x20\x20\x20\x20\x20\x73\x74\x79\x6c\x65\x3d\x22\x73\x74\x6f\x70\
-\x2d\x63\x6f\x6c\x6f\x72\x3a\x23\x30\x30\x66\x66\x30\x30\x3b\x73\
-\x74\x6f\x70\x2d\x6f\x70\x61\x63\x69\x74\x79\x3a\x30\x3b\x22\x0a\
-\x20\x20\x20\x20\x20\x20\x20\x20\x20\x6f\x66\x66\x73\x65\x74\x3d\
-\x22\x31\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x69\x64\x3d\
-\x22\x73\x74\x6f\x70\x33\x31\x34\x30\x22\x20\x2f\x3e\x0a\x20\x20\
-\x20\x20\x3c\x2f\x6c\x69\x6e\x65\x61\x72\x47\x72\x61\x64\x69\x65\
-\x6e\x74\x3e\x0a\x20\x20\x20\x20\x3c\x72\x61\x64\x69\x61\x6c\x47\
-\x72\x61\x64\x69\x65\x6e\x74\x0a\x20\x20\x20\x20\x20\x20\x20\x69\
-\x6e\x6b\x73\x63\x61\x70\x65\x3a\x63\x6f\x6c\x6c\x65\x63\x74\x3d\
-\x22\x61\x6c\x77\x61\x79\x73\x22\x0a\x20\x20\x20\x20\x20\x20\x20\
-\x78\x6c\x69\x6e\x6b\x3a\x68\x72\x65\x66\x3d\x22\x23\x6c\x69\x6e\
-\x65\x61\x72\x47\x72\x61\x64\x69\x65\x6e\x74\x33\x31\x33\x36\x22\
-\x0a\x20\x20\x20\x20\x20\x20\x20\x69\x64\x3d\x22\x72\x61\x64\x69\
-\x61\x6c\x47\x72\x61\x64\x69\x65\x6e\x74\x33\x31\x34\x32\x22\x0a\
-\x20\x20\x20\x20\x20\x20\x20\x63\x78\x3d\x22\x33\x32\x37\x2e\x34\
-\x31\x39\x32\x35\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x63\x79\x3d\
-\x22\x33\x34\x2e\x31\x30\x31\x39\x38\x32\x22\x0a\x20\x20\x20\x20\
-\x20\x20\x20\x66\x78\x3d\x22\x33\x32\x37\x2e\x34\x31\x39\x32\x35\
-\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x66\x79\x3d\x22\x33\x34\x2e\
-\x31\x30\x31\x39\x38\x32\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x72\
-\x3d\x22\x31\x33\x30\x2e\x31\x33\x32\x34\x22\x0a\x20\x20\x20\x20\
-\x20\x20\x20\x67\x72\x61\x64\x69\x65\x6e\x74\x55\x6e\x69\x74\x73\
-\x3d\x22\x75\x73\x65\x72\x53\x70\x61\x63\x65\x4f\x6e\x55\x73\x65\
-\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x67\x72\x61\x64\x69\x65\x6e\
-\x74\x54\x72\x61\x6e\x73\x66\x6f\x72\x6d\x3d\x22\x6d\x61\x74\x72\
-\x69\x78\x28\x32\x2e\x35\x36\x39\x35\x37\x30\x37\x65\x2d\x37\x2c\
-\x2d\x33\x2e\x32\x34\x36\x39\x38\x35\x38\x2c\x32\x2e\x32\x39\x36\
-\x32\x34\x35\x2c\x36\x2e\x38\x37\x30\x38\x39\x36\x39\x65\x2d\x36\
-\x2c\x33\x36\x36\x2e\x39\x31\x30\x34\x39\x2c\x31\x35\x30\x34\x2e\
-\x31\x38\x33\x29\x22\x20\x2f\x3e\x0a\x20\x20\x20\x20\x3c\x6c\x69\
-\x6e\x65\x61\x72\x47\x72\x61\x64\x69\x65\x6e\x74\x0a\x20\x20\x20\
-\x20\x20\x20\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x63\x6f\x6c\
-\x6c\x65\x63\x74\x3d\x22\x61\x6c\x77\x61\x79\x73\x22\x0a\x20\x20\
-\x20\x20\x20\x20\x20\x78\x6c\x69\x6e\x6b\x3a\x68\x72\x65\x66\x3d\
-\x22\x23\x6c\x69\x6e\x65\x61\x72\x47\x72\x61\x64\x69\x65\x6e\x74\
-\x34\x31\x31\x37\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x69\x64\x3d\
-\x22\x6c\x69\x6e\x65\x61\x72\x47\x72\x61\x64\x69\x65\x6e\x74\x34\
-\x31\x32\x33\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x78\x31\x3d\x22\
-\x32\x36\x30\x2e\x39\x35\x32\x34\x32\x22\x0a\x20\x20\x20\x20\x20\
-\x20\x20\x79\x31\x3d\x22\x31\x32\x31\x2e\x31\x38\x38\x34\x32\x22\
-\x0a\x20\x20\x20\x20\x20\x20\x20\x78\x32\x3d\x22\x34\x38\x38\x2e\
-\x36\x35\x39\x35\x35\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x79\x32\
-\x3d\x22\x33\x35\x31\x2e\x34\x38\x30\x36\x35\x22\x0a\x20\x20\x20\
-\x20\x20\x20\x20\x67\x72\x61\x64\x69\x65\x6e\x74\x55\x6e\x69\x74\
-\x73\x3d\x22\x75\x73\x65\x72\x53\x70\x61\x63\x65\x4f\x6e\x55\x73\
-\x65\x22\x20\x2f\x3e\x0a\x20\x20\x20\x20\x3c\x6c\x69\x6e\x65\x61\
-\x72\x47\x72\x61\x64\x69\x65\x6e\x74\x0a\x20\x20\x20\x20\x20\x20\
-\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x63\x6f\x6c\x6c\x65\x63\
-\x74\x3d\x22\x61\x6c\x77\x61\x79\x73\x22\x0a\x20\x20\x20\x20\x20\
-\x20\x20\x78\x6c\x69\x6e\x6b\x3a\x68\x72\x65\x66\x3d\x22\x23\x6c\
-\x69\x6e\x65\x61\x72\x47\x72\x61\x64\x69\x65\x6e\x74\x34\x31\x31\
-\x37\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x69\x64\x3d\x22\x6c\x69\
-\x6e\x65\x61\x72\x47\x72\x61\x64\x69\x65\x6e\x74\x34\x31\x32\x39\
-\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x67\x72\x61\x64\x69\x65\x6e\
-\x74\x55\x6e\x69\x74\x73\x3d\x22\x75\x73\x65\x72\x53\x70\x61\x63\
-\x65\x4f\x6e\x55\x73\x65\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x78\
-\x31\x3d\x22\x32\x36\x30\x2e\x39\x35\x32\x34\x32\x22\x0a\x20\x20\
-\x20\x20\x20\x20\x20\x79\x31\x3d\x22\x31\x32\x31\x2e\x31\x38\x38\
-\x34\x32\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x78\x32\x3d\x22\x34\
-\x38\x38\x2e\x36\x35\x39\x35\x35\x22\x0a\x20\x20\x20\x20\x20\x20\
-\x20\x79\x32\x3d\x22\x33\x35\x31\x2e\x34\x38\x30\x36\x35\x22\x0a\
-\x20\x20\x20\x20\x20\x20\x20\x67\x72\x61\x64\x69\x65\x6e\x74\x54\
-\x72\x61\x6e\x73\x66\x6f\x72\x6d\x3d\x22\x6d\x61\x74\x72\x69\x78\
-\x28\x31\x2e\x32\x34\x35\x37\x32\x32\x36\x2c\x30\x2c\x30\x2c\x31\
-\x2e\x32\x36\x31\x35\x38\x35\x34\x2c\x2d\x31\x37\x36\x2e\x37\x37\
-\x36\x38\x2c\x2d\x39\x30\x2e\x34\x39\x36\x35\x30\x38\x29\x22\x20\
-\x2f\x3e\x0a\x20\x20\x3c\x2f\x64\x65\x66\x73\x3e\x0a\x20\x20\x3c\
-\x73\x6f\x64\x69\x70\x6f\x64\x69\x3a\x6e\x61\x6d\x65\x64\x76\x69\
-\x65\x77\x0a\x20\x20\x20\x20\x20\x69\x64\x3d\x22\x62\x61\x73\x65\
-\x22\x0a\x20\x20\x20\x20\x20\x70\x61\x67\x65\x63\x6f\x6c\x6f\x72\
-\x3d\x22\x23\x66\x66\x66\x66\x66\x66\x22\x0a\x20\x20\x20\x20\x20\
-\x62\x6f\x72\x64\x65\x72\x63\x6f\x6c\x6f\x72\x3d\x22\x23\x36\x36\
-\x36\x36\x36\x36\x22\x0a\x20\x20\x20\x20\x20\x62\x6f\x72\x64\x65\
-\x72\x6f\x70\x61\x63\x69\x74\x79\x3d\x22\x31\x2e\x30\x22\x0a\x20\
-\x20\x20\x20\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x70\x61\x67\
-\x65\x6f\x70\x61\x63\x69\x74\x79\x3d\x22\x30\x2e\x30\x22\x0a\x20\
-\x20\x20\x20\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x70\x61\x67\
-\x65\x73\x68\x61\x64\x6f\x77\x3d\x22\x32\x22\x0a\x20\x20\x20\x20\
-\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x7a\x6f\x6f\x6d\x3d\x22\
-\x30\x2e\x34\x38\x30\x38\x32\x33\x30\x36\x22\x0a\x20\x20\x20\x20\
-\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x63\x78\x3d\x22\x33\x37\
-\x32\x2e\x30\x34\x37\x32\x34\x22\x0a\x20\x20\x20\x20\x20\x69\x6e\
-\x6b\x73\x63\x61\x70\x65\x3a\x63\x79\x3d\x22\x32\x30\x37\x2e\x31\
-\x32\x31\x33\x22\x0a\x20\x20\x20\x20\x20\x69\x6e\x6b\x73\x63\x61\
-\x70\x65\x3a\x64\x6f\x63\x75\x6d\x65\x6e\x74\x2d\x75\x6e\x69\x74\
-\x73\x3d\x22\x70\x78\x22\x0a\x20\x20\x20\x20\x20\x69\x6e\x6b\x73\
-\x63\x61\x70\x65\x3a\x63\x75\x72\x72\x65\x6e\x74\x2d\x6c\x61\x79\
-\x65\x72\x3d\x22\x6c\x61\x79\x65\x72\x31\x22\x0a\x20\x20\x20\x20\
-\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x77\x69\x6e\x64\x6f\x77\
-\x2d\x77\x69\x64\x74\x68\x3d\x22\x39\x39\x36\x22\x0a\x20\x20\x20\
-\x20\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x77\x69\x6e\x64\x6f\
-\x77\x2d\x68\x65\x69\x67\x68\x74\x3d\x22\x37\x31\x34\x22\x0a\x20\
-\x20\x20\x20\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x77\x69\x6e\
-\x64\x6f\x77\x2d\x78\x3d\x22\x32\x35\x22\x0a\x20\x20\x20\x20\x20\
-\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x77\x69\x6e\x64\x6f\x77\x2d\
-\x79\x3d\x22\x34\x22\x20\x2f\x3e\x0a\x20\x20\x3c\x6d\x65\x74\x61\
-\x64\x61\x74\x61\x0a\x20\x20\x20\x20\x20\x69\x64\x3d\x22\x6d\x65\
-\x74\x61\x64\x61\x74\x61\x37\x22\x3e\x0a\x20\x20\x20\x20\x3c\x72\
-\x64\x66\x3a\x52\x44\x46\x3e\x0a\x20\x20\x20\x20\x20\x20\x3c\x63\
-\x63\x3a\x57\x6f\x72\x6b\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\
-\x72\x64\x66\x3a\x61\x62\x6f\x75\x74\x3d\x22\x22\x3e\x0a\x20\x20\
-\x20\x20\x20\x20\x20\x20\x3c\x64\x63\x3a\x66\x6f\x72\x6d\x61\x74\
-\x3e\x69\x6d\x61\x67\x65\x2f\x73\x76\x67\x2b\x78\x6d\x6c\x3c\x2f\
-\x64\x63\x3a\x66\x6f\x72\x6d\x61\x74\x3e\x0a\x20\x20\x20\x20\x20\
-\x20\x20\x20\x3c\x64\x63\x3a\x74\x79\x70\x65\x0a\x20\x20\x20\x20\
-\x20\x20\x20\x20\x20\x20\x20\x72\x64\x66\x3a\x72\x65\x73\x6f\x75\
-\x72\x63\x65\x3d\x22\x68\x74\x74\x70\x3a\x2f\x2f\x70\x75\x72\x6c\
-\x2e\x6f\x72\x67\x2f\x64\x63\x2f\x64\x63\x6d\x69\x74\x79\x70\x65\
-\x2f\x53\x74\x69\x6c\x6c\x49\x6d\x61\x67\x65\x22\x20\x2f\x3e\x0a\
-\x20\x20\x20\x20\x20\x20\x3c\x2f\x63\x63\x3a\x57\x6f\x72\x6b\x3e\
-\x0a\x20\x20\x20\x20\x3c\x2f\x72\x64\x66\x3a\x52\x44\x46\x3e\x0a\
-\x20\x20\x3c\x2f\x6d\x65\x74\x61\x64\x61\x74\x61\x3e\x0a\x20\x20\
-\x3c\x67\x0a\x20\x20\x20\x20\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\
-\x3a\x6c\x61\x62\x65\x6c\x3d\x22\x43\x61\x6c\x71\x75\x65\x20\x31\
-\x22\x0a\x20\x20\x20\x20\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\
-\x67\x72\x6f\x75\x70\x6d\x6f\x64\x65\x3d\x22\x6c\x61\x79\x65\x72\
-\x22\x0a\x20\x20\x20\x20\x20\x69\x64\x3d\x22\x6c\x61\x79\x65\x72\
-\x31\x22\x0a\x20\x20\x20\x20\x20\x74\x72\x61\x6e\x73\x66\x6f\x72\
-\x6d\x3d\x22\x74\x72\x61\x6e\x73\x6c\x61\x74\x65\x28\x2d\x31\x37\
-\x35\x2e\x39\x35\x38\x35\x32\x2c\x2d\x31\x37\x31\x2e\x37\x39\x38\
-\x39\x39\x29\x22\x3e\x0a\x20\x20\x20\x20\x3c\x72\x65\x63\x74\x0a\
-\x20\x20\x20\x20\x20\x20\x20\x73\x74\x79\x6c\x65\x3d\x22\x6f\x70\
-\x61\x63\x69\x74\x79\x3a\x31\x3b\x66\x69\x6c\x6c\x3a\x23\x30\x30\
-\x66\x66\x30\x30\x3b\x66\x69\x6c\x6c\x2d\x6f\x70\x61\x63\x69\x74\
-\x79\x3a\x31\x3b\x66\x69\x6c\x6c\x2d\x72\x75\x6c\x65\x3a\x6e\x6f\
-\x6e\x7a\x65\x72\x6f\x3b\x73\x74\x72\x6f\x6b\x65\x3a\x23\x66\x66\
-\x66\x66\x66\x66\x3b\x73\x74\x72\x6f\x6b\x65\x2d\x77\x69\x64\x74\
-\x68\x3a\x30\x2e\x32\x39\x33\x39\x30\x36\x36\x36\x3b\x73\x74\x72\
-\x6f\x6b\x65\x2d\x6c\x69\x6e\x65\x63\x61\x70\x3a\x62\x75\x74\x74\
-\x3b\x73\x74\x72\x6f\x6b\x65\x2d\x6d\x69\x74\x65\x72\x6c\x69\x6d\
-\x69\x74\x3a\x34\x3b\x73\x74\x72\x6f\x6b\x65\x2d\x64\x61\x73\x68\
-\x61\x72\x72\x61\x79\x3a\x30\x2e\x32\x39\x33\x39\x30\x36\x36\x36\
-\x2c\x20\x30\x2e\x32\x39\x33\x39\x30\x36\x36\x36\x3b\x73\x74\x72\
-\x6f\x6b\x65\x2d\x64\x61\x73\x68\x6f\x66\x66\x73\x65\x74\x3a\x30\
-\x3b\x73\x74\x72\x6f\x6b\x65\x2d\x6f\x70\x61\x63\x69\x74\x79\x3a\
-\x31\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x69\x64\x3d\x22\x72\x65\
-\x63\x74\x32\x31\x36\x30\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x77\
-\x69\x64\x74\x68\x3d\x22\x32\x35\x39\x2e\x39\x37\x30\x38\x39\x22\
-\x0a\x20\x20\x20\x20\x20\x20\x20\x68\x65\x69\x67\x68\x74\x3d\x22\
-\x32\x35\x39\x2e\x39\x37\x30\x38\x39\x22\x0a\x20\x20\x20\x20\x20\
-\x20\x20\x78\x3d\x22\x31\x38\x35\x2e\x30\x39\x39\x32\x37\x22\x0a\
-\x20\x20\x20\x20\x20\x20\x20\x79\x3d\x22\x31\x38\x30\x2e\x39\x33\
-\x39\x37\x34\x22\x20\x2f\x3e\x0a\x20\x20\x20\x20\x3c\x72\x65\x63\
-\x74\x0a\x20\x20\x20\x20\x20\x20\x20\x79\x3d\x22\x31\x37\x36\x2e\
-\x33\x38\x37\x34\x34\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x78\x3d\
-\x22\x31\x38\x30\x2e\x35\x34\x36\x39\x37\x22\x0a\x20\x20\x20\x20\
-\x20\x20\x20\x68\x65\x69\x67\x68\x74\x3d\x22\x32\x36\x39\x2e\x30\
-\x37\x35\x35\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x77\x69\x64\x74\
-\x68\x3d\x22\x32\x36\x39\x2e\x30\x37\x35\x35\x22\x0a\x20\x20\x20\
-\x20\x20\x20\x20\x69\x64\x3d\x22\x72\x65\x63\x74\x32\x31\x36\x32\
-\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x73\x74\x79\x6c\x65\x3d\x22\
-\x6f\x70\x61\x63\x69\x74\x79\x3a\x31\x3b\x66\x69\x6c\x6c\x3a\x6e\
-\x6f\x6e\x65\x3b\x66\x69\x6c\x6c\x2d\x6f\x70\x61\x63\x69\x74\x79\
-\x3a\x31\x3b\x66\x69\x6c\x6c\x2d\x72\x75\x6c\x65\x3a\x6e\x6f\x6e\
-\x7a\x65\x72\x6f\x3b\x73\x74\x72\x6f\x6b\x65\x3a\x23\x30\x30\x63\
-\x34\x30\x62\x3b\x73\x74\x72\x6f\x6b\x65\x2d\x77\x69\x64\x74\x68\
-\x3a\x39\x2e\x31\x37\x36\x38\x39\x38\x39\x36\x3b\x73\x74\x72\x6f\
-\x6b\x65\x2d\x6c\x69\x6e\x65\x63\x61\x70\x3a\x62\x75\x74\x74\x3b\
-\x73\x74\x72\x6f\x6b\x65\x2d\x6d\x69\x74\x65\x72\x6c\x69\x6d\x69\
-\x74\x3a\x34\x3b\x73\x74\x72\x6f\x6b\x65\x2d\x64\x61\x73\x68\x61\
-\x72\x72\x61\x79\x3a\x6e\x6f\x6e\x65\x3b\x73\x74\x72\x6f\x6b\x65\
-\x2d\x64\x61\x73\x68\x6f\x66\x66\x73\x65\x74\x3a\x30\x3b\x73\x74\
-\x72\x6f\x6b\x65\x2d\x6f\x70\x61\x63\x69\x74\x79\x3a\x31\x22\x20\
-\x2f\x3e\x0a\x20\x20\x20\x20\x3c\x72\x65\x63\x74\x0a\x20\x20\x20\
-\x20\x20\x20\x20\x79\x3d\x22\x31\x38\x30\x2e\x39\x33\x39\x37\x34\
-\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x78\x3d\x22\x31\x38\x35\x2e\
-\x30\x39\x39\x32\x37\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x68\x65\
-\x69\x67\x68\x74\x3d\x22\x32\x35\x39\x2e\x39\x37\x30\x38\x39\x22\
-\x0a\x20\x20\x20\x20\x20\x20\x20\x77\x69\x64\x74\x68\x3d\x22\x32\
-\x35\x39\x2e\x39\x37\x30\x38\x39\x22\x0a\x20\x20\x20\x20\x20\x20\
-\x20\x69\x64\x3d\x22\x72\x65\x63\x74\x33\x31\x33\x34\x22\x0a\x20\
-\x20\x20\x20\x20\x20\x20\x73\x74\x79\x6c\x65\x3d\x22\x6f\x70\x61\
-\x63\x69\x74\x79\x3a\x31\x3b\x66\x69\x6c\x6c\x3a\x75\x72\x6c\x28\
-\x23\x72\x61\x64\x69\x61\x6c\x47\x72\x61\x64\x69\x65\x6e\x74\x33\
-\x31\x34\x32\x29\x3b\x66\x69\x6c\x6c\x2d\x6f\x70\x61\x63\x69\x74\
-\x79\x3a\x31\x3b\x66\x69\x6c\x6c\x2d\x72\x75\x6c\x65\x3a\x6e\x6f\
-\x6e\x7a\x65\x72\x6f\x3b\x73\x74\x72\x6f\x6b\x65\x3a\x23\x66\x66\
-\x66\x66\x66\x66\x3b\x73\x74\x72\x6f\x6b\x65\x2d\x77\x69\x64\x74\
-\x68\x3a\x30\x2e\x32\x39\x33\x39\x30\x36\x36\x36\x3b\x73\x74\x72\
-\x6f\x6b\x65\x2d\x6c\x69\x6e\x65\x63\x61\x70\x3a\x62\x75\x74\x74\
-\x3b\x73\x74\x72\x6f\x6b\x65\x2d\x6d\x69\x74\x65\x72\x6c\x69\x6d\
-\x69\x74\x3a\x34\x3b\x73\x74\x72\x6f\x6b\x65\x2d\x64\x61\x73\x68\
-\x61\x72\x72\x61\x79\x3a\x30\x2e\x32\x39\x33\x39\x30\x36\x36\x36\
-\x2c\x20\x30\x2e\x32\x39\x33\x39\x30\x36\x36\x36\x3b\x73\x74\x72\
-\x6f\x6b\x65\x2d\x64\x61\x73\x68\x6f\x66\x66\x73\x65\x74\x3a\x30\
-\x3b\x73\x74\x72\x6f\x6b\x65\x2d\x6f\x70\x61\x63\x69\x74\x79\x3a\
-\x31\x22\x20\x2f\x3e\x0a\x20\x20\x20\x20\x3c\x70\x61\x74\x68\x0a\
-\x20\x20\x20\x20\x20\x20\x20\x73\x74\x79\x6c\x65\x3d\x22\x66\x69\
-\x6c\x6c\x3a\x75\x72\x6c\x28\x23\x6c\x69\x6e\x65\x61\x72\x47\x72\
-\x61\x64\x69\x65\x6e\x74\x34\x31\x32\x39\x29\x3b\x66\x69\x6c\x6c\
-\x2d\x6f\x70\x61\x63\x69\x74\x79\x3a\x31\x3b\x66\x69\x6c\x6c\x2d\
-\x72\x75\x6c\x65\x3a\x6e\x6f\x6e\x7a\x65\x72\x6f\x3b\x73\x74\x72\
-\x6f\x6b\x65\x3a\x6e\x6f\x6e\x65\x3b\x73\x74\x72\x6f\x6b\x65\x2d\
-\x77\x69\x64\x74\x68\x3a\x35\x3b\x73\x74\x72\x6f\x6b\x65\x2d\x6c\
-\x69\x6e\x65\x63\x61\x70\x3a\x62\x75\x74\x74\x3b\x73\x74\x72\x6f\
-\x6b\x65\x2d\x6d\x69\x74\x65\x72\x6c\x69\x6d\x69\x74\x3a\x34\x3b\
-\x73\x74\x72\x6f\x6b\x65\x2d\x64\x61\x73\x68\x6f\x66\x66\x73\x65\
-\x74\x3a\x30\x3b\x73\x74\x72\x6f\x6b\x65\x2d\x6f\x70\x61\x63\x69\
-\x74\x79\x3a\x31\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x64\x3d\x22\
-\x4d\x20\x31\x38\x35\x2e\x30\x39\x33\x37\x35\x2c\x31\x38\x30\x2e\
-\x39\x33\x37\x35\x20\x4c\x20\x31\x38\x35\x2e\x30\x39\x33\x37\x35\
-\x2c\x33\x35\x32\x2e\x35\x36\x32\x35\x20\x43\x20\x31\x39\x30\x2e\
-\x39\x33\x37\x35\x32\x2c\x33\x35\x32\x2e\x37\x39\x39\x38\x32\x20\
-\x31\x39\x36\x2e\x38\x33\x38\x35\x36\x2c\x33\x35\x32\x2e\x39\x33\
-\x37\x35\x20\x32\x30\x32\x2e\x37\x38\x31\x32\x35\x2c\x33\x35\x32\
-\x2e\x39\x33\x37\x35\x20\x43\x20\x33\x31\x32\x2e\x38\x30\x30\x31\
-\x34\x2c\x33\x35\x32\x2e\x39\x33\x37\x35\x20\x34\x30\x36\x2e\x39\
-\x35\x30\x34\x39\x2c\x33\x31\x31\x2e\x36\x31\x30\x34\x34\x20\x34\
-\x34\x35\x2e\x30\x36\x32\x35\x2c\x32\x35\x33\x2e\x32\x35\x20\x4c\
-\x20\x34\x34\x35\x2e\x30\x36\x32\x35\x2c\x31\x38\x30\x2e\x39\x33\
-\x37\x35\x20\x4c\x20\x31\x38\x35\x2e\x30\x39\x33\x37\x35\x2c\x31\
-\x38\x30\x2e\x39\x33\x37\x35\x20\x7a\x20\x22\x0a\x20\x20\x20\x20\
-\x20\x20\x20\x69\x64\x3d\x22\x70\x61\x74\x68\x33\x31\x34\x34\x22\
-\x20\x2f\x3e\x0a\x20\x20\x20\x20\x3c\x70\x61\x74\x68\x0a\x20\x20\
-\x20\x20\x20\x20\x20\x73\x6f\x64\x69\x70\x6f\x64\x69\x3a\x74\x79\
-\x70\x65\x3d\x22\x61\x72\x63\x22\x0a\x20\x20\x20\x20\x20\x20\x20\
-\x73\x74\x79\x6c\x65\x3d\x22\x6f\x70\x61\x63\x69\x74\x79\x3a\x31\
-\x3b\x66\x69\x6c\x6c\x3a\x6e\x6f\x6e\x65\x3b\x66\x69\x6c\x6c\x2d\
-\x6f\x70\x61\x63\x69\x74\x79\x3a\x31\x3b\x66\x69\x6c\x6c\x2d\x72\
-\x75\x6c\x65\x3a\x6e\x6f\x6e\x7a\x65\x72\x6f\x3b\x73\x74\x72\x6f\
-\x6b\x65\x3a\x23\x30\x30\x30\x30\x30\x30\x3b\x73\x74\x72\x6f\x6b\
-\x65\x2d\x77\x69\x64\x74\x68\x3a\x35\x3b\x73\x74\x72\x6f\x6b\x65\
-\x2d\x6c\x69\x6e\x65\x63\x61\x70\x3a\x62\x75\x74\x74\x3b\x73\x74\
-\x72\x6f\x6b\x65\x2d\x6d\x69\x74\x65\x72\x6c\x69\x6d\x69\x74\x3a\
-\x34\x3b\x73\x74\x72\x6f\x6b\x65\x2d\x64\x61\x73\x68\x61\x72\x72\
-\x61\x79\x3a\x6e\x6f\x6e\x65\x3b\x73\x74\x72\x6f\x6b\x65\x2d\x64\
-\x61\x73\x68\x6f\x66\x66\x73\x65\x74\x3a\x30\x3b\x73\x74\x72\x6f\
-\x6b\x65\x2d\x6f\x70\x61\x63\x69\x74\x79\x3a\x31\x22\x0a\x20\x20\
-\x20\x20\x20\x20\x20\x69\x64\x3d\x22\x70\x61\x74\x68\x33\x31\x34\
-\x36\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x73\x6f\x64\x69\x70\x6f\
-\x64\x69\x3a\x63\x78\x3d\x22\x33\x30\x33\x2e\x36\x34\x36\x22\x0a\
-\x20\x20\x20\x20\x20\x20\x20\x73\x6f\x64\x69\x70\x6f\x64\x69\x3a\
-\x63\x79\x3d\x22\x31\x32\x39\x2e\x39\x38\x35\x34\x34\x22\x0a\x20\
-\x20\x20\x20\x20\x20\x20\x73\x6f\x64\x69\x70\x6f\x64\x69\x3a\x72\
-\x78\x3d\x22\x30\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x73\x6f\x64\
-\x69\x70\x6f\x64\x69\x3a\x72\x79\x3d\x22\x37\x2e\x32\x37\x39\x31\
-\x38\x35\x33\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x64\x3d\x22\x4d\
-\x20\x33\x30\x33\x2e\x36\x34\x36\x20\x31\x32\x39\x2e\x39\x38\x35\
-\x34\x34\x20\x41\x20\x30\x20\x37\x2e\x32\x37\x39\x31\x38\x35\x33\
-\x20\x30\x20\x31\x20\x31\x20\x20\x33\x30\x33\x2e\x36\x34\x36\x2c\
-\x31\x32\x39\x2e\x39\x38\x35\x34\x34\x20\x41\x20\x30\x20\x37\x2e\
-\x32\x37\x39\x31\x38\x35\x33\x20\x30\x20\x31\x20\x31\x20\x20\x33\
-\x30\x33\x2e\x36\x34\x36\x20\x31\x32\x39\x2e\x39\x38\x35\x34\x34\
-\x20\x7a\x22\x20\x2f\x3e\x0a\x20\x20\x3c\x2f\x67\x3e\x0a\x3c\x2f\
-\x73\x76\x67\x3e\x0a\
-\x00\x00\x10\xa0\
-\x3c\
-\x3f\x78\x6d\x6c\x20\x76\x65\x72\x73\x69\x6f\x6e\x3d\x22\x31\x2e\
-\x30\x22\x20\x65\x6e\x63\x6f\x64\x69\x6e\x67\x3d\x22\x55\x54\x46\
-\x2d\x38\x22\x20\x73\x74\x61\x6e\x64\x61\x6c\x6f\x6e\x65\x3d\x22\
-\x6e\x6f\x22\x3f\x3e\x0a\x3c\x21\x2d\x2d\x20\x43\x72\x65\x61\x74\
-\x65\x64\x20\x77\x69\x74\x68\x20\x49\x6e\x6b\x73\x63\x61\x70\x65\
-\x20\x28\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\x77\x2e\x69\x6e\x6b\
-\x73\x63\x61\x70\x65\x2e\x6f\x72\x67\x2f\x29\x20\x2d\x2d\x3e\x0a\
-\x3c\x73\x76\x67\x0a\x20\x20\x20\x78\x6d\x6c\x6e\x73\x3a\x64\x63\
-\x3d\x22\x68\x74\x74\x70\x3a\x2f\x2f\x70\x75\x72\x6c\x2e\x6f\x72\
-\x67\x2f\x64\x63\x2f\x65\x6c\x65\x6d\x65\x6e\x74\x73\x2f\x31\x2e\
-\x31\x2f\x22\x0a\x20\x20\x20\x78\x6d\x6c\x6e\x73\x3a\x63\x63\x3d\
-\x22\x68\x74\x74\x70\x3a\x2f\x2f\x77\x65\x62\x2e\x72\x65\x73\x6f\
-\x75\x72\x63\x65\x2e\x6f\x72\x67\x2f\x63\x63\x2f\x22\x0a\x20\x20\
-\x20\x78\x6d\x6c\x6e\x73\x3a\x72\x64\x66\x3d\x22\x68\x74\x74\x70\
-\x3a\x2f\x2f\x77\x77\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x31\x39\
-\x39\x39\x2f\x30\x32\x2f\x32\x32\x2d\x72\x64\x66\x2d\x73\x79\x6e\
-\x74\x61\x78\x2d\x6e\x73\x23\x22\x0a\x20\x20\x20\x78\x6d\x6c\x6e\
-\x73\x3a\x73\x76\x67\x3d\x22\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\
-\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x32\x30\x30\x30\x2f\x73\x76\
-\x67\x22\x0a\x20\x20\x20\x78\x6d\x6c\x6e\x73\x3d\x22\x68\x74\x74\
-\x70\x3a\x2f\x2f\x77\x77\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x32\
-\x30\x30\x30\x2f\x73\x76\x67\x22\x0a\x20\x20\x20\x78\x6d\x6c\x6e\
-\x73\x3a\x78\x6c\x69\x6e\x6b\x3d\x22\x68\x74\x74\x70\x3a\x2f\x2f\
-\x77\x77\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x31\x39\x39\x39\x2f\
-\x78\x6c\x69\x6e\x6b\x22\x0a\x20\x20\x20\x78\x6d\x6c\x6e\x73\x3a\
-\x73\x6f\x64\x69\x70\x6f\x64\x69\x3d\x22\x68\x74\x74\x70\x3a\x2f\
-\x2f\x73\x6f\x64\x69\x70\x6f\x64\x69\x2e\x73\x6f\x75\x72\x63\x65\
-\x66\x6f\x72\x67\x65\x2e\x6e\x65\x74\x2f\x44\x54\x44\x2f\x73\x6f\
-\x64\x69\x70\x6f\x64\x69\x2d\x30\x2e\x64\x74\x64\x22\x0a\x20\x20\
-\x20\x78\x6d\x6c\x6e\x73\x3a\x69\x6e\x6b\x73\x63\x61\x70\x65\x3d\
-\x22\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\x77\x2e\x69\x6e\x6b\x73\
-\x63\x61\x70\x65\x2e\x6f\x72\x67\x2f\x6e\x61\x6d\x65\x73\x70\x61\
-\x63\x65\x73\x2f\x69\x6e\x6b\x73\x63\x61\x70\x65\x22\x0a\x20\x20\
-\x20\x77\x69\x64\x74\x68\x3d\x22\x32\x37\x38\x2e\x32\x35\x32\x34\
-\x31\x22\x0a\x20\x20\x20\x68\x65\x69\x67\x68\x74\x3d\x22\x32\x37\
-\x38\x2e\x32\x35\x32\x34\x31\x22\x0a\x20\x20\x20\x69\x64\x3d\x22\
-\x73\x76\x67\x32\x22\x0a\x20\x20\x20\x73\x6f\x64\x69\x70\x6f\x64\
-\x69\x3a\x76\x65\x72\x73\x69\x6f\x6e\x3d\x22\x30\x2e\x33\x32\x22\
-\x0a\x20\x20\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x76\x65\x72\
-\x73\x69\x6f\x6e\x3d\x22\x30\x2e\x34\x35\x2e\x31\x22\x0a\x20\x20\
-\x20\x73\x6f\x64\x69\x70\x6f\x64\x69\x3a\x64\x6f\x63\x62\x61\x73\
-\x65\x3d\x22\x2f\x68\x6f\x6d\x65\x2f\x64\x61\x76\x69\x64\x2f\x45\
-\x6c\x65\x63\x74\x72\x6f\x6e\x69\x63\x2f\x48\x50\x33\x35\x36\x32\
-\x2f\x69\x63\x6f\x6e\x73\x22\x0a\x20\x20\x20\x73\x6f\x64\x69\x70\
-\x6f\x64\x69\x3a\x64\x6f\x63\x6e\x61\x6d\x65\x3d\x22\x6c\x65\x64\
-\x5f\x67\x72\x65\x65\x6e\x5f\x6f\x66\x66\x2e\x73\x76\x67\x22\x0a\
-\x20\x20\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x6f\x75\x74\x70\
-\x75\x74\x5f\x65\x78\x74\x65\x6e\x73\x69\x6f\x6e\x3d\x22\x6f\x72\
-\x67\x2e\x69\x6e\x6b\x73\x63\x61\x70\x65\x2e\x6f\x75\x74\x70\x75\
-\x74\x2e\x73\x76\x67\x2e\x69\x6e\x6b\x73\x63\x61\x70\x65\x22\x0a\
-\x20\x20\x20\x76\x65\x72\x73\x69\x6f\x6e\x3d\x22\x31\x2e\x30\x22\
-\x3e\x0a\x20\x20\x3c\x64\x65\x66\x73\x0a\x20\x20\x20\x20\x20\x69\
-\x64\x3d\x22\x64\x65\x66\x73\x34\x22\x3e\x0a\x20\x20\x20\x20\x3c\
-\x6c\x69\x6e\x65\x61\x72\x47\x72\x61\x64\x69\x65\x6e\x74\x0a\x20\
-\x20\x20\x20\x20\x20\x20\x69\x64\x3d\x22\x6c\x69\x6e\x65\x61\x72\
-\x47\x72\x61\x64\x69\x65\x6e\x74\x34\x31\x31\x37\x22\x3e\x0a\x20\
-\x20\x20\x20\x20\x20\x3c\x73\x74\x6f\x70\x0a\x20\x20\x20\x20\x20\
-\x20\x20\x20\x20\x73\x74\x79\x6c\x65\x3d\x22\x73\x74\x6f\x70\x2d\
-\x63\x6f\x6c\x6f\x72\x3a\x23\x61\x63\x61\x63\x61\x63\x3b\x73\x74\
-\x6f\x70\x2d\x6f\x70\x61\x63\x69\x74\x79\x3a\x30\x2e\x36\x38\x37\
-\x38\x33\x30\x36\x39\x3b\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\
-\x20\x6f\x66\x66\x73\x65\x74\x3d\x22\x30\x22\x0a\x20\x20\x20\x20\
-\x20\x20\x20\x20\x20\x69\x64\x3d\x22\x73\x74\x6f\x70\x34\x31\x31\
-\x39\x22\x20\x2f\x3e\x0a\x20\x20\x20\x20\x20\x20\x3c\x73\x74\x6f\
-\x70\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x73\x74\x79\x6c\x65\
-\x3d\x22\x73\x74\x6f\x70\x2d\x63\x6f\x6c\x6f\x72\x3a\x23\x66\x66\
-\x66\x66\x66\x66\x3b\x73\x74\x6f\x70\x2d\x6f\x70\x61\x63\x69\x74\
-\x79\x3a\x30\x3b\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x6f\
-\x66\x66\x73\x65\x74\x3d\x22\x31\x22\x0a\x20\x20\x20\x20\x20\x20\
-\x20\x20\x20\x69\x64\x3d\x22\x73\x74\x6f\x70\x34\x31\x32\x31\x22\
-\x20\x2f\x3e\x0a\x20\x20\x20\x20\x3c\x2f\x6c\x69\x6e\x65\x61\x72\
-\x47\x72\x61\x64\x69\x65\x6e\x74\x3e\x0a\x20\x20\x20\x20\x3c\x6c\
-\x69\x6e\x65\x61\x72\x47\x72\x61\x64\x69\x65\x6e\x74\x0a\x20\x20\
-\x20\x20\x20\x20\x20\x69\x64\x3d\x22\x6c\x69\x6e\x65\x61\x72\x47\
-\x72\x61\x64\x69\x65\x6e\x74\x33\x31\x33\x36\x22\x3e\x0a\x20\x20\
-\x20\x20\x20\x20\x3c\x73\x74\x6f\x70\x0a\x20\x20\x20\x20\x20\x20\
-\x20\x20\x20\x73\x74\x79\x6c\x65\x3d\x22\x73\x74\x6f\x70\x2d\x63\
-\x6f\x6c\x6f\x72\x3a\x23\x66\x66\x66\x66\x66\x66\x3b\x73\x74\x6f\
-\x70\x2d\x6f\x70\x61\x63\x69\x74\x79\x3a\x31\x3b\x22\x0a\x20\x20\
-\x20\x20\x20\x20\x20\x20\x20\x6f\x66\x66\x73\x65\x74\x3d\x22\x30\
-\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x69\x64\x3d\x22\x73\
-\x74\x6f\x70\x33\x31\x33\x38\x22\x20\x2f\x3e\x0a\x20\x20\x20\x20\
-\x20\x20\x3c\x73\x74\x6f\x70\x0a\x20\x20\x20\x20\x20\x20\x20\x20\
-\x20\x73\x74\x79\x6c\x65\x3d\x22\x73\x74\x6f\x70\x2d\x63\x6f\x6c\
-\x6f\x72\x3a\x23\x30\x30\x66\x66\x30\x30\x3b\x73\x74\x6f\x70\x2d\
-\x6f\x70\x61\x63\x69\x74\x79\x3a\x30\x3b\x22\x0a\x20\x20\x20\x20\
-\x20\x20\x20\x20\x20\x6f\x66\x66\x73\x65\x74\x3d\x22\x31\x22\x0a\
-\x20\x20\x20\x20\x20\x20\x20\x20\x20\x69\x64\x3d\x22\x73\x74\x6f\
-\x70\x33\x31\x34\x30\x22\x20\x2f\x3e\x0a\x20\x20\x20\x20\x3c\x2f\
-\x6c\x69\x6e\x65\x61\x72\x47\x72\x61\x64\x69\x65\x6e\x74\x3e\x0a\
-\x20\x20\x20\x20\x3c\x6c\x69\x6e\x65\x61\x72\x47\x72\x61\x64\x69\
-\x65\x6e\x74\x0a\x20\x20\x20\x20\x20\x20\x20\x69\x6e\x6b\x73\x63\
-\x61\x70\x65\x3a\x63\x6f\x6c\x6c\x65\x63\x74\x3d\x22\x61\x6c\x77\
-\x61\x79\x73\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x78\x6c\x69\x6e\
-\x6b\x3a\x68\x72\x65\x66\x3d\x22\x23\x6c\x69\x6e\x65\x61\x72\x47\
-\x72\x61\x64\x69\x65\x6e\x74\x34\x31\x31\x37\x22\x0a\x20\x20\x20\
-\x20\x20\x20\x20\x69\x64\x3d\x22\x6c\x69\x6e\x65\x61\x72\x47\x72\
-\x61\x64\x69\x65\x6e\x74\x34\x31\x32\x39\x22\x0a\x20\x20\x20\x20\
-\x20\x20\x20\x67\x72\x61\x64\x69\x65\x6e\x74\x55\x6e\x69\x74\x73\
-\x3d\x22\x75\x73\x65\x72\x53\x70\x61\x63\x65\x4f\x6e\x55\x73\x65\
-\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x78\x31\x3d\x22\x32\x36\x30\
-\x2e\x39\x35\x32\x34\x32\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x79\
-\x31\x3d\x22\x31\x32\x31\x2e\x31\x38\x38\x34\x32\x22\x0a\x20\x20\
-\x20\x20\x20\x20\x20\x78\x32\x3d\x22\x34\x38\x38\x2e\x36\x35\x39\
-\x35\x35\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x79\x32\x3d\x22\x33\
-\x35\x31\x2e\x34\x38\x30\x36\x35\x22\x0a\x20\x20\x20\x20\x20\x20\
-\x20\x67\x72\x61\x64\x69\x65\x6e\x74\x54\x72\x61\x6e\x73\x66\x6f\
-\x72\x6d\x3d\x22\x6d\x61\x74\x72\x69\x78\x28\x31\x2e\x32\x34\x35\
-\x37\x32\x32\x36\x2c\x30\x2c\x30\x2c\x31\x2e\x32\x36\x31\x35\x38\
-\x35\x34\x2c\x2d\x31\x37\x36\x2e\x37\x37\x36\x38\x2c\x2d\x39\x30\
-\x2e\x34\x39\x36\x35\x30\x38\x29\x22\x20\x2f\x3e\x0a\x20\x20\x3c\
-\x2f\x64\x65\x66\x73\x3e\x0a\x20\x20\x3c\x73\x6f\x64\x69\x70\x6f\
-\x64\x69\x3a\x6e\x61\x6d\x65\x64\x76\x69\x65\x77\x0a\x20\x20\x20\
-\x20\x20\x69\x64\x3d\x22\x62\x61\x73\x65\x22\x0a\x20\x20\x20\x20\
-\x20\x70\x61\x67\x65\x63\x6f\x6c\x6f\x72\x3d\x22\x23\x66\x66\x66\
-\x66\x66\x66\x22\x0a\x20\x20\x20\x20\x20\x62\x6f\x72\x64\x65\x72\
-\x63\x6f\x6c\x6f\x72\x3d\x22\x23\x36\x36\x36\x36\x36\x36\x22\x0a\
-\x20\x20\x20\x20\x20\x62\x6f\x72\x64\x65\x72\x6f\x70\x61\x63\x69\
-\x74\x79\x3d\x22\x31\x2e\x30\x22\x0a\x20\x20\x20\x20\x20\x69\x6e\
-\x6b\x73\x63\x61\x70\x65\x3a\x70\x61\x67\x65\x6f\x70\x61\x63\x69\
-\x74\x79\x3d\x22\x30\x2e\x30\x22\x0a\x20\x20\x20\x20\x20\x69\x6e\
-\x6b\x73\x63\x61\x70\x65\x3a\x70\x61\x67\x65\x73\x68\x61\x64\x6f\
-\x77\x3d\x22\x32\x22\x0a\x20\x20\x20\x20\x20\x69\x6e\x6b\x73\x63\
-\x61\x70\x65\x3a\x7a\x6f\x6f\x6d\x3d\x22\x30\x2e\x34\x38\x30\x38\
-\x32\x33\x30\x36\x22\x0a\x20\x20\x20\x20\x20\x69\x6e\x6b\x73\x63\
-\x61\x70\x65\x3a\x63\x78\x3d\x22\x33\x37\x32\x2e\x30\x34\x37\x32\
-\x34\x22\x0a\x20\x20\x20\x20\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\
-\x3a\x63\x79\x3d\x22\x2d\x36\x34\x2e\x37\x39\x33\x36\x39\x36\x22\
-\x0a\x20\x20\x20\x20\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x64\
-\x6f\x63\x75\x6d\x65\x6e\x74\x2d\x75\x6e\x69\x74\x73\x3d\x22\x70\
-\x78\x22\x0a\x20\x20\x20\x20\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\
-\x3a\x63\x75\x72\x72\x65\x6e\x74\x2d\x6c\x61\x79\x65\x72\x3d\x22\
-\x6c\x61\x79\x65\x72\x31\x22\x0a\x20\x20\x20\x20\x20\x69\x6e\x6b\
-\x73\x63\x61\x70\x65\x3a\x77\x69\x6e\x64\x6f\x77\x2d\x77\x69\x64\
-\x74\x68\x3d\x22\x39\x39\x36\x22\x0a\x20\x20\x20\x20\x20\x69\x6e\
-\x6b\x73\x63\x61\x70\x65\x3a\x77\x69\x6e\x64\x6f\x77\x2d\x68\x65\
-\x69\x67\x68\x74\x3d\x22\x37\x31\x34\x22\x0a\x20\x20\x20\x20\x20\
-\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x77\x69\x6e\x64\x6f\x77\x2d\
-\x78\x3d\x22\x32\x32\x22\x0a\x20\x20\x20\x20\x20\x69\x6e\x6b\x73\
-\x63\x61\x70\x65\x3a\x77\x69\x6e\x64\x6f\x77\x2d\x79\x3d\x22\x32\
-\x31\x22\x20\x2f\x3e\x0a\x20\x20\x3c\x6d\x65\x74\x61\x64\x61\x74\
-\x61\x0a\x20\x20\x20\x20\x20\x69\x64\x3d\x22\x6d\x65\x74\x61\x64\
-\x61\x74\x61\x37\x22\x3e\x0a\x20\x20\x20\x20\x3c\x72\x64\x66\x3a\
-\x52\x44\x46\x3e\x0a\x20\x20\x20\x20\x20\x20\x3c\x63\x63\x3a\x57\
-\x6f\x72\x6b\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x72\x64\x66\
-\x3a\x61\x62\x6f\x75\x74\x3d\x22\x22\x3e\x0a\x20\x20\x20\x20\x20\
-\x20\x20\x20\x3c\x64\x63\x3a\x66\x6f\x72\x6d\x61\x74\x3e\x69\x6d\
-\x61\x67\x65\x2f\x73\x76\x67\x2b\x78\x6d\x6c\x3c\x2f\x64\x63\x3a\
-\x66\x6f\x72\x6d\x61\x74\x3e\x0a\x20\x20\x20\x20\x20\x20\x20\x20\
-\x3c\x64\x63\x3a\x74\x79\x70\x65\x0a\x20\x20\x20\x20\x20\x20\x20\
-\x20\x20\x20\x20\x72\x64\x66\x3a\x72\x65\x73\x6f\x75\x72\x63\x65\
-\x3d\x22\x68\x74\x74\x70\x3a\x2f\x2f\x70\x75\x72\x6c\x2e\x6f\x72\
-\x67\x2f\x64\x63\x2f\x64\x63\x6d\x69\x74\x79\x70\x65\x2f\x53\x74\
-\x69\x6c\x6c\x49\x6d\x61\x67\x65\x22\x20\x2f\x3e\x0a\x20\x20\x20\
-\x20\x20\x20\x3c\x2f\x63\x63\x3a\x57\x6f\x72\x6b\x3e\x0a\x20\x20\
-\x20\x20\x3c\x2f\x72\x64\x66\x3a\x52\x44\x46\x3e\x0a\x20\x20\x3c\
-\x2f\x6d\x65\x74\x61\x64\x61\x74\x61\x3e\x0a\x20\x20\x3c\x67\x0a\
-\x20\x20\x20\x20\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x6c\x61\
-\x62\x65\x6c\x3d\x22\x43\x61\x6c\x71\x75\x65\x20\x31\x22\x0a\x20\
-\x20\x20\x20\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x67\x72\x6f\
-\x75\x70\x6d\x6f\x64\x65\x3d\x22\x6c\x61\x79\x65\x72\x22\x0a\x20\
-\x20\x20\x20\x20\x69\x64\x3d\x22\x6c\x61\x79\x65\x72\x31\x22\x0a\
-\x20\x20\x20\x20\x20\x74\x72\x61\x6e\x73\x66\x6f\x72\x6d\x3d\x22\
-\x74\x72\x61\x6e\x73\x6c\x61\x74\x65\x28\x2d\x31\x37\x35\x2e\x39\
-\x35\x38\x35\x32\x2c\x2d\x31\x37\x31\x2e\x37\x39\x38\x39\x39\x29\
-\x22\x3e\x0a\x20\x20\x20\x20\x3c\x72\x65\x63\x74\x0a\x20\x20\x20\
-\x20\x20\x20\x20\x73\x74\x79\x6c\x65\x3d\x22\x6f\x70\x61\x63\x69\
-\x74\x79\x3a\x31\x3b\x66\x69\x6c\x6c\x3a\x23\x30\x30\x39\x39\x30\
-\x30\x3b\x66\x69\x6c\x6c\x2d\x6f\x70\x61\x63\x69\x74\x79\x3a\x31\
-\x3b\x66\x69\x6c\x6c\x2d\x72\x75\x6c\x65\x3a\x6e\x6f\x6e\x7a\x65\
-\x72\x6f\x3b\x73\x74\x72\x6f\x6b\x65\x3a\x23\x66\x66\x66\x66\x66\
-\x66\x3b\x73\x74\x72\x6f\x6b\x65\x2d\x77\x69\x64\x74\x68\x3a\x30\
-\x2e\x32\x39\x33\x39\x30\x36\x36\x36\x3b\x73\x74\x72\x6f\x6b\x65\
-\x2d\x6c\x69\x6e\x65\x63\x61\x70\x3a\x62\x75\x74\x74\x3b\x73\x74\
-\x72\x6f\x6b\x65\x2d\x6d\x69\x74\x65\x72\x6c\x69\x6d\x69\x74\x3a\
-\x34\x3b\x73\x74\x72\x6f\x6b\x65\x2d\x64\x61\x73\x68\x61\x72\x72\
-\x61\x79\x3a\x30\x2e\x32\x39\x33\x39\x30\x36\x36\x36\x2c\x20\x30\
-\x2e\x32\x39\x33\x39\x30\x36\x36\x36\x3b\x73\x74\x72\x6f\x6b\x65\
-\x2d\x64\x61\x73\x68\x6f\x66\x66\x73\x65\x74\x3a\x30\x3b\x73\x74\
-\x72\x6f\x6b\x65\x2d\x6f\x70\x61\x63\x69\x74\x79\x3a\x31\x22\x0a\
-\x20\x20\x20\x20\x20\x20\x20\x69\x64\x3d\x22\x72\x65\x63\x74\x32\
-\x31\x36\x30\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x77\x69\x64\x74\
-\x68\x3d\x22\x32\x35\x39\x2e\x39\x37\x30\x38\x39\x22\x0a\x20\x20\
-\x20\x20\x20\x20\x20\x68\x65\x69\x67\x68\x74\x3d\x22\x32\x35\x39\
-\x2e\x39\x37\x30\x38\x39\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x78\
-\x3d\x22\x31\x38\x35\x2e\x30\x39\x39\x32\x37\x22\x0a\x20\x20\x20\
-\x20\x20\x20\x20\x79\x3d\x22\x31\x38\x30\x2e\x39\x33\x39\x37\x34\
-\x22\x20\x2f\x3e\x0a\x20\x20\x20\x20\x3c\x72\x65\x63\x74\x0a\x20\
-\x20\x20\x20\x20\x20\x20\x79\x3d\x22\x31\x37\x36\x2e\x33\x38\x37\
-\x34\x34\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x78\x3d\x22\x31\x38\
-\x30\x2e\x35\x34\x36\x39\x37\x22\x0a\x20\x20\x20\x20\x20\x20\x20\
-\x68\x65\x69\x67\x68\x74\x3d\x22\x32\x36\x39\x2e\x30\x37\x35\x35\
-\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x77\x69\x64\x74\x68\x3d\x22\
-\x32\x36\x39\x2e\x30\x37\x35\x35\x22\x0a\x20\x20\x20\x20\x20\x20\
-\x20\x69\x64\x3d\x22\x72\x65\x63\x74\x32\x31\x36\x32\x22\x0a\x20\
-\x20\x20\x20\x20\x20\x20\x73\x74\x79\x6c\x65\x3d\x22\x6f\x70\x61\
-\x63\x69\x74\x79\x3a\x31\x3b\x66\x69\x6c\x6c\x3a\x6e\x6f\x6e\x65\
-\x3b\x66\x69\x6c\x6c\x2d\x6f\x70\x61\x63\x69\x74\x79\x3a\x31\x3b\
-\x66\x69\x6c\x6c\x2d\x72\x75\x6c\x65\x3a\x6e\x6f\x6e\x7a\x65\x72\
-\x6f\x3b\x73\x74\x72\x6f\x6b\x65\x3a\x23\x30\x30\x38\x33\x30\x34\
-\x3b\x73\x74\x72\x6f\x6b\x65\x2d\x77\x69\x64\x74\x68\x3a\x39\x2e\
-\x31\x37\x36\x38\x39\x38\x39\x36\x3b\x73\x74\x72\x6f\x6b\x65\x2d\
-\x6c\x69\x6e\x65\x63\x61\x70\x3a\x62\x75\x74\x74\x3b\x73\x74\x72\
-\x6f\x6b\x65\x2d\x6d\x69\x74\x65\x72\x6c\x69\x6d\x69\x74\x3a\x34\
-\x3b\x73\x74\x72\x6f\x6b\x65\x2d\x64\x61\x73\x68\x61\x72\x72\x61\
-\x79\x3a\x6e\x6f\x6e\x65\x3b\x73\x74\x72\x6f\x6b\x65\x2d\x64\x61\
-\x73\x68\x6f\x66\x66\x73\x65\x74\x3a\x30\x3b\x73\x74\x72\x6f\x6b\
-\x65\x2d\x6f\x70\x61\x63\x69\x74\x79\x3a\x31\x22\x20\x2f\x3e\x0a\
-\x20\x20\x20\x20\x3c\x70\x61\x74\x68\x0a\x20\x20\x20\x20\x20\x20\
-\x20\x73\x74\x79\x6c\x65\x3d\x22\x66\x69\x6c\x6c\x3a\x75\x72\x6c\
-\x28\x23\x6c\x69\x6e\x65\x61\x72\x47\x72\x61\x64\x69\x65\x6e\x74\
-\x34\x31\x32\x39\x29\x3b\x66\x69\x6c\x6c\x2d\x6f\x70\x61\x63\x69\
-\x74\x79\x3a\x31\x3b\x66\x69\x6c\x6c\x2d\x72\x75\x6c\x65\x3a\x6e\
-\x6f\x6e\x7a\x65\x72\x6f\x3b\x73\x74\x72\x6f\x6b\x65\x3a\x6e\x6f\
-\x6e\x65\x3b\x73\x74\x72\x6f\x6b\x65\x2d\x77\x69\x64\x74\x68\x3a\
-\x35\x3b\x73\x74\x72\x6f\x6b\x65\x2d\x6c\x69\x6e\x65\x63\x61\x70\
-\x3a\x62\x75\x74\x74\x3b\x73\x74\x72\x6f\x6b\x65\x2d\x6d\x69\x74\
-\x65\x72\x6c\x69\x6d\x69\x74\x3a\x34\x3b\x73\x74\x72\x6f\x6b\x65\
-\x2d\x64\x61\x73\x68\x6f\x66\x66\x73\x65\x74\x3a\x30\x3b\x73\x74\
-\x72\x6f\x6b\x65\x2d\x6f\x70\x61\x63\x69\x74\x79\x3a\x31\x22\x0a\
-\x20\x20\x20\x20\x20\x20\x20\x64\x3d\x22\x4d\x20\x31\x38\x35\x2e\
-\x30\x39\x33\x37\x35\x2c\x31\x38\x30\x2e\x39\x33\x37\x35\x20\x4c\
-\x20\x31\x38\x35\x2e\x30\x39\x33\x37\x35\x2c\x33\x35\x32\x2e\x35\
-\x36\x32\x35\x20\x43\x20\x31\x39\x30\x2e\x39\x33\x37\x35\x32\x2c\
-\x33\x35\x32\x2e\x37\x39\x39\x38\x32\x20\x31\x39\x36\x2e\x38\x33\
-\x38\x35\x36\x2c\x33\x35\x32\x2e\x39\x33\x37\x35\x20\x32\x30\x32\
-\x2e\x37\x38\x31\x32\x35\x2c\x33\x35\x32\x2e\x39\x33\x37\x35\x20\
-\x43\x20\x33\x31\x32\x2e\x38\x30\x30\x31\x34\x2c\x33\x35\x32\x2e\
-\x39\x33\x37\x35\x20\x34\x30\x36\x2e\x39\x35\x30\x34\x39\x2c\x33\
-\x31\x31\x2e\x36\x31\x30\x34\x34\x20\x34\x34\x35\x2e\x30\x36\x32\
-\x35\x2c\x32\x35\x33\x2e\x32\x35\x20\x4c\x20\x34\x34\x35\x2e\x30\
-\x36\x32\x35\x2c\x31\x38\x30\x2e\x39\x33\x37\x35\x20\x4c\x20\x31\
-\x38\x35\x2e\x30\x39\x33\x37\x35\x2c\x31\x38\x30\x2e\x39\x33\x37\
-\x35\x20\x7a\x20\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x69\x64\x3d\
-\x22\x70\x61\x74\x68\x33\x31\x34\x34\x22\x20\x2f\x3e\x0a\x20\x20\
-\x20\x20\x3c\x70\x61\x74\x68\x0a\x20\x20\x20\x20\x20\x20\x20\x73\
-\x6f\x64\x69\x70\x6f\x64\x69\x3a\x74\x79\x70\x65\x3d\x22\x61\x72\
-\x63\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x73\x74\x79\x6c\x65\x3d\
-\x22\x6f\x70\x61\x63\x69\x74\x79\x3a\x31\x3b\x66\x69\x6c\x6c\x3a\
-\x6e\x6f\x6e\x65\x3b\x66\x69\x6c\x6c\x2d\x6f\x70\x61\x63\x69\x74\
-\x79\x3a\x31\x3b\x66\x69\x6c\x6c\x2d\x72\x75\x6c\x65\x3a\x6e\x6f\
-\x6e\x7a\x65\x72\x6f\x3b\x73\x74\x72\x6f\x6b\x65\x3a\x23\x30\x30\
-\x30\x30\x30\x30\x3b\x73\x74\x72\x6f\x6b\x65\x2d\x77\x69\x64\x74\
-\x68\x3a\x35\x3b\x73\x74\x72\x6f\x6b\x65\x2d\x6c\x69\x6e\x65\x63\
-\x61\x70\x3a\x62\x75\x74\x74\x3b\x73\x74\x72\x6f\x6b\x65\x2d\x6d\
-\x69\x74\x65\x72\x6c\x69\x6d\x69\x74\x3a\x34\x3b\x73\x74\x72\x6f\
-\x6b\x65\x2d\x64\x61\x73\x68\x61\x72\x72\x61\x79\x3a\x6e\x6f\x6e\
-\x65\x3b\x73\x74\x72\x6f\x6b\x65\x2d\x64\x61\x73\x68\x6f\x66\x66\
-\x73\x65\x74\x3a\x30\x3b\x73\x74\x72\x6f\x6b\x65\x2d\x6f\x70\x61\
-\x63\x69\x74\x79\x3a\x31\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x69\
-\x64\x3d\x22\x70\x61\x74\x68\x33\x31\x34\x36\x22\x0a\x20\x20\x20\
-\x20\x20\x20\x20\x73\x6f\x64\x69\x70\x6f\x64\x69\x3a\x63\x78\x3d\
-\x22\x33\x30\x33\x2e\x36\x34\x36\x22\x0a\x20\x20\x20\x20\x20\x20\
-\x20\x73\x6f\x64\x69\x70\x6f\x64\x69\x3a\x63\x79\x3d\x22\x31\x32\
-\x39\x2e\x39\x38\x35\x34\x34\x22\x0a\x20\x20\x20\x20\x20\x20\x20\
-\x73\x6f\x64\x69\x70\x6f\x64\x69\x3a\x72\x78\x3d\x22\x30\x22\x0a\
-\x20\x20\x20\x20\x20\x20\x20\x73\x6f\x64\x69\x70\x6f\x64\x69\x3a\
-\x72\x79\x3d\x22\x37\x2e\x32\x37\x39\x31\x38\x35\x33\x22\x0a\x20\
-\x20\x20\x20\x20\x20\x20\x64\x3d\x22\x4d\x20\x33\x30\x33\x2e\x36\
-\x34\x36\x20\x31\x32\x39\x2e\x39\x38\x35\x34\x34\x20\x41\x20\x30\
-\x20\x37\x2e\x32\x37\x39\x31\x38\x35\x33\x20\x30\x20\x31\x20\x31\
-\x20\x20\x33\x30\x33\x2e\x36\x34\x36\x2c\x31\x32\x39\x2e\x39\x38\
-\x35\x34\x34\x20\x41\x20\x30\x20\x37\x2e\x32\x37\x39\x31\x38\x35\
-\x33\x20\x30\x20\x31\x20\x31\x20\x20\x33\x30\x33\x2e\x36\x34\x36\
-\x20\x31\x32\x39\x2e\x39\x38\x35\x34\x34\x20\x7a\x22\x20\x2f\x3e\
-\x0a\x20\x20\x3c\x2f\x67\x3e\x0a\x3c\x2f\x73\x76\x67\x3e\x0a\
-\x00\x00\x14\x96\
-\x3c\
-\x3f\x78\x6d\x6c\x20\x76\x65\x72\x73\x69\x6f\x6e\x3d\x22\x31\x2e\
-\x30\x22\x20\x65\x6e\x63\x6f\x64\x69\x6e\x67\x3d\x22\x55\x54\x46\
-\x2d\x38\x22\x20\x73\x74\x61\x6e\x64\x61\x6c\x6f\x6e\x65\x3d\x22\
-\x6e\x6f\x22\x3f\x3e\x0a\x3c\x21\x2d\x2d\x20\x43\x72\x65\x61\x74\
-\x65\x64\x20\x77\x69\x74\x68\x20\x49\x6e\x6b\x73\x63\x61\x70\x65\
-\x20\x28\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\x77\x2e\x69\x6e\x6b\
-\x73\x63\x61\x70\x65\x2e\x6f\x72\x67\x2f\x29\x20\x2d\x2d\x3e\x0a\
-\x3c\x73\x76\x67\x0a\x20\x20\x20\x78\x6d\x6c\x6e\x73\x3a\x64\x63\
-\x3d\x22\x68\x74\x74\x70\x3a\x2f\x2f\x70\x75\x72\x6c\x2e\x6f\x72\
-\x67\x2f\x64\x63\x2f\x65\x6c\x65\x6d\x65\x6e\x74\x73\x2f\x31\x2e\
-\x31\x2f\x22\x0a\x20\x20\x20\x78\x6d\x6c\x6e\x73\x3a\x63\x63\x3d\
-\x22\x68\x74\x74\x70\x3a\x2f\x2f\x77\x65\x62\x2e\x72\x65\x73\x6f\
-\x75\x72\x63\x65\x2e\x6f\x72\x67\x2f\x63\x63\x2f\x22\x0a\x20\x20\
-\x20\x78\x6d\x6c\x6e\x73\x3a\x72\x64\x66\x3d\x22\x68\x74\x74\x70\
-\x3a\x2f\x2f\x77\x77\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x31\x39\
-\x39\x39\x2f\x30\x32\x2f\x32\x32\x2d\x72\x64\x66\x2d\x73\x79\x6e\
-\x74\x61\x78\x2d\x6e\x73\x23\x22\x0a\x20\x20\x20\x78\x6d\x6c\x6e\
-\x73\x3a\x73\x76\x67\x3d\x22\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\
-\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x32\x30\x30\x30\x2f\x73\x76\
-\x67\x22\x0a\x20\x20\x20\x78\x6d\x6c\x6e\x73\x3d\x22\x68\x74\x74\
-\x70\x3a\x2f\x2f\x77\x77\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x32\
-\x30\x30\x30\x2f\x73\x76\x67\x22\x0a\x20\x20\x20\x78\x6d\x6c\x6e\
-\x73\x3a\x78\x6c\x69\x6e\x6b\x3d\x22\x68\x74\x74\x70\x3a\x2f\x2f\
-\x77\x77\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x31\x39\x39\x39\x2f\
-\x78\x6c\x69\x6e\x6b\x22\x0a\x20\x20\x20\x78\x6d\x6c\x6e\x73\x3a\
-\x73\x6f\x64\x69\x70\x6f\x64\x69\x3d\x22\x68\x74\x74\x70\x3a\x2f\
-\x2f\x73\x6f\x64\x69\x70\x6f\x64\x69\x2e\x73\x6f\x75\x72\x63\x65\
-\x66\x6f\x72\x67\x65\x2e\x6e\x65\x74\x2f\x44\x54\x44\x2f\x73\x6f\
-\x64\x69\x70\x6f\x64\x69\x2d\x30\x2e\x64\x74\x64\x22\x0a\x20\x20\
-\x20\x78\x6d\x6c\x6e\x73\x3a\x69\x6e\x6b\x73\x63\x61\x70\x65\x3d\
-\x22\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\x77\x2e\x69\x6e\x6b\x73\
-\x63\x61\x70\x65\x2e\x6f\x72\x67\x2f\x6e\x61\x6d\x65\x73\x70\x61\
-\x63\x65\x73\x2f\x69\x6e\x6b\x73\x63\x61\x70\x65\x22\x0a\x20\x20\
-\x20\x77\x69\x64\x74\x68\x3d\x22\x32\x37\x38\x2e\x32\x35\x32\x34\
-\x31\x22\x0a\x20\x20\x20\x68\x65\x69\x67\x68\x74\x3d\x22\x32\x37\
-\x38\x2e\x32\x35\x32\x34\x31\x22\x0a\x20\x20\x20\x69\x64\x3d\x22\
-\x73\x76\x67\x32\x22\x0a\x20\x20\x20\x73\x6f\x64\x69\x70\x6f\x64\
-\x69\x3a\x76\x65\x72\x73\x69\x6f\x6e\x3d\x22\x30\x2e\x33\x32\x22\
-\x0a\x20\x20\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x76\x65\x72\
-\x73\x69\x6f\x6e\x3d\x22\x30\x2e\x34\x35\x2e\x31\x22\x0a\x20\x20\
-\x20\x73\x6f\x64\x69\x70\x6f\x64\x69\x3a\x64\x6f\x63\x62\x61\x73\
-\x65\x3d\x22\x2f\x68\x6f\x6d\x65\x2f\x64\x61\x76\x69\x64\x2f\x45\
-\x6c\x65\x63\x74\x72\x6f\x6e\x69\x63\x2f\x48\x50\x33\x35\x36\x32\
-\x2f\x69\x63\x6f\x6e\x73\x22\x0a\x20\x20\x20\x73\x6f\x64\x69\x70\
-\x6f\x64\x69\x3a\x64\x6f\x63\x6e\x61\x6d\x65\x3d\x22\x6c\x65\x64\
-\x5f\x72\x65\x64\x2e\x73\x76\x67\x22\x0a\x20\x20\x20\x69\x6e\x6b\
-\x73\x63\x61\x70\x65\x3a\x6f\x75\x74\x70\x75\x74\x5f\x65\x78\x74\
-\x65\x6e\x73\x69\x6f\x6e\x3d\x22\x6f\x72\x67\x2e\x69\x6e\x6b\x73\
-\x63\x61\x70\x65\x2e\x6f\x75\x74\x70\x75\x74\x2e\x73\x76\x67\x2e\
-\x69\x6e\x6b\x73\x63\x61\x70\x65\x22\x0a\x20\x20\x20\x76\x65\x72\
-\x73\x69\x6f\x6e\x3d\x22\x31\x2e\x30\x22\x3e\x0a\x20\x20\x3c\x64\
-\x65\x66\x73\x0a\x20\x20\x20\x20\x20\x69\x64\x3d\x22\x64\x65\x66\
-\x73\x34\x22\x3e\x0a\x20\x20\x20\x20\x3c\x6c\x69\x6e\x65\x61\x72\
-\x47\x72\x61\x64\x69\x65\x6e\x74\x0a\x20\x20\x20\x20\x20\x20\x20\
-\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x63\x6f\x6c\x6c\x65\x63\x74\
-\x3d\x22\x61\x6c\x77\x61\x79\x73\x22\x0a\x20\x20\x20\x20\x20\x20\
-\x20\x69\x64\x3d\x22\x6c\x69\x6e\x65\x61\x72\x47\x72\x61\x64\x69\
-\x65\x6e\x74\x34\x31\x31\x37\x22\x3e\x0a\x20\x20\x20\x20\x20\x20\
-\x3c\x73\x74\x6f\x70\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x73\
-\x74\x79\x6c\x65\x3d\x22\x73\x74\x6f\x70\x2d\x63\x6f\x6c\x6f\x72\
-\x3a\x23\x66\x66\x66\x66\x66\x66\x3b\x73\x74\x6f\x70\x2d\x6f\x70\
-\x61\x63\x69\x74\x79\x3a\x31\x3b\x22\x0a\x20\x20\x20\x20\x20\x20\
-\x20\x20\x20\x6f\x66\x66\x73\x65\x74\x3d\x22\x30\x22\x0a\x20\x20\
-\x20\x20\x20\x20\x20\x20\x20\x69\x64\x3d\x22\x73\x74\x6f\x70\x34\
-\x31\x31\x39\x22\x20\x2f\x3e\x0a\x20\x20\x20\x20\x20\x20\x3c\x73\
-\x74\x6f\x70\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x73\x74\x79\
-\x6c\x65\x3d\x22\x73\x74\x6f\x70\x2d\x63\x6f\x6c\x6f\x72\x3a\x23\
-\x66\x66\x66\x66\x66\x66\x3b\x73\x74\x6f\x70\x2d\x6f\x70\x61\x63\
-\x69\x74\x79\x3a\x30\x3b\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\
-\x20\x6f\x66\x66\x73\x65\x74\x3d\x22\x31\x22\x0a\x20\x20\x20\x20\
-\x20\x20\x20\x20\x20\x69\x64\x3d\x22\x73\x74\x6f\x70\x34\x31\x32\
-\x31\x22\x20\x2f\x3e\x0a\x20\x20\x20\x20\x3c\x2f\x6c\x69\x6e\x65\
-\x61\x72\x47\x72\x61\x64\x69\x65\x6e\x74\x3e\x0a\x20\x20\x20\x20\
-\x3c\x6c\x69\x6e\x65\x61\x72\x47\x72\x61\x64\x69\x65\x6e\x74\x0a\
-\x20\x20\x20\x20\x20\x20\x20\x69\x64\x3d\x22\x6c\x69\x6e\x65\x61\
-\x72\x47\x72\x61\x64\x69\x65\x6e\x74\x33\x31\x33\x36\x22\x3e\x0a\
-\x20\x20\x20\x20\x20\x20\x3c\x73\x74\x6f\x70\x0a\x20\x20\x20\x20\
-\x20\x20\x20\x20\x20\x73\x74\x79\x6c\x65\x3d\x22\x73\x74\x6f\x70\
-\x2d\x63\x6f\x6c\x6f\x72\x3a\x23\x66\x66\x66\x66\x66\x66\x3b\x73\
-\x74\x6f\x70\x2d\x6f\x70\x61\x63\x69\x74\x79\x3a\x31\x3b\x22\x0a\
-\x20\x20\x20\x20\x20\x20\x20\x20\x20\x6f\x66\x66\x73\x65\x74\x3d\
-\x22\x30\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x69\x64\x3d\
-\x22\x73\x74\x6f\x70\x33\x31\x33\x38\x22\x20\x2f\x3e\x0a\x20\x20\
-\x20\x20\x20\x20\x3c\x73\x74\x6f\x70\x0a\x20\x20\x20\x20\x20\x20\
-\x20\x20\x20\x73\x74\x79\x6c\x65\x3d\x22\x73\x74\x6f\x70\x2d\x63\
-\x6f\x6c\x6f\x72\x3a\x23\x66\x66\x30\x30\x30\x30\x3b\x73\x74\x6f\
-\x70\x2d\x6f\x70\x61\x63\x69\x74\x79\x3a\x30\x3b\x22\x0a\x20\x20\
-\x20\x20\x20\x20\x20\x20\x20\x6f\x66\x66\x73\x65\x74\x3d\x22\x31\
-\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x69\x64\x3d\x22\x73\
-\x74\x6f\x70\x33\x31\x34\x30\x22\x20\x2f\x3e\x0a\x20\x20\x20\x20\
-\x3c\x2f\x6c\x69\x6e\x65\x61\x72\x47\x72\x61\x64\x69\x65\x6e\x74\
-\x3e\x0a\x20\x20\x20\x20\x3c\x72\x61\x64\x69\x61\x6c\x47\x72\x61\
-\x64\x69\x65\x6e\x74\x0a\x20\x20\x20\x20\x20\x20\x20\x69\x6e\x6b\
-\x73\x63\x61\x70\x65\x3a\x63\x6f\x6c\x6c\x65\x63\x74\x3d\x22\x61\
-\x6c\x77\x61\x79\x73\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x78\x6c\
-\x69\x6e\x6b\x3a\x68\x72\x65\x66\x3d\x22\x23\x6c\x69\x6e\x65\x61\
-\x72\x47\x72\x61\x64\x69\x65\x6e\x74\x33\x31\x33\x36\x22\x0a\x20\
-\x20\x20\x20\x20\x20\x20\x69\x64\x3d\x22\x72\x61\x64\x69\x61\x6c\
-\x47\x72\x61\x64\x69\x65\x6e\x74\x33\x31\x34\x32\x22\x0a\x20\x20\
-\x20\x20\x20\x20\x20\x63\x78\x3d\x22\x33\x32\x37\x2e\x34\x31\x39\
-\x32\x35\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x63\x79\x3d\x22\x33\
-\x34\x2e\x31\x30\x31\x39\x38\x32\x22\x0a\x20\x20\x20\x20\x20\x20\
-\x20\x66\x78\x3d\x22\x33\x32\x37\x2e\x34\x31\x39\x32\x35\x22\x0a\
-\x20\x20\x20\x20\x20\x20\x20\x66\x79\x3d\x22\x33\x34\x2e\x31\x30\
-\x31\x39\x38\x32\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x72\x3d\x22\
-\x31\x33\x30\x2e\x31\x33\x32\x34\x22\x0a\x20\x20\x20\x20\x20\x20\
-\x20\x67\x72\x61\x64\x69\x65\x6e\x74\x55\x6e\x69\x74\x73\x3d\x22\
-\x75\x73\x65\x72\x53\x70\x61\x63\x65\x4f\x6e\x55\x73\x65\x22\x0a\
-\x20\x20\x20\x20\x20\x20\x20\x67\x72\x61\x64\x69\x65\x6e\x74\x54\
-\x72\x61\x6e\x73\x66\x6f\x72\x6d\x3d\x22\x6d\x61\x74\x72\x69\x78\
-\x28\x32\x2e\x35\x36\x39\x35\x37\x30\x37\x65\x2d\x37\x2c\x2d\x33\
-\x2e\x32\x34\x36\x39\x38\x35\x38\x2c\x32\x2e\x32\x39\x36\x32\x34\
-\x35\x2c\x36\x2e\x38\x37\x30\x38\x39\x36\x39\x65\x2d\x36\x2c\x33\
-\x36\x36\x2e\x39\x31\x30\x34\x39\x2c\x31\x35\x30\x34\x2e\x31\x38\
-\x33\x29\x22\x20\x2f\x3e\x0a\x20\x20\x20\x20\x3c\x6c\x69\x6e\x65\
-\x61\x72\x47\x72\x61\x64\x69\x65\x6e\x74\x0a\x20\x20\x20\x20\x20\
-\x20\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x63\x6f\x6c\x6c\x65\
-\x63\x74\x3d\x22\x61\x6c\x77\x61\x79\x73\x22\x0a\x20\x20\x20\x20\
-\x20\x20\x20\x78\x6c\x69\x6e\x6b\x3a\x68\x72\x65\x66\x3d\x22\x23\
-\x6c\x69\x6e\x65\x61\x72\x47\x72\x61\x64\x69\x65\x6e\x74\x34\x31\
-\x31\x37\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x69\x64\x3d\x22\x6c\
-\x69\x6e\x65\x61\x72\x47\x72\x61\x64\x69\x65\x6e\x74\x34\x31\x32\
-\x33\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x78\x31\x3d\x22\x32\x36\
-\x30\x2e\x39\x35\x32\x34\x32\x22\x0a\x20\x20\x20\x20\x20\x20\x20\
-\x79\x31\x3d\x22\x31\x32\x31\x2e\x31\x38\x38\x34\x32\x22\x0a\x20\
-\x20\x20\x20\x20\x20\x20\x78\x32\x3d\x22\x34\x38\x38\x2e\x36\x35\
-\x39\x35\x35\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x79\x32\x3d\x22\
-\x33\x35\x31\x2e\x34\x38\x30\x36\x35\x22\x0a\x20\x20\x20\x20\x20\
-\x20\x20\x67\x72\x61\x64\x69\x65\x6e\x74\x55\x6e\x69\x74\x73\x3d\
-\x22\x75\x73\x65\x72\x53\x70\x61\x63\x65\x4f\x6e\x55\x73\x65\x22\
-\x20\x2f\x3e\x0a\x20\x20\x20\x20\x3c\x6c\x69\x6e\x65\x61\x72\x47\
-\x72\x61\x64\x69\x65\x6e\x74\x0a\x20\x20\x20\x20\x20\x20\x20\x69\
-\x6e\x6b\x73\x63\x61\x70\x65\x3a\x63\x6f\x6c\x6c\x65\x63\x74\x3d\
-\x22\x61\x6c\x77\x61\x79\x73\x22\x0a\x20\x20\x20\x20\x20\x20\x20\
-\x78\x6c\x69\x6e\x6b\x3a\x68\x72\x65\x66\x3d\x22\x23\x6c\x69\x6e\
-\x65\x61\x72\x47\x72\x61\x64\x69\x65\x6e\x74\x34\x31\x31\x37\x22\
-\x0a\x20\x20\x20\x20\x20\x20\x20\x69\x64\x3d\x22\x6c\x69\x6e\x65\
-\x61\x72\x47\x72\x61\x64\x69\x65\x6e\x74\x34\x31\x32\x39\x22\x0a\
-\x20\x20\x20\x20\x20\x20\x20\x67\x72\x61\x64\x69\x65\x6e\x74\x55\
-\x6e\x69\x74\x73\x3d\x22\x75\x73\x65\x72\x53\x70\x61\x63\x65\x4f\
-\x6e\x55\x73\x65\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x78\x31\x3d\
-\x22\x32\x36\x30\x2e\x39\x35\x32\x34\x32\x22\x0a\x20\x20\x20\x20\
-\x20\x20\x20\x79\x31\x3d\x22\x31\x32\x31\x2e\x31\x38\x38\x34\x32\
-\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x78\x32\x3d\x22\x34\x38\x38\
-\x2e\x36\x35\x39\x35\x35\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x79\
-\x32\x3d\x22\x33\x35\x31\x2e\x34\x38\x30\x36\x35\x22\x0a\x20\x20\
-\x20\x20\x20\x20\x20\x67\x72\x61\x64\x69\x65\x6e\x74\x54\x72\x61\
-\x6e\x73\x66\x6f\x72\x6d\x3d\x22\x6d\x61\x74\x72\x69\x78\x28\x31\
-\x2e\x32\x34\x35\x37\x32\x32\x36\x2c\x30\x2c\x30\x2c\x31\x2e\x32\
-\x36\x31\x35\x38\x35\x34\x2c\x2d\x31\x37\x36\x2e\x37\x37\x36\x38\
-\x2c\x2d\x39\x30\x2e\x34\x39\x36\x35\x30\x38\x29\x22\x20\x2f\x3e\
-\x0a\x20\x20\x3c\x2f\x64\x65\x66\x73\x3e\x0a\x20\x20\x3c\x73\x6f\
-\x64\x69\x70\x6f\x64\x69\x3a\x6e\x61\x6d\x65\x64\x76\x69\x65\x77\
-\x0a\x20\x20\x20\x20\x20\x69\x64\x3d\x22\x62\x61\x73\x65\x22\x0a\
-\x20\x20\x20\x20\x20\x70\x61\x67\x65\x63\x6f\x6c\x6f\x72\x3d\x22\
-\x23\x66\x66\x66\x66\x66\x66\x22\x0a\x20\x20\x20\x20\x20\x62\x6f\
-\x72\x64\x65\x72\x63\x6f\x6c\x6f\x72\x3d\x22\x23\x36\x36\x36\x36\
-\x36\x36\x22\x0a\x20\x20\x20\x20\x20\x62\x6f\x72\x64\x65\x72\x6f\
-\x70\x61\x63\x69\x74\x79\x3d\x22\x31\x2e\x30\x22\x0a\x20\x20\x20\
-\x20\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x70\x61\x67\x65\x6f\
-\x70\x61\x63\x69\x74\x79\x3d\x22\x30\x2e\x30\x22\x0a\x20\x20\x20\
-\x20\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x70\x61\x67\x65\x73\
-\x68\x61\x64\x6f\x77\x3d\x22\x32\x22\x0a\x20\x20\x20\x20\x20\x69\
-\x6e\x6b\x73\x63\x61\x70\x65\x3a\x7a\x6f\x6f\x6d\x3d\x22\x30\x2e\
-\x39\x36\x31\x36\x34\x36\x31\x31\x22\x0a\x20\x20\x20\x20\x20\x69\
-\x6e\x6b\x73\x63\x61\x70\x65\x3a\x63\x78\x3d\x22\x33\x32\x36\x2e\
-\x33\x38\x33\x38\x32\x22\x0a\x20\x20\x20\x20\x20\x69\x6e\x6b\x73\
-\x63\x61\x70\x65\x3a\x63\x79\x3d\x22\x38\x39\x2e\x38\x36\x32\x38\
-\x36\x39\x22\x0a\x20\x20\x20\x20\x20\x69\x6e\x6b\x73\x63\x61\x70\
-\x65\x3a\x64\x6f\x63\x75\x6d\x65\x6e\x74\x2d\x75\x6e\x69\x74\x73\
-\x3d\x22\x70\x78\x22\x0a\x20\x20\x20\x20\x20\x69\x6e\x6b\x73\x63\
-\x61\x70\x65\x3a\x63\x75\x72\x72\x65\x6e\x74\x2d\x6c\x61\x79\x65\
-\x72\x3d\x22\x6c\x61\x79\x65\x72\x31\x22\x0a\x20\x20\x20\x20\x20\
-\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x77\x69\x6e\x64\x6f\x77\x2d\
-\x77\x69\x64\x74\x68\x3d\x22\x39\x39\x36\x22\x0a\x20\x20\x20\x20\
-\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x77\x69\x6e\x64\x6f\x77\
-\x2d\x68\x65\x69\x67\x68\x74\x3d\x22\x37\x31\x34\x22\x0a\x20\x20\
-\x20\x20\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x77\x69\x6e\x64\
-\x6f\x77\x2d\x78\x3d\x22\x31\x31\x22\x0a\x20\x20\x20\x20\x20\x69\
-\x6e\x6b\x73\x63\x61\x70\x65\x3a\x77\x69\x6e\x64\x6f\x77\x2d\x79\
-\x3d\x22\x31\x33\x22\x20\x2f\x3e\x0a\x20\x20\x3c\x6d\x65\x74\x61\
-\x64\x61\x74\x61\x0a\x20\x20\x20\x20\x20\x69\x64\x3d\x22\x6d\x65\
-\x74\x61\x64\x61\x74\x61\x37\x22\x3e\x0a\x20\x20\x20\x20\x3c\x72\
-\x64\x66\x3a\x52\x44\x46\x3e\x0a\x20\x20\x20\x20\x20\x20\x3c\x63\
-\x63\x3a\x57\x6f\x72\x6b\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\
-\x72\x64\x66\x3a\x61\x62\x6f\x75\x74\x3d\x22\x22\x3e\x0a\x20\x20\
-\x20\x20\x20\x20\x20\x20\x3c\x64\x63\x3a\x66\x6f\x72\x6d\x61\x74\
-\x3e\x69\x6d\x61\x67\x65\x2f\x73\x76\x67\x2b\x78\x6d\x6c\x3c\x2f\
-\x64\x63\x3a\x66\x6f\x72\x6d\x61\x74\x3e\x0a\x20\x20\x20\x20\x20\
-\x20\x20\x20\x3c\x64\x63\x3a\x74\x79\x70\x65\x0a\x20\x20\x20\x20\
-\x20\x20\x20\x20\x20\x20\x20\x72\x64\x66\x3a\x72\x65\x73\x6f\x75\
-\x72\x63\x65\x3d\x22\x68\x74\x74\x70\x3a\x2f\x2f\x70\x75\x72\x6c\
-\x2e\x6f\x72\x67\x2f\x64\x63\x2f\x64\x63\x6d\x69\x74\x79\x70\x65\
-\x2f\x53\x74\x69\x6c\x6c\x49\x6d\x61\x67\x65\x22\x20\x2f\x3e\x0a\
-\x20\x20\x20\x20\x20\x20\x3c\x2f\x63\x63\x3a\x57\x6f\x72\x6b\x3e\
-\x0a\x20\x20\x20\x20\x3c\x2f\x72\x64\x66\x3a\x52\x44\x46\x3e\x0a\
-\x20\x20\x3c\x2f\x6d\x65\x74\x61\x64\x61\x74\x61\x3e\x0a\x20\x20\
-\x3c\x67\x0a\x20\x20\x20\x20\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\
-\x3a\x6c\x61\x62\x65\x6c\x3d\x22\x43\x61\x6c\x71\x75\x65\x20\x31\
-\x22\x0a\x20\x20\x20\x20\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\
-\x67\x72\x6f\x75\x70\x6d\x6f\x64\x65\x3d\x22\x6c\x61\x79\x65\x72\
-\x22\x0a\x20\x20\x20\x20\x20\x69\x64\x3d\x22\x6c\x61\x79\x65\x72\
-\x31\x22\x0a\x20\x20\x20\x20\x20\x74\x72\x61\x6e\x73\x66\x6f\x72\
-\x6d\x3d\x22\x74\x72\x61\x6e\x73\x6c\x61\x74\x65\x28\x2d\x31\x37\
-\x35\x2e\x39\x35\x38\x35\x32\x2c\x2d\x31\x37\x31\x2e\x37\x39\x38\
-\x39\x39\x29\x22\x3e\x0a\x20\x20\x20\x20\x3c\x72\x65\x63\x74\x0a\
-\x20\x20\x20\x20\x20\x20\x20\x73\x74\x79\x6c\x65\x3d\x22\x6f\x70\
-\x61\x63\x69\x74\x79\x3a\x31\x3b\x66\x69\x6c\x6c\x3a\x23\x66\x66\
-\x30\x30\x30\x30\x3b\x66\x69\x6c\x6c\x2d\x6f\x70\x61\x63\x69\x74\
-\x79\x3a\x31\x3b\x66\x69\x6c\x6c\x2d\x72\x75\x6c\x65\x3a\x6e\x6f\
-\x6e\x7a\x65\x72\x6f\x3b\x73\x74\x72\x6f\x6b\x65\x3a\x23\x66\x66\
-\x66\x66\x66\x66\x3b\x73\x74\x72\x6f\x6b\x65\x2d\x77\x69\x64\x74\
-\x68\x3a\x30\x2e\x32\x39\x33\x39\x30\x36\x36\x36\x3b\x73\x74\x72\
-\x6f\x6b\x65\x2d\x6c\x69\x6e\x65\x63\x61\x70\x3a\x62\x75\x74\x74\
-\x3b\x73\x74\x72\x6f\x6b\x65\x2d\x6d\x69\x74\x65\x72\x6c\x69\x6d\
-\x69\x74\x3a\x34\x3b\x73\x74\x72\x6f\x6b\x65\x2d\x64\x61\x73\x68\
-\x61\x72\x72\x61\x79\x3a\x30\x2e\x32\x39\x33\x39\x30\x36\x36\x36\
-\x2c\x20\x30\x2e\x32\x39\x33\x39\x30\x36\x36\x36\x3b\x73\x74\x72\
-\x6f\x6b\x65\x2d\x64\x61\x73\x68\x6f\x66\x66\x73\x65\x74\x3a\x30\
-\x3b\x73\x74\x72\x6f\x6b\x65\x2d\x6f\x70\x61\x63\x69\x74\x79\x3a\
-\x31\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x69\x64\x3d\x22\x72\x65\
-\x63\x74\x32\x31\x36\x30\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x77\
-\x69\x64\x74\x68\x3d\x22\x32\x35\x39\x2e\x39\x37\x30\x38\x39\x22\
-\x0a\x20\x20\x20\x20\x20\x20\x20\x68\x65\x69\x67\x68\x74\x3d\x22\
-\x32\x35\x39\x2e\x39\x37\x30\x38\x39\x22\x0a\x20\x20\x20\x20\x20\
-\x20\x20\x78\x3d\x22\x31\x38\x35\x2e\x30\x39\x39\x32\x37\x22\x0a\
-\x20\x20\x20\x20\x20\x20\x20\x79\x3d\x22\x31\x38\x30\x2e\x39\x33\
-\x39\x37\x34\x22\x20\x2f\x3e\x0a\x20\x20\x20\x20\x3c\x72\x65\x63\
-\x74\x0a\x20\x20\x20\x20\x20\x20\x20\x79\x3d\x22\x31\x37\x36\x2e\
-\x33\x38\x37\x34\x34\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x78\x3d\
-\x22\x31\x38\x30\x2e\x35\x34\x36\x39\x37\x22\x0a\x20\x20\x20\x20\
-\x20\x20\x20\x68\x65\x69\x67\x68\x74\x3d\x22\x32\x36\x39\x2e\x30\
-\x37\x35\x35\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x77\x69\x64\x74\
-\x68\x3d\x22\x32\x36\x39\x2e\x30\x37\x35\x35\x22\x0a\x20\x20\x20\
-\x20\x20\x20\x20\x69\x64\x3d\x22\x72\x65\x63\x74\x32\x31\x36\x32\
-\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x73\x74\x79\x6c\x65\x3d\x22\
-\x6f\x70\x61\x63\x69\x74\x79\x3a\x31\x3b\x66\x69\x6c\x6c\x3a\x6e\
-\x6f\x6e\x65\x3b\x66\x69\x6c\x6c\x2d\x6f\x70\x61\x63\x69\x74\x79\
-\x3a\x31\x3b\x66\x69\x6c\x6c\x2d\x72\x75\x6c\x65\x3a\x6e\x6f\x6e\
-\x7a\x65\x72\x6f\x3b\x73\x74\x72\x6f\x6b\x65\x3a\x23\x66\x66\x30\
-\x30\x30\x30\x3b\x73\x74\x72\x6f\x6b\x65\x2d\x77\x69\x64\x74\x68\
-\x3a\x39\x2e\x31\x37\x36\x38\x39\x38\x39\x36\x3b\x73\x74\x72\x6f\
-\x6b\x65\x2d\x6c\x69\x6e\x65\x63\x61\x70\x3a\x62\x75\x74\x74\x3b\
-\x73\x74\x72\x6f\x6b\x65\x2d\x6d\x69\x74\x65\x72\x6c\x69\x6d\x69\
-\x74\x3a\x34\x3b\x73\x74\x72\x6f\x6b\x65\x2d\x64\x61\x73\x68\x61\
-\x72\x72\x61\x79\x3a\x6e\x6f\x6e\x65\x3b\x73\x74\x72\x6f\x6b\x65\
-\x2d\x64\x61\x73\x68\x6f\x66\x66\x73\x65\x74\x3a\x30\x3b\x73\x74\
-\x72\x6f\x6b\x65\x2d\x6f\x70\x61\x63\x69\x74\x79\x3a\x31\x22\x20\
-\x2f\x3e\x0a\x20\x20\x20\x20\x3c\x70\x61\x74\x68\x0a\x20\x20\x20\
-\x20\x20\x20\x20\x73\x74\x79\x6c\x65\x3d\x22\x66\x69\x6c\x6c\x3a\
-\x75\x72\x6c\x28\x23\x6c\x69\x6e\x65\x61\x72\x47\x72\x61\x64\x69\
-\x65\x6e\x74\x34\x31\x32\x39\x29\x3b\x66\x69\x6c\x6c\x2d\x6f\x70\
-\x61\x63\x69\x74\x79\x3a\x31\x3b\x66\x69\x6c\x6c\x2d\x72\x75\x6c\
-\x65\x3a\x6e\x6f\x6e\x7a\x65\x72\x6f\x3b\x73\x74\x72\x6f\x6b\x65\
-\x3a\x6e\x6f\x6e\x65\x3b\x73\x74\x72\x6f\x6b\x65\x2d\x77\x69\x64\
-\x74\x68\x3a\x35\x3b\x73\x74\x72\x6f\x6b\x65\x2d\x6c\x69\x6e\x65\
-\x63\x61\x70\x3a\x62\x75\x74\x74\x3b\x73\x74\x72\x6f\x6b\x65\x2d\
-\x6d\x69\x74\x65\x72\x6c\x69\x6d\x69\x74\x3a\x34\x3b\x73\x74\x72\
-\x6f\x6b\x65\x2d\x64\x61\x73\x68\x6f\x66\x66\x73\x65\x74\x3a\x30\
-\x3b\x73\x74\x72\x6f\x6b\x65\x2d\x6f\x70\x61\x63\x69\x74\x79\x3a\
-\x31\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x64\x3d\x22\x4d\x20\x31\
-\x38\x35\x2e\x30\x39\x33\x37\x35\x2c\x31\x38\x30\x2e\x39\x33\x37\
-\x35\x20\x4c\x20\x31\x38\x35\x2e\x30\x39\x33\x37\x35\x2c\x33\x35\
-\x32\x2e\x35\x36\x32\x35\x20\x43\x20\x31\x39\x30\x2e\x39\x33\x37\
-\x35\x32\x2c\x33\x35\x32\x2e\x37\x39\x39\x38\x32\x20\x31\x39\x36\
-\x2e\x38\x33\x38\x35\x36\x2c\x33\x35\x32\x2e\x39\x33\x37\x35\x20\
-\x32\x30\x32\x2e\x37\x38\x31\x32\x35\x2c\x33\x35\x32\x2e\x39\x33\
-\x37\x35\x20\x43\x20\x33\x31\x32\x2e\x38\x30\x30\x31\x34\x2c\x33\
-\x35\x32\x2e\x39\x33\x37\x35\x20\x34\x30\x36\x2e\x39\x35\x30\x34\
-\x39\x2c\x33\x31\x31\x2e\x36\x31\x30\x34\x34\x20\x34\x34\x35\x2e\
-\x30\x36\x32\x35\x2c\x32\x35\x33\x2e\x32\x35\x20\x4c\x20\x34\x34\
-\x35\x2e\x30\x36\x32\x35\x2c\x31\x38\x30\x2e\x39\x33\x37\x35\x20\
-\x4c\x20\x31\x38\x35\x2e\x30\x39\x33\x37\x35\x2c\x31\x38\x30\x2e\
-\x39\x33\x37\x35\x20\x7a\x20\x22\x0a\x20\x20\x20\x20\x20\x20\x20\
-\x69\x64\x3d\x22\x70\x61\x74\x68\x33\x31\x34\x34\x22\x20\x2f\x3e\
-\x0a\x20\x20\x20\x20\x3c\x70\x61\x74\x68\x0a\x20\x20\x20\x20\x20\
-\x20\x20\x73\x6f\x64\x69\x70\x6f\x64\x69\x3a\x74\x79\x70\x65\x3d\
-\x22\x61\x72\x63\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x73\x74\x79\
-\x6c\x65\x3d\x22\x6f\x70\x61\x63\x69\x74\x79\x3a\x31\x3b\x66\x69\
-\x6c\x6c\x3a\x6e\x6f\x6e\x65\x3b\x66\x69\x6c\x6c\x2d\x6f\x70\x61\
-\x63\x69\x74\x79\x3a\x31\x3b\x66\x69\x6c\x6c\x2d\x72\x75\x6c\x65\
-\x3a\x6e\x6f\x6e\x7a\x65\x72\x6f\x3b\x73\x74\x72\x6f\x6b\x65\x3a\
-\x23\x30\x30\x30\x30\x30\x30\x3b\x73\x74\x72\x6f\x6b\x65\x2d\x77\
-\x69\x64\x74\x68\x3a\x35\x3b\x73\x74\x72\x6f\x6b\x65\x2d\x6c\x69\
-\x6e\x65\x63\x61\x70\x3a\x62\x75\x74\x74\x3b\x73\x74\x72\x6f\x6b\
-\x65\x2d\x6d\x69\x74\x65\x72\x6c\x69\x6d\x69\x74\x3a\x34\x3b\x73\
-\x74\x72\x6f\x6b\x65\x2d\x64\x61\x73\x68\x61\x72\x72\x61\x79\x3a\
-\x6e\x6f\x6e\x65\x3b\x73\x74\x72\x6f\x6b\x65\x2d\x64\x61\x73\x68\
-\x6f\x66\x66\x73\x65\x74\x3a\x30\x3b\x73\x74\x72\x6f\x6b\x65\x2d\
-\x6f\x70\x61\x63\x69\x74\x79\x3a\x31\x22\x0a\x20\x20\x20\x20\x20\
-\x20\x20\x69\x64\x3d\x22\x70\x61\x74\x68\x33\x31\x34\x36\x22\x0a\
-\x20\x20\x20\x20\x20\x20\x20\x73\x6f\x64\x69\x70\x6f\x64\x69\x3a\
-\x63\x78\x3d\x22\x33\x30\x33\x2e\x36\x34\x36\x22\x0a\x20\x20\x20\
-\x20\x20\x20\x20\x73\x6f\x64\x69\x70\x6f\x64\x69\x3a\x63\x79\x3d\
-\x22\x31\x32\x39\x2e\x39\x38\x35\x34\x34\x22\x0a\x20\x20\x20\x20\
-\x20\x20\x20\x73\x6f\x64\x69\x70\x6f\x64\x69\x3a\x72\x78\x3d\x22\
-\x30\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x73\x6f\x64\x69\x70\x6f\
-\x64\x69\x3a\x72\x79\x3d\x22\x37\x2e\x32\x37\x39\x31\x38\x35\x33\
-\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x64\x3d\x22\x4d\x20\x33\x30\
-\x33\x2e\x36\x34\x36\x20\x31\x32\x39\x2e\x39\x38\x35\x34\x34\x20\
-\x41\x20\x30\x20\x37\x2e\x32\x37\x39\x31\x38\x35\x33\x20\x30\x20\
-\x31\x20\x31\x20\x20\x33\x30\x33\x2e\x36\x34\x36\x2c\x31\x32\x39\
-\x2e\x39\x38\x35\x34\x34\x20\x41\x20\x30\x20\x37\x2e\x32\x37\x39\
-\x31\x38\x35\x33\x20\x30\x20\x31\x20\x31\x20\x20\x33\x30\x33\x2e\
-\x36\x34\x36\x20\x31\x32\x39\x2e\x39\x38\x35\x34\x34\x20\x7a\x22\
-\x20\x2f\x3e\x0a\x20\x20\x20\x20\x3c\x72\x65\x63\x74\x0a\x20\x20\
-\x20\x20\x20\x20\x20\x79\x3d\x22\x31\x38\x30\x2e\x39\x33\x39\x37\
-\x34\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x78\x3d\x22\x31\x38\x35\
-\x2e\x30\x39\x39\x32\x37\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x68\
-\x65\x69\x67\x68\x74\x3d\x22\x32\x35\x39\x2e\x39\x37\x30\x38\x39\
-\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x77\x69\x64\x74\x68\x3d\x22\
-\x32\x35\x39\x2e\x39\x37\x30\x38\x39\x22\x0a\x20\x20\x20\x20\x20\
-\x20\x20\x69\x64\x3d\x22\x72\x65\x63\x74\x33\x31\x33\x34\x22\x0a\
-\x20\x20\x20\x20\x20\x20\x20\x73\x74\x79\x6c\x65\x3d\x22\x6f\x70\
-\x61\x63\x69\x74\x79\x3a\x31\x3b\x66\x69\x6c\x6c\x3a\x75\x72\x6c\
-\x28\x23\x72\x61\x64\x69\x61\x6c\x47\x72\x61\x64\x69\x65\x6e\x74\
-\x33\x31\x34\x32\x29\x3b\x66\x69\x6c\x6c\x2d\x6f\x70\x61\x63\x69\
-\x74\x79\x3a\x31\x3b\x66\x69\x6c\x6c\x2d\x72\x75\x6c\x65\x3a\x6e\
-\x6f\x6e\x7a\x65\x72\x6f\x3b\x73\x74\x72\x6f\x6b\x65\x3a\x23\x66\
-\x66\x66\x66\x66\x66\x3b\x73\x74\x72\x6f\x6b\x65\x2d\x77\x69\x64\
-\x74\x68\x3a\x30\x2e\x32\x39\x33\x39\x30\x36\x36\x36\x3b\x73\x74\
-\x72\x6f\x6b\x65\x2d\x6c\x69\x6e\x65\x63\x61\x70\x3a\x62\x75\x74\
-\x74\x3b\x73\x74\x72\x6f\x6b\x65\x2d\x6d\x69\x74\x65\x72\x6c\x69\
-\x6d\x69\x74\x3a\x34\x3b\x73\x74\x72\x6f\x6b\x65\x2d\x64\x61\x73\
-\x68\x61\x72\x72\x61\x79\x3a\x30\x2e\x32\x39\x33\x39\x30\x36\x36\
-\x36\x2c\x20\x30\x2e\x32\x39\x33\x39\x30\x36\x36\x36\x3b\x73\x74\
-\x72\x6f\x6b\x65\x2d\x64\x61\x73\x68\x6f\x66\x66\x73\x65\x74\x3a\
-\x30\x3b\x73\x74\x72\x6f\x6b\x65\x2d\x6f\x70\x61\x63\x69\x74\x79\
-\x3a\x31\x22\x20\x2f\x3e\x0a\x20\x20\x3c\x2f\x67\x3e\x0a\x3c\x2f\
-\x73\x76\x67\x3e\x0a\
-"
-
-qt_resource_name = "\
-\x00\x05\
-\x00\x6f\xa6\x53\
-\x00\x69\
-\x00\x63\x00\x6f\x00\x6e\x00\x73\
-\x00\x0f\
-\x01\x19\xe4\x67\
-\x00\x6c\
-\x00\x65\x00\x64\x00\x5f\x00\x72\x00\x65\x00\x64\x00\x5f\x00\x6f\x00\x66\x00\x66\x00\x2e\x00\x73\x00\x76\x00\x67\
-\x00\x0d\
-\x0e\xf5\xe6\x07\
-\x00\x6c\
-\x00\x65\x00\x64\x00\x5f\x00\x67\x00\x72\x00\x65\x00\x65\x00\x6e\x00\x2e\x00\x73\x00\x76\x00\x67\
-\x00\x11\
-\x09\x14\xa8\xe7\
-\x00\x6c\
-\x00\x65\x00\x64\x00\x5f\x00\x67\x00\x72\x00\x65\x00\x65\x00\x6e\x00\x5f\x00\x6f\x00\x66\x00\x66\x00\x2e\x00\x73\x00\x76\x00\x67\
-\
-\x00\x0b\
-\x08\x52\x2e\x07\
-\x00\x6c\
-\x00\x65\x00\x64\x00\x5f\x00\x72\x00\x65\x00\x64\x00\x2e\x00\x73\x00\x76\x00\x67\
-"
-
-qt_resource_struct = "\
-\x00\x00\x00\x00\x00\x02\x00\x00\x00\x01\x00\x00\x00\x01\
-\x00\x00\x00\x00\x00\x02\x00\x00\x00\x04\x00\x00\x00\x02\
-\x00\x00\x00\x10\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\
-\x00\x00\x00\x7c\x00\x00\x00\x00\x00\x01\x00\x00\x39\xd9\
-\x00\x00\x00\x54\x00\x00\x00\x00\x00\x01\x00\x00\x29\x35\
-\x00\x00\x00\x34\x00\x00\x00\x00\x00\x01\x00\x00\x14\x9b\
-"
-
-def qInitResources():
-    QtCore.qRegisterResourceData(0x01, qt_resource_struct, qt_resource_name, qt_resource_data)
-
-def qCleanupResources():
-    QtCore.qUnregisterResourceData(0x01, qt_resource_struct, qt_resource_name, qt_resource_data)
-
-qInitResources()
--- a/plotter/hpgl_qt.py	Mon Feb 04 19:49:48 2008 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,144 +0,0 @@
-# -*- coding: utf-8 -*-
-import numpy
-import pylab
-import math
-import new # monkey patching...
-
-from PyQt4 import QtGui, QtCore
-from PyQt4.QtCore import Qt, SIGNAL
-
-from hpgl_parser import HPGLParser
-
-class QHPGLPlotterWidget(HPGLParser, QtGui.QWidget):
-    pen_styles = {2: [0.4, 0.6],
-                  3: [0.6, 0.4],
-                  4: [0.7, 0.1, 0.1, 0.1],
-                  5: [0.6, 0.1, 0.2, 0.1],
-                  6: [0.45, 0.1, 0.1, 0.2, 0.1, 0.05],
-                  }
-    pen_colors = ["black", "green", "red", "blue", "yellow", "cyan", "magenta",
-                  "darkred", "darkblue"]
-    
-    def __init__(self, parent=None):
-        QtGui.QWidget.__init__(self, parent)
-        l = QtGui.QVBoxLayout(self)
-        l.setMargin(1)
-        self.qview = QtGui.QGraphicsView(self)
-        self.qview.setRenderHints(QtGui.QPainter.Antialiasing)
-        self.qview.scale(0.5,-0.5)
-        l = self.layout()
-        l.addWidget(self.qview)
-        self.setBackgroundRole(QtGui.QPalette.Base)
-        self.setSizePolicy(QtGui.QSizePolicy.Expanding,
-                           QtGui.QSizePolicy.Expanding)
-        self.clear()
-        HPGLParser.__init__(self)
-
-    def parse(self, data):
-        HPGLParser.parse(self, data)
-        self.resize(self.size())
-        
-    def clear(self):
-        self.qpen = QtGui.QPen(QtCore.Qt.blue)
-        self.qbrush = QtGui.QBrush(QtCore.Qt.blue)
-        self.qfont = QtGui.QFont('Courier') 
-        self.qantialiased = False
-        self.qtransformed = False
-        self.qscene = QtGui.QGraphicsScene()
-        self.qview.setScene(self.qscene)
-        
-    def _get_PW(self):
-        return self._pen_width
-    def _set_PW(self, value):
-        value = float(value)
-        #print "set pen width", value, value*300.0/75.0
-        #self.qpen.setWidthF(value*300.0/75.0)
-        self._pen_width = value
-    pen_width = property(_get_PW, _set_PW)
-        
-    def LT(self):
-        HPGLParser.LT(self)
-        if self.line_type == 0:
-            self.qpen.setStyle(Qt.SolidLine)
-        elif self.line_type == 1:
-            self.qpen.setStyle(Qt.DotLine)
-        else:
-            pattern = numpy.array(self.pen_styles[self.line_type])
-            x0, x1, y0, y1 = self.scale
-            dist = math.sqrt((x1-x0)**2 + (y1-y0)**2)
-            pattern = self.pattern_len*dist/100.0 * pattern
-            if self.qpen.widthF()>0:
-                pattern = pattern/self.qpen.widthF()
-            self.qpen.setDashPattern(pattern.tolist())
-            
-    def SP(self):
-        HPGLParser.SP(self)
-        color = self.pen_colors[self.pen]
-        if isinstance(color, tuple):
-            color = QtGui.QColor(*color)
-        else:
-            color = QtGui.QColor(color)
-        self.qpen.setColor(color)
-        
-    def parse(self, data):
-        HPGLParser.parse(self, data)
-        self.update()
-        self.qview.fitInView(self.qscene.sceneRect(), Qt.KeepAspectRatio)
-        
-    def minimumSizeHint(self):
-        return QtCore.QSize(100, 100)
-
-    def sizeHint(self):
-        return QtCore.QSize(400, 400)
-
-    def resizeEvent(self, event):
-        self.qview.fitInView(self.qscene.sceneRect(), Qt.KeepAspectRatio)
-        QtGui.QWidget.resizeEvent(self, event)
-
-    def plot_lines(self, points):
-        if len(points) == 1:
-            return
-        pa = QtGui.QPainterPath()
-        pa.addPolygon(QtGui.QPolygonF([QtCore.QPointF(*p) for p in points]))
-        self.qscene.addPath(pa, self.qpen)
-        
-    def plot_symbols(self, points):
-        pass
-    
-    def plot_string(self, s):
-        cw, ch = self.get_char_size()
-        # this is very ugly and so, but I don't understand haw is
-        # computed string positionning in HPGL...
-        t0 = self.qscene.addSimpleText(" ", self.qfont) 
-        br = t0.boundingRect()
-        mw = br.width()
-        mh = br.height()
-        self.qscene.removeItem(t0)
-        # don't ask me why theses constants are here, they seem OK, that's all
-        t = self.qscene.addSimpleText(s, self.qfont)
-        t.scale(1.0 * cw/mw, -1.6 * ch/mh)
-        x, y = self.pos
-        t.moveBy(x,y)
-        br = t.boundingRect()
-        t.moveBy(-0.5*cw+8, math.sqrt(2)*ch - 13)
-
-        
-if __name__=='__main__':
-    import sys
-    a = QtGui.QApplication(sys.argv)
-    mw = QtGui.QMainWindow()
-    w = QtGui.QWidget(mw)
-    mw.setCentralWidget(w)
-
-    l = QtGui.QVBoxLayout(w)
-    p = QHPGLPlotterWidget(w)
-    l.addWidget(p, 1)
-    b = QtGui.QPushButton("Replot", w)
-    l.addWidget(b)
-    def plot():
-        p.parse(open(sys.argv[1]).read())
-    b.connect(b, SIGNAL('pressed()'), plot)
-    mw.show()
-    plot()
-    a.exec_()
-    
--- a/plotter/qgpib_plotter.py	Mon Feb 04 19:49:48 2008 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,347 +0,0 @@
-#
-
-import os, sys
-import time
-import glob
-
-from PyQt4 import QtGui, QtCore, uic
-from PyQt4.QtCore import SIGNAL, Qt
-
-if "-m" in sys.argv:
-    from gpib_plotter_mockup import GPIBplotter
-else:
-    from gpib_plotter import GPIBplotter
-from hpgl_qt import QHPGLPlotterWidget
-import hpgl_plotter_rc
-
-ldir = os.path.abspath(os.path.dirname(__file__))
-sys.path.append(ldir)
-form_class, base_class = uic.loadUiType(os.path.join(ldir, "qhpgl_plotter.ui"))
-
-from qpreferences import BaseItem, IntItem, UnicodeItem, ColorItem
-from qpreferences import PointItem, SizeItem, ByteArrayItem
-from qpreferences import AbstractPreferences
-from qpreferenceseditor import PreferencesEditor
-
-from tools import str_num_cmp
-
-class Preferences(AbstractPreferences):
-    ORGANISATION="Logilab"
-    APPLICATION="qgpib_plotter"
-
-    _pos = PointItem()
-    _size = SizeItem()
-    _appState = ByteArrayItem()
-
-    device = UnicodeItem(default='/dev/ttyUSB0',
-                         name=u'device',
-                         description=u'GPIB device',
-                         group="GPIB settings")
-    address = IntItem(default=5, min=0, max=16,
-                      name=u'GPIB address',
-                      group="GPIB settings")
-    
-    background = ColorItem(default=QtGui.QColor("white"),
-                           name="Background",
-                           group="Colors")
-    color0 = ColorItem(default=QtGui.QColor("black"),
-                       name="Pen #0",
-                       group="Colors")
-    color1 = ColorItem(default=QtGui.QColor("green"),
-                       name="Pen #1",
-                       group="Colors")
-    color2 = ColorItem(default=QtGui.QColor("red"),
-                       name="Pen #2",
-                       group="Colors")
-    color3 = ColorItem(default=QtGui.QColor("blue"),
-                       name="Pen #3",
-                       group="Colors")
-    color4 = ColorItem(default=QtGui.QColor("yellow"),
-                       name="Pen #4",
-                       group="Colors")
-    color5 = ColorItem(default=QtGui.QColor("cyan"),
-                       name="Pen #5",
-                       group="Colors")
-    color6 = ColorItem(default=QtGui.QColor("magenta"),
-                       name="Pen #6",
-                       group="Colors")
-    color7 = ColorItem(default=QtGui.QColor("darkred"),
-                       name="Pen #7",
-                       group="Colors")
-    
-class QtHPGLPlotter(QtGui.QMainWindow, form_class):
-    def __init__(self, parent=None):
-        QtGui.QMainWindow.__init__(self, parent)
-        self._plots = {}        
-        self._prefs = Preferences()
-        self.setupUi()
-        self.initializeGPIB()
-        if self._prefs._pos:
-            self.move(self._prefs._pos)
-        if self._prefs._size:
-            self.resize(self._prefs._size)
-        if self._prefs._appState:
-            self.restoreState(self._prefs._appState)
-        self.readPreferences()
-
-    def readPreferences(self):
-        bg = self._prefs.background
-        if bg and bg.isValid():
-            self.plotterWidget.qview.setBackgroundBrush(QtGui.QBrush(bg))
-        pen_colors = [self._prefs["color%d"%i] for i in range(8)]
-        self.plotterWidget.pen_colors = pen_colors
-        
-    def replotCurrent(self):
-        self.currentPlotChanged(self.plotsView.currentIndex())
-        
-    def setupUi(self):
-        form_class.setupUi(self, self) # call qtdesigner generated form creation        
-        # actions defined in designer
-        self.connect(self.actionPreferences, SIGNAL('triggered(bool)'),
-                     self.preferencesTriggered)
-        self.connect(self.actionQuit, SIGNAL('triggered(bool)'),
-                     self.quitTriggered)
-        self.actionQuit.setShortcut(QtGui.QKeySequence(u'Ctrl+Q'))
-        self.connect(self.actionOpen, SIGNAL('triggered(bool)'),
-                     self.openTriggered)
-        self.actionOpen.setShortcut(QtGui.QKeySequence(u'Ctrl+O'))
-        self.connect(self.actionSave, SIGNAL('triggered(bool)'),
-                     self.saveTriggered)
-        self.actionSave.setShortcut(QtGui.QKeySequence(u'Ctrl+S'))
-        self.connect(self.actionSaveAs, SIGNAL('triggered(bool)'),
-                     self.saveAsTriggered)
-
-        self.plotterWidget = QHPGLPlotterWidget(self)
-        self.setCentralWidget(self.plotterWidget)
-
-        self.connect(self.captureButton, SIGNAL("toggled(bool)"),
-                     self.captureToggled)
-
-        self._plots_list = QtGui.QStringListModel()
-        self.plotsView.setModel(self._plots_list)
-        self.connect(self.plotsView, SIGNAL('activated(const QModelIndex&)'),
-                     self.currentPlotChanged)
-        self.connect(self.plotsView.selectionModel(),
-                     SIGNAL('currentChanged(const QModelIndex&, const QModelIndex&)'),
-                     self.currentPlotChanged)
-
-    def currentPlotChanged(self, index, old_index=None):
-        if index.isValid():
-            value = unicode(self.plotsView.model().data(index, Qt.DisplayRole).toString())
-            
-            self.plotterWidget.clear()
-            self.plotterWidget.parse(self._plots[value])
-            
-    def preferencesTriggered(self, checked=False):
-        PreferencesEditor(self._prefs, self).exec_()
-        self.readPreferences()
-        self.replotCurrent()
-
-    def quitTriggered(self, checked=False):
-        self.close()
-
-    def closeEvent(self, event):
-        if 1:
-        #if self.promptForSave():
-            self._prefs._pos = self.pos()
-            self._prefs._size = self.size()
-            self._prefs._appState = self.saveState()
-            event.accept()
-        else:
-            event.ignore()
-        
-    def openTriggered(self, checked=False):
-        filenames = QtGui.QFileDialog.getOpenFileNames(self, "Open a HPGL file to display", '.', 'HPGL files (*.plt)\nAll files (*)')
-        self.openFiles(filenames)
-        self.displayFirst()
-        
-    def displayFirst(self):
-        if not self.plotsView.currentIndex().isValid():
-            self.plotsView.setCurrentIndex(self.plotsView.model().index(0, 0))
-        
-    def openFiles(self, filenames):
-        ok = False
-        for filename in filenames:
-            filename = str(filename)
-            if os.path.exists(filename):
-                data = open(filename).read()
-                name = os.path.basename(filename)
-                name = os.path.splitext(name)[0]
-                lst = self.plotsView.model().stringList()
-                lst.append(name)            
-                self._plots[name] = data
-                self.plotsView.model().setStringList(lst)
-                ok = True
-        return ok
-        
-    def plotReceived(self, num):
-        self._receiving = False
-        self.setReceivingLed()
-        plot, timestamp = self.captureThread.getPlot(num)
-        name = "plot_%s"%(num)
-        lst = self.plotsView.model().stringList()
-        lst.append(name)            
-        self._plots[name] = plot
-        self.plotsView.model().setStringList(lst)
-
-    def plotStarted(self):
-        self._receiving = True
-        self.setReceivingLed()
-        
-    def saveTriggered(self, checked=False):
-        print "save"
-        
-    def saveAsTriggered(self, checked=False):
-        index = self.plotsView.selectionModel().currentIndex()
-        if index.isValid():
-            filename = QtGui.QFileDialog.getSaveFileName(self, "Selecte a file name to save HPGL file", '.', 'HPGL files (*.plt)\nAll files (*)')
-            n = index.row()
-            value = unicode(self.plotsView.model().data(index, Qt.DisplayRole).toString())
-            open(filename, 'w').write(self._plots[value])
-            
-        
-    def initializeGPIB(self):
-        self._online = False
-        try:
-            self.gpib_plotter = QGPIBplotter(device=self._prefs.device,
-                                            address=self._prefs.address,
-                                            )
-            self.captureThread = GPIBReceiver(self.gpib_plotter)
-            self.connect(self.captureThread, SIGNAL('plotReceived(int)'),
-                         self.plotReceived)
-            self.connect(self.captureThread, SIGNAL('plotStarted()'),
-                         self.plotStarted)
-            self.captureThread.start()
-        except Exception, e:
-            #print e
-            self.gpib_plotter = None
-        self.setCaptureLed()
-
-    def captureToggled(self, state):
-        if state:
-            if self.gpib_plotter is None:
-                self.initializeGPIB()
-                if self.gpib_plotter is None:
-                    QtGui.QMessageBox.critical(self, self.tr("GPIB error"),
-                                               self.tr("<b>Unable to initialize GPIB connection</b>.<br>Please check your GPIB dongle and settings."))
-                    self._online = False
-                    self.setCaptureLed()
-                    return
-            self._online = True
-            self.captureThread.startCapture()
-        else:
-            if self.captureThread:
-                self.captureThread.stopCapture()
-            self._online = False
-        self.setCaptureLed()
-        
-    def setCaptureLed(self):
-        if self._online:
-            icn = QtGui.QIcon(':/icons/led_green.svg')
-        else:
-            icn = QtGui.QIcon(':/icons/led_green_off.svg')
-        self.captureButton.setIcon(icn)
-        self.captureButton.setChecked(self._online)
-
-    def setReceivingLed(self):
-        if self._receiving:
-            icn = QtGui.QIcon(':/icons/led_red.svg')
-        else:
-            icn = QtGui.QIcon(':/icons/led_red_off.svg')
-        self.receivingButton.setIcon(icn)
-
-class QGPIBplotter(GPIBplotter):
-    def __init__(self, device="/dev/ttyUSB0", baudrate=115200, timeout=0.1,
-                 address=5):
-        GPIBplotter.__init__(self, device, baudrate, timeout, address)        
-        self.emitter = None
-
-    def plotStarted(self):
-        if self.emitter:
-            self.emitter.emit(SIGNAL('plotStarted()'))
-            #self.emitter.msleep(1)
-        
-class GPIBReceiver(QtCore.QThread):
-    def __init__(self, cnx):
-        QtCore.QThread.__init__(self)
-        self.gpibplotter = cnx
-        self.gpibplotter.emitter = self
-        
-        self._cancelmutex = QtCore.QMutex()
-        self._cancel = False
-        #self._nreceived = 0
-        self._plotsmutex = QtCore.QMutex()
-        self._plots = []
-        self._startstopmutex = QtCore.QMutex()
-        self._startstop = QtCore.QWaitCondition()
-        self._capturing = False
-        
-    def cancel(self):
-        self._cancelmutex.lock()
-        self._cancel = True
-        self._cancelmutex.unlock()
-
-    def startCapture(self):
-        self._startstop.wakeOne()
-
-    def stopCapture(self):
-        self._startstopmutex.lock()
-        self._capturing = False
-        self._startstopmutex.unlock()
-
-    def run(self):
-        while 1:
-            self._cancelmutex.lock()
-            if self._cancel:
-                return
-            self._cancelmutex.unlock()
-            self._startstopmutex.lock()
-            if not self._capturing:
-                self._startstop.wait(self._startstopmutex)
-                self._capturing = True
-            self._startstopmutex.unlock()
-        
-            plot = self.gpibplotter.load_plot(wait_timeout=0.1)
-            timestamp = time.time()
-            if plot:
-                self._plotsmutex.lock()
-                self._plots.append((plot, timestamp))
-                n = len(self._plots)
-                self._plotsmutex.unlock()
-                self.emit(SIGNAL('plotReceived(int)'), n-1)
-            self.msleep(10)
-            
-    def getPlot(self, num):
-        self._plotsmutex.lock()
-        try:
-            return self._plots[num]
-        finally:
-            self._plotsmutex.unlock()
-
-def main():
-    import optparse
-    opt = optparse.OptionParser('A simple PyQt4 HP7470A GPIB plotter emulator for USB-GPIB bundle (ProLogix)')
-    opt.add_option('-m', '--mockup', default=False,
-                   action="store_true",
-                   dest='mockup',
-                   help='Use a pseudo GPIB connection (for test purpose)',
-                   )
-    opt.add_option('-v', '--verbose', default=False,
-                   action="store_true",
-                   dest="verbose",
-                   help="Verbose mode",)
-    
-    options, argv = opt.parse_args(sys.argv)
-
-    a = QtGui.QApplication(argv)
-    w = QtHPGLPlotter()
-    files = [f for f in argv[1:] if os.path.isfile(f)]
-    files.sort(cmp=str_num_cmp)
-    if w.openFiles(files):    
-        w.displayFirst()
-
-    w.show()
-    a.exec_()
-        
-if __name__ == '__main__':
-    main()
--- a/plotter/qhpgl_plotter.ui	Mon Feb 04 19:49:48 2008 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,166 +0,0 @@
-<ui version="4.0" >
- <class>MainWindow</class>
- <widget class="QMainWindow" name="MainWindow" >
-  <property name="geometry" >
-   <rect>
-    <x>0</x>
-    <y>0</y>
-    <width>507</width>
-    <height>492</height>
-   </rect>
-  </property>
-  <property name="windowTitle" >
-   <string>MainWindow</string>
-  </property>
-  <widget class="QWidget" name="centralwidget" />
-  <widget class="QMenuBar" name="menubar" >
-   <property name="geometry" >
-    <rect>
-     <x>0</x>
-     <y>0</y>
-     <width>507</width>
-     <height>25</height>
-    </rect>
-   </property>
-   <widget class="QMenu" name="menu_File" >
-    <property name="title" >
-     <string>&amp;File</string>
-    </property>
-    <addaction name="actionOpen" />
-    <addaction name="actionSave" />
-    <addaction name="actionSaveAs" />
-    <addaction name="separator" />
-    <addaction name="actionQuit" />
-   </widget>
-   <widget class="QMenu" name="menuEdit" >
-    <property name="title" >
-     <string>Edit</string>
-    </property>
-    <addaction name="actionPreferences" />
-   </widget>
-   <addaction name="menu_File" />
-   <addaction name="menuEdit" />
-  </widget>
-  <widget class="QStatusBar" name="statusbar" />
-  <widget class="QDockWidget" name="plotsDock" >
-   <attribute name="dockWidgetArea" >
-    <number>1</number>
-   </attribute>
-   <widget class="QWidget" name="dockWidgetContents" >
-    <layout class="QVBoxLayout" >
-     <property name="spacing" >
-      <number>4</number>
-     </property>
-     <property name="leftMargin" >
-      <number>1</number>
-     </property>
-     <property name="topMargin" >
-      <number>4</number>
-     </property>
-     <property name="rightMargin" >
-      <number>1</number>
-     </property>
-     <property name="bottomMargin" >
-      <number>1</number>
-     </property>
-     <item>
-      <layout class="QHBoxLayout" >
-       <item>
-        <widget class="QToolButton" name="captureButton" >
-         <property name="minimumSize" >
-          <size>
-           <width>0</width>
-           <height>29</height>
-          </size>
-         </property>
-         <property name="text" >
-          <string>on line</string>
-         </property>
-         <property name="icon" >
-          <iconset resource="hpgl_plotter.qrc" >:/icons/led_green.svg</iconset>
-         </property>
-         <property name="iconSize" >
-          <size>
-           <width>16</width>
-           <height>16</height>
-          </size>
-         </property>
-         <property name="checkable" >
-          <bool>true</bool>
-         </property>
-         <property name="toolButtonStyle" >
-          <enum>Qt::ToolButtonTextBesideIcon</enum>
-         </property>
-        </widget>
-       </item>
-       <item>
-        <spacer>
-         <property name="orientation" >
-          <enum>Qt::Horizontal</enum>
-         </property>
-         <property name="sizeHint" >
-          <size>
-           <width>40</width>
-           <height>20</height>
-          </size>
-         </property>
-        </spacer>
-       </item>
-       <item>
-        <widget class="QPushButton" name="receivingButton" >
-         <property name="text" >
-          <string/>
-         </property>
-         <property name="icon" >
-          <iconset resource="hpgl_plotter.qrc" >:/icons/led_red_off.svg</iconset>
-         </property>
-         <property name="iconSize" >
-          <size>
-           <width>16</width>
-           <height>16</height>
-          </size>
-         </property>
-         <property name="flat" >
-          <bool>true</bool>
-         </property>
-        </widget>
-       </item>
-      </layout>
-     </item>
-     <item>
-      <widget class="QListView" name="plotsView" />
-     </item>
-    </layout>
-   </widget>
-  </widget>
-  <action name="actionOpen" >
-   <property name="text" >
-    <string>&amp;Open</string>
-   </property>
-  </action>
-  <action name="actionSave" >
-   <property name="text" >
-    <string>&amp;Save</string>
-   </property>
-  </action>
-  <action name="actionSaveAs" >
-   <property name="text" >
-    <string>Save as...</string>
-   </property>
-  </action>
-  <action name="actionQuit" >
-   <property name="text" >
-    <string>&amp;Quit</string>
-   </property>
-  </action>
-  <action name="actionPreferences" >
-   <property name="text" >
-    <string>Preferences</string>
-   </property>
-  </action>
- </widget>
- <resources>
-  <include location="hpgl_plotter.qrc" />
- </resources>
- <connections/>
-</ui>
--- a/prologix.py	Mon Feb 04 19:49:48 2008 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,117 +0,0 @@
-"""
-prologix
-========
-
-Module defining a communication object to talk to Prologix USB-GPIB controler.
-
-"""
-import serial
-import time
-
-import pygpib
-from pygpib import ConnectionError
-
-GPIB_CONTROLLER = 1
-GPIB_DEVICE = 0
-
-class GPIB(object):
-    _retries = 15
-    def __init__(self, device="/dev/ttyUSB0", baudrate=115200, timeout=0.1,
-                    address=0, mode=1):        
-        """
-        Create a new GPIB controller for the Prologix USB-GPIB device
-        located on serial device 'device'.        
-        """
-        self._cnx = serial.Serial(port=device, baudrate=baudrate, timeout=timeout)
-        self._timeout = timeout
-        
-        self.set_mode(mode)
-        self.set_address(address)
-        
-    def set_address(self, address):
-        """
-        Set the address of the GPIB device:
-        
-        - if the device is the Controller In Charge, this is the
-          address of the device commands are sent to,
-
-        - if the device is in GPIB_DEVICE mode, this is its address.
-        """
-        self._set_cmd('addr', address)
-        self._adress = address
-        
-    def set_mode(self, mode):
-        """
-        Set GPIB device mode to 'mode':
-        
-        - GPIB_CONTROLLER: set the device as the Controller In Charge
-          on the GPIB bus
-
-        - GPIB_DEVICE: set the device as a standard GPIB device on the
-          bus.
-        """
-        self._set_cmd('mode', mode)
-        self._mode = mode
-
-    def set_controller(self):
-        """
-        Set GPIB device the Controller In Charge on the GPIB bus.
-        """
-        self.set_mode(1)
-
-    def set_device(self):
-        """
-        Set the GPIB device as a simple device on the GPIB bus.        
-        """
-        self.set_mode(0)
-
-    def send_command(self, cmd):
-        """
-        Send the specified GPIB command on the bus (must be the CIC),
-        and read the answer.
-        """
-        assert self._mode == 1
-        self._cnx.write(cmd+'\r')
-        time.sleep(self._timeout) # required?
-        ret = self._cnx.readlines()
-        return ''.join(ret)
-
-    def check_srq(self):
-        """
-        Check the SRQ line
-        """
-        assert self._mode == 1, "must be the Controller In Charge"
-        self._cnx.write('++srq\r')
-        ret = self._cnx.readline().strip()
-        if ret:
-            return bool(int(ret))
-        return None
-
-    def poll(self):
-        """
-        Poll every address, and return a dictionnary
-         {add: status, ...}        
-        """
-        assert self._mode == 1, "must be the Controller In Charge"
-        dico = {}
-        for add in range(31):
-            self._cnx.write('++spoll %d\r'%i)
-            ret = self._cnx.readline().strip()
-            if ret:
-                dico[i] = int(ret)
-        return dico
-    
-    def _read(self):
-        for i in range(self._retries):
-            rdata = self._cnx.readline()
-            if rdata.strip() != "":
-                break
-            time.sleep(self._timeout)
-        return rdata
-
-    def _set_cmd(self, cmd, value):
-        self._cnx.write('++%s %d\r'%(cmd, value))
-        self._cnx.write('++%s\r'%(cmd))
-        rval = self._read().strip()
-        if not rval.isdigit() or int(rval) != value:
-            raise ConnectionError("Can't set GPIB %s to %s [ret=%s]"%(cmd, value, repr(rval)))
--- a/pygpib.py	Mon Feb 04 19:49:48 2008 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,64 +0,0 @@
-"""
-gpib: create serial connection to GPIB-USB device (ProLogix is the
-only supported device for now).
-"""
-import serial
-from serial.serialutil import SerialException
-import time
-
-class ConnectionError(Exception):
-    pass
-
-class Constants(object):
-    def __init__(self):
-        self.constants = {}
-        self.descriptions = {}
-        self.rev_constants = {}
-        for v, k, m in self._constants:
-            self.k = v
-            self.constants[v] = k
-            self.rev_constants[k] = v
-            self.descriptions[v] = m
-            
-    def __getitem__(self, k):
-        if isinstance(k, basestring):
-            return self.rev_constants[k]
-        else:
-            return self.constants[k]
-
-    def get_description(self, k):
-        if isinstance(k, basestring):
-            k = self.rev_constants[k]
-        return self.descriptions[k]
-    
-
-class MODE(Constants):    
-    _constants = [(1, "CONTROLLER", "Set device as Controller in Charge"),
-                  (0, "DEVICE", "Set device as simple listener"),
-                  ]
-# TODO
-# class STATUS_BYTE(Constants):
-#     # IEEE 488.2 Status Byte constants
-#     MAV = 0x10 # Message AVailable: bit 4 of the Status Byte
-#     ESB = 0x20 # Event Status Bit: bit 5 of the Status Byte
-#     MSS = 0x40 # Master Summary Status bit: bit 6 of the Status Byte (NOT
-#                # sent in response to a serial poll)
-#     RQS = 0x40 # Request Service: bit 6 of the Status Byte (when sent in
-#                # response to a serial poll)
-# class SESR(Constants):
-#     # SESR constants (Standard Event Status Register)
-#     PON = 0x80 # Power On: Power has been turned On since last register
-#                # read access
-#     URQ = 0x40 # User Request: the user has activated some device control
-#                # (whatever the Remote Local state is)
-#     CME = 0x20 # Command Error
-#     EXE = 0x10 # Execution Error
-#     DDE = 0x08 # Device Dependant Error
-#     QYE = 0x04 # QuerY Error (attempt to read data while Output Queue is
-#                # empty, or data in the OQ was lost)
-#     RQC = 0x02 # Request Control: tell the CiC that the device wants to
-#                # become the CiC
-#     OPC = 0x01 # Operation Complete: device has completed any pending
-#                # operation (ready to accept new commands). This bit is
-#                # generated in response to a OPC command.
-    
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/pygpibtoolkit/HP3562A/__init__.py	Tue Feb 05 18:59:29 2008 +0100
@@ -0,0 +1,242 @@
+"""
+HP3562A
+=======
+
+Module for communicating with the HP 3562A Digital Signal Analyzer.
+
+Subpackages
+-----------
+
+
+Constants
+---------
+
+"""
+import struct
+import re
+import pygpibtoolkit.pygpib as gpib
+import numpy
+
+########################################
+# HP3562A internal binary types decoders
+
+def decode_float(s):
+    if len(s) == 4:
+        i1, i2, e = struct.unpack('>hbb', s)
+        i2 = i2 * 2**(-23)
+        return (i1/32768. + i2)*2**e
+    else:
+        i1, i2, i3, i4, e = struct.unpack('>hhhbb', s)
+        if i2 < 0:
+            i2 = (i2+32768.)*2**(-15)
+        else:
+            i2 = i2*2**(-15)
+        if i3 < 0:
+            i3 = (i3+32768.)*2**(-30)
+        else:
+            i3 = i3*2**(-15)
+        i4 = i4 * 2**(-38)
+        return (i1+i2+i3+i4)*2**(e-15)
+        
+# def decode_float(s):
+#     assert len(s) in [4,8]
+#     # exponential term 
+#     e = ord(s[-1])
+#     if e & 0x80:
+#         e = e - 256
+
+#     # mantissa
+#     m = [ord(x) for x in s[:-1]]
+#     M = 0.
+#     for i in range(len(s)-1):
+#         #M += m[i]<<(i*8)
+#         M += float(m[i])/2**((i+1)*8)
+#     # XXX how do we deal negative numbers?
+#     #if m[0] & 0x80:
+#     #    M = M - 2^(len(s))
+#     return M * 2**(e+1)
+
+def decode_string(s):
+    nb = ord(s[0])
+    s = s[1:nb+2]
+    r = ""
+    # XXX why do we need to do this? It's not described in the manual...
+    for c in s:
+        r += chr(ord(c) & 0x7F)
+    return r
+
+
+###
+# Some useful functions
+def format_header(header, head_struct, columns=80):
+    """
+    Pretty print a data block (trace, state or coord) 
+    """
+    bool_re = re.compile(r'((?P<before>.*) )?(?P<flag>\w+/\w+)( (?P<after>.*))?')
+    
+    todisp = []
+    for row in head_struct:
+        key = row[0]
+        typ = row[1]
+        if typ is None:
+            continue
+        val = header.get(key, "N/A")
+        if isinstance(val, basestring):
+            val = repr(val)
+        elif typ is bool and isinstance(val, typ):
+            m = bool_re.match(key)
+            if m:
+                d = m.groupdict()
+                key = ""
+                if d['before']:
+                    key += d['before']
+                if d['after']:
+                    key += d['after']
+                key = key.capitalize()
+                val = d['flag'].split('/')[not val]
+            else:
+                val = str(val)
+        else:            
+            val = str(val)
+        todisp.append((key+":", val))
+    maxk = max([len(k) for k, v in todisp])
+    maxv = max([len(v) for k, v in todisp])
+    fmt = "%%-%ds %%-%ds"%(maxk, maxv)
+    w = maxk+maxv+4
+    ncols = columns/w
+    if ncols:
+        nrows = len(todisp)/ncols
+    else:
+        nrows = len(todisp)
+    res = ""
+    for i in range(nrows):
+        res += "| ".join([fmt%todisp[j*nrows+i] for j in range(ncols)]) + "\n"
+    return res
+
+def decode_header(data, header_struct, idx=0):    
+    d = data
+    if d[idx:].startswith('#'):
+        # we have a preliminary header here...
+        typ = d[idx:idx+2]
+        assert typ == "#A"
+        idx += 2
+        totlen = struct.unpack('>h', d[idx:idx+2])[0]
+        idx += 2
+    tt=0
+    header = {}
+    for i, (nam, dtype, fmt, nbytes) in enumerate(header_struct):
+        if dtype is None:
+            idx += nbytes
+            continue
+        elif dtype == str:
+            val = decode_string(d[idx:])
+        else:
+            if fmt:
+                v = struct.unpack('>'+fmt, d[idx: idx+nbytes])[0]
+                if isinstance(dtype, dict):
+                    val = dtype.get(int(v), "N/A")
+                else:
+                    val = dtype(v)
+            else:
+                val = dtype(d[idx: idx+nbytes])
+        header[nam] = val
+        idx += nbytes
+    return header, idx
+
+def read_trace(data, idx, nelts):
+    assert len(data[idx:]) >= (nelts*4), "data[idx:] is too small (%s for %s)"%(len(data[idx:]), (nelts*4))
+    resu = []
+    for i in range(nelts):
+        resu.append(decode_float(data[idx: idx+4]))
+        idx += 4
+    return numpy.array(resu, dtype=float)
+    
+#####################
+# HP3562A constants
+
+# GPIB buffer size is 3x80 characters lines
+class STATUS_BYTE(gpib.Constants):
+    # HP3562A Status Byte, as returned by a serial poll
+    _constants = [(0x40, "RQS", "Request Service"), # when sent in response to a serial poll
+                  (0x20, "ERR", "GPIB error"),
+                  (0x10, "RDY", "ready to accept GPIB commands"),
+                  ]
+
+    conditions = [(0, "NSR", "No service requested"),
+                  (1, "USRQ1", "User SRQ #1"),
+                  (2, "USRQ1", "User SRQ #2"),
+                  (3, "USRQ1", "User SRQ #3"),
+                  (4, "USRQ1", "User SRQ #4"),
+                  (5, "USRQ1", "User SRQ #5"),
+                  (6, "USRQ1", "User SRQ #6"),
+                  (7, "USRQ1", "User SRQ #7"),
+                  (8, "USRQ1", "User SRQ #8"),
+                  (9, "EOD", "End of disk action"),
+                  (10, "EOP", "End of plot action"),
+                  (11, "STCH", "Instrument status changed"), # any change in 
+                  # the status register sets this condition
+                  (12, "PWR", "Power on"),
+                  (13, "KEY", "Key pressed"),
+                  (14, "DCP", "Device clear plotter (listen)"),
+                  # ...
+                  ]
+    def __init__(self):
+        super(STATUS_BYTE, self).__init__()
+        self._conditions = dict([(x[0], x[1]) for x in self.conditions])
+        self._rev_conditions = dict([(x[1], x[0]) for x in self.conditions])
+        self._long_conditions = dict([(x[0], x[2]) for x in self.conditions])
+               
+    def byte_condition(self, byte):
+        byte = byte & 0x8F
+        return self._conditions.get(byte, "N/A")
+
+class IS_REGISTER(gpib.Constants):
+    _constants = [(0x01, "MEASP", "measeurement pause"),
+                  (0x02, "ASQP", "Auto sequence pause"),
+                  (0X04, "EOM", "End of measurement, capture or throughput"),
+                  (0x08, "EOAS", "End of auto sequence"),
+                  (0x10, "SWPR", "Sweep point ready"),
+                  (0x20, "CH1OV", "Channel 1 overrange"),
+                  (0x40, "CH2OV", "Channel 2 overrange"),
+                  (0X80, "CH1HR", "Channel 1 half range"),
+                  (0x100, "CH2HR", "Channel 2 half range"),
+                  (0x200, "SFALT", "Source falt"),
+                  (0x400, "RUNL", "Reference unlock"),
+                  (0x800, "RMKT", "Remote marker knob turn"),
+                  (0x1000, "REKT", "Remote entry knob turn"),
+                  (0x2000, "ASRC", "Asctive Status Register changed"),
+                  (0x4000, "PWRF", "Power-on test failed"),
+                  ]
+    
+class StatusQuery(gpib.Constants):
+    _command = "STA?"
+    _constants = [(0x01, "N/A", "Not used"),
+                  (0x02, "N/A", "Not used"),
+                  (0x04, "KEY", "Key pressed"),
+                  (0x08, "N/A", "Not used"),
+                  (0x10, "RDY", "Ready"),
+                  (0x20, "ERR", "Error"),
+                  (0x40, "RQS", "Request"),
+                  (0x80, "MOS", "Message on screen"),
+                  (0x100, "MEASP", "measeurement pause"),
+                  (0x200, "ASQP", "Auto sequence pause"),
+                  (0X400, "EOM", "End of measurement, capture or throughput"),
+                  (0x800, "EOAS", "End of auto sequence"),
+                  (0x1000, "SWPR", "Sweep point ready"),
+                  (0x2000, "CH1OV", "Channel 1 overrange"),
+                  (0x4000, "CH2OV", "Channel 2 overrange"),
+                  (0x8000, "MAOV", "Math overflow"),
+                  ]
+class ActivityStatysRegister(gpib.Constants):
+    _command = "AS?"
+    _constants = [(0x01, "CKFL", "Check fault log"),
+                  (0x02, "FITR", "Filling time record"),
+                  (0x04, "FLTR", "Filters settings"),
+                  (0x08, "CFTP", "Curve fir in progress"),
+                  (0x10, "MSSM", "Missed sample"),
+                  (0x20, "TMPR", "Timed preview"),
+                  (0x40, "ACDA", "Accept date"),
+                  #...
+                  ]
+
+    
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/pygpibtoolkit/HP3562A/coord_decoder.py	Tue Feb 05 18:59:29 2008 +0100
@@ -0,0 +1,126 @@
+# -*- coding: utf-8 -*-
+"""
+state_decoder
+=============
+
+Module for decoding the internal state of the HP3562A DSA, using the
+GPIB command "DSBN" (Dump State BiNary).
+
+This file can be exectued as a python script. Use '-h' for more informations. 
+"""
+
+from pygpibtoolkit.HP3562A import format_header, decode_float, decode_string, decode_header, read_trace
+from pygpibtoolkit.HP3562A.trace_decoder import decode_trace, HEADER as TRACE_HEADER
+from pygpibtoolkit.HP3562A.enum_types import *
+
+HEADER = [("Y coordinates", EYCOORD, 'h', 2),
+          ("# of disp elements", int, "h", 2),
+          ("First element", int, "h", 2),
+          ("Total elements", int, 'h', 2),
+          ("Display sampling", EDISPSMP, 'h', 2),
+          ("Scaling", ESCAL, 'h', 2),
+          ("Data pointer", long, 'l', 4),
+          ("In data", long, 'l', 4),
+          ("Log/linear x-axis", bool, 'h', 2),
+          ("Sampled display data", bool, 'h', 2),
+          ("Plot/Graph mode", bool, 'h', 2),
+          ("Phase wrap", bool, 'h', 2),
+          ("Not used", None, None, 36),
+          ("X scale factor", decode_float, None, 4),
+          ("Grid min Y scale", decode_float, None, 4),
+          ("Grid max Y scale", decode_float, None, 4),
+          ("/div", decode_float, None, 4),
+          ("Min value of data", decode_float, None, 4),
+          ("Max value of data", decode_float, None, 4),
+          ("Y cumulative min", decode_float, None, 4),
+          ("Y cumulative max", decode_float, None, 4),
+          ("Y scale factor", decode_float, None, 4),
+          ("Not used", None, None, 16),
+          ("Stop value", decode_float, None, 8),
+          ("Left grid", decode_float, None, 8),
+          ("Right grid", decode_float, None, 8),
+          ("Left data", decode_float, None, 8),
+          ("Right data", decode_float, None, 8),          
+    ]
+
+def decode_coord(data):
+    """
+    Decode the data (as generated by the HP3562A DSA in response to a
+    "DSBN" command), and returns a dict (header)
+
+    header is the dictionnary of the header of the dumped data block,
+    """
+    header, idx = decode_header(data, HEADER)
+    trace_header, idx = decode_header(data, TRACE_HEADER, idx)
+    trace = read_trace(data, idx, trace_header["Number of elements"])
+    return header, trace_header, trace
+    
+
+def main():
+    import sys
+    import optparse
+    import numpy
+    
+    opt = optparse.OptionParser("A simple tool for displaying dumped coord data block")
+    opt.add_option('-f', '--filename', default=None,
+                   dest='filename',
+                   help='Output filename. If not set, read from stdin')
+    opt.add_option('-m', '--mode', default='binary',
+                   dest='mode',
+                   help='Dumping mode (may be "binary" [default], "ascii" or "ansi")',
+                   )
+    opt.add_option('-d', '--display-header', default=False,
+                   action="store_true",
+                   dest="displayheader",
+                   help="Display the trace header")
+    opt.add_option('-P', '--noplot-trace', default=True,
+                   action="store_false",
+                   dest="plot",
+                   help="Do not display the plot of the trace")
+    opt.add_option('-x', '--xmode', default='lin',
+                   dest='xmode',
+                   help='X coordinate mode (may be "lin" [default] or "log")')
+    opt.add_option('-y', '--ymode', default='lin',
+                   dest='ymode',
+                   help='Y coordinate mode (may be "lin" [default], "log" or "db")')
+    
+    options, argv = opt.parse_args(sys.argv)
+
+
+    if options.filename is None:
+        print "Can't deal stdin for now..."
+        sys.exit(1)
+    try:
+        coord_header, header, data = decode_coord(open(options.filename, 'rb').read())
+    except Exception, e:
+        print "ERROR: can't read %s an interpret it as a HP3562 trace"%options.filename
+        print e
+        sys.exit(1)
+
+    if options.displayheader:
+        print format_header(coord_header, HEADER, 100)
+        print format_header(header, TRACE_HEADER, 100)
+    if options.plot:
+        f0 = header['Start freq value']
+        dx = header['Delta X-axis']
+        n = header['Number of elements']
+        x = numpy.linspace(f0, f0+dx*n, len(data)) 
+        y = data.copy()
+
+        ym = coord_header['Min value of data']
+        yM = coord_header['Max value of data']
+        ys = coord_header['Y scale factor']
+        
+        y[y<ym] = ym
+        y *= ys
+        
+        import pylab
+        pylab.ylabel(header['Amplitude units'])
+        pylab.grid()
+        pylab.plot(x, y)
+        pylab.xlabel('frequency (%s)'%header["X axis units"])
+        pylab.ylabel("%s (%s)"%(coord_header['Y coordinates'], header['Amplitude units']) )
+        pylab.show()
+    
+if __name__ == "__main__":
+    main()
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/pygpibtoolkit/HP3562A/dump_datablock.py	Tue Feb 05 18:59:29 2008 +0100
@@ -0,0 +1,87 @@
+import sys
+import time
+import gpib
+import prologix
+
+
+class HP3562dumper(prologix.GPIB):
+    """
+    Class dedicated to dump data blocks from HP3562A DSA (trace,
+    internal state or coordinate).
+    """
+    MODES = {'trace': 'DD',
+             'state': 'DS',
+             'coord': 'DC',
+             }
+    
+    FORMATS = {'binary': 'BN',
+               'ascii': 'AS',
+               'ansi': 'AN'}
+            
+    def __init__(self, device="/dev/ttyUSB0", baudrate=115200, timeout=0.1,
+                 address=0):
+        super(HP3562dumper, self).__init__(device, baudrate, timeout, address, mode=1)
+
+    def dump(self, mode='trace', format="binary"): 
+        """
+        Dump the required data block and return it as a raw string buffer.
+
+        'mode' can be 'trace' [default], 'state' or 'coord'.
+        'format' can be 'binary' [default], 'ascii' or 'ansi'.
+        """
+        format = format.lower()
+        mode = mode.lower()
+        assert mode in self.MODES
+        assert format in self.FORMATS
+        cmd = self.MODES[mode] + self.FORMATS[format]
+
+        res = ""
+        print "command = ", cmd
+        self._cnx.write('%s\r'%cmd)
+        i = 0
+        while i<self._retries:
+            l = self._cnx.readline()
+            if l.strip() == "":
+                i += 1
+                time.sleep(self._timeout)
+                continue
+            res += l 
+            i = 0
+        return res
+
+    
+
+def main():
+    import optparse
+    opt = optparse.OptionParser("A simple tool for dumping the current trace")
+    opt.add_option('-f', '--filename', default=None,
+                   dest='filename',
+                   help='Output filename. If not set, write to stdout')
+    opt.add_option('-d', '--device', default='/dev/ttyUSB0',
+                   dest='device',
+                   help='Device of the RS232 connection (default: /dev/ttyUSB0)',
+                   )
+    opt.add_option('-a', '--address', default=0,
+                   dest='address',
+                   help='GPIB address of the device',
+                   )
+    opt.add_option('-b', '--block', default='trace',
+                   dest='block',
+                   help='Data block to dump (may be "trace" [default], "state" or "coord")',
+                   )
+    opt.add_option('-m', '--mode', default='binary',
+                   dest='mode',
+                   help='Dumping mode (may be "binary" [default], "ascii" or "ansi")',
+                   )
+    options, argv = opt.parse_args(sys.argv)
+
+    cnx = HP3562dumper(device=options.device, address=int(options.address))
+    res = cnx.dump(mode=options.block, format=options.mode)
+    sys.stderr.write("read %s bytes\n"%(len(res)))
+    if options.filename:
+        open(options.filename, 'w').write(res)
+    else:
+        print res
+    
+if __name__=='__main__':
+    main()
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/pygpibtoolkit/HP3562A/enum_types.py	Tue Feb 05 18:59:29 2008 +0100
@@ -0,0 +1,273 @@
+# -*- coding: utf-8 -*-
+"""
+Constants used for HP3562A data block interpretation.
+"""
+
+EDSP = {0: "No data",
+        1: "Frequency response",
+        2: "Power spectrum 1",
+        3: "Power spectrum 2",
+        4: "Coherence",
+        5: "Cross spectrum",
+        6: "Input time 1",
+        7: "Input time 2",
+        8: "Input linear spectrum 1",
+        9: "Input linear spectrum 2",
+        10: "Impulse response",
+        11: "Cross correlation",
+        12: "Auto correlation 1",
+        13: "Auto correlation 2",
+        14: "Histogram 1",
+        15: "Histogram 2",
+        16: "Cumulative density function 1",
+        17: "Cumulative density function 2",
+        18: "Probability density function 1",
+        19: "Probability density function 2",
+        20: "Average linear spectrum 1",
+        21: "Average linear spectrum 2",
+        22: "Average time record 1",
+        23: "Average time record 2",
+        24: "Synthesis pole-zeros",
+        25: "Synthesis pole-residue",
+        26: "Synthesis polynomial",
+        27: "Synthesis constant",
+        28: "Windowed time record 1",
+        29: "Windowed time record 2",
+        30: "Windowed linear spectrum 1",
+        31: "Windowed linear spectrum 2",
+        32: "Filtered time record 1",
+        33: "Filtered time record 2",
+        34: "Filtered linear spectrum 1",
+        35: "Filtered linear spectrum 2",
+        36: "Time capture buffer",
+        37: "Captured linear spectrum",
+        38: "Captured time record",
+        39: "Throughput time record 1",
+        40: "Throughput time record 2",
+        41: "Curve fit",
+        42: "Weighted function",
+        43: "Not used",
+        44: "Orbits",
+        45: "Demodulation polar",
+        46: "Preview demod record 1",
+        47: "Preview demod record 2",
+        48: "Preview demod linear spectrum 1",
+        49: "Preview demod linear spectrum 2",
+        }
+
+ECH = {0: "Channel 1",
+       1: "Channel 2",
+       2: "Channel 1&2",
+       3: "No channel",
+       }
+
+EOVR = ECH
+
+EDOM = {0: 'Time',
+        1: 'Frequency',
+        2: 'Voltage (amplitude)',
+        }
+
+EVLT = {0: "Peak",
+        1: "RMS",
+        2: "Volt (indicates peak only)",
+        }
+
+EAMP = {0: u"Volts",
+        1: u"Volts²",
+        2: u"PSD (V²/Hz)",
+        3: u"ESD (V²s/Hz)",
+        4: u"PSD¹² (V/Hz¹²)",
+        5: u"No unit",
+        6: u"Unit volts",
+        7: u"Unit volts²",
+        }
+        
+EXAXIS= {0: u"No units",
+         1: u"Hertz",
+         2: u"RPM",
+         3: u"Orders",
+         4: u"Seconds",
+         5: u"Revs",
+         6: u"Degrees",
+         7: u"dB",
+         8: u"dBV",
+         9: u"Volts",
+         10: u"V\u221AHz",
+         11: u"Hz/s",
+         12: u"V/EU",
+         13: u"Vrms",
+         14: u"V²/Hz",
+         15: u"%",
+         16: u"Points",
+         17: u"Records",
+         18: u"Ohms",
+         19: u"Hertz/octave",
+         20: u"Pulse/Rev",
+         21: u"Decades",
+         22: u"Minutes",
+         23: u"V²s/Hz",
+         24: u"Octave",
+         25: u"Seconds/Decade",
+         26: u"Seconds/Octave",
+         27: u"Hz/Point",
+         28: u"Points/Sweep",
+         29: u"Points/Decade",
+         30: u"Points/Octave",
+         31: u"V/Vrms",
+         32: u"V²",
+         33: u"EU referenced to chan 1",
+         34: u"EU referenced to chan 2",
+         35: u"EU value",
+         }
+
+EMEAS = {0: "Linear resolution",
+         1: "Log resolution",
+         2: "Swept sine",
+         3: "Time capture",
+         4: "Linear resolution throughput",
+         }
+
+EDEMOD = {45: "AM",
+          46: "FM",
+          47: "PM",
+          }
+
+EAVG = {0: "No data",
+        1: "Not averaged",
+        2: "Averaged",}
+
+EWIN = {0: "N/A",
+        1: "Hann",
+        2: "Flat top",
+        3: "Uniforme",
+        4: "Exponential",
+        5: "Force",
+        6: "Force chan 1/expon chan 2",
+        7: "Expon chan 1/force chan 2",
+        8: "User",
+        }
+
+EMTYP = {0: "Frequency responce",
+         1: "Cross correlation",
+         2: "Power spectrum",
+         3: "Auto correlation",
+         4: "Histogram",
+         5: "No measurement",
+         }
+
+EWINTYP = { 11: "Hanning",
+            12: "Flat top",
+            13: "Uniform",
+            14: "User window",
+            15: "Force/Exponential",
+            }
+
+EFEXPW = { 0: "Force",
+           1: "Exponential",
+           }
+
+EAVGTYP = { 6: "Stable",
+            7: "Exponential",
+            8: "Peak",
+            9: "Continuous peak",
+            10: "Averaging off",
+            }
+
+ETRGTYP = { 18: "Free run",
+            19: "Channel 1",
+            20: "Channel 2",
+            21: "External",
+            22: "Source trigger",
+            23: "HP-IB trigger",
+            }
+
+ETRGSLP = { 16: "Positive",
+            17: "Negative",
+            }
+
+EPRVTYP = { 0: "Manual preview",
+            1: "Timed preview",
+            2: "Preview off",
+            }
+
+ESMPTYP = { 24: "Internal sample",
+            25: "External sample",
+            }
+
+ERNGUNT = EXAXIS
+
+ERNGTYP = { 26: "Auto range on",
+            27: "Auto range off",
+            28: "Auto range set",
+            }
+
+EINCPL = { 29: "AC",
+           30: "DC",
+           }
+
+ESRCTYP = { 31: "Source off",
+            32: "Random noise",
+            33: "Burst random",
+            34: "Periodic chirp",
+            35: "Burst chirp",
+            36: "Swept sine",
+            37: "Fixed sine",
+            }
+
+ESWPDIR = { 41: "Up",
+            42: "Sweep hold",
+            43: "Manual sweep",
+            44: "Down",
+            }
+
+ESWPMOD = { 39: "Linear sweep",
+            40: "Log sweep",
+            }
+
+EEXTSMPFREQUNT = EXAXIS
+
+EBNDUNT = EXAXIS
+
+ESWPRATEUNT = EXAXIS
+
+EAUGAINREFCH = { 0: "Channel 1",
+                 1: "Channel 2",
+                 2: "Not used",
+                 3: "No channel",
+                 }
+EDEMODCH = {  0: "Channel 1",
+              1: "Channel 2",
+              2: "Both channels",
+              3: "No channel",
+              }
+
+ESRCLVLUNT = EXAXIS
+
+ESRCDCOFFST = EXAXIS
+
+ETRGLVLUNT = EXAXIS
+
+ECPTLGHUNT = EXAXIS
+
+EYCOORD = { 1: "Real",
+            2: "Imaginary",
+            3: "Linear magnitude",
+            4: "Log magnitude",
+            5: "dB",
+            6: "Nyquist",
+            7: "Not used",
+            8: "Phase",
+            9: "Nichols",
+            10: "dBm",
+            }
+
+EDISPSMP = { 0: "Not sampled", # #displayed elements = total elements
+             1: "Half sampled", # #displayed elements = total elements/2
+             2: "Sampled", # #displayed elements < total elements
+            }
+ESCAL = { 0: "X and Y auto scale",
+          1: "X fixed, Y auto scale",
+          2: "X auto scale, Y fixed",
+          3: "X and Y fixed",
+          }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/pygpibtoolkit/HP3562A/q3562A.py	Tue Feb 05 18:59:29 2008 +0100
@@ -0,0 +1,346 @@
+#
+
+import os, sys
+import time
+import glob
+
+from PyQt4 import QtGui, QtCore, uic
+from PyQt4.QtCore import SIGNAL, Qt
+
+if "-m" in sys.argv:
+    from dump_datablock_mockup import HP3562dumper
+else:
+    from dump_datablock import HP3562dumper
+import q3562A_rc
+
+ldir = os.path.abspath(os.path.dirname(__file__))
+sys.path.append(ldir)
+form_class, base_class = uic.loadUiType(os.path.join(ldir, "q3562A.ui"))
+
+from qpreferences import BaseItem, IntItem, UnicodeItem, ColorItem
+from qpreferences import PointItem, SizeItem, ByteArrayItem
+from qpreferences import AbstractPreferences
+from qpreferenceseditor import PreferencesEditor
+
+from tools import str_num_cmp
+
+class Preferences(AbstractPreferences):
+    ORGANISATION="Logilab"
+    APPLICATION="qgpib_plotter"
+
+    _pos = PointItem()
+    _size = SizeItem()
+    _appState = ByteArrayItem()
+
+    device = UnicodeItem(default='/dev/ttyUSB0',
+                         name=u'device',
+                         description=u'GPIB device',
+                         group="GPIB settings")
+    address = IntItem(default=5, min=0, max=16,
+                      name=u'GPIB address',
+                      group="GPIB settings")
+    
+    background = ColorItem(default=QtGui.QColor("white"),
+                           name="Background",
+                           group="Colors")
+    color0 = ColorItem(default=QtGui.QColor("black"),
+                       name="Pen #0",
+                       group="Colors")
+    color1 = ColorItem(default=QtGui.QColor("green"),
+                       name="Pen #1",
+                       group="Colors")
+    color2 = ColorItem(default=QtGui.QColor("red"),
+                       name="Pen #2",
+                       group="Colors")
+    color3 = ColorItem(default=QtGui.QColor("blue"),
+                       name="Pen #3",
+                       group="Colors")
+    color4 = ColorItem(default=QtGui.QColor("yellow"),
+                       name="Pen #4",
+                       group="Colors")
+    color5 = ColorItem(default=QtGui.QColor("cyan"),
+                       name="Pen #5",
+                       group="Colors")
+    color6 = ColorItem(default=QtGui.QColor("magenta"),
+                       name="Pen #6",
+                       group="Colors")
+    color7 = ColorItem(default=QtGui.QColor("darkred"),
+                       name="Pen #7",
+                       group="Colors")
+    
+class QtHPGLPlotter(QtGui.QMainWindow, form_class):
+    def __init__(self, parent=None):
+        QtGui.QMainWindow.__init__(self, parent)
+        self._plots = {}        
+        self._prefs = Preferences()
+        self.setupUi()
+        self.initializeGPIB()
+        if self._prefs._pos:
+            self.move(self._prefs._pos)
+        if self._prefs._size:
+            self.resize(self._prefs._size)
+        if self._prefs._appState:
+            self.restoreState(self._prefs._appState)
+        self.readPreferences()
+
+    def readPreferences(self):
+        bg = self._prefs.background
+        if bg and bg.isValid():
+            self.plotterWidget.qview.setBackgroundBrush(QtGui.QBrush(bg))
+        pen_colors = [self._prefs["color%d"%i] for i in range(8)]
+        self.plotterWidget.pen_colors = pen_colors
+        
+    def replotCurrent(self):
+        self.currentPlotChanged(self.plotsView.currentIndex())
+        
+    def setupUi(self):
+        form_class.setupUi(self, self) # call qtdesigner generated form creation        
+        # actions defined in designer
+        self.connect(self.actionPreferences, SIGNAL('triggered(bool)'),
+                     self.preferencesTriggered)
+        self.connect(self.actionQuit, SIGNAL('triggered(bool)'),
+                     self.quitTriggered)
+        self.actionQuit.setShortcut(QtGui.QKeySequence(u'Ctrl+Q'))
+        self.connect(self.actionOpen, SIGNAL('triggered(bool)'),
+                     self.openTriggered)
+        self.actionOpen.setShortcut(QtGui.QKeySequence(u'Ctrl+O'))
+        self.connect(self.actionSave, SIGNAL('triggered(bool)'),
+                     self.saveTriggered)
+        self.actionSave.setShortcut(QtGui.QKeySequence(u'Ctrl+S'))
+        self.connect(self.actionSaveAs, SIGNAL('triggered(bool)'),
+                     self.saveAsTriggered)
+
+        self.plotterWidget = QHPGLPlotterWidget(self)
+        self.setCentralWidget(self.plotterWidget)
+
+        self.connect(self.captureButton, SIGNAL("toggled(bool)"),
+                     self.captureToggled)
+
+        self._plots_list = QtGui.QStringListModel()
+        self.plotsView.setModel(self._plots_list)
+        self.connect(self.plotsView, SIGNAL('activated(const QModelIndex&)'),
+                     self.currentPlotChanged)
+        self.connect(self.plotsView.selectionModel(),
+                     SIGNAL('currentChanged(const QModelIndex&, const QModelIndex&)'),
+                     self.currentPlotChanged)
+
+    def currentPlotChanged(self, index, old_index=None):
+        if index.isValid():
+            value = unicode(self.plotsView.model().data(index, Qt.DisplayRole).toString())
+            
+            self.plotterWidget.clear()
+            self.plotterWidget.parse(self._plots[value])
+            
+    def preferencesTriggered(self, checked=False):
+        PreferencesEditor(self._prefs, self).exec_()
+        self.readPreferences()
+        self.replotCurrent()
+
+    def quitTriggered(self, checked=False):
+        self.close()
+
+    def closeEvent(self, event):
+        if 1:
+        #if self.promptForSave():
+            self._prefs._pos = self.pos()
+            self._prefs._size = self.size()
+            self._prefs._appState = self.saveState()
+            event.accept()
+        else:
+            event.ignore()
+        
+    def openTriggered(self, checked=False):
+        filenames = QtGui.QFileDialog.getOpenFileNames(self, "Open a HPGL file to display", '.', 'HPGL files (*.plt)\nAll files (*)')
+        self.openFiles(filenames)
+        self.displayFirst()
+        
+    def displayFirst(self):
+        if not self.plotsView.currentIndex().isValid():
+            self.plotsView.setCurrentIndex(self.plotsView.model().index(0, 0))
+        
+    def openFiles(self, filenames):
+        ok = False
+        for filename in filenames:
+            filename = str(filename)
+            if os.path.exists(filename):
+                data = open(filename).read()
+                name = os.path.basename(filename)
+                name = os.path.splitext(name)[0]
+                lst = self.plotsView.model().stringList()
+                lst.append(name)            
+                self._plots[name] = data
+                self.plotsView.model().setStringList(lst)
+                ok = True
+        return ok
+        
+    def plotReceived(self, num):
+        self._receiving = False
+        self.setReceivingLed()
+        plot, timestamp = self.captureThread.getPlot(num)
+        name = "plot_%s"%(num)
+        lst = self.plotsView.model().stringList()
+        lst.append(name)            
+        self._plots[name] = plot
+        self.plotsView.model().setStringList(lst)
+
+    def plotStarted(self):
+        self._receiving = True
+        self.setReceivingLed()
+        
+    def saveTriggered(self, checked=False):
+        print "save"
+        
+    def saveAsTriggered(self, checked=False):
+        index = self.plotsView.selectionModel().currentIndex()
+        if index.isValid():
+            filename = QtGui.QFileDialog.getSaveFileName(self, "Selecte a file name to save HPGL file", '.', 'HPGL files (*.plt)\nAll files (*)')
+            n = index.row()
+            value = unicode(self.plotsView.model().data(index, Qt.DisplayRole).toString())
+            open(filename, 'w').write(self._plots[value])
+            
+        
+    def initializeGPIB(self):
+        self._online = False
+        try:
+            self.gpib_plotter = QGPIBplotter(device=self._prefs.device,
+                                            address=self._prefs.address,
+                                            )
+            self.captureThread = GPIBReceiver(self.gpib_plotter)
+            self.connect(self.captureThread, SIGNAL('plotReceived(int)'),
+                         self.plotReceived)
+            self.connect(self.captureThread, SIGNAL('plotStarted()'),
+                         self.plotStarted)
+            self.captureThread.start()
+        except Exception, e:
+            #print e
+            self.gpib_plotter = None
+        self.setCaptureLed()
+
+    def captureToggled(self, state):
+        if state:
+            if self.gpib_plotter is None:
+                self.initializeGPIB()
+                if self.gpib_plotter is None:
+                    QtGui.QMessageBox.critical(self, self.tr("GPIB error"),
+                                               self.tr("<b>Unable to initialize GPIB connection</b>.<br>Please check your GPIB dongle and settings."))
+                    self._online = False
+                    self.setCaptureLed()
+                    return
+            self._online = True
+            self.captureThread.startCapture()
+        else:
+            if self.captureThread:
+                self.captureThread.stopCapture()
+            self._online = False
+        self.setCaptureLed()
+        
+    def setCaptureLed(self):
+        if self._online:
+            icn = QtGui.QIcon(':/icons/led_green.svg')
+        else:
+            icn = QtGui.QIcon(':/icons/led_green_off.svg')
+        self.captureButton.setIcon(icn)
+        self.captureButton.setChecked(self._online)
+
+    def setReceivingLed(self):
+        if self._receiving:
+            icn = QtGui.QIcon(':/icons/led_red.svg')
+        else:
+            icn = QtGui.QIcon(':/icons/led_red_off.svg')
+        self.receivingButton.setIcon(icn)
+
+class QGPIBplotter(GPIBplotter):
+    def __init__(self, device="/dev/ttyUSB0", baudrate=115200, timeout=0.1,
+                 address=5):
+        GPIBplotter.__init__(self, device, baudrate, timeout, address)        
+        self.emitter = None
+
+    def plotStarted(self):
+        if self.emitter:
+            self.emitter.emit(SIGNAL('plotStarted()'))
+            #self.emitter.msleep(1)
+        
+class GPIBReceiver(QtCore.QThread):
+    def __init__(self, cnx):
+        QtCore.QThread.__init__(self)
+        self.gpibplotter = cnx
+        self.gpibplotter.emitter = self
+        
+        self._cancelmutex = QtCore.QMutex()
+        self._cancel = False
+        #self._nreceived = 0
+        self._plotsmutex = QtCore.QMutex()
+        self._plots = []
+        self._startstopmutex = QtCore.QMutex()
+        self._startstop = QtCore.QWaitCondition()
+        self._capturing = False
+        
+    def cancel(self):
+        self._cancelmutex.lock()
+        self._cancel = True
+        self._cancelmutex.unlock()
+
+    def startCapture(self):
+        self._startstop.wakeOne()
+
+    def stopCapture(self):
+        self._startstopmutex.lock()
+        self._capturing = False
+        self._startstopmutex.unlock()
+
+    def run(self):
+        while 1:
+            self._cancelmutex.lock()
+            if self._cancel:
+                return
+            self._cancelmutex.unlock()
+            self._startstopmutex.lock()
+            if not self._capturing:
+                self._startstop.wait(self._startstopmutex)
+                self._capturing = True
+            self._startstopmutex.unlock()
+        
+            plot = self.gpibplotter.load_plot(wait_timeout=0.1)
+            timestamp = time.time()
+            if plot:
+                self._plotsmutex.lock()
+                self._plots.append((plot, timestamp))
+                n = len(self._plots)
+                self._plotsmutex.unlock()
+                self.emit(SIGNAL('plotReceived(int)'), n-1)
+            self.msleep(10)
+            
+    def getPlot(self, num):
+        self._plotsmutex.lock()
+        try:
+            return self._plots[num]
+        finally:
+            self._plotsmutex.unlock()
+
+def main():
+    import optparse
+    opt = optparse.OptionParser('A simple PyQt4 HP7470A GPIB plotter emulator for USB-GPIB bundle (ProLogix)')
+    opt.add_option('-m', '--mockup', default=False,
+                   action="store_true",
+                   dest='mockup',
+                   help='Use a pseudo GPIB connection (for test purpose)',
+                   )
+    opt.add_option('-v', '--verbose', default=False,
+                   action="store_true",
+                   dest="verbose",
+                   help="Verbose mode",)
+    
+    options, argv = opt.parse_args(sys.argv)
+
+    a = QtGui.QApplication(argv)
+    w = QtHPGLPlotter()
+    files = [f for f in argv[1:] if os.path.isfile(f)]
+    files.sort(cmp=str_num_cmp)
+    if w.openFiles(files):    
+        w.displayFirst()
+
+    w.show()
+    a.exec_()
+        
+if __name__ == '__main__':
+    main()
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/pygpibtoolkit/HP3562A/q3562A.ui	Tue Feb 05 18:59:29 2008 +0100
@@ -0,0 +1,179 @@
+<ui version="4.0" >
+ <class>MainWindow</class>
+ <widget class="QMainWindow" name="MainWindow" >
+  <property name="geometry" >
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>507</width>
+    <height>492</height>
+   </rect>
+  </property>
+  <property name="windowTitle" >
+   <string>MainWindow</string>
+  </property>
+  <widget class="QWidget" name="centralwidget" />
+  <widget class="QMenuBar" name="menubar" >
+   <property name="geometry" >
+    <rect>
+     <x>0</x>
+     <y>0</y>
+     <width>507</width>
+     <height>25</height>
+    </rect>
+   </property>
+   <widget class="QMenu" name="menu_File" >
+    <property name="title" >
+     <string>&amp;File</string>
+    </property>
+    <addaction name="actionOpen" />
+    <addaction name="actionSave" />
+    <addaction name="actionSaveAs" />
+    <addaction name="separator" />
+    <addaction name="actionQuit" />
+   </widget>
+   <widget class="QMenu" name="menuEdit" >
+    <property name="title" >
+     <string>Edit</string>
+    </property>
+    <addaction name="actionPreferences" />
+   </widget>
+   <addaction name="menu_File" />
+   <addaction name="menuEdit" />
+  </widget>
+  <widget class="QStatusBar" name="statusbar" />
+  <widget class="QDockWidget" name="plotsDock" >
+   <attribute name="dockWidgetArea" >
+    <number>1</number>
+   </attribute>
+   <widget class="QWidget" name="dockWidgetContents" >
+    <layout class="QVBoxLayout" >
+     <property name="spacing" >
+      <number>4</number>
+     </property>
+     <property name="leftMargin" >
+      <number>1</number>
+     </property>
+     <property name="topMargin" >
+      <number>4</number>
+     </property>
+     <property name="rightMargin" >
+      <number>1</number>
+     </property>
+     <property name="bottomMargin" >
+      <number>1</number>
+     </property>
+     <item>
+      <layout class="QHBoxLayout" >
+       <item>
+        <widget class="QToolButton" name="getTraceButton" >
+         <property name="minimumSize" >
+          <size>
+           <width>0</width>
+           <height>29</height>
+          </size>
+         </property>
+         <property name="text" >
+          <string>get trace</string>
+         </property>
+         <property name="icon" >
+          <iconset/>
+         </property>
+         <property name="iconSize" >
+          <size>
+           <width>16</width>
+           <height>16</height>
+          </size>
+         </property>
+         <property name="checkable" >
+          <bool>true</bool>
+         </property>
+         <property name="toolButtonStyle" >
+          <enum>Qt::ToolButtonTextBesideIcon</enum>
+         </property>
+        </widget>
+       </item>
+       <item>
+        <widget class="QToolButton" name="getStatusButton" >
+         <property name="minimumSize" >
+          <size>
+           <width>0</width>
+           <height>29</height>
+          </size>
+         </property>
+         <property name="text" >
+          <string>get status</string>
+         </property>
+         <property name="checkable" >
+          <bool>true</bool>
+         </property>
+        </widget>
+       </item>
+       <item>
+        <widget class="QToolButton" name="getCoordButton" >
+         <property name="minimumSize" >
+          <size>
+           <width>0</width>
+           <height>29</height>
+          </size>
+         </property>
+         <property name="text" >
+          <string>get coord</string>
+         </property>
+         <property name="checkable" >
+          <bool>true</bool>
+         </property>
+        </widget>
+       </item>
+       <item>
+        <spacer>
+         <property name="orientation" >
+          <enum>Qt::Horizontal</enum>
+         </property>
+         <property name="sizeHint" >
+          <size>
+           <width>40</width>
+           <height>20</height>
+          </size>
+         </property>
+        </spacer>
+       </item>
+      </layout>
+     </item>
+     <item>
+      <widget class="QListView" name="objectsView" />
+     </item>
+    </layout>
+   </widget>
+  </widget>
+  <action name="actionOpen" >
+   <property name="text" >
+    <string>&amp;Open</string>
+   </property>
+  </action>
+  <action name="actionSave" >
+   <property name="text" >
+    <string>&amp;Save</string>
+   </property>
+  </action>
+  <action name="actionSaveAs" >
+   <property name="text" >
+    <string>Save as...</string>
+   </property>
+  </action>
+  <action name="actionQuit" >
+   <property name="text" >
+    <string>&amp;Quit</string>
+   </property>
+  </action>
+  <action name="actionPreferences" >
+   <property name="text" >
+    <string>Preferences</string>
+   </property>
+  </action>
+ </widget>
+ <resources>
+  <include location="../qt4/resources.qrc" />
+ </resources>
+ <connections/>
+</ui>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/pygpibtoolkit/HP3562A/state_decoder.py	Tue Feb 05 18:59:29 2008 +0100
@@ -0,0 +1,151 @@
+# -*- coding: utf-8 -*-
+"""
+state_decoder
+=============
+
+Module for decoding the internal state of the HP3562A DSA, using the
+GPIB command "DSBN" (Dump State BiNary).
+
+This file can be exectued as a python script. Use '-h' for more informations. 
+"""
+from pygpibtoolkit.HP3562A import format_header, decode_float, decode_string, decode_header
+
+from pygpibtoolkit.HP3562A.enum_types import *
+
+HEADER = [("Measurement mode", EMEAS, 'h', 2),
+          ("Measurement 1", EMTYP, 'h', 2),
+          ("Measurement 2", EMTYP, 'h', 2),
+          ("Window type", EWINTYP, 'h', 2),
+          ("Force/Expon window 1", EFEXPW, 'h', 2),
+          ("Force/Expon window 2", EFEXPW, 'h', 2),
+          ("Average type", EAVGTYP, 'h', 2),
+          ("Overlap percentage", int, 'h', 2),
+          ("Number of averages", int, 'h', 2),
+          ("Sweep # of averages", int, 'h', 2),
+          ("Trigger type", ETRGTYP, 'h', 2),
+          ("Trigger slope", ETRGSLP, 'h', 2),
+          ("Preview type", EPRVTYP, 'h', 2),
+          ("Sample type", ESMPTYP, 'h', 2),
+          ("Range units chan 1", ERNGUNT, 'h', 2),
+          ("Range units chan 2", ERNGUNT, 'h', 2),
+          ("Range type 1", ERNGTYP, 'h', 2),
+          ("Range type 2", ERNGTYP, 'h', 2),
+          ("Input coupling 1", EINCPL, 'h', 2),
+          ("Input coupling 2", EINCPL, 'h', 2),
+          ("Source type", ESRCTYP, 'h', 2),
+          ("Chirp percent", int, 'h', 2),
+          ("Burst percent", int, 'h', 2),
+          ("Sweep direction", ESWPDIR, 'h', 2),
+          ("Sweep mode", ESWPMOD, 'h', 2),
+          ("Ext sample freq untis", EXAXIS, 'h', 2),
+          ("Bandwidth units", EXAXIS, 'h', 2),
+          ("Log span index", int, 'h', 2),
+          ("Log start index", int, 'h', 2),
+          ("Sweep rate units", EXAXIS, 'h', 2),
+          ("Auto gain ref chan", EDEMODCH, 'h', 2),
+          ("Demod channels", EDEMODCH, 'h', 2),
+          ("Demod type chan 1", EDEMOD, 'h', 2),
+          ("Demod type chan 2", EDEMOD, 'h', 2),
+          ("Source level units", EXAXIS, 'h', 2),
+          ("Source offset units", EXAXIS, 'h', 2),
+          ("Trigger level units", EXAXIS, 'h', 2),
+          ("Capt/thru length units", EXAXIS, 'h', 2),
+          ("EU label 1", str, 's', 6),
+          ("EU label 2", str, 's', 6),
+          ("Auto carrier on/off", bool, 'h', 2),
+          ("Time average on/off", bool, 'h', 2),
+          ("Auto/fixed resolution", bool, 'h', 2),
+          ("Auto gain on/off", bool, 'h', 2),
+          ("Auto/fixed integrate",bool, 'h', 2),
+          ("Fast average on/off", bool, 'h', 2),
+          ("Overload reject on/off", bool, 'h', 2),
+          ("Chan 1 float/ground", bool, 'h', 2),
+          ("Chan 2 float/ground", bool, 'h', 2),
+          ("Time throughput on/off", bool, 'h', 2),
+          ("Demodulation on/off", bool, 'h', 2),
+          ("EU/volts chan 1", bool, 'h', 2),
+          ("EU/volts chan 2", bool, 'h', 2),
+          ("Manual/auto arm", bool, 'h', 2),
+          ("Demod preview on/off", bool, 'h', 2),
+          ("Delete freq on/off", bool, 'h', 2),
+          ("Lin res Fstart pegged", bool, 'h', 2),
+          ("Swept Fstart pegged", bool, 'h', 2),
+          ("Force length chan 1", decode_float, None, 4),
+          ("Force length chan 2", decode_float, None, 4),
+          ("Expon time constant 1", decode_float, None, 4),
+          ("Expon time constant 2", decode_float, None, 4),
+          ("Sweep time", decode_float, None, 4),
+          ("Sweep rate", decode_float, None, 4),
+          ("Sweep resolution", decode_float, None, 4),
+          ("Sweep integrate time", decode_float, None, 4),
+          ("Auto gain level", decode_float, None, 4),
+          ("Auto gain limit", decode_float, None, 4),
+          ("Source level", decode_float, None, 4),
+          ("EU value chan 1", decode_float, None, 4),
+          ("EU value chan 2", decode_float, None, 4),
+          ("Trigger delay chan 1", decode_float, None, 4),
+          ("Trigger delay chan 2", decode_float, None, 4),
+          ("Integrate var thresh", decode_float, None, 4),
+          ("Capt/thru length", decode_float, None, 4),
+          ("Frequency span", decode_float, None, 4),
+          ("Time record length", decode_float, None, 4),
+          ("Frequency resolution", decode_float, None, 4),
+          ("Time resolution", decode_float, None, 4),
+          ("External sample rate", decode_float, None, 4),
+          ("Sample rate (actual)", decode_float, None, 4),
+          ("Range channel 1", decode_float, None, 4),
+          ("Range channel 2", decode_float, None, 4),
+          ("Preview time", decode_float, None, 4),
+          ("Trigger level", decode_float, None, 4),
+          ("Source dc offset", decode_float, None, 4),
+          ("Fixed sine frequency", decode_float, None, 8),
+          ("Start frequency", decode_float, None, 8),
+          ("Center frequency", decode_float, None, 8),
+          ("Sweep start", decode_float, None, 8),
+          ("Sweep end", decode_float, None, 8),
+          ("Carrier frequency", decode_float, None, 8),
+          ]
+          
+def decode_state(data):
+    """
+    Decode the data (as generated by the HP3562A DSA in response to a
+    "DSBN" command), and returns a dict (header)
+
+    header is the dictionnary of the header of the dumped data block,
+    """
+    header, idx = decode_header(data, HEADER)
+    return header
+    
+
+def main():
+    import sys
+    import optparse
+    opt = optparse.OptionParser("A simple tool for tracing a dumped trace")
+    opt.add_option('-f', '--filename', default=None,
+                   dest='filename',
+                   help='Output filename. If not set, read from stdin')
+    opt.add_option('-m', '--mode', default='binary',
+                   dest='mode',
+                   help='Dumping mode (may be "binary" [default], "ascii" or "ansi")',
+                   )
+    
+    options, argv = opt.parse_args(sys.argv)
+
+
+    if options.filename is None:
+        print "Can't deal stdin for now..."
+        sys.exit(1)
+    #try:
+    if 1:
+        header = decode_state(open(options.filename, 'rb').read())
+    else:
+    #except Exception, e:
+        print "ERROR: can't read %s an interpret it as a HP3562 trace"%options.filename
+        print e
+        sys.exit(1)
+
+    print format_header(header, HEADER, 100)
+    
+if __name__ == "__main__":
+    main()
+          
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/pygpibtoolkit/HP3562A/trace_decoder.py	Tue Feb 05 18:59:29 2008 +0100
@@ -0,0 +1,139 @@
+# -*- coding: utf-8 -*-
+"""
+trace_decoder
+=============
+
+Module for decoding a trace generated by the HP3562A DSA, using the
+GPIB command "DDBN" (Dump Data BiNary).
+
+This file can be exectued as a python script. Use '-h' for more informations. 
+"""
+import struct
+import numpy
+from pygpibtoolkit.HP3562A import format_header, decode_float, decode_string, decode_header, read_trace
+from pygpibtoolkit.HP3562A.enum_types import *
+
+
+HEADER = [ ("Display function", EDSP, 'h', 2),
+           ('Number of elements', int, 'h', 2),
+           ('Displayed elements', int, 'h', 2),
+           ('Number of averages', int, 'h', 2),
+           ('Channel selection', ECH, 'h', 2),
+           ('Overflow status', EOVR, 'h', 2),
+           ('Overlap percentage', int, 'h', 2),
+           ('Domain', EDOM, 'h', 2),
+           ('Volts peak/rms', EVLT, 'h', 2),
+           ('Amplitude units', EAMP, 'h', 2),
+           ('X axis units', EXAXIS, 'h', 2),
+           ('Auto math label', str, 's', 14),
+           ('Trace label', str, 's', 22),
+           ('EU label 1', str, 's', 6),
+           ('EU label 2', str, 's', 6),
+           ('Float/Interger', bool, 'h', 2),
+           ('Complex/Real', bool, 'h', 2),
+           ('Live/Recalled', bool, 'h', 2),
+           ('Math result', bool, 'h', 2),
+           ('Real/Complex input', bool, 'h', 2),
+           ('Log/Linear data', bool, 'h', 2),
+           ('Auto math', bool, 'h', 2),
+           ('Real time status', bool, 'h', 2),
+           ('Measurement mode', EMEAS, 'h', 2),
+           ('Window', EWIN, 'h', 2),
+           ('Demod type channel 1', EDEMOD, 'h', 2),
+           ('Demod type channel 2', EDEMOD, 'h', 2),
+           ('Demod active channel 1', bool, 'h', 2),
+           ('Demod active channel 2', bool, 'h', 2),
+           ('Average status', EAVG, 'h', 2),
+           ('Not used', int, 'hh', 4),
+           ('Samp freq/2 (real)', decode_float, None, 4),
+           ('Samp freq/2 (imag)', decode_float, None, 4),
+           ('Not used', decode_float, None, 4),
+           ('Delta X-axis', decode_float, None, 4),
+           ('Max range', decode_float, None, 4),
+           ('Start time value', decode_float, None, 4),
+           ('Expon wind const 1', decode_float, None, 4),
+           ('Expon wind const 2', decode_float, None, 4),
+           ('EU value chan 1', decode_float, None, 4),
+           ('EU value chan 2', decode_float, None, 4),
+           ('Trig delay chan 1', decode_float, None, 4),
+           ('Trig delay chan 2', decode_float, None, 4),
+           ('Start freq value', decode_float, None, 8),
+           ('Start data value', decode_float, None, 8),
+           ]
+
+def decode_trace(data, idx=0):
+    """
+    Decode the data (as generated by the HP3562A DSA in response to a
+    "DDBN" command), and returns a couple (header, values).
+
+    header is the dictionnary of the header of the dumped data block,
+    value is a numpy array holding the trace (vector of float or
+    complex values).
+    """
+    header, idx = decode_header(data, HEADER, idx)
+    return header, read_trace(data, idx, header["Number of elements"])
+
+def main():
+    import sys
+    import optparse
+    opt = optparse.OptionParser("A simple tool for tracing a dumped trace")
+    opt.add_option('-f', '--filename', default=None,
+                   dest='filename',
+                   help='Output filename. If not set, read from stdin')
+    opt.add_option('-m', '--mode', default='binary',
+                   dest='mode',
+                   help='Dumping mode (may be "binary" [default], "ascii" or "ansi")',
+                   )
+    opt.add_option('-d', '--display-header', default=False,
+                   action="store_true",
+                   dest="displayheader",
+                   help="Display the trace header")
+    opt.add_option('-P', '--noplot-trace', default=True,
+                   action="store_false",
+                   dest="plot",
+                   help="Do not display the plot of the trace")
+    opt.add_option('-x', '--xmode', default='lin',
+                   dest='xmode',
+                   help='X coordinate mode (may be "lin" [default] or "log")')
+    opt.add_option('-y', '--ymode', default='lin',
+                   dest='ymode',
+                   help='Y coordinate mode (may be "lin" [default], "log" or "db")')
+    
+    options, argv = opt.parse_args(sys.argv)
+
+
+    if options.filename is None:
+        print "Can't deal stdin for now..."
+        sys.exit(1)
+    try:
+        header, data = decode_trace(open(options.filename, 'rb').read())
+    except Exception, e:
+        print "ERROR: can't read %s an interpret it as a HP3562 trace"%options.filename
+        print e
+        sys.exit(1)
+
+    if options.displayheader:
+        print format_header(header, HEADER, 100)
+    if options.plot:
+        f0 = header['Start freq value']
+        dx = header['Delta X-axis']
+        n = header['Number of elements']
+        x = numpy.linspace(f0, f0+dx*n, len(data)) 
+        y = data.copy()
+
+        import pylab
+        if options.ymode != "lin":
+            minv = min(y[y>0])
+            y[y==0] = minv
+            y = numpy.log10(y)
+        if options.ymode == "db":
+            y = y*10
+            pylab.ylabel('db')
+        pylab.grid()
+        pylab.plot(x, y)
+        pylab.xlabel('frequency')
+        pylab.show()
+    
+          
+if __name__ == "__main__":
+    main()
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/pygpibtoolkit/plotter/gpib_plotter.py	Tue Feb 05 18:59:29 2008 +0100
@@ -0,0 +1,138 @@
+import sys, os
+import time
+from pygpibtoolkit import pygpib as gpib
+from pygpibtoolkit.prologix import GPIB
+
+class GPIBplotter(GPIB):
+    _replies={
+        "OE": "0",
+        "OH": "0,0,10000,7500",
+        "OI": "7470A",
+        "OP": "0,0,10000,7500",
+        "OO": "0,1,0,0,0,0,0,0",
+        "OF": "40,40",
+        "OS": "24",
+        }
+    def __init__(self, device="/dev/ttyUSB0", baudrate=115200, timeout=0.1,
+                 address=5):
+        super(GPIBplotter, self).__init__(device, baudrate, timeout, address, mode=0)
+
+    def plotStarted(self):
+        pass
+
+    def load_plot(self, wait_timeout=0):
+        """
+        Make a full plot process.
+
+        'wait_timeout' is the first timeout. Same semantic as the
+        'timeout' property of a serial connection (if set to None, it
+        will block until the GPIB device actually perform a plot
+        command.)
+        """
+        res = ""
+        i=0
+        replies = self._replies.copy()
+        if wait_timeout is not None and not isinstance(wait_timeout, (float, int)):
+            raise TypeError, "wait_timeout (%s:%s) has wrong type"%(repr(wait_timeout), type(wait_timeout))
+        if wait_timeout<0:
+            raise ValueError
+        
+        self._cnx.timeout = wait_timeout
+        firstloop = True
+        newdata = False
+        while i<self._retries:
+            l = self._cnx.readline().strip()
+            if firstloop:
+                self._cnx.timeout = self._timeout
+                firstloop = False
+                self.plotStarted()
+            if l == "":
+                if i == 0:# > (self._retries/2):
+                    # ie. we just received new stuffs (i is reset in the else block)
+                    for k, v in replies.items():
+                        # check wether we should reply smthg
+                        eres = res.replace('\n', '').strip()
+                        if eres.endswith(k) or eres.endswith(k+';') or eres.endswith(k+';OE'):
+                            self._cnx.write("%s"%v)
+                            if k == "OS":
+                                replies[k] = "16"
+                            break
+                    self._cnx.write('\r')
+                    #time.sleep(0.1)
+                i += 1
+            else:
+                if not res:
+                    print "Plotting..."
+                res += l + '\n'
+                i = 0
+                #time.sleep(0.1)
+        if res:
+            print "DONE (received %d characters)"%len(res)
+        return res
+
+if __name__ == '__main__':
+    import optparse
+    opt = optparse.OptionParser('A simple HP7470A GPIB plotter emulator for USB-GPIB bundle (ProLogix)')
+    opt.add_option('-f', '--filename', default=None,
+                   dest='filename',
+                   help='Output filename. If not set, write to stdout')
+    opt.add_option('-d', '--device', default='/dev/ttyUSB0',
+                   dest='device',
+                   help='Device of the RS232 connection (default: /dev/ttyUSB0)',
+                   )
+    opt.add_option('-a', '--address', default=0,
+                   dest='address',
+                   help='GPIB address of the device',
+                   )
+    opt.add_option('-l', '--loop', default=False,
+                   action="store_true",
+                   dest="loop",
+                   help="Continuously wait for new plots. If set, filename must be set and files will be created with _n at the end")
+    opt.add_option('-v', '--verbose', default=False,
+                   action="store_true",
+                   dest="verbose",
+                   help="Verbose mode",)
+    
+    options, argv = opt.parse_args(sys.argv)
+
+    if options.loop and not options.filename:
+        opt.error('If loop is set, you *must* provide a filename')
+
+    if options.filename:        
+        outf = open(options.filename, "w")
+    else:
+        outf = sys.stdout
+
+
+    try:
+        plotter = GPIBplotter(device=options.device, address=int(options.address),
+                              timeout=0.06)
+    except (gpib.SerialException, gpib.ConnectionError), e:
+        sys.stderr.write('Connection error:\n\t' + '\n\t'.join([str(x) for x in e.args]) + '\n')
+        sys.stderr.write('Check your parameters\n')
+        sys.exit(1)
+    if options.verbose:
+        sys.stderr.write('connection established\n')
+
+    loop = True
+    nloop = 0
+    while loop:
+        plot = plotter.load_plot(wait_timeout=0.1)
+        if options.verbose:
+            sys.stderr.write('.')
+        if plot:
+            outf.write(plot)
+            if options.verbose:
+                sys.stderr.write('\n')
+            sys.stderr.write('Received a new plot (written to %s)\n'%outf.name) 
+            if not options.loop:
+                loop = False
+            else:
+                nloop += 1
+                fname, ext = os.path.splitext(options.filename)
+                outf = open(fname + "_%d"%nloop + ext, 'w')
+                
+        
+    
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/pygpibtoolkit/plotter/gpib_plotter_mockup.py	Tue Feb 05 18:59:29 2008 +0100
@@ -0,0 +1,35 @@
+import glob
+import os
+import time
+import random
+
+class GPIBplotter:#(GPIB):
+    """
+    A mockup thet will find in a directory some HPGL files and feed them randomly
+    """
+    def __init__(self, device="/dev/ttyUSB0", baudrate=115200, timeout=0.1,
+                 address=5):
+        self._timeout = timeout
+        self.filenames = glob.glob('examples/*.plt')
+        self._next = random.randint(10,50)
+        self._num = 0
+
+    def plotStarted(self):
+        pass
+        
+    def load_plot(self, wait_timeout=0):
+        if wait_timeout:
+            time.sleep(wait_timeout)
+        self._num += 1
+        if self._num > self._next:
+            ret = open(random.choice(self.filenames)).read()
+            if len(ret)>0:
+                self.plotStarted()
+                self._num = 0
+                self._next = random.randint(10,100)
+                time.sleep(random.randint(1,3))
+                return ret
+            return None
+        return None
+    
+        
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/pygpibtoolkit/plotter/hpgl_mpl.py	Tue Feb 05 18:59:29 2008 +0100
@@ -0,0 +1,26 @@
+# -*- coding: utf-8 -*-
+import numpy
+import pylab
+
+from hpgl_parser import HPGLParser
+
+class HPGLmplPlotter(HPGLParser):
+    pens = "krbgcmyw"
+    lines = ['-', ':', '--', '-.', '.', '-', '-', '-']
+    def __init__(self, data):        
+        super(HPGLmplPlotter, self).__init__(data)
+        pylab.show()
+        
+    def plot_symbols(self, points):
+        x, y = points.T
+        pylab.plot(x, y, 'o')
+
+    def plot_lines(self, points):
+        x, y = points.T
+        pylab.plot(x, y, self.pens[self.pen]+self.lines[self.line_type])
+        
+if __name__ == "__main__":
+    import sys
+    data = open(sys.argv[1]).read()
+    HPGLmplPlotter(data)
+    
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/pygpibtoolkit/plotter/hpgl_parser.py	Tue Feb 05 18:59:29 2008 +0100
@@ -0,0 +1,451 @@
+# -*- coding: utf-8 -*-
+
+import re
+import numpy
+
+vsplitter = re.compile('[ ,]')
+vextractor = re.compile('(?P<value>[^;\n\r\aA-DF-Za-df-z]*?)(?P<terminator>[;\n\r\a]+)', re.S+re.M) 
+
+class HPGLParser(object):
+    def __init__(self, data=None):
+        self.str_terminator = chr(0x03)
+        self.IN()
+        if data:
+            self.parse(data)
+
+    def parse(self, data):
+        self.data = data
+        self.idx = 0
+        self.IN()        
+        while self.idx<len(data):
+            while data[self.idx] in [';','\n','\r', '\a', ' ']:
+                self.idx += 1
+            if data[self.idx] == chr(0x03):
+                self.ESC()
+            else:
+                cmd = data[self.idx: self.idx+2].upper()
+                self.idx += 2
+                getattr(self, cmd)()
+            while self.idx<len(data) and data[self.idx] in [';','\n','\r', '\a', ' ']:
+                self.idx += 1
+
+    def user_to_abs(self, pos):
+        """
+        converts a position (x, y) given in user units to absolute
+        units
+        """
+        return pos #TODO
+        
+    def extract_value(self, raw=False):
+        m = vextractor.match(self.data[self.idx:])
+        if m:
+            val = m.group("value")
+            self.idx = self.idx + len(val) + len(m.group("terminator"))
+            val = vsplitter.split(val)
+            if not raw:
+                val = [eval(x) for x in val if x.strip()]
+            return val
+        return []
+
+    def extract_string(self):
+        idx2 = self.data.find(self.str_terminator, self.idx)
+        val = self.data[self.idx: idx2]
+        self.idx = idx2+1
+        return val
+
+    def polyline(self, values):
+        if (len(values)%2) == 1:
+            # this is a syntax error in the HPGL data
+            values = values[:-1]
+        values = numpy.array(values).reshape(-1, 2)
+        # TODO use scaling            
+        # do plots 
+        values = numpy.r_[[self.pos], values] #add self.pos as 1st value
+        if self.plot_mode == 'relative':
+            values = values.cumsum(axis=0)
+        if self.symbol_mode:
+            self.plot_symbols(values[1:])
+        if self.pen_state == "down":
+            self.plot_lines(values)
+        self.pos = values[-1]
+
+    def plot_string(self, s):
+        pass
+    
+    def get_window_for_paper(self):
+        return 0,100,0,100
+    def get_scaling_points_for_paper(self):
+        return 0,100,0,100
+        
+    # effective plot methods; to be defined in subclasses (backends)
+    def plot_symbols(self, points):
+        pass
+    def plot_lines(self, points):
+        pass
+        
+    # HPGL-related methods
+    def ESC(self):
+        #print "ESC"
+        self.idx += 1
+
+    def OE(self):
+        """ Output Error """
+        pass
+        
+    def EC(self):
+        """? what's this """
+        values = self.extract_value()
+
+    def OO(self):
+        """idem"""
+        pass
+
+    def OP(self):
+        """idem"""
+        pass
+
+    def VS(self):
+        """idem"""
+        pass
+        
+        
+    def DF(self):
+        """ Default """
+        self.pen = 0
+        self.pen_width = 1 # 1/300 inch
+        self.pos = 0,0
+        self.char_set = "std"
+        self.plot_mode = 'absolute'
+        self.char_direction = 1,0
+        self.line_type = 0 # 'solid'
+        self.pattern_len = 4 #percentage
+        self.window = self.get_window_for_paper()
+        self.char_size = 0.75, 1.5 #percentages
+        self.symbol_mode = False
+        self.tick_len = 0.5, 0.5 # %
+        self.std_char_set = 0
+        self.alt_char_set = 0
+        self.selected_char_set = 0
+        self.char_slant = 0 # degrees
+        self.scale = None
+        self.str_terminator = chr(0x03)
+        self.chord_ang = 5 #degrees
+        self.fill_type = 'bidirectionnal', 1
+        self.fill_distance = 1 # %
+        self.fill_slant = 0 # degrees
+        self.pen_thickness = 0.3 # mm
+
+    def IN(self):
+        """ Initialize """
+        self.DF()
+        self.pen_state = "up"
+        self.rotation = 0 #degrees
+        self.scaling_points = self.get_scaling_points_for_paper()
+
+    def IP(self):
+        """ Input Scale Point"""
+        values = self.extract_value()
+        if len(values) == 0:
+            self.scaling_points = self.get_scaling_points_for_paper()
+        elif len(values) == 2:
+            p1x, p1y, p2x, p2y = self.scaling_points
+            dx, dy = p2x-p1x, p2y-p1y
+            x, y = values
+            self.scaling = (x, y, x+dx, y+dy)
+        elif len(values) == 4:
+            self.values = tuple(values)
+            
+    def SC(self):
+        """ Scale """
+        values = self.extract_value()
+        if len(values) == 4:
+            self.scale = tuple(values)
+        else:
+            self.scale = None
+
+    def IW(self):
+        values = self.extract_value()
+        if len(values) == 0:
+            self.window = self.get_window_for_paper()
+        elif len(value) == 4:            
+            self.window = tuple(values)
+
+    def RO(self):
+        values = self.extract_value()
+        if len(values) == 0:
+            self.rotation = 0
+        elif len(values) == 1:
+            self.rotation = values[0]
+
+    def PG(self):
+        pass
+
+    def PU(self):
+        """ Pen Up"""
+        self.pen_state = "up"        
+        values = self.extract_value()
+        self.polyline(values)
+
+    def PD(self):
+        """ Pen Down """
+        self.pen_state = "down"        
+        values = self.extract_value()
+        self.polyline(values)
+
+    def PA(self):
+        """ Plot Absolute """
+        self.plot_mode = "absolute"        
+        values = self.extract_value()
+        self.polyline(values)
+
+    def PR(self):
+        """ Plot Relative """
+        self.plot_mode = "relative"        
+        values = self.extract_value()
+        self.polyline(values)
+
+    def AA(self):
+        """ Arc Absolute """
+        values = self.extract_value()
+        if len(values) in [3, 4]:
+            x, y, qc = values[:3]
+            if len(values)==4:
+                qd = values[-1]
+            else:
+                qd = self.chord_ang
+            # TODO : plot arc
+            print "plotting an arc"
+    def AR(self):
+        """ Arc Relative """
+        values = self.extract_value()
+        # TODO
+
+    def CI(self):
+        """ Circle Plot"""
+        values = self.extract_value()
+        # TODO
+
+    def EA(self):
+        """Edge Rectangle Absolute"""
+        values = self.extract_value()
+        # TODO
+
+    def ER(self):
+        """Edge Rectangle Relative"""
+        values = self.extract_value()
+        # TODO
+
+    def EW(self):
+        """ Edge Wedge """
+        values = self.extract_value()
+        # TODO
+
+    def RA(self):
+        """ Fill Rectangle Absolute """
+        values = self.extract_value()
+        # TODO
+
+    def RR(self):
+        """ Fill Rectangle Relative """
+        values = self.extract_value()
+        # TODO
+
+    def WG(self):
+        """ Fill Wedge """
+        values = self.extract_value()
+        # TODO
+
+    def FT(self):
+        """ Fill Type """
+        values = self.extract_value()
+        # TODO
+
+    def LT(self):
+        """ Line Type """
+        values = self.extract_value()
+
+        if len(values)==0:
+            self.line_type = 0 #'solid'
+        else:
+            self.line_type = values[0]
+            if len(values)>1:
+                self.pattern_len = values[1]
+
+    def PW(self):
+        """ Pen Width """
+        values = self.extract_value()
+        if len(values) == 1:
+            self.pen_thickness = values[0]
+
+    def SM(self):
+        """ Symbol Mode """
+        values = self.extract_value()
+        if len(values) == 0:
+            self.symbol_mode = False
+        elif len(values) == 1:
+            self.symbol_mode = values[0]
+
+    def SP(self):
+        """ Select Pen """
+        values = self.extract_value()
+        if len(values) == 1:
+            self.pen = values[0]
+
+    def TL(self):
+        """ Tick Len """
+        values = self.extract_value()
+        # TODO
+
+    def XT(self):
+        """ X-axis Tick """
+        # TODO
+        print "X ticks"
+
+    def YT(self):
+        """ X-axis Tick """
+        # TODO
+        print "Y ticks"
+
+    def PT(self):
+        """ Pen Thickness Select """
+        values = self.extract_value()
+        if len(values) == 0:
+            self.pen_thickness = 0.3
+        elif len(values) == 1:
+            self.pen_thickness = values[0]
+
+    def CS(self):
+        """ Standard Character Set """
+        values = self.extract_value()
+        if len(values) == 0:
+            self.std_char_set = 0
+        elif len(values) == 1:
+            self.std_char_set = values[0]
+
+    def CA(self):
+        """ Alternate Character Set """
+        values = self.extract_value()
+        if len(values) == 0:
+            self.alt_char_set = 0
+        elif len(values) == 1:
+            self.alt_char_set = values[0]
+        
+    def SS(self):
+        """ Select Standard Character Set """
+        self.char_set = "std"
+
+    def SA(self):
+        """ Select Alternate Character Set """
+        self.char_set = "alt"
+
+    def DT(self):
+        """ Define Label Terminator """
+        values = self.extract_value(raw=True)
+        if len(values) == 0:
+            self.str_terminator = chr(0x03)
+        elif len(values) == 1:
+            self.str_terminator = values[0]
+
+    def LB(self):
+        """ Character Plot """
+        values = self.extract_string()
+        self.plot_string(values)
+        x, y = self.pos
+        values = values.split('\n')
+        if self.char_size == "absolute":
+            x += len(values[-1]) * self.char_width *1016/2.54
+            y += (len(values)-1) * self.char_height *1016/2.54
+        else:
+            x0, x1, y0, y1 = self.scale
+            dx = x1-x0
+            dy = y1-y0
+            x += len(values[-1]) * self.char_width / 100.0 * dx
+            y += (len(values)-1) * self.char_height / 100.0 * dy
+            
+        #print "LB pos[%s] %s -> %s"%(repr(values), self.pos, (x,y))
+        self.pos = [x, y]
+
+    def get_char_size(self):
+        if self.char_size == "absolute":
+            x = self.char_width *1016/2.54
+            y = self.char_height *1016/2.54
+        else:
+            x0, x1, y0, y1 = self.scale
+            dx = x1-x0
+            dy = y1-y0
+            x = self.char_width / 100.0 * dx
+            y = self.char_height / 100.0 * dy
+        return x, y
+    
+    def DI(self):
+        """ Absolute Direction """
+        values = self.extract_value()
+        if len(values) == 0:
+            self.char_direction = 1.0, 0.0
+        elif len(values) == 2:
+            self.char_direction = values
+
+    def DR(self):
+        """ Relative Direction """
+        values = self.extract_value()
+        if len(values) == 0:
+            self.char_direction = 1.0, 0.0
+        elif len(values) == 2:
+            # TODO : compute as percentages
+            self.char_direction = values
+
+    def CP(self):
+        """ Character Plot """
+        values = self.extract_value()
+        # TODO
+        if len(values) == 0:
+            values = 0, 1
+        x, y = self.pos
+        if self.char_size == "absolute":
+            x += values[0] * self.char_width *1016/2.54
+            y += values[1] * self.char_height *1016/2.54
+        else:
+            x0, x1, y0, y1 = self.scale
+            dx = x1-x0
+            dy = y1-y0
+            x += values[0] * self.char_width / 100.0 * dx
+            y += values[1] * self.char_height / 100.0 * dy
+        #print "CB pos[%s] %s -> %s"%(repr(values), self.pos, (x,y))
+        self.pos = [x, y]
+
+    def SI(self):
+        """ Set Absolute Character Size """
+        values = self.extract_value()
+        self.char_size = "absolute"
+        if len(values) == 0:
+            self.char_width = 0.1879 # cm
+            self.char_height = 0.2690 # cm
+        elif len(values) == 2:
+            self.char_width, self.char_height = values
+
+    def SR(self):
+        """ Set Relative Character Size """
+        values = self.extract_value()
+        self.char_size = "relative"
+        if len(values) == 0:
+            self.char_width = 0.75 # percentage
+            self.char_height = 1.5 # id
+        elif len(values) == 2:
+            self.char_width, self.char_height = values
+        
+    def SL(self):
+        """ Character Slant """        
+        values = self.extract_value()
+        # TODO
+
+    def UC(self):
+        """ User Defined Character """
+        values = self.extract_value()
+        # TODO
+        
+if __name__ == '__main__':
+    import sys
+    data = open(sys.argv[1]).read()
+    
+    p = HPGLParser(data)
+    
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/pygpibtoolkit/plotter/hpgl_plotter_rc.py	Tue Feb 05 18:59:29 2008 +0100
@@ -0,0 +1,1318 @@
+# -*- coding: utf-8 -*-
+
+# Resource object code
+#
+# Created: sam. janv. 26 11:14:20 2008
+#      by: The Resource Compiler for PyQt (Qt v4.3.2)
+#
+# WARNING! All changes made in this file will be lost!
+
+from PyQt4 import QtCore
+
+qt_resource_data = "\
+\x00\x00\x14\x97\
+\x3c\
+\x3f\x78\x6d\x6c\x20\x76\x65\x72\x73\x69\x6f\x6e\x3d\x22\x31\x2e\
+\x30\x22\x20\x65\x6e\x63\x6f\x64\x69\x6e\x67\x3d\x22\x55\x54\x46\
+\x2d\x38\x22\x20\x73\x74\x61\x6e\x64\x61\x6c\x6f\x6e\x65\x3d\x22\
+\x6e\x6f\x22\x3f\x3e\x0a\x3c\x21\x2d\x2d\x20\x43\x72\x65\x61\x74\
+\x65\x64\x20\x77\x69\x74\x68\x20\x49\x6e\x6b\x73\x63\x61\x70\x65\
+\x20\x28\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\x77\x2e\x69\x6e\x6b\
+\x73\x63\x61\x70\x65\x2e\x6f\x72\x67\x2f\x29\x20\x2d\x2d\x3e\x0a\
+\x3c\x73\x76\x67\x0a\x20\x20\x20\x78\x6d\x6c\x6e\x73\x3a\x64\x63\
+\x3d\x22\x68\x74\x74\x70\x3a\x2f\x2f\x70\x75\x72\x6c\x2e\x6f\x72\
+\x67\x2f\x64\x63\x2f\x65\x6c\x65\x6d\x65\x6e\x74\x73\x2f\x31\x2e\
+\x31\x2f\x22\x0a\x20\x20\x20\x78\x6d\x6c\x6e\x73\x3a\x63\x63\x3d\
+\x22\x68\x74\x74\x70\x3a\x2f\x2f\x77\x65\x62\x2e\x72\x65\x73\x6f\
+\x75\x72\x63\x65\x2e\x6f\x72\x67\x2f\x63\x63\x2f\x22\x0a\x20\x20\
+\x20\x78\x6d\x6c\x6e\x73\x3a\x72\x64\x66\x3d\x22\x68\x74\x74\x70\
+\x3a\x2f\x2f\x77\x77\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x31\x39\
+\x39\x39\x2f\x30\x32\x2f\x32\x32\x2d\x72\x64\x66\x2d\x73\x79\x6e\
+\x74\x61\x78\x2d\x6e\x73\x23\x22\x0a\x20\x20\x20\x78\x6d\x6c\x6e\
+\x73\x3a\x73\x76\x67\x3d\x22\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\
+\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x32\x30\x30\x30\x2f\x73\x76\
+\x67\x22\x0a\x20\x20\x20\x78\x6d\x6c\x6e\x73\x3d\x22\x68\x74\x74\
+\x70\x3a\x2f\x2f\x77\x77\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x32\
+\x30\x30\x30\x2f\x73\x76\x67\x22\x0a\x20\x20\x20\x78\x6d\x6c\x6e\
+\x73\x3a\x78\x6c\x69\x6e\x6b\x3d\x22\x68\x74\x74\x70\x3a\x2f\x2f\
+\x77\x77\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x31\x39\x39\x39\x2f\
+\x78\x6c\x69\x6e\x6b\x22\x0a\x20\x20\x20\x78\x6d\x6c\x6e\x73\x3a\
+\x73\x6f\x64\x69\x70\x6f\x64\x69\x3d\x22\x68\x74\x74\x70\x3a\x2f\
+\x2f\x73\x6f\x64\x69\x70\x6f\x64\x69\x2e\x73\x6f\x75\x72\x63\x65\
+\x66\x6f\x72\x67\x65\x2e\x6e\x65\x74\x2f\x44\x54\x44\x2f\x73\x6f\
+\x64\x69\x70\x6f\x64\x69\x2d\x30\x2e\x64\x74\x64\x22\x0a\x20\x20\
+\x20\x78\x6d\x6c\x6e\x73\x3a\x69\x6e\x6b\x73\x63\x61\x70\x65\x3d\
+\x22\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\x77\x2e\x69\x6e\x6b\x73\
+\x63\x61\x70\x65\x2e\x6f\x72\x67\x2f\x6e\x61\x6d\x65\x73\x70\x61\
+\x63\x65\x73\x2f\x69\x6e\x6b\x73\x63\x61\x70\x65\x22\x0a\x20\x20\
+\x20\x77\x69\x64\x74\x68\x3d\x22\x32\x37\x38\x2e\x32\x35\x32\x35\
+\x22\x0a\x20\x20\x20\x68\x65\x69\x67\x68\x74\x3d\x22\x32\x37\x38\
+\x2e\x32\x35\x32\x35\x22\x0a\x20\x20\x20\x69\x64\x3d\x22\x73\x76\
+\x67\x32\x22\x0a\x20\x20\x20\x73\x6f\x64\x69\x70\x6f\x64\x69\x3a\
+\x76\x65\x72\x73\x69\x6f\x6e\x3d\x22\x30\x2e\x33\x32\x22\x0a\x20\
+\x20\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x76\x65\x72\x73\x69\
+\x6f\x6e\x3d\x22\x30\x2e\x34\x35\x2e\x31\x22\x0a\x20\x20\x20\x73\
+\x6f\x64\x69\x70\x6f\x64\x69\x3a\x64\x6f\x63\x62\x61\x73\x65\x3d\
+\x22\x2f\x68\x6f\x6d\x65\x2f\x64\x61\x76\x69\x64\x2f\x45\x6c\x65\
+\x63\x74\x72\x6f\x6e\x69\x63\x2f\x48\x50\x33\x35\x36\x32\x2f\x69\
+\x63\x6f\x6e\x73\x22\x0a\x20\x20\x20\x73\x6f\x64\x69\x70\x6f\x64\
+\x69\x3a\x64\x6f\x63\x6e\x61\x6d\x65\x3d\x22\x6c\x65\x64\x5f\x72\
+\x65\x64\x5f\x6f\x66\x66\x2e\x73\x76\x67\x22\x0a\x20\x20\x20\x69\
+\x6e\x6b\x73\x63\x61\x70\x65\x3a\x6f\x75\x74\x70\x75\x74\x5f\x65\
+\x78\x74\x65\x6e\x73\x69\x6f\x6e\x3d\x22\x6f\x72\x67\x2e\x69\x6e\
+\x6b\x73\x63\x61\x70\x65\x2e\x6f\x75\x74\x70\x75\x74\x2e\x73\x76\
+\x67\x2e\x69\x6e\x6b\x73\x63\x61\x70\x65\x22\x0a\x20\x20\x20\x76\
+\x65\x72\x73\x69\x6f\x6e\x3d\x22\x31\x2e\x30\x22\x3e\x0a\x20\x20\
+\x3c\x64\x65\x66\x73\x0a\x20\x20\x20\x20\x20\x69\x64\x3d\x22\x64\
+\x65\x66\x73\x34\x22\x3e\x0a\x20\x20\x20\x20\x3c\x6c\x69\x6e\x65\
+\x61\x72\x47\x72\x61\x64\x69\x65\x6e\x74\x0a\x20\x20\x20\x20\x20\
+\x20\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x63\x6f\x6c\x6c\x65\
+\x63\x74\x3d\x22\x61\x6c\x77\x61\x79\x73\x22\x0a\x20\x20\x20\x20\
+\x20\x20\x20\x69\x64\x3d\x22\x6c\x69\x6e\x65\x61\x72\x47\x72\x61\
+\x64\x69\x65\x6e\x74\x34\x31\x31\x37\x22\x3e\x0a\x20\x20\x20\x20\
+\x20\x20\x3c\x73\x74\x6f\x70\x0a\x20\x20\x20\x20\x20\x20\x20\x20\
+\x20\x73\x74\x79\x6c\x65\x3d\x22\x73\x74\x6f\x70\x2d\x63\x6f\x6c\
+\x6f\x72\x3a\x23\x66\x66\x66\x66\x66\x66\x3b\x73\x74\x6f\x70\x2d\
+\x6f\x70\x61\x63\x69\x74\x79\x3a\x31\x3b\x22\x0a\x20\x20\x20\x20\
+\x20\x20\x20\x20\x20\x6f\x66\x66\x73\x65\x74\x3d\x22\x30\x22\x0a\
+\x20\x20\x20\x20\x20\x20\x20\x20\x20\x69\x64\x3d\x22\x73\x74\x6f\
+\x70\x34\x31\x31\x39\x22\x20\x2f\x3e\x0a\x20\x20\x20\x20\x20\x20\
+\x3c\x73\x74\x6f\x70\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x73\
+\x74\x79\x6c\x65\x3d\x22\x73\x74\x6f\x70\x2d\x63\x6f\x6c\x6f\x72\
+\x3a\x23\x66\x66\x66\x66\x66\x66\x3b\x73\x74\x6f\x70\x2d\x6f\x70\
+\x61\x63\x69\x74\x79\x3a\x30\x3b\x22\x0a\x20\x20\x20\x20\x20\x20\
+\x20\x20\x20\x6f\x66\x66\x73\x65\x74\x3d\x22\x31\x22\x0a\x20\x20\
+\x20\x20\x20\x20\x20\x20\x20\x69\x64\x3d\x22\x73\x74\x6f\x70\x34\
+\x31\x32\x31\x22\x20\x2f\x3e\x0a\x20\x20\x20\x20\x3c\x2f\x6c\x69\
+\x6e\x65\x61\x72\x47\x72\x61\x64\x69\x65\x6e\x74\x3e\x0a\x20\x20\
+\x20\x20\x3c\x6c\x69\x6e\x65\x61\x72\x47\x72\x61\x64\x69\x65\x6e\
+\x74\x0a\x20\x20\x20\x20\x20\x20\x20\x69\x64\x3d\x22\x6c\x69\x6e\
+\x65\x61\x72\x47\x72\x61\x64\x69\x65\x6e\x74\x33\x31\x33\x36\x22\
+\x3e\x0a\x20\x20\x20\x20\x20\x20\x3c\x73\x74\x6f\x70\x0a\x20\x20\
+\x20\x20\x20\x20\x20\x20\x20\x73\x74\x79\x6c\x65\x3d\x22\x73\x74\
+\x6f\x70\x2d\x63\x6f\x6c\x6f\x72\x3a\x23\x66\x66\x66\x66\x66\x66\
+\x3b\x73\x74\x6f\x70\x2d\x6f\x70\x61\x63\x69\x74\x79\x3a\x31\x3b\
+\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x6f\x66\x66\x73\x65\
+\x74\x3d\x22\x30\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x69\
+\x64\x3d\x22\x73\x74\x6f\x70\x33\x31\x33\x38\x22\x20\x2f\x3e\x0a\
+\x20\x20\x20\x20\x20\x20\x3c\x73\x74\x6f\x70\x0a\x20\x20\x20\x20\
+\x20\x20\x20\x20\x20\x73\x74\x79\x6c\x65\x3d\x22\x73\x74\x6f\x70\
+\x2d\x63\x6f\x6c\x6f\x72\x3a\x23\x61\x61\x30\x30\x30\x30\x3b\x73\
+\x74\x6f\x70\x2d\x6f\x70\x61\x63\x69\x74\x79\x3a\x30\x3b\x22\x0a\
+\x20\x20\x20\x20\x20\x20\x20\x20\x20\x6f\x66\x66\x73\x65\x74\x3d\
+\x22\x31\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x69\x64\x3d\
+\x22\x73\x74\x6f\x70\x33\x31\x34\x30\x22\x20\x2f\x3e\x0a\x20\x20\
+\x20\x20\x3c\x2f\x6c\x69\x6e\x65\x61\x72\x47\x72\x61\x64\x69\x65\
+\x6e\x74\x3e\x0a\x20\x20\x20\x20\x3c\x72\x61\x64\x69\x61\x6c\x47\
+\x72\x61\x64\x69\x65\x6e\x74\x0a\x20\x20\x20\x20\x20\x20\x20\x69\
+\x6e\x6b\x73\x63\x61\x70\x65\x3a\x63\x6f\x6c\x6c\x65\x63\x74\x3d\
+\x22\x61\x6c\x77\x61\x79\x73\x22\x0a\x20\x20\x20\x20\x20\x20\x20\
+\x78\x6c\x69\x6e\x6b\x3a\x68\x72\x65\x66\x3d\x22\x23\x6c\x69\x6e\
+\x65\x61\x72\x47\x72\x61\x64\x69\x65\x6e\x74\x33\x31\x33\x36\x22\
+\x0a\x20\x20\x20\x20\x20\x20\x20\x69\x64\x3d\x22\x72\x61\x64\x69\
+\x61\x6c\x47\x72\x61\x64\x69\x65\x6e\x74\x33\x31\x34\x32\x22\x0a\
+\x20\x20\x20\x20\x20\x20\x20\x63\x78\x3d\x22\x33\x32\x37\x2e\x34\
+\x31\x39\x32\x35\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x63\x79\x3d\
+\x22\x33\x34\x2e\x31\x30\x31\x39\x38\x32\x22\x0a\x20\x20\x20\x20\
+\x20\x20\x20\x66\x78\x3d\x22\x33\x32\x37\x2e\x34\x31\x39\x32\x35\
+\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x66\x79\x3d\x22\x33\x34\x2e\
+\x31\x30\x31\x39\x38\x32\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x72\
+\x3d\x22\x31\x33\x30\x2e\x31\x33\x32\x34\x22\x0a\x20\x20\x20\x20\
+\x20\x20\x20\x67\x72\x61\x64\x69\x65\x6e\x74\x55\x6e\x69\x74\x73\
+\x3d\x22\x75\x73\x65\x72\x53\x70\x61\x63\x65\x4f\x6e\x55\x73\x65\
+\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x67\x72\x61\x64\x69\x65\x6e\
+\x74\x54\x72\x61\x6e\x73\x66\x6f\x72\x6d\x3d\x22\x6d\x61\x74\x72\
+\x69\x78\x28\x32\x2e\x35\x36\x39\x35\x37\x30\x37\x65\x2d\x37\x2c\
+\x2d\x33\x2e\x32\x34\x36\x39\x38\x35\x38\x2c\x32\x2e\x32\x39\x36\
+\x32\x34\x35\x2c\x36\x2e\x38\x37\x30\x38\x39\x36\x39\x65\x2d\x36\
+\x2c\x33\x36\x36\x2e\x39\x31\x30\x34\x39\x2c\x31\x35\x30\x34\x2e\
+\x31\x38\x33\x29\x22\x20\x2f\x3e\x0a\x20\x20\x20\x20\x3c\x6c\x69\
+\x6e\x65\x61\x72\x47\x72\x61\x64\x69\x65\x6e\x74\x0a\x20\x20\x20\
+\x20\x20\x20\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x63\x6f\x6c\
+\x6c\x65\x63\x74\x3d\x22\x61\x6c\x77\x61\x79\x73\x22\x0a\x20\x20\
+\x20\x20\x20\x20\x20\x78\x6c\x69\x6e\x6b\x3a\x68\x72\x65\x66\x3d\
+\x22\x23\x6c\x69\x6e\x65\x61\x72\x47\x72\x61\x64\x69\x65\x6e\x74\
+\x34\x31\x31\x37\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x69\x64\x3d\
+\x22\x6c\x69\x6e\x65\x61\x72\x47\x72\x61\x64\x69\x65\x6e\x74\x34\
+\x31\x32\x33\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x78\x31\x3d\x22\
+\x32\x36\x30\x2e\x39\x35\x32\x34\x32\x22\x0a\x20\x20\x20\x20\x20\
+\x20\x20\x79\x31\x3d\x22\x31\x32\x31\x2e\x31\x38\x38\x34\x32\x22\
+\x0a\x20\x20\x20\x20\x20\x20\x20\x78\x32\x3d\x22\x34\x38\x38\x2e\
+\x36\x35\x39\x35\x35\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x79\x32\
+\x3d\x22\x33\x35\x31\x2e\x34\x38\x30\x36\x35\x22\x0a\x20\x20\x20\
+\x20\x20\x20\x20\x67\x72\x61\x64\x69\x65\x6e\x74\x55\x6e\x69\x74\
+\x73\x3d\x22\x75\x73\x65\x72\x53\x70\x61\x63\x65\x4f\x6e\x55\x73\
+\x65\x22\x20\x2f\x3e\x0a\x20\x20\x20\x20\x3c\x6c\x69\x6e\x65\x61\
+\x72\x47\x72\x61\x64\x69\x65\x6e\x74\x0a\x20\x20\x20\x20\x20\x20\
+\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x63\x6f\x6c\x6c\x65\x63\
+\x74\x3d\x22\x61\x6c\x77\x61\x79\x73\x22\x0a\x20\x20\x20\x20\x20\
+\x20\x20\x78\x6c\x69\x6e\x6b\x3a\x68\x72\x65\x66\x3d\x22\x23\x6c\
+\x69\x6e\x65\x61\x72\x47\x72\x61\x64\x69\x65\x6e\x74\x34\x31\x31\
+\x37\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x69\x64\x3d\x22\x6c\x69\
+\x6e\x65\x61\x72\x47\x72\x61\x64\x69\x65\x6e\x74\x34\x31\x32\x39\
+\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x67\x72\x61\x64\x69\x65\x6e\
+\x74\x55\x6e\x69\x74\x73\x3d\x22\x75\x73\x65\x72\x53\x70\x61\x63\
+\x65\x4f\x6e\x55\x73\x65\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x78\
+\x31\x3d\x22\x32\x36\x30\x2e\x39\x35\x32\x34\x32\x22\x0a\x20\x20\
+\x20\x20\x20\x20\x20\x79\x31\x3d\x22\x31\x32\x31\x2e\x31\x38\x38\
+\x34\x32\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x78\x32\x3d\x22\x34\
+\x38\x38\x2e\x36\x35\x39\x35\x35\x22\x0a\x20\x20\x20\x20\x20\x20\
+\x20\x79\x32\x3d\x22\x33\x35\x31\x2e\x34\x38\x30\x36\x35\x22\x0a\
+\x20\x20\x20\x20\x20\x20\x20\x67\x72\x61\x64\x69\x65\x6e\x74\x54\
+\x72\x61\x6e\x73\x66\x6f\x72\x6d\x3d\x22\x6d\x61\x74\x72\x69\x78\
+\x28\x31\x2e\x32\x34\x35\x37\x32\x32\x36\x2c\x30\x2c\x30\x2c\x31\
+\x2e\x32\x36\x31\x35\x38\x35\x34\x2c\x2d\x31\x37\x36\x2e\x37\x37\
+\x36\x38\x2c\x2d\x39\x30\x2e\x34\x39\x36\x35\x30\x38\x29\x22\x20\
+\x2f\x3e\x0a\x20\x20\x3c\x2f\x64\x65\x66\x73\x3e\x0a\x20\x20\x3c\
+\x73\x6f\x64\x69\x70\x6f\x64\x69\x3a\x6e\x61\x6d\x65\x64\x76\x69\
+\x65\x77\x0a\x20\x20\x20\x20\x20\x69\x64\x3d\x22\x62\x61\x73\x65\
+\x22\x0a\x20\x20\x20\x20\x20\x70\x61\x67\x65\x63\x6f\x6c\x6f\x72\
+\x3d\x22\x23\x66\x66\x66\x66\x66\x66\x22\x0a\x20\x20\x20\x20\x20\
+\x62\x6f\x72\x64\x65\x72\x63\x6f\x6c\x6f\x72\x3d\x22\x23\x36\x36\
+\x36\x36\x36\x36\x22\x0a\x20\x20\x20\x20\x20\x62\x6f\x72\x64\x65\
+\x72\x6f\x70\x61\x63\x69\x74\x79\x3d\x22\x31\x2e\x30\x22\x0a\x20\
+\x20\x20\x20\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x70\x61\x67\
+\x65\x6f\x70\x61\x63\x69\x74\x79\x3d\x22\x30\x2e\x30\x22\x0a\x20\
+\x20\x20\x20\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x70\x61\x67\
+\x65\x73\x68\x61\x64\x6f\x77\x3d\x22\x32\x22\x0a\x20\x20\x20\x20\
+\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x7a\x6f\x6f\x6d\x3d\x22\
+\x30\x2e\x39\x36\x31\x36\x34\x36\x31\x31\x22\x0a\x20\x20\x20\x20\
+\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x63\x78\x3d\x22\x33\x32\
+\x36\x2e\x33\x38\x33\x38\x32\x22\x0a\x20\x20\x20\x20\x20\x69\x6e\
+\x6b\x73\x63\x61\x70\x65\x3a\x63\x79\x3d\x22\x36\x39\x2e\x37\x31\
+\x35\x34\x39\x22\x0a\x20\x20\x20\x20\x20\x69\x6e\x6b\x73\x63\x61\
+\x70\x65\x3a\x64\x6f\x63\x75\x6d\x65\x6e\x74\x2d\x75\x6e\x69\x74\
+\x73\x3d\x22\x70\x78\x22\x0a\x20\x20\x20\x20\x20\x69\x6e\x6b\x73\
+\x63\x61\x70\x65\x3a\x63\x75\x72\x72\x65\x6e\x74\x2d\x6c\x61\x79\
+\x65\x72\x3d\x22\x6c\x61\x79\x65\x72\x31\x22\x0a\x20\x20\x20\x20\
+\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x77\x69\x6e\x64\x6f\x77\
+\x2d\x77\x69\x64\x74\x68\x3d\x22\x39\x39\x36\x22\x0a\x20\x20\x20\
+\x20\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x77\x69\x6e\x64\x6f\
+\x77\x2d\x68\x65\x69\x67\x68\x74\x3d\x22\x37\x31\x34\x22\x0a\x20\
+\x20\x20\x20\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x77\x69\x6e\
+\x64\x6f\x77\x2d\x78\x3d\x22\x31\x31\x22\x0a\x20\x20\x20\x20\x20\
+\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x77\x69\x6e\x64\x6f\x77\x2d\
+\x79\x3d\x22\x31\x33\x22\x20\x2f\x3e\x0a\x20\x20\x3c\x6d\x65\x74\
+\x61\x64\x61\x74\x61\x0a\x20\x20\x20\x20\x20\x69\x64\x3d\x22\x6d\
+\x65\x74\x61\x64\x61\x74\x61\x37\x22\x3e\x0a\x20\x20\x20\x20\x3c\
+\x72\x64\x66\x3a\x52\x44\x46\x3e\x0a\x20\x20\x20\x20\x20\x20\x3c\
+\x63\x63\x3a\x57\x6f\x72\x6b\x0a\x20\x20\x20\x20\x20\x20\x20\x20\
+\x20\x72\x64\x66\x3a\x61\x62\x6f\x75\x74\x3d\x22\x22\x3e\x0a\x20\
+\x20\x20\x20\x20\x20\x20\x20\x3c\x64\x63\x3a\x66\x6f\x72\x6d\x61\
+\x74\x3e\x69\x6d\x61\x67\x65\x2f\x73\x76\x67\x2b\x78\x6d\x6c\x3c\
+\x2f\x64\x63\x3a\x66\x6f\x72\x6d\x61\x74\x3e\x0a\x20\x20\x20\x20\
+\x20\x20\x20\x20\x3c\x64\x63\x3a\x74\x79\x70\x65\x0a\x20\x20\x20\
+\x20\x20\x20\x20\x20\x20\x20\x20\x72\x64\x66\x3a\x72\x65\x73\x6f\
+\x75\x72\x63\x65\x3d\x22\x68\x74\x74\x70\x3a\x2f\x2f\x70\x75\x72\
+\x6c\x2e\x6f\x72\x67\x2f\x64\x63\x2f\x64\x63\x6d\x69\x74\x79\x70\
+\x65\x2f\x53\x74\x69\x6c\x6c\x49\x6d\x61\x67\x65\x22\x20\x2f\x3e\
+\x0a\x20\x20\x20\x20\x20\x20\x3c\x2f\x63\x63\x3a\x57\x6f\x72\x6b\
+\x3e\x0a\x20\x20\x20\x20\x3c\x2f\x72\x64\x66\x3a\x52\x44\x46\x3e\
+\x0a\x20\x20\x3c\x2f\x6d\x65\x74\x61\x64\x61\x74\x61\x3e\x0a\x20\
+\x20\x3c\x67\x0a\x20\x20\x20\x20\x20\x69\x6e\x6b\x73\x63\x61\x70\
+\x65\x3a\x6c\x61\x62\x65\x6c\x3d\x22\x43\x61\x6c\x71\x75\x65\x20\
+\x31\x22\x0a\x20\x20\x20\x20\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\
+\x3a\x67\x72\x6f\x75\x70\x6d\x6f\x64\x65\x3d\x22\x6c\x61\x79\x65\
+\x72\x22\x0a\x20\x20\x20\x20\x20\x69\x64\x3d\x22\x6c\x61\x79\x65\
+\x72\x31\x22\x0a\x20\x20\x20\x20\x20\x74\x72\x61\x6e\x73\x66\x6f\
+\x72\x6d\x3d\x22\x74\x72\x61\x6e\x73\x6c\x61\x74\x65\x28\x2d\x31\
+\x37\x35\x2e\x39\x35\x38\x34\x37\x2c\x2d\x31\x37\x31\x2e\x37\x39\
+\x38\x39\x34\x29\x22\x3e\x0a\x20\x20\x20\x20\x3c\x72\x65\x63\x74\
+\x0a\x20\x20\x20\x20\x20\x20\x20\x79\x3d\x22\x31\x38\x30\x2e\x39\
+\x33\x39\x37\x34\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x78\x3d\x22\
+\x31\x38\x35\x2e\x30\x39\x39\x32\x37\x22\x0a\x20\x20\x20\x20\x20\
+\x20\x20\x68\x65\x69\x67\x68\x74\x3d\x22\x32\x35\x39\x2e\x39\x37\
+\x30\x38\x39\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x77\x69\x64\x74\
+\x68\x3d\x22\x32\x35\x39\x2e\x39\x37\x30\x38\x39\x22\x0a\x20\x20\
+\x20\x20\x20\x20\x20\x69\x64\x3d\x22\x72\x65\x63\x74\x33\x31\x33\
+\x34\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x73\x74\x79\x6c\x65\x3d\
+\x22\x6f\x70\x61\x63\x69\x74\x79\x3a\x31\x3b\x66\x69\x6c\x6c\x3a\
+\x75\x72\x6c\x28\x23\x72\x61\x64\x69\x61\x6c\x47\x72\x61\x64\x69\
+\x65\x6e\x74\x33\x31\x34\x32\x29\x3b\x66\x69\x6c\x6c\x2d\x6f\x70\
+\x61\x63\x69\x74\x79\x3a\x31\x3b\x66\x69\x6c\x6c\x2d\x72\x75\x6c\
+\x65\x3a\x6e\x6f\x6e\x7a\x65\x72\x6f\x3b\x73\x74\x72\x6f\x6b\x65\
+\x3a\x23\x66\x66\x66\x66\x66\x66\x3b\x73\x74\x72\x6f\x6b\x65\x2d\
+\x77\x69\x64\x74\x68\x3a\x30\x2e\x32\x39\x33\x39\x30\x36\x36\x36\
+\x3b\x73\x74\x72\x6f\x6b\x65\x2d\x6c\x69\x6e\x65\x63\x61\x70\x3a\
+\x62\x75\x74\x74\x3b\x73\x74\x72\x6f\x6b\x65\x2d\x6d\x69\x74\x65\
+\x72\x6c\x69\x6d\x69\x74\x3a\x34\x3b\x73\x74\x72\x6f\x6b\x65\x2d\
+\x64\x61\x73\x68\x61\x72\x72\x61\x79\x3a\x30\x2e\x32\x39\x33\x39\
+\x30\x36\x36\x36\x2c\x20\x30\x2e\x32\x39\x33\x39\x30\x36\x36\x36\
+\x3b\x73\x74\x72\x6f\x6b\x65\x2d\x64\x61\x73\x68\x6f\x66\x66\x73\
+\x65\x74\x3a\x30\x3b\x73\x74\x72\x6f\x6b\x65\x2d\x6f\x70\x61\x63\
+\x69\x74\x79\x3a\x31\x22\x20\x2f\x3e\x0a\x20\x20\x20\x20\x3c\x72\
+\x65\x63\x74\x0a\x20\x20\x20\x20\x20\x20\x20\x73\x74\x79\x6c\x65\
+\x3d\x22\x6f\x70\x61\x63\x69\x74\x79\x3a\x31\x3b\x66\x69\x6c\x6c\
+\x3a\x23\x61\x32\x30\x30\x30\x30\x3b\x66\x69\x6c\x6c\x2d\x6f\x70\
+\x61\x63\x69\x74\x79\x3a\x31\x3b\x66\x69\x6c\x6c\x2d\x72\x75\x6c\
+\x65\x3a\x6e\x6f\x6e\x7a\x65\x72\x6f\x3b\x73\x74\x72\x6f\x6b\x65\
+\x3a\x23\x66\x66\x66\x66\x66\x66\x3b\x73\x74\x72\x6f\x6b\x65\x2d\
+\x77\x69\x64\x74\x68\x3a\x30\x2e\x32\x39\x33\x39\x30\x36\x36\x36\
+\x3b\x73\x74\x72\x6f\x6b\x65\x2d\x6c\x69\x6e\x65\x63\x61\x70\x3a\
+\x62\x75\x74\x74\x3b\x73\x74\x72\x6f\x6b\x65\x2d\x6d\x69\x74\x65\
+\x72\x6c\x69\x6d\x69\x74\x3a\x34\x3b\x73\x74\x72\x6f\x6b\x65\x2d\
+\x64\x61\x73\x68\x61\x72\x72\x61\x79\x3a\x30\x2e\x32\x39\x33\x39\
+\x30\x36\x36\x36\x2c\x20\x30\x2e\x32\x39\x33\x39\x30\x36\x36\x36\
+\x3b\x73\x74\x72\x6f\x6b\x65\x2d\x64\x61\x73\x68\x6f\x66\x66\x73\
+\x65\x74\x3a\x30\x3b\x73\x74\x72\x6f\x6b\x65\x2d\x6f\x70\x61\x63\
+\x69\x74\x79\x3a\x31\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x69\x64\
+\x3d\x22\x72\x65\x63\x74\x32\x31\x36\x30\x22\x0a\x20\x20\x20\x20\
+\x20\x20\x20\x77\x69\x64\x74\x68\x3d\x22\x32\x35\x39\x2e\x39\x37\
+\x30\x38\x39\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x68\x65\x69\x67\
+\x68\x74\x3d\x22\x32\x35\x39\x2e\x39\x37\x30\x38\x39\x22\x0a\x20\
+\x20\x20\x20\x20\x20\x20\x78\x3d\x22\x31\x38\x35\x2e\x30\x39\x39\
+\x32\x37\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x79\x3d\x22\x31\x38\
+\x30\x2e\x39\x33\x39\x37\x34\x22\x20\x2f\x3e\x0a\x20\x20\x20\x20\
+\x3c\x72\x65\x63\x74\x0a\x20\x20\x20\x20\x20\x20\x20\x79\x3d\x22\
+\x31\x37\x36\x2e\x33\x38\x37\x34\x34\x22\x0a\x20\x20\x20\x20\x20\
+\x20\x20\x78\x3d\x22\x31\x38\x30\x2e\x35\x34\x36\x39\x37\x22\x0a\
+\x20\x20\x20\x20\x20\x20\x20\x68\x65\x69\x67\x68\x74\x3d\x22\x32\
+\x36\x39\x2e\x30\x37\x35\x35\x22\x0a\x20\x20\x20\x20\x20\x20\x20\
+\x77\x69\x64\x74\x68\x3d\x22\x32\x36\x39\x2e\x30\x37\x35\x35\x22\
+\x0a\x20\x20\x20\x20\x20\x20\x20\x69\x64\x3d\x22\x72\x65\x63\x74\
+\x32\x31\x36\x32\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x73\x74\x79\
+\x6c\x65\x3d\x22\x6f\x70\x61\x63\x69\x74\x79\x3a\x31\x3b\x66\x69\
+\x6c\x6c\x3a\x6e\x6f\x6e\x65\x3b\x66\x69\x6c\x6c\x2d\x6f\x70\x61\
+\x63\x69\x74\x79\x3a\x31\x3b\x66\x69\x6c\x6c\x2d\x72\x75\x6c\x65\
+\x3a\x6e\x6f\x6e\x7a\x65\x72\x6f\x3b\x73\x74\x72\x6f\x6b\x65\x3a\
+\x23\x39\x35\x30\x30\x30\x30\x3b\x73\x74\x72\x6f\x6b\x65\x2d\x77\
+\x69\x64\x74\x68\x3a\x39\x2e\x31\x37\x37\x30\x30\x30\x30\x35\x3b\
+\x73\x74\x72\x6f\x6b\x65\x2d\x6c\x69\x6e\x65\x63\x61\x70\x3a\x62\
+\x75\x74\x74\x3b\x73\x74\x72\x6f\x6b\x65\x2d\x6d\x69\x74\x65\x72\
+\x6c\x69\x6d\x69\x74\x3a\x34\x3b\x73\x74\x72\x6f\x6b\x65\x2d\x64\
+\x61\x73\x68\x61\x72\x72\x61\x79\x3a\x6e\x6f\x6e\x65\x3b\x73\x74\
+\x72\x6f\x6b\x65\x2d\x64\x61\x73\x68\x6f\x66\x66\x73\x65\x74\x3a\
+\x30\x3b\x73\x74\x72\x6f\x6b\x65\x2d\x6f\x70\x61\x63\x69\x74\x79\
+\x3a\x31\x22\x20\x2f\x3e\x0a\x20\x20\x20\x20\x3c\x70\x61\x74\x68\
+\x0a\x20\x20\x20\x20\x20\x20\x20\x73\x74\x79\x6c\x65\x3d\x22\x66\
+\x69\x6c\x6c\x3a\x75\x72\x6c\x28\x23\x6c\x69\x6e\x65\x61\x72\x47\
+\x72\x61\x64\x69\x65\x6e\x74\x34\x31\x32\x39\x29\x3b\x66\x69\x6c\
+\x6c\x2d\x6f\x70\x61\x63\x69\x74\x79\x3a\x31\x3b\x66\x69\x6c\x6c\
+\x2d\x72\x75\x6c\x65\x3a\x6e\x6f\x6e\x7a\x65\x72\x6f\x3b\x73\x74\
+\x72\x6f\x6b\x65\x3a\x6e\x6f\x6e\x65\x3b\x73\x74\x72\x6f\x6b\x65\
+\x2d\x77\x69\x64\x74\x68\x3a\x35\x3b\x73\x74\x72\x6f\x6b\x65\x2d\
+\x6c\x69\x6e\x65\x63\x61\x70\x3a\x62\x75\x74\x74\x3b\x73\x74\x72\
+\x6f\x6b\x65\x2d\x6d\x69\x74\x65\x72\x6c\x69\x6d\x69\x74\x3a\x34\
+\x3b\x73\x74\x72\x6f\x6b\x65\x2d\x64\x61\x73\x68\x6f\x66\x66\x73\
+\x65\x74\x3a\x30\x3b\x73\x74\x72\x6f\x6b\x65\x2d\x6f\x70\x61\x63\
+\x69\x74\x79\x3a\x31\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x64\x3d\
+\x22\x4d\x20\x31\x38\x35\x2e\x30\x39\x33\x37\x35\x2c\x31\x38\x30\
+\x2e\x39\x33\x37\x35\x20\x4c\x20\x31\x38\x35\x2e\x30\x39\x33\x37\
+\x35\x2c\x33\x35\x32\x2e\x35\x36\x32\x35\x20\x43\x20\x31\x39\x30\
+\x2e\x39\x33\x37\x35\x32\x2c\x33\x35\x32\x2e\x37\x39\x39\x38\x32\
+\x20\x31\x39\x36\x2e\x38\x33\x38\x35\x36\x2c\x33\x35\x32\x2e\x39\
+\x33\x37\x35\x20\x32\x30\x32\x2e\x37\x38\x31\x32\x35\x2c\x33\x35\
+\x32\x2e\x39\x33\x37\x35\x20\x43\x20\x33\x31\x32\x2e\x38\x30\x30\
+\x31\x34\x2c\x33\x35\x32\x2e\x39\x33\x37\x35\x20\x34\x30\x36\x2e\
+\x39\x35\x30\x34\x39\x2c\x33\x31\x31\x2e\x36\x31\x30\x34\x34\x20\
+\x34\x34\x35\x2e\x30\x36\x32\x35\x2c\x32\x35\x33\x2e\x32\x35\x20\
+\x4c\x20\x34\x34\x35\x2e\x30\x36\x32\x35\x2c\x31\x38\x30\x2e\x39\
+\x33\x37\x35\x20\x4c\x20\x31\x38\x35\x2e\x30\x39\x33\x37\x35\x2c\
+\x31\x38\x30\x2e\x39\x33\x37\x35\x20\x7a\x20\x22\x0a\x20\x20\x20\
+\x20\x20\x20\x20\x69\x64\x3d\x22\x70\x61\x74\x68\x33\x31\x34\x34\
+\x22\x20\x2f\x3e\x0a\x20\x20\x20\x20\x3c\x70\x61\x74\x68\x0a\x20\
+\x20\x20\x20\x20\x20\x20\x73\x6f\x64\x69\x70\x6f\x64\x69\x3a\x74\
+\x79\x70\x65\x3d\x22\x61\x72\x63\x22\x0a\x20\x20\x20\x20\x20\x20\
+\x20\x73\x74\x79\x6c\x65\x3d\x22\x6f\x70\x61\x63\x69\x74\x79\x3a\
+\x31\x3b\x66\x69\x6c\x6c\x3a\x6e\x6f\x6e\x65\x3b\x66\x69\x6c\x6c\
+\x2d\x6f\x70\x61\x63\x69\x74\x79\x3a\x31\x3b\x66\x69\x6c\x6c\x2d\
+\x72\x75\x6c\x65\x3a\x6e\x6f\x6e\x7a\x65\x72\x6f\x3b\x73\x74\x72\
+\x6f\x6b\x65\x3a\x23\x30\x30\x30\x30\x30\x30\x3b\x73\x74\x72\x6f\
+\x6b\x65\x2d\x77\x69\x64\x74\x68\x3a\x35\x3b\x73\x74\x72\x6f\x6b\
+\x65\x2d\x6c\x69\x6e\x65\x63\x61\x70\x3a\x62\x75\x74\x74\x3b\x73\
+\x74\x72\x6f\x6b\x65\x2d\x6d\x69\x74\x65\x72\x6c\x69\x6d\x69\x74\
+\x3a\x34\x3b\x73\x74\x72\x6f\x6b\x65\x2d\x64\x61\x73\x68\x61\x72\
+\x72\x61\x79\x3a\x6e\x6f\x6e\x65\x3b\x73\x74\x72\x6f\x6b\x65\x2d\
+\x64\x61\x73\x68\x6f\x66\x66\x73\x65\x74\x3a\x30\x3b\x73\x74\x72\
+\x6f\x6b\x65\x2d\x6f\x70\x61\x63\x69\x74\x79\x3a\x31\x22\x0a\x20\
+\x20\x20\x20\x20\x20\x20\x69\x64\x3d\x22\x70\x61\x74\x68\x33\x31\
+\x34\x36\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x73\x6f\x64\x69\x70\
+\x6f\x64\x69\x3a\x63\x78\x3d\x22\x33\x30\x33\x2e\x36\x34\x36\x22\
+\x0a\x20\x20\x20\x20\x20\x20\x20\x73\x6f\x64\x69\x70\x6f\x64\x69\
+\x3a\x63\x79\x3d\x22\x31\x32\x39\x2e\x39\x38\x35\x34\x34\x22\x0a\
+\x20\x20\x20\x20\x20\x20\x20\x73\x6f\x64\x69\x70\x6f\x64\x69\x3a\
+\x72\x78\x3d\x22\x30\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x73\x6f\
+\x64\x69\x70\x6f\x64\x69\x3a\x72\x79\x3d\x22\x37\x2e\x32\x37\x39\
+\x31\x38\x35\x33\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x64\x3d\x22\
+\x4d\x20\x33\x30\x33\x2e\x36\x34\x36\x20\x31\x32\x39\x2e\x39\x38\
+\x35\x34\x34\x20\x41\x20\x30\x20\x37\x2e\x32\x37\x39\x31\x38\x35\
+\x33\x20\x30\x20\x31\x20\x31\x20\x20\x33\x30\x33\x2e\x36\x34\x36\
+\x2c\x31\x32\x39\x2e\x39\x38\x35\x34\x34\x20\x41\x20\x30\x20\x37\
+\x2e\x32\x37\x39\x31\x38\x35\x33\x20\x30\x20\x31\x20\x31\x20\x20\
+\x33\x30\x33\x2e\x36\x34\x36\x20\x31\x32\x39\x2e\x39\x38\x35\x34\
+\x34\x20\x7a\x22\x20\x2f\x3e\x0a\x20\x20\x3c\x2f\x67\x3e\x0a\x3c\
+\x2f\x73\x76\x67\x3e\x0a\
+\x00\x00\x14\x96\
+\x3c\
+\x3f\x78\x6d\x6c\x20\x76\x65\x72\x73\x69\x6f\x6e\x3d\x22\x31\x2e\
+\x30\x22\x20\x65\x6e\x63\x6f\x64\x69\x6e\x67\x3d\x22\x55\x54\x46\
+\x2d\x38\x22\x20\x73\x74\x61\x6e\x64\x61\x6c\x6f\x6e\x65\x3d\x22\
+\x6e\x6f\x22\x3f\x3e\x0a\x3c\x21\x2d\x2d\x20\x43\x72\x65\x61\x74\
+\x65\x64\x20\x77\x69\x74\x68\x20\x49\x6e\x6b\x73\x63\x61\x70\x65\
+\x20\x28\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\x77\x2e\x69\x6e\x6b\
+\x73\x63\x61\x70\x65\x2e\x6f\x72\x67\x2f\x29\x20\x2d\x2d\x3e\x0a\
+\x3c\x73\x76\x67\x0a\x20\x20\x20\x78\x6d\x6c\x6e\x73\x3a\x64\x63\
+\x3d\x22\x68\x74\x74\x70\x3a\x2f\x2f\x70\x75\x72\x6c\x2e\x6f\x72\
+\x67\x2f\x64\x63\x2f\x65\x6c\x65\x6d\x65\x6e\x74\x73\x2f\x31\x2e\
+\x31\x2f\x22\x0a\x20\x20\x20\x78\x6d\x6c\x6e\x73\x3a\x63\x63\x3d\
+\x22\x68\x74\x74\x70\x3a\x2f\x2f\x77\x65\x62\x2e\x72\x65\x73\x6f\
+\x75\x72\x63\x65\x2e\x6f\x72\x67\x2f\x63\x63\x2f\x22\x0a\x20\x20\
+\x20\x78\x6d\x6c\x6e\x73\x3a\x72\x64\x66\x3d\x22\x68\x74\x74\x70\
+\x3a\x2f\x2f\x77\x77\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x31\x39\
+\x39\x39\x2f\x30\x32\x2f\x32\x32\x2d\x72\x64\x66\x2d\x73\x79\x6e\
+\x74\x61\x78\x2d\x6e\x73\x23\x22\x0a\x20\x20\x20\x78\x6d\x6c\x6e\
+\x73\x3a\x73\x76\x67\x3d\x22\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\
+\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x32\x30\x30\x30\x2f\x73\x76\
+\x67\x22\x0a\x20\x20\x20\x78\x6d\x6c\x6e\x73\x3d\x22\x68\x74\x74\
+\x70\x3a\x2f\x2f\x77\x77\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x32\
+\x30\x30\x30\x2f\x73\x76\x67\x22\x0a\x20\x20\x20\x78\x6d\x6c\x6e\
+\x73\x3a\x78\x6c\x69\x6e\x6b\x3d\x22\x68\x74\x74\x70\x3a\x2f\x2f\
+\x77\x77\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x31\x39\x39\x39\x2f\
+\x78\x6c\x69\x6e\x6b\x22\x0a\x20\x20\x20\x78\x6d\x6c\x6e\x73\x3a\
+\x73\x6f\x64\x69\x70\x6f\x64\x69\x3d\x22\x68\x74\x74\x70\x3a\x2f\
+\x2f\x73\x6f\x64\x69\x70\x6f\x64\x69\x2e\x73\x6f\x75\x72\x63\x65\
+\x66\x6f\x72\x67\x65\x2e\x6e\x65\x74\x2f\x44\x54\x44\x2f\x73\x6f\
+\x64\x69\x70\x6f\x64\x69\x2d\x30\x2e\x64\x74\x64\x22\x0a\x20\x20\
+\x20\x78\x6d\x6c\x6e\x73\x3a\x69\x6e\x6b\x73\x63\x61\x70\x65\x3d\
+\x22\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\x77\x2e\x69\x6e\x6b\x73\
+\x63\x61\x70\x65\x2e\x6f\x72\x67\x2f\x6e\x61\x6d\x65\x73\x70\x61\
+\x63\x65\x73\x2f\x69\x6e\x6b\x73\x63\x61\x70\x65\x22\x0a\x20\x20\
+\x20\x77\x69\x64\x74\x68\x3d\x22\x32\x37\x38\x2e\x32\x35\x32\x34\
+\x31\x22\x0a\x20\x20\x20\x68\x65\x69\x67\x68\x74\x3d\x22\x32\x37\
+\x38\x2e\x32\x35\x32\x34\x31\x22\x0a\x20\x20\x20\x69\x64\x3d\x22\
+\x73\x76\x67\x32\x22\x0a\x20\x20\x20\x73\x6f\x64\x69\x70\x6f\x64\
+\x69\x3a\x76\x65\x72\x73\x69\x6f\x6e\x3d\x22\x30\x2e\x33\x32\x22\
+\x0a\x20\x20\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x76\x65\x72\
+\x73\x69\x6f\x6e\x3d\x22\x30\x2e\x34\x35\x2e\x31\x22\x0a\x20\x20\
+\x20\x73\x6f\x64\x69\x70\x6f\x64\x69\x3a\x64\x6f\x63\x62\x61\x73\
+\x65\x3d\x22\x2f\x68\x6f\x6d\x65\x2f\x64\x61\x76\x69\x64\x2f\x45\
+\x6c\x65\x63\x74\x72\x6f\x6e\x69\x63\x2f\x48\x50\x33\x35\x36\x32\
+\x2f\x69\x63\x6f\x6e\x73\x22\x0a\x20\x20\x20\x73\x6f\x64\x69\x70\
+\x6f\x64\x69\x3a\x64\x6f\x63\x6e\x61\x6d\x65\x3d\x22\x6c\x65\x64\
+\x5f\x67\x72\x65\x65\x6e\x2e\x73\x76\x67\x22\x0a\x20\x20\x20\x69\
+\x6e\x6b\x73\x63\x61\x70\x65\x3a\x6f\x75\x74\x70\x75\x74\x5f\x65\
+\x78\x74\x65\x6e\x73\x69\x6f\x6e\x3d\x22\x6f\x72\x67\x2e\x69\x6e\
+\x6b\x73\x63\x61\x70\x65\x2e\x6f\x75\x74\x70\x75\x74\x2e\x73\x76\
+\x67\x2e\x69\x6e\x6b\x73\x63\x61\x70\x65\x22\x0a\x20\x20\x20\x76\
+\x65\x72\x73\x69\x6f\x6e\x3d\x22\x31\x2e\x30\x22\x3e\x0a\x20\x20\
+\x3c\x64\x65\x66\x73\x0a\x20\x20\x20\x20\x20\x69\x64\x3d\x22\x64\
+\x65\x66\x73\x34\x22\x3e\x0a\x20\x20\x20\x20\x3c\x6c\x69\x6e\x65\
+\x61\x72\x47\x72\x61\x64\x69\x65\x6e\x74\x0a\x20\x20\x20\x20\x20\
+\x20\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x63\x6f\x6c\x6c\x65\
+\x63\x74\x3d\x22\x61\x6c\x77\x61\x79\x73\x22\x0a\x20\x20\x20\x20\
+\x20\x20\x20\x69\x64\x3d\x22\x6c\x69\x6e\x65\x61\x72\x47\x72\x61\
+\x64\x69\x65\x6e\x74\x34\x31\x31\x37\x22\x3e\x0a\x20\x20\x20\x20\
+\x20\x20\x3c\x73\x74\x6f\x70\x0a\x20\x20\x20\x20\x20\x20\x20\x20\
+\x20\x73\x74\x79\x6c\x65\x3d\x22\x73\x74\x6f\x70\x2d\x63\x6f\x6c\
+\x6f\x72\x3a\x23\x66\x66\x66\x66\x66\x66\x3b\x73\x74\x6f\x70\x2d\
+\x6f\x70\x61\x63\x69\x74\x79\x3a\x31\x3b\x22\x0a\x20\x20\x20\x20\
+\x20\x20\x20\x20\x20\x6f\x66\x66\x73\x65\x74\x3d\x22\x30\x22\x0a\
+\x20\x20\x20\x20\x20\x20\x20\x20\x20\x69\x64\x3d\x22\x73\x74\x6f\
+\x70\x34\x31\x31\x39\x22\x20\x2f\x3e\x0a\x20\x20\x20\x20\x20\x20\
+\x3c\x73\x74\x6f\x70\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x73\
+\x74\x79\x6c\x65\x3d\x22\x73\x74\x6f\x70\x2d\x63\x6f\x6c\x6f\x72\
+\x3a\x23\x66\x66\x66\x66\x66\x66\x3b\x73\x74\x6f\x70\x2d\x6f\x70\
+\x61\x63\x69\x74\x79\x3a\x30\x3b\x22\x0a\x20\x20\x20\x20\x20\x20\
+\x20\x20\x20\x6f\x66\x66\x73\x65\x74\x3d\x22\x31\x22\x0a\x20\x20\
+\x20\x20\x20\x20\x20\x20\x20\x69\x64\x3d\x22\x73\x74\x6f\x70\x34\
+\x31\x32\x31\x22\x20\x2f\x3e\x0a\x20\x20\x20\x20\x3c\x2f\x6c\x69\
+\x6e\x65\x61\x72\x47\x72\x61\x64\x69\x65\x6e\x74\x3e\x0a\x20\x20\
+\x20\x20\x3c\x6c\x69\x6e\x65\x61\x72\x47\x72\x61\x64\x69\x65\x6e\
+\x74\x0a\x20\x20\x20\x20\x20\x20\x20\x69\x64\x3d\x22\x6c\x69\x6e\
+\x65\x61\x72\x47\x72\x61\x64\x69\x65\x6e\x74\x33\x31\x33\x36\x22\
+\x3e\x0a\x20\x20\x20\x20\x20\x20\x3c\x73\x74\x6f\x70\x0a\x20\x20\
+\x20\x20\x20\x20\x20\x20\x20\x73\x74\x79\x6c\x65\x3d\x22\x73\x74\
+\x6f\x70\x2d\x63\x6f\x6c\x6f\x72\x3a\x23\x66\x66\x66\x66\x66\x66\
+\x3b\x73\x74\x6f\x70\x2d\x6f\x70\x61\x63\x69\x74\x79\x3a\x31\x3b\
+\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x6f\x66\x66\x73\x65\
+\x74\x3d\x22\x30\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x69\
+\x64\x3d\x22\x73\x74\x6f\x70\x33\x31\x33\x38\x22\x20\x2f\x3e\x0a\
+\x20\x20\x20\x20\x20\x20\x3c\x73\x74\x6f\x70\x0a\x20\x20\x20\x20\
+\x20\x20\x20\x20\x20\x73\x74\x79\x6c\x65\x3d\x22\x73\x74\x6f\x70\
+\x2d\x63\x6f\x6c\x6f\x72\x3a\x23\x30\x30\x66\x66\x30\x30\x3b\x73\
+\x74\x6f\x70\x2d\x6f\x70\x61\x63\x69\x74\x79\x3a\x30\x3b\x22\x0a\
+\x20\x20\x20\x20\x20\x20\x20\x20\x20\x6f\x66\x66\x73\x65\x74\x3d\
+\x22\x31\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x69\x64\x3d\
+\x22\x73\x74\x6f\x70\x33\x31\x34\x30\x22\x20\x2f\x3e\x0a\x20\x20\
+\x20\x20\x3c\x2f\x6c\x69\x6e\x65\x61\x72\x47\x72\x61\x64\x69\x65\
+\x6e\x74\x3e\x0a\x20\x20\x20\x20\x3c\x72\x61\x64\x69\x61\x6c\x47\
+\x72\x61\x64\x69\x65\x6e\x74\x0a\x20\x20\x20\x20\x20\x20\x20\x69\
+\x6e\x6b\x73\x63\x61\x70\x65\x3a\x63\x6f\x6c\x6c\x65\x63\x74\x3d\
+\x22\x61\x6c\x77\x61\x79\x73\x22\x0a\x20\x20\x20\x20\x20\x20\x20\
+\x78\x6c\x69\x6e\x6b\x3a\x68\x72\x65\x66\x3d\x22\x23\x6c\x69\x6e\
+\x65\x61\x72\x47\x72\x61\x64\x69\x65\x6e\x74\x33\x31\x33\x36\x22\
+\x0a\x20\x20\x20\x20\x20\x20\x20\x69\x64\x3d\x22\x72\x61\x64\x69\
+\x61\x6c\x47\x72\x61\x64\x69\x65\x6e\x74\x33\x31\x34\x32\x22\x0a\
+\x20\x20\x20\x20\x20\x20\x20\x63\x78\x3d\x22\x33\x32\x37\x2e\x34\
+\x31\x39\x32\x35\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x63\x79\x3d\
+\x22\x33\x34\x2e\x31\x30\x31\x39\x38\x32\x22\x0a\x20\x20\x20\x20\
+\x20\x20\x20\x66\x78\x3d\x22\x33\x32\x37\x2e\x34\x31\x39\x32\x35\
+\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x66\x79\x3d\x22\x33\x34\x2e\
+\x31\x30\x31\x39\x38\x32\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x72\
+\x3d\x22\x31\x33\x30\x2e\x31\x33\x32\x34\x22\x0a\x20\x20\x20\x20\
+\x20\x20\x20\x67\x72\x61\x64\x69\x65\x6e\x74\x55\x6e\x69\x74\x73\
+\x3d\x22\x75\x73\x65\x72\x53\x70\x61\x63\x65\x4f\x6e\x55\x73\x65\
+\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x67\x72\x61\x64\x69\x65\x6e\
+\x74\x54\x72\x61\x6e\x73\x66\x6f\x72\x6d\x3d\x22\x6d\x61\x74\x72\
+\x69\x78\x28\x32\x2e\x35\x36\x39\x35\x37\x30\x37\x65\x2d\x37\x2c\
+\x2d\x33\x2e\x32\x34\x36\x39\x38\x35\x38\x2c\x32\x2e\x32\x39\x36\
+\x32\x34\x35\x2c\x36\x2e\x38\x37\x30\x38\x39\x36\x39\x65\x2d\x36\
+\x2c\x33\x36\x36\x2e\x39\x31\x30\x34\x39\x2c\x31\x35\x30\x34\x2e\
+\x31\x38\x33\x29\x22\x20\x2f\x3e\x0a\x20\x20\x20\x20\x3c\x6c\x69\
+\x6e\x65\x61\x72\x47\x72\x61\x64\x69\x65\x6e\x74\x0a\x20\x20\x20\
+\x20\x20\x20\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x63\x6f\x6c\
+\x6c\x65\x63\x74\x3d\x22\x61\x6c\x77\x61\x79\x73\x22\x0a\x20\x20\
+\x20\x20\x20\x20\x20\x78\x6c\x69\x6e\x6b\x3a\x68\x72\x65\x66\x3d\
+\x22\x23\x6c\x69\x6e\x65\x61\x72\x47\x72\x61\x64\x69\x65\x6e\x74\
+\x34\x31\x31\x37\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x69\x64\x3d\
+\x22\x6c\x69\x6e\x65\x61\x72\x47\x72\x61\x64\x69\x65\x6e\x74\x34\
+\x31\x32\x33\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x78\x31\x3d\x22\
+\x32\x36\x30\x2e\x39\x35\x32\x34\x32\x22\x0a\x20\x20\x20\x20\x20\
+\x20\x20\x79\x31\x3d\x22\x31\x32\x31\x2e\x31\x38\x38\x34\x32\x22\
+\x0a\x20\x20\x20\x20\x20\x20\x20\x78\x32\x3d\x22\x34\x38\x38\x2e\
+\x36\x35\x39\x35\x35\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x79\x32\
+\x3d\x22\x33\x35\x31\x2e\x34\x38\x30\x36\x35\x22\x0a\x20\x20\x20\
+\x20\x20\x20\x20\x67\x72\x61\x64\x69\x65\x6e\x74\x55\x6e\x69\x74\
+\x73\x3d\x22\x75\x73\x65\x72\x53\x70\x61\x63\x65\x4f\x6e\x55\x73\
+\x65\x22\x20\x2f\x3e\x0a\x20\x20\x20\x20\x3c\x6c\x69\x6e\x65\x61\
+\x72\x47\x72\x61\x64\x69\x65\x6e\x74\x0a\x20\x20\x20\x20\x20\x20\
+\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x63\x6f\x6c\x6c\x65\x63\
+\x74\x3d\x22\x61\x6c\x77\x61\x79\x73\x22\x0a\x20\x20\x20\x20\x20\
+\x20\x20\x78\x6c\x69\x6e\x6b\x3a\x68\x72\x65\x66\x3d\x22\x23\x6c\
+\x69\x6e\x65\x61\x72\x47\x72\x61\x64\x69\x65\x6e\x74\x34\x31\x31\
+\x37\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x69\x64\x3d\x22\x6c\x69\
+\x6e\x65\x61\x72\x47\x72\x61\x64\x69\x65\x6e\x74\x34\x31\x32\x39\
+\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x67\x72\x61\x64\x69\x65\x6e\
+\x74\x55\x6e\x69\x74\x73\x3d\x22\x75\x73\x65\x72\x53\x70\x61\x63\
+\x65\x4f\x6e\x55\x73\x65\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x78\
+\x31\x3d\x22\x32\x36\x30\x2e\x39\x35\x32\x34\x32\x22\x0a\x20\x20\
+\x20\x20\x20\x20\x20\x79\x31\x3d\x22\x31\x32\x31\x2e\x31\x38\x38\
+\x34\x32\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x78\x32\x3d\x22\x34\
+\x38\x38\x2e\x36\x35\x39\x35\x35\x22\x0a\x20\x20\x20\x20\x20\x20\
+\x20\x79\x32\x3d\x22\x33\x35\x31\x2e\x34\x38\x30\x36\x35\x22\x0a\
+\x20\x20\x20\x20\x20\x20\x20\x67\x72\x61\x64\x69\x65\x6e\x74\x54\
+\x72\x61\x6e\x73\x66\x6f\x72\x6d\x3d\x22\x6d\x61\x74\x72\x69\x78\
+\x28\x31\x2e\x32\x34\x35\x37\x32\x32\x36\x2c\x30\x2c\x30\x2c\x31\
+\x2e\x32\x36\x31\x35\x38\x35\x34\x2c\x2d\x31\x37\x36\x2e\x37\x37\
+\x36\x38\x2c\x2d\x39\x30\x2e\x34\x39\x36\x35\x30\x38\x29\x22\x20\
+\x2f\x3e\x0a\x20\x20\x3c\x2f\x64\x65\x66\x73\x3e\x0a\x20\x20\x3c\
+\x73\x6f\x64\x69\x70\x6f\x64\x69\x3a\x6e\x61\x6d\x65\x64\x76\x69\
+\x65\x77\x0a\x20\x20\x20\x20\x20\x69\x64\x3d\x22\x62\x61\x73\x65\
+\x22\x0a\x20\x20\x20\x20\x20\x70\x61\x67\x65\x63\x6f\x6c\x6f\x72\
+\x3d\x22\x23\x66\x66\x66\x66\x66\x66\x22\x0a\x20\x20\x20\x20\x20\
+\x62\x6f\x72\x64\x65\x72\x63\x6f\x6c\x6f\x72\x3d\x22\x23\x36\x36\
+\x36\x36\x36\x36\x22\x0a\x20\x20\x20\x20\x20\x62\x6f\x72\x64\x65\
+\x72\x6f\x70\x61\x63\x69\x74\x79\x3d\x22\x31\x2e\x30\x22\x0a\x20\
+\x20\x20\x20\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x70\x61\x67\
+\x65\x6f\x70\x61\x63\x69\x74\x79\x3d\x22\x30\x2e\x30\x22\x0a\x20\
+\x20\x20\x20\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x70\x61\x67\
+\x65\x73\x68\x61\x64\x6f\x77\x3d\x22\x32\x22\x0a\x20\x20\x20\x20\
+\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x7a\x6f\x6f\x6d\x3d\x22\
+\x30\x2e\x34\x38\x30\x38\x32\x33\x30\x36\x22\x0a\x20\x20\x20\x20\
+\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x63\x78\x3d\x22\x33\x37\
+\x32\x2e\x30\x34\x37\x32\x34\x22\x0a\x20\x20\x20\x20\x20\x69\x6e\
+\x6b\x73\x63\x61\x70\x65\x3a\x63\x79\x3d\x22\x32\x30\x37\x2e\x31\
+\x32\x31\x33\x22\x0a\x20\x20\x20\x20\x20\x69\x6e\x6b\x73\x63\x61\
+\x70\x65\x3a\x64\x6f\x63\x75\x6d\x65\x6e\x74\x2d\x75\x6e\x69\x74\
+\x73\x3d\x22\x70\x78\x22\x0a\x20\x20\x20\x20\x20\x69\x6e\x6b\x73\
+\x63\x61\x70\x65\x3a\x63\x75\x72\x72\x65\x6e\x74\x2d\x6c\x61\x79\
+\x65\x72\x3d\x22\x6c\x61\x79\x65\x72\x31\x22\x0a\x20\x20\x20\x20\
+\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x77\x69\x6e\x64\x6f\x77\
+\x2d\x77\x69\x64\x74\x68\x3d\x22\x39\x39\x36\x22\x0a\x20\x20\x20\
+\x20\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x77\x69\x6e\x64\x6f\
+\x77\x2d\x68\x65\x69\x67\x68\x74\x3d\x22\x37\x31\x34\x22\x0a\x20\
+\x20\x20\x20\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x77\x69\x6e\
+\x64\x6f\x77\x2d\x78\x3d\x22\x32\x35\x22\x0a\x20\x20\x20\x20\x20\
+\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x77\x69\x6e\x64\x6f\x77\x2d\
+\x79\x3d\x22\x34\x22\x20\x2f\x3e\x0a\x20\x20\x3c\x6d\x65\x74\x61\
+\x64\x61\x74\x61\x0a\x20\x20\x20\x20\x20\x69\x64\x3d\x22\x6d\x65\
+\x74\x61\x64\x61\x74\x61\x37\x22\x3e\x0a\x20\x20\x20\x20\x3c\x72\
+\x64\x66\x3a\x52\x44\x46\x3e\x0a\x20\x20\x20\x20\x20\x20\x3c\x63\
+\x63\x3a\x57\x6f\x72\x6b\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\
+\x72\x64\x66\x3a\x61\x62\x6f\x75\x74\x3d\x22\x22\x3e\x0a\x20\x20\
+\x20\x20\x20\x20\x20\x20\x3c\x64\x63\x3a\x66\x6f\x72\x6d\x61\x74\
+\x3e\x69\x6d\x61\x67\x65\x2f\x73\x76\x67\x2b\x78\x6d\x6c\x3c\x2f\
+\x64\x63\x3a\x66\x6f\x72\x6d\x61\x74\x3e\x0a\x20\x20\x20\x20\x20\
+\x20\x20\x20\x3c\x64\x63\x3a\x74\x79\x70\x65\x0a\x20\x20\x20\x20\
+\x20\x20\x20\x20\x20\x20\x20\x72\x64\x66\x3a\x72\x65\x73\x6f\x75\
+\x72\x63\x65\x3d\x22\x68\x74\x74\x70\x3a\x2f\x2f\x70\x75\x72\x6c\
+\x2e\x6f\x72\x67\x2f\x64\x63\x2f\x64\x63\x6d\x69\x74\x79\x70\x65\
+\x2f\x53\x74\x69\x6c\x6c\x49\x6d\x61\x67\x65\x22\x20\x2f\x3e\x0a\
+\x20\x20\x20\x20\x20\x20\x3c\x2f\x63\x63\x3a\x57\x6f\x72\x6b\x3e\
+\x0a\x20\x20\x20\x20\x3c\x2f\x72\x64\x66\x3a\x52\x44\x46\x3e\x0a\
+\x20\x20\x3c\x2f\x6d\x65\x74\x61\x64\x61\x74\x61\x3e\x0a\x20\x20\
+\x3c\x67\x0a\x20\x20\x20\x20\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\
+\x3a\x6c\x61\x62\x65\x6c\x3d\x22\x43\x61\x6c\x71\x75\x65\x20\x31\
+\x22\x0a\x20\x20\x20\x20\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\
+\x67\x72\x6f\x75\x70\x6d\x6f\x64\x65\x3d\x22\x6c\x61\x79\x65\x72\
+\x22\x0a\x20\x20\x20\x20\x20\x69\x64\x3d\x22\x6c\x61\x79\x65\x72\
+\x31\x22\x0a\x20\x20\x20\x20\x20\x74\x72\x61\x6e\x73\x66\x6f\x72\
+\x6d\x3d\x22\x74\x72\x61\x6e\x73\x6c\x61\x74\x65\x28\x2d\x31\x37\
+\x35\x2e\x39\x35\x38\x35\x32\x2c\x2d\x31\x37\x31\x2e\x37\x39\x38\
+\x39\x39\x29\x22\x3e\x0a\x20\x20\x20\x20\x3c\x72\x65\x63\x74\x0a\
+\x20\x20\x20\x20\x20\x20\x20\x73\x74\x79\x6c\x65\x3d\x22\x6f\x70\
+\x61\x63\x69\x74\x79\x3a\x31\x3b\x66\x69\x6c\x6c\x3a\x23\x30\x30\
+\x66\x66\x30\x30\x3b\x66\x69\x6c\x6c\x2d\x6f\x70\x61\x63\x69\x74\
+\x79\x3a\x31\x3b\x66\x69\x6c\x6c\x2d\x72\x75\x6c\x65\x3a\x6e\x6f\
+\x6e\x7a\x65\x72\x6f\x3b\x73\x74\x72\x6f\x6b\x65\x3a\x23\x66\x66\
+\x66\x66\x66\x66\x3b\x73\x74\x72\x6f\x6b\x65\x2d\x77\x69\x64\x74\
+\x68\x3a\x30\x2e\x32\x39\x33\x39\x30\x36\x36\x36\x3b\x73\x74\x72\
+\x6f\x6b\x65\x2d\x6c\x69\x6e\x65\x63\x61\x70\x3a\x62\x75\x74\x74\
+\x3b\x73\x74\x72\x6f\x6b\x65\x2d\x6d\x69\x74\x65\x72\x6c\x69\x6d\
+\x69\x74\x3a\x34\x3b\x73\x74\x72\x6f\x6b\x65\x2d\x64\x61\x73\x68\
+\x61\x72\x72\x61\x79\x3a\x30\x2e\x32\x39\x33\x39\x30\x36\x36\x36\
+\x2c\x20\x30\x2e\x32\x39\x33\x39\x30\x36\x36\x36\x3b\x73\x74\x72\
+\x6f\x6b\x65\x2d\x64\x61\x73\x68\x6f\x66\x66\x73\x65\x74\x3a\x30\
+\x3b\x73\x74\x72\x6f\x6b\x65\x2d\x6f\x70\x61\x63\x69\x74\x79\x3a\
+\x31\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x69\x64\x3d\x22\x72\x65\
+\x63\x74\x32\x31\x36\x30\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x77\
+\x69\x64\x74\x68\x3d\x22\x32\x35\x39\x2e\x39\x37\x30\x38\x39\x22\
+\x0a\x20\x20\x20\x20\x20\x20\x20\x68\x65\x69\x67\x68\x74\x3d\x22\
+\x32\x35\x39\x2e\x39\x37\x30\x38\x39\x22\x0a\x20\x20\x20\x20\x20\
+\x20\x20\x78\x3d\x22\x31\x38\x35\x2e\x30\x39\x39\x32\x37\x22\x0a\
+\x20\x20\x20\x20\x20\x20\x20\x79\x3d\x22\x31\x38\x30\x2e\x39\x33\
+\x39\x37\x34\x22\x20\x2f\x3e\x0a\x20\x20\x20\x20\x3c\x72\x65\x63\
+\x74\x0a\x20\x20\x20\x20\x20\x20\x20\x79\x3d\x22\x31\x37\x36\x2e\
+\x33\x38\x37\x34\x34\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x78\x3d\
+\x22\x31\x38\x30\x2e\x35\x34\x36\x39\x37\x22\x0a\x20\x20\x20\x20\
+\x20\x20\x20\x68\x65\x69\x67\x68\x74\x3d\x22\x32\x36\x39\x2e\x30\
+\x37\x35\x35\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x77\x69\x64\x74\
+\x68\x3d\x22\x32\x36\x39\x2e\x30\x37\x35\x35\x22\x0a\x20\x20\x20\
+\x20\x20\x20\x20\x69\x64\x3d\x22\x72\x65\x63\x74\x32\x31\x36\x32\
+\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x73\x74\x79\x6c\x65\x3d\x22\
+\x6f\x70\x61\x63\x69\x74\x79\x3a\x31\x3b\x66\x69\x6c\x6c\x3a\x6e\
+\x6f\x6e\x65\x3b\x66\x69\x6c\x6c\x2d\x6f\x70\x61\x63\x69\x74\x79\
+\x3a\x31\x3b\x66\x69\x6c\x6c\x2d\x72\x75\x6c\x65\x3a\x6e\x6f\x6e\
+\x7a\x65\x72\x6f\x3b\x73\x74\x72\x6f\x6b\x65\x3a\x23\x30\x30\x63\
+\x34\x30\x62\x3b\x73\x74\x72\x6f\x6b\x65\x2d\x77\x69\x64\x74\x68\
+\x3a\x39\x2e\x31\x37\x36\x38\x39\x38\x39\x36\x3b\x73\x74\x72\x6f\
+\x6b\x65\x2d\x6c\x69\x6e\x65\x63\x61\x70\x3a\x62\x75\x74\x74\x3b\
+\x73\x74\x72\x6f\x6b\x65\x2d\x6d\x69\x74\x65\x72\x6c\x69\x6d\x69\
+\x74\x3a\x34\x3b\x73\x74\x72\x6f\x6b\x65\x2d\x64\x61\x73\x68\x61\
+\x72\x72\x61\x79\x3a\x6e\x6f\x6e\x65\x3b\x73\x74\x72\x6f\x6b\x65\
+\x2d\x64\x61\x73\x68\x6f\x66\x66\x73\x65\x74\x3a\x30\x3b\x73\x74\
+\x72\x6f\x6b\x65\x2d\x6f\x70\x61\x63\x69\x74\x79\x3a\x31\x22\x20\
+\x2f\x3e\x0a\x20\x20\x20\x20\x3c\x72\x65\x63\x74\x0a\x20\x20\x20\
+\x20\x20\x20\x20\x79\x3d\x22\x31\x38\x30\x2e\x39\x33\x39\x37\x34\
+\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x78\x3d\x22\x31\x38\x35\x2e\
+\x30\x39\x39\x32\x37\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x68\x65\
+\x69\x67\x68\x74\x3d\x22\x32\x35\x39\x2e\x39\x37\x30\x38\x39\x22\
+\x0a\x20\x20\x20\x20\x20\x20\x20\x77\x69\x64\x74\x68\x3d\x22\x32\
+\x35\x39\x2e\x39\x37\x30\x38\x39\x22\x0a\x20\x20\x20\x20\x20\x20\
+\x20\x69\x64\x3d\x22\x72\x65\x63\x74\x33\x31\x33\x34\x22\x0a\x20\
+\x20\x20\x20\x20\x20\x20\x73\x74\x79\x6c\x65\x3d\x22\x6f\x70\x61\
+\x63\x69\x74\x79\x3a\x31\x3b\x66\x69\x6c\x6c\x3a\x75\x72\x6c\x28\
+\x23\x72\x61\x64\x69\x61\x6c\x47\x72\x61\x64\x69\x65\x6e\x74\x33\
+\x31\x34\x32\x29\x3b\x66\x69\x6c\x6c\x2d\x6f\x70\x61\x63\x69\x74\
+\x79\x3a\x31\x3b\x66\x69\x6c\x6c\x2d\x72\x75\x6c\x65\x3a\x6e\x6f\
+\x6e\x7a\x65\x72\x6f\x3b\x73\x74\x72\x6f\x6b\x65\x3a\x23\x66\x66\
+\x66\x66\x66\x66\x3b\x73\x74\x72\x6f\x6b\x65\x2d\x77\x69\x64\x74\
+\x68\x3a\x30\x2e\x32\x39\x33\x39\x30\x36\x36\x36\x3b\x73\x74\x72\
+\x6f\x6b\x65\x2d\x6c\x69\x6e\x65\x63\x61\x70\x3a\x62\x75\x74\x74\
+\x3b\x73\x74\x72\x6f\x6b\x65\x2d\x6d\x69\x74\x65\x72\x6c\x69\x6d\
+\x69\x74\x3a\x34\x3b\x73\x74\x72\x6f\x6b\x65\x2d\x64\x61\x73\x68\
+\x61\x72\x72\x61\x79\x3a\x30\x2e\x32\x39\x33\x39\x30\x36\x36\x36\
+\x2c\x20\x30\x2e\x32\x39\x33\x39\x30\x36\x36\x36\x3b\x73\x74\x72\
+\x6f\x6b\x65\x2d\x64\x61\x73\x68\x6f\x66\x66\x73\x65\x74\x3a\x30\
+\x3b\x73\x74\x72\x6f\x6b\x65\x2d\x6f\x70\x61\x63\x69\x74\x79\x3a\
+\x31\x22\x20\x2f\x3e\x0a\x20\x20\x20\x20\x3c\x70\x61\x74\x68\x0a\
+\x20\x20\x20\x20\x20\x20\x20\x73\x74\x79\x6c\x65\x3d\x22\x66\x69\
+\x6c\x6c\x3a\x75\x72\x6c\x28\x23\x6c\x69\x6e\x65\x61\x72\x47\x72\
+\x61\x64\x69\x65\x6e\x74\x34\x31\x32\x39\x29\x3b\x66\x69\x6c\x6c\
+\x2d\x6f\x70\x61\x63\x69\x74\x79\x3a\x31\x3b\x66\x69\x6c\x6c\x2d\
+\x72\x75\x6c\x65\x3a\x6e\x6f\x6e\x7a\x65\x72\x6f\x3b\x73\x74\x72\
+\x6f\x6b\x65\x3a\x6e\x6f\x6e\x65\x3b\x73\x74\x72\x6f\x6b\x65\x2d\
+\x77\x69\x64\x74\x68\x3a\x35\x3b\x73\x74\x72\x6f\x6b\x65\x2d\x6c\
+\x69\x6e\x65\x63\x61\x70\x3a\x62\x75\x74\x74\x3b\x73\x74\x72\x6f\
+\x6b\x65\x2d\x6d\x69\x74\x65\x72\x6c\x69\x6d\x69\x74\x3a\x34\x3b\
+\x73\x74\x72\x6f\x6b\x65\x2d\x64\x61\x73\x68\x6f\x66\x66\x73\x65\
+\x74\x3a\x30\x3b\x73\x74\x72\x6f\x6b\x65\x2d\x6f\x70\x61\x63\x69\
+\x74\x79\x3a\x31\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x64\x3d\x22\
+\x4d\x20\x31\x38\x35\x2e\x30\x39\x33\x37\x35\x2c\x31\x38\x30\x2e\
+\x39\x33\x37\x35\x20\x4c\x20\x31\x38\x35\x2e\x30\x39\x33\x37\x35\
+\x2c\x33\x35\x32\x2e\x35\x36\x32\x35\x20\x43\x20\x31\x39\x30\x2e\
+\x39\x33\x37\x35\x32\x2c\x33\x35\x32\x2e\x37\x39\x39\x38\x32\x20\
+\x31\x39\x36\x2e\x38\x33\x38\x35\x36\x2c\x33\x35\x32\x2e\x39\x33\
+\x37\x35\x20\x32\x30\x32\x2e\x37\x38\x31\x32\x35\x2c\x33\x35\x32\
+\x2e\x39\x33\x37\x35\x20\x43\x20\x33\x31\x32\x2e\x38\x30\x30\x31\
+\x34\x2c\x33\x35\x32\x2e\x39\x33\x37\x35\x20\x34\x30\x36\x2e\x39\
+\x35\x30\x34\x39\x2c\x33\x31\x31\x2e\x36\x31\x30\x34\x34\x20\x34\
+\x34\x35\x2e\x30\x36\x32\x35\x2c\x32\x35\x33\x2e\x32\x35\x20\x4c\
+\x20\x34\x34\x35\x2e\x30\x36\x32\x35\x2c\x31\x38\x30\x2e\x39\x33\
+\x37\x35\x20\x4c\x20\x31\x38\x35\x2e\x30\x39\x33\x37\x35\x2c\x31\
+\x38\x30\x2e\x39\x33\x37\x35\x20\x7a\x20\x22\x0a\x20\x20\x20\x20\
+\x20\x20\x20\x69\x64\x3d\x22\x70\x61\x74\x68\x33\x31\x34\x34\x22\
+\x20\x2f\x3e\x0a\x20\x20\x20\x20\x3c\x70\x61\x74\x68\x0a\x20\x20\
+\x20\x20\x20\x20\x20\x73\x6f\x64\x69\x70\x6f\x64\x69\x3a\x74\x79\
+\x70\x65\x3d\x22\x61\x72\x63\x22\x0a\x20\x20\x20\x20\x20\x20\x20\
+\x73\x74\x79\x6c\x65\x3d\x22\x6f\x70\x61\x63\x69\x74\x79\x3a\x31\
+\x3b\x66\x69\x6c\x6c\x3a\x6e\x6f\x6e\x65\x3b\x66\x69\x6c\x6c\x2d\
+\x6f\x70\x61\x63\x69\x74\x79\x3a\x31\x3b\x66\x69\x6c\x6c\x2d\x72\
+\x75\x6c\x65\x3a\x6e\x6f\x6e\x7a\x65\x72\x6f\x3b\x73\x74\x72\x6f\
+\x6b\x65\x3a\x23\x30\x30\x30\x30\x30\x30\x3b\x73\x74\x72\x6f\x6b\
+\x65\x2d\x77\x69\x64\x74\x68\x3a\x35\x3b\x73\x74\x72\x6f\x6b\x65\
+\x2d\x6c\x69\x6e\x65\x63\x61\x70\x3a\x62\x75\x74\x74\x3b\x73\x74\
+\x72\x6f\x6b\x65\x2d\x6d\x69\x74\x65\x72\x6c\x69\x6d\x69\x74\x3a\
+\x34\x3b\x73\x74\x72\x6f\x6b\x65\x2d\x64\x61\x73\x68\x61\x72\x72\
+\x61\x79\x3a\x6e\x6f\x6e\x65\x3b\x73\x74\x72\x6f\x6b\x65\x2d\x64\
+\x61\x73\x68\x6f\x66\x66\x73\x65\x74\x3a\x30\x3b\x73\x74\x72\x6f\
+\x6b\x65\x2d\x6f\x70\x61\x63\x69\x74\x79\x3a\x31\x22\x0a\x20\x20\
+\x20\x20\x20\x20\x20\x69\x64\x3d\x22\x70\x61\x74\x68\x33\x31\x34\
+\x36\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x73\x6f\x64\x69\x70\x6f\
+\x64\x69\x3a\x63\x78\x3d\x22\x33\x30\x33\x2e\x36\x34\x36\x22\x0a\
+\x20\x20\x20\x20\x20\x20\x20\x73\x6f\x64\x69\x70\x6f\x64\x69\x3a\
+\x63\x79\x3d\x22\x31\x32\x39\x2e\x39\x38\x35\x34\x34\x22\x0a\x20\
+\x20\x20\x20\x20\x20\x20\x73\x6f\x64\x69\x70\x6f\x64\x69\x3a\x72\
+\x78\x3d\x22\x30\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x73\x6f\x64\
+\x69\x70\x6f\x64\x69\x3a\x72\x79\x3d\x22\x37\x2e\x32\x37\x39\x31\
+\x38\x35\x33\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x64\x3d\x22\x4d\
+\x20\x33\x30\x33\x2e\x36\x34\x36\x20\x31\x32\x39\x2e\x39\x38\x35\
+\x34\x34\x20\x41\x20\x30\x20\x37\x2e\x32\x37\x39\x31\x38\x35\x33\
+\x20\x30\x20\x31\x20\x31\x20\x20\x33\x30\x33\x2e\x36\x34\x36\x2c\
+\x31\x32\x39\x2e\x39\x38\x35\x34\x34\x20\x41\x20\x30\x20\x37\x2e\
+\x32\x37\x39\x31\x38\x35\x33\x20\x30\x20\x31\x20\x31\x20\x20\x33\
+\x30\x33\x2e\x36\x34\x36\x20\x31\x32\x39\x2e\x39\x38\x35\x34\x34\
+\x20\x7a\x22\x20\x2f\x3e\x0a\x20\x20\x3c\x2f\x67\x3e\x0a\x3c\x2f\
+\x73\x76\x67\x3e\x0a\
+\x00\x00\x10\xa0\
+\x3c\
+\x3f\x78\x6d\x6c\x20\x76\x65\x72\x73\x69\x6f\x6e\x3d\x22\x31\x2e\
+\x30\x22\x20\x65\x6e\x63\x6f\x64\x69\x6e\x67\x3d\x22\x55\x54\x46\
+\x2d\x38\x22\x20\x73\x74\x61\x6e\x64\x61\x6c\x6f\x6e\x65\x3d\x22\
+\x6e\x6f\x22\x3f\x3e\x0a\x3c\x21\x2d\x2d\x20\x43\x72\x65\x61\x74\
+\x65\x64\x20\x77\x69\x74\x68\x20\x49\x6e\x6b\x73\x63\x61\x70\x65\
+\x20\x28\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\x77\x2e\x69\x6e\x6b\
+\x73\x63\x61\x70\x65\x2e\x6f\x72\x67\x2f\x29\x20\x2d\x2d\x3e\x0a\
+\x3c\x73\x76\x67\x0a\x20\x20\x20\x78\x6d\x6c\x6e\x73\x3a\x64\x63\
+\x3d\x22\x68\x74\x74\x70\x3a\x2f\x2f\x70\x75\x72\x6c\x2e\x6f\x72\
+\x67\x2f\x64\x63\x2f\x65\x6c\x65\x6d\x65\x6e\x74\x73\x2f\x31\x2e\
+\x31\x2f\x22\x0a\x20\x20\x20\x78\x6d\x6c\x6e\x73\x3a\x63\x63\x3d\
+\x22\x68\x74\x74\x70\x3a\x2f\x2f\x77\x65\x62\x2e\x72\x65\x73\x6f\
+\x75\x72\x63\x65\x2e\x6f\x72\x67\x2f\x63\x63\x2f\x22\x0a\x20\x20\
+\x20\x78\x6d\x6c\x6e\x73\x3a\x72\x64\x66\x3d\x22\x68\x74\x74\x70\
+\x3a\x2f\x2f\x77\x77\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x31\x39\
+\x39\x39\x2f\x30\x32\x2f\x32\x32\x2d\x72\x64\x66\x2d\x73\x79\x6e\
+\x74\x61\x78\x2d\x6e\x73\x23\x22\x0a\x20\x20\x20\x78\x6d\x6c\x6e\
+\x73\x3a\x73\x76\x67\x3d\x22\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\
+\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x32\x30\x30\x30\x2f\x73\x76\
+\x67\x22\x0a\x20\x20\x20\x78\x6d\x6c\x6e\x73\x3d\x22\x68\x74\x74\
+\x70\x3a\x2f\x2f\x77\x77\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x32\
+\x30\x30\x30\x2f\x73\x76\x67\x22\x0a\x20\x20\x20\x78\x6d\x6c\x6e\
+\x73\x3a\x78\x6c\x69\x6e\x6b\x3d\x22\x68\x74\x74\x70\x3a\x2f\x2f\
+\x77\x77\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x31\x39\x39\x39\x2f\
+\x78\x6c\x69\x6e\x6b\x22\x0a\x20\x20\x20\x78\x6d\x6c\x6e\x73\x3a\
+\x73\x6f\x64\x69\x70\x6f\x64\x69\x3d\x22\x68\x74\x74\x70\x3a\x2f\
+\x2f\x73\x6f\x64\x69\x70\x6f\x64\x69\x2e\x73\x6f\x75\x72\x63\x65\
+\x66\x6f\x72\x67\x65\x2e\x6e\x65\x74\x2f\x44\x54\x44\x2f\x73\x6f\
+\x64\x69\x70\x6f\x64\x69\x2d\x30\x2e\x64\x74\x64\x22\x0a\x20\x20\
+\x20\x78\x6d\x6c\x6e\x73\x3a\x69\x6e\x6b\x73\x63\x61\x70\x65\x3d\
+\x22\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\x77\x2e\x69\x6e\x6b\x73\
+\x63\x61\x70\x65\x2e\x6f\x72\x67\x2f\x6e\x61\x6d\x65\x73\x70\x61\
+\x63\x65\x73\x2f\x69\x6e\x6b\x73\x63\x61\x70\x65\x22\x0a\x20\x20\
+\x20\x77\x69\x64\x74\x68\x3d\x22\x32\x37\x38\x2e\x32\x35\x32\x34\
+\x31\x22\x0a\x20\x20\x20\x68\x65\x69\x67\x68\x74\x3d\x22\x32\x37\
+\x38\x2e\x32\x35\x32\x34\x31\x22\x0a\x20\x20\x20\x69\x64\x3d\x22\
+\x73\x76\x67\x32\x22\x0a\x20\x20\x20\x73\x6f\x64\x69\x70\x6f\x64\
+\x69\x3a\x76\x65\x72\x73\x69\x6f\x6e\x3d\x22\x30\x2e\x33\x32\x22\
+\x0a\x20\x20\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x76\x65\x72\
+\x73\x69\x6f\x6e\x3d\x22\x30\x2e\x34\x35\x2e\x31\x22\x0a\x20\x20\
+\x20\x73\x6f\x64\x69\x70\x6f\x64\x69\x3a\x64\x6f\x63\x62\x61\x73\
+\x65\x3d\x22\x2f\x68\x6f\x6d\x65\x2f\x64\x61\x76\x69\x64\x2f\x45\
+\x6c\x65\x63\x74\x72\x6f\x6e\x69\x63\x2f\x48\x50\x33\x35\x36\x32\
+\x2f\x69\x63\x6f\x6e\x73\x22\x0a\x20\x20\x20\x73\x6f\x64\x69\x70\
+\x6f\x64\x69\x3a\x64\x6f\x63\x6e\x61\x6d\x65\x3d\x22\x6c\x65\x64\
+\x5f\x67\x72\x65\x65\x6e\x5f\x6f\x66\x66\x2e\x73\x76\x67\x22\x0a\
+\x20\x20\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x6f\x75\x74\x70\
+\x75\x74\x5f\x65\x78\x74\x65\x6e\x73\x69\x6f\x6e\x3d\x22\x6f\x72\
+\x67\x2e\x69\x6e\x6b\x73\x63\x61\x70\x65\x2e\x6f\x75\x74\x70\x75\
+\x74\x2e\x73\x76\x67\x2e\x69\x6e\x6b\x73\x63\x61\x70\x65\x22\x0a\
+\x20\x20\x20\x76\x65\x72\x73\x69\x6f\x6e\x3d\x22\x31\x2e\x30\x22\
+\x3e\x0a\x20\x20\x3c\x64\x65\x66\x73\x0a\x20\x20\x20\x20\x20\x69\
+\x64\x3d\x22\x64\x65\x66\x73\x34\x22\x3e\x0a\x20\x20\x20\x20\x3c\
+\x6c\x69\x6e\x65\x61\x72\x47\x72\x61\x64\x69\x65\x6e\x74\x0a\x20\
+\x20\x20\x20\x20\x20\x20\x69\x64\x3d\x22\x6c\x69\x6e\x65\x61\x72\
+\x47\x72\x61\x64\x69\x65\x6e\x74\x34\x31\x31\x37\x22\x3e\x0a\x20\
+\x20\x20\x20\x20\x20\x3c\x73\x74\x6f\x70\x0a\x20\x20\x20\x20\x20\
+\x20\x20\x20\x20\x73\x74\x79\x6c\x65\x3d\x22\x73\x74\x6f\x70\x2d\
+\x63\x6f\x6c\x6f\x72\x3a\x23\x61\x63\x61\x63\x61\x63\x3b\x73\x74\
+\x6f\x70\x2d\x6f\x70\x61\x63\x69\x74\x79\x3a\x30\x2e\x36\x38\x37\
+\x38\x33\x30\x36\x39\x3b\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\
+\x20\x6f\x66\x66\x73\x65\x74\x3d\x22\x30\x22\x0a\x20\x20\x20\x20\
+\x20\x20\x20\x20\x20\x69\x64\x3d\x22\x73\x74\x6f\x70\x34\x31\x31\
+\x39\x22\x20\x2f\x3e\x0a\x20\x20\x20\x20\x20\x20\x3c\x73\x74\x6f\
+\x70\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x73\x74\x79\x6c\x65\
+\x3d\x22\x73\x74\x6f\x70\x2d\x63\x6f\x6c\x6f\x72\x3a\x23\x66\x66\
+\x66\x66\x66\x66\x3b\x73\x74\x6f\x70\x2d\x6f\x70\x61\x63\x69\x74\
+\x79\x3a\x30\x3b\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x6f\
+\x66\x66\x73\x65\x74\x3d\x22\x31\x22\x0a\x20\x20\x20\x20\x20\x20\
+\x20\x20\x20\x69\x64\x3d\x22\x73\x74\x6f\x70\x34\x31\x32\x31\x22\
+\x20\x2f\x3e\x0a\x20\x20\x20\x20\x3c\x2f\x6c\x69\x6e\x65\x61\x72\
+\x47\x72\x61\x64\x69\x65\x6e\x74\x3e\x0a\x20\x20\x20\x20\x3c\x6c\
+\x69\x6e\x65\x61\x72\x47\x72\x61\x64\x69\x65\x6e\x74\x0a\x20\x20\
+\x20\x20\x20\x20\x20\x69\x64\x3d\x22\x6c\x69\x6e\x65\x61\x72\x47\
+\x72\x61\x64\x69\x65\x6e\x74\x33\x31\x33\x36\x22\x3e\x0a\x20\x20\
+\x20\x20\x20\x20\x3c\x73\x74\x6f\x70\x0a\x20\x20\x20\x20\x20\x20\
+\x20\x20\x20\x73\x74\x79\x6c\x65\x3d\x22\x73\x74\x6f\x70\x2d\x63\
+\x6f\x6c\x6f\x72\x3a\x23\x66\x66\x66\x66\x66\x66\x3b\x73\x74\x6f\
+\x70\x2d\x6f\x70\x61\x63\x69\x74\x79\x3a\x31\x3b\x22\x0a\x20\x20\
+\x20\x20\x20\x20\x20\x20\x20\x6f\x66\x66\x73\x65\x74\x3d\x22\x30\
+\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x69\x64\x3d\x22\x73\
+\x74\x6f\x70\x33\x31\x33\x38\x22\x20\x2f\x3e\x0a\x20\x20\x20\x20\
+\x20\x20\x3c\x73\x74\x6f\x70\x0a\x20\x20\x20\x20\x20\x20\x20\x20\
+\x20\x73\x74\x79\x6c\x65\x3d\x22\x73\x74\x6f\x70\x2d\x63\x6f\x6c\
+\x6f\x72\x3a\x23\x30\x30\x66\x66\x30\x30\x3b\x73\x74\x6f\x70\x2d\
+\x6f\x70\x61\x63\x69\x74\x79\x3a\x30\x3b\x22\x0a\x20\x20\x20\x20\
+\x20\x20\x20\x20\x20\x6f\x66\x66\x73\x65\x74\x3d\x22\x31\x22\x0a\
+\x20\x20\x20\x20\x20\x20\x20\x20\x20\x69\x64\x3d\x22\x73\x74\x6f\
+\x70\x33\x31\x34\x30\x22\x20\x2f\x3e\x0a\x20\x20\x20\x20\x3c\x2f\
+\x6c\x69\x6e\x65\x61\x72\x47\x72\x61\x64\x69\x65\x6e\x74\x3e\x0a\
+\x20\x20\x20\x20\x3c\x6c\x69\x6e\x65\x61\x72\x47\x72\x61\x64\x69\
+\x65\x6e\x74\x0a\x20\x20\x20\x20\x20\x20\x20\x69\x6e\x6b\x73\x63\
+\x61\x70\x65\x3a\x63\x6f\x6c\x6c\x65\x63\x74\x3d\x22\x61\x6c\x77\
+\x61\x79\x73\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x78\x6c\x69\x6e\
+\x6b\x3a\x68\x72\x65\x66\x3d\x22\x23\x6c\x69\x6e\x65\x61\x72\x47\
+\x72\x61\x64\x69\x65\x6e\x74\x34\x31\x31\x37\x22\x0a\x20\x20\x20\
+\x20\x20\x20\x20\x69\x64\x3d\x22\x6c\x69\x6e\x65\x61\x72\x47\x72\
+\x61\x64\x69\x65\x6e\x74\x34\x31\x32\x39\x22\x0a\x20\x20\x20\x20\
+\x20\x20\x20\x67\x72\x61\x64\x69\x65\x6e\x74\x55\x6e\x69\x74\x73\
+\x3d\x22\x75\x73\x65\x72\x53\x70\x61\x63\x65\x4f\x6e\x55\x73\x65\
+\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x78\x31\x3d\x22\x32\x36\x30\
+\x2e\x39\x35\x32\x34\x32\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x79\
+\x31\x3d\x22\x31\x32\x31\x2e\x31\x38\x38\x34\x32\x22\x0a\x20\x20\
+\x20\x20\x20\x20\x20\x78\x32\x3d\x22\x34\x38\x38\x2e\x36\x35\x39\
+\x35\x35\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x79\x32\x3d\x22\x33\
+\x35\x31\x2e\x34\x38\x30\x36\x35\x22\x0a\x20\x20\x20\x20\x20\x20\
+\x20\x67\x72\x61\x64\x69\x65\x6e\x74\x54\x72\x61\x6e\x73\x66\x6f\
+\x72\x6d\x3d\x22\x6d\x61\x74\x72\x69\x78\x28\x31\x2e\x32\x34\x35\
+\x37\x32\x32\x36\x2c\x30\x2c\x30\x2c\x31\x2e\x32\x36\x31\x35\x38\
+\x35\x34\x2c\x2d\x31\x37\x36\x2e\x37\x37\x36\x38\x2c\x2d\x39\x30\
+\x2e\x34\x39\x36\x35\x30\x38\x29\x22\x20\x2f\x3e\x0a\x20\x20\x3c\
+\x2f\x64\x65\x66\x73\x3e\x0a\x20\x20\x3c\x73\x6f\x64\x69\x70\x6f\
+\x64\x69\x3a\x6e\x61\x6d\x65\x64\x76\x69\x65\x77\x0a\x20\x20\x20\
+\x20\x20\x69\x64\x3d\x22\x62\x61\x73\x65\x22\x0a\x20\x20\x20\x20\
+\x20\x70\x61\x67\x65\x63\x6f\x6c\x6f\x72\x3d\x22\x23\x66\x66\x66\
+\x66\x66\x66\x22\x0a\x20\x20\x20\x20\x20\x62\x6f\x72\x64\x65\x72\
+\x63\x6f\x6c\x6f\x72\x3d\x22\x23\x36\x36\x36\x36\x36\x36\x22\x0a\
+\x20\x20\x20\x20\x20\x62\x6f\x72\x64\x65\x72\x6f\x70\x61\x63\x69\
+\x74\x79\x3d\x22\x31\x2e\x30\x22\x0a\x20\x20\x20\x20\x20\x69\x6e\
+\x6b\x73\x63\x61\x70\x65\x3a\x70\x61\x67\x65\x6f\x70\x61\x63\x69\
+\x74\x79\x3d\x22\x30\x2e\x30\x22\x0a\x20\x20\x20\x20\x20\x69\x6e\
+\x6b\x73\x63\x61\x70\x65\x3a\x70\x61\x67\x65\x73\x68\x61\x64\x6f\
+\x77\x3d\x22\x32\x22\x0a\x20\x20\x20\x20\x20\x69\x6e\x6b\x73\x63\
+\x61\x70\x65\x3a\x7a\x6f\x6f\x6d\x3d\x22\x30\x2e\x34\x38\x30\x38\
+\x32\x33\x30\x36\x22\x0a\x20\x20\x20\x20\x20\x69\x6e\x6b\x73\x63\
+\x61\x70\x65\x3a\x63\x78\x3d\x22\x33\x37\x32\x2e\x30\x34\x37\x32\
+\x34\x22\x0a\x20\x20\x20\x20\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\
+\x3a\x63\x79\x3d\x22\x2d\x36\x34\x2e\x37\x39\x33\x36\x39\x36\x22\
+\x0a\x20\x20\x20\x20\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x64\
+\x6f\x63\x75\x6d\x65\x6e\x74\x2d\x75\x6e\x69\x74\x73\x3d\x22\x70\
+\x78\x22\x0a\x20\x20\x20\x20\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\
+\x3a\x63\x75\x72\x72\x65\x6e\x74\x2d\x6c\x61\x79\x65\x72\x3d\x22\
+\x6c\x61\x79\x65\x72\x31\x22\x0a\x20\x20\x20\x20\x20\x69\x6e\x6b\
+\x73\x63\x61\x70\x65\x3a\x77\x69\x6e\x64\x6f\x77\x2d\x77\x69\x64\
+\x74\x68\x3d\x22\x39\x39\x36\x22\x0a\x20\x20\x20\x20\x20\x69\x6e\
+\x6b\x73\x63\x61\x70\x65\x3a\x77\x69\x6e\x64\x6f\x77\x2d\x68\x65\
+\x69\x67\x68\x74\x3d\x22\x37\x31\x34\x22\x0a\x20\x20\x20\x20\x20\
+\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x77\x69\x6e\x64\x6f\x77\x2d\
+\x78\x3d\x22\x32\x32\x22\x0a\x20\x20\x20\x20\x20\x69\x6e\x6b\x73\
+\x63\x61\x70\x65\x3a\x77\x69\x6e\x64\x6f\x77\x2d\x79\x3d\x22\x32\
+\x31\x22\x20\x2f\x3e\x0a\x20\x20\x3c\x6d\x65\x74\x61\x64\x61\x74\
+\x61\x0a\x20\x20\x20\x20\x20\x69\x64\x3d\x22\x6d\x65\x74\x61\x64\
+\x61\x74\x61\x37\x22\x3e\x0a\x20\x20\x20\x20\x3c\x72\x64\x66\x3a\
+\x52\x44\x46\x3e\x0a\x20\x20\x20\x20\x20\x20\x3c\x63\x63\x3a\x57\
+\x6f\x72\x6b\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x72\x64\x66\
+\x3a\x61\x62\x6f\x75\x74\x3d\x22\x22\x3e\x0a\x20\x20\x20\x20\x20\
+\x20\x20\x20\x3c\x64\x63\x3a\x66\x6f\x72\x6d\x61\x74\x3e\x69\x6d\
+\x61\x67\x65\x2f\x73\x76\x67\x2b\x78\x6d\x6c\x3c\x2f\x64\x63\x3a\
+\x66\x6f\x72\x6d\x61\x74\x3e\x0a\x20\x20\x20\x20\x20\x20\x20\x20\
+\x3c\x64\x63\x3a\x74\x79\x70\x65\x0a\x20\x20\x20\x20\x20\x20\x20\
+\x20\x20\x20\x20\x72\x64\x66\x3a\x72\x65\x73\x6f\x75\x72\x63\x65\
+\x3d\x22\x68\x74\x74\x70\x3a\x2f\x2f\x70\x75\x72\x6c\x2e\x6f\x72\
+\x67\x2f\x64\x63\x2f\x64\x63\x6d\x69\x74\x79\x70\x65\x2f\x53\x74\
+\x69\x6c\x6c\x49\x6d\x61\x67\x65\x22\x20\x2f\x3e\x0a\x20\x20\x20\
+\x20\x20\x20\x3c\x2f\x63\x63\x3a\x57\x6f\x72\x6b\x3e\x0a\x20\x20\
+\x20\x20\x3c\x2f\x72\x64\x66\x3a\x52\x44\x46\x3e\x0a\x20\x20\x3c\
+\x2f\x6d\x65\x74\x61\x64\x61\x74\x61\x3e\x0a\x20\x20\x3c\x67\x0a\
+\x20\x20\x20\x20\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x6c\x61\
+\x62\x65\x6c\x3d\x22\x43\x61\x6c\x71\x75\x65\x20\x31\x22\x0a\x20\
+\x20\x20\x20\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x67\x72\x6f\
+\x75\x70\x6d\x6f\x64\x65\x3d\x22\x6c\x61\x79\x65\x72\x22\x0a\x20\
+\x20\x20\x20\x20\x69\x64\x3d\x22\x6c\x61\x79\x65\x72\x31\x22\x0a\
+\x20\x20\x20\x20\x20\x74\x72\x61\x6e\x73\x66\x6f\x72\x6d\x3d\x22\
+\x74\x72\x61\x6e\x73\x6c\x61\x74\x65\x28\x2d\x31\x37\x35\x2e\x39\
+\x35\x38\x35\x32\x2c\x2d\x31\x37\x31\x2e\x37\x39\x38\x39\x39\x29\
+\x22\x3e\x0a\x20\x20\x20\x20\x3c\x72\x65\x63\x74\x0a\x20\x20\x20\
+\x20\x20\x20\x20\x73\x74\x79\x6c\x65\x3d\x22\x6f\x70\x61\x63\x69\
+\x74\x79\x3a\x31\x3b\x66\x69\x6c\x6c\x3a\x23\x30\x30\x39\x39\x30\
+\x30\x3b\x66\x69\x6c\x6c\x2d\x6f\x70\x61\x63\x69\x74\x79\x3a\x31\
+\x3b\x66\x69\x6c\x6c\x2d\x72\x75\x6c\x65\x3a\x6e\x6f\x6e\x7a\x65\
+\x72\x6f\x3b\x73\x74\x72\x6f\x6b\x65\x3a\x23\x66\x66\x66\x66\x66\
+\x66\x3b\x73\x74\x72\x6f\x6b\x65\x2d\x77\x69\x64\x74\x68\x3a\x30\
+\x2e\x32\x39\x33\x39\x30\x36\x36\x36\x3b\x73\x74\x72\x6f\x6b\x65\
+\x2d\x6c\x69\x6e\x65\x63\x61\x70\x3a\x62\x75\x74\x74\x3b\x73\x74\
+\x72\x6f\x6b\x65\x2d\x6d\x69\x74\x65\x72\x6c\x69\x6d\x69\x74\x3a\
+\x34\x3b\x73\x74\x72\x6f\x6b\x65\x2d\x64\x61\x73\x68\x61\x72\x72\
+\x61\x79\x3a\x30\x2e\x32\x39\x33\x39\x30\x36\x36\x36\x2c\x20\x30\
+\x2e\x32\x39\x33\x39\x30\x36\x36\x36\x3b\x73\x74\x72\x6f\x6b\x65\
+\x2d\x64\x61\x73\x68\x6f\x66\x66\x73\x65\x74\x3a\x30\x3b\x73\x74\
+\x72\x6f\x6b\x65\x2d\x6f\x70\x61\x63\x69\x74\x79\x3a\x31\x22\x0a\
+\x20\x20\x20\x20\x20\x20\x20\x69\x64\x3d\x22\x72\x65\x63\x74\x32\
+\x31\x36\x30\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x77\x69\x64\x74\
+\x68\x3d\x22\x32\x35\x39\x2e\x39\x37\x30\x38\x39\x22\x0a\x20\x20\
+\x20\x20\x20\x20\x20\x68\x65\x69\x67\x68\x74\x3d\x22\x32\x35\x39\
+\x2e\x39\x37\x30\x38\x39\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x78\
+\x3d\x22\x31\x38\x35\x2e\x30\x39\x39\x32\x37\x22\x0a\x20\x20\x20\
+\x20\x20\x20\x20\x79\x3d\x22\x31\x38\x30\x2e\x39\x33\x39\x37\x34\
+\x22\x20\x2f\x3e\x0a\x20\x20\x20\x20\x3c\x72\x65\x63\x74\x0a\x20\
+\x20\x20\x20\x20\x20\x20\x79\x3d\x22\x31\x37\x36\x2e\x33\x38\x37\
+\x34\x34\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x78\x3d\x22\x31\x38\
+\x30\x2e\x35\x34\x36\x39\x37\x22\x0a\x20\x20\x20\x20\x20\x20\x20\
+\x68\x65\x69\x67\x68\x74\x3d\x22\x32\x36\x39\x2e\x30\x37\x35\x35\
+\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x77\x69\x64\x74\x68\x3d\x22\
+\x32\x36\x39\x2e\x30\x37\x35\x35\x22\x0a\x20\x20\x20\x20\x20\x20\
+\x20\x69\x64\x3d\x22\x72\x65\x63\x74\x32\x31\x36\x32\x22\x0a\x20\
+\x20\x20\x20\x20\x20\x20\x73\x74\x79\x6c\x65\x3d\x22\x6f\x70\x61\
+\x63\x69\x74\x79\x3a\x31\x3b\x66\x69\x6c\x6c\x3a\x6e\x6f\x6e\x65\
+\x3b\x66\x69\x6c\x6c\x2d\x6f\x70\x61\x63\x69\x74\x79\x3a\x31\x3b\
+\x66\x69\x6c\x6c\x2d\x72\x75\x6c\x65\x3a\x6e\x6f\x6e\x7a\x65\x72\
+\x6f\x3b\x73\x74\x72\x6f\x6b\x65\x3a\x23\x30\x30\x38\x33\x30\x34\
+\x3b\x73\x74\x72\x6f\x6b\x65\x2d\x77\x69\x64\x74\x68\x3a\x39\x2e\
+\x31\x37\x36\x38\x39\x38\x39\x36\x3b\x73\x74\x72\x6f\x6b\x65\x2d\
+\x6c\x69\x6e\x65\x63\x61\x70\x3a\x62\x75\x74\x74\x3b\x73\x74\x72\
+\x6f\x6b\x65\x2d\x6d\x69\x74\x65\x72\x6c\x69\x6d\x69\x74\x3a\x34\
+\x3b\x73\x74\x72\x6f\x6b\x65\x2d\x64\x61\x73\x68\x61\x72\x72\x61\
+\x79\x3a\x6e\x6f\x6e\x65\x3b\x73\x74\x72\x6f\x6b\x65\x2d\x64\x61\
+\x73\x68\x6f\x66\x66\x73\x65\x74\x3a\x30\x3b\x73\x74\x72\x6f\x6b\
+\x65\x2d\x6f\x70\x61\x63\x69\x74\x79\x3a\x31\x22\x20\x2f\x3e\x0a\
+\x20\x20\x20\x20\x3c\x70\x61\x74\x68\x0a\x20\x20\x20\x20\x20\x20\
+\x20\x73\x74\x79\x6c\x65\x3d\x22\x66\x69\x6c\x6c\x3a\x75\x72\x6c\
+\x28\x23\x6c\x69\x6e\x65\x61\x72\x47\x72\x61\x64\x69\x65\x6e\x74\
+\x34\x31\x32\x39\x29\x3b\x66\x69\x6c\x6c\x2d\x6f\x70\x61\x63\x69\
+\x74\x79\x3a\x31\x3b\x66\x69\x6c\x6c\x2d\x72\x75\x6c\x65\x3a\x6e\
+\x6f\x6e\x7a\x65\x72\x6f\x3b\x73\x74\x72\x6f\x6b\x65\x3a\x6e\x6f\
+\x6e\x65\x3b\x73\x74\x72\x6f\x6b\x65\x2d\x77\x69\x64\x74\x68\x3a\
+\x35\x3b\x73\x74\x72\x6f\x6b\x65\x2d\x6c\x69\x6e\x65\x63\x61\x70\
+\x3a\x62\x75\x74\x74\x3b\x73\x74\x72\x6f\x6b\x65\x2d\x6d\x69\x74\
+\x65\x72\x6c\x69\x6d\x69\x74\x3a\x34\x3b\x73\x74\x72\x6f\x6b\x65\
+\x2d\x64\x61\x73\x68\x6f\x66\x66\x73\x65\x74\x3a\x30\x3b\x73\x74\
+\x72\x6f\x6b\x65\x2d\x6f\x70\x61\x63\x69\x74\x79\x3a\x31\x22\x0a\
+\x20\x20\x20\x20\x20\x20\x20\x64\x3d\x22\x4d\x20\x31\x38\x35\x2e\
+\x30\x39\x33\x37\x35\x2c\x31\x38\x30\x2e\x39\x33\x37\x35\x20\x4c\
+\x20\x31\x38\x35\x2e\x30\x39\x33\x37\x35\x2c\x33\x35\x32\x2e\x35\
+\x36\x32\x35\x20\x43\x20\x31\x39\x30\x2e\x39\x33\x37\x35\x32\x2c\
+\x33\x35\x32\x2e\x37\x39\x39\x38\x32\x20\x31\x39\x36\x2e\x38\x33\
+\x38\x35\x36\x2c\x33\x35\x32\x2e\x39\x33\x37\x35\x20\x32\x30\x32\
+\x2e\x37\x38\x31\x32\x35\x2c\x33\x35\x32\x2e\x39\x33\x37\x35\x20\
+\x43\x20\x33\x31\x32\x2e\x38\x30\x30\x31\x34\x2c\x33\x35\x32\x2e\
+\x39\x33\x37\x35\x20\x34\x30\x36\x2e\x39\x35\x30\x34\x39\x2c\x33\
+\x31\x31\x2e\x36\x31\x30\x34\x34\x20\x34\x34\x35\x2e\x30\x36\x32\
+\x35\x2c\x32\x35\x33\x2e\x32\x35\x20\x4c\x20\x34\x34\x35\x2e\x30\
+\x36\x32\x35\x2c\x31\x38\x30\x2e\x39\x33\x37\x35\x20\x4c\x20\x31\
+\x38\x35\x2e\x30\x39\x33\x37\x35\x2c\x31\x38\x30\x2e\x39\x33\x37\
+\x35\x20\x7a\x20\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x69\x64\x3d\
+\x22\x70\x61\x74\x68\x33\x31\x34\x34\x22\x20\x2f\x3e\x0a\x20\x20\
+\x20\x20\x3c\x70\x61\x74\x68\x0a\x20\x20\x20\x20\x20\x20\x20\x73\
+\x6f\x64\x69\x70\x6f\x64\x69\x3a\x74\x79\x70\x65\x3d\x22\x61\x72\
+\x63\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x73\x74\x79\x6c\x65\x3d\
+\x22\x6f\x70\x61\x63\x69\x74\x79\x3a\x31\x3b\x66\x69\x6c\x6c\x3a\
+\x6e\x6f\x6e\x65\x3b\x66\x69\x6c\x6c\x2d\x6f\x70\x61\x63\x69\x74\
+\x79\x3a\x31\x3b\x66\x69\x6c\x6c\x2d\x72\x75\x6c\x65\x3a\x6e\x6f\
+\x6e\x7a\x65\x72\x6f\x3b\x73\x74\x72\x6f\x6b\x65\x3a\x23\x30\x30\
+\x30\x30\x30\x30\x3b\x73\x74\x72\x6f\x6b\x65\x2d\x77\x69\x64\x74\
+\x68\x3a\x35\x3b\x73\x74\x72\x6f\x6b\x65\x2d\x6c\x69\x6e\x65\x63\
+\x61\x70\x3a\x62\x75\x74\x74\x3b\x73\x74\x72\x6f\x6b\x65\x2d\x6d\
+\x69\x74\x65\x72\x6c\x69\x6d\x69\x74\x3a\x34\x3b\x73\x74\x72\x6f\
+\x6b\x65\x2d\x64\x61\x73\x68\x61\x72\x72\x61\x79\x3a\x6e\x6f\x6e\
+\x65\x3b\x73\x74\x72\x6f\x6b\x65\x2d\x64\x61\x73\x68\x6f\x66\x66\
+\x73\x65\x74\x3a\x30\x3b\x73\x74\x72\x6f\x6b\x65\x2d\x6f\x70\x61\
+\x63\x69\x74\x79\x3a\x31\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x69\
+\x64\x3d\x22\x70\x61\x74\x68\x33\x31\x34\x36\x22\x0a\x20\x20\x20\
+\x20\x20\x20\x20\x73\x6f\x64\x69\x70\x6f\x64\x69\x3a\x63\x78\x3d\
+\x22\x33\x30\x33\x2e\x36\x34\x36\x22\x0a\x20\x20\x20\x20\x20\x20\
+\x20\x73\x6f\x64\x69\x70\x6f\x64\x69\x3a\x63\x79\x3d\x22\x31\x32\
+\x39\x2e\x39\x38\x35\x34\x34\x22\x0a\x20\x20\x20\x20\x20\x20\x20\
+\x73\x6f\x64\x69\x70\x6f\x64\x69\x3a\x72\x78\x3d\x22\x30\x22\x0a\
+\x20\x20\x20\x20\x20\x20\x20\x73\x6f\x64\x69\x70\x6f\x64\x69\x3a\
+\x72\x79\x3d\x22\x37\x2e\x32\x37\x39\x31\x38\x35\x33\x22\x0a\x20\
+\x20\x20\x20\x20\x20\x20\x64\x3d\x22\x4d\x20\x33\x30\x33\x2e\x36\
+\x34\x36\x20\x31\x32\x39\x2e\x39\x38\x35\x34\x34\x20\x41\x20\x30\
+\x20\x37\x2e\x32\x37\x39\x31\x38\x35\x33\x20\x30\x20\x31\x20\x31\
+\x20\x20\x33\x30\x33\x2e\x36\x34\x36\x2c\x31\x32\x39\x2e\x39\x38\
+\x35\x34\x34\x20\x41\x20\x30\x20\x37\x2e\x32\x37\x39\x31\x38\x35\
+\x33\x20\x30\x20\x31\x20\x31\x20\x20\x33\x30\x33\x2e\x36\x34\x36\
+\x20\x31\x32\x39\x2e\x39\x38\x35\x34\x34\x20\x7a\x22\x20\x2f\x3e\
+\x0a\x20\x20\x3c\x2f\x67\x3e\x0a\x3c\x2f\x73\x76\x67\x3e\x0a\
+\x00\x00\x14\x96\
+\x3c\
+\x3f\x78\x6d\x6c\x20\x76\x65\x72\x73\x69\x6f\x6e\x3d\x22\x31\x2e\
+\x30\x22\x20\x65\x6e\x63\x6f\x64\x69\x6e\x67\x3d\x22\x55\x54\x46\
+\x2d\x38\x22\x20\x73\x74\x61\x6e\x64\x61\x6c\x6f\x6e\x65\x3d\x22\
+\x6e\x6f\x22\x3f\x3e\x0a\x3c\x21\x2d\x2d\x20\x43\x72\x65\x61\x74\
+\x65\x64\x20\x77\x69\x74\x68\x20\x49\x6e\x6b\x73\x63\x61\x70\x65\
+\x20\x28\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\x77\x2e\x69\x6e\x6b\
+\x73\x63\x61\x70\x65\x2e\x6f\x72\x67\x2f\x29\x20\x2d\x2d\x3e\x0a\
+\x3c\x73\x76\x67\x0a\x20\x20\x20\x78\x6d\x6c\x6e\x73\x3a\x64\x63\
+\x3d\x22\x68\x74\x74\x70\x3a\x2f\x2f\x70\x75\x72\x6c\x2e\x6f\x72\
+\x67\x2f\x64\x63\x2f\x65\x6c\x65\x6d\x65\x6e\x74\x73\x2f\x31\x2e\
+\x31\x2f\x22\x0a\x20\x20\x20\x78\x6d\x6c\x6e\x73\x3a\x63\x63\x3d\
+\x22\x68\x74\x74\x70\x3a\x2f\x2f\x77\x65\x62\x2e\x72\x65\x73\x6f\
+\x75\x72\x63\x65\x2e\x6f\x72\x67\x2f\x63\x63\x2f\x22\x0a\x20\x20\
+\x20\x78\x6d\x6c\x6e\x73\x3a\x72\x64\x66\x3d\x22\x68\x74\x74\x70\
+\x3a\x2f\x2f\x77\x77\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x31\x39\
+\x39\x39\x2f\x30\x32\x2f\x32\x32\x2d\x72\x64\x66\x2d\x73\x79\x6e\
+\x74\x61\x78\x2d\x6e\x73\x23\x22\x0a\x20\x20\x20\x78\x6d\x6c\x6e\
+\x73\x3a\x73\x76\x67\x3d\x22\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\
+\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x32\x30\x30\x30\x2f\x73\x76\
+\x67\x22\x0a\x20\x20\x20\x78\x6d\x6c\x6e\x73\x3d\x22\x68\x74\x74\
+\x70\x3a\x2f\x2f\x77\x77\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x32\
+\x30\x30\x30\x2f\x73\x76\x67\x22\x0a\x20\x20\x20\x78\x6d\x6c\x6e\
+\x73\x3a\x78\x6c\x69\x6e\x6b\x3d\x22\x68\x74\x74\x70\x3a\x2f\x2f\
+\x77\x77\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x31\x39\x39\x39\x2f\
+\x78\x6c\x69\x6e\x6b\x22\x0a\x20\x20\x20\x78\x6d\x6c\x6e\x73\x3a\
+\x73\x6f\x64\x69\x70\x6f\x64\x69\x3d\x22\x68\x74\x74\x70\x3a\x2f\
+\x2f\x73\x6f\x64\x69\x70\x6f\x64\x69\x2e\x73\x6f\x75\x72\x63\x65\
+\x66\x6f\x72\x67\x65\x2e\x6e\x65\x74\x2f\x44\x54\x44\x2f\x73\x6f\
+\x64\x69\x70\x6f\x64\x69\x2d\x30\x2e\x64\x74\x64\x22\x0a\x20\x20\
+\x20\x78\x6d\x6c\x6e\x73\x3a\x69\x6e\x6b\x73\x63\x61\x70\x65\x3d\
+\x22\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\x77\x2e\x69\x6e\x6b\x73\
+\x63\x61\x70\x65\x2e\x6f\x72\x67\x2f\x6e\x61\x6d\x65\x73\x70\x61\
+\x63\x65\x73\x2f\x69\x6e\x6b\x73\x63\x61\x70\x65\x22\x0a\x20\x20\
+\x20\x77\x69\x64\x74\x68\x3d\x22\x32\x37\x38\x2e\x32\x35\x32\x34\
+\x31\x22\x0a\x20\x20\x20\x68\x65\x69\x67\x68\x74\x3d\x22\x32\x37\
+\x38\x2e\x32\x35\x32\x34\x31\x22\x0a\x20\x20\x20\x69\x64\x3d\x22\
+\x73\x76\x67\x32\x22\x0a\x20\x20\x20\x73\x6f\x64\x69\x70\x6f\x64\
+\x69\x3a\x76\x65\x72\x73\x69\x6f\x6e\x3d\x22\x30\x2e\x33\x32\x22\
+\x0a\x20\x20\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x76\x65\x72\
+\x73\x69\x6f\x6e\x3d\x22\x30\x2e\x34\x35\x2e\x31\x22\x0a\x20\x20\
+\x20\x73\x6f\x64\x69\x70\x6f\x64\x69\x3a\x64\x6f\x63\x62\x61\x73\
+\x65\x3d\x22\x2f\x68\x6f\x6d\x65\x2f\x64\x61\x76\x69\x64\x2f\x45\
+\x6c\x65\x63\x74\x72\x6f\x6e\x69\x63\x2f\x48\x50\x33\x35\x36\x32\
+\x2f\x69\x63\x6f\x6e\x73\x22\x0a\x20\x20\x20\x73\x6f\x64\x69\x70\
+\x6f\x64\x69\x3a\x64\x6f\x63\x6e\x61\x6d\x65\x3d\x22\x6c\x65\x64\
+\x5f\x72\x65\x64\x2e\x73\x76\x67\x22\x0a\x20\x20\x20\x69\x6e\x6b\
+\x73\x63\x61\x70\x65\x3a\x6f\x75\x74\x70\x75\x74\x5f\x65\x78\x74\
+\x65\x6e\x73\x69\x6f\x6e\x3d\x22\x6f\x72\x67\x2e\x69\x6e\x6b\x73\
+\x63\x61\x70\x65\x2e\x6f\x75\x74\x70\x75\x74\x2e\x73\x76\x67\x2e\
+\x69\x6e\x6b\x73\x63\x61\x70\x65\x22\x0a\x20\x20\x20\x76\x65\x72\
+\x73\x69\x6f\x6e\x3d\x22\x31\x2e\x30\x22\x3e\x0a\x20\x20\x3c\x64\
+\x65\x66\x73\x0a\x20\x20\x20\x20\x20\x69\x64\x3d\x22\x64\x65\x66\
+\x73\x34\x22\x3e\x0a\x20\x20\x20\x20\x3c\x6c\x69\x6e\x65\x61\x72\
+\x47\x72\x61\x64\x69\x65\x6e\x74\x0a\x20\x20\x20\x20\x20\x20\x20\
+\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x63\x6f\x6c\x6c\x65\x63\x74\
+\x3d\x22\x61\x6c\x77\x61\x79\x73\x22\x0a\x20\x20\x20\x20\x20\x20\
+\x20\x69\x64\x3d\x22\x6c\x69\x6e\x65\x61\x72\x47\x72\x61\x64\x69\
+\x65\x6e\x74\x34\x31\x31\x37\x22\x3e\x0a\x20\x20\x20\x20\x20\x20\
+\x3c\x73\x74\x6f\x70\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x73\
+\x74\x79\x6c\x65\x3d\x22\x73\x74\x6f\x70\x2d\x63\x6f\x6c\x6f\x72\
+\x3a\x23\x66\x66\x66\x66\x66\x66\x3b\x73\x74\x6f\x70\x2d\x6f\x70\
+\x61\x63\x69\x74\x79\x3a\x31\x3b\x22\x0a\x20\x20\x20\x20\x20\x20\
+\x20\x20\x20\x6f\x66\x66\x73\x65\x74\x3d\x22\x30\x22\x0a\x20\x20\
+\x20\x20\x20\x20\x20\x20\x20\x69\x64\x3d\x22\x73\x74\x6f\x70\x34\
+\x31\x31\x39\x22\x20\x2f\x3e\x0a\x20\x20\x20\x20\x20\x20\x3c\x73\
+\x74\x6f\x70\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x73\x74\x79\
+\x6c\x65\x3d\x22\x73\x74\x6f\x70\x2d\x63\x6f\x6c\x6f\x72\x3a\x23\
+\x66\x66\x66\x66\x66\x66\x3b\x73\x74\x6f\x70\x2d\x6f\x70\x61\x63\
+\x69\x74\x79\x3a\x30\x3b\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\
+\x20\x6f\x66\x66\x73\x65\x74\x3d\x22\x31\x22\x0a\x20\x20\x20\x20\
+\x20\x20\x20\x20\x20\x69\x64\x3d\x22\x73\x74\x6f\x70\x34\x31\x32\
+\x31\x22\x20\x2f\x3e\x0a\x20\x20\x20\x20\x3c\x2f\x6c\x69\x6e\x65\
+\x61\x72\x47\x72\x61\x64\x69\x65\x6e\x74\x3e\x0a\x20\x20\x20\x20\
+\x3c\x6c\x69\x6e\x65\x61\x72\x47\x72\x61\x64\x69\x65\x6e\x74\x0a\
+\x20\x20\x20\x20\x20\x20\x20\x69\x64\x3d\x22\x6c\x69\x6e\x65\x61\
+\x72\x47\x72\x61\x64\x69\x65\x6e\x74\x33\x31\x33\x36\x22\x3e\x0a\
+\x20\x20\x20\x20\x20\x20\x3c\x73\x74\x6f\x70\x0a\x20\x20\x20\x20\
+\x20\x20\x20\x20\x20\x73\x74\x79\x6c\x65\x3d\x22\x73\x74\x6f\x70\
+\x2d\x63\x6f\x6c\x6f\x72\x3a\x23\x66\x66\x66\x66\x66\x66\x3b\x73\
+\x74\x6f\x70\x2d\x6f\x70\x61\x63\x69\x74\x79\x3a\x31\x3b\x22\x0a\
+\x20\x20\x20\x20\x20\x20\x20\x20\x20\x6f\x66\x66\x73\x65\x74\x3d\
+\x22\x30\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x69\x64\x3d\
+\x22\x73\x74\x6f\x70\x33\x31\x33\x38\x22\x20\x2f\x3e\x0a\x20\x20\
+\x20\x20\x20\x20\x3c\x73\x74\x6f\x70\x0a\x20\x20\x20\x20\x20\x20\
+\x20\x20\x20\x73\x74\x79\x6c\x65\x3d\x22\x73\x74\x6f\x70\x2d\x63\
+\x6f\x6c\x6f\x72\x3a\x23\x66\x66\x30\x30\x30\x30\x3b\x73\x74\x6f\
+\x70\x2d\x6f\x70\x61\x63\x69\x74\x79\x3a\x30\x3b\x22\x0a\x20\x20\
+\x20\x20\x20\x20\x20\x20\x20\x6f\x66\x66\x73\x65\x74\x3d\x22\x31\
+\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x69\x64\x3d\x22\x73\
+\x74\x6f\x70\x33\x31\x34\x30\x22\x20\x2f\x3e\x0a\x20\x20\x20\x20\
+\x3c\x2f\x6c\x69\x6e\x65\x61\x72\x47\x72\x61\x64\x69\x65\x6e\x74\
+\x3e\x0a\x20\x20\x20\x20\x3c\x72\x61\x64\x69\x61\x6c\x47\x72\x61\
+\x64\x69\x65\x6e\x74\x0a\x20\x20\x20\x20\x20\x20\x20\x69\x6e\x6b\
+\x73\x63\x61\x70\x65\x3a\x63\x6f\x6c\x6c\x65\x63\x74\x3d\x22\x61\
+\x6c\x77\x61\x79\x73\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x78\x6c\
+\x69\x6e\x6b\x3a\x68\x72\x65\x66\x3d\x22\x23\x6c\x69\x6e\x65\x61\
+\x72\x47\x72\x61\x64\x69\x65\x6e\x74\x33\x31\x33\x36\x22\x0a\x20\
+\x20\x20\x20\x20\x20\x20\x69\x64\x3d\x22\x72\x61\x64\x69\x61\x6c\
+\x47\x72\x61\x64\x69\x65\x6e\x74\x33\x31\x34\x32\x22\x0a\x20\x20\
+\x20\x20\x20\x20\x20\x63\x78\x3d\x22\x33\x32\x37\x2e\x34\x31\x39\
+\x32\x35\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x63\x79\x3d\x22\x33\
+\x34\x2e\x31\x30\x31\x39\x38\x32\x22\x0a\x20\x20\x20\x20\x20\x20\
+\x20\x66\x78\x3d\x22\x33\x32\x37\x2e\x34\x31\x39\x32\x35\x22\x0a\
+\x20\x20\x20\x20\x20\x20\x20\x66\x79\x3d\x22\x33\x34\x2e\x31\x30\
+\x31\x39\x38\x32\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x72\x3d\x22\
+\x31\x33\x30\x2e\x31\x33\x32\x34\x22\x0a\x20\x20\x20\x20\x20\x20\
+\x20\x67\x72\x61\x64\x69\x65\x6e\x74\x55\x6e\x69\x74\x73\x3d\x22\
+\x75\x73\x65\x72\x53\x70\x61\x63\x65\x4f\x6e\x55\x73\x65\x22\x0a\
+\x20\x20\x20\x20\x20\x20\x20\x67\x72\x61\x64\x69\x65\x6e\x74\x54\
+\x72\x61\x6e\x73\x66\x6f\x72\x6d\x3d\x22\x6d\x61\x74\x72\x69\x78\
+\x28\x32\x2e\x35\x36\x39\x35\x37\x30\x37\x65\x2d\x37\x2c\x2d\x33\
+\x2e\x32\x34\x36\x39\x38\x35\x38\x2c\x32\x2e\x32\x39\x36\x32\x34\
+\x35\x2c\x36\x2e\x38\x37\x30\x38\x39\x36\x39\x65\x2d\x36\x2c\x33\
+\x36\x36\x2e\x39\x31\x30\x34\x39\x2c\x31\x35\x30\x34\x2e\x31\x38\
+\x33\x29\x22\x20\x2f\x3e\x0a\x20\x20\x20\x20\x3c\x6c\x69\x6e\x65\
+\x61\x72\x47\x72\x61\x64\x69\x65\x6e\x74\x0a\x20\x20\x20\x20\x20\
+\x20\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x63\x6f\x6c\x6c\x65\
+\x63\x74\x3d\x22\x61\x6c\x77\x61\x79\x73\x22\x0a\x20\x20\x20\x20\
+\x20\x20\x20\x78\x6c\x69\x6e\x6b\x3a\x68\x72\x65\x66\x3d\x22\x23\
+\x6c\x69\x6e\x65\x61\x72\x47\x72\x61\x64\x69\x65\x6e\x74\x34\x31\
+\x31\x37\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x69\x64\x3d\x22\x6c\
+\x69\x6e\x65\x61\x72\x47\x72\x61\x64\x69\x65\x6e\x74\x34\x31\x32\
+\x33\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x78\x31\x3d\x22\x32\x36\
+\x30\x2e\x39\x35\x32\x34\x32\x22\x0a\x20\x20\x20\x20\x20\x20\x20\
+\x79\x31\x3d\x22\x31\x32\x31\x2e\x31\x38\x38\x34\x32\x22\x0a\x20\
+\x20\x20\x20\x20\x20\x20\x78\x32\x3d\x22\x34\x38\x38\x2e\x36\x35\
+\x39\x35\x35\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x79\x32\x3d\x22\
+\x33\x35\x31\x2e\x34\x38\x30\x36\x35\x22\x0a\x20\x20\x20\x20\x20\
+\x20\x20\x67\x72\x61\x64\x69\x65\x6e\x74\x55\x6e\x69\x74\x73\x3d\
+\x22\x75\x73\x65\x72\x53\x70\x61\x63\x65\x4f\x6e\x55\x73\x65\x22\
+\x20\x2f\x3e\x0a\x20\x20\x20\x20\x3c\x6c\x69\x6e\x65\x61\x72\x47\
+\x72\x61\x64\x69\x65\x6e\x74\x0a\x20\x20\x20\x20\x20\x20\x20\x69\
+\x6e\x6b\x73\x63\x61\x70\x65\x3a\x63\x6f\x6c\x6c\x65\x63\x74\x3d\
+\x22\x61\x6c\x77\x61\x79\x73\x22\x0a\x20\x20\x20\x20\x20\x20\x20\
+\x78\x6c\x69\x6e\x6b\x3a\x68\x72\x65\x66\x3d\x22\x23\x6c\x69\x6e\
+\x65\x61\x72\x47\x72\x61\x64\x69\x65\x6e\x74\x34\x31\x31\x37\x22\
+\x0a\x20\x20\x20\x20\x20\x20\x20\x69\x64\x3d\x22\x6c\x69\x6e\x65\
+\x61\x72\x47\x72\x61\x64\x69\x65\x6e\x74\x34\x31\x32\x39\x22\x0a\
+\x20\x20\x20\x20\x20\x20\x20\x67\x72\x61\x64\x69\x65\x6e\x74\x55\
+\x6e\x69\x74\x73\x3d\x22\x75\x73\x65\x72\x53\x70\x61\x63\x65\x4f\
+\x6e\x55\x73\x65\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x78\x31\x3d\
+\x22\x32\x36\x30\x2e\x39\x35\x32\x34\x32\x22\x0a\x20\x20\x20\x20\
+\x20\x20\x20\x79\x31\x3d\x22\x31\x32\x31\x2e\x31\x38\x38\x34\x32\
+\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x78\x32\x3d\x22\x34\x38\x38\
+\x2e\x36\x35\x39\x35\x35\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x79\
+\x32\x3d\x22\x33\x35\x31\x2e\x34\x38\x30\x36\x35\x22\x0a\x20\x20\
+\x20\x20\x20\x20\x20\x67\x72\x61\x64\x69\x65\x6e\x74\x54\x72\x61\
+\x6e\x73\x66\x6f\x72\x6d\x3d\x22\x6d\x61\x74\x72\x69\x78\x28\x31\
+\x2e\x32\x34\x35\x37\x32\x32\x36\x2c\x30\x2c\x30\x2c\x31\x2e\x32\
+\x36\x31\x35\x38\x35\x34\x2c\x2d\x31\x37\x36\x2e\x37\x37\x36\x38\
+\x2c\x2d\x39\x30\x2e\x34\x39\x36\x35\x30\x38\x29\x22\x20\x2f\x3e\
+\x0a\x20\x20\x3c\x2f\x64\x65\x66\x73\x3e\x0a\x20\x20\x3c\x73\x6f\
+\x64\x69\x70\x6f\x64\x69\x3a\x6e\x61\x6d\x65\x64\x76\x69\x65\x77\
+\x0a\x20\x20\x20\x20\x20\x69\x64\x3d\x22\x62\x61\x73\x65\x22\x0a\
+\x20\x20\x20\x20\x20\x70\x61\x67\x65\x63\x6f\x6c\x6f\x72\x3d\x22\
+\x23\x66\x66\x66\x66\x66\x66\x22\x0a\x20\x20\x20\x20\x20\x62\x6f\
+\x72\x64\x65\x72\x63\x6f\x6c\x6f\x72\x3d\x22\x23\x36\x36\x36\x36\
+\x36\x36\x22\x0a\x20\x20\x20\x20\x20\x62\x6f\x72\x64\x65\x72\x6f\
+\x70\x61\x63\x69\x74\x79\x3d\x22\x31\x2e\x30\x22\x0a\x20\x20\x20\
+\x20\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x70\x61\x67\x65\x6f\
+\x70\x61\x63\x69\x74\x79\x3d\x22\x30\x2e\x30\x22\x0a\x20\x20\x20\
+\x20\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x70\x61\x67\x65\x73\
+\x68\x61\x64\x6f\x77\x3d\x22\x32\x22\x0a\x20\x20\x20\x20\x20\x69\
+\x6e\x6b\x73\x63\x61\x70\x65\x3a\x7a\x6f\x6f\x6d\x3d\x22\x30\x2e\
+\x39\x36\x31\x36\x34\x36\x31\x31\x22\x0a\x20\x20\x20\x20\x20\x69\
+\x6e\x6b\x73\x63\x61\x70\x65\x3a\x63\x78\x3d\x22\x33\x32\x36\x2e\
+\x33\x38\x33\x38\x32\x22\x0a\x20\x20\x20\x20\x20\x69\x6e\x6b\x73\
+\x63\x61\x70\x65\x3a\x63\x79\x3d\x22\x38\x39\x2e\x38\x36\x32\x38\
+\x36\x39\x22\x0a\x20\x20\x20\x20\x20\x69\x6e\x6b\x73\x63\x61\x70\
+\x65\x3a\x64\x6f\x63\x75\x6d\x65\x6e\x74\x2d\x75\x6e\x69\x74\x73\
+\x3d\x22\x70\x78\x22\x0a\x20\x20\x20\x20\x20\x69\x6e\x6b\x73\x63\
+\x61\x70\x65\x3a\x63\x75\x72\x72\x65\x6e\x74\x2d\x6c\x61\x79\x65\
+\x72\x3d\x22\x6c\x61\x79\x65\x72\x31\x22\x0a\x20\x20\x20\x20\x20\
+\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x77\x69\x6e\x64\x6f\x77\x2d\
+\x77\x69\x64\x74\x68\x3d\x22\x39\x39\x36\x22\x0a\x20\x20\x20\x20\
+\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x77\x69\x6e\x64\x6f\x77\
+\x2d\x68\x65\x69\x67\x68\x74\x3d\x22\x37\x31\x34\x22\x0a\x20\x20\
+\x20\x20\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x77\x69\x6e\x64\
+\x6f\x77\x2d\x78\x3d\x22\x31\x31\x22\x0a\x20\x20\x20\x20\x20\x69\
+\x6e\x6b\x73\x63\x61\x70\x65\x3a\x77\x69\x6e\x64\x6f\x77\x2d\x79\
+\x3d\x22\x31\x33\x22\x20\x2f\x3e\x0a\x20\x20\x3c\x6d\x65\x74\x61\
+\x64\x61\x74\x61\x0a\x20\x20\x20\x20\x20\x69\x64\x3d\x22\x6d\x65\
+\x74\x61\x64\x61\x74\x61\x37\x22\x3e\x0a\x20\x20\x20\x20\x3c\x72\
+\x64\x66\x3a\x52\x44\x46\x3e\x0a\x20\x20\x20\x20\x20\x20\x3c\x63\
+\x63\x3a\x57\x6f\x72\x6b\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\
+\x72\x64\x66\x3a\x61\x62\x6f\x75\x74\x3d\x22\x22\x3e\x0a\x20\x20\
+\x20\x20\x20\x20\x20\x20\x3c\x64\x63\x3a\x66\x6f\x72\x6d\x61\x74\
+\x3e\x69\x6d\x61\x67\x65\x2f\x73\x76\x67\x2b\x78\x6d\x6c\x3c\x2f\
+\x64\x63\x3a\x66\x6f\x72\x6d\x61\x74\x3e\x0a\x20\x20\x20\x20\x20\
+\x20\x20\x20\x3c\x64\x63\x3a\x74\x79\x70\x65\x0a\x20\x20\x20\x20\
+\x20\x20\x20\x20\x20\x20\x20\x72\x64\x66\x3a\x72\x65\x73\x6f\x75\
+\x72\x63\x65\x3d\x22\x68\x74\x74\x70\x3a\x2f\x2f\x70\x75\x72\x6c\
+\x2e\x6f\x72\x67\x2f\x64\x63\x2f\x64\x63\x6d\x69\x74\x79\x70\x65\
+\x2f\x53\x74\x69\x6c\x6c\x49\x6d\x61\x67\x65\x22\x20\x2f\x3e\x0a\
+\x20\x20\x20\x20\x20\x20\x3c\x2f\x63\x63\x3a\x57\x6f\x72\x6b\x3e\
+\x0a\x20\x20\x20\x20\x3c\x2f\x72\x64\x66\x3a\x52\x44\x46\x3e\x0a\
+\x20\x20\x3c\x2f\x6d\x65\x74\x61\x64\x61\x74\x61\x3e\x0a\x20\x20\
+\x3c\x67\x0a\x20\x20\x20\x20\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\
+\x3a\x6c\x61\x62\x65\x6c\x3d\x22\x43\x61\x6c\x71\x75\x65\x20\x31\
+\x22\x0a\x20\x20\x20\x20\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\
+\x67\x72\x6f\x75\x70\x6d\x6f\x64\x65\x3d\x22\x6c\x61\x79\x65\x72\
+\x22\x0a\x20\x20\x20\x20\x20\x69\x64\x3d\x22\x6c\x61\x79\x65\x72\
+\x31\x22\x0a\x20\x20\x20\x20\x20\x74\x72\x61\x6e\x73\x66\x6f\x72\
+\x6d\x3d\x22\x74\x72\x61\x6e\x73\x6c\x61\x74\x65\x28\x2d\x31\x37\
+\x35\x2e\x39\x35\x38\x35\x32\x2c\x2d\x31\x37\x31\x2e\x37\x39\x38\
+\x39\x39\x29\x22\x3e\x0a\x20\x20\x20\x20\x3c\x72\x65\x63\x74\x0a\
+\x20\x20\x20\x20\x20\x20\x20\x73\x74\x79\x6c\x65\x3d\x22\x6f\x70\
+\x61\x63\x69\x74\x79\x3a\x31\x3b\x66\x69\x6c\x6c\x3a\x23\x66\x66\
+\x30\x30\x30\x30\x3b\x66\x69\x6c\x6c\x2d\x6f\x70\x61\x63\x69\x74\
+\x79\x3a\x31\x3b\x66\x69\x6c\x6c\x2d\x72\x75\x6c\x65\x3a\x6e\x6f\
+\x6e\x7a\x65\x72\x6f\x3b\x73\x74\x72\x6f\x6b\x65\x3a\x23\x66\x66\
+\x66\x66\x66\x66\x3b\x73\x74\x72\x6f\x6b\x65\x2d\x77\x69\x64\x74\
+\x68\x3a\x30\x2e\x32\x39\x33\x39\x30\x36\x36\x36\x3b\x73\x74\x72\
+\x6f\x6b\x65\x2d\x6c\x69\x6e\x65\x63\x61\x70\x3a\x62\x75\x74\x74\
+\x3b\x73\x74\x72\x6f\x6b\x65\x2d\x6d\x69\x74\x65\x72\x6c\x69\x6d\
+\x69\x74\x3a\x34\x3b\x73\x74\x72\x6f\x6b\x65\x2d\x64\x61\x73\x68\
+\x61\x72\x72\x61\x79\x3a\x30\x2e\x32\x39\x33\x39\x30\x36\x36\x36\
+\x2c\x20\x30\x2e\x32\x39\x33\x39\x30\x36\x36\x36\x3b\x73\x74\x72\
+\x6f\x6b\x65\x2d\x64\x61\x73\x68\x6f\x66\x66\x73\x65\x74\x3a\x30\
+\x3b\x73\x74\x72\x6f\x6b\x65\x2d\x6f\x70\x61\x63\x69\x74\x79\x3a\
+\x31\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x69\x64\x3d\x22\x72\x65\
+\x63\x74\x32\x31\x36\x30\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x77\
+\x69\x64\x74\x68\x3d\x22\x32\x35\x39\x2e\x39\x37\x30\x38\x39\x22\
+\x0a\x20\x20\x20\x20\x20\x20\x20\x68\x65\x69\x67\x68\x74\x3d\x22\
+\x32\x35\x39\x2e\x39\x37\x30\x38\x39\x22\x0a\x20\x20\x20\x20\x20\
+\x20\x20\x78\x3d\x22\x31\x38\x35\x2e\x30\x39\x39\x32\x37\x22\x0a\
+\x20\x20\x20\x20\x20\x20\x20\x79\x3d\x22\x31\x38\x30\x2e\x39\x33\
+\x39\x37\x34\x22\x20\x2f\x3e\x0a\x20\x20\x20\x20\x3c\x72\x65\x63\
+\x74\x0a\x20\x20\x20\x20\x20\x20\x20\x79\x3d\x22\x31\x37\x36\x2e\
+\x33\x38\x37\x34\x34\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x78\x3d\
+\x22\x31\x38\x30\x2e\x35\x34\x36\x39\x37\x22\x0a\x20\x20\x20\x20\
+\x20\x20\x20\x68\x65\x69\x67\x68\x74\x3d\x22\x32\x36\x39\x2e\x30\
+\x37\x35\x35\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x77\x69\x64\x74\
+\x68\x3d\x22\x32\x36\x39\x2e\x30\x37\x35\x35\x22\x0a\x20\x20\x20\
+\x20\x20\x20\x20\x69\x64\x3d\x22\x72\x65\x63\x74\x32\x31\x36\x32\
+\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x73\x74\x79\x6c\x65\x3d\x22\
+\x6f\x70\x61\x63\x69\x74\x79\x3a\x31\x3b\x66\x69\x6c\x6c\x3a\x6e\
+\x6f\x6e\x65\x3b\x66\x69\x6c\x6c\x2d\x6f\x70\x61\x63\x69\x74\x79\
+\x3a\x31\x3b\x66\x69\x6c\x6c\x2d\x72\x75\x6c\x65\x3a\x6e\x6f\x6e\
+\x7a\x65\x72\x6f\x3b\x73\x74\x72\x6f\x6b\x65\x3a\x23\x66\x66\x30\
+\x30\x30\x30\x3b\x73\x74\x72\x6f\x6b\x65\x2d\x77\x69\x64\x74\x68\
+\x3a\x39\x2e\x31\x37\x36\x38\x39\x38\x39\x36\x3b\x73\x74\x72\x6f\
+\x6b\x65\x2d\x6c\x69\x6e\x65\x63\x61\x70\x3a\x62\x75\x74\x74\x3b\
+\x73\x74\x72\x6f\x6b\x65\x2d\x6d\x69\x74\x65\x72\x6c\x69\x6d\x69\
+\x74\x3a\x34\x3b\x73\x74\x72\x6f\x6b\x65\x2d\x64\x61\x73\x68\x61\
+\x72\x72\x61\x79\x3a\x6e\x6f\x6e\x65\x3b\x73\x74\x72\x6f\x6b\x65\
+\x2d\x64\x61\x73\x68\x6f\x66\x66\x73\x65\x74\x3a\x30\x3b\x73\x74\
+\x72\x6f\x6b\x65\x2d\x6f\x70\x61\x63\x69\x74\x79\x3a\x31\x22\x20\
+\x2f\x3e\x0a\x20\x20\x20\x20\x3c\x70\x61\x74\x68\x0a\x20\x20\x20\
+\x20\x20\x20\x20\x73\x74\x79\x6c\x65\x3d\x22\x66\x69\x6c\x6c\x3a\
+\x75\x72\x6c\x28\x23\x6c\x69\x6e\x65\x61\x72\x47\x72\x61\x64\x69\
+\x65\x6e\x74\x34\x31\x32\x39\x29\x3b\x66\x69\x6c\x6c\x2d\x6f\x70\
+\x61\x63\x69\x74\x79\x3a\x31\x3b\x66\x69\x6c\x6c\x2d\x72\x75\x6c\
+\x65\x3a\x6e\x6f\x6e\x7a\x65\x72\x6f\x3b\x73\x74\x72\x6f\x6b\x65\
+\x3a\x6e\x6f\x6e\x65\x3b\x73\x74\x72\x6f\x6b\x65\x2d\x77\x69\x64\
+\x74\x68\x3a\x35\x3b\x73\x74\x72\x6f\x6b\x65\x2d\x6c\x69\x6e\x65\
+\x63\x61\x70\x3a\x62\x75\x74\x74\x3b\x73\x74\x72\x6f\x6b\x65\x2d\
+\x6d\x69\x74\x65\x72\x6c\x69\x6d\x69\x74\x3a\x34\x3b\x73\x74\x72\
+\x6f\x6b\x65\x2d\x64\x61\x73\x68\x6f\x66\x66\x73\x65\x74\x3a\x30\
+\x3b\x73\x74\x72\x6f\x6b\x65\x2d\x6f\x70\x61\x63\x69\x74\x79\x3a\
+\x31\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x64\x3d\x22\x4d\x20\x31\
+\x38\x35\x2e\x30\x39\x33\x37\x35\x2c\x31\x38\x30\x2e\x39\x33\x37\
+\x35\x20\x4c\x20\x31\x38\x35\x2e\x30\x39\x33\x37\x35\x2c\x33\x35\
+\x32\x2e\x35\x36\x32\x35\x20\x43\x20\x31\x39\x30\x2e\x39\x33\x37\
+\x35\x32\x2c\x33\x35\x32\x2e\x37\x39\x39\x38\x32\x20\x31\x39\x36\
+\x2e\x38\x33\x38\x35\x36\x2c\x33\x35\x32\x2e\x39\x33\x37\x35\x20\
+\x32\x30\x32\x2e\x37\x38\x31\x32\x35\x2c\x33\x35\x32\x2e\x39\x33\
+\x37\x35\x20\x43\x20\x33\x31\x32\x2e\x38\x30\x30\x31\x34\x2c\x33\
+\x35\x32\x2e\x39\x33\x37\x35\x20\x34\x30\x36\x2e\x39\x35\x30\x34\
+\x39\x2c\x33\x31\x31\x2e\x36\x31\x30\x34\x34\x20\x34\x34\x35\x2e\
+\x30\x36\x32\x35\x2c\x32\x35\x33\x2e\x32\x35\x20\x4c\x20\x34\x34\
+\x35\x2e\x30\x36\x32\x35\x2c\x31\x38\x30\x2e\x39\x33\x37\x35\x20\
+\x4c\x20\x31\x38\x35\x2e\x30\x39\x33\x37\x35\x2c\x31\x38\x30\x2e\
+\x39\x33\x37\x35\x20\x7a\x20\x22\x0a\x20\x20\x20\x20\x20\x20\x20\
+\x69\x64\x3d\x22\x70\x61\x74\x68\x33\x31\x34\x34\x22\x20\x2f\x3e\
+\x0a\x20\x20\x20\x20\x3c\x70\x61\x74\x68\x0a\x20\x20\x20\x20\x20\
+\x20\x20\x73\x6f\x64\x69\x70\x6f\x64\x69\x3a\x74\x79\x70\x65\x3d\
+\x22\x61\x72\x63\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x73\x74\x79\
+\x6c\x65\x3d\x22\x6f\x70\x61\x63\x69\x74\x79\x3a\x31\x3b\x66\x69\
+\x6c\x6c\x3a\x6e\x6f\x6e\x65\x3b\x66\x69\x6c\x6c\x2d\x6f\x70\x61\
+\x63\x69\x74\x79\x3a\x31\x3b\x66\x69\x6c\x6c\x2d\x72\x75\x6c\x65\
+\x3a\x6e\x6f\x6e\x7a\x65\x72\x6f\x3b\x73\x74\x72\x6f\x6b\x65\x3a\
+\x23\x30\x30\x30\x30\x30\x30\x3b\x73\x74\x72\x6f\x6b\x65\x2d\x77\
+\x69\x64\x74\x68\x3a\x35\x3b\x73\x74\x72\x6f\x6b\x65\x2d\x6c\x69\
+\x6e\x65\x63\x61\x70\x3a\x62\x75\x74\x74\x3b\x73\x74\x72\x6f\x6b\
+\x65\x2d\x6d\x69\x74\x65\x72\x6c\x69\x6d\x69\x74\x3a\x34\x3b\x73\
+\x74\x72\x6f\x6b\x65\x2d\x64\x61\x73\x68\x61\x72\x72\x61\x79\x3a\
+\x6e\x6f\x6e\x65\x3b\x73\x74\x72\x6f\x6b\x65\x2d\x64\x61\x73\x68\
+\x6f\x66\x66\x73\x65\x74\x3a\x30\x3b\x73\x74\x72\x6f\x6b\x65\x2d\
+\x6f\x70\x61\x63\x69\x74\x79\x3a\x31\x22\x0a\x20\x20\x20\x20\x20\
+\x20\x20\x69\x64\x3d\x22\x70\x61\x74\x68\x33\x31\x34\x36\x22\x0a\
+\x20\x20\x20\x20\x20\x20\x20\x73\x6f\x64\x69\x70\x6f\x64\x69\x3a\
+\x63\x78\x3d\x22\x33\x30\x33\x2e\x36\x34\x36\x22\x0a\x20\x20\x20\
+\x20\x20\x20\x20\x73\x6f\x64\x69\x70\x6f\x64\x69\x3a\x63\x79\x3d\
+\x22\x31\x32\x39\x2e\x39\x38\x35\x34\x34\x22\x0a\x20\x20\x20\x20\
+\x20\x20\x20\x73\x6f\x64\x69\x70\x6f\x64\x69\x3a\x72\x78\x3d\x22\
+\x30\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x73\x6f\x64\x69\x70\x6f\
+\x64\x69\x3a\x72\x79\x3d\x22\x37\x2e\x32\x37\x39\x31\x38\x35\x33\
+\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x64\x3d\x22\x4d\x20\x33\x30\
+\x33\x2e\x36\x34\x36\x20\x31\x32\x39\x2e\x39\x38\x35\x34\x34\x20\
+\x41\x20\x30\x20\x37\x2e\x32\x37\x39\x31\x38\x35\x33\x20\x30\x20\
+\x31\x20\x31\x20\x20\x33\x30\x33\x2e\x36\x34\x36\x2c\x31\x32\x39\
+\x2e\x39\x38\x35\x34\x34\x20\x41\x20\x30\x20\x37\x2e\x32\x37\x39\
+\x31\x38\x35\x33\x20\x30\x20\x31\x20\x31\x20\x20\x33\x30\x33\x2e\
+\x36\x34\x36\x20\x31\x32\x39\x2e\x39\x38\x35\x34\x34\x20\x7a\x22\
+\x20\x2f\x3e\x0a\x20\x20\x20\x20\x3c\x72\x65\x63\x74\x0a\x20\x20\
+\x20\x20\x20\x20\x20\x79\x3d\x22\x31\x38\x30\x2e\x39\x33\x39\x37\
+\x34\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x78\x3d\x22\x31\x38\x35\
+\x2e\x30\x39\x39\x32\x37\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x68\
+\x65\x69\x67\x68\x74\x3d\x22\x32\x35\x39\x2e\x39\x37\x30\x38\x39\
+\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x77\x69\x64\x74\x68\x3d\x22\
+\x32\x35\x39\x2e\x39\x37\x30\x38\x39\x22\x0a\x20\x20\x20\x20\x20\
+\x20\x20\x69\x64\x3d\x22\x72\x65\x63\x74\x33\x31\x33\x34\x22\x0a\
+\x20\x20\x20\x20\x20\x20\x20\x73\x74\x79\x6c\x65\x3d\x22\x6f\x70\
+\x61\x63\x69\x74\x79\x3a\x31\x3b\x66\x69\x6c\x6c\x3a\x75\x72\x6c\
+\x28\x23\x72\x61\x64\x69\x61\x6c\x47\x72\x61\x64\x69\x65\x6e\x74\
+\x33\x31\x34\x32\x29\x3b\x66\x69\x6c\x6c\x2d\x6f\x70\x61\x63\x69\
+\x74\x79\x3a\x31\x3b\x66\x69\x6c\x6c\x2d\x72\x75\x6c\x65\x3a\x6e\
+\x6f\x6e\x7a\x65\x72\x6f\x3b\x73\x74\x72\x6f\x6b\x65\x3a\x23\x66\
+\x66\x66\x66\x66\x66\x3b\x73\x74\x72\x6f\x6b\x65\x2d\x77\x69\x64\
+\x74\x68\x3a\x30\x2e\x32\x39\x33\x39\x30\x36\x36\x36\x3b\x73\x74\
+\x72\x6f\x6b\x65\x2d\x6c\x69\x6e\x65\x63\x61\x70\x3a\x62\x75\x74\
+\x74\x3b\x73\x74\x72\x6f\x6b\x65\x2d\x6d\x69\x74\x65\x72\x6c\x69\
+\x6d\x69\x74\x3a\x34\x3b\x73\x74\x72\x6f\x6b\x65\x2d\x64\x61\x73\
+\x68\x61\x72\x72\x61\x79\x3a\x30\x2e\x32\x39\x33\x39\x30\x36\x36\
+\x36\x2c\x20\x30\x2e\x32\x39\x33\x39\x30\x36\x36\x36\x3b\x73\x74\
+\x72\x6f\x6b\x65\x2d\x64\x61\x73\x68\x6f\x66\x66\x73\x65\x74\x3a\
+\x30\x3b\x73\x74\x72\x6f\x6b\x65\x2d\x6f\x70\x61\x63\x69\x74\x79\
+\x3a\x31\x22\x20\x2f\x3e\x0a\x20\x20\x3c\x2f\x67\x3e\x0a\x3c\x2f\
+\x73\x76\x67\x3e\x0a\
+"
+
+qt_resource_name = "\
+\x00\x05\
+\x00\x6f\xa6\x53\
+\x00\x69\
+\x00\x63\x00\x6f\x00\x6e\x00\x73\
+\x00\x0f\
+\x01\x19\xe4\x67\
+\x00\x6c\
+\x00\x65\x00\x64\x00\x5f\x00\x72\x00\x65\x00\x64\x00\x5f\x00\x6f\x00\x66\x00\x66\x00\x2e\x00\x73\x00\x76\x00\x67\
+\x00\x0d\
+\x0e\xf5\xe6\x07\
+\x00\x6c\
+\x00\x65\x00\x64\x00\x5f\x00\x67\x00\x72\x00\x65\x00\x65\x00\x6e\x00\x2e\x00\x73\x00\x76\x00\x67\
+\x00\x11\
+\x09\x14\xa8\xe7\
+\x00\x6c\
+\x00\x65\x00\x64\x00\x5f\x00\x67\x00\x72\x00\x65\x00\x65\x00\x6e\x00\x5f\x00\x6f\x00\x66\x00\x66\x00\x2e\x00\x73\x00\x76\x00\x67\
+\
+\x00\x0b\
+\x08\x52\x2e\x07\
+\x00\x6c\
+\x00\x65\x00\x64\x00\x5f\x00\x72\x00\x65\x00\x64\x00\x2e\x00\x73\x00\x76\x00\x67\
+"
+
+qt_resource_struct = "\
+\x00\x00\x00\x00\x00\x02\x00\x00\x00\x01\x00\x00\x00\x01\
+\x00\x00\x00\x00\x00\x02\x00\x00\x00\x04\x00\x00\x00\x02\
+\x00\x00\x00\x10\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\
+\x00\x00\x00\x7c\x00\x00\x00\x00\x00\x01\x00\x00\x39\xd9\
+\x00\x00\x00\x54\x00\x00\x00\x00\x00\x01\x00\x00\x29\x35\
+\x00\x00\x00\x34\x00\x00\x00\x00\x00\x01\x00\x00\x14\x9b\
+"
+
+def qInitResources():
+    QtCore.qRegisterResourceData(0x01, qt_resource_struct, qt_resource_name, qt_resource_data)
+
+def qCleanupResources():
+    QtCore.qUnregisterResourceData(0x01, qt_resource_struct, qt_resource_name, qt_resource_data)
+
+qInitResources()
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/pygpibtoolkit/plotter/hpgl_qt.py	Tue Feb 05 18:59:29 2008 +0100
@@ -0,0 +1,144 @@
+# -*- coding: utf-8 -*-
+import numpy
+import pylab
+import math
+import new # monkey patching...
+
+from PyQt4 import QtGui, QtCore
+from PyQt4.QtCore import Qt, SIGNAL
+
+from hpgl_parser import HPGLParser
+
+class QHPGLPlotterWidget(HPGLParser, QtGui.QWidget):
+    pen_styles = {2: [0.4, 0.6],
+                  3: [0.6, 0.4],
+                  4: [0.7, 0.1, 0.1, 0.1],
+                  5: [0.6, 0.1, 0.2, 0.1],
+                  6: [0.45, 0.1, 0.1, 0.2, 0.1, 0.05],
+                  }
+    pen_colors = ["black", "green", "red", "blue", "yellow", "cyan", "magenta",
+                  "darkred", "darkblue"]
+    
+    def __init__(self, parent=None):
+        QtGui.QWidget.__init__(self, parent)
+        l = QtGui.QVBoxLayout(self)
+        l.setMargin(1)
+        self.qview = QtGui.QGraphicsView(self)
+        self.qview.setRenderHints(QtGui.QPainter.Antialiasing)
+        self.qview.scale(0.5,-0.5)
+        l = self.layout()
+        l.addWidget(self.qview)
+        self.setBackgroundRole(QtGui.QPalette.Base)
+        self.setSizePolicy(QtGui.QSizePolicy.Expanding,
+                           QtGui.QSizePolicy.Expanding)
+        self.clear()
+        HPGLParser.__init__(self)
+
+    def parse(self, data):
+        HPGLParser.parse(self, data)
+        self.resize(self.size())
+        
+    def clear(self):
+        self.qpen = QtGui.QPen(QtCore.Qt.blue)
+        self.qbrush = QtGui.QBrush(QtCore.Qt.blue)
+        self.qfont = QtGui.QFont('Courier') 
+        self.qantialiased = False
+        self.qtransformed = False
+        self.qscene = QtGui.QGraphicsScene()
+        self.qview.setScene(self.qscene)
+        
+    def _get_PW(self):
+        return self._pen_width
+    def _set_PW(self, value):
+        value = float(value)
+        #print "set pen width", value, value*300.0/75.0
+        #self.qpen.setWidthF(value*300.0/75.0)
+        self._pen_width = value
+    pen_width = property(_get_PW, _set_PW)
+        
+    def LT(self):
+        HPGLParser.LT(self)
+        if self.line_type == 0:
+            self.qpen.setStyle(Qt.SolidLine)
+        elif self.line_type == 1:
+            self.qpen.setStyle(Qt.DotLine)
+        else:
+            pattern = numpy.array(self.pen_styles[self.line_type])
+            x0, x1, y0, y1 = self.scale
+            dist = math.sqrt((x1-x0)**2 + (y1-y0)**2)
+            pattern = self.pattern_len*dist/100.0 * pattern
+            if self.qpen.widthF()>0:
+                pattern = pattern/self.qpen.widthF()
+            self.qpen.setDashPattern(pattern.tolist())
+            
+    def SP(self):
+        HPGLParser.SP(self)
+        color = self.pen_colors[self.pen]
+        if isinstance(color, tuple):
+            color = QtGui.QColor(*color)
+        else:
+            color = QtGui.QColor(color)
+        self.qpen.setColor(color)
+        
+    def parse(self, data):
+        HPGLParser.parse(self, data)
+        self.update()
+        self.qview.fitInView(self.qscene.sceneRect(), Qt.KeepAspectRatio)
+        
+    def minimumSizeHint(self):
+        return QtCore.QSize(100, 100)
+
+    def sizeHint(self):
+        return QtCore.QSize(400, 400)
+
+    def resizeEvent(self, event):
+        self.qview.fitInView(self.qscene.sceneRect(), Qt.KeepAspectRatio)
+        QtGui.QWidget.resizeEvent(self, event)
+
+    def plot_lines(self, points):
+        if len(points) == 1:
+            return
+        pa = QtGui.QPainterPath()
+        pa.addPolygon(QtGui.QPolygonF([QtCore.QPointF(*p) for p in points]))
+        self.qscene.addPath(pa, self.qpen)
+        
+    def plot_symbols(self, points):
+        pass
+    
+    def plot_string(self, s):
+        cw, ch = self.get_char_size()
+        # this is very ugly and so, but I don't understand haw is
+        # computed string positionning in HPGL...
+        t0 = self.qscene.addSimpleText(" ", self.qfont) 
+        br = t0.boundingRect()
+        mw = br.width()
+        mh = br.height()
+        self.qscene.removeItem(t0)
+        # don't ask me why theses constants are here, they seem OK, that's all
+        t = self.qscene.addSimpleText(s, self.qfont)
+        t.scale(1.0 * cw/mw, -1.6 * ch/mh)
+        x, y = self.pos
+        t.moveBy(x,y)
+        br = t.boundingRect()
+        t.moveBy(-0.5*cw+8, math.sqrt(2)*ch - 13)
+
+        
+if __name__=='__main__':
+    import sys
+    a = QtGui.QApplication(sys.argv)
+    mw = QtGui.QMainWindow()
+    w = QtGui.QWidget(mw)
+    mw.setCentralWidget(w)
+
+    l = QtGui.QVBoxLayout(w)
+    p = QHPGLPlotterWidget(w)
+    l.addWidget(p, 1)
+    b = QtGui.QPushButton("Replot", w)
+    l.addWidget(b)
+    def plot():
+        p.parse(open(sys.argv[1]).read())
+    b.connect(b, SIGNAL('pressed()'), plot)
+    mw.show()
+    plot()
+    a.exec_()
+    
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/pygpibtoolkit/plotter/qgpib_plotter.py	Tue Feb 05 18:59:29 2008 +0100
@@ -0,0 +1,346 @@
+#
+
+import os, sys
+import time
+import glob
+
+from PyQt4 import QtGui, QtCore, uic
+from PyQt4.QtCore import SIGNAL, Qt
+
+if "-m" in sys.argv:
+    from gpib_plotter_mockup import GPIBplotter
+else:
+    from gpib_plotter import GPIBplotter
+from hpgl_qt import QHPGLPlotterWidget
+
+ldir = os.path.abspath(os.path.dirname(__file__))
+sys.path.append(ldir)
+form_class, base_class = uic.loadUiType(os.path.join(ldir, "qhpgl_plotter.ui"))
+
+from pygpibtoolkit.qt4.qpreferences import BaseItem, IntItem, UnicodeItem, ColorItem
+from pygpibtoolkit.qt4.qpreferences import PointItem, SizeItem, ByteArrayItem
+from pygpibtoolkit.qt4.qpreferences import AbstractPreferences
+from pygpibtoolkit.qt4.qpreferenceseditor import PreferencesEditor
+
+from pygpibtoolkit.tools import str_num_cmp
+
+class Preferences(AbstractPreferences):
+    ORGANISATION="Logilab"
+    APPLICATION="qgpib_plotter"
+
+    _pos = PointItem()
+    _size = SizeItem()
+    _appState = ByteArrayItem()
+
+    device = UnicodeItem(default='/dev/ttyUSB0',
+                         name=u'device',
+                         description=u'GPIB device',
+                         group="GPIB settings")
+    address = IntItem(default=5, min=0, max=16,
+                      name=u'GPIB address',
+                      group="GPIB settings")
+    
+    background = ColorItem(default=QtGui.QColor("white"),
+                           name="Background",
+                           group="Colors")
+    color0 = ColorItem(default=QtGui.QColor("black"),
+                       name="Pen #0",
+                       group="Colors")
+    color1 = ColorItem(default=QtGui.QColor("green"),
+                       name="Pen #1",
+                       group="Colors")
+    color2 = ColorItem(default=QtGui.QColor("red"),
+                       name="Pen #2",
+                       group="Colors")
+    color3 = ColorItem(default=QtGui.QColor("blue"),
+                       name="Pen #3",
+                       group="Colors")
+    color4 = ColorItem(default=QtGui.QColor("yellow"),
+                       name="Pen #4",
+                       group="Colors")
+    color5 = ColorItem(default=QtGui.QColor("cyan"),
+                       name="Pen #5",
+                       group="Colors")
+    color6 = ColorItem(default=QtGui.QColor("magenta"),
+                       name="Pen #6",
+                       group="Colors")
+    color7 = ColorItem(default=QtGui.QColor("darkred"),
+                       name="Pen #7",
+                       group="Colors")
+    
+class QtHPGLPlotter(QtGui.QMainWindow, form_class):
+    def __init__(self, parent=None):
+        QtGui.QMainWindow.__init__(self, parent)
+        self._plots = {}        
+        self._prefs = Preferences()
+        self.setupUi()
+        self.initializeGPIB()
+        if self._prefs._pos:
+            self.move(self._prefs._pos)
+        if self._prefs._size:
+            self.resize(self._prefs._size)
+        if self._prefs._appState:
+            self.restoreState(self._prefs._appState)
+        self.readPreferences()
+
+    def readPreferences(self):
+        bg = self._prefs.background
+        if bg and bg.isValid():
+            self.plotterWidget.qview.setBackgroundBrush(QtGui.QBrush(bg))
+        pen_colors = [self._prefs["color%d"%i] for i in range(8)]
+        self.plotterWidget.pen_colors = pen_colors
+        
+    def replotCurrent(self):
+        self.currentPlotChanged(self.plotsView.currentIndex())
+        
+    def setupUi(self):
+        form_class.setupUi(self, self) # call qtdesigner generated form creation        
+        # actions defined in designer
+        self.connect(self.actionPreferences, SIGNAL('triggered(bool)'),
+                     self.preferencesTriggered)
+        self.connect(self.actionQuit, SIGNAL('triggered(bool)'),
+                     self.quitTriggered)
+        self.actionQuit.setShortcut(QtGui.QKeySequence(u'Ctrl+Q'))
+        self.connect(self.actionOpen, SIGNAL('triggered(bool)'),
+                     self.openTriggered)
+        self.actionOpen.setShortcut(QtGui.QKeySequence(u'Ctrl+O'))
+        self.connect(self.actionSave, SIGNAL('triggered(bool)'),
+                     self.saveTriggered)
+        self.actionSave.setShortcut(QtGui.QKeySequence(u'Ctrl+S'))
+        self.connect(self.actionSaveAs, SIGNAL('triggered(bool)'),
+                     self.saveAsTriggered)
+
+        self.plotterWidget = QHPGLPlotterWidget(self)
+        self.setCentralWidget(self.plotterWidget)
+
+        self.connect(self.captureButton, SIGNAL("toggled(bool)"),
+                     self.captureToggled)
+
+        self._plots_list = QtGui.QStringListModel()
+        self.plotsView.setModel(self._plots_list)
+        self.connect(self.plotsView, SIGNAL('activated(const QModelIndex&)'),
+                     self.currentPlotChanged)
+        self.connect(self.plotsView.selectionModel(),
+                     SIGNAL('currentChanged(const QModelIndex&, const QModelIndex&)'),
+                     self.currentPlotChanged)
+
+    def currentPlotChanged(self, index, old_index=None):
+        if index.isValid():
+            value = unicode(self.plotsView.model().data(index, Qt.DisplayRole).toString())
+            
+            self.plotterWidget.clear()
+            self.plotterWidget.parse(self._plots[value])
+            
+    def preferencesTriggered(self, checked=False):
+        PreferencesEditor(self._prefs, self).exec_()
+        self.readPreferences()
+        self.replotCurrent()
+
+    def quitTriggered(self, checked=False):
+        self.close()
+
+    def closeEvent(self, event):
+        if 1:
+        #if self.promptForSave():
+            self._prefs._pos = self.pos()
+            self._prefs._size = self.size()
+            self._prefs._appState = self.saveState()
+            event.accept()
+        else:
+            event.ignore()
+        
+    def openTriggered(self, checked=False):
+        filenames = QtGui.QFileDialog.getOpenFileNames(self, "Open a HPGL file to display", '.', 'HPGL files (*.plt)\nAll files (*)')
+        self.openFiles(filenames)
+        self.displayFirst()
+        
+    def displayFirst(self):
+        if not self.plotsView.currentIndex().isValid():
+            self.plotsView.setCurrentIndex(self.plotsView.model().index(0, 0))
+        
+    def openFiles(self, filenames):
+        ok = False
+        for filename in filenames:
+            filename = str(filename)
+            if os.path.exists(filename):
+                data = open(filename).read()
+                name = os.path.basename(filename)
+                name = os.path.splitext(name)[0]
+                lst = self.plotsView.model().stringList()
+                lst.append(name)            
+                self._plots[name] = data
+                self.plotsView.model().setStringList(lst)
+                ok = True
+        return ok
+        
+    def plotReceived(self, num):
+        self._receiving = False
+        self.setReceivingLed()
+        plot, timestamp = self.captureThread.getPlot(num)
+        name = "plot_%s"%(num)
+        lst = self.plotsView.model().stringList()
+        lst.append(name)            
+        self._plots[name] = plot
+        self.plotsView.model().setStringList(lst)
+
+    def plotStarted(self):
+        self._receiving = True
+        self.setReceivingLed()
+        
+    def saveTriggered(self, checked=False):
+        print "save"
+        
+    def saveAsTriggered(self, checked=False):
+        index = self.plotsView.selectionModel().currentIndex()
+        if index.isValid():
+            filename = QtGui.QFileDialog.getSaveFileName(self, "Selecte a file name to save HPGL file", '.', 'HPGL files (*.plt)\nAll files (*)')
+            n = index.row()
+            value = unicode(self.plotsView.model().data(index, Qt.DisplayRole).toString())
+            open(filename, 'w').write(self._plots[value])
+            
+        
+    def initializeGPIB(self):
+        self._online = False
+        try:
+            self.gpib_plotter = QGPIBplotter(device=self._prefs.device,
+                                            address=self._prefs.address,
+                                            )
+            self.captureThread = GPIBReceiver(self.gpib_plotter)
+            self.connect(self.captureThread, SIGNAL('plotReceived(int)'),
+                         self.plotReceived)
+            self.connect(self.captureThread, SIGNAL('plotStarted()'),
+                         self.plotStarted)
+            self.captureThread.start()
+        except Exception, e:
+            #print e
+            self.gpib_plotter = None
+        self.setCaptureLed()
+
+    def captureToggled(self, state):
+        if state:
+            if self.gpib_plotter is None:
+                self.initializeGPIB()
+                if self.gpib_plotter is None:
+                    QtGui.QMessageBox.critical(self, self.tr("GPIB error"),
+                                               self.tr("<b>Unable to initialize GPIB connection</b>.<br>Please check your GPIB dongle and settings."))
+                    self._online = False
+                    self.setCaptureLed()
+                    return
+            self._online = True
+            self.captureThread.startCapture()
+        else:
+            if self.captureThread:
+                self.captureThread.stopCapture()
+            self._online = False
+        self.setCaptureLed()
+        
+    def setCaptureLed(self):
+        if self._online:
+            icn = QtGui.QIcon(':/icons/led_green.svg')
+        else:
+            icn = QtGui.QIcon(':/icons/led_green_off.svg')
+        self.captureButton.setIcon(icn)
+        self.captureButton.setChecked(self._online)
+
+    def setReceivingLed(self):
+        if self._receiving:
+            icn = QtGui.QIcon(':/icons/led_red.svg')
+        else:
+            icn = QtGui.QIcon(':/icons/led_red_off.svg')
+        self.receivingButton.setIcon(icn)
+
+class QGPIBplotter(GPIBplotter):
+    def __init__(self, device="/dev/ttyUSB0", baudrate=115200, timeout=0.1,
+                 address=5):
+        GPIBplotter.__init__(self, device, baudrate, timeout, address)        
+        self.emitter = None
+
+    def plotStarted(self):
+        if self.emitter:
+            self.emitter.emit(SIGNAL('plotStarted()'))
+            #self.emitter.msleep(1)
+        
+class GPIBReceiver(QtCore.QThread):
+    def __init__(self, cnx):
+        QtCore.QThread.__init__(self)
+        self.gpibplotter = cnx
+        self.gpibplotter.emitter = self
+        
+        self._cancelmutex = QtCore.QMutex()
+        self._cancel = False
+        #self._nreceived = 0
+        self._plotsmutex = QtCore.QMutex()
+        self._plots = []
+        self._startstopmutex = QtCore.QMutex()
+        self._startstop = QtCore.QWaitCondition()
+        self._capturing = False
+        
+    def cancel(self):
+        self._cancelmutex.lock()
+        self._cancel = True
+        self._cancelmutex.unlock()
+
+    def startCapture(self):
+        self._startstop.wakeOne()
+
+    def stopCapture(self):
+        self._startstopmutex.lock()
+        self._capturing = False
+        self._startstopmutex.unlock()
+
+    def run(self):
+        while 1:
+            self._cancelmutex.lock()
+            if self._cancel:
+                return
+            self._cancelmutex.unlock()
+            self._startstopmutex.lock()
+            if not self._capturing:
+                self._startstop.wait(self._startstopmutex)
+                self._capturing = True
+            self._startstopmutex.unlock()
+        
+            plot = self.gpibplotter.load_plot(wait_timeout=0.1)
+            timestamp = time.time()
+            if plot:
+                self._plotsmutex.lock()
+                self._plots.append((plot, timestamp))
+                n = len(self._plots)
+                self._plotsmutex.unlock()
+                self.emit(SIGNAL('plotReceived(int)'), n-1)
+            self.msleep(10)
+            
+    def getPlot(self, num):
+        self._plotsmutex.lock()
+        try:
+            return self._plots[num]
+        finally:
+            self._plotsmutex.unlock()
+
+def main():
+    import optparse
+    opt = optparse.OptionParser('A simple PyQt4 HP7470A GPIB plotter emulator for USB-GPIB bundle (ProLogix)')
+    opt.add_option('-m', '--mockup', default=False,
+                   action="store_true",
+                   dest='mockup',
+                   help='Use a pseudo GPIB connection (for test purpose)',
+                   )
+    opt.add_option('-v', '--verbose', default=False,
+                   action="store_true",
+                   dest="verbose",
+                   help="Verbose mode",)
+    
+    options, argv = opt.parse_args(sys.argv)
+
+    a = QtGui.QApplication(argv)
+    w = QtHPGLPlotter()
+    files = [f for f in argv[1:] if os.path.isfile(f)]
+    files.sort(cmp=str_num_cmp)
+    if w.openFiles(files):    
+        w.displayFirst()
+
+    w.show()
+    a.exec_()
+        
+if __name__ == '__main__':
+    main()
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/pygpibtoolkit/plotter/qhpgl_plotter.ui	Tue Feb 05 18:59:29 2008 +0100
@@ -0,0 +1,166 @@
+<ui version="4.0" >
+ <class>MainWindow</class>
+ <widget class="QMainWindow" name="MainWindow" >
+  <property name="geometry" >
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>507</width>
+    <height>492</height>
+   </rect>
+  </property>
+  <property name="windowTitle" >
+   <string>MainWindow</string>
+  </property>
+  <widget class="QWidget" name="centralwidget" />
+  <widget class="QMenuBar" name="menubar" >
+   <property name="geometry" >
+    <rect>
+     <x>0</x>
+     <y>0</y>
+     <width>507</width>
+     <height>25</height>
+    </rect>
+   </property>
+   <widget class="QMenu" name="menu_File" >
+    <property name="title" >
+     <string>&amp;File</string>
+    </property>
+    <addaction name="actionOpen" />
+    <addaction name="actionSave" />
+    <addaction name="actionSaveAs" />
+    <addaction name="separator" />
+    <addaction name="actionQuit" />
+   </widget>
+   <widget class="QMenu" name="menuEdit" >
+    <property name="title" >
+     <string>Edit</string>
+    </property>
+    <addaction name="actionPreferences" />
+   </widget>
+   <addaction name="menu_File" />
+   <addaction name="menuEdit" />
+  </widget>
+  <widget class="QStatusBar" name="statusbar" />
+  <widget class="QDockWidget" name="plotsDock" >
+   <attribute name="dockWidgetArea" >
+    <number>1</number>
+   </attribute>
+   <widget class="QWidget" name="dockWidgetContents" >
+    <layout class="QVBoxLayout" >
+     <property name="spacing" >
+      <number>4</number>
+     </property>
+     <property name="leftMargin" >
+      <number>1</number>
+     </property>
+     <property name="topMargin" >
+      <number>4</number>
+     </property>
+     <property name="rightMargin" >
+      <number>1</number>
+     </property>
+     <property name="bottomMargin" >
+      <number>1</number>
+     </property>
+     <item>
+      <layout class="QHBoxLayout" >
+       <item>
+        <widget class="QToolButton" name="captureButton" >
+         <property name="minimumSize" >
+          <size>
+           <width>0</width>
+           <height>29</height>
+          </size>
+         </property>
+         <property name="text" >
+          <string>on line</string>
+         </property>
+         <property name="icon" >
+          <iconset/>
+         </property>
+         <property name="iconSize" >
+          <size>
+           <width>16</width>
+           <height>16</height>
+          </size>
+         </property>
+         <property name="checkable" >
+          <bool>true</bool>
+         </property>
+         <property name="toolButtonStyle" >
+          <enum>Qt::ToolButtonTextBesideIcon</enum>
+         </property>
+        </widget>
+       </item>
+       <item>
+        <spacer>
+         <property name="orientation" >
+          <enum>Qt::Horizontal</enum>
+         </property>
+         <property name="sizeHint" >
+          <size>
+           <width>40</width>
+           <height>20</height>
+          </size>
+         </property>
+        </spacer>
+       </item>
+       <item>
+        <widget class="QPushButton" name="receivingButton" >
+         <property name="text" >
+          <string/>
+         </property>
+         <property name="icon" >
+          <iconset/>
+         </property>
+         <property name="iconSize" >
+          <size>
+           <width>16</width>
+           <height>16</height>
+          </size>
+         </property>
+         <property name="flat" >
+          <bool>true</bool>
+         </property>
+        </widget>
+       </item>
+      </layout>
+     </item>
+     <item>
+      <widget class="QListView" name="plotsView" />
+     </item>
+    </layout>
+   </widget>
+  </widget>
+  <action name="actionOpen" >
+   <property name="text" >
+    <string>&amp;Open</string>
+   </property>
+  </action>
+  <action name="actionSave" >
+   <property name="text" >
+    <string>&amp;Save</string>
+   </property>
+  </action>
+  <action name="actionSaveAs" >
+   <property name="text" >
+    <string>Save as...</string>
+   </property>
+  </action>
+  <action name="actionQuit" >
+   <property name="text" >
+    <string>&amp;Quit</string>
+   </property>
+  </action>
+  <action name="actionPreferences" >
+   <property name="text" >
+    <string>Preferences</string>
+   </property>
+  </action>
+ </widget>
+ <resources>
+  <include location="../qt4/resources.qrc" />
+ </resources>
+ <connections/>
+</ui>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/pygpibtoolkit/prologix.py	Tue Feb 05 18:59:29 2008 +0100
@@ -0,0 +1,117 @@
+"""
+prologix
+========
+
+Module defining a communication object to talk to Prologix USB-GPIB controler.
+
+"""
+import serial
+import time
+
+from pygpibtoolkit import pygpib
+from pygpibtoolkit.pygpib import ConnectionError
+
+GPIB_CONTROLLER = 1
+GPIB_DEVICE = 0
+
+class GPIB(object):
+    _retries = 15
+    def __init__(self, device="/dev/ttyUSB0", baudrate=115200, timeout=0.1,
+                    address=0, mode=1):        
+        """
+        Create a new GPIB controller for the Prologix USB-GPIB device
+        located on serial device 'device'.        
+        """
+        self._cnx = serial.Serial(port=device, baudrate=baudrate, timeout=timeout)
+        self._timeout = timeout
+        
+        self.set_mode(mode)
+        self.set_address(address)
+        
+    def set_address(self, address):
+        """
+        Set the address of the GPIB device:
+        
+        - if the device is the Controller In Charge, this is the
+          address of the device commands are sent to,
+
+        - if the device is in GPIB_DEVICE mode, this is its address.
+        """
+        self._set_cmd('addr', address)
+        self._adress = address
+        
+    def set_mode(self, mode):
+        """
+        Set GPIB device mode to 'mode':
+        
+        - GPIB_CONTROLLER: set the device as the Controller In Charge
+          on the GPIB bus
+
+        - GPIB_DEVICE: set the device as a standard GPIB device on the
+          bus.
+        """
+        self._set_cmd('mode', mode)
+        self._mode = mode
+
+    def set_controller(self):
+        """
+        Set GPIB device the Controller In Charge on the GPIB bus.
+        """
+        self.set_mode(1)
+
+    def set_device(self):
+        """
+        Set the GPIB device as a simple device on the GPIB bus.        
+        """
+        self.set_mode(0)
+
+    def send_command(self, cmd):
+        """
+        Send the specified GPIB command on the bus (must be the CIC),
+        and read the answer.
+        """
+        assert self._mode == 1
+        self._cnx.write(cmd+'\r')
+        time.sleep(self._timeout) # required?
+        ret = self._cnx.readlines()
+        return ''.join(ret)
+
+    def check_srq(self):
+        """
+        Check the SRQ line
+        """
+        assert self._mode == 1, "must be the Controller In Charge"
+        self._cnx.write('++srq\r')
+        ret = self._cnx.readline().strip()
+        if ret:
+            return bool(int(ret))
+        return None
+
+    def poll(self):
+        """
+        Poll every address, and return a dictionnary
+         {add: status, ...}        
+        """
+        assert self._mode == 1, "must be the Controller In Charge"
+        dico = {}
+        for add in range(31):
+            self._cnx.write('++spoll %d\r'%i)
+            ret = self._cnx.readline().strip()
+            if ret:
+                dico[i] = int(ret)
+        return dico
+    
+    def _read(self):
+        for i in range(self._retries):
+            rdata = self._cnx.readline()
+            if rdata.strip() != "":
+                break
+            time.sleep(self._timeout)
+        return rdata
+
+    def _set_cmd(self, cmd, value):
+        self._cnx.write('++%s %d\r'%(cmd, value))
+        self._cnx.write('++%s\r'%(cmd))
+        rval = self._read().strip()
+        if not rval.isdigit() or int(rval) != value:
+            raise ConnectionError("Can't set GPIB %s to %s [ret=%s]"%(cmd, value, repr(rval)))
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/pygpibtoolkit/pygpib.py	Tue Feb 05 18:59:29 2008 +0100
@@ -0,0 +1,64 @@
+"""
+gpib: create serial connection to GPIB-USB device (ProLogix is the
+only supported device for now).
+"""
+import serial
+from serial.serialutil import SerialException
+import time
+
+class ConnectionError(Exception):
+    pass
+
+class Constants(object):
+    def __init__(self):
+        self.constants = {}
+        self.descriptions = {}
+        self.rev_constants = {}
+        for v, k, m in self._constants:
+            self.k = v
+            self.constants[v] = k
+            self.rev_constants[k] = v
+            self.descriptions[v] = m
+            
+    def __getitem__(self, k):
+        if isinstance(k, basestring):
+            return self.rev_constants[k]
+        else:
+            return self.constants[k]
+
+    def get_description(self, k):
+        if isinstance(k, basestring):
+            k = self.rev_constants[k]
+        return self.descriptions[k]
+    
+
+class MODE(Constants):    
+    _constants = [(1, "CONTROLLER", "Set device as Controller in Charge"),
+                  (0, "DEVICE", "Set device as simple listener"),
+                  ]
+# TODO
+# class STATUS_BYTE(Constants):
+#     # IEEE 488.2 Status Byte constants
+#     MAV = 0x10 # Message AVailable: bit 4 of the Status Byte
+#     ESB = 0x20 # Event Status Bit: bit 5 of the Status Byte
+#     MSS = 0x40 # Master Summary Status bit: bit 6 of the Status Byte (NOT
+#                # sent in response to a serial poll)
+#     RQS = 0x40 # Request Service: bit 6 of the Status Byte (when sent in
+#                # response to a serial poll)
+# class SESR(Constants):
+#     # SESR constants (Standard Event Status Register)
+#     PON = 0x80 # Power On: Power has been turned On since last register
+#                # read access
+#     URQ = 0x40 # User Request: the user has activated some device control
+#                # (whatever the Remote Local state is)
+#     CME = 0x20 # Command Error
+#     EXE = 0x10 # Execution Error
+#     DDE = 0x08 # Device Dependant Error
+#     QYE = 0x04 # QuerY Error (attempt to read data while Output Queue is
+#                # empty, or data in the OQ was lost)
+#     RQC = 0x02 # Request Control: tell the CiC that the device wants to
+#                # become the CiC
+#     OPC = 0x01 # Operation Complete: device has completed any pending
+#                # operation (ready to accept new commands). This bit is
+#                # generated in response to a OPC command.
+    
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/pygpibtoolkit/qt4/icons/led_green.svg	Tue Feb 05 18:59:29 2008 +0100
@@ -0,0 +1,144 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://web.resource.org/cc/"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:xlink="http://www.w3.org/1999/xlink"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   width="278.25241"
+   height="278.25241"
+   id="svg2"
+   sodipodi:version="0.32"
+   inkscape:version="0.45.1"
+   sodipodi:docbase="/home/david/Electronic/HP3562/icons"
+   sodipodi:docname="led_green.svg"
+   inkscape:output_extension="org.inkscape.output.svg.inkscape"
+   version="1.0">
+  <defs
+     id="defs4">
+    <linearGradient
+       inkscape:collect="always"
+       id="linearGradient4117">
+      <stop
+         style="stop-color:#ffffff;stop-opacity:1;"
+         offset="0"
+         id="stop4119" />
+      <stop
+         style="stop-color:#ffffff;stop-opacity:0;"
+         offset="1"
+         id="stop4121" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient3136">
+      <stop
+         style="stop-color:#ffffff;stop-opacity:1;"
+         offset="0"
+         id="stop3138" />
+      <stop
+         style="stop-color:#00ff00;stop-opacity:0;"
+         offset="1"
+         id="stop3140" />
+    </linearGradient>
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient3136"
+       id="radialGradient3142"
+       cx="327.41925"
+       cy="34.101982"
+       fx="327.41925"
+       fy="34.101982"
+       r="130.1324"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(2.5695707e-7,-3.2469858,2.296245,6.8708969e-6,366.91049,1504.183)" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient4117"
+       id="linearGradient4123"
+       x1="260.95242"
+       y1="121.18842"
+       x2="488.65955"
+       y2="351.48065"
+       gradientUnits="userSpaceOnUse" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient4117"
+       id="linearGradient4129"
+       gradientUnits="userSpaceOnUse"
+       x1="260.95242"
+       y1="121.18842"
+       x2="488.65955"
+       y2="351.48065"
+       gradientTransform="matrix(1.2457226,0,0,1.2615854,-176.7768,-90.496508)" />
+  </defs>
+  <sodipodi:namedview
+     id="base"
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1.0"
+     inkscape:pageopacity="0.0"
+     inkscape:pageshadow="2"
+     inkscape:zoom="0.48082306"
+     inkscape:cx="372.04724"
+     inkscape:cy="207.1213"
+     inkscape:document-units="px"
+     inkscape:current-layer="layer1"
+     inkscape:window-width="996"
+     inkscape:window-height="714"
+     inkscape:window-x="25"
+     inkscape:window-y="4" />
+  <metadata
+     id="metadata7">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+      </cc:Work>
+    </rdf:RDF>
+  </metadata>
+  <g
+     inkscape:label="Calque 1"
+     inkscape:groupmode="layer"
+     id="layer1"
+     transform="translate(-175.95852,-171.79899)">
+    <rect
+       style="opacity:1;fill:#00ff00;fill-opacity:1;fill-rule:nonzero;stroke:#ffffff;stroke-width:0.29390666;stroke-linecap:butt;stroke-miterlimit:4;stroke-dasharray:0.29390666, 0.29390666;stroke-dashoffset:0;stroke-opacity:1"
+       id="rect2160"
+       width="259.97089"
+       height="259.97089"
+       x="185.09927"
+       y="180.93974" />
+    <rect
+       y="176.38744"
+       x="180.54697"
+       height="269.0755"
+       width="269.0755"
+       id="rect2162"
+       style="opacity:1;fill:none;fill-opacity:1;fill-rule:nonzero;stroke:#00c40b;stroke-width:9.17689896;stroke-linecap:butt;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
+    <rect
+       y="180.93974"
+       x="185.09927"
+       height="259.97089"
+       width="259.97089"
+       id="rect3134"
+       style="opacity:1;fill:url(#radialGradient3142);fill-opacity:1;fill-rule:nonzero;stroke:#ffffff;stroke-width:0.29390666;stroke-linecap:butt;stroke-miterlimit:4;stroke-dasharray:0.29390666, 0.29390666;stroke-dashoffset:0;stroke-opacity:1" />
+    <path
+       style="fill:url(#linearGradient4129);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:5;stroke-linecap:butt;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:1"
+       d="M 185.09375,180.9375 L 185.09375,352.5625 C 190.93752,352.79982 196.83856,352.9375 202.78125,352.9375 C 312.80014,352.9375 406.95049,311.61044 445.0625,253.25 L 445.0625,180.9375 L 185.09375,180.9375 z "
+       id="path3144" />
+    <path
+       sodipodi:type="arc"
+       style="opacity:1;fill:none;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:5;stroke-linecap:butt;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+       id="path3146"
+       sodipodi:cx="303.646"
+       sodipodi:cy="129.98544"
+       sodipodi:rx="0"
+       sodipodi:ry="7.2791853"
+       d="M 303.646 129.98544 A 0 7.2791853 0 1 1  303.646,129.98544 A 0 7.2791853 0 1 1  303.646 129.98544 z" />
+  </g>
+</svg>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/pygpibtoolkit/qt4/icons/led_green_off.svg	Tue Feb 05 18:59:29 2008 +0100
@@ -0,0 +1,116 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://web.resource.org/cc/"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:xlink="http://www.w3.org/1999/xlink"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   width="278.25241"
+   height="278.25241"
+   id="svg2"
+   sodipodi:version="0.32"
+   inkscape:version="0.45.1"
+   sodipodi:docbase="/home/david/Electronic/HP3562/icons"
+   sodipodi:docname="led_green_off.svg"
+   inkscape:output_extension="org.inkscape.output.svg.inkscape"
+   version="1.0">
+  <defs
+     id="defs4">
+    <linearGradient
+       id="linearGradient4117">
+      <stop
+         style="stop-color:#acacac;stop-opacity:0.68783069;"
+         offset="0"
+         id="stop4119" />
+      <stop
+         style="stop-color:#ffffff;stop-opacity:0;"
+         offset="1"
+         id="stop4121" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient3136">
+      <stop
+         style="stop-color:#ffffff;stop-opacity:1;"
+         offset="0"
+         id="stop3138" />
+      <stop
+         style="stop-color:#00ff00;stop-opacity:0;"
+         offset="1"
+         id="stop3140" />
+    </linearGradient>
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient4117"
+       id="linearGradient4129"
+       gradientUnits="userSpaceOnUse"
+       x1="260.95242"
+       y1="121.18842"
+       x2="488.65955"
+       y2="351.48065"
+       gradientTransform="matrix(1.2457226,0,0,1.2615854,-176.7768,-90.496508)" />
+  </defs>
+  <sodipodi:namedview
+     id="base"
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1.0"
+     inkscape:pageopacity="0.0"
+     inkscape:pageshadow="2"
+     inkscape:zoom="0.48082306"
+     inkscape:cx="372.04724"
+     inkscape:cy="-64.793696"
+     inkscape:document-units="px"
+     inkscape:current-layer="layer1"
+     inkscape:window-width="996"
+     inkscape:window-height="714"
+     inkscape:window-x="22"
+     inkscape:window-y="21" />
+  <metadata
+     id="metadata7">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+      </cc:Work>
+    </rdf:RDF>
+  </metadata>
+  <g
+     inkscape:label="Calque 1"
+     inkscape:groupmode="layer"
+     id="layer1"
+     transform="translate(-175.95852,-171.79899)">
+    <rect
+       style="opacity:1;fill:#009900;fill-opacity:1;fill-rule:nonzero;stroke:#ffffff;stroke-width:0.29390666;stroke-linecap:butt;stroke-miterlimit:4;stroke-dasharray:0.29390666, 0.29390666;stroke-dashoffset:0;stroke-opacity:1"
+       id="rect2160"
+       width="259.97089"
+       height="259.97089"
+       x="185.09927"
+       y="180.93974" />
+    <rect
+       y="176.38744"
+       x="180.54697"
+       height="269.0755"
+       width="269.0755"
+       id="rect2162"
+       style="opacity:1;fill:none;fill-opacity:1;fill-rule:nonzero;stroke:#008304;stroke-width:9.17689896;stroke-linecap:butt;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
+    <path
+       style="fill:url(#linearGradient4129);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:5;stroke-linecap:butt;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:1"
+       d="M 185.09375,180.9375 L 185.09375,352.5625 C 190.93752,352.79982 196.83856,352.9375 202.78125,352.9375 C 312.80014,352.9375 406.95049,311.61044 445.0625,253.25 L 445.0625,180.9375 L 185.09375,180.9375 z "
+       id="path3144" />
+    <path
+       sodipodi:type="arc"
+       style="opacity:1;fill:none;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:5;stroke-linecap:butt;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+       id="path3146"
+       sodipodi:cx="303.646"
+       sodipodi:cy="129.98544"
+       sodipodi:rx="0"
+       sodipodi:ry="7.2791853"
+       d="M 303.646 129.98544 A 0 7.2791853 0 1 1  303.646,129.98544 A 0 7.2791853 0 1 1  303.646 129.98544 z" />
+  </g>
+</svg>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/pygpibtoolkit/qt4/icons/led_red.svg	Tue Feb 05 18:59:29 2008 +0100
@@ -0,0 +1,144 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://web.resource.org/cc/"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:xlink="http://www.w3.org/1999/xlink"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   width="278.25241"
+   height="278.25241"
+   id="svg2"
+   sodipodi:version="0.32"
+   inkscape:version="0.45.1"
+   sodipodi:docbase="/home/david/Electronic/HP3562/icons"
+   sodipodi:docname="led_red.svg"
+   inkscape:output_extension="org.inkscape.output.svg.inkscape"
+   version="1.0">
+  <defs
+     id="defs4">
+    <linearGradient
+       inkscape:collect="always"
+       id="linearGradient4117">
+      <stop
+         style="stop-color:#ffffff;stop-opacity:1;"
+         offset="0"
+         id="stop4119" />
+      <stop
+         style="stop-color:#ffffff;stop-opacity:0;"
+         offset="1"
+         id="stop4121" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient3136">
+      <stop
+         style="stop-color:#ffffff;stop-opacity:1;"
+         offset="0"
+         id="stop3138" />
+      <stop
+         style="stop-color:#ff0000;stop-opacity:0;"
+         offset="1"
+         id="stop3140" />
+    </linearGradient>
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient3136"
+       id="radialGradient3142"
+       cx="327.41925"
+       cy="34.101982"
+       fx="327.41925"
+       fy="34.101982"
+       r="130.1324"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(2.5695707e-7,-3.2469858,2.296245,6.8708969e-6,366.91049,1504.183)" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient4117"
+       id="linearGradient4123"
+       x1="260.95242"
+       y1="121.18842"
+       x2="488.65955"
+       y2="351.48065"
+       gradientUnits="userSpaceOnUse" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient4117"
+       id="linearGradient4129"
+       gradientUnits="userSpaceOnUse"
+       x1="260.95242"
+       y1="121.18842"
+       x2="488.65955"
+       y2="351.48065"
+       gradientTransform="matrix(1.2457226,0,0,1.2615854,-176.7768,-90.496508)" />
+  </defs>
+  <sodipodi:namedview
+     id="base"
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1.0"
+     inkscape:pageopacity="0.0"
+     inkscape:pageshadow="2"
+     inkscape:zoom="0.96164611"
+     inkscape:cx="326.38382"
+     inkscape:cy="89.862869"
+     inkscape:document-units="px"
+     inkscape:current-layer="layer1"
+     inkscape:window-width="996"
+     inkscape:window-height="714"
+     inkscape:window-x="11"
+     inkscape:window-y="13" />
+  <metadata
+     id="metadata7">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+      </cc:Work>
+    </rdf:RDF>
+  </metadata>
+  <g
+     inkscape:label="Calque 1"
+     inkscape:groupmode="layer"
+     id="layer1"
+     transform="translate(-175.95852,-171.79899)">
+    <rect
+       style="opacity:1;fill:#ff0000;fill-opacity:1;fill-rule:nonzero;stroke:#ffffff;stroke-width:0.29390666;stroke-linecap:butt;stroke-miterlimit:4;stroke-dasharray:0.29390666, 0.29390666;stroke-dashoffset:0;stroke-opacity:1"
+       id="rect2160"
+       width="259.97089"
+       height="259.97089"
+       x="185.09927"
+       y="180.93974" />
+    <rect
+       y="176.38744"
+       x="180.54697"
+       height="269.0755"
+       width="269.0755"
+       id="rect2162"
+       style="opacity:1;fill:none;fill-opacity:1;fill-rule:nonzero;stroke:#ff0000;stroke-width:9.17689896;stroke-linecap:butt;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
+    <path
+       style="fill:url(#linearGradient4129);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:5;stroke-linecap:butt;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:1"
+       d="M 185.09375,180.9375 L 185.09375,352.5625 C 190.93752,352.79982 196.83856,352.9375 202.78125,352.9375 C 312.80014,352.9375 406.95049,311.61044 445.0625,253.25 L 445.0625,180.9375 L 185.09375,180.9375 z "
+       id="path3144" />
+    <path
+       sodipodi:type="arc"
+       style="opacity:1;fill:none;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:5;stroke-linecap:butt;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+       id="path3146"
+       sodipodi:cx="303.646"
+       sodipodi:cy="129.98544"
+       sodipodi:rx="0"
+       sodipodi:ry="7.2791853"
+       d="M 303.646 129.98544 A 0 7.2791853 0 1 1  303.646,129.98544 A 0 7.2791853 0 1 1  303.646 129.98544 z" />
+    <rect
+       y="180.93974"
+       x="185.09927"
+       height="259.97089"
+       width="259.97089"
+       id="rect3134"
+       style="opacity:1;fill:url(#radialGradient3142);fill-opacity:1;fill-rule:nonzero;stroke:#ffffff;stroke-width:0.29390666;stroke-linecap:butt;stroke-miterlimit:4;stroke-dasharray:0.29390666, 0.29390666;stroke-dashoffset:0;stroke-opacity:1" />
+  </g>
+</svg>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/pygpibtoolkit/qt4/icons/led_red_off.svg	Tue Feb 05 18:59:29 2008 +0100
@@ -0,0 +1,144 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://web.resource.org/cc/"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:xlink="http://www.w3.org/1999/xlink"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   width="278.2525"
+   height="278.2525"
+   id="svg2"
+   sodipodi:version="0.32"
+   inkscape:version="0.45.1"
+   sodipodi:docbase="/home/david/Electronic/HP3562/icons"
+   sodipodi:docname="led_red_off.svg"
+   inkscape:output_extension="org.inkscape.output.svg.inkscape"
+   version="1.0">
+  <defs
+     id="defs4">
+    <linearGradient
+       inkscape:collect="always"
+       id="linearGradient4117">
+      <stop
+         style="stop-color:#ffffff;stop-opacity:1;"
+         offset="0"
+         id="stop4119" />
+      <stop
+         style="stop-color:#ffffff;stop-opacity:0;"
+         offset="1"
+         id="stop4121" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient3136">
+      <stop
+         style="stop-color:#ffffff;stop-opacity:1;"
+         offset="0"
+         id="stop3138" />
+      <stop
+         style="stop-color:#aa0000;stop-opacity:0;"
+         offset="1"
+         id="stop3140" />
+    </linearGradient>
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient3136"
+       id="radialGradient3142"
+       cx="327.41925"
+       cy="34.101982"
+       fx="327.41925"
+       fy="34.101982"
+       r="130.1324"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(2.5695707e-7,-3.2469858,2.296245,6.8708969e-6,366.91049,1504.183)" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient4117"
+       id="linearGradient4123"
+       x1="260.95242"
+       y1="121.18842"
+       x2="488.65955"
+       y2="351.48065"
+       gradientUnits="userSpaceOnUse" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient4117"
+       id="linearGradient4129"
+       gradientUnits="userSpaceOnUse"
+       x1="260.95242"
+       y1="121.18842"
+       x2="488.65955"
+       y2="351.48065"
+       gradientTransform="matrix(1.2457226,0,0,1.2615854,-176.7768,-90.496508)" />
+  </defs>
+  <sodipodi:namedview
+     id="base"
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1.0"
+     inkscape:pageopacity="0.0"
+     inkscape:pageshadow="2"
+     inkscape:zoom="0.96164611"
+     inkscape:cx="326.38382"
+     inkscape:cy="69.71549"
+     inkscape:document-units="px"
+     inkscape:current-layer="layer1"
+     inkscape:window-width="996"
+     inkscape:window-height="714"
+     inkscape:window-x="11"
+     inkscape:window-y="13" />
+  <metadata
+     id="metadata7">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+      </cc:Work>
+    </rdf:RDF>
+  </metadata>
+  <g
+     inkscape:label="Calque 1"
+     inkscape:groupmode="layer"
+     id="layer1"
+     transform="translate(-175.95847,-171.79894)">
+    <rect
+       y="180.93974"
+       x="185.09927"
+       height="259.97089"
+       width="259.97089"
+       id="rect3134"
+       style="opacity:1;fill:url(#radialGradient3142);fill-opacity:1;fill-rule:nonzero;stroke:#ffffff;stroke-width:0.29390666;stroke-linecap:butt;stroke-miterlimit:4;stroke-dasharray:0.29390666, 0.29390666;stroke-dashoffset:0;stroke-opacity:1" />
+    <rect
+       style="opacity:1;fill:#a20000;fill-opacity:1;fill-rule:nonzero;stroke:#ffffff;stroke-width:0.29390666;stroke-linecap:butt;stroke-miterlimit:4;stroke-dasharray:0.29390666, 0.29390666;stroke-dashoffset:0;stroke-opacity:1"
+       id="rect2160"
+       width="259.97089"
+       height="259.97089"
+       x="185.09927"
+       y="180.93974" />
+    <rect
+       y="176.38744"
+       x="180.54697"
+       height="269.0755"
+       width="269.0755"
+       id="rect2162"
+       style="opacity:1;fill:none;fill-opacity:1;fill-rule:nonzero;stroke:#950000;stroke-width:9.17700005;stroke-linecap:butt;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
+    <path
+       style="fill:url(#linearGradient4129);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:5;stroke-linecap:butt;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:1"
+       d="M 185.09375,180.9375 L 185.09375,352.5625 C 190.93752,352.79982 196.83856,352.9375 202.78125,352.9375 C 312.80014,352.9375 406.95049,311.61044 445.0625,253.25 L 445.0625,180.9375 L 185.09375,180.9375 z "
+       id="path3144" />
+    <path
+       sodipodi:type="arc"
+       style="opacity:1;fill:none;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:5;stroke-linecap:butt;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+       id="path3146"
+       sodipodi:cx="303.646"
+       sodipodi:cy="129.98544"
+       sodipodi:rx="0"
+       sodipodi:ry="7.2791853"
+       d="M 303.646 129.98544 A 0 7.2791853 0 1 1  303.646,129.98544 A 0 7.2791853 0 1 1  303.646 129.98544 z" />
+  </g>
+</svg>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/pygpibtoolkit/qt4/qpreferences.py	Tue Feb 05 18:59:29 2008 +0100
@@ -0,0 +1,150 @@
+import os
+from PyQt4 import QtCore, QtGui, uic
+from tools import AbstractRegister 
+
+def fromVariant(v):
+    _cvrts = {0: lambda x:None,
+              1: lambda x:x.toBool(),
+              2: lambda x:x.toInt()[0],
+              6: lambda x:x.toDouble()[0],
+              10: lambda x:unicode(x.toString()),
+              12: lambda x:x.toByteArray(),
+              21: lambda x:x.toSize(),
+              22: lambda x:x.toSizeF(),
+              25: lambda x:x.toPoint(),
+              26: lambda x:x.toPointF(),
+              64: lambda x:QtGui.QFont(x),
+              67: lambda x:QtGui.QColor(x),
+              }
+    t = v.userType()
+    return _cvrts[t](v)
+
+class PreferenceMetaclass(type):
+    _widgets = {}
+    def __init__(cls, name, bases, dct):
+        # called at class creation
+        super(type, cls).__init__(name, bases, dct)
+        if name != "BaseItem":
+            ItemRegister().add(cls)
+
+class BaseItem(object):
+    #__metaclass__ = PreferenceMetaclass
+    _id = 0
+    def __init__(self, default=None, name=None, description=None, group=None):
+        self._default = default
+        self._id = BaseItem._id
+        self._name = name
+        self._description = description
+        self._group = group
+        BaseItem._id += 1
+
+    def validate(self, value):
+        return True
+    
+    def __get__(self, obj, cls):
+        if obj is None: #when called from the class, return the Item itself
+            return self
+        try:
+            return obj.getPref(self._id)
+        except Exception, e:
+            return None
+
+    def __set__(self, obj, value):
+        obj.setPref(self._id, value)
+
+class ItemRegister(AbstractRegister):
+    _registered_type = BaseItem
+    getItem = AbstractRegister.get_class
+
+class PointItem(BaseItem):
+    _type = QtCore.QPoint
+
+class SizeItem(BaseItem):
+    _type = QtCore.QSize
+
+class ByteArrayItem(BaseItem):
+    _type = QtCore.QByteArray
+    
+class UnicodeItem(BaseItem):
+    _type = unicode
+    def validate(self, value):
+        return isinstance(value, basestring)
+        
+class IntItem(BaseItem):
+    _type = int
+    def __init__(self, default=None, name=None, description=None, group=None, min=None, max=None):
+        BaseItem.__init__(self, default, name, description, group)
+        self._min = min
+        self._max = max
+
+    def validate(self, value):
+        try:
+            value = self._type(value)
+        except:
+            return False
+        if self._min is not None and value<self._min:
+            return False
+        if self._max is not None and value>self._max:
+            return False
+        return True
+
+class ColorItem(BaseItem):
+    _type = QtGui.QColor
+
+    def validate(self, value):
+        try:
+            self._type(value)
+            return True
+        except:
+            return False
+    
+class AbstractPreferences(QtCore.QObject):
+    def __init__(self):
+        QtCore.QObject.__init__(self)
+        self._settings = QtCore.QSettings(QtCore.QSettings.UserScope,
+                                          self.ORGANISATION, self.APPLICATION)
+        self._prefs = {}
+        self.groups = []
+        keys = []
+        for k in dir(self.__class__):
+            item = self.getItem(k)
+            if isinstance(item, BaseItem):
+                keys.append((k,item))
+        keys.sort(key=lambda x: x[1]._id)
+        for k, item in keys:
+            self._prefs[item._id] = k
+            if item._group not in self.groups:
+                self.groups.append(item._group)
+
+    def getItem(self, key):
+        return getattr(self.__class__, key)
+        #return self._prefs.get(key, None)
+    
+    def getPref(self, key):
+        key = self._prefs.get(key, key)
+        default = getattr(self.__class__, key)._default
+        if default is not None:
+            default = QtCore.QVariant(default)
+        else:
+            default = QtCore.QVariant()
+        val = fromVariant(self._settings.value(key, default))
+        return val
+    
+    def setPref(self, key, value):
+        key = self._prefs.get(key, key)
+        self._settings.setValue(key, QtCore.QVariant(value))
+
+    def keys(self, group=None):
+        return [k for k in self._prefs.values() if not k.startswith('_') and self.getItem(k)._group == group]
+
+    def getName(self, key):
+        item = getattr(self.__class__, key)
+        return item._name
+
+    def getDescription(self, key):
+        item = getattr(self.__class__, key)
+        return item._description
+
+    def __getitem__(self, key):
+        return getattr(self, key)
+    
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/pygpibtoolkit/qt4/qpreferences_dialog.ui	Tue Feb 05 18:59:29 2008 +0100
@@ -0,0 +1,75 @@
+<ui version="4.0" >
+ <class>PreferencesDialog</class>
+ <widget class="QDialog" name="PreferencesDialog" >
+  <property name="geometry" >
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>400</width>
+    <height>300</height>
+   </rect>
+  </property>
+  <property name="windowTitle" >
+   <string>Dialog</string>
+  </property>
+  <layout class="QVBoxLayout" >
+   <item>
+    <widget class="QTabWidget" name="centralTab" >
+     <property name="currentIndex" >
+      <number>0</number>
+     </property>
+     <widget class="QWidget" name="tab" >
+      <attribute name="title" >
+       <string>Tab 1</string>
+      </attribute>
+     </widget>
+    </widget>
+   </item>
+   <item>
+    <widget class="QDialogButtonBox" name="buttonBox" >
+     <property name="orientation" >
+      <enum>Qt::Horizontal</enum>
+     </property>
+     <property name="standardButtons" >
+      <set>QDialogButtonBox::Cancel|QDialogButtonBox::NoButton|QDialogButtonBox::Ok</set>
+     </property>
+    </widget>
+   </item>
+  </layout>
+ </widget>
+ <resources/>
+ <connections>
+  <connection>
+   <sender>buttonBox</sender>
+   <signal>accepted()</signal>
+   <receiver>PreferencesDialog</receiver>
+   <slot>accept()</slot>
+   <hints>
+    <hint type="sourcelabel" >
+     <x>248</x>
+     <y>254</y>
+    </hint>
+    <hint type="destinationlabel" >
+     <x>157</x>
+     <y>274</y>
+    </hint>
+   </hints>
+  </connection>
+  <connection>
+   <sender>buttonBox</sender>
+   <signal>rejected()</signal>
+   <receiver>PreferencesDialog</receiver>
+   <slot>reject()</slot>
+   <hints>
+    <hint type="sourcelabel" >
+     <x>316</x>
+     <y>260</y>
+    </hint>
+    <hint type="destinationlabel" >
+     <x>286</x>
+     <y>274</y>
+    </hint>
+   </hints>
+  </connection>
+ </connections>
+</ui>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/pygpibtoolkit/qt4/qpreferenceseditor.py	Tue Feb 05 18:59:29 2008 +0100
@@ -0,0 +1,231 @@
+import os
+from PyQt4 import QtCore, QtGui, uic
+from PyQt4.QtCore import Qt, SIGNAL
+import sip
+from qpreferences import fromVariant
+from qpreferences import UnicodeItem
+from tools import AbstractRegister 
+
+class WidgetMetaclass(sip.wrappertype):
+    _widgets = {}
+    def __init__(cls, name, bases, dct):
+        # called at class creation
+        super(WidgetMetaclass, cls).__init__(name, bases, dct)
+        if name != "BaseWidget":
+            WidgetRegister().add(cls)
+
+class BaseWidget(QtGui.QWidget):
+    __metaclass__ = WidgetMetaclass
+    _filter = None
+    
+class WidgetRegister(AbstractRegister):
+    _registered_type = BaseWidget
+    getWidget = AbstractRegister.get_class
+
+form_class, base_class = uic.loadUiType(os.path.join(os.path.dirname(__file__), "qpreferences_dialog.ui"))
+
+class ItemValidator(QtGui.QValidator):
+    def __init__(self, parent, item):
+        QtGui.QValidator.__init__(self, parent)
+        self._item = item
+        
+    def validate(self, value, pos):
+        value = unicode(value)
+        if value.strip() == "":
+            return (self.Intermediate, pos)
+        if self._item.validate(value):
+            return (self.Acceptable, pos)
+        return (self.Invalid, pos)
+    
+class BaseEditor(BaseWidget):
+    """
+    Basic editor for preference items. Use a QLineEdit with no
+    validation or so...
+    """
+    _accepts = "UnicodeItem"
+    def __init__(self, parent, item):
+        BaseWidget.__init__(self, parent)
+        self._item = item
+        self.setupUI()
+
+    def setValue(self, value):
+        self._editor.setText(unicode(value))
+
+    def getValue(self):
+        return unicode(self._editor.text())
+    
+    def setupUI(self):
+        self._editor = QtGui.QLineEdit(self)
+        self._validator = ItemValidator(self, self._item)
+        self._editor.setValidator(self._validator)
+        l = QtGui.QHBoxLayout(self)
+        l.setContentsMargins(0,0,0,0)
+        l.addWidget(self._editor, 1)
+        self.setFocusProxy(self._editor)
+
+class IntEditor(BaseEditor):
+    _accepts = "IntItem"
+    def setupUI(self):
+        self._editor = QtGui.QSpinBox(self)
+        self._editor.setMinimum(self._item._min)
+        self._editor.setMaximum(self._item._max)
+        l = QtGui.QHBoxLayout(self)
+        l.setContentsMargins(0,0,0,0)
+        l.addWidget(self._editor, 1)
+        self.setFocusProxy(self._editor)
+
+    def setValue(self, value):
+        self._editor.setValue(int(value))
+
+    def getValue(self):
+        return self._editor.value()
+
+class ColorEditor(BaseEditor):
+    _accepts = "ColorItem"
+    def setupUI(self):
+        self._editor_pix = QtGui.QPixmap(40,30)
+        self._editor_pix.fill(QtGui.QColor('white'))
+
+        self._editor_btn = QtGui.QPushButton("")
+        self._editor_btn.setFlat(True)
+        self._editor_btn.setFocusPolicy(Qt.NoFocus)
+        self._editor_btn.setIcon(QtGui.QIcon(self._editor_pix))
+
+        self._editor_edt = QtGui.QLineEdit()
+        self._editor_edt.setInputMask(r"\#HHHHHHhh")
+        fm = QtGui.QApplication.fontMetrics()
+        w = fm.width("#FFFFFFFF   ")
+        self._editor_edt.setMaximumWidth(w)
+
+
+        l = QtGui.QHBoxLayout(self)
+        l.setContentsMargins(0,0,0,0)
+        l.addWidget(self._editor_edt)
+        l.addWidget(self._editor_btn)
+        l.addStretch(1)
+        self.setFocusProxy(self._editor_edt)                
+        assert self.connect(self._editor_btn, SIGNAL("pressed()"),
+                            self.chooseColor)
+        assert self.connect(self._editor_edt, SIGNAL("editingFinished()"),
+                            self.colorEdited)
+        
+    def setValue(self, value):
+        if isinstance(value, tuple):
+            color = self._item._type(*value)
+        elif isinstance(value, self._item._type):
+            color = value
+        elif isinstance(value, long):
+            color = self._item._type(value)
+            alpha = value >> 24
+            color.setAlpha(alpha)
+        else:
+            color = self._item._type(value)
+            
+        rgba = color.getRgb()
+        colorname = ("#"+"%02X"*4)%rgba
+        self._rgba = rgba
+        self._editor_pix.fill(color)
+        self._editor_btn.setIcon(QtGui.QIcon(self._editor_pix))
+        self._editor_edt.setText(colorname)
+
+    def getValue(self):
+        return self._item._type(*self._rgba)
+
+    def colorEdited(self):
+        val = unicode(self._editor_edt.text())
+        if len(val) == 7:
+            val += "FF" # miss alpha channel
+        val = val[1:]
+        val = [val[2*i:2*i+2] for i in range(len(val)/2)]
+        val = [int(x, 16) for x in val]
+        
+        self._rgba = tuple(val)
+        self.setValue(self._rgba)
+                         
+        
+    def chooseColor(self):
+        newcolor, ok = QtGui.QColorDialog.getRgba(self.getValue().rgba(), self)
+        if ok:
+            self.setValue(newcolor)
+        
+class PreferencesEditor(QtGui.QDialog, form_class):
+    def __init__(self, preferences, parent=None):
+        QtGui.QDialog.__init__(self, parent)
+        self.setupUi(self)
+        self._prefs = preferences
+        self.buildUI()
+
+    def buildUI(self):
+        mainw = self.centralTab
+        for i in range(mainw.count()):
+            mainw.removeTab(0)        
+
+        eds = {}
+        self._editors = eds
+
+        wr = WidgetRegister()
+        if len(self._prefs.groups)>1:
+            for group in self._prefs.groups:
+                if group is None:
+                    continue
+                w = QtGui.QWidget(mainw)
+                mainw.addTab(w, group)
+                g = QtGui.QGridLayout(w)
+                g.setVerticalSpacing(2)
+                for i, k in enumerate(self._prefs.keys(group)):
+                    name = self._prefs.getName(k)
+                    item = self._prefs.getItem(k)
+                    if not name:
+                        name = k
+                    l = QtGui.QLabel(name, w)
+                    g.addWidget(l, i, 0)
+                    if self._prefs.getDescription(k):
+                        l.setToolTip(self._prefs.getDescription(k))
+                    wcls = wr.getWidget(item)
+                    e = wcls(w, item)
+                    eds[k] = e
+                    g.addWidget(e, i, 1)
+                    val = self._prefs.getPref(k)
+                    if val is None:
+                        val = ''
+                    e.setValue(val)
+
+                # add blank space
+                g.addWidget(QtGui.QWidget(w), i+1, 0)
+                g.setRowStretch(i+1,1)
+                g.setColumnStretch(1,1)
+
+    def accept(self):
+        p=self._prefs
+        for k in self._editors:
+            newval = self._editors[k].getValue()
+            p.setPref(k, newval)            
+        return QtGui.QDialog.accept(self)
+            
+if __name__ == '__main__':
+    from qpreferences import AbstractPreferences, UnicodeItem, IntItem, BaseItem
+    from qpreferences import ColorItem
+    class TestPreferences(AbstractPreferences):
+        ORGANISATION="Logilab"
+        APPLICATION="test_qpref_editor"
+
+        device = UnicodeItem('/dev/ttyUSB0', name="the device",
+                             group="GPIB settings")
+        address = IntItem(5, name="address",
+                          description="GPIB address of the plotter",
+                          group="GPIB settings",
+                          min=0, max=16)
+        other = UnicodeItem('toto', name="other stuff",
+                             group="General")
+        color = ColorItem(default='red',name="Colour",
+                          group="General")
+        _pos = BaseItem(None)
+        _size = BaseItem(None)
+        _appState = BaseItem(None)
+        
+    a = QtGui.QApplication([])
+
+    prefs = TestPreferences()
+    w = PreferencesEditor(prefs)
+    w.show()
+    a.exec_()
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/pygpibtoolkit/qt4/resources.qrc	Tue Feb 05 18:59:29 2008 +0100
@@ -0,0 +1,8 @@
+<RCC>
+    <qresource prefix="/" >
+        <file>icons/led_green.svg</file>
+        <file>icons/led_green_off.svg</file>
+        <file>icons/led_red.svg</file>
+        <file>icons/led_red_off.svg</file>
+    </qresource>
+</RCC>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/pygpibtoolkit/tools.py	Tue Feb 05 18:59:29 2008 +0100
@@ -0,0 +1,81 @@
+#
+"""
+Helper functions and classes
+"""
+import re
+
+def str_num_cmp(s1,s2):
+    """
+    string comparator function that will put 'toto_10' after 'toto_2'
+    Also works for strings like 'toto_1_et_23er25'.
+    """
+    r = re.compile(r'((?<=\d)\D+|(?<=\D)\d+)')
+    r1= r.split(s1)
+    r2= r.split(s2)
+    r1=[not x.isdigit() and x or int(x) for x in r1 if x!='']
+    r2=[not x.isdigit() and x or int(x) for x in r2 if x!='']
+    return cmp(r1,r2)
+
+
+class AbstractRegister(object):
+    _instance = None
+    _registered_type = None
+    def __new__(cls):
+        # implements a singleton
+        if cls._instance is None:
+            #debug('Instanciating %s', cls.__name__)
+            cls._instance = super(AbstractRegister, cls).__new__(cls)
+            cls._instance.registered = {}
+            cls._instance.accepts = set()
+        return cls._instance
+    
+    def add(self, cls):
+        assert issubclass(cls, self._registered_type)
+        if cls is self._registered_type:
+            return
+        if cls._accepts is None:
+            return
+        #assert isinstance(cls._accepts, (basestring, tuple))
+        
+        #debug("Registerered %s for %s", cls.__name__)
+        if not isinstance(cls._accepts, tuple):
+            cls._accepts = (cls._accepts,)
+        for key in cls._accepts:
+            key = self._get_typ(key)
+            #debug("  new key = %s", key)            
+            self.registered.setdefault(key, []).append(cls)
+            self.accepts.add(key)
+
+    def _get_typ(self, typ):
+        if not isinstance(typ, basestring):
+            if not isinstance(typ, type):
+                return None
+            typ = typ.__name__
+        return typ
+    
+    def __contains__(self, val):
+        val = self._get_typ(val)
+        return val in self.accepts
+
+    def get_class(self, typ):
+        item = typ
+        if not isinstance(typ, type):
+            typ = typ.__class__
+        name = typ.__name__
+        #debug("Looking a widget for %s", typ.__name__)
+        orig_typ = typ
+        while typ is not None:
+            if typ.__name__ in self.registered:
+                for w in self.registered[typ.__name__]:
+                    if w._filter is None or w._filter(item):
+                        #debug("Widget for %s is %s", typ.__name__, w)
+                        return  w#self.registered[typ.__name__]
+            if typ.__bases__:
+                typ = typ.__bases__[0]
+                if typ == object:
+                    typ = None
+                elif typ.__name__ in ("ObjectItem_", "AbstractListItem_"):
+                    typ = orig_typ._type
+            else:
+                typ = None
+        raise ValueError('No registered class for %s' % (name))
--- a/qt4/icons/led_green.svg	Mon Feb 04 19:49:48 2008 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,144 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<!-- Created with Inkscape (http://www.inkscape.org/) -->
-<svg
-   xmlns:dc="http://purl.org/dc/elements/1.1/"
-   xmlns:cc="http://web.resource.org/cc/"
-   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
-   xmlns:svg="http://www.w3.org/2000/svg"
-   xmlns="http://www.w3.org/2000/svg"
-   xmlns:xlink="http://www.w3.org/1999/xlink"
-   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
-   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
-   width="278.25241"
-   height="278.25241"
-   id="svg2"
-   sodipodi:version="0.32"
-   inkscape:version="0.45.1"
-   sodipodi:docbase="/home/david/Electronic/HP3562/icons"
-   sodipodi:docname="led_green.svg"
-   inkscape:output_extension="org.inkscape.output.svg.inkscape"
-   version="1.0">
-  <defs
-     id="defs4">
-    <linearGradient
-       inkscape:collect="always"
-       id="linearGradient4117">
-      <stop
-         style="stop-color:#ffffff;stop-opacity:1;"
-         offset="0"
-         id="stop4119" />
-      <stop
-         style="stop-color:#ffffff;stop-opacity:0;"
-         offset="1"
-         id="stop4121" />
-    </linearGradient>
-    <linearGradient
-       id="linearGradient3136">
-      <stop
-         style="stop-color:#ffffff;stop-opacity:1;"
-         offset="0"
-         id="stop3138" />
-      <stop
-         style="stop-color:#00ff00;stop-opacity:0;"
-         offset="1"
-         id="stop3140" />
-    </linearGradient>
-    <radialGradient
-       inkscape:collect="always"
-       xlink:href="#linearGradient3136"
-       id="radialGradient3142"
-       cx="327.41925"
-       cy="34.101982"
-       fx="327.41925"
-       fy="34.101982"
-       r="130.1324"
-       gradientUnits="userSpaceOnUse"
-       gradientTransform="matrix(2.5695707e-7,-3.2469858,2.296245,6.8708969e-6,366.91049,1504.183)" />
-    <linearGradient
-       inkscape:collect="always"
-       xlink:href="#linearGradient4117"
-       id="linearGradient4123"
-       x1="260.95242"
-       y1="121.18842"
-       x2="488.65955"
-       y2="351.48065"
-       gradientUnits="userSpaceOnUse" />
-    <linearGradient
-       inkscape:collect="always"
-       xlink:href="#linearGradient4117"
-       id="linearGradient4129"
-       gradientUnits="userSpaceOnUse"
-       x1="260.95242"
-       y1="121.18842"
-       x2="488.65955"
-       y2="351.48065"
-       gradientTransform="matrix(1.2457226,0,0,1.2615854,-176.7768,-90.496508)" />
-  </defs>
-  <sodipodi:namedview
-     id="base"
-     pagecolor="#ffffff"
-     bordercolor="#666666"
-     borderopacity="1.0"
-     inkscape:pageopacity="0.0"
-     inkscape:pageshadow="2"
-     inkscape:zoom="0.48082306"
-     inkscape:cx="372.04724"
-     inkscape:cy="207.1213"
-     inkscape:document-units="px"
-     inkscape:current-layer="layer1"
-     inkscape:window-width="996"
-     inkscape:window-height="714"
-     inkscape:window-x="25"
-     inkscape:window-y="4" />
-  <metadata
-     id="metadata7">
-    <rdf:RDF>
-      <cc:Work
-         rdf:about="">
-        <dc:format>image/svg+xml</dc:format>
-        <dc:type
-           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
-      </cc:Work>
-    </rdf:RDF>
-  </metadata>
-  <g
-     inkscape:label="Calque 1"
-     inkscape:groupmode="layer"
-     id="layer1"
-     transform="translate(-175.95852,-171.79899)">
-    <rect
-       style="opacity:1;fill:#00ff00;fill-opacity:1;fill-rule:nonzero;stroke:#ffffff;stroke-width:0.29390666;stroke-linecap:butt;stroke-miterlimit:4;stroke-dasharray:0.29390666, 0.29390666;stroke-dashoffset:0;stroke-opacity:1"
-       id="rect2160"
-       width="259.97089"
-       height="259.97089"
-       x="185.09927"
-       y="180.93974" />
-    <rect
-       y="176.38744"
-       x="180.54697"
-       height="269.0755"
-       width="269.0755"
-       id="rect2162"
-       style="opacity:1;fill:none;fill-opacity:1;fill-rule:nonzero;stroke:#00c40b;stroke-width:9.17689896;stroke-linecap:butt;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
-    <rect
-       y="180.93974"
-       x="185.09927"
-       height="259.97089"
-       width="259.97089"
-       id="rect3134"
-       style="opacity:1;fill:url(#radialGradient3142);fill-opacity:1;fill-rule:nonzero;stroke:#ffffff;stroke-width:0.29390666;stroke-linecap:butt;stroke-miterlimit:4;stroke-dasharray:0.29390666, 0.29390666;stroke-dashoffset:0;stroke-opacity:1" />
-    <path
-       style="fill:url(#linearGradient4129);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:5;stroke-linecap:butt;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:1"
-       d="M 185.09375,180.9375 L 185.09375,352.5625 C 190.93752,352.79982 196.83856,352.9375 202.78125,352.9375 C 312.80014,352.9375 406.95049,311.61044 445.0625,253.25 L 445.0625,180.9375 L 185.09375,180.9375 z "
-       id="path3144" />
-    <path
-       sodipodi:type="arc"
-       style="opacity:1;fill:none;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:5;stroke-linecap:butt;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
-       id="path3146"
-       sodipodi:cx="303.646"
-       sodipodi:cy="129.98544"
-       sodipodi:rx="0"
-       sodipodi:ry="7.2791853"
-       d="M 303.646 129.98544 A 0 7.2791853 0 1 1  303.646,129.98544 A 0 7.2791853 0 1 1  303.646 129.98544 z" />
-  </g>
-</svg>
--- a/qt4/icons/led_green_off.svg	Mon Feb 04 19:49:48 2008 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,116 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<!-- Created with Inkscape (http://www.inkscape.org/) -->
-<svg
-   xmlns:dc="http://purl.org/dc/elements/1.1/"
-   xmlns:cc="http://web.resource.org/cc/"
-   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
-   xmlns:svg="http://www.w3.org/2000/svg"
-   xmlns="http://www.w3.org/2000/svg"
-   xmlns:xlink="http://www.w3.org/1999/xlink"
-   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
-   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
-   width="278.25241"
-   height="278.25241"
-   id="svg2"
-   sodipodi:version="0.32"
-   inkscape:version="0.45.1"
-   sodipodi:docbase="/home/david/Electronic/HP3562/icons"
-   sodipodi:docname="led_green_off.svg"
-   inkscape:output_extension="org.inkscape.output.svg.inkscape"
-   version="1.0">
-  <defs
-     id="defs4">
-    <linearGradient
-       id="linearGradient4117">
-      <stop
-         style="stop-color:#acacac;stop-opacity:0.68783069;"
-         offset="0"
-         id="stop4119" />
-      <stop
-         style="stop-color:#ffffff;stop-opacity:0;"
-         offset="1"
-         id="stop4121" />
-    </linearGradient>
-    <linearGradient
-       id="linearGradient3136">
-      <stop
-         style="stop-color:#ffffff;stop-opacity:1;"
-         offset="0"
-         id="stop3138" />
-      <stop
-         style="stop-color:#00ff00;stop-opacity:0;"
-         offset="1"
-         id="stop3140" />
-    </linearGradient>
-    <linearGradient
-       inkscape:collect="always"
-       xlink:href="#linearGradient4117"
-       id="linearGradient4129"
-       gradientUnits="userSpaceOnUse"
-       x1="260.95242"
-       y1="121.18842"
-       x2="488.65955"
-       y2="351.48065"
-       gradientTransform="matrix(1.2457226,0,0,1.2615854,-176.7768,-90.496508)" />
-  </defs>
-  <sodipodi:namedview
-     id="base"
-     pagecolor="#ffffff"
-     bordercolor="#666666"
-     borderopacity="1.0"
-     inkscape:pageopacity="0.0"
-     inkscape:pageshadow="2"
-     inkscape:zoom="0.48082306"
-     inkscape:cx="372.04724"
-     inkscape:cy="-64.793696"
-     inkscape:document-units="px"
-     inkscape:current-layer="layer1"
-     inkscape:window-width="996"
-     inkscape:window-height="714"
-     inkscape:window-x="22"
-     inkscape:window-y="21" />
-  <metadata
-     id="metadata7">
-    <rdf:RDF>
-      <cc:Work
-         rdf:about="">
-        <dc:format>image/svg+xml</dc:format>
-        <dc:type
-           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
-      </cc:Work>
-    </rdf:RDF>
-  </metadata>
-  <g
-     inkscape:label="Calque 1"
-     inkscape:groupmode="layer"
-     id="layer1"
-     transform="translate(-175.95852,-171.79899)">
-    <rect
-       style="opacity:1;fill:#009900;fill-opacity:1;fill-rule:nonzero;stroke:#ffffff;stroke-width:0.29390666;stroke-linecap:butt;stroke-miterlimit:4;stroke-dasharray:0.29390666, 0.29390666;stroke-dashoffset:0;stroke-opacity:1"
-       id="rect2160"
-       width="259.97089"
-       height="259.97089"
-       x="185.09927"
-       y="180.93974" />
-    <rect
-       y="176.38744"
-       x="180.54697"
-       height="269.0755"
-       width="269.0755"
-       id="rect2162"
-       style="opacity:1;fill:none;fill-opacity:1;fill-rule:nonzero;stroke:#008304;stroke-width:9.17689896;stroke-linecap:butt;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
-    <path
-       style="fill:url(#linearGradient4129);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:5;stroke-linecap:butt;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:1"
-       d="M 185.09375,180.9375 L 185.09375,352.5625 C 190.93752,352.79982 196.83856,352.9375 202.78125,352.9375 C 312.80014,352.9375 406.95049,311.61044 445.0625,253.25 L 445.0625,180.9375 L 185.09375,180.9375 z "
-       id="path3144" />
-    <path
-       sodipodi:type="arc"
-       style="opacity:1;fill:none;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:5;stroke-linecap:butt;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
-       id="path3146"
-       sodipodi:cx="303.646"
-       sodipodi:cy="129.98544"
-       sodipodi:rx="0"
-       sodipodi:ry="7.2791853"
-       d="M 303.646 129.98544 A 0 7.2791853 0 1 1  303.646,129.98544 A 0 7.2791853 0 1 1  303.646 129.98544 z" />
-  </g>
-</svg>
--- a/qt4/icons/led_red.svg	Mon Feb 04 19:49:48 2008 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,144 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<!-- Created with Inkscape (http://www.inkscape.org/) -->
-<svg
-   xmlns:dc="http://purl.org/dc/elements/1.1/"
-   xmlns:cc="http://web.resource.org/cc/"
-   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
-   xmlns:svg="http://www.w3.org/2000/svg"
-   xmlns="http://www.w3.org/2000/svg"
-   xmlns:xlink="http://www.w3.org/1999/xlink"
-   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
-   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
-   width="278.25241"
-   height="278.25241"
-   id="svg2"
-   sodipodi:version="0.32"
-   inkscape:version="0.45.1"
-   sodipodi:docbase="/home/david/Electronic/HP3562/icons"
-   sodipodi:docname="led_red.svg"
-   inkscape:output_extension="org.inkscape.output.svg.inkscape"
-   version="1.0">
-  <defs
-     id="defs4">
-    <linearGradient
-       inkscape:collect="always"
-       id="linearGradient4117">
-      <stop
-         style="stop-color:#ffffff;stop-opacity:1;"
-         offset="0"
-         id="stop4119" />
-      <stop
-         style="stop-color:#ffffff;stop-opacity:0;"
-         offset="1"
-         id="stop4121" />
-    </linearGradient>
-    <linearGradient
-       id="linearGradient3136">
-      <stop
-         style="stop-color:#ffffff;stop-opacity:1;"
-         offset="0"
-         id="stop3138" />
-      <stop
-         style="stop-color:#ff0000;stop-opacity:0;"
-         offset="1"
-         id="stop3140" />
-    </linearGradient>
-    <radialGradient
-       inkscape:collect="always"
-       xlink:href="#linearGradient3136"
-       id="radialGradient3142"
-       cx="327.41925"
-       cy="34.101982"
-       fx="327.41925"
-       fy="34.101982"
-       r="130.1324"
-       gradientUnits="userSpaceOnUse"
-       gradientTransform="matrix(2.5695707e-7,-3.2469858,2.296245,6.8708969e-6,366.91049,1504.183)" />
-    <linearGradient
-       inkscape:collect="always"
-       xlink:href="#linearGradient4117"
-       id="linearGradient4123"
-       x1="260.95242"
-       y1="121.18842"
-       x2="488.65955"
-       y2="351.48065"
-       gradientUnits="userSpaceOnUse" />
-    <linearGradient
-       inkscape:collect="always"
-       xlink:href="#linearGradient4117"
-       id="linearGradient4129"
-       gradientUnits="userSpaceOnUse"
-       x1="260.95242"
-       y1="121.18842"
-       x2="488.65955"
-       y2="351.48065"
-       gradientTransform="matrix(1.2457226,0,0,1.2615854,-176.7768,-90.496508)" />
-  </defs>
-  <sodipodi:namedview
-     id="base"
-     pagecolor="#ffffff"
-     bordercolor="#666666"
-     borderopacity="1.0"
-     inkscape:pageopacity="0.0"
-     inkscape:pageshadow="2"
-     inkscape:zoom="0.96164611"
-     inkscape:cx="326.38382"
-     inkscape:cy="89.862869"
-     inkscape:document-units="px"
-     inkscape:current-layer="layer1"
-     inkscape:window-width="996"
-     inkscape:window-height="714"
-     inkscape:window-x="11"
-     inkscape:window-y="13" />
-  <metadata
-     id="metadata7">
-    <rdf:RDF>
-      <cc:Work
-         rdf:about="">
-        <dc:format>image/svg+xml</dc:format>
-        <dc:type
-           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
-      </cc:Work>
-    </rdf:RDF>
-  </metadata>
-  <g
-     inkscape:label="Calque 1"
-     inkscape:groupmode="layer"
-     id="layer1"
-     transform="translate(-175.95852,-171.79899)">
-    <rect
-       style="opacity:1;fill:#ff0000;fill-opacity:1;fill-rule:nonzero;stroke:#ffffff;stroke-width:0.29390666;stroke-linecap:butt;stroke-miterlimit:4;stroke-dasharray:0.29390666, 0.29390666;stroke-dashoffset:0;stroke-opacity:1"
-       id="rect2160"
-       width="259.97089"
-       height="259.97089"
-       x="185.09927"
-       y="180.93974" />
-    <rect
-       y="176.38744"
-       x="180.54697"
-       height="269.0755"
-       width="269.0755"
-       id="rect2162"
-       style="opacity:1;fill:none;fill-opacity:1;fill-rule:nonzero;stroke:#ff0000;stroke-width:9.17689896;stroke-linecap:butt;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
-    <path
-       style="fill:url(#linearGradient4129);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:5;stroke-linecap:butt;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:1"
-       d="M 185.09375,180.9375 L 185.09375,352.5625 C 190.93752,352.79982 196.83856,352.9375 202.78125,352.9375 C 312.80014,352.9375 406.95049,311.61044 445.0625,253.25 L 445.0625,180.9375 L 185.09375,180.9375 z "
-       id="path3144" />
-    <path
-       sodipodi:type="arc"
-       style="opacity:1;fill:none;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:5;stroke-linecap:butt;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
-       id="path3146"
-       sodipodi:cx="303.646"
-       sodipodi:cy="129.98544"
-       sodipodi:rx="0"
-       sodipodi:ry="7.2791853"
-       d="M 303.646 129.98544 A 0 7.2791853 0 1 1  303.646,129.98544 A 0 7.2791853 0 1 1  303.646 129.98544 z" />
-    <rect
-       y="180.93974"
-       x="185.09927"
-       height="259.97089"
-       width="259.97089"
-       id="rect3134"
-       style="opacity:1;fill:url(#radialGradient3142);fill-opacity:1;fill-rule:nonzero;stroke:#ffffff;stroke-width:0.29390666;stroke-linecap:butt;stroke-miterlimit:4;stroke-dasharray:0.29390666, 0.29390666;stroke-dashoffset:0;stroke-opacity:1" />
-  </g>
-</svg>
--- a/qt4/icons/led_red_off.svg	Mon Feb 04 19:49:48 2008 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,144 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<!-- Created with Inkscape (http://www.inkscape.org/) -->
-<svg
-   xmlns:dc="http://purl.org/dc/elements/1.1/"
-   xmlns:cc="http://web.resource.org/cc/"
-   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
-   xmlns:svg="http://www.w3.org/2000/svg"
-   xmlns="http://www.w3.org/2000/svg"
-   xmlns:xlink="http://www.w3.org/1999/xlink"
-   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
-   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
-   width="278.2525"
-   height="278.2525"
-   id="svg2"
-   sodipodi:version="0.32"
-   inkscape:version="0.45.1"
-   sodipodi:docbase="/home/david/Electronic/HP3562/icons"
-   sodipodi:docname="led_red_off.svg"
-   inkscape:output_extension="org.inkscape.output.svg.inkscape"
-   version="1.0">
-  <defs
-     id="defs4">
-    <linearGradient
-       inkscape:collect="always"
-       id="linearGradient4117">
-      <stop
-         style="stop-color:#ffffff;stop-opacity:1;"
-         offset="0"
-         id="stop4119" />
-      <stop
-         style="stop-color:#ffffff;stop-opacity:0;"
-         offset="1"
-         id="stop4121" />
-    </linearGradient>
-    <linearGradient
-       id="linearGradient3136">
-      <stop
-         style="stop-color:#ffffff;stop-opacity:1;"
-         offset="0"
-         id="stop3138" />
-      <stop
-         style="stop-color:#aa0000;stop-opacity:0;"
-         offset="1"
-         id="stop3140" />
-    </linearGradient>
-    <radialGradient
-       inkscape:collect="always"
-       xlink:href="#linearGradient3136"
-       id="radialGradient3142"
-       cx="327.41925"
-       cy="34.101982"
-       fx="327.41925"
-       fy="34.101982"
-       r="130.1324"
-       gradientUnits="userSpaceOnUse"
-       gradientTransform="matrix(2.5695707e-7,-3.2469858,2.296245,6.8708969e-6,366.91049,1504.183)" />
-    <linearGradient
-       inkscape:collect="always"
-       xlink:href="#linearGradient4117"
-       id="linearGradient4123"
-       x1="260.95242"
-       y1="121.18842"
-       x2="488.65955"
-       y2="351.48065"
-       gradientUnits="userSpaceOnUse" />
-    <linearGradient
-       inkscape:collect="always"
-       xlink:href="#linearGradient4117"
-       id="linearGradient4129"
-       gradientUnits="userSpaceOnUse"
-       x1="260.95242"
-       y1="121.18842"
-       x2="488.65955"
-       y2="351.48065"
-       gradientTransform="matrix(1.2457226,0,0,1.2615854,-176.7768,-90.496508)" />
-  </defs>
-  <sodipodi:namedview
-     id="base"
-     pagecolor="#ffffff"
-     bordercolor="#666666"
-     borderopacity="1.0"
-     inkscape:pageopacity="0.0"
-     inkscape:pageshadow="2"
-     inkscape:zoom="0.96164611"
-     inkscape:cx="326.38382"
-     inkscape:cy="69.71549"
-     inkscape:document-units="px"
-     inkscape:current-layer="layer1"
-     inkscape:window-width="996"
-     inkscape:window-height="714"
-     inkscape:window-x="11"
-     inkscape:window-y="13" />
-  <metadata
-     id="metadata7">
-    <rdf:RDF>
-      <cc:Work
-         rdf:about="">
-        <dc:format>image/svg+xml</dc:format>
-        <dc:type
-           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
-      </cc:Work>
-    </rdf:RDF>
-  </metadata>
-  <g
-     inkscape:label="Calque 1"
-     inkscape:groupmode="layer"
-     id="layer1"
-     transform="translate(-175.95847,-171.79894)">
-    <rect
-       y="180.93974"
-       x="185.09927"
-       height="259.97089"
-       width="259.97089"
-       id="rect3134"
-       style="opacity:1;fill:url(#radialGradient3142);fill-opacity:1;fill-rule:nonzero;stroke:#ffffff;stroke-width:0.29390666;stroke-linecap:butt;stroke-miterlimit:4;stroke-dasharray:0.29390666, 0.29390666;stroke-dashoffset:0;stroke-opacity:1" />
-    <rect
-       style="opacity:1;fill:#a20000;fill-opacity:1;fill-rule:nonzero;stroke:#ffffff;stroke-width:0.29390666;stroke-linecap:butt;stroke-miterlimit:4;stroke-dasharray:0.29390666, 0.29390666;stroke-dashoffset:0;stroke-opacity:1"
-       id="rect2160"
-       width="259.97089"
-       height="259.97089"
-       x="185.09927"
-       y="180.93974" />
-    <rect
-       y="176.38744"
-       x="180.54697"
-       height="269.0755"
-       width="269.0755"
-       id="rect2162"
-       style="opacity:1;fill:none;fill-opacity:1;fill-rule:nonzero;stroke:#950000;stroke-width:9.17700005;stroke-linecap:butt;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
-    <path
-       style="fill:url(#linearGradient4129);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:5;stroke-linecap:butt;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:1"
-       d="M 185.09375,180.9375 L 185.09375,352.5625 C 190.93752,352.79982 196.83856,352.9375 202.78125,352.9375 C 312.80014,352.9375 406.95049,311.61044 445.0625,253.25 L 445.0625,180.9375 L 185.09375,180.9375 z "
-       id="path3144" />
-    <path
-       sodipodi:type="arc"
-       style="opacity:1;fill:none;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:5;stroke-linecap:butt;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
-       id="path3146"
-       sodipodi:cx="303.646"
-       sodipodi:cy="129.98544"
-       sodipodi:rx="0"
-       sodipodi:ry="7.2791853"
-       d="M 303.646 129.98544 A 0 7.2791853 0 1 1  303.646,129.98544 A 0 7.2791853 0 1 1  303.646 129.98544 z" />
-  </g>
-</svg>
--- a/qt4/qpreferences.py	Mon Feb 04 19:49:48 2008 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,150 +0,0 @@
-import os
-from PyQt4 import QtCore, QtGui, uic
-from tools import AbstractRegister 
-
-def fromVariant(v):
-    _cvrts = {0: lambda x:None,
-              1: lambda x:x.toBool(),
-              2: lambda x:x.toInt()[0],
-              6: lambda x:x.toDouble()[0],
-              10: lambda x:unicode(x.toString()),
-              12: lambda x:x.toByteArray(),
-              21: lambda x:x.toSize(),
-              22: lambda x:x.toSizeF(),
-              25: lambda x:x.toPoint(),
-              26: lambda x:x.toPointF(),
-              64: lambda x:QtGui.QFont(x),
-              67: lambda x:QtGui.QColor(x),
-              }
-    t = v.userType()
-    return _cvrts[t](v)
-
-class PreferenceMetaclass(type):
-    _widgets = {}
-    def __init__(cls, name, bases, dct):
-        # called at class creation
-        super(type, cls).__init__(name, bases, dct)
-        if name != "BaseItem":
-            ItemRegister().add(cls)
-
-class BaseItem(object):
-    #__metaclass__ = PreferenceMetaclass
-    _id = 0
-    def __init__(self, default=None, name=None, description=None, group=None):
-        self._default = default
-        self._id = BaseItem._id
-        self._name = name
-        self._description = description
-        self._group = group
-        BaseItem._id += 1
-
-    def validate(self, value):
-        return True
-    
-    def __get__(self, obj, cls):
-        if obj is None: #when called from the class, return the Item itself
-            return self
-        try:
-            return obj.getPref(self._id)
-        except Exception, e:
-            return None
-
-    def __set__(self, obj, value):
-        obj.setPref(self._id, value)
-
-class ItemRegister(AbstractRegister):
-    _registered_type = BaseItem
-    getItem = AbstractRegister.get_class
-
-class PointItem(BaseItem):
-    _type = QtCore.QPoint
-
-class SizeItem(BaseItem):
-    _type = QtCore.QSize
-
-class ByteArrayItem(BaseItem):
-    _type = QtCore.QByteArray
-    
-class UnicodeItem(BaseItem):
-    _type = unicode
-    def validate(self, value):
-        return isinstance(value, basestring)
-        
-class IntItem(BaseItem):
-    _type = int
-    def __init__(self, default=None, name=None, description=None, group=None, min=None, max=None):
-        BaseItem.__init__(self, default, name, description, group)
-        self._min = min
-        self._max = max
-
-    def validate(self, value):
-        try:
-            value = self._type(value)
-        except:
-            return False
-        if self._min is not None and value<self._min:
-            return False
-        if self._max is not None and value>self._max:
-            return False
-        return True
-
-class ColorItem(BaseItem):
-    _type = QtGui.QColor
-
-    def validate(self, value):
-        try:
-            self._type(value)
-            return True
-        except:
-            return False
-    
-class AbstractPreferences(QtCore.QObject):
-    def __init__(self):
-        QtCore.QObject.__init__(self)
-        self._settings = QtCore.QSettings(QtCore.QSettings.UserScope,
-                                          self.ORGANISATION, self.APPLICATION)
-        self._prefs = {}
-        self.groups = []
-        keys = []
-        for k in dir(self.__class__):
-            item = self.getItem(k)
-            if isinstance(item, BaseItem):
-                keys.append((k,item))
-        keys.sort(key=lambda x: x[1]._id)
-        for k, item in keys:
-            self._prefs[item._id] = k
-            if item._group not in self.groups:
-                self.groups.append(item._group)
-
-    def getItem(self, key):
-        return getattr(self.__class__, key)
-        #return self._prefs.get(key, None)
-    
-    def getPref(self, key):
-        key = self._prefs.get(key, key)
-        default = getattr(self.__class__, key)._default
-        if default is not None:
-            default = QtCore.QVariant(default)
-        else:
-            default = QtCore.QVariant()
-        val = fromVariant(self._settings.value(key, default))
-        return val
-    
-    def setPref(self, key, value):
-        key = self._prefs.get(key, key)
-        self._settings.setValue(key, QtCore.QVariant(value))
-
-    def keys(self, group=None):
-        return [k for k in self._prefs.values() if not k.startswith('_') and self.getItem(k)._group == group]
-
-    def getName(self, key):
-        item = getattr(self.__class__, key)
-        return item._name
-
-    def getDescription(self, key):
-        item = getattr(self.__class__, key)
-        return item._description
-
-    def __getitem__(self, key):
-        return getattr(self, key)
-    
--- a/qt4/qpreferences_dialog.ui	Mon Feb 04 19:49:48 2008 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,75 +0,0 @@
-<ui version="4.0" >
- <class>PreferencesDialog</class>
- <widget class="QDialog" name="PreferencesDialog" >
-  <property name="geometry" >
-   <rect>
-    <x>0</x>
-    <y>0</y>
-    <width>400</width>
-    <height>300</height>
-   </rect>
-  </property>
-  <property name="windowTitle" >
-   <string>Dialog</string>
-  </property>
-  <layout class="QVBoxLayout" >
-   <item>
-    <widget class="QTabWidget" name="centralTab" >
-     <property name="currentIndex" >
-      <number>0</number>
-     </property>
-     <widget class="QWidget" name="tab" >
-      <attribute name="title" >
-       <string>Tab 1</string>
-      </attribute>
-     </widget>
-    </widget>
-   </item>
-   <item>
-    <widget class="QDialogButtonBox" name="buttonBox" >
-     <property name="orientation" >
-      <enum>Qt::Horizontal</enum>
-     </property>
-     <property name="standardButtons" >
-      <set>QDialogButtonBox::Cancel|QDialogButtonBox::NoButton|QDialogButtonBox::Ok</set>
-     </property>
-    </widget>
-   </item>
-  </layout>
- </widget>
- <resources/>
- <connections>
-  <connection>
-   <sender>buttonBox</sender>
-   <signal>accepted()</signal>
-   <receiver>PreferencesDialog</receiver>
-   <slot>accept()</slot>
-   <hints>
-    <hint type="sourcelabel" >
-     <x>248</x>
-     <y>254</y>
-    </hint>
-    <hint type="destinationlabel" >
-     <x>157</x>
-     <y>274</y>
-    </hint>
-   </hints>
-  </connection>
-  <connection>
-   <sender>buttonBox</sender>
-   <signal>rejected()</signal>
-   <receiver>PreferencesDialog</receiver>
-   <slot>reject()</slot>
-   <hints>
-    <hint type="sourcelabel" >
-     <x>316</x>
-     <y>260</y>
-    </hint>
-    <hint type="destinationlabel" >
-     <x>286</x>
-     <y>274</y>
-    </hint>
-   </hints>
-  </connection>
- </connections>
-</ui>
--- a/qt4/resources.qrc	Mon Feb 04 19:49:48 2008 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,8 +0,0 @@
-<RCC>
-    <qresource prefix="/" >
-        <file>icons/led_green.svg</file>
-        <file>icons/led_green_off.svg</file>
-        <file>icons/led_red.svg</file>
-        <file>icons/led_red_off.svg</file>
-    </qresource>
-</RCC>
--- a/tools.py	Mon Feb 04 19:49:48 2008 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,81 +0,0 @@
-#
-"""
-Helper functions and classes
-"""
-import re
-
-def str_num_cmp(s1,s2):
-    """
-    string comparator function that will put 'toto_10' after 'toto_2'
-    Also works for strings like 'toto_1_et_23er25'.
-    """
-    r = re.compile(r'((?<=\d)\D+|(?<=\D)\d+)')
-    r1= r.split(s1)
-    r2= r.split(s2)
-    r1=[not x.isdigit() and x or int(x) for x in r1 if x!='']
-    r2=[not x.isdigit() and x or int(x) for x in r2 if x!='']
-    return cmp(r1,r2)
-
-
-class AbstractRegister(object):
-    _instance = None
-    _registered_type = None
-    def __new__(cls):
-        # implements a singleton
-        if cls._instance is None:
-            #debug('Instanciating %s', cls.__name__)
-            cls._instance = super(AbstractRegister, cls).__new__(cls)
-            cls._instance.registered = {}
-            cls._instance.accepts = set()
-        return cls._instance
-    
-    def add(self, cls):
-        assert issubclass(cls, self._registered_type)
-        if cls is self._registered_type:
-            return
-        if cls._accepts is None:
-            return
-        #assert isinstance(cls._accepts, (basestring, tuple))
-        
-        #debug("Registerered %s for %s", cls.__name__)
-        if not isinstance(cls._accepts, tuple):
-            cls._accepts = (cls._accepts,)
-        for key in cls._accepts:
-            key = self._get_typ(key)
-            #debug("  new key = %s", key)            
-            self.registered.setdefault(key, []).append(cls)
-            self.accepts.add(key)
-
-    def _get_typ(self, typ):
-        if not isinstance(typ, basestring):
-            if not isinstance(typ, type):
-                return None
-            typ = typ.__name__
-        return typ
-    
-    def __contains__(self, val):
-        val = self._get_typ(val)
-        return val in self.accepts
-
-    def get_class(self, typ):
-        item = typ
-        if not isinstance(typ, type):
-            typ = typ.__class__
-        name = typ.__name__
-        #debug("Looking a widget for %s", typ.__name__)
-        orig_typ = typ
-        while typ is not None:
-            if typ.__name__ in self.registered:
-                for w in self.registered[typ.__name__]:
-                    if w._filter is None or w._filter(item):
-                        #debug("Widget for %s is %s", typ.__name__, w)
-                        return  w#self.registered[typ.__name__]
-            if typ.__bases__:
-                typ = typ.__bases__[0]
-                if typ == object:
-                    typ = None
-                elif typ.__name__ in ("ObjectItem_", "AbstractListItem_"):
-                    typ = orig_typ._type
-            else:
-                typ = None
-        raise ValueError('No registered class for %s' % (name))

mercurial