玩樂天堂 pockyland

標題: 模組翻譯問題 [打印本頁]

作者: q4445552001    時間: 2009-11-27 21:13
標題: 模組翻譯問題
各位大大
請問es插件的 xxxxx.py 檔怎把它翻譯成中文
我只會翻譯es_xxxx.txt 的
因為我看到你們的伺服器 有看到一個插件 (ccbalance)
我自己去抓下來 是py檔 但是不知道怎麼相你們一樣把它翻譯成中文
能的話請大大教教我 感謝


2009/12/02 21:13 補充:
我想問開任務伺服器的那位大大看看

就是這種的>>
#/////////////////////////////////////////////////////////////////////
#// Can's Crew Autobalancer
#//     [cC] Sparty
#//     [cC] *XYZ*SaYnt
#/////////////////////////////////////////////////////////////////////
import sys,time
import es,gamethread,playerlib,usermsg
import operator
import traceback
using_xa = 0
xabalance = None
modname = 'ccbalance'
#comment out this section if not running under xa.
#if es.exists("variable","xa_debug"):
#from xa import xa
#using_xa = True
#xabalance = None
#modname = 'xabalance'
#############################
import psyco
psyco.full()
cfg = {}



########################################################################
## config variables (global for now)
## These are the variables that you, the user, can configure.
## The defaults behave very well, so unless you are trying to address
## a specific issue, it is recommended that these settings be left
## as-is.
##
## Thanks for trying the cC Team Balancer!
########################################################################
# set run_frequency to the frequency, in rounds, that you want the autobalancer
# to run.  The overall idea of this balancer is to be nonintrusive, so we
# recommend run frequencies of somewhere between 3 and 5.
cfg['run_frequency'] = 4

# The wait_until_dead flag determines whether or not live players are swapped.  If
# you are running mani admin, it is perfectly safe and desirable to swap live players;
# they will not be slain and will be seamlessly be moved to the other team.
# if you are not running mani, however, the player will be killed (if they are
# alive) to be moved to the other team, in which case the recommended setting
# is True.
# recommended to be set to False if you do have mani admin.
# recommended to be set to True if you do not have mani admin.
cfg['wait_until_dead'] = False  

# the balancer will do nothing until the min_player_count is reached.
cfg['min_player_count'] = 6

# At balance time, if team strengths are already balanced to within this percent,
# then no one is moved or swapped.  Recommended: 10.0
cfg['acceptable_strength_imbalance'] = 10.0

# At any round, if the team COUNTS are imbalanced by this percentage, a balancing
# is forced.  For example, if it is 7 vs. 5, that imbalance is 5/7*100 = 71%, which
# will cause a rebalancing to occur.  The default value is 84 percent, which forces
# a rebalance on a 24-player server if ever one team has 2 more than another.
cfg['team_imbalance_percentage_trigger'] = 84.0

# At any round, if the team STRENGTHS are imbalanced by this percentage, a balancing
# is forced.  Recommended: 60.0 percent (which means that one team is nearly twice
# as strong as the other)
cfg['team_strength_percentage_trigger'] = 60.0

# A player gets immunity from swapping once they are swapped, and they keep that
# immunity for the rest of the map.  However, for maps that stay on for a very long
# time, the player loses this immunity, and may be swapped again, after
# cfg['lose_immunity_after'] rounds.  Recommended: 30.
cfg['lose_immunity_after'] = 30  

# This parameter determines how long a player is immune from swapping after just
# having joined.  This is to prevent player swaps as soon as they join.  
# Recommended: 3
cfg['immune_for'] = 3

# This parameter sets the maximum number of player swaps that are considered; on
# large servers, the amount of computation can get quite large, so we limit
# it with this parameter.  If the balancer is taking too long at end of round,
# turn this number down.
cfg['max_swaps_considered'] = 100


# the verbosity can be set to 0 to 3, where 3 is a high level of printouts to
# console, and 0 completely silences the balancer.
cfg['verbose'] = 3

# these are factors that are probably better left alone.  Basically, the idea is
# that a player's killrate will probably be better if switched to a stronger team,
# and worse if switched to a weaker team.  These factors determine how much better
# or worse the killrate will be.
#better_factor = 1.5 # originally proposed by sparty
#worse_factor = 0.85 # originally proposed by sparty
cfg['better_factor'] = 1.1
cfg['worse_factor'] = 0.9


# player immunity list.  Players in this list will not ever be swapped.  List
# steam id's here in this variable, separated by spaces.
cfg['global_immunity'] = "STEAM_0:0:12480610 STEAM_0:0:21631"

# how to inform a player that he/she has been swapped.  
# 0 - no notification
# 1 - notification with a colored overlay at spawn
# 2 - notification with a colored overlay at spawn, and a brief sound.
# 3 - notification with a colored overlay at spawn, sound, and a centered message.
cfg['notify_team_change'] = 3
########################################################################























info = es.AddonInfo()
info['name']        = "cC Team Balancer"
info['version']     = "1.1"
info['author']      = "*XYZ*SaYnt"
info['url']         = "http://addons.eventscripts.com/addons/view/ccbalance"
info['basename']    = "ccbalance"
info['description'] = "Team balancing solution for CSS"

cfg['global_immunity'] = cfg['global_immunity'].split()



