From c65fa172a5e32f6bfe44a9f5bcb16b5324f45045 Mon Sep 17 00:00:00 2001 From: Jesusaves Date: Sat, 18 May 2019 11:38:55 -0300 Subject: Remove udesign (not needed anymore) --- wiki/udesign.py | 718 -------------------------------------------------------- 1 file changed, 718 deletions(-) delete mode 100755 wiki/udesign.py (limited to 'wiki') diff --git a/wiki/udesign.py b/wiki/udesign.py deleted file mode 100755 index 6aefef5..0000000 --- a/wiki/udesign.py +++ /dev/null @@ -1,718 +0,0 @@ -#! /usr/bin/env python3 -# -*- coding: utf8 -*- -# -# Copyright (C) 2010-2011 Evol Online -# Copyright (C) 2018 TMW-2 -# Author: Andrei Karas (4144) -# Author: Jesusalva - -import datetime -import sys - -stgen=True - -wikib=open("EleMonsters.html", "w") -wikib.write('EleGen File') - -exp=[ 9,16,25,36,77,112,153,200,253,320, - 385,490,585,700,830,970,1120,1260,1420,1620, - 1860,1990,2240,2504,2950,3426,3934,4474,6889,7995, - 9174,10425,11748,13967,15775,17678,19677,21773,28543,34212, - 38065,42102,46323,53026,58419,64041,69892,75973,92468,115254, - 128692,142784,157528,178184,196300,215198,234879,255341,310188,365914, - 402508,442769,487051,535756,589342,648281,713112,784421,862867,949158, - 1044076,1148484,1263331,1389671,1528642,1681509,1849671,2034639,2238111, - 2461928, - 2708132,2978946,3276840,3604530,3964987,4361495,4797656,5277432,5805184,6095442, - 6400217,6720231,7056251,7409070,7779531,8168509,8576941,9005793,9456080,9928893, - 10425342,10946613,11493946,12068655,12672087,13305690,13970980,14669530,15403013,16173172, - 16981833,17830934,18722479,19658611,20641552,21673632,22757319,23895184,25089950,25591758, - 26103599,26625670,27158181,27701356,28255388,28820507,29396920,29984867,30584571,31196260, - 31820184,32456596,33105727,33767845,34443202,35132065,35834705,36551410,37282446,38028099, - 38788671,39564454,40355745,41162860,41986116,42825838,43682362,44556009,45447138,45901616, - 46360641,46824255,47292503,47765432,48243093,48725528,49212784,49704921,50201982,50704003, - 51211047,51723162,52240405,52762810,53290446,53823354,54361598,54905214,55454271,56008820, - 56568910,57134610,57705965,58283032,58865873,59454536,60049086,60649586,61256083,61868649, - 62487336,63112216,63743344,64380779,65024597,65674843,66331602,66994930,67664885,68341538, - 69024959,69715207,70412360,71116485,71827658,72545940,73271398,74004114,74744153,75491595, - 76246518,77008984,77779077,78556879,79342456,80135878,80937236,81746616,82564087,83389730, - 84223638,85065880,85916545,86775711,87643468,88519912,89405121,90299171,91202163,92114182, - 93035322,93965687,94905347,95854406,96812948,97781076,98758892,99746478,100743951,101751398, - 102768911,103796609,104834582,105882930,106941769,108011193,109091315,110182230,111284052,112396904, - 113520874,114656091,115802657,116960692,118130296,119311601,120504716,121709770,122926875,124156150, - 125397711,126651686,127918206,129197392,130489375,131794267,133112212,134443338,135787774,137145652, - 138517109,139902284,141301316,142714335,144141489,145582902,147038738,148509126,149994219,150894194, - 151799571,152710366,153626627,154548387,155475676,156408540,157346998,158291079,159240837,160196288, - 161157464,162124419,163097165,164075757,165060214,166050576,167046878,168049166,169057470,170071823, - 171092262,172118826,173151541,174190460,175235604,176287026,177344758,178408837,179479294,180556179, - 181639518,182729367,183825754,184928711,186038293,187154528,188277464,189407130,190543577,191686849, - 192836981,193994007,195157974,196328927,197506910,198691949,199884102,201083405,202289908,203503646, - 204724676,205953024,207188754,208431886,209682484,210940582,212206225,213479467,214760350,216048919, - 217345224,218649298,219961193,221280960,222608645,223944302,225287974,226639708,227999552,229367554, - 230743762,232128226,233520999,234922133,236331675,237749668,239176170,240611236,242054915,243507252, - 244968307,246438117,247916753,249404252,250900687,252406101,253920540,255444067,256976742,258518609, - 260069729,261630158,263199938,264779135,266367816,267966025,269573820,271191260,272818408,274455326, - 276102061,277758679,279425234,281101787,282788399,284485141,286192050,287909214,289636677,291374496, - 293122752,294881486,296650782,298430689,300221275,302022609,303834742,305657759,307491713,309336672, - 311192696,313059863,314938223,316827859,318728836,320641216,322565061,324500459,326447460,328406143, - 330376584,332358847,334353004,336359128,338377288,340407551,342449994,344504696,346571722,348651151, - 350743062,352847532,354964629,357094423,359236990,361392422,363560778,365742141,367936599,370144221, - 372365091,374599279,376846874,379107955,381382611,383670915,385972949,388288794,390618537,392962257, - 395320037,397691969,400078129,402478601,404893475,407322841,409766782,412225383,414698739,417186939, - 419690069,422208209,424741456,427289911,429853651,432432776,435027370,437637543,440263366,442024421, - 443792521,445567690,447349963,449139360,450935926,452739673,454550638,456368839,458194326,460027115, - 461867221,463714693,465569558,467431848,469301579,471178794,473063508,474955766,476855601,478763022, - 480678083,482600803,484531205,486469328,488415217,490368880,492330355,494299675,496276878,498261990, - 500255043,502256068,504265102,506282171,508307305,510340540,512381907,514431439,516489176,518555144, - 520629376,522711891,524802748,526901963,529009581,531125618,533250127,535383137,537524678,539674777, - 541833486,544000830,546176836,548361554,550555012,552757234,554968274,557188159,559416915,561654583, - 563901210,566156820,568421455,570695142,572977924,575269847,577570928,579881219,582200741,584529542, - 586867672,589215145,591572009,593938303,596314063,598699319,601094122,603498497,605912494,608336152, - 610769496,613212575,615665434,618128102,620600617,623083026,625575357,628077658,630589971,633112332, - 635644789,638187373,640740134,643303101,645876314,648459827,651053675,653657891,656272528,658897623, - 661533224,664179368,666836088,669503437,672181451,674870184,677569669,680279959,683001081,685733085, - 688476023,691229930,693994859,696770843,699557927,702356165,705165600,707986270,710818214,713661496, - 716516145,719382218,722259755,725148792,728049398,730961596,733885443,736820993,739768279,742727359, - 745698276,748681079,751675801,754682510,757701238,760732051,763774987,766830096,769897426,772977027, - 776068941,779173220,782289911,785419075,788560754,791714999,794881861,798061393,801253640,804458666, - 807676501,810907214,814150847,817407448,820677081,823959788,827255638,830564665,833886935,837222492 - ] - -def printSeparator(): - print("--------------------------------------------------------------------------------") - -def showHeader(): - print("TMW2 Ele Generator") - print("Udesign does a final polishing on monster HP.") - print("By default, redesign does not adds enough HP to mobs. UDesign fix that.") - print("Not running UDesign will make weapons from SeDesign overpowered.") - ##print "Evol client data validator." - print("Run at: " + datetime.datetime.now().isoformat()) - print("Output is: EleMonsters.html") - ##print "https://gitlab.com/evol/evol-tools/blob/master/testxml/testxml.py" - printSeparator() - -def showFooter(): - #pass - #printSeparator() - print("Done.") - - - -Mobs1=[] -Mobs2=[] -Mobs3=[] -Mobs4=[] -Mobs5=[] -Mobs6=[] -MobsA=[] - -SysDrops=[] - -def fwalk(wmask): - if wmask == 'WATER': - return '%s' % (wmask) - elif wmask == 'AIR': - return '%s' % (wmask) - elif wmask == 'WALL': - return '%s' % (wmask) - elif wmask == 'NORMAL' or wmask == 'DEFAULT': - return '%s' % (wmask) - else: - print("Invalid walk mask: "+wmask) - exit(1) - -def WhatRace(rac): - rc=rac.race - if rc == 0: - return "Formless" - elif rc == 1: - return "Undead" - elif rc == 2: - return "Brute" - elif rc == 3: - return "Plant" - elif rc == 4: - return "Insect" - elif rc == 5: - return "Fish" - elif rc == 6: - return "-" - elif rc == 7: - return "SemiHuman" - elif rc == 8: - return "Angel" - elif rc == 9: - return "Dragon" - elif rc == 10: - return "Player" - elif rc == 11: - return "Boss" - elif rc == 12: - return "NonBoss" - elif rc == 14: - return "NonSemiHuman" - elif rc == 15: - return "NonPlayer" - elif rc == 16: - return "SemiPlayer" - elif rc == 17: - return "NonSemiPlayer" - else: - print("ERROR, INVALID RACE ID: %d (ID: %s)" % (rc, rac.id)) - exit(1) - -def WhatElem(rac): - rc=rac.elem - tl="ERROR" - cl="#F00" - if rc == 0: - tl,cl="Neutral","#000" - elif rc == 1: - tl,cl="Water","#00F" - elif rc == 2: - tl,cl="Earth","#7A0" - elif rc == 3: - tl,cl="Fire","#F00" - elif rc == 4: - tl,cl="Wind","#093" - elif rc == 5: - tl,cl="Nature","#040" - elif rc == 6: - tl,cl="Holy","#afa" - elif rc == 7: - tl,cl="Dark","#908" - elif rc == 8: - tl,cl="Ghost","#404" - elif rc == 9: - tl,cl="Undead","#440" - else: - print("ERROR, INVALID ELEM ID: %d (ID: %s)" % (rc, rac.id)) - exit(1) - return "%s" % (cl, tl) - -class Mob: - def __init__(self): - # Basic - self.id="0" - #self.aegis="UnknownMonster" # SpriteName is not used anywhere, we are using its ID - self.name="Unknown Monster Name" - self.view="1" - self.boss=False - - # Defensive - self.mobpt="0" # Mob Points “Level” - self.hp="0" - self.xp="Exp: 0" - self.jp="JExp: 0" - self.st="" - - # Offensive - self.atk="[0, 0]" - self.range="0" - self.move="0" - self.delay="0" - self.drops=[] - - # New - self.race=-1 - self.elem=-1 - self.elel=-1 - self.walk="NORMAL" - - # Stats - self.str='0' - self.agi='0' - self.vit='0' - self.int='0' - self.dex='0' - self.luk='0' - -def MobAlloc(ab): - try: - maab=int(ab.mobpt) - except: - maab=9901 - - Mobs1.append(ab) - return - - if maab <= 20: - Mobs1.append(ab) - elif maab <= 40: - Mobs2.append(ab) - elif maab <= 60: - Mobs3.append(ab) - elif maab <= 80: - Mobs4.append(ab) - elif maab <= 100: - Mobs5.append(ab) - elif maab <= 150: - Mobs6.append(ab) - else: - MobsA.append(ab) - -def testMobs(): - print("Generating Elem-Mob Wiki...") - if len(sys.argv) >= 2: - src=open(sys.argv[1]+"/db/re/mob_db.conf", "r") - else: - src=open("../../server-data/db/re/mob_db.conf", "r") - - wikib.write("

