import sys
import os
import traceback

DEBUG = False

# scheme format:
# [case string, [avg_wait, max_wait, overall_wait, total_sim], [scores] ]
# -1: skip
AVG_WT_IDX = 0
MAX_WT_IDX = 1
OVA_WT_IDX = 2
TOT_SIM_IDX = 3

CHK_ARR_STR = ["avg_wait", "max_wait", "overall_wait", "total_sim"]
scheme = [
    ["sp3 1 150 1 1 0", [0, -1, -1, -1], [2, 0, 0, 0]],
    ["sp3 1 150 1 1 1", [0, -1, -1, -1], [2, 0, 0 ,0]],
    ["sp3 5 100 10 1 0", [-1, -1, 10, -1], [0, 0, 3, 0] ],
    ["sp3 5 100 10 1 0", [-1, -1, 10, -1], [0, 0, 2, 0] ],
    ["sp3 2 300 0 1 1", [-1, 18, -1, 6], [0, 1.5, 0, 1.5] ],    
    ["sp3 2 300 0 1 1", [-1, 18, -1, 6], [0, 1, 0, 1] ],
    ["sp3 6 100 0 1 0", [-1, 58, -1, 5], [0, 1.5, 0, 1.5] ],
    ["sp3 6 100 0 1 1", [-1, 58, -1, 5], [0, 1, 0, 1] ],
    ["sp3 10 80 0 1 0", [-1, 98, -1, 4], [0, 1.5, 0, 1.5] ],
    ["sp3 10 80 0 1 1", [-1, 98, -1, 4], [0, 1, 0, 1] ],
]

def mark_case(lines, param, chk_arr, grd_arr):
    if DEBUG:
        print("\nChecking " + param + " ...")
    total_succ = [True, True, True, True]
    parsed_succ = [0, 0, 0, 0]
    failed_succ = [-1, -1, -1, -1]

    start = False
    for line in lines:
        if line.startswith("========================== Using parameters"):
            if not start:
                if line.find(param) != -1:
                    start = True
                continue
            else:
                # next case
                break

        if not start:
            continue
        
        if  line.startswith("N:") or \
            line.startswith("E:") or \
            line.startswith("S:") or \
            line.startswith("W:"):

            elements = line.split()
            if len(elements) != 11:
                raise Exception("Line " + line + " cannot be parsed")
            
            parsed_succ[AVG_WT_IDX] = int(float(elements[5]) * 1000)
            parsed_succ[MAX_WT_IDX] = int(float(elements[9]) * 1000)

            if DEBUG:
                print("Parsed: \"" + line + "\" " + " a_wait: " + str(parsed_succ[AVG_WT_IDX]) + " m_wait: " + str(parsed_succ[MAX_WT_IDX]))

            if total_succ[AVG_WT_IDX] and (chk_arr[AVG_WT_IDX] != -1) and (parsed_succ[AVG_WT_IDX] > chk_arr[AVG_WT_IDX]):
                total_succ[AVG_WT_IDX] = False
                failed_succ[AVG_WT_IDX] = parsed_succ[AVG_WT_IDX]
            
            if total_succ[MAX_WT_IDX] and (chk_arr[MAX_WT_IDX] != -1) and (parsed_succ[MAX_WT_IDX] > chk_arr[MAX_WT_IDX]):
                total_succ[MAX_WT_IDX] = False
                failed_succ[MAX_WT_IDX] = parsed_succ[MAX_WT_IDX]
            
            
            continue
        
        if line.startswith("all:"):
            elements = line.split()
            if len(elements) != 7:
                raise Exception("Line " + line + " cannot be parsed")
            parsed_succ[OVA_WT_IDX] = float(elements[4])

            if DEBUG:
                print("Parsed: \"" + line + "\" " + " avg_time: " + str(parsed_succ[OVA_WT_IDX]))
            
            if total_succ[OVA_WT_IDX] and (chk_arr[OVA_WT_IDX] != -1) and (parsed_succ[OVA_WT_IDX] > chk_arr[OVA_WT_IDX]):
                total_succ[OVA_WT_IDX] = False
                failed_succ[OVA_WT_IDX] = parsed_succ[OVA_WT_IDX]

        if line.startswith("Simulation: "):
            elements = line.split()
            if len(elements) != 5:
                print("Line " + line + " cannot be parsed")
                exit(1)
            parsed_succ[TOT_SIM_IDX] = float(elements[1])

            if DEBUG:
                print("Parsed: \"" + line + "\" " + " sim_time: " + str(parsed_succ[TOT_SIM_IDX]))

            if total_succ[TOT_SIM_IDX] and (chk_arr[TOT_SIM_IDX] != -1) and (parsed_succ[TOT_SIM_IDX] > chk_arr[TOT_SIM_IDX]):
                total_succ[TOT_SIM_IDX] = False
                failed_succ[TOT_SIM_IDX] = parsed_succ[TOT_SIM_IDX]

    if not start:
        raise Exception("Case " + param + " not found ")
    
    print("Case \"" + param + "\":")

    total_mark = 0
    for i in range(len(total_succ)):
        if not total_succ[i]:
            print("    [FAIL +0] " + CHK_ARR_STR[i] + " " + str(failed_succ[i]) + " > " + str(chk_arr[i]))
        else:
            if chk_arr[i] != -1:
                print("    [PASS +" + str(grd_arr[i]) + "] " + CHK_ARR_STR[i])
                total_mark = total_mark + grd_arr[i]

    return total_mark

def mark(fp: str):
    with open(fp, "r") as f:
        lines = f.read().splitlines()

    tot_mark = 0
    for i in range(0, len(scheme)):
        tot_mark = tot_mark + mark_case(lines, scheme[i][0], scheme[i][1], scheme[i][2])
    
    print("Total mark: " + str(tot_mark))


def mark_dir(fp: dir):
    for ed in os.walk(fp):
        try:
            print("Username: " + os.path.basename(ed[0]))
            mark(os.path.join(fp, ed[0], "runTests.log"))
        except Exception as e:
            print("Failed to mark due to: " + str(e))
            #traceback.print_exc()

        print("\n")

def main():
    if len(sys.argv) != 2:
        print("Usage: python mark.py [student submission dir]")
        exit(1)

    mark_dir(sys.argv[1])

main()