class Player(object):
    """
    Describes what we know about a player
    """
    def __init__(self):
        self.userid = 0
        self.name = ""
        self.steamid = ""
        self.deaths = 0
        self.kills = 0
        self.deaths = 0
        self.rounds = 0
        self.rounds_since_swap = 0
        self.overall_deaths = 0
        self.overall_kills = 0
        self.overall_rounds = 0
        self.killrate = 1.0
        self.rank = 0
        self.team = '0'
        self.connected = 0
        self.immune = 0
        self.init_done = False
        self.dead = 0
        self.changing_team = False
   
    def dump(self):
        log("Player %d: %s [%s]" % (self.userid,self.name,self.steamid))
        log("         : deaths=%d kills=%d rounds=%d killrate=%f" % (self.deaths,self.kills,self.rounds.self.killrate))
        log("         : team=%d connected=%d immune=%s init_done=%s" % (self.team,self.connected,str(self.immune),str(self.init_done)))

    def setkillrate(self,from_overall=False):
        global rounds_inactive
        if (self.rounds <= rounds_inactive) or from_overall:
            k = self.overall_kills
            r = self.overall_rounds        
        else:
            k = self.kills
            r = self.rounds
        if r == 0:
            self.killrate = 0.75
        else:
            self.killrate = float(k)/float(r)
            
    def addrounds(self,n):
        self.rounds += n
        self.overall_rounds += n
        self.rounds_since_swap += n
        
    def addkill(self):
        self.kills += 1
        self.overall_kills += 1     
        KillTotal[self.team] += 1
        #self.setkillrate()
        
    def adddeath(self):
        self.deaths += 1
        self.overall_deaths += 1
        DeathTotal[self.team] += 1

    def update_database(self):
        """
        write player information into the database for cold storage
        """
        check = es.sql('queryvalue',modname,"SELECT steamid FROM killrate WHERE steamid='%s'" % self.steamid)
        if check == None:
            es.sql('query',modname,"INSERT INTO killrate (steamid) VALUES ('%s')" % self.steamid)
        es.sql('query',modname,"UPDATE killrate SET name = ('%s') WHERE steamid='%s'" % (self.name, self.steamid))
        es.sql('query',modname,"UPDATE killrate SET overall_deaths = ('%d') WHERE steamid='%s'" % (self.overall_deaths, self.steamid))
        es.sql('query',modname,"UPDATE killrate SET overall_kills = ('%d') WHERE steamid='%s'" % (self.overall_kills, self.steamid))
        es.sql('query',modname,"UPDATE killrate SET overall_rounds = ('%d') WHERE steamid='%s'" % (self.overall_rounds, self.steamid))



class Merit(object):
    """
    Holds information on the merit of switching a particular t and ct
    """
    def __init__(self):
        self.userid_t = 0
        self.userid_ct = 0
        self.desirability = 0
        self.align = 0
        self.score = 0.0
        self.adjusted_score = 0.0
   



   
   
########################################################################
## global variables
########################################################################
global_rounds = 0
balanced_on_round = 0
Players = {}
DisconnectedPlayers = []
KillTotal = {}
DeathTotal = {}
mid_game_load = False
rounds_inactive = cfg['run_frequency'] - 1
########################################################################


def config():
    """
    Perform any custom configuration.  
    """
    if using_xa:
        for k,v in cfg.iteritems():        
              xabalance.setting.createVariable("balance_%s"%k,str(v),"Help text")
        
    global rounds_inactive
    rounds_inactive = cfg['run_frequency'] - 1

   
   
def load():
    """
    EVENT: executes whenever the script is loaded via es_load
    Perform initializations.
    """
    if using_xa:
        global xabalance
        xabalance = xa.register('xabalance')
   
    config()
   
    # initialize the database that we will use for persistent storage.
    es.sql('open',modname,'|ccbalance')
    es.sql('query',modname,"CREATE TABLE IF NOT EXISTS killrate (steamid TEXT,name TEXT DEFAULT 'unnamed',overall_kills TEXT DEFAULT '0',overall_deaths TEXT DEFAULT '0',overall_rounds TEXT DEFAULT '0')")
   
    #register a command that can be typed in chat to show internal statistics
    es.regsaycmd("ccbstats","%s/showstats" % modname,"Shows team balance merit information")
   
    #perform any init that needs to be done if we are loaded when a game is
    #already in progress.
    in_game_init()
   
    # if mani not present, we have to wait until dead, even if the user has
    # selected not to.
    #global cfg['wait_until_dead']
    #if not hasmani():      
    #    cfg['wait_until_dead'] = True
   
    logmsg("cC Team Balancer %s loaded." % info['version'],1)
    es.set("ccb_version",info['version'])
    es.makepublic("ccb_version")






def unload():
    """
    EVENT: executes whenever the script is unloaded via es_unload
    Perform any necessary cleanup.
    """  
   
    #flush data to the database
    flush_database()

    #close down the database.
    es.sql('close',modname)
   
    #clean up the say command.
    es.unregsaycmd('ccbstats')
   
   

    #say we are done.
    logmsg("cC Team Balancer %s unloaded." % info['version'],1)
   
    if using_xa:
        global xabalance
        xabalance.unregister()





