% ------------------------------------------------------------------------------------------------------
% SLA Contract between Fordnox Bank and AlwaysUp AG
% 
% Implements the SLA between these two companies
% ------------------------------------------------------------------------------------------------------

% module OID
module("sla_fordnox_alwaysup.prova").



:-eval(consult('ContractLog/math.prova')).
:-eval(consult('ContractLog/list.prova')).
:-eval(consult('ContractLog/list_math.prova')).
:-eval(consult('ContractLog/datetime.prova')).
:-eval(consult('ContractLog/timeinterval.prova')).
:-eval(consult('ContractLog/ecaruntime.prova')).
:-eval(consult('ContractLog/utils.prova')).

% ------------------------------------------------------------------------------------------------------
% Contract
% ------------------------------------------------------------------------------------------------------

% +++++++++++++++  collect data for availability ++++++++++++++++++++++

% start with empty data
%% data container
homepage_available([]).
categorya_available([]).
categoryb_available([]).

%ECA 1
eca(everyTenSec(DT),pingFailed(),_,assertFailed()).

%TIME
everyTenSec(DT) :-
	sysTime(DT),
	println(["Ping"]),
	(timespan(0,0,0,10), DT).

%EVENT
pingFailed() :-
	testWebserver(),println(["ping failed !!!!!!"]),!,fail().
pingFailed().

%CONDITION


%ACTION
assertFailed() :-
	sysTime(DT),
	timepoint_construct(TP, DT, "pingFailed"),
	save_timepoint(TP).

% ECA Rule: test homepage all 5 seconds

eca(eventFiveSec(DT),_,_,actionTestHomepage(DT)).

eventFiveSec(DT) :-
	sysTime(DT),
	(timespan(0,0,0,5), DT),
	println(["eventFiveSec DT:", DT]).

actionTestHomepage(DT) :-
	testWebserver(DT, OK),
	timepoint_construct(H, DT, OK),
	homepage_available(HS),
	append(HS, [H], HH),
	retractall(homepage_available(_)),
	assert(homepage_available(HH)),
	println(["Test Webserver: ", HH]),
	
	retractall(currentHomepageAvail(_)),
	assert(currentHomepageAvail(OK)).


% ECA Rule: test other services every minute
eca(eventMinute(DT),_,_,actionTestCategorieAandB(DT)).

eventMinute(DT) :-
	sysTime(DT),
	(timespan(0,0,0,10), DT).

actionTestCategorieAandB(DT) :-
	testCategoryA(DT, ARES),
	timepoint_construct(A, DT, ARES),
	
	categorya_available(AS),
	println(["Test Categorie : categorya_available (AS) AS: ", AS]),
	append(AS,[A],AA),
	println(["Test Categorie A : append(AS,[A], AA)", AA]),
	retractall(categorya_available(_)),
	assert(categorya_available(AA)),
	retractall(currentCategorieAAvail(_)),
	assert(currentCategorieAAvail(ARES)),
	
	testCategoryB(DT, BRES),
	timepoint_construct(B, DT, BRES),
	categoryb_available(BS),
	println(["Test Categorie : categoryb_available (BS) BS: ", BS]),
	append(BS, [B], BB),
	retractall(categoryb_available(_)),
	assert(categoryb_available(BB)),	
	println(["Test Categorie B : append(BS,[B], BB)", BB]),

	retractall(currentCategorieBAvail(_)),
	assert(currentCategorieBAvail(BRES)).



% +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++


%% +++++++++++++++ calculate availabilty ++++++++++++++++++++++	

%% Helpmethod	
% Calculate Availability for one timepoint list
	
