<a class="main_navlink" href="/start?problem_category=ACIDOBAZIC">pH jednosytné kyseliny/báze</a>
+ <a class="main_navlink" href="/start?problem_category=SOLUBILITY">Srážecí rovnováhy</a>
--- /dev/null
+
+ <div class="backgrounded_block">
+ <div class="caption_v1">Zadání:</div>
+ <div class="assignment_text">Jaká je koncentrace látky X<span class="subscript">@_X_STOCHIO_@</span>Z<span class="subscript">@_Z_STOCHIO_@</span> o K<span class="subscript">s</span> = @_KS_INT_@,@_KS_DEC_@ . 10<span class="exponent">@_KS_EXP_@</span> která je rozpuštěna v roztoku, který obsahuje uni-univalentní elektrolyt o koncetraci @_EC_INT_@,@_EC_DEC_@ . 10<span class="exponent">@_EC_EXP_@</span> mol/dm<span class="exponent">3</span>, který nemá s danou látkou žádný společný iont?</div>
+ @_SUBMIT_FORM_@
+ </div>
+
+ @_ANSWER_SECTION_@
+
+ <div class="backgrounded_block">
+ <span class="expand_section" onclick="show_hide_item('hints_section', 'hints_button', 'block', '/images/arrow_right.png', '/images/arrow_down.png')">
+ <img class="expand_section" id="hints_button" src="/images/arrow_right.png" alt="Zobraz sekci" title="Zobraz sekci" />
+ </span>
+ <div class="caption_v1">Nápověda:</div>
+ <div class="assignment_hint" id="hints_section">
+ @_HINTS_SECTION_@
+ </div>
+ </div>
+
+ <div class="backgrounded_block">
+ <div class="caption_v1">Parametry příkladů:</div>
+ @_PARAMETERS_FORM_@
+ </div>
--- /dev/null
+
+ <div class="backgrounded_block">
+ <div class="caption_v1">Zadání:</div>
+ <div class="assignment_text">Jaká je koncentrace látky X<span class="subscript">@_X_STOCHIO_@</span>Z<span class="subscript">@_Z_STOCHIO_@</span> o K<span class="subscript">s</span> = @_KS_INT_@,@_KS_DEC_@ . 10<span class="exponent">@_KS_EXP_@</span> která je rozpuštěna v roztoku, který obsahuje zcela rozpuštěnou látku A<span class="subscript">@_X_STOCHIO_@</span>Z o koncentraci @_EC_INT_@,@_EC_DEC_@ . 10<span class="exponent">@_EC_EXP_@</span> mol/dm<span class="exponent">3</span>. Anion obou látek je stejný.</div>
+ @_SUBMIT_FORM_@
+ </div>
+
+ @_ANSWER_SECTION_@
+
+ <div class="backgrounded_block">
+ <span class="expand_section" onclick="show_hide_item('hints_section', 'hints_button', 'block', '/images/arrow_right.png', '/images/arrow_down.png')">
+ <img class="expand_section" id="hints_button" src="/images/arrow_right.png" alt="Zobraz sekci" title="Zobraz sekci" />
+ </span>
+ <div class="caption_v1">Nápověda:</div>
+ <div class="assignment_hint" id="hints_section">
+ @_HINTS_SECTION_@
+ </div>
+ </div>
+
+ <div class="backgrounded_block">
+ <div class="caption_v1">Parametry příkladů:</div>
+ @_PARAMETERS_FORM_@
+ </div>
--- /dev/null
+
+ <div class="backgrounded_block">
+ <div class="caption_v1">Zadání:</div>
+ <div class="assignment_text">Jaké je K<span class="subscript">s</span> látky X<span class="subscript">@_X_STOCHIO_@</span>Z<span class="subscript">@_Z_STOCHIO_@</span> o molární hmotnosti MW=@_MOLAR_MASS_INT_@,@_MOLAR_MASS_DEC_@ g/mol, jejíž @_SAMPLE_WEIGHT_INT_@,@_SAMPLE_WEIGHT_DEC_@ g se zcela rozpustí v @_SAMPLE_VOLUME_INT_@,@_SAMPLE_VOLUME_DEC_@ . 10<span class="exponent">@_SAMPLE_VOLUME_EXP_@</span> dm<span class="exponent">3</span></div>
+ @_SUBMIT_FORM_@
+ </div>
+
+ @_ANSWER_SECTION_@
+
+ <div class="backgrounded_block">
+ <span class="expand_section" onclick="show_hide_item('hints_section', 'hints_button', 'block', '/images/arrow_right.png', '/images/arrow_down.png')">
+ <img class="expand_section" id="hints_button" src="/images/arrow_right.png" alt="Zobraz sekci" title="Zobraz sekci" />
+ </span>
+ <div class="caption_v1">Nápověda:</div>
+ <div class="assignment_hint" id="hints_section">
+ @_HINTS_SECTION_@
+ </div>
+ </div>
+
+ <div class="backgrounded_block">
+ <div class="caption_v1">Parametry příkladů:</div>
+ @_PARAMETERS_FORM_@
+ </div>
--- /dev/null
+ <form class="problem_form" method="post" action="/next_problem" enctype="multipart/form-data">
+ <div class="form_line">
+ <label class="form_label_sol_param" for="@_PARAMETER_IONIC_STRENGTH_@">Uvažovat iontovou sílu:</label>
+ <input type="checkbox" name="@_PARAMETER_IONIC_STRENGTH_@" value="True" @_PARAMETER_IONIC_STRENGTH_CHECKED_@ />
+ </div>
+ <div class="form_line">
+ <label class="form_label_sol_param" for="@_PARAMETER_PROBLEM_SUBTYPE_@">Typ příkladu:</label>
+ <select name="@_PARAMETER_PROBLEM_SUBTYPE_@">
+ <option value="@_V_FROM_G_KS_@" @_V_FROM_G_KS_SELECTED_@>Objem potřebný k rozpuštění, zadáno Ks, G, MW</option>
+ <option value="@_KS_FROM_G_V_@" @_KS_FROM_G_V_SELECTED_@>Součin rozpustnosti, zadnáno G, V, MW</option>
+ <option value="@_C_FROM_KS_DIFFERENT_IONS_@" @_C_FROM_KS_DIFFERENT_IONS_SELECTED_@>Koncentrace rozpuštené látky v přítomnosti indiferentního elektrolytu</option>
+ <option value="@_C_FROM_KS_SHARED_ION_@" @_C_FROM_KS_SHARED_ION_SELECTED_@>Koncentrace rozpuštěné látky v přítomnosti elektrolytu se stejným aniontem</option>
+ </select>
+ </div>
+ <div class="form_line">
+ <input type="submit" name="next_problem" value="Další příklad" />
+ </div>
+ </form>
--- /dev/null
+ <form class="problem_form" method="post" action="/check_answer" enctype="multipart/form-data">
+ <div class="form_line">
+ <label class="form_label_sol" for="ANSWER_NUM">Výsledek:</label>
+ <input class="form_input_sol" type="text" name="ANSWER_NUM" maxlength="128" value="" />
+ </div>
+ <div class="form_line">
+ <input type="submit" name="send_answer" value="Zkontrolovat" />
+ </div>
+ </form>
--- /dev/null
+
+ <div class="backgrounded_block">
+ <div class="caption_v1">Zadání:</div>
+ <div class="assignment_text">V jakém objemu se rozpustí @_SAMPLE_WEIGHT_INT_@,@_SAMPLE_WEIGHT_DEC_@ g látky X<span class="subscript">@_X_STOCHIO_@</span>Z<span class="subscript">@_Z_STOCHIO_@</span> o K<span class="subscript">s</span>=@_KS_INT_@,@_KS_DEC_@ . 10<span class="exponent">@_KS_EXP_@</span> a molekulové hmotnosti MW=@_MOLAR_MASS_INT_@,@_MOLAR_MASS_DEC_@ g/mol?</div>
+ @_SUBMIT_FORM_@
+ </div>
+
+ @_ANSWER_SECTION_@
+
+ <div class="backgrounded_block">
+ <span class="expand_section" onclick="show_hide_item('hints_section', 'hints_button', 'block', '/images/arrow_right.png', '/images/arrow_down.png')">
+ <img class="expand_section" id="hints_button" src="/images/arrow_right.png" alt="Zobraz sekci" title="Zobraz sekci" />
+ </span>
+ <div class="caption_v1">Nápověda:</div>
+ <div class="assignment_hint" id="hints_section">
+ @_HINTS_SECTION_@
+ </div>
+ </div>
+
+ <div class="backgrounded_block">
+ <div class="caption_v1">Parametry příkladů:</div>
+ @_PARAMETERS_FORM_@
+ </div>
-with AWS.Templates;
+with Ada.Strings.Unbounded;
package body Face_Generator is
function Generate_Index_Face(HTML: out HTML_Code) return Boolean is
use AWS.Templates;
+
Temp: HTML_Code;
Translations_Hdr: Translate_Set;
begin
declare
Problem_Type_Str: constant String := Assignment.Element(PROBLEM_TYPE_KEY);
begin
- if Problem_Type_Str = Problem_Type'Image(Acidobazic) then
+ if Problem_Type_Str = PROBLEM_TYPE_ACIDOBAZIC then
return Generate_Face_Acidobazic(Assignment, Answer_Message, Answer_Code, Parameters, HTML);
+ elsif Problem_Type_Str = PROBLEM_TYPE_SOLUBILITY then
+ return Generate_Face_Solubility(Assignment, Answer_Message, Answer_Code, Parameters, HTML);
else
return False;
end if;
end Generate_Face_With_Answer;
-- BEGIN: Private functions
+
+ procedure Add_Answer_Section(Translations: in out AWS.Templates.Translate_Set; Answer_Message: in UB_Text;
+ AR: in Problem_Generator_Syswides.Answer_RetCode) is
+ use AWS.Templates;
+ use Problem_Generator_Syswides;
+
+ Temp: HTML_Code;
+ Translations_Answer: Translate_Set;
+ begin
+ case AR is
+ when Correct_Answer =>
+ Insert(Translations_Answer, Assoc(ANSWER_KIND_KEY, ANSWER_KIND_GOOD));
+ Insert(Translations_Answer, Assoc(ANSWER_MESSAGE_KEY, UB_Text_To_Fixed_String(Answer_Message)));
+ Temp := Parse(Filename => "templates/answer_section.html", Translations => Translations_Answer);
+ Insert(Translations, Assoc(ANSWER_SECTION_KEY, HTML_To_Fixed_String(Temp)));
+ when Wrong_Answer | Malformed_Answer =>
+ Insert(Translations_Answer, Assoc(ANSWER_KIND_KEY, ANSWER_KIND_BAD));
+ Insert(Translations_Answer, Assoc(ANSWER_MESSAGE_KEY, UB_Text_To_Fixed_String(Answer_Message)));
+ Temp := Parse(Filename => "templates/answer_section.html", Translations => Translations_Answer);
+ Insert(Translations, Assoc(ANSWER_SECTION_KEY, HTML_To_Fixed_String(Temp)));
+ when others =>
+ Insert(Translations, Assoc(ANSWER_SECTION_KEY, ""));
+ end case;
+ end Add_Answer_Section;
+
function Generate_Face_Acidobazic(Assignment: in Problem_Generator_Syswides.Assignment_Info.Map;
Answer_Message: in UB_Text;
Answer_Code: in Problem_Generator_Syswides.Answer_RetCode;
use Problem_Generator_Syswides.Assignment_Info;
use Problem_Generator_Syswides.Parameters_Info;
- Translations_Answer: Translate_Set;
Translations_Hdr: Translate_Set;
Translations: Translate_Set;
Temp: HTML_Code;
Insert(Translations, Assoc("PARAMETER_NO_BOTH_SIMPLIFICATIONS_CHECKED", "checked"));
end if;
- case Answer_Code is
- when Correct_Answer =>
- Insert(Translations_Answer, Assoc(ANSWER_KIND_KEY, ANSWER_KIND_GOOD));
- Insert(Translations_Answer, Assoc(ANSWER_MESSAGE_KEY, UB_Text_To_Fixed_String(Answer_Message)));
- Temp := Parse(Filename => "templates/answer_section.html", Translations => Translations_Answer);
- Insert(Translations, Assoc(ANSWER_SECTION_KEY, HTML_To_Fixed_String(Temp)));
- when Wrong_Answer | Malformed_Answer =>
- Insert(Translations_Answer, Assoc(ANSWER_KIND_KEY, ANSWER_KIND_BAD));
- Insert(Translations_Answer, Assoc(ANSWER_MESSAGE_KEY, UB_Text_To_Fixed_String(Answer_Message)));
- Temp := Parse(Filename => "templates/answer_section.html", Translations => Translations_Answer);
- Insert(Translations, Assoc(ANSWER_SECTION_KEY, HTML_To_Fixed_String(Temp)));
- when others =>
- Insert(Translations, Assoc(ANSWER_SECTION_KEY, ""));
- end case;
+ Add_Answer_Section(Translations, Answer_Message, Answer_Code);
-- Generate hints
if Assignment.Element(Acidobazic_Suite.PKX_KEY) = Acidobazic_Suite.PKX_PKA_TEXT then
return True;
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) return Boolean is
+ use Ada.Strings.Unbounded;
+ use AWS.Templates;
+ use Problem_Generator_Syswides;
+ use Problem_Generator_Syswides.Assignment_Info;
+ use Problem_Generator_Syswides.Parameters_Info;
+
+ Translations_Hdr: Translate_Set;
+ Translations_Params: Translate_Set;
+ Translations: Translate_Set;
+ Temp: HTML_Code;
+ Params_Code: HTML_Code;
+
+ P_Subtype: UB_Text;
+ begin
+ Insert(Translations_Hdr, Assoc(HEADER_CAPTION_KEY, "< " & Solubility_Suite.PROBLEM_NAME_READABLE));
+ Insert(Translations_Hdr, Assoc(META_EXPIRE_NOW_KEY, META_EXPIRE_NOW_TEXT));
+ Insert(Translations_Hdr, Assoc(META_NO_CACHE_KEY, META_NO_CACHE_TEXT));
+ HTML := Parse(Filename => "templates/header.html", Translations => Translations_Hdr);
+ -- Add JavaScripts
+ Temp := Parse(Filename => "scripts/expand_collapse.js", Cached => True);
+ Append_HTML(Source => HTML, New_Item => Temp);
+
+ Add_Answer_Section(Translations, Answer_Message, Answer_Code);
+
+ Temp := Parse(Filename => "templates/face_solubility_submit.html", Cached => True);
+ Insert(Translations, Assoc("SUBMIT_FORM", HTML_To_Fixed_String(Temp)));
+
+ -- Add parameters section
+ Insert(Translations_Params, Assoc(Solubility_Suite.PARAMETER_IONIC_STRENGTH_KEY, Solubility_Suite.PARAMETER_IONIC_STRENGTH_KEY));
+ if Parameters.Find(Solubility_Suite.PARAMETER_IONIC_STRENGTH_KEY) /= Parameters_Info.No_Element then
+ Insert(Translations_Params, Assoc("PARAMETER_IONIC_STRENGTH_CHECKED", "checked=""checked"""));
+ end if;
+ if Parameters.Find(Solubility_Suite.PARAMETER_PROBLEM_SUBTYPE_KEY) = Parameters_Info.No_Element then
+ -- This parameter must be always present
+ return False;
+ 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));
+ Insert(Translations_Params, Assoc(Solubility_Suite.PROBLEM_SUBTYPE_V_FROM_G_KS, Solubility_Suite.PROBLEM_SUBTYPE_V_FROM_G_KS));
+ Insert(Translations_Params, Assoc(Solubility_Suite.PROBLEM_SUBTYPE_KS_FROM_G_V, Solubility_Suite.PROBLEM_SUBTYPE_KS_FROM_G_V));
+ Insert(Translations_Params, Assoc(Solubility_Suite.PROBLEM_SUBTYPE_C_FROM_KS_DIFFERENT_IONS, Solubility_Suite.PROBLEM_SUBTYPE_C_FROM_KS_DIFFERENT_IONS));
+ Insert(Translations_Params, Assoc(Solubility_Suite.PROBLEM_SUBTYPE_C_FROM_KS_SHARED_ION, Solubility_Suite.PROBLEM_SUBTYPE_C_FROM_KS_SHARED_ION));
+ Insert(Translations_Params, Assoc(UB_Text_To_Fixed_String(P_Subtype) & "_SELECTED", "selected=""selected"""));
+ -- Load and parse parameters template
+ Params_Code := Parse(Filename => "templates/face_solubility_params.html", Translations => Translations_Params);
+ -- Put the processed parameters template into the face
+ Insert(Translations, Assoc("PARAMETERS_FORM", HTML_To_Fixed_String(Params_Code)));
+
+
+ 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;
+ end if;
+ if Assignment.Find(Solubility_Suite.Z_STOCHIO_KEY) = Assignment_Info.No_Element then
+ return False;
+ end if;
+ if Assignment.Find(Solubility_Suite.KS_INT_KEY) = Assignment_Info.No_Element then
+ return False;
+ end if;
+ if Assignment.Find(Solubility_Suite.KS_DEC_KEY) = Assignment_Info.No_Element then
+ return False;
+ end if;
+ if Assignment.Find(Solubility_Suite.KS_INT_KEY) = Assignment_Info.No_Element then
+ return False;
+ end if;
+ if Assignment.Find(Solubility_Suite.SAMPLE_WEIGHT_INT_KEY) = Assignment_Info.No_Element then
+ return False;
+ end if;
+ if Assignment.Find(Solubility_Suite.SAMPLE_WEIGHT_DEC_KEY) = Assignment_Info.No_Element then
+ return False;
+ end if;
+ if Assignment.Find(Solubility_Suite.MOLAR_MASS_INT_KEY) = Assignment_Info.No_Element then
+ return False;
+ end if;
+ if Assignment.Find(Solubility_Suite.MOLAR_MASS_DEC_KEY) = Assignment_Info.No_Element then
+ return False;
+ end if;
+
+ Insert(Translations, Assoc(Solubility_Suite.X_STOCHIO_KEY, Assignment.Element(Solubility_Suite.X_STOCHIO_KEY)));
+ Insert(Translations, Assoc(Solubility_Suite.Z_STOCHIO_KEY, Assignment.Element(Solubility_Suite.Z_STOCHIO_KEY)));
+ Insert(Translations, Assoc(Solubility_Suite.KS_INT_KEY, Assignment.Element(Solubility_Suite.KS_INT_KEY)));
+ Insert(Translations, Assoc(Solubility_Suite.KS_DEC_KEY, Assignment.Element(Solubility_Suite.KS_DEC_KEY)));
+ Insert(Translations, Assoc(Solubility_Suite.KS_EXP_KEY, Assignment.Element(Solubility_Suite.KS_EXP_KEY)));
+ Insert(Translations, Assoc(Solubility_Suite.SAMPLE_WEIGHT_INT_KEY, Assignment.Element(Solubility_Suite.SAMPLE_WEIGHT_INT_KEY)));
+ Insert(Translations, Assoc(Solubility_Suite.SAMPLE_WEIGHT_DEC_KEY, Assignment.Element(Solubility_Suite.SAMPLE_WEIGHT_DEC_KEY)));
+ Insert(Translations, Assoc(Solubility_Suite.MOLAR_MASS_INT_KEY, Assignment.Element(Solubility_Suite.MOLAR_MASS_INT_KEY)));
+ Insert(Translations, Assoc(Solubility_Suite.MOLAR_MASS_DEC_KEY, Assignment.Element(Solubility_Suite.MOLAR_MASS_DEC_KEY)));
+
+ Temp := Parse(Filename => "templates/face_solubility_v_f_g_ks.html", Translations => Translations);
+ Append_HTML(Source => HTML, New_Item => Temp);
+ 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;
+ end if;
+ if Assignment.Find(Solubility_Suite.Z_STOCHIO_KEY) = Assignment_Info.No_Element then
+ return False;
+ end if;
+ if Assignment.Find(Solubility_Suite.SAMPLE_VOLUME_INT_KEY) = Assignment_Info.No_Element then
+ return False;
+ end if;
+ if Assignment.Find(Solubility_Suite.SAMPLE_VOLUME_DEC_KEY) = Assignment_Info.No_Element then
+ return False;
+ end if;
+ if Assignment.Find(Solubility_Suite.SAMPLE_VOLUME_EXP_KEY) = Assignment_Info.No_Element then
+ return False;
+ end if;
+ if Assignment.Find(Solubility_Suite.SAMPLE_WEIGHT_INT_KEY) = Assignment_Info.No_Element then
+ return False;
+ end if;
+ if Assignment.Find(Solubility_Suite.SAMPLE_WEIGHT_DEC_KEY) = Assignment_Info.No_Element then
+ return False;
+ end if;
+ if Assignment.Find(Solubility_Suite.MOLAR_MASS_INT_KEY) = Assignment_Info.No_Element then
+ return False;
+ end if;
+ if Assignment.Find(Solubility_Suite.MOLAR_MASS_DEC_KEY) = Assignment_Info.No_Element then
+ return False;
+ end if;
+
+ Insert(Translations, Assoc(Solubility_Suite.X_STOCHIO_KEY, Assignment.Element(Solubility_Suite.X_STOCHIO_KEY)));
+ Insert(Translations, Assoc(Solubility_Suite.Z_STOCHIO_KEY, Assignment.Element(Solubility_Suite.Z_STOCHIO_KEY)));
+ Insert(Translations, Assoc(Solubility_Suite.SAMPLE_VOLUME_INT_KEY, Assignment.Element(Solubility_Suite.SAMPLE_VOLUME_INT_KEY)));
+ Insert(Translations, Assoc(Solubility_Suite.SAMPLE_VOLUME_DEC_KEY, Assignment.Element(Solubility_Suite.SAMPLE_VOLUME_DEC_KEY)));
+ Insert(Translations, Assoc(Solubility_Suite.SAMPLE_VOLUME_EXP_KEY, Assignment.Element(Solubility_Suite.SAMPLE_VOLUME_EXP_KEY)));
+ Insert(Translations, Assoc(Solubility_Suite.SAMPLE_WEIGHT_INT_KEY, Assignment.Element(Solubility_Suite.SAMPLE_WEIGHT_INT_KEY)));
+ Insert(Translations, Assoc(Solubility_Suite.SAMPLE_WEIGHT_DEC_KEY, Assignment.Element(Solubility_Suite.SAMPLE_WEIGHT_DEC_KEY)));
+ Insert(Translations, Assoc(Solubility_Suite.MOLAR_MASS_INT_KEY, Assignment.Element(Solubility_Suite.MOLAR_MASS_INT_KEY)));
+ Insert(Translations, Assoc(Solubility_Suite.MOLAR_MASS_DEC_KEY, Assignment.Element(Solubility_Suite.MOLAR_MASS_DEC_KEY)));
+
+ Temp := Parse(Filename => "templates/face_solubility_ks_f_g_v.html", Translations => Translations);
+ Append_HTML(Source => HTML, New_Item => Temp);
+ 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;
+ end if;
+ if Assignment.Find(Solubility_Suite.Z_STOCHIO_KEY) = Assignment_Info.No_Element then
+ return False;
+ end if;
+ if Assignment.Find(Solubility_Suite.EC_INT_KEY) = Assignment_Info.No_Element then
+ return False;
+ end if;
+ if Assignment.Find(Solubility_Suite.EC_DEC_KEY) = Assignment_Info.No_Element then
+ return False;
+ end if;
+ if Assignment.Find(Solubility_Suite.EC_EXP_KEY) = Assignment_Info.No_Element then
+ return False;
+ end if;
+ if Assignment.Find(Solubility_Suite.KS_INT_KEY) = Assignment_Info.No_Element then
+ return False;
+ end if;
+ if Assignment.Find(Solubility_Suite.KS_DEC_KEY) = Assignment_Info.No_Element then
+ return False;
+ end if;
+ if Assignment.Find(Solubility_Suite.KS_INT_KEY) = Assignment_Info.No_Element then
+ return False;
+ end if;
+
+ Insert(Translations, Assoc(Solubility_Suite.X_STOCHIO_KEY, Assignment.Element(Solubility_Suite.X_STOCHIO_KEY)));
+ Insert(Translations, Assoc(Solubility_Suite.Z_STOCHIO_KEY, Assignment.Element(Solubility_Suite.Z_STOCHIO_KEY)));
+ Insert(Translations, Assoc(Solubility_Suite.EC_INT_KEY, Assignment.Element(Solubility_Suite.EC_INT_KEY)));
+ Insert(Translations, Assoc(Solubility_Suite.EC_DEC_KEY, Assignment.Element(Solubility_Suite.EC_DEC_KEY)));
+ Insert(Translations, Assoc(Solubility_Suite.EC_EXP_KEY, Assignment.Element(Solubility_Suite.EC_EXP_KEY)));
+ Insert(Translations, Assoc(Solubility_Suite.KS_INT_KEY, Assignment.Element(Solubility_Suite.KS_INT_KEY)));
+ Insert(Translations, Assoc(Solubility_Suite.KS_DEC_KEY, Assignment.Element(Solubility_Suite.KS_DEC_KEY)));
+ Insert(Translations, Assoc(Solubility_Suite.KS_EXP_KEY, Assignment.Element(Solubility_Suite.KS_EXP_KEY)));
+
+ if P_Subtype = Solubility_Suite.PROBLEM_SUBTYPE_C_FROM_KS_DIFFERENT_IONS then
+ Temp := Parse(Filename => "templates/face_solubility_c_f_ks_diff.html", Translations => Translations);
+ else
+ Temp := Parse(Filename => "templates/face_solubility_c_f_ks_shared.html", Translations => Translations);
+ end if;
+ Append_HTML(Source => HTML, New_Item => Temp);
+ else
+ return False;
+ end if;
+
+ Temp := Parse(Filename => "templates/footer.html");
+ Append_HTML(Source => HTML, New_Item => Temp);
+
+ return True;
+ end Generate_Face_Solubility;
+
end Face_Generator;
with Global_Types;
with Problem_Generator_Syswides;
+with AWS.Templates;
use Global_Types;
package Face_Generator is
HTML: out HTML_Code) return Boolean;
private
+ procedure Add_Answer_Section(Translations: in out AWS.Templates.Translate_Set; Answer_Message: in UB_Text;
+ AR: in Problem_Generator_Syswides.Answer_RetCode);
+
function Generate_Face_Acidobazic(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) return Boolean;
+ 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) return Boolean;
+
HEADER_CAPTION_KEY: constant String := "HEADER_CAPTION";
HINTS_SECTION_KEY: constant String := "HINTS_SECTION";
META_EXPIRE_NOW_KEY: constant String := "META_EXPIRE_NOW";
package body Formatting_Helpers is
+ function Get_Decimal_Part_Flt(Num: in FH_Float) return FH_Float is
+ package FHEF is new Ada.Numerics.Generic_Elementary_Functions(FH_Float);
+ use FHEF;
+
+ Log_Arg_Floored: FH_Float;
+ begin
+ Log_Arg_Floored := FH_Float'Floor(FHEF.Log(Base => 10.0, X => Num));
+
+ return ((10.0 ** Log_Arg_Floored) - 1.0) / Log_Arg_Floored;
+ end Get_Decimal_Part_Flt;
+
+ function Get_Integer_Part_Int(Num: in FH_Float) return Integer is
+ package FHEF is new Ada.Numerics.Generic_Elementary_Functions(FH_Float);
+ use FHEF;
+
+ Log_Arg_Floored: FH_Float;
+ Scaled: FH_Float;
+ begin
+ Log_Arg_Floored := FH_Float'Floor(FHEF.Log(Base => 10.0, X => Num));
+ Scaled := Num / Log_Arg_Floored;
+
+ return Integer(Scaled - Get_Decimal_Part_Flt(Num));
+ end Get_Integer_Part_Int;
+
+ function String_To_Float(S: in String) return FH_Float is
+ F: FH_Float;
+ Idx: Natural;
+ SS: String := S;
+ begin
+ -- Replace "," with "." as decimal seaprator
+ Idx := Ada.Strings.Fixed.Index(Source => SS, Pattern => ",", From => 1);
+ if Idx > 0 then
+ Ada.Strings.Fixed.Replace_Slice(Source => SS, Low => Idx, High => Idx, By => ".");
+ end if;
+
+ begin
+ return FH_Float'Value(S);
+ exception
+ when Constraint_Error =>
+ raise Constraint_Error;
+ end;
+ end String_To_Float;
+
function Round_To_Valid_Nums(Num: in FH_Float; Decimals: in FH_Float) return FH_Float is
package FHEF is new Ada.Numerics.Generic_Elementary_Functions(FH_Float);
use FHEF;
type FH_Float is digits <>;
package Formatting_Helpers is
+ function Get_Decimal_Part_Flt(Num: in FH_Float) return FH_Float;
+ function Get_Integer_Part_Int(Num: in FH_Float) return Integer;
+ function String_To_Float(S: in String) return FH_Float;
function Round_To_Valid_Nums(Num: in FH_Float; Decimals: FH_Float) return FH_Float;
procedure Split_Integer_Decimal_Strs(Num: in FH_Float; Decimals: in FH_Float; Integer_Part: out UB_Text; Decimal_Part: out UB_Text);
procedure Split_Integer_Decimal_Exponent_Strs(Num: in FH_Float; Decimals: in FH_Float; Integer_Part: out UB_Text; Decimal_Part: out UB_Text;
Ada.Strings.Unbounded.Append(Source => Source, New_Item => New_Item);
end Append_UB_Text;
+ procedure Append_UB_Text(Source: in out UB_Text; New_Item: in String) is
+ begin
+ Ada.Strings.Unbounded.Append(Source => Source, New_Item => To_UB_Text(New_Item));
+ end Append_UB_Text;
+
function HTML_To_Fixed_String(HTML: in HTML_Code) return String is
begin
return Ada.Strings.Unbounded.To_String(HTML);
procedure Append_HTML(Source: in out HTML_Code; New_Item: in HTML_Code);
procedure Append_UB_Text(Source: in out UB_Text; New_Item: in UB_Text);
+ procedure Append_UB_Text(Source: in out UB_Text; New_Item: in String);
function HTML_To_Fixed_String(HTML: in HTML_Code) return String;
function To_HTML_Code(S: in String) return HTML_Code;
function To_UB_Text(S: in String) return UB_Text;
Success: Boolean;
begin
if Raw_Problem_Category = Problem_Manager.Problem_Category'Image(Problem_Manager.Acidobazic) then
- P_Cat := Problem_Manager.Acidobazic;
+ P_Cat := Problem_Manager.Acidobazic;
+ elsif Raw_Problem_Category = Problem_Manager.Problem_Category'Image(Problem_Manager.Solubility) then
+ P_Cat := Problem_Manager.Solubility;
else
- return AWS.Response.URL(Location => "/");
+ return AWS.Response.URL(Location => "/");
end if;
-- Register new UID if necessary and create a first problem
with Ada.Numerics.Float_Random;
with Ada.Numerics.Generic_Elementary_Functions;
with Ada.Strings.Fixed;
---with Ada.Text_IO;
+with Ada.Text_IO;
with Formatting_Helpers;
separate(Problem_Generator)
package FH is new Formatting_Helpers(pH_Float);
use Answer_Info;
+ Guard: Auto_Lock.LC;
pH: pH_Float;
pH_Answered: pH_Float;
begin
- Problem.Lock_State;
+ Auto_Lock.Init(Guard, Problem.Mutex'Unchecked_Access);
+ Guard.Lock;
pH := Calculate_Solution(Problem);
-- Verify answer data
return Malformed_Answer;
end if;
if Answer.Find(ANSWER_SIMPLIFICATION_KEY) = Answer_Info.No_Element then
- Problem.Unlock_State;
return Malformed_Answer;
end if;
exception
when Constraint_Error =>
Message := To_UB_Text("Nesprávně zadaná hodnota pH");
- Problem.Unlock_State;
return Malformed_Answer;
end;
Ada.Text_IO.Put_Line("SS : " & Simplification_Str & " SI : " & Simplification'Image(Problem.Simpl));
if Simplification_Str /= Simplification'Image(Problem.Simpl) then
Message := To_UB_Text("Nesprávné zanedbání");
- Problem.Unlock_State;
return Wrong_Answer;
end if;
end;
if pH_Answered - (Precision * 5.0) < pH and pH_Answered + (Precision * 5.0) > pH then
Message := To_UB_Text("Správná odpověď");
- Problem.Unlock_State;
return Correct_Answer;
else
declare
Append_UB_Text(Source => Message, New_Item => To_UB_Text(","));
Append_UB_Text(Source => Message, New_Item => Dec_S);
Append_UB_Text(Source => Message, New_Item => To_UB_Text(")"));
- Problem.Unlock_State;
return Wrong_Answer;
end;
end if;
end Check_Answer;
function Get_Assignment(Problem: in out Acidobazic_Problem; Assignment: in out Assignment_Info.Map) return Boolean is
+ Guard: Auto_Lock.LC;
C: Assignment_Info.Cursor;
Success: Boolean;
pKx: pH_Float;
begin
- Problem.Lock_State;
+ Auto_Lock.Init(Guard, Problem.Mutex'Unchecked_Access);
+ Guard.Lock;
Assignment.Insert(PROBLEM_TYPE_KEY, PROBLEM_TYPE_ACIDOBAZIC, C, Success);
if Success = False then
- Problem.Unlock_State;
return False;
end if;
case Problem.Subst_Type is
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
- Problem.Unlock_State;
return False;
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
- Problem.Unlock_State;
return False;
end if;
end;
- Problem.Unlock_State;
return True;
end Get_Assignment;
function Get_Parameters(Problem: in out Acidobazic_Problem; Parameters: out Parameters_Info.Map) return Boolean is
+ Guard: Auto_Lock.LC;
C: Parameters_Info.Cursor;
Success: Boolean;
begin
- Problem.Lock_State;
+ Auto_Lock.Init(Guard, Problem.Mutex'Unchecked_Access);
+ Guard.Lock;
+
if Problem.Parameters.No_Both_Simplifications then
Parameters.Insert(PARAMETER_NO_BOTH_SIMPLIFICATIONS_KEY, "True", C, Success);
- Problem.Unlock_State;
return Success;
end if;
- Problem.Unlock_State;
return True;
end Get_Parameters;
procedure New_Problem(Problem: in out Acidobazic_Problem) is
-
package Random_Substance_Type_Gen is new Ada.Numerics.Discrete_Random(Result_Subtype => Substance_Type);
package Random_Dissoc_Type_Gen is new Ada.Numerics.Discrete_Random(Result_Subtype => Dissociation_Constant_Type);
+ Guard: Auto_Lock.LC;
DCT_G: Random_Dissoc_Type_Gen.Generator;
ST_G: Random_Substance_Type_Gen.Generator;
cX_Min: pH_Float;
cX_Max: pH_Float;
begin
- Problem.Lock_State;
+ Auto_Lock.Init(Guard, Problem.Mutex'Unchecked_Access);
+ Guard.Lock;
-- Dissociation constant type (pKa or pKb)
Random_Dissoc_Type_Gen.Reset(Gen => DCT_G);
Problem.DCT := Random_Dissoc_Type_Gen.Random(Gen => DCT_G);
Calculate_Concentration_Limits(cX_Min, cX_Max, Problem.Kx, Problem.Simpl);
Problem.cX := Random_cX(cX_Min, cX_Max);
- Problem.Unlock_State;
end New_Problem;
function Set_Parameters(Problem: in out Acidobazic_Problem; Parameters: in Parameters_Info.Map) return Boolean is
use Parameters_Info;
+
+ Guard: Auto_Lock.LC;
begin
- Problem.Lock_State;
+ Auto_Lock.Init(Guard, Problem.Mutex'Unchecked_Access);
+ Guard.Lock;
+
if Parameters.Find(PARAMETER_NO_BOTH_SIMPLIFICATIONS_KEY) = Parameters_Info.No_Element then
Problem.Parameters.No_Both_Simplifications := False;
else
Problem.Parameters.No_Both_Simplifications := True;
end if;
- Problem.Unlock_State;
return True;
end Set_Parameters;
-- END: Inherited functions
--- /dev/null
+with Ada.Numerics.Discrete_Random;
+with Ada.Numerics.Float_Random;
+with Ada.Numerics.Generic_Elementary_Functions;
+with Ada.Strings.Fixed;
+with Ada.Text_IO;
+with Formatting_Helpers;
+
+separate(Problem_Generator)
+
+package body Solubility_Suite is
+
+ -- BEGIN: Inherited funcions
+ function Create return access Solubility_Problem is
+ Problem: access Solubility_Problem;
+ Parameters: Solubility_Parameters;
+ begin
+ Parameters := (Ionic_Strength => False,
+ P_Subtype => V_FROM_G_KS);
+
+ Problem := new Solubility_Problem;
+ Problem.Parameters := Parameters;
+ return Problem;
+ end;
+
+ function Check_Answer(Problem: in out Solubility_Problem; Answer: in Answer_Info.Map; Message: out UB_Text) return Answer_RetCode is
+ package FH is new Formatting_Helpers(SS_Float);
+ use Answer_Info;
+ use FH;
+
+ Guard: Auto_Lock.LC;
+ AF: SS_Float;
+ Int_Part_Got: Integer;
+ Int_Part_Calcd: Integer;
+ Dec_Part_Got: SS_Float;
+ Dec_Part_Calcd: SS_Float;
+ begin
+ Auto_Lock.Init(Guard, Problem.Mutex'Unchecked_Access);
+ Guard.Lock;
+ -- Check that there is a valid answer in the map
+ if Answer.Find(ANSWER_NUM_KEY) = Answer_Info.No_Element then
+ return No_Answer;
+ end if;
+
+ begin
+ AF := String_To_Float(Answer.Element(ANSWER_NUM_KEY));
+ exception
+ when Constraint_Error =>
+ Message := To_UB_Text("Nesprávně zadaná odpověď");
+ return Malformed_Answer;
+ end;
+
+ Int_Part_Got := Get_Integer_Part_Int(AF);
+ Int_Part_Calcd := Get_Integer_Part_Int(Problem.Answer_Num);
+ if Int_Part_Got /= Int_Part_Calcd then
+ Get_Correct_Answer_String(Message, Problem.Parameters.P_Subtype, Problem.Answer_Num);
+ return Wrong_Answer;
+ end if;
+
+ Dec_Part_Got := Get_Decimal_Part_Flt(AF);
+ Dec_Part_Calcd := Get_Decimal_Part_Flt(Problem.Answer_Num);
+
+ if Dec_Part_Calcd + PRECISION < Dec_Part_Got and Dec_Part_Calcd - PRECISION > Dec_Part_Got then
+ return Correct_Answer;
+ else
+ Get_Correct_Answer_String(Message, Problem.Parameters.P_Subtype, Problem.Answer_Num);
+ return Wrong_Answer;
+ end if;
+ end Check_Answer;
+
+ function Get_Assignment(Problem: in out Solubility_Problem; Assignment: in out Assignment_Info.Map) return Boolean is
+ package FH is new Formatting_Helpers(SS_Float);
+ use FH;
+
+ Guard: Auto_Lock.LC;
+ begin
+ Auto_Lock.Init(Guard, Problem.Mutex'Unchecked_Access);
+ Guard.Lock;
+ Assignment.Insert(PROBLEM_TYPE_KEY, PROBLEM_TYPE_SOLUBILITY);
+ Assignment.Insert(PROBLEM_SUBTYPE_KEY, Problem_Subtype'Image(Problem.Parameters.P_Subtype));
+
+ -- Stochiometry
+ if (Problem.Prob_Data.M > 1.0) then
+ Assignment.Insert(X_STOCHIO_KEY, Stochiometric_Count'Image(Stochiometric_Count(Problem.Prob_Data.M)));
+ else
+ Assignment.Insert(X_STOCHIO_KEY, "");
+ end if;
+ if (Problem.Prob_Data.N > 1.0) then
+ Assignment.Insert(Z_STOCHIO_KEY, Stochiometric_Count'Image(Stochiometric_Count(Problem.Prob_Data.N)));
+ else
+ Assignment.Insert(Z_STOCHIO_KEY, "");
+ end if;
+
+ case Problem.Parameters.P_Subtype is
+ when V_FROM_G_KS =>
+ declare
+ G_Str_Int: UB_Text;
+ G_Str_Dec: UB_Text;
+ Ks_Str_Int: UB_Text;
+ Ks_Str_Dec: UB_Text;
+ Ks_Str_Exp: UB_Text;
+ MW_Str_Int: UB_Text;
+ MW_Str_Dec: UB_Text;
+ begin
+ Split_Integer_Decimal_Strs(Problem.Prob_Data.V_G, DECIMALS, G_Str_Int, G_Str_Dec);
+ Split_Integer_Decimal_Strs(Problem.Prob_Data.V_MW, DECIMALS_MW, MW_Str_Int, MW_Str_Dec);
+ Split_Integer_Decimal_Exponent_Strs(Problem.Prob_Data.V_Ks, DECIMALS, Ks_Str_Int, Ks_Str_Dec, Ks_Str_Exp);
+
+ Assignment.Insert(SAMPLE_WEIGHT_INT_KEY, UB_Text_To_Fixed_String(G_Str_Int));
+ Assignment.Insert(SAMPLE_WEIGHT_DEC_KEY, UB_Text_To_Fixed_String(G_Str_Dec));
+ Assignment.Insert(MOLAR_MASS_INT_KEY, UB_Text_To_Fixed_String(MW_Str_Int));
+ Assignment.Insert(MOLAR_MASS_DEC_KEY, UB_Text_To_Fixed_String(MW_Str_Dec));
+ 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;
+ end;
+ when KS_FROM_G_V =>
+ declare
+ G_Str_Int: UB_Text;
+ G_Str_Dec: UB_Text;
+ MW_Str_Int: UB_Text;
+ MW_Str_Dec: UB_Text;
+ V_Str_Int: UB_Text;
+ V_Str_Dec: UB_Text;
+ V_Str_Exp: UB_Text;
+ begin
+ Split_Integer_Decimal_Strs(Problem.Prob_Data.Ks_G, DECIMALS, G_Str_Int, G_Str_Dec);
+ Split_Integer_Decimal_Strs(Problem.Prob_Data.Ks_MW, DECIMALS_MW, MW_Str_Int, MW_Str_Dec);
+ Split_Integer_Decimal_Exponent_Strs(Problem.Prob_Data.Ks_V, DECIMALS, V_Str_Int, V_Str_Dec, V_Str_Exp);
+
+ Assignment.Insert(SAMPLE_WEIGHT_INT_KEY, UB_Text_To_Fixed_String(G_Str_Int));
+ Assignment.Insert(SAMPLE_WEIGHT_DEC_KEY, UB_Text_To_Fixed_String(G_Str_Dec));
+ Assignment.Insert(MOLAR_MASS_INT_KEY, UB_Text_To_Fixed_String(MW_Str_Int));
+ Assignment.Insert(MOLAR_MASS_DEC_KEY, UB_Text_To_Fixed_String(MW_Str_Dec));
+ 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;
+ end;
+ when C_FROM_KS_DIFFERENT_IONS | C_FROM_KS_SHARED_ION =>
+ declare
+ EC_Str_Int: UB_Text;
+ EC_Str_Dec: UB_Text;
+ EC_Str_Exp: UB_Text;
+ Ks_Str_Int: UB_Text;
+ Ks_Str_Dec: UB_Text;
+ Ks_Str_Exp: UB_Text;
+ begin
+ Split_Integer_Decimal_Exponent_Strs(Problem.Prob_Data.C_EC, DECIMALS, EC_Str_Int, EC_Str_Dec, EC_Str_Exp);
+ Split_Integer_Decimal_Exponent_Strs(Problem.Prob_Data.C_Ks, DECIMALS, Ks_Str_Int, Ks_Str_Dec, Ks_Str_Exp);
+
+ Assignment.Insert(EC_INT_KEY, UB_Text_To_Fixed_String(EC_Str_Int));
+ Assignment.Insert(EC_DEC_KEY, UB_Text_To_Fixed_String(EC_Str_Dec));
+ Assignment.Insert(EC_EXP_KEY, UB_Text_To_Fixed_String(EC_Str_Exp));
+ 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;
+ end;
+ end case;
+ end Get_Assignment;
+
+ function Get_Parameters(Problem: in out Solubility_Problem; Parameters: out Parameters_Info.Map) return Boolean is
+ Guard: Auto_Lock.LC;
+ C: Parameters_Info.Cursor;
+ Success: Boolean;
+ begin
+ Auto_Lock.Init(Guard, Problem.Mutex'Unchecked_Access);
+ Guard.Lock;
+
+ if Problem.Parameters.Ionic_Strength then
+ Parameters.Insert(PARAMETER_IONIC_STRENGTH_KEY, "True", C, Success);
+ if Success = False then
+ return False;
+ end if;
+ end if;
+
+ Parameters.Insert(PARAMETER_PROBLEM_SUBTYPE_KEY, Problem_Subtype'Image(Problem.Parameters.P_Subtype), C, Success);
+
+ return Success;
+ end Get_Parameters;
+
+ procedure New_Problem(Problem: in out Solubility_Problem) is
+ package FH is new Formatting_Helpers(SS_Float);
+ package Random_Stochio_Count is new Ada.Numerics.Discrete_Random(Stochiometric_Count);
+ use FH;
+ use Ada.Numerics.Float_Random;
+
+ Stochio_RGen: Random_Stochio_Count.Generator;
+ Float_RGen: Generator;
+
+ Guard: Auto_Lock.LC;
+ M: Stochiometric_Count; -- Number of cations
+ N: Stochiometric_Count; -- Number of anions
+ Answer_Num: SS_Float; -- Answer to this problem
+ Prob_Data: Solubility_Problem_Data; -- Assignment data
+ begin
+ Auto_Lock.Init(Guard, Problem.Mutex'Unchecked_Access);
+ Guard.Lock;
+ -- Generate MW
+ Reset(Gen => Float_RGen);
+
+ -- Generate stochiometry of the molecul
+ Random_Stochio_Count.Reset(Gen => Stochio_RGen);
+ M := Random_Stochio_Count.Random(Gen => Stochio_RGen);
+ N := Random_Stochio_Count.Random(Gen => Stochio_RGen);
+
+ -- Reduce molecule stochiometry to the lowest terms
+ declare
+ High: Stochiometric_Count := Stochiometric_Count'Max(M, N);
+ Low: constant Stochiometric_Count := Stochiometric_Count'Min(M, N);
+ Modulus: Natural;
+ begin
+ Modulus := High mod Low;
+ if Modulus = 0 then
+ High := High / Low;
+ if M > N then
+ M := High;
+ N := 1;
+ else
+ N := High;
+ M := 1;
+ end if;
+ end if;
+ end;
+
+ -- Generate the rest of the data based on the problem subtype and calulate the solution
+ case Problem.Parameters.P_Subtype is
+ when V_FROM_G_KS =>
+ declare
+ MOLECULE_WEIGHT_RANGE: constant SS_Float := MOLECULE_WEIGHT_MAX - MOLECULE_WEIGHT_MIN;
+ SAMPLE_WEIGHT_RANGE: constant SS_Float := SAMPLE_WEIGHT_MAX - SAMPLE_WEIGHT_MIN;
+ G: SS_Float; -- Sample weight in grams
+ Ks: SS_Float; -- Solubility product
+ MW: SS_Float; -- Molar mass
+ begin
+ -- Generate sample weight
+ G := (SS_Float(Random(Gen => Float_RGen)) * SAMPLE_WEIGHT_RANGE) + SAMPLE_WEIGHT_MIN;
+ G := Round_To_Valid_Nums(G, DECIMALS);
+ Ks := Round_To_Valid_Nums(Generate_Solubility_Product, DECIMALS);
+ MW := (SS_Float(Random(Gen => Float_RGen)) * MOLECULE_WEIGHT_RANGE) + MOLECULE_WEIGHT_MIN;
+ MW := Round_To_Valid_Nums(MW, DECIMALS_MW);
+ Prob_Data := (Option => V_FROM_G_KS,
+ M => SS_Float(M), N => SS_Float(N),
+ V_G => G, V_Ks => Ks, V_MW => MW);
+ Answer_Num := Calculate_Sample_Volume(Prob_Data, Problem.Parameters.Ionic_Strength);
+ end;
+ when KS_FROM_G_V =>
+ declare
+ MOLECULE_WEIGHT_RANGE: constant SS_Float := MOLECULE_WEIGHT_MAX - MOLECULE_WEIGHT_MIN;
+ SAMPLE_WEIGHT_RANGE: constant SS_Float := SAMPLE_WEIGHT_MAX - SAMPLE_WEIGHT_MIN;
+ G: SS_Float; -- Sample weight in grams
+ MW: SS_Float; -- Molar mass
+ V: SS_Float; -- Sample volume in dm3
+ begin
+ G := (SS_Float(Random(Gen => Float_RGen)) * SAMPLE_WEIGHT_RANGE) + SAMPLE_WEIGHT_MIN;
+ G := Round_To_Valid_Nums(G, DECIMALS);
+ MW := (SS_Float(Random(Gen => Float_RGen)) * MOLECULE_WEIGHT_RANGE) + MOLECULE_WEIGHT_MIN;
+ MW := Round_To_Valid_Nums(MW, DECIMALS_MW);
+ V := Round_To_Valid_Nums(Generate_Sample_Volume, DECIMALS);
+ Prob_Data := (Option => KS_FROM_G_V,
+ M => SS_Float(M), N => SS_Float(N),
+ Ks_G => G, Ks_MW => MW, Ks_V => V);
+ Answer_Num := Calculate_Solubility_Product(Prob_Data, Problem.Parameters.Ionic_Strength);
+ end;
+ when C_FROM_KS_DIFFERENT_IONS =>
+ declare
+ EC: SS_Float; -- Concentration of the other electrolyte if mol/dm3 which does *not* share an ion with the target electrolyte
+ Ks: SS_Float; -- Solubility product
+ begin
+ EC := Round_To_Valid_Nums(Generate_Electrolyte_Concentration, DECIMALS);
+ Ks := Round_To_Valid_Nums(Generate_Solubility_Product, DECIMALS);
+ Prob_Data := (Option => C_FROM_KS_DIFFERENT_IONS,
+ M => SS_Float(M), N => SS_Float(N),
+ C_EC => EC, C_Ks => Ks);
+ Answer_Num := Calculate_Sat_Concentration_Different(Prob_Data, Problem.Parameters.Ionic_Strength);
+ end;
+ when C_FROM_KS_SHARED_ION =>
+ declare
+ EC: SS_Float; -- Concentration of the other electrolyte if mol/dm3 which *does* share an ion with the target electrolyte
+ Ks: SS_Float; -- Solubility product
+ begin
+ EC := Round_To_Valid_Nums(Generate_Electrolyte_Concentration, DECIMALS);
+ Ks := Round_To_Valid_Nums(Generate_Solubility_Product, DECIMALS);
+ Prob_Data := (Option => C_FROM_KS_SHARED_ION,
+ M => SS_Float(M), N => SS_Float(N),
+ C_EC => EC, C_Ks => Ks);
+ Answer_Num := Calculate_Sat_Concentration_Shared(Prob_Data, Problem.Parameters.Ionic_Strength);
+ end;
+ end case;
+
+ -- Set assignment data
+ Problem.Prob_Data := Prob_Data;
+ Problem.Answer_Num := Answer_Num;
+ end New_Problem;
+
+ function Set_Parameters(Problem: in out Solubility_Problem; Parameters: in Parameters_Info.Map) return Boolean is
+ use Parameters_Info;
+
+ Guard: Auto_Lock.LC;
+ begin
+ Auto_Lock.Init(Guard, Problem.Mutex'Unchecked_Access);
+ Guard.Lock;
+ -- Change ionic strength settings
+ if Parameters.Find(PARAMETER_IONIC_STRENGTH_KEY) /= Parameters_Info.No_Element then
+ Problem.Parameters.Ionic_Strength := True;
+ else
+ Problem.Parameters.Ionic_Strength := False;
+ end if;
+
+ -- Change problem subtype
+ if Parameters.Find(PARAMETER_PROBLEM_SUBTYPE_KEY) /= Parameters_Info.No_Element then
+ declare
+ PS_Str: constant String := Parameters.Element(PARAMETER_PROBLEM_SUBTYPE_KEY);
+ begin
+ if PS_Str = PROBLEM_SUBTYPE_V_FROM_G_KS then
+ Problem.Parameters.P_Subtype := V_FROM_G_KS;
+ elsif PS_Str = PROBLEM_SUBTYPE_KS_FROM_G_V then
+ Problem.Parameters.P_Subtype := KS_FROM_G_V;
+ elsif PS_Str = PROBLEM_SUBTYPE_C_FROM_KS_DIFFERENT_IONS then
+ Problem.Parameters.P_Subtype := C_FROM_KS_DIFFERENT_IONS;
+ elsif PS_Str = PROBLEM_SUBTYPE_C_FROM_KS_SHARED_ION then
+ Problem.Parameters.P_Subtype := C_FROM_KS_SHARED_ION;
+ else
+ raise Constraint_Error;
+ end if;
+ end;
+ else
+ -- This parameter must be always present
+ return False;
+ end if;
+
+ return True;
+ end Set_Parameters;
+
+ -- END: Inherited functions
+
+ -- BEGIN: Private functions
+
+ function Calculate_Activity_Coefficient(Charge: in SS_Float; Ionic_Strength: in SS_Float) return SS_Float is
+ package MEF is new Ada.Numerics.Generic_Elementary_Functions(SS_Float);
+ use MEF;
+
+ Z_Squared: constant SS_Float := Charge ** 2.0;
+ IS_Sqrt: constant SS_Float := Sqrt(Ionic_Strength);
+ Log_AC: SS_Float;
+ begin
+ Log_AC := (0.509 * Z_Squared * IS_Sqrt) / (1.0 + IS_Sqrt);
+ return 10.0 ** (-Log_AC);
+ end Calculate_Activity_Coefficient;
+
+ function Calculate_Ionic_Strength(Ions: in Ion_List) return SS_Float is
+ package MEF is new Ada.Numerics.Generic_Elementary_Functions(SS_Float);
+ use MEF;
+
+ I: SS_Float := 0.0;
+ begin
+ for Idx in Ions'Range loop
+ I := I + (Ions(Idx).Concentration * SS_Float((Ions(Idx).Charge ** 2)));
+ end loop;
+
+ return 0.5 * I;
+ end Calculate_Ionic_Strength;
+
+ function Calculate_Sample_Volume(Prob_Data: in Solubility_Problem_Data; Ionic_Strength: in Boolean) return SS_Float is
+ package SS_IO is new Ada.Text_IO.Float_IO(SS_Float);
+
+ C: SS_Float;
+ begin
+ C := Calculate_Sat_Concentration(Prob_Data.M, Prob_Data.N, Prob_Data.V_Ks, 1.0, 1.0);
+
+ if Ionic_Strength then
+ declare
+ I: SS_Float; -- Ionic strength in mol/dm3
+ GM: SS_Float; -- Activity coefficent for the cation
+ GN: SS_Float; -- Activity coefficient for the anion
+
+ Ions: Ion_List(1 .. 2);
+ begin
+ Ions(1) := (Concentration => C, Charge => Prob_Data.N);
+ Ions(2) := (Concentration => C, Charge => Prob_Data.M);
+ I := Calculate_Ionic_Strength(Ions);
+
+ GM := Calculate_Activity_Coefficient(Prob_Data.N, I);
+ GN := Calculate_Activity_Coefficient(Prob_Data.M, I);
+
+ Ada.Text_IO.Put_Line("IS, AC");
+ SS_IO.Put(I); Ada.Text_IO.New_Line;
+ SS_IO.Put(GM); Ada.Text_IO.New_Line;
+ SS_IO.Put(GN); Ada.Text_IO.New_Line;
+
+ C := Calculate_Sat_Concentration(Prob_Data.M, Prob_Data.N, Prob_Data.V_Ks, GM, GN);
+ end;
+ end if;
+
+ return Prob_Data.V_G / (Prob_Data.V_MW * C);
+ end Calculate_Sample_Volume;
+
+ function Calculate_Sat_Concentration(Cation_Count: in SS_Float; Anion_Count: in SS_Float; Ks: in SS_Float;
+ Cation_Gamma: in SS_Float; Anion_Gamma: in SS_Float) return SS_Float is
+ package MEF is new Ada.Numerics.Generic_Elementary_Functions(SS_Float);
+ use MEF;
+
+ MPN: constant SS_Float := Cation_Count + Anion_Count;
+ MM: constant SS_Float := Cation_Count ** Cation_Count;
+ NN: constant SS_Float := Anion_Count ** Anion_Count;
+ begin
+ return (Ks / (MM * (Cation_Gamma ** Cation_Count) * NN * (Anion_Gamma ** Anion_Count))) ** (1.0 / MPN);
+ end Calculate_Sat_Concentration;
+
+ function Calculate_Sat_Concentration_Different(Prob_Data: in Solubility_Problem_Data; Ionic_Strength: in Boolean) return SS_Float is
+ package MEF is new Ada.Numerics.Generic_Elementary_Functions(SS_Float);
+ use MEF;
+
+ GM: SS_Float;
+ GN: SS_Float;
+ C: SS_Float; -- Sample concentration
+ I: SS_Float; -- Ionic strength of the other electrolyte in mol/dm3
+ Ions_Other: Ion_List(1 .. 2);
+ begin
+ -- Calculate ionic strength of the other electrolyte
+ Ions_Other(1) := (Concentration => Prob_Data.C_EC, Charge => 1.0);
+ Ions_Other(2) := (Concentration => Prob_Data.C_EC, Charge => 1.0);
+ I := Calculate_Ionic_Strength(Ions_Other);
+ GM := Calculate_Activity_Coefficient(1.0, I);
+ GN := Calculate_Activity_Coefficient(1.0, I);
+ C := Calculate_Sat_Concentration(Prob_Data.M, Prob_Data.N, Prob_Data.C_Ks, GM, GN);
+
+ if Ionic_Strength then
+ declare
+ I_All: SS_Float; -- Ionic strength of all ions in mol/dm3
+ GM: SS_Float; -- Activity coefficent for the cation
+ GN: SS_Float; -- Activity coefficient for the anion
+
+ Ions_All: Ion_List(1 .. 4);
+ begin
+ Ions_All(1) := (Concentration => Prob_Data.C_EC, Charge => 1.0);
+ Ions_All(2) := (Concentration => Prob_Data.C_EC, Charge => 1.0);
+ Ions_All(3) := (Concentration => C, Charge => Prob_Data.N);
+ Ions_All(4) := (Concentration => C, Charge => Prob_Data.M);
+ I_All := Calculate_Ionic_Strength(Ions_All);
+
+ GM := Calculate_Activity_Coefficient(Prob_Data.M, I_All);
+ GN := Calculate_Activity_Coefficient(Prob_Data.N, I_All);
+
+ C := Calculate_Sat_Concentration(Prob_Data.M, Prob_Data.N, Prob_Data.C_Ks, GM, GN);
+ end;
+ end if;
+
+ return C;
+ end Calculate_Sat_Concentration_Different;
+
+ function Calculate_Sat_Concentration_Shared(Prob_Data: in Solubility_Problem_Data; Ionic_Strength: in Boolean) return SS_Float is
+ package MEF is new Ada.Numerics.Generic_Elementary_Functions(SS_Float);
+ use MEF;
+
+ GN: SS_Float := 1.0; -- Activity coefficient of the anion if the other electrolyte
+ EC_Pwrd: SS_Float;
+ R: SS_Float;
+ begin
+ EC_Pwrd := Prob_Data.C_EC ** Prob_Data.N;
+
+ if Ionic_Strength then
+ declare
+ I_EC: SS_Float; -- Ionic strength of the ions from the other electrolyte
+ Ions: Ion_List(1 .. 2);
+ begin
+ Ions(1) := (Concentration => Prob_Data.C_EC, Charge => 1.0);
+ Ions(2) := (Concentration => Prob_Data.C_EC, Charge => Prob_Data.M);
+ I_EC := Calculate_Ionic_Strength(Ions);
+
+ GN := Calculate_Activity_Coefficient(Prob_Data.M, I_EC);
+ end;
+ end if;
+
+ R := Prob_Data.C_Ks / (EC_Pwrd * (GN ** Prob_Data.N));
+
+ return (R ** (1.0 / Prob_Data.M)) / Prob_Data.M;
+ end Calculate_Sat_Concentration_Shared;
+
+ function Calculate_Solubility_Product(Prob_Data: in Solubility_Problem_Data; Ionic_Strength: in Boolean) return SS_Float is
+ package MEF is new Ada.Numerics.Generic_Elementary_Functions(SS_Float);
+ use MEF;
+
+ M: constant SS_Float := Prob_Data.M; -- Stochiometry of the cation
+ N: constant SS_Float := Prob_Data.N; -- Stochiometry of the anion
+ C: SS_Float; -- Concentration of the sample
+ GM: SS_Float := 1.0; -- Activity coefficent for the cation
+ GN: SS_Float := 1.0; -- Activity coefficient for the anion
+ begin
+ C := Prob_Data.Ks_G / (Prob_Data.Ks_MW * Prob_Data.Ks_V);
+
+ if Ionic_Strength then
+ declare
+ I: SS_Float; -- Ionic strength in mol/dm3
+
+ Ions: Ion_List(1 .. 2);
+ begin
+ Ions(1) := (Concentration => C, Charge => Prob_Data.N); -- Cation
+ Ions(2) := (Concentration => C, Charge => Prob_Data.M); -- Anion
+ I := Calculate_Ionic_Strength(Ions);
+
+ GM := Calculate_Activity_Coefficient(M, I); -- Cation
+ GN := Calculate_Activity_Coefficient(N, I); -- Anion
+ end;
+ end if;
+
+ return ((Prob_Data.M * C * GM) ** Prob_Data.M) * ((Prob_Data.N * C * GN) ** Prob_Data.N);
+ end Calculate_Solubility_Product;
+
+ function Generate_Electrolyte_Concentration return SS_Float is
+ package MEF is new Ada.Numerics.Generic_Elementary_Functions(SS_Float);
+ use Ada.Numerics.Float_Random;
+ use MEF;
+
+ CONC_RANGE: constant SS_Float := ELECTROLYTE_CONCENTRATION_LOG_MAX - ELECTROLYTE_CONCENTRATION_LOG_MIN;
+
+ Float_RGen: Generator;
+ R: SS_Float;
+ begin
+ Reset(Gen => Float_RGen);
+ R := (SS_Float(Random(Gen => Float_RGen)) * CONC_RANGE) + ELECTROLYTE_CONCENTRATION_LOG_MIN;
+
+ return 10.0 ** R;
+ end Generate_Electrolyte_Concentration;
+
+ function Generate_Sample_Volume return SS_Float is
+ package MEF is new Ada.Numerics.Generic_Elementary_Functions(SS_Float);
+ use Ada.Numerics.Float_Random;
+ use MEF;
+
+ VOL_RANGE: constant SS_Float := SAMPLE_VOLUME_LOG_MAX - SAMPLE_VOLUME_LOG_MIN;
+ Float_RGen: Generator;
+ R: SS_Float;
+ begin
+ Reset(Gen => Float_RGen);
+ R := (SS_Float(Random(Gen => Float_RGen)) * VOL_RANGE) + SAMPLE_VOLUME_LOG_MIN;
+
+ return 10.0 ** R;
+ end Generate_Sample_Volume;
+
+ function Generate_Solubility_Product return SS_Float is
+ package MEF is new Ada.Numerics.Generic_Elementary_Functions(SS_Float);
+ use Ada.Numerics.Float_Random;
+ use MEF;
+
+ PKS_RANGE: constant SS_Float := PKS_MAX - PKS_MIN;
+ Float_RGen: Generator;
+ R: SS_Float;
+ begin
+ Reset(Gen => Float_RGen);
+ R := (SS_Float(Random(Gen => Float_RGen)) * PKS_RANGE) + PKS_MIN;
+
+ return 10.0 ** (-R);
+ end Generate_Solubility_Product;
+
+ procedure Get_Correct_Answer_String(Message: in out UB_Text; P_Subtype: in Problem_Subtype; Answer: in SS_Float) is
+ package FH is new Formatting_Helpers(SS_Float);
+ use FH;
+
+ Ans_Int_Str: UB_Text;
+ Ans_Dec_Str: UB_Text;
+ Ans_Exp_Str: UB_Text;
+ begin
+ Split_Integer_Decimal_Exponent_Strs(Answer, DECIMALS, Ans_Int_Str, Ans_Dec_Str, Ans_Exp_Str);
+ Message := To_UB_Text("Špatná odpověď, hodnota správného výsledku je ");
+
+ case P_Subtype is
+ when V_FROM_G_KS =>
+ Append_UB_Text(Source => Message, New_Item => "V = ");
+ when KS_FROM_G_V =>
+ Append_UB_Text(Source => Message, New_Item => "K<span class=""subscript""s</span> = ");
+ when C_FROM_KS_DIFFERENT_IONS | C_FROM_KS_SHARED_ION =>
+ Append_UB_Text(Source => Message, New_Item => "c = ");
+ end case;
+
+ Append_UB_Text(Source => Message, New_Item => Ans_Int_Str); Append_UB_Text(Source => Message, New_Item => ","); Append_UB_Text(Source => Message, New_Item => Ans_Dec_Str);
+ Append_UB_Text(Source => Message, New_Item => " . 10<span class=""exponent"">"); Append_UB_Text(Source => Message, New_Item => Ans_Exp_Str); Append_UB_Text(Source => Message, New_Item => "</span> ");
+
+ case P_Subtype is
+ when V_FROM_G_KS =>
+ Append_UB_Text(Source => Message, New_Item => "dm<span class=""exponent"">3</span>");
+ when KS_FROM_G_V =>
+ null;
+ when C_FROM_KS_DIFFERENT_IONS | C_FROM_KS_SHARED_ION =>
+ Append_UB_Text(Source => Message, New_Item => "mol/dm<span class=""exponent"">3</span>");
+ end case;
+ end Get_Correct_Answer_String;
+
+
+end Solubility_Suite;
-with Ada.Text_IO;
-
package body Problem_Generator is
protected body Problem_Mutex is
entry Lock when Locked = False is
begin
Locked := True;
- end Lock;
-
- procedure Unlock is
+ end Lock;
+
+ entry Unlock when Locked is
begin
Locked := False;
end Unlock;
end Problem_Mutex;
+
+ package body Auto_Lock is
+ procedure Init(This: in out LC; Mutex: Problem_Mutex_All_Access; Auto_Unlock: in Boolean := True) is
+ begin
+ This.Auto_Unlock := Auto_Unlock;
+ This.Mutex := Mutex;
+ end;
+
+ procedure Lock(This: in out LC) is
+ begin
+ This.Mutex.Lock;
+ end Lock;
+
+ procedure Unlock(This: in out LC) is
+ begin
+ This.Mutex.Unlock;
+ end Unlock;
+
+ procedure Finalize(This: in out LC) is
+ begin
+ if This.Auto_Unlock then
+ This.Unlock;
+ end if;
+ end Finalize;
+ end Auto_Lock;
function Get_Problem(P_Type: in Problem_Type) return access Chem_Problem'Class is
begin
case P_Type is
when Acidobazic =>
return Acidobazic_Suite.Create;
+ when Solubility =>
+ return Solubility_Suite.Create;
end case;
end Get_Problem;
- procedure Lock_State(Problem: in out Chem_Problem) is
- begin
- Problem.Mutex.Lock;
- end Lock_State;
-
- procedure Unlock_State(Problem: in out Chem_Problem) is
- begin
- Problem.Mutex.Unlock;
- end Unlock_State;
-
package body Acidobazic_Suite is separate;
+ package body Solubility_Suite is separate;
end Problem_Generator;
with Global_Types;
with Problem_Generator_Syswides;
+with Ada.Finalization;
use Global_Types;
use Problem_Generator_Syswides;
protected type Problem_Mutex is
entry Lock;
- procedure Unlock;
+ entry Unlock;
private
Locked: Boolean := False;
end Problem_Mutex;
+ type Problem_Mutex_All_Access is access all Problem_Mutex;
type Chem_Problem is abstract tagged limited private;
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;
procedure New_Problem(Problem: in out Chem_Problem) is abstract;
- procedure Lock_State(Problem: in out Chem_Problem);
function Set_Parameters(Problem: in out Chem_Problem; Parameters: in Parameters_Info.Map) return Boolean is abstract;
- procedure Unlock_State(Problem: in out Chem_Problem);
function Get_Problem(P_Type: in Problem_Type) return access Chem_Problem'Class;
private
type Chem_Problem is abstract tagged limited
record
- Mutex: Problem_Mutex;
+ Mutex: aliased Problem_Mutex;
end record;
+ package Auto_Lock is
+ type LC is new Ada.Finalization.Controlled with private;
+ procedure Init(This: in out LC; Mutex: Problem_Mutex_All_Access; Auto_Unlock: in Boolean := True);
+ procedure Lock(This: in out LC);
+ procedure Unlock(This: in out LC);
+ private
+ type LC is new Ada.Finalization.Controlled with
+ record
+ Auto_Unlock: Boolean;
+ Mutex: Problem_Mutex_All_Access;
+ end record;
+ overriding procedure Finalize(This: in out LC);
+
+ Pragma Volatile(LC);
+ end Auto_Lock;
+
package Acidobazic_Suite is
use Problem_Generator_Syswides.Acidobazic_Suite;
end Acidobazic_Suite;
+ package Solubility_Suite is
+ use Problem_Generator_Syswides.Solubility_Suite;
+
+ type Solubility_Problem is new Problem_Generator.Chem_Problem with private;
+ -- Constructor
+ function Create return access Solubility_Problem;
+ -- 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;
+
+ private
+ type SS_Float is digits 18;
+ subtype Stochiometric_Count is Positive range 1 .. 5;
+
+ ELECTROLYTE_CONCENTRATION_LOG_MAX: constant SS_Float := 0.176;
+ ELECTROLYTE_CONCENTRATION_LOG_MIN: constant SS_Float := -4.0;
+ MOLECULE_WEIGHT_MAX: constant SS_Float := 450.0;
+ MOLECULE_WEIGHT_MIN: constant SS_Float := 45.0;
+ PKS_MAX: constant SS_Float := 54.0;
+ PKS_MIN: constant SS_Float := 10.0;
+ SAMPLE_VOLUME_LOG_MAX: constant SS_Float := 10.0;
+ SAMPLE_VOLUME_LOG_MIN: constant SS_Float := -0.3;
+ SAMPLE_WEIGHT_MAX: constant SS_Float := 1.5;
+ SAMPLE_WEIGHT_MIN: constant SS_Float := 0.1;
+ DECIMALS: constant SS_Float := 1.0E3;
+ DECIMALS_MW: constant SS_Float := 1.0E2;
+ PRECISION: constant SS_Float := 1.0E-2;
+
+ type Ion is
+ record
+ Concentration: SS_Float;
+ Charge: SS_Float;
+ end record;
+ type Ion_List is Array (Positive range <>) of Ion;
+
+ type Solubility_Parameters is
+ record
+ Ionic_Strength: Boolean; -- Correct for ionic strength in calculations
+ P_Subtype: Problem_Subtype;
+ end record;
+
+ type Solubility_Problem_Data(Option: Problem_Subtype := V_FROM_G_KS) is
+ record
+ M: SS_Float; -- Number of cations
+ N: SS_Float; -- Number of anions
+ case Option is
+ when V_FROM_G_KS =>
+ V_G: SS_Float; -- Sample mass in grams
+ V_Ks: SS_Float; -- Ks constant
+ V_MW: SS_Float; -- Molar mass of the sample
+ when KS_FROM_G_V =>
+ Ks_G: SS_Float; -- Sample mass in grams
+ Ks_MW: SS_Float; -- Molar mass of the sample
+ Ks_V: SS_Float; -- Sample volume in dm3
+ when C_FROM_KS_DIFFERENT_IONS | C_FROM_KS_SHARED_ION =>
+ C_EC: SS_Float; -- Concentration of the other electrolyte in the solution
+ C_Ks: SS_Float; -- Ks constant
+ end case;
+ end record;
+
+ type Solubility_Problem is new Problem_Generator.Chem_Problem with
+ record
+ Parameters: Solubility_Parameters; -- Parameters of the generator
+ Prob_Data: Solubility_Problem_Data; -- Data which make the assignment
+ Answer_Num: SS_Float; -- Answer to the problem
+ end record;
+
+ function Calculate_Activity_Coefficient(Charge: in SS_Float; Ionic_Strength: in SS_Float) return SS_Float;
+ function Calculate_Ionic_Strength(Ions: in Ion_List) return SS_Float;
+ function Calculate_Sat_Concentration(Cation_Count: in SS_Float; Anion_Count: in SS_Float; Ks: in SS_Float;
+ Cation_Gamma: in SS_Float; Anion_Gamma: in SS_Float) return SS_Float;
+ function Calculate_Sat_Concentration_Different(Prob_Data: in Solubility_Problem_Data; Ionic_Strength: in Boolean) return SS_Float;
+ function Calculate_Sat_Concentration_Shared(Prob_Data: in Solubility_Problem_Data; Ionic_Strength: in Boolean) return SS_Float;
+ function Calculate_Sample_Volume(Prob_Data: in Solubility_Problem_Data; Ionic_Strength: in Boolean) return SS_Float;
+ function Calculate_Solubility_Product(Prob_Data: in Solubility_Problem_Data; Ionic_Strength: in Boolean) return SS_Float;
+ function Generate_Electrolyte_Concentration return SS_Float;
+ function Generate_Sample_Volume return SS_Float;
+ function Generate_Solubility_Product return SS_Float;
+ procedure Get_Correct_Answer_String(Message: in out UB_Text; P_Subtype: in Problem_Subtype; Answer: in SS_Float);
+
+ end Solubility_Suite;
+
end Problem_Generator;
package Problem_Generator_Syswides is
type Answer_RetCode is (Invalid_Answer, No_Answer, Correct_Answer, Wrong_Answer, Malformed_Answer);
- type Problem_Type is (Acidobazic);
+ type Problem_Type is (Acidobazic, Solubility);
package Answer_Info is new Ada.Containers.Indefinite_Ordered_Maps(String, String);
package Assignment_Info is new Ada.Containers.Indefinite_Ordered_Maps(String, String);
package Parameters_Info is new Ada.Containers.Indefinite_Ordered_Maps(String, String);
ANSWER_KIND_BAD: constant String := "answer_kind_bad";
ANSWER_MESSAGE_KEY: constant String := "ANSWER_MESSAGE";
ANSWER_SECTION_KEY: constant String := "ANSWER_SECTION";
+ --
+ PARAMETER_TRUE: constant String := "True";
+ PARAMETER_FALSE: constant String := "False";
+ --
PROBLEM_TYPE_KEY: constant String := "PROBLEM_TYPE";
PROBLEM_TYPE_ACIDOBAZIC: constant String := Problem_Type'Image(Acidobazic);
+ PROBLEM_TYPE_SOLUBILITY: constant String := Problem_Type'Image(Solubility);
package Acidobazic_Suite is
-- What effect to ignore in calculations?
PARAMETER_NO_BOTH_SIMPLIFICATIONS_KEY: constant String := "PARAMETER_NO_BOTH_SIMPLIFICATIONS";
end Acidobazic_Suite;
+ package Solubility_Suite is
+ type Problem_Subtype is (V_FROM_G_KS, KS_FROM_G_V, C_FROM_KS_DIFFERENT_IONS, C_FROM_KS_SHARED_ION);
+
+ PROBLEM_NAME_READABLE: constant String := "Srážecí rovnováhy";
+ PROBLEM_SUBTYPE_KEY: constant String := "PROBLEM_SUBTYPE";
+ PROBLEM_SUBTYPE_V_FROM_G_KS: constant String := Problem_Subtype'Image(V_FROM_G_KS);
+ PROBLEM_SUBTYPE_KS_FROM_G_V: constant String := Problem_Subtype'Image(KS_FROM_G_V);
+ PROBLEM_SUBTYPE_C_FROM_KS_DIFFERENT_IONS: constant String := Problem_Subtype'Image(C_FROM_KS_DIFFERENT_IONS);
+ PROBLEM_SUBTYPE_C_FROM_KS_SHARED_ION: constant String := Problem_Subtype'Image(C_FROM_KS_SHARED_ION);
+ ANSWER_NUM_KEY: constant String := "ANSWER_NUM";
+ --
+ EC_INT_KEY: constant String := "EC_INT";
+ EC_DEC_KEY: constant String := "EC_DEC";
+ EC_EXP_KEY: constant String := "EC_EXP";
+ KS_INT_KEY: constant String := "KS_INT";
+ KS_DEC_KEY: constant String := "KS_DEC";
+ KS_EXP_KEY: constant String := "KS_EXP";
+ MOLAR_MASS_INT_KEY: constant String := "MOLAR_MASS_INT";
+ MOLAR_MASS_DEC_KEY: constant String := "MOLAR_MASS_DEC";
+ SAMPLE_VOLUME_INT_KEY: constant String := "SAMPLE_VOLUME_INT";
+ SAMPLE_VOLUME_DEC_KEY: constant String := "SAMPLE_VOLUME_DEC";
+ SAMPLE_VOLUME_EXP_KEY: constant String := "SAMPLE_VOLUME_EXP";
+ SAMPLE_WEIGHT_INT_KEY: constant String := "SAMPLE_WEIGHT_INT";
+ SAMPLE_WEIGHT_DEC_KEY: constant String := "SAMPLE_WEIGHT_DEC";
+ X_STOCHIO_KEY: constant String := "X_STOCHIO";
+ Z_STOCHIO_KEY: constant String := "Z_STOCHIO";
+ --
+ PARAMETER_IONIC_STRENGTH_KEY: constant String := "PARAMETER_IONIC_STRENGTH";
+ PARAMETER_PROBLEM_SUBTYPE_KEY: constant String := "PARAMETER_PROBLEM_SUBTYPE";
+
+ end Solubility_Suite;
+
end Problem_Generator_Syswides;
if Success = False then
return False;
end if;
+
-- Get assignment
Success := USD.Problem.Get_Assignment(Assignment);
if Success = False then
case P_Cat is
when Acidobazic =>
New_USD.Problem := Problem_Generator.Get_Problem(Problem_Generator_Syswides.Acidobazic);
+ when Solubility =>
+ New_USD.Problem := Problem_Generator.Get_Problem(Problem_Generator_Syswides.Solubility);
when others =>
return False;
end case;
use Global_Types;
package Problem_Manager is
- type Problem_Category is (Invalid, Acidobazic);
+ 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) return Boolean;
function Display_New_Assignment(UID: in Unique_ID; HTML: out HTML_Code) return Boolean;