Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Download

GAP 4.8.9 installation with standard packages -- copy to your CoCalc project to get it

1035298 views
################################################################################
##
##  simpcomp / tools.gi
##
##  Miscellaneous functions   
##
##  $Id$
##
################################################################################

SCSettings.SCMailAddress:="";
SCSettings.SCMailEnabled:=false;
SCSettings.SCMailMinInterval:=3600; # 1h
SCSettings.SCMailPendingMsg:="";
SCSettings.SCMailTimeLastMsg:=-1;
SCSettings.SCTimer:=-1;


SCIntFunc.GetProgramOutput:=
function(program,params)
	local syspath,prog,out,tmp;
	syspath:=DirectoriesSystemPrograms();
	
	if(syspath=fail) then
		Info(InfoWarning,1,"simpcomp: could not determine system programs path.");
		return fail;
	fi;
	
	prog:=Filename(syspath,program);

	if(prog=fail) then
		Info(InfoWarning,1,"simpcomp: could not call external process \"",program,"\".");
		return fail;
	fi;
	
	out:="";
	tmp:=OutputTextString(out,true);
	Process(DirectoryCurrent(),prog,InputTextNone(),tmp,params);
	CloseStream(tmp);
	
	return out;
end;


SCIntFunc.ArrayLineString:=
function(list)
	local i,out;

	out:="";
	for i in [1..Length(list)] do
		if(not IsBound(list[i])) then
			continue;
		fi;
		Append(out,String(list[i]));
		Append(out,"\n");
	od;
	return out;
end;



SCIntFunc.GetCurrentTimeString:=
function()
	local time,timestring;
	time:=DMYhmsSeconds(IO_gettimeofday().tv_sec);
	if time = fail then
		Info(InfoWarning,1,"simpcomp: could not determine system time.");
		return fail;
	fi;
	if time[1] < 10 then
		time[1] := Concatenation("0",String(time[1]));
	else
		time[1] := String(time[1]);
	fi;
	if time[2] < 10 then
		time[2] := Concatenation("0",String(time[2]));
	else
		time[2] := String(time[2]);
	fi;
	if time[4] < 10 then
		time[4] := Concatenation("0",String(time[4]));
	else
		time[4] := String(time[4]);
	fi;
	if time[5] < 10 then
		time[5] := Concatenation("0",String(time[5]));
	else
		time[5] := String(time[5]);
	fi;
	if time[6] < 10 then
		time[6] := Concatenation("0",String(time[6]));
	else
		time[6] := String(time[6]);
	fi;
	timestring:=Concatenation(String(time[3]),"-",time[2],"-",time[1],"_",time[4],"-",time[5],"-",time[6]);
	if timestring = fail then
		Info(InfoWarning,1,"simpcomp: could not determine system time.");
		return fail;
	fi;
	return timestring;
end;

SCIntFunc.SanitizeFilename:=
function(fname)
	local san,i,legalspecialchars;

	legalspecialchars:="_-+=,.#()[]!/";
	san:=[];
	for i in [1..Length(fname)] do
		if(not IsAlphaChar(fname[i]) and not IsDigitChar(fname[i]) and not fname[i] in legalspecialchars) then
			continue;
		else
			Add(san,fname[i]);
		fi;
	od;

	return san;
end;

SCIntFunc.GetHostname:=
function()
	local hostname;
	hostname:=IO_gethostname();
	if hostname = fail then
		return "unknown";
	else
		return hostname;
	fi;
end;

SCIntFunc.GetSystemType:=
function()
	local systype;
	systype:=Chomp(SCIntFunc.GetProgramOutput("uname",["-a"]));
	if systype = fail then
		return "unknown";
	else
		return systype;
	fi;
end;

SCIntFunc.GetCurrentTimeInt:=
function()
	local out;
	out:=IO_gettimeofday().tv_sec;
	if(out=fail) then
		Info(InfoWarning,1,"simpcomp: could not determine system time.");
		return fail;
	else
		return out;
	fi;
end;

SCIntFunc.ConvertTimespanToString:=
function(t1,t2)
	local i,div,span,str,tmp,conv,convstr;

	if(t2<t1) then
		return fail;
	fi;

	str:="";
	span:=t2-t1;

	conv:=[1,60,60,24];
	convstr:=["second","minute","hour","day"];

	for i in Reversed([1..Length(conv)]) do
		div:=Product(conv{[1..i]});
		if(span>=div or div=1) then
			tmp:=Int(span/div);
			if(not IsEmptyString(str)) then
				Append(str,", ");
			fi;
			Append(str,Concatenation([String(tmp)," ",convstr[i]]));
			if(tmp<>1) then Append(str,"s"); fi;
			span:=span mod div;
		fi;
	od;

	return str;
end;