def in_game_init():
    """
    initialize the team balancer when the script is loaded mid-game
    """
    global mid_game_load
    mid_game_load = True
    try:
        for i in range(4):
            KillTotal[str(i)]  = 0
            DeathTotal[str(i)] = 0
        myPlayerList = playerlib.getPlayerList('#all')
        for ply in myPlayerList:
            userid = int(ply.userid)
            x = Player()
            x.userid = userid
            x.team = str(ply.attributes['teamid'])
            x.steamid = ply.attributes['steamid']
            x.name = ply.attributes['name']
            x.connected = 1
            Players[userid] = x
        
            initkillrate(x.userid,x.steamid)
        
            kills = ply.attributes['kills']
            deaths = ply.attributes['deaths']
            
            if x.team != '0':
                KillTotal[x.team] = KillTotal[x.team] + kills
                DeathTotal[x.team] = DeathTotal[x.team] + deaths
   
        log('ingameinit:  T kill/death total is now %d %d' % (KillTotal['2'],DeathTotal['2']))
        log('ingameinit: CT kill/death total is now %d %d' % (KillTotal['3'],DeathTotal['3']))
        setrank()
         
    except:
        log("ERROR: exception caught in in_game_init()")
        logexception()
        raise
   
         
def es_map_start(ev):
    """
    EVENT: executes whenever the map starts.
    Reset all of the counters and flags that we need to.
    """
    global mid_game_load
    global balanced_on_round
   
    mid_game_load = False
    balanced_on_round = -1
   
    # reset the team kill counts
    for i in range(4):
        KillTotal[str(i)]  = 0
        DeathTotal[str(i)] = 0
   
    for uid in Players:
        Players[uid].immune = 0
        Players[uid].kills = 0
        Players[uid].deaths = 0
        Players[uid].rounds = 0
        Players[uid].rounds_since_swap = 0
        
    #all players need to be expunged on a map change.  We will pick them up
    #again as they reconnect back.
    for uid in Players:
        delete_player(uid,False)
    Players.clear()
   
    # any players that have disconnected have been moved to a temporary
    # list, waiting to have their data flushed to disk.  It is done here to
    # prevent any data writes from occuring in-game.
    flush_database()
     
    # reset the round counter
    global global_rounds
    global_rounds = 0
   
   
def round_start(ev):
    """
    EVENT: executes whenever a round starts
    Increment the number of rounds that have been played for this map.
    """
    global global_rounds
    global_rounds += 1
   
    # remove everyone's invulnerability
    p = es.getUseridList()
    for userid in p:
       es.setplayerprop(str(userid),"CBaseAnimating.m_nHitboxSet",0)
   

def round_end(ev):
    """
    EVENT: executes whenever a round ends
    Delay a little bit, and call the delayed_round_end function.
    """
    gamethread.delayed(1.0,delayed_round_end_timed,int(ev['reason']))

def delayed_round_end_timed(reason):
    start = time.time()
    delayed_round_end(reason)
    stop = time.time()
    log("End of round processing took %f seconds" % (stop-start))


def delayed_round_end(reason):
    """
    Round end processing.
    executes a second after round end, because of the delay in the round_end
    that we do above.
   
    Keep track of the number of rounds each player has played, and compute their
    kill rates.
   
    If it is time, spring into action and do some team balancing.
    """   
    try:
        global global_rounds
   
        # update settings from xa if needed.
        update_all_cvars()
   
        #do the team balancing calculations here.
        if reason == 10 or reason == 16:
            #do nothing on rounds that end in a draw
            #do nothing for rounds that end for game commence
            for x in Players:
                Players[x].addrounds(-1)
            global_rounds -= 1
            return
        else:           
            for x in Players.itervalues():
                x.setkillrate()
                           
            #set everyone's rank, which is determined by their killrate.      
            setrank()
           
               
        number_of_t = int(es.getplayercount('2'))
        number_of_ct = int(es.getplayercount('3'))
        (st,sct) = compute_team_strength(float(cfg['run_frequency']))
        
              
        logmsg("Round %d: Team Strengths: T = %.2f | CT = %.2f."  % (global_rounds,st,sct),3)
        
        #last_balance_round = global_rounds - (global_rounds%cfg['run_frequency'])
        #next_balance_round = last_balance_round + cfg['run_frequency']
        report = "Balancing in %s rounds." % (cfg['run_frequency'] - global_rounds%cfg['run_frequency'])
        
        
        # if there are not enough players on the server, do not even
        # attempt to do any balancing.
        if number_of_t+number_of_ct < cfg['min_player_count']:
            logmsg("No team balancing done, because there are not enough players: %d required." % cfg['min_player_count'],3)
            return
            
            
        # after all of these calculations, we need to swap players if need be.
        balance_this_round = 0
        obey_immunity = False
        
        if (global_rounds % cfg['run_frequency']) == 0:
            balance_this_round = 1
            
        
            
        if not balance_this_round:
            if not is_team_number_balanced(number_of_t,number_of_ct):
                report = "Imbalance in team counts.  Balancing this round."
                balance_this_round = 2
                obey_immunity = False
               
            if is_team_strength_off_kilter(st,sct):
                report = "Severe imbalance in team strengths.  Balancing this round."
                balance_this_round = 2
                obey_immunity = False
               
        if balance_this_round == 1:   
            if (global_rounds < rounds_inactive) and not mid_game_load:
               balance_this_round = 0
        
        if balance_this_round == 1:  
            balancepercentage = abs(2*(st-sct)/(st+sct))*100.0
            if balancepercentage < cfg['acceptable_strength_imbalance']:
                 report = "No balancing needed; the teams are balanced to %.1f percent." % balancepercentage
                 balance_this_round = 0
        
        if balance_this_round == 1:
            if global_rounds-balanced_on_round == 1:
                report = "Teams were balanced last round, so balancing is skipped."
                balance_this_round = 0
               
        logmsg(report,3)
         
        if balance_this_round:        
            dobalance(st-sct,obey_immunity)
            
            
        # remove immunity for any player that has been playing for over cfg['lose_immunity_after']
        # rounds.
        for x in Players:
            if Players[x].rounds_since_swap >= cfg['lose_immunity_after']:
                Players[x].swap_immunity = 0
               
    except:
        log("ERROR: exception caught in round_end()")
        logexception()
        raise
        
   


