Jump to content
VegaS™

python [Python] localeInfo.py - Refactored

Recommended Posts

There are a lot of people which had problem with localeInfo because korean-characters and bad encoding, there's a clean file with refactored code.

  • Removed all the code which isn't used like korean characters < bad encoding [runmain error / crash](editors problem) and more checks.
  • Removed over 500 lines unused.
  • Removed function mapping(**kwargs) and use constructor of dict > dict(**kwarg) which is same (**kwarg let you take arbitrary number of keyword arguments).
  • Removed function CutMoneyString because is used just when locale is HongKong, CIBN.
  • Removed check IsYMIR from function LoadLocaleData which load locale as locale/ymir or locale/we_korea.
  • Removed GUILD_MARK_NOT_ENOUGH_LEVEL, GUILD_HEADQUARTER, GUILD_FACILITY, GUILD_OBJECT, MAP_TRENT02, MAP_WL, MAP_NUSLUCK, MAP_TREE2, LOGIN_FAILURE_WEB_BLOCK, LOGIN_FAILURE_BLOCK_LOGIN, CHANNEL_NOTIFY_FULL, now they're readed directly from locale_game.txt.
  • Removed declared global variables.
  • Removed checks for declaring LOCALE_FILE_NAME, FN_GM_MARK and use current path.
  • Removed korean functions/lists/dictionaries/characters GetAuxiliaryWordType, JOBINFO_DATA_LIST, dictSingleWord, dictDoubleWord, etc.
  • Removed unused things: locale mapping, 'all' list etc.
  • Removed IN_GAME_SHOP_ENABLE declaration, should be declared inside of constInfo directly.
  • Removed checks (locale path) - 949, 932 == app.GetDefaultCodePage(), IsHONGKONG, IsNEWCIBN() or IsCIBN10() from declaration of functions like (NumberToMoneyString, NumberToSecondaryCoinString, ...),now they're declared directly from old style (IsEUROPE() and not IsWE_KOREA() and not IsYMIR()).
  • Added custom string format(format_string, *args, **kwargs) instead of %. (old-style).
  • Added new checks inside of LoadLocaleFile for security:
  •     Check if token3 (token1=original_string, token2=return-string, token3=function) function name exist in our types (SA, SNA, SAA, SAN) then try to call it.
  •     Check if string line have no tabs.

Diff-checker: (856 Removals + 301 Additions)

[hide]Download link[/hide]

  • Love 14

Share this post


Link to post
Share on other sites

I suggest you to put the file inside a Quote, because we're unable to download attachments.

 

At least, it doesn't let me <_<

  • Love 1

Share this post


Link to post
Share on other sites
0714 17:03:19906 :: 
uiCharacter.py(line:430) __LoadWindow
uiCharacter.py(line:257) __BindObject
uicharacterdetails.py(line:45) __init__
uicharacterdetails.py(line:73) __LoadScript
uicharacterdetails.py(line:88) __Initialize
uicharacterdetails.py(line:99) CreateTooltip

CharacterWindow.__LoadWindow - <type 'exceptions.AttributeError'>:'module' object has no attribute 'GetVariableName'

0714 17:03:19906 :: ============================================================================================================
0714 17:03:19906 :: Abort!!!!

 

  • Haha 1

Share this post


Link to post
Share on other sites
43 minutes ago, Caramelito said:

0714 17:03:19906 :: 
uiCharacter.py(line:430) __LoadWindow
uiCharacter.py(line:257) __BindObject
uicharacterdetails.py(line:45) __init__
uicharacterdetails.py(line:73) __LoadScript
uicharacterdetails.py(line:88) __Initialize
uicharacterdetails.py(line:99) CreateTooltip

CharacterWindow.__LoadWindow - <type 'exceptions.AttributeError'>:'module' object has no attribute 'GetVariableName'

0714 17:03:19906 :: ============================================================================================================
0714 17:03:19906 :: Abort!!!!

 

Look at your old locale and find GetVariableName and add to new file

  • Love 1

Share this post


Link to post
Share on other sites

thank you

Some functions would be shorter and more efficient with certain functions ...
Like

def SecondToHM(time):
  return " ".join(map(str, divmod(time, 60)))

 

  • Confused 1

Share this post


Link to post
Share on other sites
22 minutes ago, hardy89 said:

thank you

Some functions would be shorter and more efficient with certain functions ...
Like


