<commit_before>%% @author <NAME> <<EMAIL>>, <NAME> <<EMAIL>>
%%   [www.csproj13.student.it.uu.se]
%% @version 1.0
%% @headerfile "json.hrl"
%% @copyright [Copyright information]
%%
%% @doc == api_help ==
%% This module will contain all help functions used by the
%% api files 
%%
%% @end
-module(api_help).
-include_lib("erlastic_search.hrl").
-include("json.hrl").

-export([any_to_float/1,
	 do_any_field_exist/2,
	 do_only_fields_exist/2,
	 generate_date/1,
	 generate_error/2,
	 generate_timestamp/2,
	 get_elastic_search_url/0,
	 get_webmachine_url/0,
	 get_and_add_id/1,
	 get_list_and_add_id/1,
	 get_list_and_add_id/2,
	 get_and_add_password/1,
	 get_list_and_add_password/1,
	 is_polling_history/1,
	 is_rank/1,
	 is_search/1,
	 is_subs/1,
	 is_unsubs/1,
	 json_handler/2,
	 make_term_query/1,
	 pair/1,
	 parse_path/1,
	 refresh/0,
	 transform/1,
	 transform/2,
	 update_doc/4,
	 update_doc/5
	]).

%% @doc
%% Purpose: Tries really hard to convert to float
%% Returns: float() or error
%% 
%% @end
-spec any_to_float(any()) -> float().
any_to_float(Val) when is_float(Val) -> Val;
any_to_float(Val) when is_integer(Val) -> float(Val);
any_to_float(Val) when is_binary(Val) -> any_to_float(binary_to_list(Val));
any_to_float(".") -> error;
any_to_float(Val) when is_list(Val) ->
	case lists:prefix(".", Val) of
		true -> PointVal = "0"++Val;
		false -> PointVal = Val
	end,
	case lists:prefix("-.", PointVal) of
		true -> NewVal = "-0"++tl(PointVal);
		false -> NewVal = PointVal
	end,
    case string:to_float(NewVal) of
        {error,no_float} -> 
        	try
        		case list_to_integer(NewVal) of
        			{error, no_integer} -> error;
        			V -> float(V)
        		end
        	catch error:badarg ->
        		error
        	end;
        {F,_Rest} -> F
    end;
any_to_float(Val) ->
	error.

%% @doc
%% Function: count_fields/1
%% Purpose: Used to return the number of fields in the given JSON
%% Returns: The number of fields in the given JSON
%% @end
-spec count_fields(Json::string()) -> integer().
count_fields(Json) ->
	count_fields(Json,1).

%% @doc
%% Function: count_fields/2
%% Purpose: Used to return the number of fields in the given JSON
%% Returns: The number of fields in the given JSON
%% @end
-spec count_fields(Json::string(),Position::integer()) -> integer().
count_fields(Json,Pos) ->
	case Pos == length(Json) of
		true -> 0;
		false ->
			case string:substr(Json, Pos, 2) of
				"\":" ->
					1 + count_fields(Json,Pos+1);
				_ ->
					case string:substr(Json, Pos, 3) of
						"\" :" ->
							1 + count_fields(Json,Pos+1);
						_ ->
							count_fields(Json,Pos+1)
					end
			end
	end.

%% @doc
%% Function: do_any_field_exist/2
%% Purpose: Used to check if a JSON contains any of the given fields
%% Returns: True if at least one of the given fields exist, false otherwise
%% @end
-spec do_any_field_exist(Json::string(),FieldList::list()) -> boolean().

do_any_field_exist(_Json,[]) ->
		false;
do_any_field_exist(Json,[First|Rest]) ->
		case lib_json:get_field(Json, First) of
			undefined ->
				do_any_field_exist(Json,Rest);
			_ ->
				true
		end.


%% @doc
%% Function: do_only_fields_exist/2
%% Purpose: Used to check if a JSON contains only fields given in the list
%% Returns: True if all fields are in the list, false otherwise
%% @end
-spec do_only_fields_exist(Json::string(),FieldList::list()) -> boolean().

do_only_fields_exist(Json,List) ->
	NumFields = count_fields(lib_json:to_string(Json)),
	Values = lib_json:get_fields(Json, List),
	NumCorrectFields = lists:foldl(fun(X, Sum) -> case X of 
							  undefined -> Sum;
							  _ -> Sum + 1
						      end
				       end, 0, Values),
	NumFields == NumCorrectFields.