availabiltyOneService(Points, R) :-
	println([" ---------------------  Report for availabiltyOneService ----------------------"]),
	println(["Points", Points]),
	timepoints_times(Points,L),
	println(["L ", L]),
	
	list_filter_between(time(0,0,0), time(0,1,0), L, MAINTIMELIST),
	println(["list_filter_between MAINTIMELIST = ", MAINTIMELIST]),
	list_filter_between(time(0,1,0), time(0,5,0), L, SERVICELIST),
	println(["list_filter_between SERVICELIST = ", SERVICELIST]),
	
	availability(Boolean.TRUE, MAINTIMELIST, MAINTIMEAVAIL),
	println(["availability MAINTIMEAVAIL = ", MAINTIMEAVAIL]),
	retractall(mainTimeAvail(_)),
	assert(mainTimeAvail(MAINTIMEAVAIL)),
	
	availability(Boolean.TRUE, SERVICELIST, SERVICEAVAIL),
	println(["availability SERVICEAVAIL = ", SERVICEAVAIL]),
	retractall(serviceTimeAvail(_)),
	assert(serviceTimeAvail(SERVICEAVAIL)),
	
	retractall(serviceAndMainTimeAvail(_)),
	assert(serviceAndMainTimeAvail(four(0.995, MAINTIMEAVAIL, 0.923, SERVICEAVAIL ))),
	
	math_add(SERVICEAVAIL,0.125,SERVICEAVAIL2),
	println(["math_add SERVICEAVAIL2 = ", SERVICEAVAIL2]),
	math_max(SERVICEAVAIL2, 1, SERVICEAVAIL3),
	println(["math_max SERVICEAVAIL3 = ", SERVICEAVAIL3]),
	math_mult(MAINTIMEAVAIL, 20, TOTALAVAIL1),
	println(["math_mult TOTALAVAIL1 = ", TOTALAVAIL1]),

	math_mult(SERVICEAVAIL, 4, TOTALAVAIL2),
	println(["math_mult TOTALAVAIL2 = ", TOTALAVAIL2]),

	math_add(TOTALAVAIL1, TOTALAVAIL2, TOTALAVAIL3),
	println(["math_mult TOTALAVAIL3 = ", TOTALAVAIL3]),

	math_div(TOTALAVAIL3, 24, R),
	println(["math_div R = ", R]),
	
	retractall(availabiltyOneService(_)),
	assert(availabiltyOneService(R)),
	
	println(["availabiltyOneService"]).
	
% Calculate Availability Penalty
%% Helpmethod	

availabilityPenalty(R):-
	println([" ---------------------  availabiltyPenalty ----------------------"]),
	
	homepage_available(HomepagePoints),
	availabiltyOneService(HomepagePoints, HomepageAvail),
	categorya_available(CatogeryaPoints),
	availabiltyOneService(CatogeryaPoints, Categorya_available),
	categoryb_available(CatogerybPoints),
	availabiltyOneService(CatogerybPoints, Categoryb_available),
	
	append(HomepageAvail,[],AVAIL1),
	append(AVAIL1,Categorya_available,AVAIL2),
	append(AVAIL2,Categoryb_available,AVAIL3),
	math_mean(AVAIL3, MEANAVAIL),
	math_mean(AVAIL1, MEANAVAIL),
	
	math_sub(0.995, MEANAVAIL, DIFF),
	math_max(0, DIFF, DIFF2),
	math_mult(DIFF2, 10, R),
	retractall(currentPenalty(_)),
	assert(currentPenalty(R)),
	
	println(["availabilityPenalty"]).


availabilityCategoryAPenalty(R):-
	println([" ---------------------  availabilityCategoryAPenalty ----------------------"]),
	
	categorya_available(CatogeryaPoints),
	availabiltyOneService(CatogeryaPoints, Categorya_available),

	append(Categorya_available,[],AVAIL1),
	math_mean(AVAIL1, MEANAVAIL),
	
	math_sub(0.995, MEANAVAIL, DIFF),
	math_max(0, DIFF, DIFF2),
	math_mult(DIFF2, 10, R),
	retractall(currentCategoryAPenalty(_)),
	assert(currentCategoryAPenalty(R)),
	
	println(["availabilityCategoryAPenalty"]).

% +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

	
%% +++++++++++++++ availabilty report ++++++++++++++++++++++	
%% Helpmethod	