def player_team(ev):
    """
    EVENT: executed whenever a player joins a team
    Update our player data structures accordingly.
    Also keep track of the team kills and deaths accordingly.
    """
    #1 = spec
    #2 = t
    #3 = ct
    #es.msg("TEAM " + ev['userid'])
    if ev['team'] != '0':
        userid = int(ev['userid'])
        player_add(userid)
        try:         
           Players[userid].team = ev['team']
   
           KillTotal[ev['team']]  += Players[userid].kills
           DeathTotal[ev['team']] += Players[userid].deaths
           KillTotal[ev['oldteam']]  -= Players[userid].kills
           DeathTotal[ev['oldteam']] -= Players[userid].deaths
           
           # POSSIBLE ISSUE: need to think through what happens here....the ranking will
           # get computed even when the round is not active....may be better to leave
           # the rankings uncomputed until it is team balance time.
           #setrank()
        except:
            log("Exception caught in player_team.  Probably a KeyError.")
            logexception()
            raise
   
  


def player_spawn(ev):
    """
    EVENT: executed whenever a player spawns
    Record the fact that the player played this round.
    """
    #es.msg("SPAWN " + ev['userid'])
    # QUESTION: if a player is in spec, do they spawn?  I think not, but I had
    # better check.
    userid = int(ev['userid'])
    player_add(userid,ev['es_username'],ev['es_steamid'])
    try: # This try block masks the exception that occurs when we change maps
        # and we get a few spurious spawns for the players before they are added
        # back into our data structures proper.
        # EDIT: this should no longer be needed.
        Players[userid].addrounds(1)
        team = ev['es_userteam']
        Players[userid].team = team
        
        # this section of code performs the notification that the player
        # has changed teams.
        if Players[userid].changing_team:
           Players[userid].changing_team = False
           if cfg['notify_team_change']:
               if team =='2':
                  usermsg.fade(userid,1,1000,100,255,0,0,60)
                  if cfg['notify_team_change'] > 1:
                     es.playsound(userid,"common/warning.wav",1)
                  if cfg['notify_team_change'] > 2:
                     es.centertell(userid,"You have been switched to the T side.")
               if team == '3':
                  usermsg.fade(userid,1,1000,100,0,0,255,60)
                  if cfg['notify_team_change'] > 1:
                     es.playsound(userid,"common/warning.wav",1)
                  if cfg['notify_team_change'] > 2:
                     es.centertell(userid,"You have been switched to the CT side.")
                  
    except KeyError:
        pass

# the sequence of events is...connect, spawn, activate, team, team, spawn

def player_connect(ev):   
    """
    EVENT: a player has connected.  
    Create a new instance of a player and add them to our dictionary.
    """
    # in the beginning, this is where player_adds were handled.  However, I think
    # that this is causing nonexistant players to be added to our data structure,
    # in the case that they connect but disconnect before actually entering
    # the game.  player_activate should be capable of picking up all players.
    #userid = int(ev['userid'])
    #player_add(userid,ev['name'],ev['networkid'])
    pass
  
   
def es_player_validated(ev):
    """
    EVENT: executed when a player is validated (gets a steam id)
    """
    #log("VALIDATED" + ev['userid'])
    # it was found that at this point, userid==''.  So this is not of much
    # use to us, unless we want to start looking up the steamid.
    #userid = int(ev['userid'])
    #player_add(userid,ev['es_username'],ev['es_steamid'])
    pass
   
def player_activate(ev):
    """
    EVENT: executed when a player is activated
    We need to handle this event and add a player if they are not already added,
    to properly handle players through a map change.  During a map change, players
    do not disconnect, but are reactivated at the beginning of the map.
    """
    #log("ACTIVATE " + ev['userid'] + ev['es_username'])  
    userid = int(ev['userid'])
    player_add(userid,ev['es_username'])
  
  
   
def player_add(userid,name='',steamid=''):
    """
    handle a player addition.  This may be called when the user is validated,
    or when the user is activated (either one).  We must be able to handle
    both cases, which is the purpose of the logic below.
    """
    if userid not in Players:
        x = Player()
        x.connected = 1
        if not name:
            name = es.getplayername(userid)
        x.name = name
        x.userid = userid
        Players[userid] = x  
        log("%s added to balancer." % name)
    if not Players[userid].init_done:
        if not steamid:
            steamid = es.getplayersteamid(userid)
        if "PENDING" not in steamid:
            initkillrate(userid,steamid)
            log("%s [%s] updated in balancer.  Kill rate of %.2f per round." % (name,steamid,Players[userid].killrate))  
        
  