%% @doc
%% Function: generate_date/2
%% Purpose: Used to create a date valid in ES
%%          from the input which should be the list
%%          [Year,Mounth,Day]
%% Returns: The generated timestamp
%%
%% @end
-spec generate_date(DateList::list()) -> string().
generate_date([First]) ->
	case First < 10 of
		true -> "0" ++ integer_to_list(First);
		false -> "" ++ integer_to_list(First)
	end;
generate_date([First|Rest]) ->
	case First < 10 of
		true -> "0" ++ integer_to_list(First) ++ "-" ++ generate_date(Rest);
		false -> "" ++ integer_to_list(First) ++ "-" ++ generate_date(Rest)
	end.

%% @doc
%% Purpose: generate an appropriate error string depending on the error code
%%
%% TODO: parse Body for more accurate response text
%%
-spec generate_error(JSONString::string(), integer()) -> string().
generate_error(Body, ErrorCode) ->
	ErrorString = integer_to_list(ErrorCode),
	case ErrorCode of
		404 -> Reason = "not found";
		_ -> Reason = binary_to_list(Body)
	end,
	"Status " ++ ErrorString ++ "\nError: " ++ Reason.

%% @doc
%% Function: generate_timpestamp/2
%% Purpose: Used to create a timestamp valid in ES
%%          from the input which should be the list
%%          [Year,Mounth,Day,Hour,Minute,Day]
%% Returns: The generated timestamp
%%
%% @end
-spec generate_timestamp(DateList::list(),Count::integer()) -> string().
generate_timestamp([],_) ->
	".000";
generate_timestamp([First|Rest],0) ->
	case First < 10 of
		true -> "0" ++ integer_to_list(First) ++ generate_timestamp(Rest,1);
		false -> "" ++ integer_to_list(First) ++ generate_timestamp(Rest,1)
	end;
generate_timestamp([First|Rest],3) ->
	case First < 10 of<commit_msg>Missing @end<commit_after>%% @author <NAME> <<EMAIL>>, <NAME> <<EMAIL>>
%%   [www.csproj13.student.it.uu.se]
%% @version 1.0
%% @headerfile "json.hrl"
%% @copyright [Copyright information]
%%
%% @doc == api_help ==
%% This module will contain all help functions used by the
%% api files 
%%
%% @end
-module(api_help).
-include_lib("erlastic_search.hrl").
-include("json.hrl").

-export([any_to_float/1,
	 do_any_field_exist/2,
	 do_only_fields_exist/2,
	 generate_date/1,
	 generate_error/2,
	 generate_timestamp/2,
	 get_elastic_search_url/0,
	 get_webmachine_url/0,
	 get_and_add_id/1,
	 get_list_and_add_id/1,
	 get_list_and_add_id/2,
	 get_and_add_password/1,
	 get_list_and_add_password/1,
	 is_polling_history/1,
	 is_rank/1,
	 is_search/1,
	 is_subs/1,
	 is_unsubs/1,
	 json_handler/2,
	 make_term_query/1,
	 pair/1,
	 parse_path/1,
	 refresh/0,
	 transform/1,
	 transform/2,
	 update_doc/4,
	 update_doc/5
	]).

%% @doc
%% Purpose: Tries really hard to convert to float
%% Returns: float() or error
%% 
%% @end
-spec any_to_float(any()) -> float().
any_to_float(Val) when is_float(Val) -> Val;
any_to_float(Val) when is_integer(Val) -> float(Val);
any_to_float(Val) when is_binary(Val) -> any_to_float(binary_to_list(Val));
any_to_float(".") -> error;
any_to_float(Val) when is_list(Val) ->
	case lists:prefix(".", Val) of
		true -> PointVal = "0"++Val;
		false -> PointVal = Val
	end,
	case lists:prefix("-.", PointVal) of
		true -> NewVal = "-0"++tl(PointVal);
		false -> NewVal = PointVal
	end,
    case string:to_float(NewVal) of
        {error,no_float} -> 
        	try
        		case list_to_integer(NewVal) of
        			{error, no_integer} -> error;
        			V -> float(V)
        		end
        	catch error:badarg ->
        		error
        	end;
        {F,_Rest} -> F
    end;
any_to_float(Val) ->
	error.