printReport(TimeList):-
	println([" ---------------------  print Report for service ----------------------"]),
	println(["Timepoints: ", TimeList]),
	timepoints_times(TimeList,),
	println(["Status : ", ]),
	
	filter_status(Boolean.FALSE, , DOWNS),

	println(["Down : ", DOWNS]),
	retractall(downs(_)),
	assert(downs(DOWNS)),
	
	list_sum(DOWNS, DOWNTIME),
	println(["Downtime: ", DOWNTIME]),
	retractall(downTime(_)),
	assert(downTime(DOWNTIME)),
		
	list_max(DOWNS, MAXDOWNTIME),
	println(["Maxdowntime: ", MAXDOWNTIME]),
	retractall(maxDownTime(_)),
	assert(maxDownTime(MAXDOWNTIME)),

	list_min(DOWNS, MINDOWNTIME),
	println(["Mindowntime: ", MINDOWNTIME]),
	
	println(["printReport end"]).
	
	
% +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++	
	
%% +++++++++++++++ send report each week ++++++++++++++++++++++	

% ECA Rule: Send Report each week (every 5 minute)
eca(eventEachWeek(DT),_,_,actionReportSystem(DT)).
	
eventEachWeek(DT) :-
	sysTime(DT),
	(timespan(0,0,3,0), DT).

actionReportSystem(DT) :-
	homepage_available(HomepagePoints),
	printReport(HomepagePoints),
%	categorya_available(CatogeryaPoints),
%	printReport(CatogeryaPoints),
%	categoryb_available(CatogerybPoints),
%	printReport(CatogerybPoints),
	availabilityPenalty(PENALTY),

	println(["Penalty: ", PENALTY]).

% +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++	
	
%% +++++++++++++++ Test ECA Rule ++++++++++++++++++++++	

% ECA Rule: Send Report every 2 min.
eca(eventTwoMin(DT),_,_,actionReportSystemHomepage(DT)).
	
eventTwoMin(DT) :-
	sysTime(DT),
	(timespan(0,0,2,0), DT).

actionReportSystemHomepage(DT) :-
	println(["*** homepage_available: ***"]),

	homepage_available(HomepagePoints),
	printReport(HomepagePoints),
	availabiltyOneService(HomepagePoints, HomepageAvail),

	println(["actionReportSystemHomepage End"]).


% ECA Rule: caulate penalty of categoreyB every 15sec.
eca(event15Sec(DT),_,_,availabilityCategoryBPenalty(R)).
	
event15Sec(DT) :-
	sysTime(DT),
	(timespan(0,0,0,15), DT).

availabilityCategoryBPenalty(R):-
	println([" ---------------------  availabilityCategoryBPenalty ----------------------"]),
	
	categorya_available(CatogerybPoints),
	availabiltyOneService(CatogerybPoints, Categoryb_available),
	println(["availabiy One Service End  Categoryb_available =",Categoryb_available ]),
	
	%append(Categoryb_available,[],AVAIL1),
	%println(["append : ", AVAIL1]),
	
	%math_mean(AVAIL1, MEANAVAIL),
	%println(["math_mean : ", MEANAVAIL]),
	
	math_sub(0.995, Categoryb_available, DIFF),
	println(["math_sub : ", DIFF]),
	
	math_max(0, DIFF, DIFF2),
	println(["math_max : ", DIFF2]),
	
	math_mult(DIFF2, 10, R),
	println(["R : ", R]),
	
	retractall(currentCategoryBPenalty(_)),
	assert(currentCategoryBPenalty(R)),
	
	println(["availabilityCategoryBPenalty"]).

% ECA Rule: calulate panalty of homepage every 15 sec.
eca(event15Sec(DT),_,_,availabilityHomepagePenalty(R)).
	
event15Sec(DT) :-
	sysTime(DT),
	(timespan(0,0,0,15), DT).

availabilityHomepagePenalty(R):-
	println([" ---------------------  availabiltyHomepagePenalty ----------------------"]),
	
	homepage_available(HomepagePoints),
	availabiltyOneService(HomepagePoints, HomepageAvail),

	append(HomepageAvail,[],AVAIL1),
	math_mean(AVAIL1, MEANAVAIL),
	
	math_sub(0.995, MEANAVAIL, DIFF),
	math_max(0, DIFF, DIFF2),
	math_mult(DIFF2, 10, R),
	retractall(currentHomepagePenalty(_)),
	assert(currentHompagePenalty(R)),
	
	println(["availabilityHomagePenalty"]).

	