def SecondToHM(time):
  return " ".join(map(str, divmod(time, 60)))

 

I could rewrite all of the functions and structure but i don't do it because the scope was to clean it not to change all structure, i did this long time ago.. if you saw the date.

Btw, It's funny how you talk about shorter and efficient functions in python while...

The code everytime can be improved, i don't like maybe a lot of scripts from metin2, but that doesn't means i've to rewrite them, there's isn't so much performance for a python script, if we don't talk about loops, searching, sort etc, it's fine how is it right now.

  • Love 1
  • Haha 1

Share this post


Link to post
Share on other sites
5 minut temu, VegaS™ napisał:

I could rewrite all of the functions and structure but i don't do it because the scope was to clean it not to change all structure, i did this some time ago.

It's funny how you talk about shorter and efficient functions in python while...you've no idea about python 😁

Let's don't do off-topic.

I don't get it. You did rewrite bunch of functions except for last 3. Almost 2 years passed since he asked you about that. I think you are a bit cocky 

Share this post


Link to post
Share on other sites
27 minutes ago, filipw1 said:

I don't get it. You did rewrite bunch of functions except for last 3.

I didn't rewrote the functions, is the same code, maybe removed unused lines or put them inline.

Let's take an example, this:

def GetAlignmentTitleName(alignment):
	if alignment >= 12000:
		return TITLE_NAME_LIST[0]
	elif alignment >= 8000:
		return TITLE_NAME_LIST[1]
	elif alignment >= 4000:
		return TITLE_NAME_LIST[2]
	elif alignment >= 1000:
		return TITLE_NAME_LIST[3]
	elif alignment >= 0:
		return TITLE_NAME_LIST[4]
	elif alignment > -4000:
		return TITLE_NAME_LIST[5]
	elif alignment > -8000:
		return TITLE_NAME_LIST[6]
	elif alignment > -12000:
		return TITLE_NAME_LIST[7]

	return TITLE_NAME_LIST[8]

We could do it as (just example, ignore the comparation): (without making a dictionary)

def GetAlignmentTitleName(currentAlignment):
	for alignmentIndex, alignmentValue in enumerate((12000, 8000, 4000, 1000, 0, -4000, -8000, -12000)):
		if currentAlignment >= alignmentValue:
			return TITLE_NAME_LIST[alignmentIndex]
	return TITLE_NAME_LIST[-1]

Do you think people will understand it so well what's the index if they don't know what the function does?
That's why i didn't touch these functions, they've edited (like added alignment grades) and don't know how to extend it.

Btw, if you want to discuss this, we can go in off-topic category, already is enough.

  • Love 3

Share this post


Link to post
Share on other sites
Il y a 2 heures, VegaS™ a dit :

I could rewrite all of the functions and structure but i don't do it because the scope was to clean it not to change all structure, i did this long time ago.. if you saw the date.

Btw, It's funny how you talk about shorter and efficient functions in python while...

The code everytime can be improved, i don't like maybe a lot of scripts from metin2, but that doesn't means i've to rewrite them, there's isn't so much performance for a python script, if we don't talk about loops, searching, sort etc, it's fine how is it right now.

I did that a long time ago to... Sorry, bbut seeing that you had refactored some functions, I thought you had forgotten this one. I just give an another way to do this. 

 

il y a une heure, VegaS™ a dit :

 


def GetAlignmentTitleName(currentAlignment):
	for alignmentIndex, alignmentValue in enumerate((12000, 8000, 4000, 1000, 0, -4000, -8000, -12000)):
		if currentAlignment >= alignmentValue:
			return TITLE_NAME_LIST[alignmentIndex]
	return TITLE_NAME_LIST[-1]

Do you think people will understand it so well what's the index if they don't know what the function does?
That's why i didn't touch these functions, they've edited (like added alignment grades) and don't know how to extend it.

Btw, if you want to discuss this, we can go in off-topic category, already is enough.

I think that people will understand better this code, even without actually understanding how it works that the huge ternary conditions of the other functions ... like :

	def NumberToMoneyString(n):
	return '0 {:s}'.format(MONETARY_UNIT0) if (n <= 0) else '{:s} {:s}'.format(('.'.join([(i - 3) < 0 and str(n)[:i] or str(n)[i - 3 : i] for i in range(len(str(n)) % 3, len(str(n)) + 1, 3) if i]), MONETARY_UNIT0))