EleGen Monster Database

\n") - start=False - dropper=False - skip=0 - x=Mob() # Only for pyflakes2 - - for a in src: - if a == "{\n": - if skip: - skip=0 - if start: - MobAlloc(x) - else: - start=True - x=Mob() - - if skip: - start=False - x=Mob() - continue - if " Id:" in a: - x.id=stp(a) - if x.id == "ID": - continue - - if " Name:" in a: - x.name=stp(a) - elif " Hp:" in a: - x.hp=stp(a) - elif " Lv:" in a: - x.mobpt=stp(a) - elif " Exp:" in a: - x.xp=stp(a) - elif " JExp:" in a: - x.jp=stp(a) - elif " Attack:" in a: - x.atk=stp(a) - elif " AttackRange:" in a: - x.range=stp(a) - elif " MoveSpeed:" in a: - x.move=stp(a) - elif " ViewRange:" in a: - x.view=stp(a) - elif " AttackDelay:" in a: - x.delay=stp(a) - - elif " Str:" in a: - x.str=stp(a) - elif " Agi:" in a: - x.agi=stp(a) - elif " Vit:" in a: - x.vit=stp(a) - elif " Int:" in a: - x.int=stp(a) - elif " Dex:" in a: - x.dex=stp(a) - elif " Luk:" in a: - x.luk=stp(a) - - - elif " Boss: true" in a: - x.boss=True - elif " Looter: true" in a: - x.st+="Lot," - elif " Assist: true" in a: - x.st+="Ass," - elif " Aggressive: true" in a: - x.st+="Agr," - elif " WalkMask:" in a: - x.walk=stp(a) - elif " Element:" in a: - tmp=stp(a) - tmp2=tmp.split(',') - try: - x.elem=int(tmp2[0]) - x.elel=int(tmp2[1]) - except: - print("Invalid Element for mob %s: %s" % (x.id, tmp)) - exit(1) - elif " Race:" in a: - try: - x.race=int(stp(a)) - except: - print("Invalid Race for mob %s: %s" % (x.id, a)) - exit(1) - elif 'Drops: ' in a: - dropper=True - elif dropper and '}' in a: - dropper=False - elif dropper: - x.drops.append(stp(a).split(": ")) - elif "Plant: true" in a: - skip=1 - # Write last entry - MobAlloc(x) - - writeMob() - - wikib.write('\n\n|Mode|Desc|\n|----|----|\n') - wikib.write('|Lot|Looter|\n') - wikib.write('|Ass|Assist|\n') - wikib.write('|Agr|Aggressive|\n') - - src.close() - -def stp(x): - return x.replace('\n', '').replace('|', '').replace('(int, defaults to ', '').replace(')', '').replace('basic experience', '').replace('"','').replace(" ","").replace("\t","").replace('(string', '').replace('Name: ','').replace('Element: ','').replace('Race: ','').replace('AttackDelay: ', '').replace('WalkMask: ','').replace('MoveSpeed: ', '').replace('AttackRange: ', '').replace('ViewRange: ','').replace('Attack: ','').replace('ViewRange: ','').replace('Hp: ','').replace('Id: ','').replace('Lv: ','').replace('view range','').replace('attack range','').replace('move speed','').replace('health','').replace('(int','').replace('attack delay','atk.').replace('(','').replace(')','').replace('WALK_','') - - -def MonsterWrite(tbl): - # TODO: Check _mobs files to determine the usual monster density (a misc info to aid adding proper drop specs) - wikib.write("\n") - if stgen: - wikib.write("\n") - else: - wikib.write("\n") - for i in sorted(tbl, key=lambda tbl: tbl.id): - if i.id == 'ID': - continue - - # Special skips for REDESIGN - #if (int(i.id) < 1187): - # continue - if (int(i.hp) <= 50) or (i.race == 3): - continue - - if i.boss: - i.name=""+i.name+"" - if stgen: - wikib.write('\n" - ) - else: - wikib.write('\n" - ) - wikib.write("
IDNameMob InfoStgenElegenMisc InfoRewardsStatsDrops
IDNameMob InfoElegenMisc InfoRewardsStatsDrops
' + - i.id +""+ - i.name +""+ - mb_core(i) +""+ - mbdt('advise',mb_stgen(i)) +""+ - mb_eleg(i) +""+ - mbdt('misc', mb_rdmisc(i)) +""+ - mbdt('Exp\'s', mb_rdrw(i)) +""+ - mbdt('stats', mb_rdstat(i)) +""+ - mbdt('drops', mb_rddrop(i)) +"
' + - i.id +""+ - i.name +""+ - mb_core(i) +""+ - mb_eleg(i) +""+ - mbdt('misc', mb_rdmisc(i)) +""+ - mbdt('Exp\'s', mb_rdrw(i)) +""+ - mbdt('stats', mb_rdstat(i)) +""+ - mbdt('drops', mb_rddrop(i)) +"
\n") - wikib.write("\n(↑) Return to top

\n\n") - -def writeMob(): - wikib.write(" ") - - wikib.write("

Lv 0-20

\n\n") - MonsterWrite(Mobs1) - wikib.write("

Lv 21-40

\n\n") - MonsterWrite(Mobs2) - wikib.write("

Lv 41-60

\n\n") - MonsterWrite(Mobs3) - wikib.write("

Lv 61-80

\n\n") - MonsterWrite(Mobs4) - wikib.write("

Lv 81-100

\n\n") - MonsterWrite(Mobs5) - wikib.write("

Lv 101-150

\n\n") - MonsterWrite(Mobs6) - - wikib.write("

Lv 101+

\n\n") - MonsterWrite(MobsA) - - -def mbdt(summary, content): - return ""+summary+"
"+content+"
" - return "
\ -"+summary+"\ -
"+content+"
" - -def mb_core(mb): - buff="" - buff+="Lvl: %s
\n" % (mb.mobpt) - buff+="HP: %s
\n" % (mb.hp) - buff+="ATK: %s
\n" % (mb.atk) - if mb.st != "": - buff+="Modes: %s" % (mb.st) - return buff - -def mb_eleg(mb): - buff="" - buff+="Race: %s
\n" % (WhatRace(mb)) - buff+="Walk: %s
\n" % (fwalk(mb.walk)) - buff+="Element: %s
\n" % (WhatElem(mb)) - return buff - -############################################################ -def mb_stgen(mb): - lv=int(mb.mobpt) - hp=int(mb.hp) - - # Force HP to be higher - # It'll only start applying from level 40 onwards - # It gives a bonus of 0.5% HP per mob level - # This means a level 100 mob got 60 times that stronger: 30% - if lv > 40: - hp=hp*(1.0+((lv-40)/210.0)) - hp=int(hp) - - buff="
"
-    buff+="Adjusted HP: %s
\n" % (hp) - buff+="
" - return buff - -def mb_rdstat(mb): - buff="
"
-    buff+="%s\n" % (mb.str)
-    buff+="%s\n" % (mb.agi)
-    buff+="%s\n" % (mb.vit)
-    buff+="%s\n" % (mb.int)
-    buff+="%s\n" % (mb.dex)
-    buff+="%s\n" % (mb.luk)
-    buff+="
" - return buff - -def mb_rdmisc(mb): - buff="" - if "agr" in mb.st.lower(): - buff+="View Range: %s\n" % (mb.view) - buff+="Attack Range: %s\n" % (mb.range) - buff+="AtkDelay: %s ms\n" % (mb.delay) - buff+="Move speed: %s ms\n" % (mb.move) - buff+="Element Level: %d\n" % (mb.elel) - return buff - -def mb_rdrw(mb): - buff="" - buff+="%s\n" % (mb.xp.replace(' ', ' ')) - buff+="%s\n" % (mb.jp.replace(' ', ' ')) - try: - buff+="MobPoints: %d\n" % (int(mb.mobpt)*11/10) - except: - pass - return buff - -def mb_rddrop(mb): - buff="" - for ax in mb.drops: - # Ignore disabled drops - if ax[0].startswith("//"): - continue - - # Write drop - try: - buff+=ax[0]+': ' + str(int(ax[1])/100.0) + ' %\n' - except IndexError: - print("Fatal: invalid %s mob with %s drops" % (mb.name, str(ax))) - exit(1) - except: - print("[Warning] %s incorrect drop: %s" % (mb.name, str(ax))) - buff+=ax[0]+': ' + ax[1] + ' ppm\n' - - # Save to SysDrops - SysDrops.append([ax[0], ax[1], mb.name]) - - return buff - - - -showHeader() - -testMobs() - -wikib.write('

') -wikib.write("Run at: " + datetime.datetime.now().isoformat()) -wikib.write('
') - -wikib.write(""" -Player Stats (melee warrior) - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
LevelStats 1Stats 2Average
00str: 2 agi: 5 vit: 7 int:1 dex: 6 luk: 3str: 2 agi: 5 vit: 7 int:1 dex: 6 luk: 3str: 2 agi: 5 vit: 7 int:1 dex: 6 luk: 3
10str:15 agi:10 vit: 5 int:1 dex:10 luk: 4str:11 agi:11 vit: 6 int:1 dex:11 luk: 7str:13 agi:11 vit: 5 int:1 dex:10 luk: 6
20str:19 agi:10 vit:10 int:1 dex:20 luk:10str:14 agi:19 vit: 8 int:1 dex:17 luk:11str:17 agi:14 vit: 9 int:1 dex:18 luk:11
30str:25 agi:30 vit:10 int:1 dex:20 luk:10str:22 agi:28 vit:12 int:1 dex:21 luk:15str:24 agi:29 vit:11 int:1 dex:20 luk:13
40str:38 agi:30 vit:20 int:1 dex:25 luk:17str:28 agi:35 vit:14 int:1 dex:32 luk:21str:33 agi:33 vit:17 int:1 dex:28 luk:19
50str:50 agi:40 vit:30 int:1 dex:25 luk:18str:41 agi:41 vit:15 int:1 dex:41 luk:26str:46 agi:41 vit:22 int:1 dex:33 luk:27
60str:54 agi:50 vit:40 int:1 dex:35 luk:20str:52 agi:52 vit:16 int:1 dex:45 luk:32str:53 agi:51 vit:28 int:1 dex:40 luk:26
70str:60 agi:60 vit:43 int:1 dex:50 luk:20str:61 agi:61 vit:22 int:1 dex:51 luk:38str:60 agi:61 vit:33 int:1 dex:50 luk:29
80str:80 agi:60 vit:50 int:1 dex:50 luk:25str:65 agi:71 vit:32 int:1 dex:60 luk:41str:72 agi:66 vit:41 int:1 dex:55 luk:33
90str:80 agi:70 vit:60 int:1 dex:60 luk:31str:71 agi:71 vit:41 int:1 dex:71 luk:51str:76 agi:70 vit:50 int:1 dex:66 luk:41
100str:90 agi:80 vit:69 int:1 dex:60 luk:31str:71 agi:81 vit:42 int:1 dex:81 luk:61str:81 agi:80 vit:56 int:1 dex:70 luk:46
110str:90 agi:90 vit:69 int:1 dex:70 luk:35str:82 agi:82 vit:50 int:1 dex:82 luk:65str:86 agi:86 vit:60 int:1 dex:76 luk:50
120str:99 agi:90 vit:69 int:1 dex:70 luk:45str:86 agi:86 vit:51 int:1 dex:86 luk:68str:93 agi:88 vit:60 int:1 dex:78 luk:56
130str:99 agi:91 vit:75 int:1 dex:70 luk:55str:91 agi:90 vit:51 int:1 dex:90 luk:68str:95 agi:91 vit:63 int:1 dex:80 luk:61
-""") -wikib.write('
') -wikib.write(""" -Reference Equipment
(?): Item not updated.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
LevelWeaponShield HeadChestShortsBootsGloves
5Knife, SmallKnifeNone- CreasedShirt CreasedShorts CreasedBoots CreasedGloves
10SharpKnifeRoundLeatherShieldCandorHeadBand CandorShirt CandorShorts CandorBoots, LousyMoccassins CandorGloves
15DaggerRoundLeatherShield, LeatherShieldBandana, SerfHat CottonShirt CottonShorts CottonBoots CottonGloves
20WoodenSwordLeatherShieldSerfHat, FancyHat CottonShirt, SilkRobe ? TulimsharGuardBoots ?
25BronzeGladius, BugSlayer, ScytheLeatherShield, WoodenShield? LeatherShirt JeansShorts, FarmerPants ? MinerGloves
30ShortGladiusWoodenShieldMinerHat ? JeansShorts ? ?
35ButcherKnife?? ? ? ? ?
40RealBronzeGladius, ShortSword, MiereCleaver?Bucket, BurglarMask, SailorHat DesertShirt ? ? LeatherGloves
45Backsword?ChefHat ? ? ? ?
50Broadsword?PinkHelmet* ForestArmor ? ? ?
60BlacksmithAxe, Kanabo?FafiMask Chainmail ? ? ?
70??? ? ? ? ?
80??? ? ? ? ?
90??? ? ? ? ?
100??? ? ? ? ?
110??? ? ? ? ?
120??? ? ? ? ?
130??? ? ? ? ?
140??? ? ? ? ?
150??? ? ? ? ?
-""") - -wikib.write('') -wikib.close() -#print(str(SysDrops)) - -showFooter() -exit(0) -- cgit v1.2.3-60-g2f50