def logmsg(s,verb=3):
    if cfg['verbose'] >= verb:
        es.msg("[cCB] " + s)
    #es.dbgmsg(0,"[cCB] "+ s)
    log(s)
   
def log(s):
    es.log("[cCB] " + s)
   
def logexception():
    pass
    #lst = traceback.format_exception(sys.exc_info()[0],10,sys.exc_info()[2])
    #for l in lst:
    #   es.log("[cCB] " + l.rstrip())


def initkillrate(userid,steamid):
    """
    sets the steam ID and initial killrate for a player given by userid and steamid
    """
    Players[userid].steamid = steamid
    #use a database to initialize the player's killrate.
        
    check = es.sql('queryvalue',modname,"SELECT overall_rounds FROM killrate WHERE steamid='%s'" % steamid)
    if check != None:
        overall_rounds = es.sql('queryvalue',modname,"SELECT overall_rounds FROM killrate WHERE steamid='%s'" % steamid)
        Players[userid].overall_rounds = int(overall_rounds)
    else:
        Players[userid].overall_rounds = 0
        
    check = es.sql('queryvalue',modname,"SELECT overall_deaths FROM killrate WHERE steamid='%s'" % steamid)
    if check != None:
        overall_deaths = es.sql('queryvalue',modname,"SELECT overall_deaths FROM killrate WHERE steamid='%s'" % steamid)
        Players[userid].overall_deaths = int(overall_deaths)
    else:
        Players[userid].overall_deaths = 0
        
    check = es.sql('queryvalue',modname,"SELECT overall_kills FROM killrate WHERE steamid='%s'" % steamid)
    if check != None:
        overall_kills = es.sql('queryvalue',modname,"SELECT overall_kills FROM killrate WHERE steamid='%s'" % steamid)
        Players[userid].overall_kills = int(overall_kills)
    else:
        Players[userid].overall_kills = 0

    Players[userid].setkillrate(from_overall=True)

    Players[userid].init_done = True


def player_changename(ev):
    """
    keep the name in our data structure synced with the player's actual name
    """
    userid = int(ev['userid'])
    Players[userid].name = ev['newname']


def player_disconnect(ev):
    userid = int(ev['userid'])
    if userid in Players:
        delete_player(userid)
   


def delete_player(userid,delete=True):
    Players[userid].connected = 0   
    DisconnectedPlayers.append(Players[userid])
    log("%s removed from balancer." % Players[userid].name)
    if delete:      
        del Players[userid]



def flush_database():
    """
    takes the list of players that we have moved to DisconnectedPlayers, and
    writes out their data to the database.
    """
    global DisconnectedPlayers
    for p in DisconnectedPlayers:
        p.update_database()
    DisconnectedPlayers = []



def player_death(ev):
    """
    EVENT: executes every time a player dies.
    record a death and a kill.
    """
    userid = int(ev['userid'])
    attacker = int(ev['attacker'])

    p = Players[userid]
    p.dead = 1
   
    # do not count suicides
    if userid == attacker: return

    p.adddeath()  
    if attacker:
        Players[attacker].addkill()
   
   
   
   
   
   