Word to the wise...

Share this post


Link to post
Share on other sites

You're right, then let's refactor this shit.

Ymir method:

def NumberToMoneyString(n) :
	if n <= 0 :
		return "0 %s" % (MONETARY_UNIT0)
	return "%s %s" % ('.'.join([ i-3<0 and str(n)[:i] or str(n)[i-3:i] for i in range(len(str(n))%3, len(str(n))+1, 3) if i ]), MONETARY_UNIT0)
  
def NumberToSecondaryCoinString(n, coinType) :
	if n <= 0:
		n = 0

	coinTypeString = ""
	if coinType == shop.SHOP_COIN_TYPE_SECONDARY_COIN:
		coinTypeString = MONETARY_UNIT_JUN
	elif coinType == shop.SHOP_COIN_TYPE_BATTLE_POINT:
		coinTypeString = BATTLE_POINT
	elif app.ENABLE_10TH_EVENT and coinType == shop.SHOP_COIN_TYPE_10TH_EVENT:
		coinTypeString = TENTH_COIN
	else:
		return "Not Valied"

	return "%s %s" % ('.'.join([ i-3<0 and str(n)[:i] or str(n)[i-3:i] for i in range(len(str(n))%3, len(str(n))+1, 3) if i ]), coinTypeString)

My method:

def NumberToMoneyString(value, currency=MONETARY_UNIT0):
	return "{:0,.0f} {}".format(value, currency).replace(',', '.')

# Test
localeInfo.NumberToMoneyString(1934263992)                # 1.934.263.992 Yang 
localeInfo.NumberToMoneyString(200000, MONETARY_UNIT_JUN) # 200.000 Jun
localeInfo.NumberToMoneyString(4210, BATTLE_POINT)        # 4.210 Combat Points
localeInfo.NumberToMoneyString(500, TENTH_COIN)           # 500 Anniversary Coin(s)

236cbaece01052cf31d3764bb32e7124.png

And yes, Ymir killed the python for no-reason.

  • Love 5

Share this post


Link to post
Share on other sites
4 godziny temu, VegaS™ napisał:

You're right, then let's refactor this shit.

Ymir method:


def NumberToMoneyString(n) :
	if n <= 0 :
		return "0 %s" % (MONETARY_UNIT0)
	return "%s %s" % ('.'.join([ i-3<0 and str(n)[:i] or str(n)[i-3:i] for i in range(len(str(n))%3, len(str(n))+1, 3) if i ]), MONETARY_UNIT0)
  
def NumberToSecondaryCoinString(n, coinType) :
	if n <= 0:
		n = 0

	coinTypeString = ""
	if coinType == shop.SHOP_COIN_TYPE_SECONDARY_COIN:
		coinTypeString = MONETARY_UNIT_JUN
	elif coinType == shop.SHOP_COIN_TYPE_BATTLE_POINT:
		coinTypeString = BATTLE_POINT
	elif app.ENABLE_10TH_EVENT and coinType == shop.SHOP_COIN_TYPE_10TH_EVENT:
		coinTypeString = TENTH_COIN
	else:
		return "Not Valied"

	return "%s %s" % ('.'.join([ i-3<0 and str(n)[:i] or str(n)[i-3:i] for i in range(len(str(n))%3, len(str(n))+1, 3) if i ]), coinTypeString)

My method:


def NumberToMoneyString(value, currency=MONETARY_UNIT0):
	return "{:0,.0f} {}".format(value, currency).replace(',', '.')

# Test
localeInfo.NumberToMoneyString(1934263992)                # 1.934.263.992 Yang 
localeInfo.NumberToMoneyString(200000, MONETARY_UNIT_JUN) # 200.000 Jun
localeInfo.NumberToMoneyString(4210, BATTLE_POINT)        # 4.210 Combat Points
localeInfo.NumberToMoneyString(500, TENTH_COIN)           # 500 Anniversary Coin(s)

236cbaece01052cf31d3764bb32e7124.png

And yes, Ymir killed the python for no-reason.

My guess is that string formating wasn't a thing when they did that code, so they coded it just to work somewhat good. 

Share this post


Link to post
Share on other sites
2 hours ago, filipw1 said:

My guess is that string formating wasn't a thing when they did that code, so they coded it just to work somewhat good. 

