#!/usr/bin/env python3
# -*- coding: utf-8 -*-

from pprint import pprint

#read savegame
raw = []
with open("persistent.sfs") as handle:
    expectnew = False
    parse = None
    path = []
    last = []
    for num, line in enumerate(handle):
        data = line.strip().split(None, 2)
        if expectnew or data[0] == '{':
            assert(expectnew)
            assert(data[0] == '{')
            assert(len(data) == 1)
            expectnew = False
        elif data[0] == '}':
            path.pop()
            parse = last.pop()
        elif len(data) == 1:
            expectnew = True
            path.append(data[0])
            last.append(parse)
            if path == ['GAME', 'SCENARIO', 'Science']:
                parse = {}
                raw.append(parse)
            else:
                parse = None
        else:
            assert(data[1] == '=')
            if parse != None:
                parse[data[0]] = data[2]

#static definitions
situations = ('SrfLanded', 'SrfSplashed', 'FlyingLow', 'FlyingHigh', 'InSpaceLow', 'InSpaceHigh', 'FlewBy', 'Flew', 'SubOrbited', 'Orbited', 'Surfaced')
kscbiomes = ('KSC', 'Administration', 'AstronautComplex', 'Crawlerway', 'FlagPole', 'LaunchPad', 'MissionControl', 'R&D', 'Runway', 'SPH', 'TrackingStation', 'VAB')

#collected dynamically
experiments = set()
biomes = {}
science = {}

# collect what science is already done and which experiments, bodies & biomes are known
for item in raw:
    experiment ,_ ,pos = item['id'].partition('@')
    experiments.add(experiment)
    for sit in situations:
        body, situation, biome = pos.partition(sit)
        if situation:
            if body == 'Kerbin':
                for kscbiome in kscbiomes:
                    if biome.startswith(kscbiome):
                        body = 'KSC'
                        break
            cap = float(item['cap'])
            sci = float(item['sci'])
            science[(experiment, body, situation, biome)] = (cap-sci, cap)
            biomes.setdefault(body, set()).add(biome)
            break
    else:
        print(item['id'], item['title'])
        assert(False)

#infer that the same experiment can be done in the same situation and body but in a different biome
for item in science.copy().items():
    (experiment, body, situation, biome), (value, cap) = item
    if biome:
        for other in biomes[body]:
            if other:
                science.setdefault((experiment, body, situation, other), (cap, cap))

#agregate among different dimensions
byfullsit = {} #exactly the same place
bybiome = {} #different situations in the same biome
bysit = {} #different biomes in the same situation, but not on the surface (unless KSC)
for item in science.items():
    (experiment, body, situation, biome), (value, cap) = item
    x = byfullsit.setdefault((body, situation, biome), [0, 0])
    x[0] += value
    x[1] += cap
    x = bybiome.setdefault((body, biome), [0, 0])
    x[0] += value
    x[1] += cap
    if body == 'KSC' or not situation.startswith('Srf'):
        x = bysit.setdefault((body, situation), [0, 0])
        x[0] += value
        x[1] += cap

# add biome inspecivic experiments to all biomes
for item in byfullsit.items():
    (body, sit, biome) = item[0]
    if biome:
        x = byfullsit.get((body, sit, ''), [0,0])
        item[1][0] += x[0]
        item[1][1] += x[1]
for item in bybiome.items():
    (body, biome) = item[0]
    if biome:
        x = bybiome.get((body, ''), [0,0])
        item[1][0] += x[0]
        item[1][1] += x[1]

def itemwithmaxval(d):
     v=list(d.values())
     k=list(d.keys())
     m=max(v)
     return k[v.index(m)],m

bestsingle = itemwithmaxval(science)
bestfullsit = itemwithmaxval(byfullsit)
bestbiome = itemwithmaxval(bybiome)
bestsit = itemwithmaxval(bysit)

best = max([bestsingle[1][0]*1.3,0], [bestfullsit[1][0]*1.2,1], [bestbiome[1][0]*1.1,2], [bestsit[1][0],3])
if best[1] == 0: #single
    if bestsingle[0][3]:
        print("{0} while {2} in the {3} area of {1}. We should definatly try to do that.".format(*bestsingle[0]))
    else:
        print("{1}! {0}! While {2}! We really need to do this".format(*bestsingle[0]))
elif best[1] == 1: #fullsit
    (body, sit, biome), (val, cap) = bestfullsit
    result = itemwithmaxval({x:y for x,y in science.items() if x[1] == body and x[2] == sit and x[3] in (biome, "")})
    if result[0][3]:
        print("Experiments while {2} in the {3} area of {1} sound good. Maybe some {0}.".format(*result[0]))
    else:
        print("There is a lot about {2} on {1} we don't know. Like {0} and such.".format(*result[0]))
    pass
elif best[1] == 2: #biome
    (body, biome), (val, cap) = bestbiome
    result = itemwithmaxval({x:y for x,y in science.items() if x[1] == body and x[3] in (biome, "")})
    if result[0][3]:
        print("The {3} area of {1} looks really interesting. Maybe we should try to {0} while {2} there.".format(*result[0]))
    else:
        print("We need to know more about {1}. For example {0} while {2}.".format(*result[0]))
else: #sit
    (body, sit), (val, cap) = bestsit
    result = itemwithmaxval({x:y for x,y in science.items() if x[1] == body and x[2] == sit})
    if result[0][3]:
        print("Go and do experiments while {2} on {1}. Like {0} in the {3} area.".format(*result[0]))
    else:
        print("We should try {2} on {1}. Why don't we do some {0} there.".format(*result[0]))
