import sys
import os

global gmax

def byte(x):
    return x.to_bytes(1,sys.byteorder)

class SemiGroup:
    def __init__(self,parent=None,x=None):
        if parent==None and x==None:
            self.m=1
            self.c=1
            self.g=0
            self.d=bytearray(3*gmax+1)
            for i in range(3*gmax+1):
                self.d[i]=1+int(i/2)
        elif parent!=None and x==None:
            self.m=parent
            self.c=self.m
            self.g=self.m-1
            self.d=bytearray(3*gmax+1)
            self.d[0]=1
            for i in range(1,2*self.m):
                self.d[i]=int(i/self.m)
            for i in range(3*gmax+1-2*self.m):
                self.d[i+2*self.m]=2+int(i/2)
        elif parent!=None and x!=None:
            if not parent.is_valid_irreductible(x):
                raise AttributeError("x is not irreducible")
            if x<parent.c:
                raise AttributeError("x is not effective")
       
            if parent.m==x:
                self.delta=1
                self.m=x+1
            else:
                if parent.d[x+parent.m]==2:
                    self.delta=0
                else:
                    self.delta=-1
            self.g=parent.g+1
            self.m=parent.m
            self.c=x+1
            self.d=bytearray(3*gmax+1)
            for y in range(x):
                self.d[y]=parent.d[y]
            self.d[x]=0
            for y in range(x+1,3*gmax+1):
                self.d[y]=parent.d[y]-min(1,parent.d[y-x])
            
    def __repr__(self):
        res='<'
        first=True
        for i in range(self.m,self.m+self.c+1):
            if self.d[i]==1:
                if not first:
                    res+=','
                res+=repr(i)
                first=False
        return res+'>'+' g='+repr(self.g)

    def is_valid_irreductible(self,x):
        if x<0 or x>3*gmax:
            raise AttributeError("x is out of range")
        return self.d[x]==1 and x!=self.m

    def split_sons(self):
        first=None
        other=[]
        for x in range(self.c,self.c+self.m):
            if self.is_valid_irreductible(x):
                if first==None:
                    first=SemiGroup(self,x)
                else:
                    other.append(SemiGroup(self,x))
        return (first,other)

    def record(self,file):
        file.write(byte(self.c))
        file.write(byte(S.g))
        file.write(byte(S.m))
        file.write(self.d)
        
if __name__=="__main__":
    file=open("genus","r")
    gmax=int(file.readline())
    file.close()
    print("Generate wilf program ...")
    os.system("cd c++;make;cd ..")
    print("Generate OAR tasks for cutted explorations of numerical semigroup up to genus",gmax,"...")
    mmax=int((3*(gmax+2))/5)
    param_file=open("oar/param","w")
    for m in range(3,mmax+1):
        S=SemiGroup(m)
        for k in range(gmax-m+1):
            (S,Others)=S.split_sons()
            task_filename="task_"+repr(m)+"_"+repr(k)
            task_file=open("tasks/"+task_filename,"wb")
            task_file.write(len(Others).to_bytes(8,sys.byteorder))
            task_file.write(byte(S.g))
            task_file.write(byte(S.m))
            for T in Others:
                T.record(task_file)
            task_file.close()
            param_file.write(task_filename+"\n")
    param_file.close()
    print("Generate OAR script ...")
    file=open("oar_wilf.sh",'w')
    file.write("#!/bin/sh\n")
    file.write("#OAR -l core=1,walltime=1:00:00\n")
    file.write("#OAR -t idempotent\n")
    file.write("#OAR -q besteffort\n")
    file.write("#OAR -t besteffort\n")
    file.write("#OAR --checkpoint 60\n")
    file.write("#OAR --signal 12\n")
    file.write("#OAR --array-param-file oar/param\n")
    file.write("#OAR -O oar/output/j%jobid%\n")
    file.write("#OAR -E oar/error/j%jobid%\n")
    file.write("cd /nfs/home/lmpa/jfromentin/wilf\n")
    file.write("./wilf tasks/$*\n")
    file.write("mv tasks/$* tasks/done")
    file.write("mv tasks/$*-out tasks/out")
    file.close()
            
        
