#!/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()