def dobalance(current_strength_difference,obey_immunity):
    """
    compute all merit scores of trading players and do the best trade
    """
   
    global balanced_on_round
   
    merit = []
   
    number_of_t = int(es.getplayercount('2'))
    number_of_ct = int(es.getplayercount('3'))
   
    log("In dobalance.  n_ct = %d, n_t = %d" % (number_of_ct,number_of_t))
                           
                           
   


    log("In dobalance.  Computing player moves.")
    # compute all possible player moves.  We need to only allow moves that will
    # satisfy team-number-balance constraints.
    for p in Players.itervalues():
        p.dead = isdead(p.userid) #kind of a hackey shortcut, but oh well.
        compute_merit_move(merit,p,number_of_t,number_of_ct,obey_immunity)
        
   
    # compute all possible swaps.  We only allow swaps if the current team counts
    # are within our allowed limits.  Otherwise, we work only with player moves
    # as computed above.
    try:
        swaps_considered = 0
        if is_team_number_balanced(number_of_t,number_of_ct):
            for t in Players.itervalues():
                if t.team == '2':
                    for ct in Players.itervalues():
                        if ct.team == '3':
                            if swaps_considered >= cfg['max_swaps_considered']: raise UserWarning
                            compute_merit_swap(merit,t,ct,obey_immunity)
                            swaps_considered += 1
    except UserWarning:
        pass
   
    if merit:
        # now that we have a list of merit objects, sort them from low to high.
        #merit.sort(key=operator.attrgetter('score'))
        
        #we need to "penalize" each merit score that involves the swap of immune
        #players.  The tricky part is figuring out how much to penalize the score.
        #From the numbers I've been observing, it seems reasonable to me to
        # simply penalize 1/4 of a kill per projected round.  We might need to
        # tweak this number, but we will start with this.
        #so from this
        for v in merit:
            v.adjusted_score = v.score + float(v.desirability)*0.25*float(cfg['run_frequency'])
        
        # in one pass, figure out who has the best merit score.
        best = 0
        topscore = 10000.0
        for i,v in enumerate(merit):
            if v.adjusted_score < topscore:
                topscore = v.adjusted_score
                best = i
   
        # for debugging, print the merit trades  
        log("%d merits computed." % len(merit))   
        #if ccbalance_debug:           
        #    for v in merit:
        #        userid_ct = v.userid_ct
        #        userid_t  = v.userid_t
        #        if userid_ct != 0 and userid_t != 0:
        #            log("merit of swapping %s (T) and %s (CT): score=%.2f/%.2f" % (Players[userid_t].name,Players[userid_ct].name,v.score,v.adjusted_score))
        #        elif userid_t != 0:
        #            log("merit of moving %s (T): score=%.2f/%.2f" % (Players[userid_t].name,v.score,v.adjusted_score))
        #        elif userid_ct != 0:
        #            log("merit of moving %s (CT): score=%.2f/%.2f" % (Players[userid_ct].name,v.score,v.adjusted_score))
        
        
        log("INFO: best align = %.1f, strengthdiff=%.1f" % (merit[best].align,current_strength_difference))
        
        # only do the swapping if:
        #   1) the new projected numbers are better than the current strength difference
        #   2) we are ignoring immunity, which means we have an exception condition in that
        #      the team numbers are off-kilter, or team strengths are severely off.         
        if (merit[best].score < 0.7*abs(current_strength_difference)) or not obey_immunity:
            
            # if the team adjustment makes a bad team worse, then dont do it.
            #if merit[best].align*current_strength_difference < 0.0:
            
            
            if True:
                balanced_on_round = global_rounds   
               
                # pick off the one with the lowest score; which is the best swap that we can possibly
                # do.  Swap those two players (or move, if the merit object tells us that's
                # what we need to do)      
                userid_ct = merit[best].userid_ct
                userid_t  = merit[best].userid_t
            
                apply_team_protections(userid_ct,userid_t)
            
                if userid_ct == 0:
                    logmsg("moving %s (T) to team CT." % Players[userid_t].name,2)
                    swapteam(userid_t,'3')
                    Players[userid_t].immune += 1
                    Players[userid_t].rounds_since_swap = 0  
                    Players[userid_t].changing_team = True  
                elif userid_t == 0:
                    logmsg("moving %s (CT) to team T." % Players[userid_ct].name,2)
                    swapteam(userid_ct,'2')
                    Players[userid_ct].immune += 1  
                    Players[userid_ct].rounds_since_swap = 0  
                    Players[userid_ct].changing_team = True  
                else:
                    logmsg("swapping %s (T) and %s (CT)" % (Players[userid_t].name,Players[userid_ct].name),2)
                    swapteam(userid_t,'3')
                    swapteam(userid_ct,'2')
                    Players[userid_t].immune += 1  
                    Players[userid_ct].immune += 1
                    Players[userid_t].rounds_since_swap = 0  
                    Players[userid_ct].rounds_since_swap = 0  
                    Players[userid_t].changing_team = True  
                    Players[userid_ct].changing_team = True  
                    
            else:
                logmsg("Team swap cancelled: moving players would worsen the situation.",2)
        else:
            logmsg("Team swap cancelled: moving players would not help imbalance.",2)
        
    else:
        logmsg("Unable to list any valid moves or swaps.",2)
      

def swapteam(userid,teamid):
    if hasmani():
        es.server.queuecmd("ma_swapteam %s" % str(userid))
    else:
        es.changeteam(str(userid),str(teamid))


def apply_team_protections(userid1,userid2):
    protect = 0
    if userid1 and not Players[userid1].dead: protect = 1
    if userid2 and not Players[userid2].dead: protect = 1
    if protect:
        for p in Players.itervalues():
            if not p.dead:
                invulnerable(p.userid)
               
               

