Add script to import a Nethack logfile
This commit is contained in:
		
							parent
							
								
									cb3818fd57
								
							
						
					
					
						commit
						5ecd480f98
					
				
					 1 changed files with 119 additions and 0 deletions
				
			
		
							
								
								
									
										119
									
								
								scripts/import-nethack-logfile.py
									
										
									
									
									
										Executable file
									
								
							
							
						
						
									
										119
									
								
								scripts/import-nethack-logfile.py
									
										
									
									
									
										Executable file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,119 @@
 | 
			
		|||
#!/usr/bin/env python3
 | 
			
		||||
# Eryn Wells <eryn@erynwells.me>
 | 
			
		||||
 | 
			
		||||
'''
 | 
			
		||||
Converts a Nethack logfile (or record file) to JSON for easier parsing by my
 | 
			
		||||
website's templating engine.
 | 
			
		||||
 | 
			
		||||
See https://nethackwiki.com/wiki/Logfile for information about the format of these
 | 
			
		||||
logfiles.
 | 
			
		||||
'''
 | 
			
		||||
 | 
			
		||||
import argparse
 | 
			
		||||
import datetime
 | 
			
		||||
import json
 | 
			
		||||
import os.path
 | 
			
		||||
import sys
 | 
			
		||||
 | 
			
		||||
DUNGEONS = {
 | 
			
		||||
    0: 'The Dungeons of Doom',
 | 
			
		||||
    1: 'Gehennom',
 | 
			
		||||
    2: 'The Gnomish Mines',
 | 
			
		||||
    3: 'The Quest',
 | 
			
		||||
    4: 'Sokoban',
 | 
			
		||||
    5: 'Fort Ludios',
 | 
			
		||||
    6: "Vlad's Tower",
 | 
			
		||||
    7: 'The Elemental Planes',
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
# The "dungeon level" field is normally positive, but negatives indicate one of these
 | 
			
		||||
# levels.
 | 
			
		||||
SPECIAL_DUNGEON_LEVELS = {
 | 
			
		||||
    -5: 'Astral Plane',
 | 
			
		||||
    -4: 'Plane of Water',
 | 
			
		||||
    -3: 'Plane of Fire',
 | 
			
		||||
    -2: 'Plane of Air',
 | 
			
		||||
    -1: 'Plane of Earth',
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
RACES = {
 | 
			
		||||
    'Hum': 'Human',
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ROLES = {
 | 
			
		||||
    'Mon': 'Monk',
 | 
			
		||||
    'Rog': 'Rogue',
 | 
			
		||||
    'Sam': 'Samurai',
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
GENDERS = {
 | 
			
		||||
    'Fem': 'Female',
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ALIGNMENTS = {
 | 
			
		||||
    'Law': 'Lawful',
 | 
			
		||||
    'Neu': 'Neutral',
 | 
			
		||||
    'Cha': 'Chaotic',
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
def parse_args(argv, *a, **kw):
 | 
			
		||||
    parser = argparse.ArgumentParser(*a, **kw)
 | 
			
		||||
    parser.add_argument('logfile', help='Path to the Nethack log file to convert')
 | 
			
		||||
    args = parser.parse_args(argv)
 | 
			
		||||
    return args
 | 
			
		||||
 | 
			
		||||
def main(argv):
 | 
			
		||||
    args = parse_args(argv[1:], prog=argv[0])
 | 
			
		||||
 | 
			
		||||
    if not os.path.isfile(args.logfile):
 | 
			
		||||
        print('Given path is not a real file!', file=sys.stderr)
 | 
			
		||||
        return -1
 | 
			
		||||
 | 
			
		||||
    records = []
 | 
			
		||||
    with open(args.logfile) as logfile:
 | 
			
		||||
        for record in logfile.readlines():
 | 
			
		||||
            fields = record.split(maxsplit=15)
 | 
			
		||||
 | 
			
		||||
            dungeon_number = int(fields[2])
 | 
			
		||||
            dungeon_name = DUNGEONS[dungeon_number]
 | 
			
		||||
 | 
			
		||||
            dungeon_level = int(fields[3])
 | 
			
		||||
            if dungeon_level > 0:
 | 
			
		||||
                dungeon_level_descriptive = f"Level {dungeon_level}"
 | 
			
		||||
            else:
 | 
			
		||||
                dungeon_level_descriptive = SPECIAL_DUNGEON_LEVELS[dungeon_level]
 | 
			
		||||
 | 
			
		||||
            start_date = datetime.datetime.strptime(fields[9], '%Y%m%d').strftime('%Y-%m-%d')
 | 
			
		||||
            end_date = datetime.datetime.strptime(fields[8], '%Y%m%d').strftime('%Y-%m-%d')
 | 
			
		||||
 | 
			
		||||
            name, reason = fields[15].split(',', maxsplit=1)
 | 
			
		||||
 | 
			
		||||
            records.append({
 | 
			
		||||
                'nethack_version': fields[0],
 | 
			
		||||
                'score': int(fields[1]),
 | 
			
		||||
                'dungeon_number': int(fields[2]),
 | 
			
		||||
                'dungeon_name': dungeon_name,
 | 
			
		||||
                'level': dungeon_level,
 | 
			
		||||
                'level_descriptive': dungeon_level_descriptive,
 | 
			
		||||
                'max_level': int(fields[4]),
 | 
			
		||||
                'hit_points': int(fields[5]),
 | 
			
		||||
                'max_hit_points': int(fields[6]),
 | 
			
		||||
                'number_of_deaths': int(fields[7]),
 | 
			
		||||
                'end_date': end_date,
 | 
			
		||||
                'start_date': start_date,
 | 
			
		||||
                'user_id': int(fields[10]),
 | 
			
		||||
                'role': ROLES[fields[11]],
 | 
			
		||||
                'race': RACES[fields[12]],
 | 
			
		||||
                'gender': GENDERS[fields[13]],
 | 
			
		||||
                'alignment': ALIGNMENTS[fields[14]],
 | 
			
		||||
                'name': name.strip(),
 | 
			
		||||
                'reason_for_death': reason.strip(),
 | 
			
		||||
            })
 | 
			
		||||
 | 
			
		||||
    json.dump(records, sys.stdout, indent=2)
 | 
			
		||||
    print('\n')
 | 
			
		||||
 | 
			
		||||
if __name__ == '__main__':
 | 
			
		||||
    import sys
 | 
			
		||||
    result = main(sys.argv)
 | 
			
		||||
    sys.exit(0 if not result else result)
 | 
			
		||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue