- Catch unhandled exceptions in calls to Chem_Problem.Get_Assignment to prevent deadlocking
package body Face_Generator is
- function Generate_Index_Face(HTML: out HTML_Code) return Boolean is
+ function Generate_Index_Face(HTML: out HTML_Code) return RetCode is
use AWS.Templates;
Temp: HTML_Code;
Temp := Parse(Filename => "templates/footer.html", Cached => True);
Append_HTML(Source => HTML, New_Item => Temp);
- return True;
+ return OK;
end Generate_Index_Face;
function Generate_Face(Assignment: in Problem_Generator_Syswides.Assignment_Info.Map; Parameters:
in Problem_Generator_Syswides.Parameters_Info.Map;
HTML: out HTML_Code;
- Pr_ID: in String; Pr_Cat: in String) return Boolean is
+ Pr_ID: in String; Pr_Cat: in String) return RetCode is
begin
return Generate_Face_With_Answer(Assignment => Assignment, Parameters => Parameters, HTML => HTML,
Answer_Message => To_UB_Text(""), Answer_Code => Problem_Generator_Syswides.Invalid_Answer,
Answer_Message: in UB_Text;
Answer_Code: in Problem_Generator_Syswides.Answer_RetCode;
Parameters: in Problem_Generator_Syswides.Parameters_Info.Map;
- HTML: out HTML_Code; Pr_ID: in String; Pr_Cat: in String) return Boolean is
+ HTML: out HTML_Code; Pr_ID: in String; Pr_Cat: in String) return RetCode is
use Problem_Generator_Syswides;
use Problem_Generator_Syswides.Assignment_Info;
begin
if Assignment.Find(PROBLEM_TYPE_KEY) = Assignment_Info.No_Element then
- return False;
+ return E_NOTFOUND;
end if;
declare
elsif Problem_Type_Str = PROBLEM_TYPE_SOLUBILITY then
return Generate_Face_Solubility(Assignment, Answer_Message, Answer_Code, Parameters, HTML, Pr_ID, Pr_Cat);
else
- return False;
+ return E_INVAL;
end if;
end;
end Generate_Face_With_Answer;
Answer_Message: in UB_Text;
Answer_Code: in Problem_Generator_Syswides.Answer_RetCode;
Parameters: in Problem_Generator_Syswides.Parameters_Info.Map;
- HTML: out HTML_Code; Pr_ID: in String; Pr_Cat: in String) return Boolean is
+ HTML: out HTML_Code; Pr_ID: in String; Pr_Cat: in String) return RetCode is
use AWS.Templates;
use Problem_Generator_Syswides;
use Problem_Generator_Syswides.Assignment_Info;
Temp := Parse(Filename => "templates/footer.html");
Append_HTML(Source => HTML, New_Item => Temp);
- return True;
+ return OK;
end Generate_Face_Acidobazic;
function Generate_Face_Solubility(Assignment: in Problem_Generator_Syswides.Assignment_Info.Map;
Answer_Message: in UB_Text;
Answer_Code: in Problem_Generator_Syswides.Answer_RetCode;
Parameters: in Problem_Generator_Syswides.Parameters_Info.Map;
- HTML: out HTML_Code; Pr_ID: in String; Pr_Cat: in String) return Boolean is
+ HTML: out HTML_Code; Pr_ID: in String; Pr_Cat: in String) return RetCode is
use Ada.Strings.Unbounded;
use AWS.Templates;
use Problem_Generator_Syswides;
end if;
if Parameters.Find(Solubility_Suite.PARAMETER_PROBLEM_SUBTYPE_KEY) = Parameters_Info.No_Element then
-- This parameter must be always present
- return False;
+ return E_INVAL;
end if;
P_Subtype := To_UB_Text(Parameters.Element(Solubility_Suite.PARAMETER_PROBLEM_SUBTYPE_KEY));
Insert(Translations_Params, Assoc(Solubility_Suite.PARAMETER_PROBLEM_SUBTYPE_KEY, Solubility_Suite.PARAMETER_PROBLEM_SUBTYPE_KEY));
if P_Subtype = Solubility_Suite.PROBLEM_SUBTYPE_V_FROM_G_KS then
-- Check that we have all necessary fields in the assignment
if Assignment.Find(Solubility_Suite.X_STOCHIO_KEY) = Assignment_Info.No_Element then
- return False;
+ return E_INVAL;
end if;
if Assignment.Find(Solubility_Suite.Z_STOCHIO_KEY) = Assignment_Info.No_Element then
- return False;
+ return E_INVAL;
end if;
if Assignment.Find(Solubility_Suite.KS_INT_KEY) = Assignment_Info.No_Element then
- return False;
+ return E_INVAL;
end if;
if Assignment.Find(Solubility_Suite.KS_DEC_KEY) = Assignment_Info.No_Element then
- return False;
+ return E_INVAL;
end if;
if Assignment.Find(Solubility_Suite.KS_INT_KEY) = Assignment_Info.No_Element then
- return False;
+ return E_INVAL;
end if;
if Assignment.Find(Solubility_Suite.SAMPLE_WEIGHT_INT_KEY) = Assignment_Info.No_Element then
- return False;
+ return E_INVAL;
end if;
if Assignment.Find(Solubility_Suite.SAMPLE_WEIGHT_DEC_KEY) = Assignment_Info.No_Element then
- return False;
+ return E_INVAL;
end if;
if Assignment.Find(Solubility_Suite.MOLAR_MASS_INT_KEY) = Assignment_Info.No_Element then
- return False;
+ return E_INVAL;
end if;
if Assignment.Find(Solubility_Suite.MOLAR_MASS_DEC_KEY) = Assignment_Info.No_Element then
- return False;
+ return E_INVAL;
end if;
Insert(Translations, Assoc(Solubility_Suite.X_STOCHIO_KEY, Assignment.Element(Solubility_Suite.X_STOCHIO_KEY)));
elsif P_Subtype = Solubility_Suite.PROBLEM_SUBTYPE_KS_FROM_G_V then
-- Check that we have all necessary fields in the assignment
if Assignment.Find(Solubility_Suite.X_STOCHIO_KEY) = Assignment_Info.No_Element then
- return False;
+ return E_INVAL;
end if;
if Assignment.Find(Solubility_Suite.Z_STOCHIO_KEY) = Assignment_Info.No_Element then
- return False;
+ return E_INVAL;
end if;
if Assignment.Find(Solubility_Suite.SAMPLE_VOLUME_INT_KEY) = Assignment_Info.No_Element then
- return False;
+ return E_INVAL;
end if;
if Assignment.Find(Solubility_Suite.SAMPLE_VOLUME_DEC_KEY) = Assignment_Info.No_Element then
- return False;
+ return E_INVAL;
end if;
if Assignment.Find(Solubility_Suite.SAMPLE_VOLUME_EXP_KEY) = Assignment_Info.No_Element then
- return False;
+ return E_INVAL;
end if;
if Assignment.Find(Solubility_Suite.SAMPLE_WEIGHT_INT_KEY) = Assignment_Info.No_Element then
- return False;
+ return E_INVAL;
end if;
if Assignment.Find(Solubility_Suite.SAMPLE_WEIGHT_DEC_KEY) = Assignment_Info.No_Element then
- return False;
+ return E_INVAL;
end if;
if Assignment.Find(Solubility_Suite.MOLAR_MASS_INT_KEY) = Assignment_Info.No_Element then
- return False;
+ return E_INVAL;
end if;
if Assignment.Find(Solubility_Suite.MOLAR_MASS_DEC_KEY) = Assignment_Info.No_Element then
- return False;
+ return E_INVAL;
end if;
Insert(Translations, Assoc(Solubility_Suite.X_STOCHIO_KEY, Assignment.Element(Solubility_Suite.X_STOCHIO_KEY)));
elsif P_Subtype = Solubility_Suite.PROBLEM_SUBTYPE_C_FROM_KS_DIFFERENT_IONS or P_Subtype = Solubility_Suite.PROBLEM_SUBTYPE_C_FROM_KS_SHARED_ION then
-- Check that we have all necessary fields in the assignment
if Assignment.Find(Solubility_Suite.X_STOCHIO_KEY) = Assignment_Info.No_Element then
- return False;
+ return E_INVAL;
end if;
if Assignment.Find(Solubility_Suite.Z_STOCHIO_KEY) = Assignment_Info.No_Element then
- return False;
+ return E_INVAL;
end if;
if Assignment.Find(Solubility_Suite.EC_INT_KEY) = Assignment_Info.No_Element then
- return False;
+ return E_INVAL;
end if;
if Assignment.Find(Solubility_Suite.EC_DEC_KEY) = Assignment_Info.No_Element then
- return False;
+ return E_INVAL;
end if;
if Assignment.Find(Solubility_Suite.EC_EXP_KEY) = Assignment_Info.No_Element then
- return False;
+ return E_INVAL;
end if;
if Assignment.Find(Solubility_Suite.KS_INT_KEY) = Assignment_Info.No_Element then
- return False;
+ return E_INVAL;
end if;
if Assignment.Find(Solubility_Suite.KS_DEC_KEY) = Assignment_Info.No_Element then
- return False;
+ return E_INVAL;
end if;
if Assignment.Find(Solubility_Suite.KS_INT_KEY) = Assignment_Info.No_Element then
- return False;
+ return E_INVAL;
end if;
Insert(Translations, Assoc(Solubility_Suite.X_STOCHIO_KEY, Assignment.Element(Solubility_Suite.X_STOCHIO_KEY)));
end if;
Append_HTML(Source => HTML, New_Item => Temp);
else
- return False;
+ return E_INVAL;
end if;
Temp := Parse(Filename => "templates/footer.html");
Append_HTML(Source => HTML, New_Item => Temp);
- return True;
+ return OK;
end Generate_Face_Solubility;
end Face_Generator;
use Global_Types;
package Face_Generator is
- function Generate_Index_Face(HTML: out HTML_Code) return Boolean;
+ function Generate_Index_Face(HTML: out HTML_Code) return RetCode;
function Generate_Face(Assignment: in Problem_Generator_Syswides.Assignment_Info.Map;
Parameters: in Problem_Generator_Syswides.Parameters_Info.Map;
HTML: out HTML_Code;
- Pr_ID: in String; Pr_Cat: in String) return Boolean;
+ Pr_ID: in String; Pr_Cat: in String) return RetCode;
function Generate_Face_With_Answer(Assignment: in Problem_Generator_Syswides.Assignment_Info.Map;
Answer_Message: in UB_Text;
Answer_Code: in Problem_Generator_Syswides.Answer_RetCode;
Parameters: in Problem_Generator_Syswides.Parameters_Info.Map;
HTML: out HTML_Code;
- Pr_ID: in String; Pr_Cat: in String) return Boolean;
+ Pr_ID: in String; Pr_Cat: in String) return RetCode;
private
procedure Add_Answer_Section(Translations: in out AWS.Templates.Translate_Set; Answer_Message: in UB_Text;
Answer_Code: in Problem_Generator_Syswides.Answer_RetCode;
Parameters: in Problem_Generator_Syswides.Parameters_Info.Map;
HTML: out HTML_Code;
- Pr_ID: in String; Pr_Cat: in String) return Boolean;
+ Pr_ID: in String; Pr_Cat: in String) return RetCode;
function Generate_Face_Solubility(Assignment: in Problem_Generator_Syswides.Assignment_Info.Map;
Answer_Message: in UB_Text;
Answer_Code: in Problem_Generator_Syswides.Answer_RetCode;
Parameters: in Problem_Generator_Syswides.Parameters_Info.Map;
HTML: out HTML_Code;
- Pr_ID: in String; Pr_Cat: in String) return Boolean;
+ Pr_ID: in String; Pr_Cat: in String) return RetCode;
HEADER_CAPTION_KEY: constant String := "HEADER_CAPTION";
HINTS_SECTION_KEY: constant String := "HINTS_SECTION";
package Global_Types is
type Problem_ID is new Ada.Containers.Count_Type;
+ type RetCode is (OK, E_NOTFOUND, E_UNKW, E_INVAL, E_NOMEM, E_NULLPTR);
type Unique_ID is new Ada.Containers.Count_Type;
subtype HTML_Code is Ada.Strings.Unbounded.Unbounded_String;
subtype UB_Text is Ada.Strings.Unbounded.Unbounded_String;
POST_Data: constant AWS.Parameters.List := AWS.Status.Parameters(Request);
Answer: Answer_Info.Map;
Pr_ID: Problem_ID;
+ Ret: RetCode;
Success: Boolean;
begin
-- Get UID
return AWS.Response.URL(Location => "/");
end;
- Success := Problem_Manager.Display_Checked_Answer(UID, Answer, HTML, Pr_ID);
- if Success = False then
+ Ret := Problem_Manager.Display_Checked_Answer(UID, Answer, HTML, Pr_ID);
+ if Ret /= OK then
Ada.Text_IO.Put_Line("No such problem in storage");
return AWS.Response.URL(Location => "/");
end if;
function Handle(Request: AWS.Status.Data) return AWS.Response.Data is
HTML: HTML_Code;
- Success: Boolean;
+ Ret: RetCode;
begin
- Success := Face_Generator.Generate_Index_Face(HTML);
- if Success = False then
+ Ret := Face_Generator.Generate_Index_Face(HTML);
+ if Ret /= OK then
return AWS.Response.Build(Content_Type => AWS.MIME.Text_HTML,
Message_Body => "Internal server error occured, we're sorry about that...",
Status_Code => AWS.Messages.S503);
Problem_Parameters: Parameters_Info.Map;
POST_Data: constant AWS.Parameters.List := AWS.Status.Parameters(Request);
+ Ret: RetCode;
Success: Boolean;
begin
-- Get UID
declare
Raw_P_Cat: constant String := Problem_Parameters.Element(Problem_Generator_Syswides.RESERVED_PROBLEM_CATEGORY_KEY);
begin
- Success := Problem_Manager.Prepare_Problem(UID, Raw_P_Cat, Problem_Parameters);
- if Success = False then
+ Ret := Problem_Manager.Prepare_Problem(UID, Raw_P_Cat, Problem_Parameters);
+ if Ret /= OK then
-- TODO: Handle error in a less reckless manner
return AWS.Response.URL(Location => "/");
end if;
-- Display new problem
- Success := Problem_Manager.Display_Assignment(UID, HTML);
- if Success = False then
+ Ret := Problem_Manager.Display_Assignment(UID, HTML);
+ if Ret /= OK then
-- TODO: Handle error in a less reckless manner
return AWS.Response.URL(Location => "/");
end if;
declare
Raw_Problem_Category: constant String := AWS.Status.Parameter(Request, "problem_category");
UID: Unique_ID;
+ Ret: RetCode;
Success: Boolean;
begin
-- Register new UID if necessary and create a first problem
Success := Problem_Manager.Get_UID(Raw_UID, UID);
if Success = False then
-- UID stored within this session is not valid, register a new one
- Success := Problem_Manager.Register_UID(UID);
- if Success = False then
+ Ret := Problem_Manager.Register_UID(UID);
+ if Ret /= OK then
-- UID could not have been registered
-- TODO: Print some sensible error message, for now just redirect to index
return AWS.Response.URL(Location => "/");
end if;
-- We're all set, create a new problem
- Success := Problem_Manager.Prepare_Problem(UID, Raw_Problem_Category);
- if Success = False then
+ Ret := Problem_Manager.Prepare_Problem(UID, Raw_Problem_Category);
+ if Ret /= OK then
-- Something went wrong when generating the problem
-- TODO: Print some sensible error message, for now just redirect to index
return AWS.Response.URL(Location => "/");
end if;
- Success := Problem_Manager.Display_Assignment(UID, HTML);
- if Success = False then
+ Ret := Problem_Manager.Display_Assignment(UID, HTML);
+ if Ret /= OK then
HTML := To_HTML_Code("Cannot display assignment");
end if;
return AWS.Response.Build(Content_Type => AWS.MIME.Text_HTML,
end if;
end Check_Answer;
- function Get_Assignment(Problem: in out Acidobazic_Problem; Assignment: in out Assignment_Info.Map) return Boolean is
+ function Get_Assignment(Problem: in out Acidobazic_Problem; Assignment: in out Assignment_Info.Map) return RetCode is
Guard: Auto_Lock.LC;
C: Assignment_Info.Cursor;
Success: Boolean;
Assignment.Insert(PROBLEM_TYPE_KEY, PROBLEM_TYPE_ACIDOBAZIC, C, Success);
if Success = False then
- return False;
+ return E_NOMEM;
end if;
case Problem.Subst_Type is
when Acid =>
Assignment.Insert(PKX_VALUE_INT_KEY, UB_Text_To_Fixed_String(Int_S), C, Success);
Assignment.Insert(PKX_VALUE_DEC_KEY, UB_Text_To_Fixed_String(Dec_S), C, Success);
if Success = False then
- return False;
+ return E_NOMEM;
end if;
end;
Assignment.Insert(CONCENTRATION_DEC_KEY, UB_Text_To_Fixed_String(Dec_S), C, Success);
Assignment.Insert(CONCENTRATION_EXP_KEY, UB_Text_To_Fixed_String(Exp_S), C, Success);
if Success = False then
- return False;
+ return E_NOMEM;
end if;
end;
- return True;
+ return OK;
end Get_Assignment;
- function Get_Parameters(Problem: in out Acidobazic_Problem; Parameters: out Parameters_Info.Map) return Boolean is
+ function Get_Parameters(Problem: in out Acidobazic_Problem; Parameters: out Parameters_Info.Map) return RetCode is
Guard: Auto_Lock.LC;
C: Parameters_Info.Cursor;
Success: Boolean;
if Problem.Parameters.No_Both_Simplifications then
Parameters.Insert(PARAMETER_NO_BOTH_SIMPLIFICATIONS_KEY, "True", C, Success);
- return Success;
+ if Success = False then
+ return E_NOMEM;
+ end if;
end if;
- return True;
+ return OK;
end Get_Parameters;
procedure New_Problem(Problem: in out Acidobazic_Problem) is
Random_Substance_Type_Gen.Reset(Gen => ST_G);
Problem.Subst_Type := Random_Substance_Type_Gen.Random(Gen => ST_G);
-- What simplification to use
- if (Problem.Parameters.No_Both_Simplifications = False) then
+ if Problem.Parameters.No_Both_Simplifications = False then
declare
package Random_Simplification_Gen is new Ada.Numerics.Discrete_Random(Result_Subtype => Simplification);
SIM_G: Random_Simplification_Gen.Generator;
Problem.cX := Random_cX(cX_Min, cX_Max);
end New_Problem;
- function Set_Parameters(Problem: in out Acidobazic_Problem; Parameters: in Parameters_Info.Map) return Boolean is
+ function Set_Parameters(Problem: in out Acidobazic_Problem; Parameters: in Parameters_Info.Map) return RetCode is
use Parameters_Info;
Guard: Auto_Lock.LC;
Problem.Parameters.No_Both_Simplifications := True;
end if;
- return True;
+ return OK;
end Set_Parameters;
-- END: Inherited functions
end if;
end Check_Answer;
- function Get_Assignment(Problem: in out Solubility_Problem; Assignment: in out Assignment_Info.Map) return Boolean is
+ function Get_Assignment(Problem: in out Solubility_Problem; Assignment: in out Assignment_Info.Map) return RetCode is
package FH is new Formatting_Helpers(SS_Float);
use FH;
Assignment.Insert(KS_DEC_KEY, UB_Text_To_Fixed_String(Ks_Str_Dec));
Assignment.Insert(KS_EXP_KEY, UB_Text_To_Fixed_String(Ks_Str_Exp));
- return True;
+ return OK;
end;
when KS_FROM_G_V =>
declare
Assignment.Insert(SAMPLE_VOLUME_INT_KEY, UB_Text_To_Fixed_String(V_Str_Int));
Assignment.Insert(SAMPLE_VOLUME_DEC_KEY, UB_Text_To_Fixed_String(V_Str_Dec));
Assignment.Insert(SAMPLE_VOLUME_EXP_KEY, UB_Text_To_Fixed_String(V_Str_Exp));
- return True;
+ return OK;
end;
when C_FROM_KS_DIFFERENT_IONS | C_FROM_KS_SHARED_ION =>
declare
Assignment.Insert(KS_INT_KEY, UB_Text_To_Fixed_String(Ks_Str_Int));
Assignment.Insert(KS_DEC_KEY, UB_Text_To_Fixed_String(Ks_Str_Dec));
Assignment.Insert(KS_EXP_KEY, UB_Text_To_Fixed_String(Ks_Str_Exp));
- return True;
+ return OK;
end;
end case;
end Get_Assignment;
- function Get_Parameters(Problem: in out Solubility_Problem; Parameters: out Parameters_Info.Map) return Boolean is
+ function Get_Parameters(Problem: in out Solubility_Problem; Parameters: out Parameters_Info.Map) return RetCode is
Guard: Auto_Lock.LC;
C: Parameters_Info.Cursor;
Success: Boolean;
if Problem.Parameters.Ionic_Strength then
Parameters.Insert(PARAMETER_IONIC_STRENGTH_KEY, "True", C, Success);
if Success = False then
- return False;
+ return E_NOMEM;
end if;
end if;
Parameters.Insert(PARAMETER_PROBLEM_SUBTYPE_KEY, Problem_Subtype'Image(Problem.Parameters.P_Subtype), C, Success);
-
- return Success;
+ if Success = False then
+ return E_NOMEM;
+ end if;
+ return OK;
end Get_Parameters;
procedure New_Problem(Problem: in out Solubility_Problem) is
Problem.Answer_Num := Answer_Num;
end New_Problem;
- function Set_Parameters(Problem: in out Solubility_Problem; Parameters: in Parameters_Info.Map) return Boolean is
+ function Set_Parameters(Problem: in out Solubility_Problem; Parameters: in Parameters_Info.Map) return RetCode is
use Parameters_Info;
Guard: Auto_Lock.LC;
elsif PS_Str = PROBLEM_SUBTYPE_C_FROM_KS_SHARED_ION then
Problem.Parameters.P_Subtype := C_FROM_KS_SHARED_ION;
else
- raise Constraint_Error;
+ return E_INVAL;
end if;
end;
else
-- This parameter must be always present
- return False;
+ return E_INVAL;
end if;
- return True;
+ return OK;
end Set_Parameters;
-- END: Inherited functions
function Create return access Chem_Problem is abstract;
function Check_Answer(Problem: in out Chem_Problem; Answer: in Answer_Info.Map; Message: out UB_Text) return Answer_RetCode is abstract;
- function Get_Assignment(Problem: in out Chem_Problem; Assignment: in out Assignment_Info.Map) return Boolean is abstract;
- function Get_Parameters(Problem: in out Chem_Problem; Parameters: out Parameters_Info.Map) return Boolean is abstract;
+ function Get_Assignment(Problem: in out Chem_Problem; Assignment: in out Assignment_Info.Map) return RetCode is abstract;
+ function Get_Parameters(Problem: in out Chem_Problem; Parameters: out Parameters_Info.Map) return RetCode is abstract;
procedure New_Problem(Problem: in out Chem_Problem) is abstract;
- function Set_Parameters(Problem: in out Chem_Problem; Parameters: in Parameters_Info.Map) return Boolean is abstract;
+ function Set_Parameters(Problem: in out Chem_Problem; Parameters: in Parameters_Info.Map) return RetCode is abstract;
function Get_Problem(P_Type: in Problem_Type) return access Chem_Problem'Class;
-- Inherited
function Check_Answer(Problem: in out Acidobazic_Problem; Answer: in Answer_Info.Map; Message: out UB_Text) return Answer_RetCode;
procedure New_Problem(Problem: in out Acidobazic_Problem);
- function Get_Assignment(Problem: in out Acidobazic_Problem; Assignment: in out Assignment_Info.Map) return Boolean;
- function Get_Parameters(Problem: in out Acidobazic_Problem; Parameters: out Parameters_Info.Map) return Boolean;
- function Set_Parameters(Problem: in out Acidobazic_Problem; Parameters: in Parameters_Info.Map) return Boolean;
+ function Get_Assignment(Problem: in out Acidobazic_Problem; Assignment: in out Assignment_Info.Map) return RetCode;
+ function Get_Parameters(Problem: in out Acidobazic_Problem; Parameters: out Parameters_Info.Map) return RetCode;
+ function Set_Parameters(Problem: in out Acidobazic_Problem; Parameters: in Parameters_Info.Map) return RetCode;
private
type pH_Float is digits 15;
-- Inherited
function Check_Answer(Problem: in out Solubility_Problem; Answer: in Answer_Info.Map; Message: out UB_Text) return Answer_RetCode;
procedure New_Problem(Problem: in out Solubility_Problem);
- function Get_Assignment(Problem: in out Solubility_Problem; Assignment: in out Assignment_Info.Map) return Boolean;
- function Get_Parameters(Problem: in out Solubility_Problem; Parameters: out Parameters_Info.Map) return Boolean;
- function Set_Parameters(Problem: in out Solubility_Problem; Parameters: in Parameters_Info.Map) return Boolean;
+ function Get_Assignment(Problem: in out Solubility_Problem; Assignment: in out Assignment_Info.Map) return RetCode;
+ function Get_Parameters(Problem: in out Solubility_Problem; Parameters: out Parameters_Info.Map) return RetCode;
+ function Set_Parameters(Problem: in out Solubility_Problem; Parameters: in Parameters_Info.Map) return RetCode;
private
type SS_Float is digits 17;
package body Problem_Manager is
- function Display_Checked_Answer(UID: in Unique_ID; Answer: in Problem_Generator_Syswides.Answer_Info.Map; HTML: out HTML_Code; Pr_ID: in Problem_ID) return Boolean is
+ function Display_Checked_Answer(UID: in Unique_ID; Answer: in Problem_Generator_Syswides.Answer_Info.Map; HTML: out HTML_Code; Pr_ID: in Problem_ID) return RetCode is
Answer_Message: UB_Text;
ARC: Problem_Generator_Syswides.Answer_RetCode;
Assignment: Problem_Generator_Syswides.Assignment_Info.Map;
Parameters: Problem_Generator_Syswides.Parameters_Info.Map;
Pr_Cat: Problem_Category;
- Success: Boolean;
+ Ret: RetCode;
Stored: Stored_Problem_All_Access;
begin
Stored := Active_Sessions.Get_Problem(UID, Pr_ID);
if Stored = null then
- return False;
+ return E_NOTFOUND;
end if;
- Success := Stored.Problem.Get_Parameters(Parameters);
- if Success = False then
- -- TODO: Handle error in a better way
+ Ret := Stored.Problem.Get_Parameters(Parameters);
+ if Ret /= OK then
Stored.Mutex.Unlock;
- return False;
- end if;
- Success := Stored.Problem.Get_Assignment(Assignment);
- if Success = False then
- -- TODO: Handle error in a better way
- Stored.Mutex.Unlock;
- return False;
+ return Ret;
end if;
+ begin
+ Ret := Stored.Problem.Get_Assignment(Assignment);
+ if Ret /= OK then
+ Stored.Mutex.Unlock;
+ return Ret;
+ end if;
+ exception
+ when others =>
+ Stored.Mutex.Unlock;
+ return E_UNKW;
+ end;
+
ARC := Stored.Problem.Check_Answer(Answer, Answer_Message);
Pr_Cat := Stored.Category;
Stored.Mutex.Unlock;
Parameters => Parameters, Pr_ID => Problem_ID'Image(Pr_ID), Pr_Cat => Problem_Category'Image(Pr_Cat));
end Display_Checked_Answer;
- function Display_Assignment(UID: in Unique_ID; HTML: out HTML_Code) return Boolean is
+ function Display_Assignment(UID: in Unique_ID; HTML: out HTML_Code) return RetCode is
Assignment: Problem_Generator_Syswides.Assignment_Info.Map;
Parameters: Problem_Generator_Syswides.Parameters_Info.Map;
Stored: Stored_Problem_All_Access;
Pr_ID: Problem_ID;
Pr_Cat: Problem_Category;
- Success: Boolean;
+ Ret: RetCode;
begin
Stored := Active_Sessions.Get_Latest_Problem_With_ID(UID, Pr_ID);
if Stored = null then
- return False;
+ return E_NOTFOUND;
end if;
- Success := Stored.Problem.Get_Parameters(Parameters);
- if Success = False then
+ Ret := Stored.Problem.Get_Parameters(Parameters);
+ if Ret /= OK then
Stored.Mutex.Unlock;
- return False;
+ return Ret;
end if;
-- Get assignment
- Success := Stored.Problem.Get_Assignment(Assignment);
- if Success = False then
- Stored.Mutex.Unlock;
- return False;
- end if;
+ begin
+ Ret := Stored.Problem.Get_Assignment(Assignment);
+ if Ret /= OK then
+ Stored.Mutex.Unlock;
+ return Ret;
+ end if;
+ exception
+ when others =>
+ Stored.Mutex.Unlock;
+ return E_UNKW;
+ end;
Pr_Cat := Stored.Category;
Stored.Mutex.Unlock;
end Get_UID;
function Prepare_Problem(UID: in Unique_ID; Raw_P_Cat: in String;
- Parameters: in Problem_Generator_Syswides.Parameters_Info.Map := Problem_Generator_Syswides.Parameters_Info.Empty_Map) return Boolean is
+ Parameters: in Problem_Generator_Syswides.Parameters_Info.Map := Problem_Generator_Syswides.Parameters_Info.Empty_Map) return RetCode is
Problem: Chem_Problem_All_Access;
Storage: Stored_Problem_All_Access;
P_Cat: Problem_Category;
- Success: Boolean;
+ Ret: RetCode;
begin
if Raw_P_Cat = Problem_Manager.Problem_Category'Image(Problem_Manager.Acidobazic) then
P_Cat := Problem_Manager.Acidobazic;
elsif Raw_P_Cat = Problem_Manager.Problem_Category'Image(Problem_Manager.Solubility) then
P_Cat := Problem_Manager.Solubility;
else
- return False;
+ return E_INVAL;
end if;
case P_Cat is
when Solubility =>
Problem := Problem_Generator.Get_Problem(Problem_Generator_Syswides.Solubility);
when others =>
- return False;
+ return E_INVAL;
end case;
if Problem = null then
- return False;
+ return E_NULLPTR;
end if;
-- Initialize problem
if Parameters.Is_Empty = False then
- Success := Problem.Set_Parameters(Parameters);
- if Success = False then
+ Ret := Problem.Set_Parameters(Parameters);
+ if Ret /= OK then
Free_Chem_Problem(Problem);
- return False;
+ return Ret;
end if;
end if;
- Problem.New_Problem;
+
+ begin
+ Problem.New_Problem;
+ exception
+ when others =>
+ Free_Chem_Problem(Problem);
+ return E_UNKW;
+ end;
Storage := new Stored_Problem;
Storage.Problem := Problem;
Storage.Category := P_Cat;
- Active_Sessions.Add_Problem(UID, Storage, Success);
+ Active_Sessions.Add_Problem(UID, Storage, Ret);
- if Success = False then
+ if Ret /= OK then
Free_Chem_Problem(Problem);
Free_Stored_Problem(Storage);
end if;
- return True;
+ return Ret;
end Prepare_Problem;
- function Register_UID(UID: out Unique_ID) return Boolean is
- Success: Boolean;
+ function Register_UID(UID: out Unique_ID) return RetCode is
+ Ret: RetCode;
begin
- Active_Sessions.Register_UID(UID, Success);
- return Success;
+ Active_Sessions.Register_UID(UID, Ret);
+ return Ret;
end Register_UID;
procedure Session_Expired(SID: in AWS.Session.ID) is
Raw_UID: constant String := AWS.Session.Get(SID, "UID");
UID: Unique_ID;
- Success: Boolean;
begin
- Success := Get_UID(Raw_UID, UID);
- if Success = False then
+ if Get_UID(Raw_UID, UID) = False then
return;
end if;
protected body Active_Sessions is
- procedure Add_Problem(UID: in Unique_ID; Problem: in Stored_Problem_All_Access; Success: out Boolean) is
+ procedure Add_Problem(UID: in Unique_ID; Problem: in Stored_Problem_All_Access; Ret: out RetCode) is
use Problem_Storage;
use Session_Keeping;
use Ada.Containers;
C: Problem_Storage.Cursor;
+ Success: Boolean;
USD: User_Session_All_Access;
begin
if Sessions.Find(UID) = Session_Keeping.No_Element then
- Success := False;
+ Ret := E_NOTFOUND;
return;
end if;
USD := Sessions.Element(UID);
USD.Problems.Insert(USD.Last_Problem_ID, Problem, C, Success);
if Success = False then
+ Ret := E_NOMEM;
return;
end if;
end;
end if;
end;
- Success := True;
+ Ret := OK;
end Add_Problem;
function Contains(UID: in Unique_ID) return Boolean is
end if;
end Contains;
- procedure Check_Free_And_Register(UID: in Unique_ID; Success: out Boolean; Stop: out Boolean) is
+ procedure Check_Free_And_Register(UID: in Unique_ID; Ret: out RetCode; Stop: out Boolean) is
use Session_Keeping;
C: Session_Keeping.Cursor;
NUSD: User_Session_All_Access;
+ Success: Boolean;
begin
- Success := False;
if Sessions.Find(UID) = Session_Keeping.No_Element then
-- We have a free slot
NUSD := new User_Session_Data;
if NUSD = null then
- Success := False;
- Stop := False;
+ -- Session data not allocated
+ Ret := E_NOMEM;
+ Stop := True;
return;
end if;
Sessions.Insert(UID, NUSD, C, Success);
if Success then
Last_UID := UID;
-- Registration successful
+ Ret := OK;
Stop := True;
return;
else
-- Registration failed
+ Ret := E_NOMEM;
Stop := True;
return;
end if;
end if;
-- Slot occupied, keep looking
+ Ret := OK;
Stop := False;
end Check_Free_And_Register;
return Get_Problem(UID, Pr_ID);
end Get_Latest_Problem_With_ID;
- procedure Register_UID(UID: out Unique_ID; Success: out Boolean) is
+ procedure Register_UID(UID: out Unique_ID; Ret: out RetCode) is
Stop: Boolean;
begin
-- Look for an available UID slot
for Idx in Last_UID .. Unique_ID'Last loop
- Check_Free_And_Register(Idx, Success, Stop);
+ Check_Free_And_Register(Idx, Ret, Stop);
if Stop then
UID := Idx;
return;
-- We found no free slot above, search the area below Last_UID
for Idx in Unique_ID'First .. Last_UID loop
- Check_Free_And_Register(Idx, Success, Stop);
+ Check_Free_And_Register(Idx, Ret, Stop);
if Stop then
UID := Idx;
return;
end loop;
-- There are no free slots available
- Success := False;
+ Ret := E_NOMEM;
end Register_UID;
procedure Remove_Session(UID: in Unique_ID) is
type Problem_Category is (Invalid, Acidobazic, Solubility);
function Display_Checked_Answer(UID: in Unique_ID; Answer: in Problem_Generator_Syswides.Answer_Info.Map; HTML: out HTML_Code;
- Pr_ID: in Problem_ID) return Boolean;
- function Display_Assignment(UID: in Unique_ID; HTML: out HTML_Code) return Boolean;
+ Pr_ID: in Problem_ID) return RetCode;
+ function Display_Assignment(UID: in Unique_ID; HTML: out HTML_Code) return RetCode;
--function Display_Next_Assignment(UID: in Unique_ID;
-- Problem_Parameters: in Problem_Generator_Syswides.Parameters_Info.Map;
-- HTML: out HTML_Code) return Boolean;
function Get_UID(Raw_UID: in String; UID: out Unique_ID) return Boolean;
function Prepare_Problem(UID: in Unique_ID; Raw_P_Cat: in String;
- Parameters: in Problem_Generator_Syswides.Parameters_Info.Map := Problem_Generator_Syswides.Parameters_Info.Empty_Map) return Boolean;
- function Register_UID(UID: out Unique_ID) return Boolean;
+ Parameters: in Problem_Generator_Syswides.Parameters_Info.Map := Problem_Generator_Syswides.Parameters_Info.Empty_Map) return RetCode;
+ function Register_UID(UID: out Unique_ID) return RetCode;
procedure Session_Expired(SID: AWS.Session.ID);
private
package Session_Keeping is new Ada.Containers.Ordered_Maps(Key_Type => Unique_ID, Element_Type => User_Session_All_Access);
protected Active_Sessions is
- procedure Add_Problem(UID: in Unique_ID; Problem: in Stored_Problem_All_Access; Success: out Boolean);
+ procedure Add_Problem(UID: in Unique_ID; Problem: in Stored_Problem_All_Access; Ret: out RetCode);
function Contains(UID: in Unique_ID) return Boolean;
function Get_Problem(UID: in Unique_ID; Pr_ID: in Problem_ID) return Stored_Problem_All_Access;
function Get_Latest_Problem_With_ID(UID: in Unique_ID; Pr_ID: out Problem_ID) return Stored_Problem_All_Access;
- procedure Register_UID(UID: out Unique_ID; Success: out Boolean);
+ procedure Register_UID(UID: out Unique_ID; Ret: out RetCode);
procedure Remove_Session(UID: in Unique_ID);
private
- procedure Check_Free_And_Register(UID: in Unique_ID; Success: out Boolean; Stop: out Boolean);
+ procedure Check_Free_And_Register(UID: in Unique_ID; Ret: out RetCode; Stop: out Boolean);
procedure Free_Session_Data(Data: in out User_Session_All_Access);
Sessions: Session_Keeping.Map;