def compute_merit_move(merit,p,number_of_t,number_of_ct,obey_immunity):
    """
    compute the merit of moving a single player
    """
  
    #if this player is alive, dont allow him to be swapped
    if cfg['wait_until_dead'] and not p.dead: return
   
    # absolutely dont allow anyone in the immunity list to be moved or swapped.
    imm_list = cfg['global_immunity']
    if p.steamid in imm_list: return
   
    # if this player already has been swapped this map, then dont allow him to be
    # swapped again.
    if p.immune > 0 and obey_immunity:
        return
   
    # if this player has only played a small number of rounds, dont allow him to be
    # swapped.
    if p.rounds <= cfg['immune_for'] and obey_immunity:
        return   
  
    m = Merit()
     
     
    total_t_kills = KillTotal['2']
    total_ct_kills = KillTotal['3']
    (st,sct) = compute_team_strength(float(cfg['run_frequency']))
   
    if (sct < st):
        #if total_ct_kills < total_t_kills:
        ctfactor = cfg['better_factor']
        tfactor = cfg['worse_factor']
    else:
        tfactor = cfg['better_factor']
        ctfactor = cfg['worse_factor']
        
        
    #compute projection of moving this player.   
    if p.team == '2':
        # player is a T, would be moving them to CT
        proposed_number_of_t = number_of_t - 1
        proposed_number_of_ct = number_of_ct + 1
        killrate = p.killrate * tfactor   
        m.userid_t = p.userid
        rounds =  cfg['run_frequency']
        t_projection = killrate * rounds
        t_loss = 0 # should I project a little loss here?
        if is_team_number_more_balanced(number_of_t,number_of_ct,proposed_number_of_t,proposed_number_of_ct) or is_team_number_balanced(proposed_number_of_t,proposed_number_of_ct):
            #m.align = (total_t_kills-p.kills-t_loss) - (total_ct_kills+p.kills+t_projection)
            #m.align = (st-p.kills-t_loss) - (sct+p.kills + t_projection)
            m.align = (st-p.killrate*rounds) - (sct + t_projection)
            m.score = float(abs(m.align))
            m.desirability = p.immune
            merit.append(m)
        
    if p.team == '3':
        # player is a CT, would be moving them to T
        proposed_number_of_t = number_of_t + 1
        proposed_number_of_ct = number_of_ct - 1
        killrate = p.killrate * ctfactor
        m.userid_ct = p.userid
        rounds = cfg['run_frequency']
        ct_projection = killrate * rounds
        ct_loss = 0 # should I project a little loss here?
        if is_team_number_more_balanced(number_of_t,number_of_ct,proposed_number_of_t,proposed_number_of_ct) or is_team_number_balanced(proposed_number_of_t,proposed_number_of_ct):
            #m.align =  (total_t_kills+p.kills+ct_projection) - (total_ct_kills-p.kills-ct_loss)
            #m.align =  (st+p.kills+ct_projection) - (sct-p.kills-ct_loss)
            m.align =  (st+ct_projection) - (sct-p.killrate*rounds)
            m.score = float(abs(m.align))
            m.desirability = p.immune
            merit.append(m)
   
def compute_team_number_imbalance(nt,nct):
    """
    Returns a number from 0...1 that indicates the amount of imbalance.
    A perfect balance is 1.0.  Horrible balance is 0.0.
    """
    return float(min(nt,nct))/float(max(nt,nct))*100.0
   
   
   
def is_team_strength_off_kilter(st,sct):
    percentage = min(st,sct)/max(st,sct)*100.0
    if percentage < cfg['team_strength_percentage_trigger']:
        return True
    else:
        return False
            
def is_team_number_balanced(nt,nct):
    """
    The team numbers are considered balanced if they are above the percentage
    threshhold OR if there is only a difference of 1 between the two team
    counts.
    """
    if abs(nt-nct) == 1: return True
   
    p = compute_team_number_imbalance(nt,nct)
    if p > cfg['team_imbalance_percentage_trigger']:
        return True
    else:
        return False

def is_team_number_more_balanced(nt,nct,ntnew,nctnew):
    """
    Answers the question of whether or not the teams are getting more balanced
    or less balanced as a result of changing the team numbers.
    """
    p    = compute_team_number_imbalance(nt,nct)
    pnew = compute_team_number_imbalance(ntnew,nctnew)

    if pnew > p:  return True
    else:         return False


def compute_merit_swap(merit,t,ct,obey_immunity):
    """
    compute the merit of swapping two players
    """
   
   
   
    if cfg['wait_until_dead']:
        if not t.dead or not ct.dead: return     
        
    # absolutely dont allow anyone in the immunity list to be moved or swapped.
    imm_list = cfg['global_immunity']
    if t.steamid in imm_list: return
    if ct.steamid in imm_list: return
   
    if obey_immunity:
        # dont allow a player that has already been swapped to be swapped again.
        if t.immune > 0 or ct.immune > 0: return
   
        # if this player has only played a small number of rounds, dont allow him to be
        # swapped.
        if (t.rounds <= cfg['immune_for']) or (ct.rounds <= cfg['immune_for']):
            return   
        
    m = Merit()
    total_t_kills = KillTotal['2']
    total_ct_kills = KillTotal['3']
   
    (st,sct) = compute_team_strength(float(cfg['run_frequency']))
   
    if (sct < st):
        #if (total_ct_kills < total_t_kills):
        ctfactor = cfg['better_factor']
        tfactor = cfg['worse_factor']
    else:
        tfactor = cfg['better_factor']
        ctfactor = cfg['worse_factor']
        
         
    #compute projection of trading these two players
     
    killrate = t.killrate * tfactor
    rounds =  cfg['run_frequency']
    t_projection = killrate * rounds

     
    killrate = ct.killrate * ctfactor
    rounds =  cfg['run_frequency']
    ct_projection = killrate * rounds

    m.userid_t = t.userid
    m.userid_ct = ct.userid
    #m.align = (total_t_kills-t.kills+ct.kills+ct_projection) - (total_ct_kills-ct.kills+t.kills+t_projection)
    #m.align = (st-t.kills+ct.kills+ct_projection) - (sct-ct.kills+t.kills+t_projection)
    m.align = (st-t.killrate*rounds+ct_projection) - (sct-ct.killrate*rounds+t_projection)
    m.score = float(abs(m.align))
    m.desirability = t.immune + ct.immune
   
    merit.append(m)
   
   
   