################################################################################
##<#GAPDoc Label="SCMailSetMinInterval">
## <ManSection>
## <Func Name="SCMailSetMinInterval" Arg="interval"/>
## <Returns><K>true</K> upon success, <K>fail</K> otherwise.</Returns>
## <Description>
## Sets the minimal time interval in seconds that mail messages can be sent by <Package>simpcomp</Package>. This prevents a flooding of the specified email address with messages sent by <Package>simpcomp</Package>. Default is 3600, i.e. one hour. 
## <Example>
## gap> SCMailSetMinInterval(7200);
## true
## </Example>
## </Description>
## </ManSection>
##<#/GAPDoc>
################################################################################
InstallGlobalFunction(SCMailSetMinInterval,
function(interval)
	if(interval<0) then
		return fail;
	fi;

	SCSettings.SCMailMinInterval:=interval;
	return true;
end);


################################################################################
##<#GAPDoc Label="SCMailSetAddress">
## <ManSection>
## <Func Name="SCMailSetAddress" Arg="address"/>
## <Returns><K>true</K> upon success, <K>fail</K> otherwise.</Returns>
## <Description>
## Sets the email address that should be used to send notification messages and enables the mail notification system by calling <Ref Func="SCMailSetEnabled" />(<K>true</K>).
## <Example>
## gap> SCMailSetAddress("johndoe@somehost");
## true
## </Example>
## </Description>
## </ManSection>
##<#/GAPDoc>
################################################################################
InstallGlobalFunction(SCMailSetAddress,
function(address)
	if(IsEmptyString(address)) then
		return fail;
	fi;

	SCSettings.SCMailAddress:=address;
	return SCMailSetEnabled(true);
end);

################################################################################
##<#GAPDoc Label="SCMailSetEnabled">
## <ManSection>
## <Func Name="SCMailSetEnabled" Arg="flag"/>
## <Returns><K>true</K> upon success, <K>fail</K> otherwise.</Returns>
## <Description>
## Enables or disables the mail notification system of <Package>simpcomp</Package>. By default it is disabled. Returns <K>fail</K> if no email message was previously set with <Ref Func="SCMailSetAddress" />.
## <Example>
## gap> SCMailSetAddress("johndoe@somehost"); #enables mail notification
## true
## gap> SCMailSetEnabled(false);
## true
## </Example>
## </Description>
## </ManSection>
##<#/GAPDoc>
################################################################################
InstallGlobalFunction(SCMailSetEnabled,
function(flag)
	if(not "mail" in SCIntFunc.ExternalProgramsAvailable or IsEmptyString(SCSettings.SCMailAddress)) then
		return fail;
	fi;

	SCMailClearPending();

	if(flag=true) then
		SCSettings.SCMailTimeLastMsg:=-1;
	fi;

	SCSettings.SCMailEnabled:=flag;
	return true;
end);


