📄 ladder.py
字号:
#!/usr/bin/env python# -*- Mode: Python; tab-width: 4 -*-## Copyright (C) 2001 Gianluigi Tiesi <sherpya@netfarm.it>## This program is free software; you can redistribute it and/or modify# it under the terms of the GNU General Public License as published by the# Free Software Foundation; either version 2, or (at your option) any later# version.## This program is distributed in the hope that it will be useful, but# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License# for more details.## Ranking patch by <JEBs@shbe.net> 20020503# Small "unsigned int" fix by <JEBs@shbe.net> 20020818## ==========================================================================__version__ = "0.9"### Only if CGI_MODE = 1CGI_MODE=0FILE="/opt/bnetd/var/ladders/ladder.D2DV"MAX=100from struct import unpack,calcsizefrom string import find,split,joinfrom os import statfrom sys import argv,exit,stdoutfrom getopt import getopt#### Templatesmodes = [ 'html', 'ansi', 'ascii', 'python' ]templates = {}for m in modes: templates[m] = {} ### html ####templates['html']['header']="""<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"><html> <head> <title>D2 Closed Realm Ladder</title> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> </head> <body bgcolor="#000000" text="#ffff00"> <h2 style="color: lightgreen;" align="center">D2 Closed Realm Ladder</h2> <table style="border: solid lightblue; border-width: 1px;" align="center" border="0" width="80%" summary="">"""#templates['html']['footer']=""" </table> <p style="color: lightblue;" align="center">Generated by ladder.py v %s - © 2001 <a style="color: lightgreen;" href="mailto:sherpya@netfarm.it">Sherpya</a></p> </body></html>""" % __version__# %s for description of ladder typetemplates['html']['summary'] = """ <tr style="color: lightblue" bgcolor="#666666"><th colspan="5">Ladder for %s</th></tr>"""#templates['html']['tbheader'] = """<tr style="color: lightgreen;"><th align="center">#</th><th align="left">Charname</th><th align="right">level</th><th align="center">class</th><th align="right">exp</th></tr>"""# %s for charnametemplates['html']['normal'] = """%s"""templates['html']['hardcore'] = { 0 : """<span style="color: red;">%s</span>""", 1 : """<span style="color: orange;">%s</span>""" }# %s charname - %d level - %s class - %d experiencetemplates['html']['entry'] = """<tr bgcolor="#222222"><td align="right">%d</td><td align="left">%s</td><td align="right">%d</td><td align="center">%s</td><td align="right">%d</td></tr>"""#templates['html']['separator'] = """<tr><td colspan="5"> </td></tr>"""#### html#### ascii / ansiline = '-' * 59 + '\n's10 = ' ' * 10s14 = ' ' * 14s5 = ' ' * 5text = 'D2 Closed Ladder'esc = '\033'off = esc + '[0m'colors = { 'grey': esc + '[1;30m', 'red': esc + '[1;31m', 'green': esc + '[1;32m', 'yellow': esc + '[1;33m', 'blue': esc + '[1;34m', 'purple': esc + '[1;35m', 'magenta': esc + '[1;36m', 'white': esc + '[1;37m', 'green': esc + '[1;32m' }templates['ascii']['header'] = line + (int((len(line) - len(text))/ 2)) * ' ' + text + '\n' + linetemplates['ascii']['footer'] = 'generated by ladder.py (c) Sherpya [sherpya@netfarm.it]\n'templates['ascii']['summary'] = 'Ladder for %s\n\n'templates['ascii']['tbheader'] = ' # charname' + s14 + 'level' + s10 + 'class' + s10 + 'exp' + '\n\n'templates['ascii']['normal'] = '%s'templates['ascii']['hardcore'] = { 0 : '*%s', 1: '^%s' }templates['ascii']['entry'] = '%3d %-23s %2d %16s %10d\n'templates['ascii']['separator'] = line + '\n'line = colors['blue'] + ( '-' * 59) + off + '\n'templates['ansi']['header'] = line + (int((len(line) - len(text) - 10)/ 2)) * ' ' + colors['green'] + text + off + '\n' + linetemplates['ansi']['footer'] = colors['green'] + 'generated by ' + colors['blue'] + 'ladder.py' + colors['green'] + ' (c) Sherpya [sherpya@netfarm.it]' + off + '\n'templates['ansi']['summary'] = colors['white'] + 'Ladder for %s' + off + '\n\n'templates['ansi']['tbheader'] = colors['green'] + ' # charname' + s14 + 'level' + s10 + 'class' + s10 + 'exp' + off + '\n\n'templates['ansi']['normal'] = colors['yellow'] + '%s'templates['ansi']['hardcore'] = { 0 : colors['red'] + '%s', 1: colors['grey'] + '%s' } templates['ansi']['entry'] = colors['yellow'] + '%3d %-30s %2d %16s %10d' + off + '\n'templates['ansi']['separator'] = line + '\n'del text#### ascii / ansi ### Some struct from d2cs/d2dbs source## ladder header (4 + 4 = 8):# bn_int maxtype# bn_int checksumLD_HEAD="<2i"szLD_HEAD = calcsize(LD_HEAD)## ladder info (4 + 2 + 1 + 1 + 16 = 24):# bn_int experience# bn_short status# bn_byte level# bn_byte class;# char charname[16];LD_INFO="<Ihbb16s"szLD_INFO = calcsize(LD_INFO)## ladder index (4 + 4 + 4 = 12):# bn_int type# bn_int offset# bn_int numberLD_INDEX="<3i"szLD_INDEX = calcsize(LD_INDEX)## Status flagsS_INIT = 0x1S_EXP = 0x20S_HC = 0x04S_DEAD = 0x08classes = { 0x00 : ['Amazon', 'f'], 0x01 : ['Sorceress', 'f'], 0x02 : ['Necromancer', 'm'], 0x03 : ['Paladin', 'm'], 0x04 : ['Barbarian', 'm'], 0x05 : ['Druid', 'm'], 0x06 : ['Assassin', 'f'] }desc = { 'nor': 'Diablo II', 'exp': 'Lord of Desctruction' }diff = { 'nor': { 0x1: { 0 : { 'm': 'Sir', 'f': 'Dame' }, 1 : { 'm': 'Count', 'f': 'Countess' } }, 0x2: { 0 : { 'm': 'Lord', 'f': 'Lady' }, 1 : { 'm': 'Duke', 'f': 'Duchess' } }, 0x3: { 0 : { 'm': 'Baron', 'f': 'Baroness' }, 1 : { 'm': 'King', 'f': 'Queen' } } }, 'exp': { 0x1: { 0 : { 'm': 'Slayer', 'f': 'Slayer' }, 1 : { 'm': 'Destroyer', 'f': 'Destroyer' } }, 0x2: { 0 : { 'm': 'Champion', 'f': 'Champion' }, 1 : { 'm': 'Conqueror', 'f': 'Conqueror' } }, 0x3: { 0 : { 'm': 'Patriarch', 'f': 'Matriarch' }, 1 : { 'm': 'Guardian', 'f': 'Guardian' } } } }## Utilsdef remove_null(text): return split(text, chr(0))[0]def get_ladder(file): try: size = stat(file)[6] data = open(file, "rb") except: print "Error opening %s for read" % file exit() maxtype, checksum = unpack(LD_HEAD, data.read(szLD_HEAD)) size = size - szLD_HEAD head = [] for i in range(maxtype): type, offset, number = unpack(LD_INDEX, data.read(szLD_INDEX)) size = size - szLD_INDEX head.append( { 'type': type, 'offset': offset, 'number': number }) ladder = {} ladder['nor'] = [] ladder['exp'] = [] temp = {} temp['nor'] = [] temp['exp'] = [] while size > 0: try: experience, status, level, _class, charname = unpack(LD_INFO, data.read(szLD_INFO)) except: ### Bad data size = size - szLD_INFO continue size = size - szLD_INFO ## Avoid null chars if not experience: continue charname = remove_null(charname) died = 0 if status & S_EXP: _type = 'exp' difficulty = ((status >> 0x08) & 0x0f) / 5 else: _type = 'nor' difficulty = ((status >> 0x08) & 0x0f) / 5 if status & S_HC: hc = 1 if status & S_DEAD: died = 1 else: hc = 0 c_class = classes[_class] if difficulty and diff[_type].has_key(difficulty): prefix = diff[_type][difficulty][hc][c_class[1]] else: prefix = None char = (experience, { 'charname' : charname, 'prefix' : prefix, 'experience' : experience, 'class' : c_class[0], 'sex' : c_class[0], 'level' : level, 'type' : _type, 'difficulty' : difficulty, 'hc' : hc, 'died' : died }) ## Dupe char? why? if char not in temp[_type]: temp[_type].append(char) data.close() ## Sorting by exp temp['nor'].sort() temp['nor'].reverse() temp['exp'].sort() temp['exp'].reverse() for _type in temp.keys(): for ch in temp[_type]: ladder[_type].append(ch[1]) del temp return ladderdef generate(ladder, mode, output, max): output.write(templates[mode]['header']) for _type in ladder.keys(): count = 1 output.write(templates[mode]['summary'] % desc[_type]) output.write(templates[mode]['tbheader']) for ch in ladder[_type]: if ch['prefix']: charname = "%s %s" % (ch['prefix'], ch['charname']) else: charname = ch['charname'] if ch['hc']: charname = templates[mode]['hardcore'][ch['died']] % charname else: charname = templates[mode]['normal'] % charname output.write(templates[mode]['entry'] % (count, charname, ch['level'], ch['class'], ch['experience'])) count = count + 1 if count > max: break output.write(templates[mode]['separator']) output.write(templates[mode]['footer'])def pickle_to(ladder, output): try: from cPickle import dump except: from pickle import dump try: out = open(output, "wb") except: print "Cannot open %s for pickle dump" % output exit() dump(ladder, out) out.close() ### Main### CGI MODEif CGI_MODE: print "Content-Type: text/html" print ladder = get_ladder(FILE) generate(ladder, 'html', stdout, MAX) exit()args = argv[1:]optlist, args = getopt(args, "hi:o:m:n:")if len(args): for bad in args: print "%s: Unrecognized option %s" % (argv[0], bad) exit()### defaultsfile = Noneoutput = None # stdoutmode = modes[0]real_max = 1000max = 100def show_help(): print print "ladder.py v%s - (c) 2001 Sherpya <sherpya@netfarm.it>" % __version__ print "Usage: ladder.py -i ladder_file [-o outputfile] [-m mode] [-n max ladder chars]" print print " -i ladder_file, is the ladder file like ladder.D2DV" print " -o output file, if omitted defaults to stdout" print " -m mode, avaiables mode are: %s, defaults to %s" % (join(modes,', '), modes[0]) print " -n max_char, max char to display in each ladder, defaults to %d" % max print print " note: python output mode creates a python object usable by pickle module" printfor opt in optlist: # Help if opt[0] == '-h': show_help() exit() # Input file if opt[0] == '-i': file = opt[1] continue # Output file if opt[0] == '-o': output = opt[1] continue # Output mode (html, ansi, ascii, python) if opt[0] == '-m': if opt[1] in modes: mode = opt[1] continue else: print "Invalid mode %s, valid modes are %s" % (opt[1], join(modes, ', ')) exit() # Max chars in ladder if opt[0] == '-n': try: max = int(opt[1]) except: max = 0 if (max < 2) or max > real_max: print "Invalid value for max char in ladder must be > 1 and < %d" % real_max exit() continueif not file: show_help() exit()ladder = get_ladder(file)if mode == 'python': if output: pickle_to(ladder, output) else: print "Cannot dump python object to stdout" exit()if output: try: output = open(output, "wb") except: print "Cannot open %s for writing" % output exit()else: output = stdout generate(ladder, mode, output, max)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -