#!/usr/bin/python
## This script reads files and process data.
# SQL Table data
sqltable="`merge`.`landoffire`"
sqltable2="`merge`.`accounts`"
# Merge configuration
# These values are inexact, a real report is done later. Tweak as needed.
pollgp=500000.0 # How many GP in total will be given? Value is approx. (default: 250,000)
pollit=1000000.0 # How many Item Points in total will be given? Value is approx. (default: 500,000)
lvadjs=12 # Level adjustment Value (magic number, default: 8)
# List all GM or cheated accounts
# If a player cheated and gave themselves 1 billion GP, in bank or in char,
# That will raise global money count, making legit players get less rewards.
gm=["2000127", "2000064", "2000070", "2000474", "2000000", "2000664", "2000464", "2000799", "2001232", "2000390", "2000106", "2000029", "2003587", "2002046", "2000005", "2000740", "2004480"] # Exclude all GM accounts (and ex-GM too). 2004480 was too suspicious
## Below this line, only change baseitem() function
acf,reg,stg,ath=[],[],[],[]
class Account:
def __init__(self, ide, nam):
self.id=ide
self.name=nam.replace("\\", "\\\\").replace("'", "\\'").replace("\"", "\\\"").replace(";", "")
self.gp=0
self.pts=0
self.lv=0 # level ^ 1.2 to valorize higher level chars (experience principle)
self.mpt=0 # MobPt
self.password="0000"
self.salt="1"
allinv={}
allit=0
allgp=0
allmp=0
allbp=0
allacc={}
report_it=0
report_ban=0
report_acc=0
report_exp=0
# Assume every dye'ed item is the base item to prevent pseudo-rarity
def baseitem(idt):
if (idt >= 2050 and idt <= 2059):
idt=1202 # Cotton shirt
elif (idt >= 2060 and idt <= 2069):
idt=624 # V Neck
elif (idt >= 2070 and idt <= 2079):
idt=564 # T Neck
elif (idt >= 2080 and idt <= 2089):
idt=720 # Silk Robe
elif (idt >= 2090 and idt <= 2099):
idt=688 # Tanktop
elif (idt >= 2100 and idt <= 2109):
idt=632 # Cotton skirt
elif (idt >= 2120 and idt <= 2129):
idt=689 # Short tanktop
elif (idt >= 2110 and idt <= 2119):
idt=586 # Cotton shorts
elif (idt >= 2130 and idt <= 2139):
idt=723 # Desert Hat
elif (idt >= 2140 and idt <= 2149):
idt=724 # Cotton Headband
elif (idt >= 2150 and idt <= 2159):
idt=735 # Cotton Boots
elif (idt >= 2160 and idt <= 2169):
idt=741 # Cotton Gloves
elif (idt >= 2170 and idt <= 2179):
idt=771 # Miniskirt
elif (idt >= 2180 and idt <= 2189):
idt=648 # Cotton Trousers
elif (idt >= 2190 and idt <= 2199):
idt=1255 # Rabbit Ears
elif (idt >= 2200 and idt <= 2209):
idt=4028 # Wizard Hat
elif (idt >= 2210 and idt <= 2219):
idt=4030 # Bowler Hat
elif (idt >= 2220 and idt <= 2229):
idt=798 # Sorcerer Robe
elif (idt >= 2230 and idt <= 2239):
idt=800 # Bowler Hat Brown
elif (idt >= 2240 and idt <= 2249):
idt=870 # Red Dress
elif (idt >= 2250 and idt <= 2259):
idt=660 # Cotton Cloth
elif (idt >= 5000 and idt <= 6000):
idt=798 # SorcererRobe*
elif (idt >= 8000 and idt <= 8003):
idt=8029 # Savior Armor
elif (idt >= 8055 and idt <= 8060):
idt=8029 # Savior Armor
return idt
def adjusted_itemvalue(your, total):
global allit
#mult=(total*float(allit))
value=float(your)/float(total)
return int( value*10000 )
query=open("query.sql", "w")
query.write("CREATE TABLE "+sqltable+" (\n\
ACNAME VARCHAR(32) NOT NULL PRIMARY KEY,\n\
GP INT(3) NOT NULL,\n\
XP INT(3) NOT NULL,\n\
INV INT(3) NOT NULL\n\
)\n\
\n\
CREATE TABLE "+sqltable2+" (\n\
ACNAME VARCHAR(32) NOT NULL PRIMARY KEY,\n\
MD5 VARCHAR(32) NOT NULL\n\
)\n")
##########################################
##########################################
## FIND THE TOTAL AMOUNT OF ALL ITEMS ##
##########################################
##########################################
acf=open("account.txt", "r")
reg=open("accreg.txt", "r")
stg=open("storage.txt", "r")
ath=open("athena.txt", "r")
# Before all, create accounts and add them to allacc
for line in acf:
a=line.split('\t')
if (a[12] != "0"): # Banned? We should skip this account
report_ban+=1
gm.append(a[0])
continue
if (a[0] in gm): # GM? We should skip, too
continue
aid=a[0]
allacc[aid]=Account(aid, a[1].replace('\\', '\\\\').replace('\n', '').replace('\'', '\\\'').replace('\"', '\\\"'))
allacc[aid].password=a[2].split('$')
allacc[aid].password=str(allacc[aid].password[1])
allacc[aid].salt=str(allacc[aid].password[0])
report_acc+=1
# Storage
for line in stg:
a=line.split('\t')
b=a[0].split(',')
if b[0] in gm: # GM/Ban? Skip this storage check
continue
b=a[1].split(',')
i=1
while (True):
try:
# sanitize item:
b[i]=baseitem(b[i])
try:
allinv[b[i]]+=int(b[i+1])
except:
allinv[b[i]]=int(b[i+1])
allit+=int(b[i+1])
i+=10
except:
try:
print "Code error at storage: %s, %s" % (b[i], b[i+1])
except:
pass
break
# Inventories
for line in ath:
a=line.split('\t')
b=a[1].split(',')
if b[0] in gm: # GM/Ban? Skip this inventory check
continue
b=a[15].split(',')
i=1
while (True):
try:
# sanitize item:
b[i]=baseitem(b[i])
try:
allinv[b[i]]+=int(b[i+1])
except:
allinv[b[i]]=int(b[i+1])
allit+=int(b[i+1])
i+=11
except:
try:
print "Code error at inventory: %s" % (b[i+1])
except:
pass
break
# While we are at it, we should save account data too
aid=a[1].split(',')
aid=aid[0]
# Prepare Money
agp=a[4].split(',')
agp=agp[2]
# Prepare Experience
alv=a[3].split(',')
alv=(float(alv[1])**1.2)/3.0
# Do you have mob points?
apt=0
for c in a[18].split(' '):
d=c.split(',')
if d[0] == "Mobpt":
apt+=int(int(d[1])/10) # TODO: Magical adjustment
allmp+=int(d[1])
if d[0] == "BOSS_POINTS":
apt+=int(d[1])*5
allbp+=int(d[1])
try:
allacc[aid].gp+=int(agp)
allacc[aid].lv+=int(alv)-(allacc[aid].lv/10)
allacc[aid].mpt+=int(apt)
except KeyError:
#print "%s account id on char data, but account was banned" % (aid)
pass
acf.close()
reg.close()
stg.close()
ath.close()
##########################################
##########################################
## FIND THE TOTAL AMOUNT OF GOLD! ##
##########################################
##########################################
acf=open("account.txt", "r")
reg=open("accreg.txt", "r")
stg=open("storage.txt", "r")
ath=open("athena.txt", "r")
# Athena
for line in ath:
a=line.split('\t')
b=a[1].split(',')
if b[0] in gm: # Banned? Skip from allgp pool
continue
b=a[4].split(',')
try:
allgp+=int(b[2])
except:
print "Code error at gp-athena: %s" % (b)
# Bank
for line in reg:
a=line.split('\t')
if a[0] in gm: # Banned? We disregard this account
continue
b=a[1].split(',')
try:
if (b[0]=="#BankAccount"):
agp=int(b[1])
except:
try:
err=True
for opt in a[1].split(' '):
if ("#BankAccount" in opt):
agp=int(opt.replace(',', '').replace('\n', '').replace(' ', '').replace('#BankAccount', ''))
err=False
break
if err:
print "error in accreg fallback: %s" % str(a[1].split(' '))
raise Exception
except:
print "Code error at accreg: %s" % (b)
pass
# While we are at it, we should save that GP to accounts too
aid=a[0]
try:
allacc[aid].gp+=int(agp)
allgp+=int(agp)
except KeyError:
pass
acf.close()
reg.close()
stg.close()
ath.close()
##########################################
##########################################
## START TREATING EACH account =D ##
##########################################
##########################################
acf=open("account.txt", "r")
stg=open("storage.txt", "r")
ath=open("athena.txt", "r")
rd1=0
#### Process and save every inventory & storage entry
# Storage
for line in stg:
a=line.split('\t')
a=a[0].split(',')
if b[0] in gm: # GM/Ban? Skip this storage check
continue
accid=b[0]
b=a[1].split(',')
i=1
while (True):
try:
# sanitize item:
b[i]=baseitem(b[i])
allacc[accid].pts+=adjusted_itemvalue(b[i+1], allinv[b[i]])
i+=10
except:
break
# Inventories
for line in ath:
a=line.split('\t')
b=a[1].split(',')
if b[0] in gm: # GM/Ban? Skip this inventory check
continue
accid=b[0]
b=a[15].split(',')
i=1
while (True):
try:
# sanitize item:
b[i]=baseitem(b[i])
allacc[accid].pts+=adjusted_itemvalue(b[i+1], allinv[b[i]])
i+=11
except:
break
rd2=0
rd3=0
for aid in allacc:
acc=allacc[aid]
# Adjust money value: If you hold 100% of LoF money (currently estimated in 1,088,273,287 GP) you would receive 250 thousands
rd1+=acc.gp
acc.gp=int( acc.gp*pollgp/allgp )
# Adjust item points (currently estimated in 2,427,618) to be within a controlled poll of 1 million points
acc.pts=int ( acc.pts*pollit/allit )
rd2+=acc.pts
# Convert level in experience points
acc.lv=int ( (acc.lv**1.2)*lvadjs )
# Add mobpoints to level, with a smaller value
acc.lv=acc.lv+(acc.mpt/14)
report_exp+=acc.lv
# We are done with adjustment. Skip empty values:
if acc.gp == acc.lv and acc.lv == acc.pts and acc.pts == 0:
continue
# Otherwise, we are done for good, save to query
query.write("INSERT INTO %s (ACNAME, GP, XP, INV) VALUES ('%s',%d,%d,%d)\n" % (sqltable, acc.name, acc.gp, acc.lv, acc.pts ))
query.write("INSERT INTO %s (ACNAME, MD5, SALT) VALUES ('%s','%s','%s')\n" % (sqltable2, acc.name, acc.password, acc.salt ))
rd3+=1
# Generate account entry on another table
acf.close()
stg.close()
ath.close()
##########################################
##########################################
## GENERATE REPORT! ##
##########################################
##########################################
for key in allinv:
report_it+=allinv[key]
## Summary
print("Found %d items (item kinds: %d)" % (report_it ,len(allinv)) )
if (allit - report_it != 0):
print("Pragma %d items" % allit)
print("Counted %d GP" % allgp)
if (allgp-rd1 != 0):
print("Pragma: %d GP (diff: %d)" % (rd1, allgp-rd1))
print("Found %d valid and %d banned accounts" % (report_acc, report_ban) )
#print("Disregard: %s" % str(gm))
print("Total mob points: %d" % allmp)
print("Total boss points: %d" % allbp)
print("Total experience given: %d" % report_exp)
print("Total accounts exported: %d" % rd3)
print("-----")
# Riches Summary
r=open("riches.csv", "w")
rd=0
for a in allacc:
r.write('%s,%s,%d\n' % (a, allacc[a].name.replace(',','+'), allacc[a].gp))
rd+=allacc[a].gp
r.close()
print("Riches theoretical check: %d" % int(allgp*pollgp/allgp))
print("Riches real check: %d" % rd)
# Items Summary
ip=open("items.csv", "w")
ipd=0
for a in allacc:
ip.write('%s,%s,%d\n' % (a, allacc[a].name.replace(',','+'), allacc[a].pts))
ipd+=allacc[a].pts
ip.close()
print("Item Points theoretical: %d" % int(allit*pollit/allit))
print("Item Points real check: %d" % rd2)
if ipd != rd2:
print("Item points distributed: %d" % ipd)
# All Items
ip=open("inventory_all.csv", "w")
for a in allinv:
ip.write('%s,%d\n' % (a, allinv[a]))
ip.close()
# Levels
r=open("level_table.csv", "w")
for a in allacc:
r.write('%s,%s,%d\n' % (a, allacc[a].name.replace(',','+'), allacc[a].lv))
r.close()