def showstats():
    """
    print out stats here, and show it only to the player identified by userid
    """
    update_cvar('run_frequency')
    (t,ct) = sortedplayerlists()
    (t_mom,ct_mom) = compute_team_momentum(float(cfg['run_frequency']))
    t_kills = KillTotal['2']
    ct_kills = KillTotal['3']
   
    userid = es.getcmduserid()
    cprint(userid,"="*60)
    cprint(userid,"Cans Crew Balancer Statistics")
    cprint(userid,"="*60)
    cprint(userid,"Total Kills (T) : %d" % t_kills)
    cprint(userid,"Total Kills (CT): %d" % ct_kills)
    #cprint(userid,"TEAM STRENGTH (T) : %d + %.2f = %.2f" % (t_kills,t_mom,t_mom+float(t_kills)))
    #cprint(userid,"TEAM STRENGTH (CT): %d + %.2f = %.2f" % (ct_kills,ct_mom,ct_mom+float(ct_kills)))
    cprint(userid,"TEAM STRENGTH (T) : %.2f" % (t_mom))
    cprint(userid,"TEAM STRENGTH (CT):  %.2f" % (ct_mom))
    cprint(userid,"-"*60)
    mystring = "%4s %5s %-30s %3s %3s %3s %s %s" % ("Rank","ID","Name","K","D","Rnd","KillRate","Swaps")
    cprint(userid,mystring)
    cprint(userid,"-"*60)
    cprint(userid,"Terrorists:")
    for player in t:
        showstat(userid,player)
    cprint(userid,"Counter Terrorists:")
    for player in ct:
        showstat(userid,player)
   
    es.tell(userid,"#green","[cCB] ccbstat results are displayed in the console.")



def compute_team_momentum(nrounds_forward):
    """
    computes the team momentums, meaning the number of kills that they are
    expected to achieve over the next nrounds_forward rounds.
    """
    s_t = 0.0
    s_ct = 0.0
    for k in Players.itervalues():
        if k.team == '2':
             s_t += k.killrate*nrounds_forward
        elif k.team == '3':
             s_ct += k.killrate*nrounds_forward
   
    return (s_t,s_ct)
   
   
   
def compute_team_strength(nrounds_forward):
    """
    compute the team strength...the kills projected for each team at the end
    of nrounds_forward rounds.
    """
    (mt,mct) = compute_team_momentum(nrounds_forward)
   
    #return (mt + float(KillTotal['2']),mct + float(KillTotal['3']))
    return (mt,mct)


def cprint(userid,s):
    es.cexec(userid,'echo','"%s"' % s)
    es.log("[CCB] " + s)

def showstat(userid,x):
    #mystring = "%4d %5d %-30s %3d|%d %3d|%d %3d|%d %.2f" % (x.rank,x.userid,x.name,x.kills,x.overall_kills,x.deaths,x.overall_deaths,x.rounds,x.overall_rounds,x.killrate)
    mystring = "%4d %5d %-30s %3d %3d %3d %.2f %d" % (x.rank,x.userid,x.name,x.kills,x.deaths,x.rounds,x.killrate,x.immune)
    cprint(userid,mystring)


def sortedplayerlists():
    t = []
    ct = []
    for k in Players.itervalues():
        if k.team == '2':
             t.append(k)
        elif k.team == '3':
             ct.append(k)
   
    t.sort(key=operator.attrgetter('killrate'))
    ct.sort(key=operator.attrgetter('killrate'))
    t.reverse()
    ct.reverse()
    return (t,ct)
   
   
   
def setrank():
    (t,ct) = sortedplayerlists()
            
    # assign the ranks
    for i,x in enumerate(t):
        Players[x.userid].rank = i+1
        
    for i,x in enumerate(ct):
        Players[x.userid].rank = i+1



def isdead(userid):
    deadflag = 0
    try:
        deadflag = int(es.getplayerprop(str(userid),"CCSPlayer.baseclass.pl.deadflag"))
    except:
        log("exception caught in isdead, player ID %d" % userid)
        #Players[userid].dump()
        #log(str(es.getUseridList()))   
    return deadflag

def hasmani():
    has_mani = es.exists("variable","mani_admin_plugin_version")
    return has_mani


def update_all_cvars():
    for k in cfg: update_cvar(k)
   
def update_cvar(varname):   
    """
    If we are using xa, updates any python global variable with the
    corresponding server variable.
    """
    if using_xa:
        #d = globals()
        d = cfg
        v = xabalance.setting.getVariable("balance_%s"%varname)
        if   isinstance(d[varname],int):      v = int(v)
        elif isinstance(d[varname],float):    v = float(v)
        elif isinstance(d[varname],bool):     v = bool(int(v))
        d[varname] = v
   
def invulnerable(userid):
    # I have to boost the health along with removing the hitboxes, because
    # the knife still does damage.
    es.setplayerprop(str(userid),"CBasePlayer.m_iHealth","1000")
    es.setplayerprop(str(userid),"CBaseAnimating.m_nHitboxSet",2)


def except_hook(type, value, tb):
   error_list = traceback.format_exception(type, value, tb)
   for message in error_list:
      es.log("[cCB:Except] " + message.strip())


sys.excepthook = except_hook
作者: 中山先生    時間: 2009-11-28 10:45
是在問啥!!
基本上你的問題需要專業人士先翻譯一下

作者: Mr.23    時間: 2009-12-1 11:14
問的好   , 我也不會  




歡迎光臨 玩樂天堂 pockyland (https://pockyland.tw/) Powered by Discuz! X3