from copy import deepcopy

# Student project allocation algorithm function
def SPA(S, Ppref, Pc, Ms, Mp, MsPrev):
    '''
    Input:
    S : Student priorities
    Ppref: Project Priorities
    Pc: Counts for each project
    Ms: Empty structure for student results
    Mp: Empty structure for project results
    MsPrev: Empty structure for end case handling

    Output:
    Student to project mapping
    '''
    isStable = True
    for i in Ms.values():
        if len(i)==0:
            isStable = False
            break
    # print(isStable)
    # Part 2 (compute and return to the webapp)
    # Run algo
    while True:
        for stud in Ms.keys():
            if len(Ms[stud])==0 and len(S[stud])>0:
                # provisionally asigning
                # print("Current student: ", stud)
                proj = S[stud][0]
                # lec = P2L[proj]
                Ms[stud].append(proj)
                Mp[proj].append(stud)
                # check if project is oversubscibed
                while len(Mp[proj]) > Pc[proj]:
                    # find the least priority students assigned to the project
                    prefList = Ppref[proj] # pref order of current project
                    idx = len(prefList)-1
                    found = False
                    while not found:
                        if prefList[idx] in Mp[proj]:
                            Mp[proj].remove(prefList[idx])
                            Ms[prefList[idx]].remove(proj)
                            S[prefList[idx]].remove(proj)
                            prefList.remove(prefList[idx])
                            # print("Removing project: ", proj)
                            # print("from student: ", prefList[idx])
                            found = True
                        else:
                            idx -= 1
        # isStable = reduce(lambda x, y: (x and (len(y)>0), Ms.values(), True)
        # isStable = True
        # for i in Ms.values():
        #     if len(i)==0:
        #         isStable = False
        #         break

        if Ms == MsPrev:
            break

        MsPrev = deepcopy(Ms)

    return Ms

if __name__ == '__main__':
    S = {"s1": ["p1", "p2"], "s2": ["p1"]}
    Ppref = {"p1": [ "s2"], "p2": [ "s2"]}
    Pc = {"p1":1, "p2": 1}
    Ms = {"s1": [], "s2": []}
    Mp = {"p1": [], "p2": []}
    MsPrev = []
    for M in Ms:
        print(Ms[M])

    res = SPA(S, Ppref, Pc, Ms, Mp, MsPrev)
    for student in res:
        print(student,res[student])