%% ++++++++++++++++++++ Test Vaule ++++++++++++++++++++++++++++

testWebserver(DT, Boolean.FALSE):-
	datetime_date_time(DT, D, T),	
	between(time(0,0,13), T, time(0,0,34)), 
	!.
testWebserver(DT, Boolean.FALSE):-
	datetime_date_time(DT, D, T),	
	between(time(0,1,10), T, time(0,1,50)), 
	!. 
testWebserver(DT, Boolean.FALSE):-
	datetime_date_time(DT, D, T),
	between(time(0,2,10), T, time(0,2,55)), 
	!. 
testWebserver(DT, Boolean.FALSE):-
	datetime_date_time(DT, D, T),
	between(time(0,3,10), T, time(0,3,55)), 
	!.
testWebserver(DT, Boolean.FALSE):-
	datetime_date_time(DT, D, T),
	between(time(0,4,10), T, time(0,4,45)), 
	!.
	
testWebserver(T, Boolean.TRUE).



testCategoryA(DT, Boolean.FALSE):-
	datetime_date_time(DT, D, T),	
	between(time(0,0,0), T, time(0,0,12)), 
	!.
	
testCategoryA(DT, Boolean.FALSE):-
	datetime_date_time(DT, D, T),	
	between(time(0,0,25), T, time(0,0,40)), 
	!. 
testCategoryA(DT, Boolean.FALSE):-
	datetime_date_time(DT, D, T),
	between(time(0,1,10), T, time(0,1,30)), 
	!. 
testCategoryA(DT, Boolean.FALSE):-
	datetime_date_time(DT, D, T),
	between(time(0,3,10), T, time(0,3,55)), 
	!.
testCategoryA(DT, Boolean.FALSE):-
	datetime_date_time(DT, D, T),
	between(time(0,4,10), T, time(0,4,45)), 
	!.
	
testCategoryA(T, Boolean.TRUE).



testCategoryB(DT, Boolean.FALSE):-
	datetime_date_time(DT, D, T),	
	between(time(0,0,32), T, time(0,0,40)), 
	!.
	
testCategoryB(DT, Boolean.FALSE):-
	datetime_date_time(DT, D, T),	
	between(time(0,1,20), T, time(0,1,44)), 
	!. 
testCategoryB(DT, Boolean.FALSE):-
	datetime_date_time(DT, D, T),
	between(time(0,2,15), T, time(0,2,30)), 
	!. 
testCategoryB(DT, Boolean.FALSE):-
	datetime_date_time(DT, D, T),
	between(time(0,3,10), T, time(0,3,55)), 
	!.
testCategoryB(DT, Boolean.FALSE):-
	datetime_date_time(DT, D, T),
	between(time(0,4,10), T, time(0,4,45)), 
	!.
	
testCategoryB(T, Boolean.TRUE).

%% ++++++++++++++++++++ User Interface ++++++++++++++++++++++++++++

customerServiceStatusLine("Dear customer service employee, this system is able verify a customer complaint. So in short words: I you get a ass kick from your customer you will have  proveable informations to give this ass kick directly to your admin. Just press start.").

eca(eventOneSecond(DT),_,actionWriteStatusLine(DT)).

actionWriteStatusLine(DT):-
	countOfServerDown(COUNT),
	currentTime(datetime(YEAR,MONTH,DAY,HOUR,MIN,SEC)),
	concat(["The SLA check system is working now. We now have ", HOUR, ":", MIN, ":", SEC, " o clock on ", DAY, ".", MONTH, ".", YEAR,". At the moment ", COUNT, " services do not work. For more information please look below."], STATUS),
	retractall(customerServiceStatusLine(_)),
	assert(customerServiceStatusLine(STATUS)).
	


countOfServerDown(COUNT):-
	currentHomepageAvail(X),
	currentCategorieAAvail(Y),
	currentCategorieBAvail(Z),
	append([X], [Y], XY),
	append(XY, [Z], XYZ),
	delete_all(Boolean.TRUE, XYZ, XYZfalse),
	println([XYZfalse]),
	size(XYZfalse, COUNT).