The function NumberToSecondaryCoinString which i posted is recent in their root, format string exists since Python 2.6, 11 years ago. Who stop them to use it? Nobody, they do a lot of things in a hard-way, they don't use many builtin functions which doing the same thing even in 2019, they prefer to do it manually in a hard way , they like old ways.

Btw, i don't see the reason why we talk about this since we talked about 'refactoring', which means advantages include improved code readability and reduced complexity, doesn't matter what they had before.

I think it's enough for today, let's don't talk about this anymore here, i'll update the gist link when i've time with these functions modified, thanks for support.

  • Love 1

Share this post


Link to post
Share on other sites

Default code for SecondToXXX:

Spoiler

 


def SecondToDHM(time):
	if time < 60:
		if IsARABIC():
			return '%.2f %s' % (time, SECOND)
		else:
			return '0' + MINUTE

	minute = int((time / 60) % 60)
	hour = int((time / 60) / 60) % 24
	day = int(int((time / 60) / 60) / 24)

	text = ''
	if day > 0:
		text += str(day) + DAY
		text += ' '

	if hour > 0:
		text += str(hour) + HOUR
		text += ' '

	if minute > 0:
		text += str(minute) + MINUTE
	return text

def SecondToHM(time):
	if time < 60:
		if IsARABIC():
			return '%.2f %s' % (time, SECOND)
		else:
			return '0' + MINUTE

	minute = int((time / 60) % 60)
	hour = int((time / 60) / 60)

	text = ''
	if hour > 0:
		text += str(hour) + HOUR
		if hour > 0:
			text += ' '

	if minute > 0:
		text += str(minute) + MINUTE
	return text

 

My extendable version: (I wrote that fast, so, if there's a problem with it, write me a pm, let's don't spam the topic.)

def sec2time(timeSeconds, timeTypes, timeShowAll=False):
	"""
	Convert seconds to specific format time readable.
	:param time: int
	:param timeTypes: str (DMS, DHS, HMS, HM, HS, MS, M, S)
	:param timeShowAll: bool (showing the time name even if the value is 0, otherwise check the value if is > 0)
	:return: string
	"""
	(d, remainder) = divmod(timeSeconds, 86400)
	(h, remainder) = divmod(remainder, 3600)
	(m, s) = divmod(remainder, 60)

	TIME_INFO_DICT = dict(
		d=(d, localeInfo.DAY), 
		h=(h, localeInfo.HOUR), 
		m=(m, localeInfo.MINUTE), 
		s=(s, localeInfo.SECOND)
	)

	timeOutput = str()
	for timeType in timeTypes:
		timeType = timeType.lower()

		if timeType in TIME_INFO_DICT:
			(timeValue, timeLocaleName) = TIME_INFO_DICT[timeType]
			if timeValue > 0 or timeShowAll:
				timeOutput += '{}{} '.format(timeValue, timeLocaleName)
	return timeOutput[:-1]

Results:

print sec2time(100000, "DHMS")
>>> 1Days 3Hours 46Minutes 40Seconds

print sec2time(10000, "HMS")
>>> 2Hours 46Minutes 40Seconds

print sec2time(1000, "MS")
>>> 16Minutes 40Seconds

print sec2time(1000, "M")
>>> 16Minutes

print sec2time(100, "S")
>>> 40Seconds

print sec2time(3600, "DHMS", True)
>>> 0Days 1Hours 0Minutes 0Seconds

print sec2time(3600, "DHMS")
>>> 1Hours

I still don't have the right time to update the module but i'll do it asap.

Edited by VegaS™
  • Love 6

Share this post


Link to post
Share on other sites

When I use your localeinfo.py I get this:

 

LoadLocaleError(locale/de/locale_game.txt)

 

Share this post


Link to post
Share on other sites
1 hour ago, Hik said:

LoadLocaleError(locale/de/locale_game.txt)

 

Change open method with pack_open in LoadLocaleFile. (for those who've that problem)

Edited by VegaS™
  • Love 2

Share this post


Link to post
Share on other sites

Thanks, I did it!

For those with problems, here is the VegaS solution:

 

lines = open (srcFileName, "r"). readlines ()

to

lines = pack_open (srcFileName, "r"). readlines ()

 

Edited by Hik

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.


  • Recently Browsing   0 members

    No registered users viewing this page.

×
×
  • Create New...

Important Information

Terms of Use / Privacy Policy / Guidelines / We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.