################################################################################
##<#GAPDoc Label="SCMailSend">
## <ManSection>
## <Func Name="SCMailSend" Arg="message [,starttime] [,forcesend]"/>
## <Returns><K>true</K> when the message was sent, <K>false</K> if it was not send, <K>fail</K> upon an error.</Returns>
## <Description>
## Tries to send an email to the address specified by <Ref Func="SCMailSetAddress" /> using the Unix program <C>mail</C>. The optional parameter <Arg>starttime</Arg> specifies the starting time (as the integer Unix timestamp) a calculation was started (then the duration of the calculation is included in the email), the optional boolean parameter <Arg>forcesend</Arg> can be used to force the sending of an email, even if this violates the minimal email sending interval, see <Ref Func="SCMailSetMinInterval" />.
## <Example>
## gap> SCMailSetAddress("johndoe@somehost"); #enables mail notification
## true
## gap> SCMailIsEnabled();
## true
## gap> SCMailSend("Hello, this is simpcomp.");
## true
## </Example>
## </Description>
## </ManSection>
##<#/GAPDoc>
################################################################################
InstallGlobalFunction(SCMailSend,
function(arg)
	local message,recipient,starttime,curtime,path,mail,instream,outstream,host,fullinfo,ret,runtime,forcewrite;

	if(Length(arg)<1 or (Length(arg)>0 and not IsString(arg[1])) or (Length(arg)>1 and not IsInt(arg[2]) and not IsBool(arg[2])) or (Length(arg)>2 and not (IsInt(arg[2]) or not IsBool(arg[3])))) then
		Info(InfoSimpcomp,1,"SCMailSend: invalid parameters.");
		return fail;
	fi;

	message:=arg[1];

	forcewrite:=false;
	starttime:=fail;
	if(Length(arg)>1) then
		if(IsInt(arg[2])) then
			starttime:=arg[2];
		else
			forcewrite:=arg[2];
		fi;
	fi;
	curtime:=fail;

	if(Length(arg)>2) then
		forcewrite:=arg[3];
	fi;

	if(not SCSettings.SCMailEnabled or IsEmptyString(SCSettings.SCMailAddress) or IsEmptyString(message)) then
		return false;
	fi;

	recipient:=SCSettings.SCMailAddress;
	path:=DirectoriesSystemPrograms();
	curtime:=SCIntFunc.GetCurrentTimeInt();
	mail:=Filename(path,"mail");
	if(mail=fail) then
		Info(InfoSimpcomp,1,"SCMail: sending mail failed.");
		return fail;
	fi;


	if(path=fail or curtime=fail) then
		Info(InfoSimpcomp,1,"SCMail: getting current time failed.");
		return fail;
	fi;


	if(Length(message)<2 or (message[Length(message)-1]<>'\n' or message[Length(message)]<>'\n')) then
		if(message[Length(message)]='\n') then
			message:=Concatenation(message,"\n");
		else
			message:=Concatenation(message,"\n\n");
		fi;
	fi;

	if(SCSettings.SCMailTimeLastMsg<>-1 and not SCSettings.SCMailMinInterval=0 and SCSettings.SCMailTimeLastMsg+SCSettings.SCMailMinInterval>curtime and not forcewrite) then
		SCSettings.SCMailPendingMsg:=message;
		return false;
	fi;


	host:=SCIntFunc.GetHostname();
	if host = fail then
		Info(InfoSimpcomp,1,"SCMail: getting hostname failed.");
		return fail;
	fi;
	fullinfo:=SCIntFunc.GetSystemType();
	if fullinfo = fail then
		Info(InfoSimpcomp,1,"SCMail: getting system type failed.");
		return fail;
	fi;

	if(starttime<>fail and curtime<>fail) then
		runtime:=Concatenation([" for ",SCIntFunc.ConvertTimespanToString(starttime,curtime)]);
	else
		runtime:="";
	fi;


	outstream:=OutputTextNone();
	instream:=InputTextString(Concatenation(["\nGreetings master,\n\nthis is simpcomp ",SCIntFunc.Version," running on ",host," (",fullinfo,"), GAP ",GAPInfo.Version,".\n\nI have been working hard",runtime," and have a message for you, see below.\n\n#### START MESSAGE ####\n\n",message,"##### END MESSAGE #####\n\nThat's all, I hope this is good news! Have a nice day.\n",String(CHAR_INT(4))]));;

	ret:=Process(path[1],mail,instream,outstream,["-s",Concatenation(["Message from simpcomp ",SCIntFunc.Version," running on ",host]),recipient]);

	if(ret<>0) then
		SCSettings.SCMailPendingMsg:=message;
	else
		SCSettings.SCMailPendingMsg:="";
		SCSettings.SCMailTimeLastMsg:=curtime;
	fi;

	return ret=0;
end);

################################################################################
##<#GAPDoc Label="SCMailSendPending">
## <ManSection>
## <Func Name="SCMailSendPending" Arg=""/>
## <Returns><K>true</K> upon success, <K>fail</K> otherwise.</Returns>
## <Description>
## Tries to send a pending email of the <Package>simpcomp</Package> email notification system. Returns <K>true</K> on success or if there was no mail pending.
## <Example>
## gap> SCMailSendPending();
## true
## </Example>
## </Description>
## </ManSection>
##<#/GAPDoc>
################################################################################
InstallGlobalFunction(SCMailSendPending,
function()
	local ret;

	if(SCSettings.SCMailEnabled=false) then
		return false;
	fi;

	if(IsEmptyString(SCSettings.SCMailPendingMsg)) then
		return true;
	fi;

	return SCMailSend(SCSettings.SCMailPendingMsg);
end);


################################################################################
##<#GAPDoc Label="SCMailIsPending">
## <ManSection>
## <Func Name="SCMailIsPending" Arg=""/>
## <Returns><K>true</K> or <K>false</K> upon success, <K>fail</K> otherwise.</Returns>
## <Description>
## Returns <K>true</K> when an email of the <Package>simpcomp</Package> email notification system is pending, <K>false</K> otherwise.
## <Example>
## gap> SCMailIsPending();
## false
## </Example>
## </Description>
## </ManSection>
##<#/GAPDoc>
################################################################################
InstallGlobalFunction(SCMailIsPending,
function()
	return not IsEmptyString(SCSettings.SCMailPendingMsg);
end);


################################################################################
##<#GAPDoc Label="SCMailIsEnabled">
## <ManSection>
## <Func Name="SCMailIsEnabled" Arg=""/>
## <Returns><K>true</K> or <K>false</K> upon success, <K>fail</K> otherwise.</Returns>
## <Description>
## Returns <K>true</K> when the mail notification system of <Package>simpcomp</Package> is enabled, <K>false</K> otherwise. Default setting is <K>false</K>.
## <Example>
## gap> SCMailSetAddress("johndoe@somehost"); #enables mail notification
## true
## gap> SCMailIsEnabled();
## true
## </Example>
## </Description>
## </ManSection>
##<#/GAPDoc>
################################################################################
InstallGlobalFunction(SCMailIsEnabled,
function()
	return SCSettings.SCMailEnabled;
end);