%% @doc
%% Function: count_fields/1
%% Purpose: Used to return the number of fields in the given JSON
%% Returns: The number of fields in the given JSON
%% @end
-spec count_fields(Json::string()) -> integer().
count_fields(Json) ->
	count_fields(Json,1).

%% @doc
%% Function: count_fields/2
%% Purpose: Used to return the number of fields in the given JSON
%% Returns: The number of fields in the given JSON
%% @end
-spec count_fields(Json::string(),Position::integer()) -> integer().
count_fields(Json,Pos) ->
	case Pos == length(Json) of
		true -> 0;
		false ->
			case string:substr(Json, Pos, 2) of
				"\":" ->
					1 + count_fields(Json,Pos+1);
				_ ->
					case string:substr(Json, Pos, 3) of
						"\" :" ->
							1 + count_fields(Json,Pos+1);
						_ ->
							count_fields(Json,Pos+1)
					end
			end
	end.

%% @doc
%% Function: do_any_field_exist/2
%% Purpose: Used to check if a JSON contains any of the given fields
%% Returns: True if at least one of the given fields exist, false otherwise
%% @end
-spec do_any_field_exist(Json::string(),FieldList::list()) -> boolean().

do_any_field_exist(_Json,[]) ->
		false;
do_any_field_exist(Json,[First|Rest]) ->
		case lib_json:get_field(Json, First) of
			undefined ->
				do_any_field_exist(Json,Rest);
			_ ->
				true
		end.


%% @doc
%% Function: do_only_fields_exist/2
%% Purpose: Used to check if a JSON contains only fields given in the list
%% Returns: True if all fields are in the list, false otherwise
%% @end
-spec do_only_fields_exist(Json::string(),FieldList::list()) -> boolean().

do_only_fields_exist(Json,List) ->
	NumFields = count_fields(lib_json:to_string(Json)),
	Values = lib_json:get_fields(Json, List),
	NumCorrectFields = lists:foldl(fun(X, Sum) -> case X of 
							  undefined -> Sum;
							  _ -> Sum + 1
						      end
				       end, 0, Values),
	NumFields == NumCorrectFields.

%% @doc
%% Function: generate_date/2
%% Purpose: Used to create a date valid in ES
%%          from the input which should be the list
%%          [Year,Mounth,Day]
%% Returns: The generated timestamp
%%
%% @end
-spec generate_date(DateList::list()) -> string().
generate_date([First]) ->
	case First < 10 of
		true -> "0" ++ integer_to_list(First);
		false -> "" ++ integer_to_list(First)
	end;
generate_date([First|Rest]) ->
	case First < 10 of
		true -> "0" ++ integer_to_list(First) ++ "-" ++ generate_date(Rest);
		false -> "" ++ integer_to_list(First) ++ "-" ++ generate_date(Rest)
	end.

%% @doc
%% Purpose: generate an appropriate error string depending on the error code
%%
%% TODO: parse Body for more accurate response text
%%
%% @end
-spec generate_error(JSONString::string(), integer()) -> string().
generate_error(Body, ErrorCode) ->
	ErrorString = integer_to_list(ErrorCode),
	case ErrorCode of
		404 -> Reason = "not found";
		_ -> Reason = binary_to_list(Body)
	end,
	"Status " ++ ErrorString ++ "\nError: " ++ Reason.

%% @doc
%% Function: generate_timpestamp/2
%% Purpose: Used to create a timestamp valid in ES
%%          from the input which should be the list
%%          [Year,Mounth,Day,Hour,Minute,Day]
%% Returns: The generated timestamp
%%
%% @end
-spec generate_timestamp(DateList::list(),Count::integer()) -> string().
generate_timestamp([],_) ->
	".000";
generate_timestamp([First|Rest],0) ->
	case First < 10 of
		true -> "0" ++ integer_to_list(First) ++ generate_timestamp(Rest,1);
		false -> "" ++ integer_to_list(First) ++ generate_timestamp(Rest,1)
	end;
generate_timestamp([First|Rest],3) ->
	case First < 10 of
{'fraction_non_alphanumeric': 0.1533713644440288, 'fraction_numerical': 0.01327971570186103, 'mean_word_length': 3.6862401402278704, 'pattern_counts': {'":': 2, '<': 23, '<?xml version=': 0, '>': 121, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4845791', 'n_tokens_mistral': 4003, 'n_tokens_neox': 3684, 'n_words': 929}