################################################################################
##<#GAPDoc Label="SCMailClearPending">
## <ManSection>
## <Func Name="SCMailClearPending" Arg=""/>
## <Returns>nothing.</Returns>
## <Description>
## Clears a pending mail message.
## <Example>
## gap> SCMailClearPending();
## </Example>
## </Description>
## </ManSection>
##<#/GAPDoc>
################################################################################
InstallGlobalFunction(SCMailClearPending,
function()
	SCSettings.SCMailPendingMsg:="";
end);



SCIntFunc.TimerStart:=
function()
	local t;
	t:=SCIntFunc.GetCurrentTimeInt();
	if(t=fail) then
		return fail;
	fi;
	SCSettings.SCTimer:=t;
	return t;
end;

SCIntFunc.TimerStop:=
function()
	SCSettings.SCTimer:=-1;
end;


SCIntFunc.TimerElapsed:=
function()
	local t,test;

	if(SCSettings.SCTimer=-1) then
		return fail;
	fi;

	t:=SCIntFunc.GetCurrentTimeInt();

	if(t=fail) then
		return fail;
	fi;

	return t-SCSettings.SCTimer;
end;


#reread the package
SCReread:=
function()
	Print("rereading init.g ",RereadPackage("simpcomp","init.g"),"\n");
	Print("rereading read.g ",RereadPackage("simpcomp","read.g"),"\n");
end;


#make gapdoc documentation
SCIntFunc.MakeDoc:=function(arg)
	
	local path, ext, f, main, files, b, bookname,basenames, cp;
	
	basenames:=["class3mflds", "propobject", "bistellar", "complex", "generate", 
    "glprops", "io", "labelops", "lib", "operations", "tools", "homology", 
    "morse", "normalsurface", "prophandler", "fromgroup", "blowups", 
    "pkghomalg", "highlySymmetricSurfaces", "isosig", "DMT"
	];
	
	cp:="gapdoc/";
		
	if Length(arg) = 1 and IsBool(arg[1]) and arg[1]=true then
		cp:="../lib/";
	elif Length(arg) >= 1 then
		basenames:=arg;
		cp:="gapdoc/";
	fi;
	
	files:=[];
	path:=DirectoriesPackageLibrary("simpcomp", "doc");

	for b in basenames do
		for ext in [".gd",".gi"] do
			f:=Concatenation(cp,b,ext);
			if(Filename(path[1],f)<>fail) then
				Add(files, f);
			fi;
		od;
	od;
	
	bookname:="<Package>simpcomp</Package>";;
	MakeGAPDocDoc(path[1], "simpcomp", files, bookname);

	return true;
end;



#function availability test
SCIntFunc.CheckExternalProgramsAvailability:=
function()
	local path,programs,p;
	
	path:=DirectoriesSystemPrograms();
	programs:=["date","hostname","uname","mail"];

	SCIntFunc.ExternalProgramsAvailable:=[];
	
	if(IsBound(GAPInfo.UserHome) and GAPInfo.UserHome<>fail and IsString(GAPInfo.UserHome) and not IsEmpty(GAPInfo.UserHome)) then
		SCIntFunc.UserHome:=GAPInfo.UserHome;
	else
		SCIntFunc.UserHome:="";
	fi;
	
	if(path=fail) then
		return fail;
	fi;

	for p in programs do 
		if Filename(path,p)<>fail then
			Add(SCIntFunc.ExternalProgramsAvailable,p);
		fi;
	od;
end;


################################################################################
##<#GAPDoc Label="SCRunTest">
## <ManSection>
## <Func Name="SCRunTest" Arg=""/>
## <Returns><K>true</K> upon success, <K>fail</K> otherwise.</Returns>
## <Description>
## Test whether the package <Package>simpcomp</Package> is functional by calling <C>Test("GAPROOT/pkg/simpcomp/tst/simpcomp.tst",rec(compareFunction := "uptowhitespace"));</C>. The returned value of GAP4stones is a measure of your system performance and differs from system to system.
## <Example>
## gap> SCRunTest();
## + test simpcomp package, version 2.1.7
## + GAP4stones: 69988
## true
## </Example>
## </Description>
## </ManSection>
##<#/GAPDoc>
################################################################################
InstallGlobalFunction(SCRunTest,
function()
	local path;
  path:=DirectoriesPackageLibrary("simpcomp", "tst");
  return Test(Filename(path,"simpcomp.tst"), rec( compareFunction := "uptowhitespace" ));
end);