mirror of https://github.com/acanas/swad-core.git
Version 22.114: May 19, 2023 Check if a rubric is recursive.
This commit is contained in:
parent
a32d962dc3
commit
0bbd73d188
|
@ -629,10 +629,11 @@ TODO: Emilce Barrera Mesa: Podr
|
|||
TODO: Emilce Barrera Mesa: Mis estudiantes presentan muchas dificultades a la hora de poner la foto porque la plataforma es muy exigente respecto al fondo de la imagen.
|
||||
|
||||
*/
|
||||
#define Log_PLATFORM_VERSION "SWAD 22.113 (2023-05-19)"
|
||||
#define Log_PLATFORM_VERSION "SWAD 22.114 (2023-05-19)"
|
||||
#define CSS_FILE "swad22.107.36.css"
|
||||
#define JS_FILE "swad22.49.js"
|
||||
/*
|
||||
Version 22.114: May 19, 2023 Check if a rubric is recursive. (336984 lines)
|
||||
Version 22.113: May 19, 2023 Check if a rubric is recursive. (336936 lines)
|
||||
Version 22.112: May 18, 2023 Code refactoring in options of selectors. (336794 lines)
|
||||
Version 22.111: May 17, 2023 A project can have more than one rubric in each category. (336691 lines)
|
||||
|
|
|
@ -4577,19 +4577,8 @@ static void Prj_ShowRubricsOfType (struct Prj_Projects *Projects,
|
|||
/* Change color for rubric criteria */
|
||||
The_ChangeRowColor ();
|
||||
|
||||
/* Check if rubric tree is correct */
|
||||
if (Rub_CheckRubricsTree (Rubric.RubCod,
|
||||
NULL)) // The stack has not yet been created
|
||||
/* Write criteria of this rubric */
|
||||
RubCri_ListCriteriaInProject (Projects,Rubric.RubCod,ICanFill);
|
||||
else
|
||||
{
|
||||
HTM_TR_Begin (NULL);
|
||||
HTM_TD_Begin ("colspan=\"8\" class=\"CT %s\"",The_GetColorRows ());
|
||||
Err_RecursiveRubric ();
|
||||
HTM_TD_End ();
|
||||
HTM_TR_End ();
|
||||
}
|
||||
/* Write criteria of this rubric */
|
||||
RubCri_ListCriteriaInProject (Projects,Rubric.RubCod,ICanFill);
|
||||
|
||||
/* Change color for next rubric */
|
||||
The_ChangeRowColor ();
|
||||
|
|
|
@ -345,6 +345,7 @@ void Rub_ShowOnlyOneRubric (struct Rub_Rubrics *Rubrics)
|
|||
{
|
||||
extern const char *Hlp_ASSESSMENT_Rubrics;
|
||||
extern const char *Txt_Rubric;
|
||||
struct Node *TOS = NULL;
|
||||
|
||||
/***** Begin box *****/
|
||||
Box_BoxBegin (NULL,Rubrics->Rubric.Title[0] ? Rubrics->Rubric.Title :
|
||||
|
@ -357,8 +358,7 @@ void Rub_ShowOnlyOneRubric (struct Rub_Rubrics *Rubrics)
|
|||
true); // Show only this rubric
|
||||
|
||||
/***** Check if rubric tree is correct *****/
|
||||
if (!Rub_CheckRubricsTree (Rubrics->Rubric.RubCod,
|
||||
NULL)) // The stack has not yet been created
|
||||
if (Rub_CheckIfRecursiveTree (Rubrics->Rubric.RubCod,&TOS))
|
||||
Err_RecursiveRubric ();
|
||||
|
||||
/***** Write criteria of this rubric *****/
|
||||
|
@ -788,6 +788,7 @@ void Rub_PutFormsOneRubric (struct Rub_Rubrics *Rubrics,
|
|||
[Rub_EXISTING_RUBRIC] = &Hlp_ASSESSMENT_Rubrics_edit_rubric,
|
||||
[Rub_NEW_RUBRIC ] = &Hlp_ASSESSMENT_Rubrics_new_rubric,
|
||||
};
|
||||
struct Node *TOS = NULL;
|
||||
|
||||
/***** Begin box *****/
|
||||
Box_BoxBegin (NULL,
|
||||
|
@ -800,8 +801,7 @@ void Rub_PutFormsOneRubric (struct Rub_Rubrics *Rubrics,
|
|||
Rub_PutFormEditionRubric (Rubrics,ExistingNewRubric);
|
||||
|
||||
/***** Check if rubric tree is correct *****/
|
||||
if (!Rub_CheckRubricsTree (Rubrics->Rubric.RubCod,
|
||||
NULL)) // The stack has not yet been created
|
||||
if (Rub_CheckIfRecursiveTree (Rubrics->Rubric.RubCod,&TOS))
|
||||
Err_RecursiveRubric ();
|
||||
|
||||
/***** Show list of criteria inside box *****/
|
||||
|
@ -1026,7 +1026,7 @@ static void Rub_UpdateRubric (struct Rub_Rubric *Rubric)
|
|||
/*****************************************************************************/
|
||||
/********** Recursive function to compute the score of a criterion ***********/
|
||||
/*****************************************************************************/
|
||||
// Return true if tree is ok, or false if infinite recursion
|
||||
// Return true if rubric tree is recursive
|
||||
/* Tree Stack
|
||||
_______ ______
|
||||
| Rub 1 | TOS (Top Of Stack)____\|___5__|
|
||||
|
@ -1061,63 +1061,47 @@ Handwritten Handwritten |_______| Handwritten
|
|||
/ | \
|
||||
Handwritten Handwritten Handwritten
|
||||
*/
|
||||
|
||||
bool Rub_CheckRubricsTree (long RubCod,struct Node *TOS)
|
||||
bool Rub_CheckIfRecursiveTree (long RubCod,struct Node **TOS)
|
||||
{
|
||||
struct Node *Node;
|
||||
bool TreeOk;
|
||||
bool RecursiveTree;
|
||||
MYSQL_RES *mysql_res;
|
||||
unsigned NumCriteria;
|
||||
unsigned NumCriterion;
|
||||
struct RubCri_Criterion Criterion;
|
||||
|
||||
/***** Check that rubric is not yet in the stack *****/
|
||||
for (Node = TOS, TreeOk = true;
|
||||
Node && TreeOk;
|
||||
Node = Node->Prev)
|
||||
if (Node->RubCod == RubCod)
|
||||
TreeOk = false;
|
||||
RecursiveTree = Rub_FindRubCodInStack (*TOS,RubCod);
|
||||
|
||||
if (TreeOk)
|
||||
if (!RecursiveTree)
|
||||
{
|
||||
/***** Push rubric code in stack *****/
|
||||
/* Save current top of stack */
|
||||
Node = TOS;
|
||||
|
||||
/* Create top of stack node */
|
||||
if ((TOS = malloc (sizeof (struct Node))) == NULL)
|
||||
Err_NotEnoughMemoryExit ();
|
||||
TOS->RubCod = RubCod;
|
||||
TOS->Prev = Node;
|
||||
Rub_PushRubCod (TOS,RubCod);
|
||||
|
||||
/* For each criteria in this rubric... */
|
||||
NumCriteria = Rub_DB_GetCriteria (&mysql_res,RubCod);
|
||||
for (NumCriterion = 0;
|
||||
NumCriterion < NumCriteria && TreeOk;
|
||||
NumCriterion < NumCriteria;
|
||||
NumCriterion++)
|
||||
{
|
||||
/* Get criterion data */
|
||||
RubCri_GetCriterionDataFromRow (mysql_res,&Criterion);
|
||||
|
||||
switch (Criterion.Link.Type)
|
||||
{
|
||||
case Rsc_RUBRIC:
|
||||
if (!Rub_CheckRubricsTree (Criterion.Link.Cod,TOS))
|
||||
TreeOk = false;
|
||||
if (Criterion.Link.Type == Rsc_RUBRIC)
|
||||
if (Rub_CheckIfRecursiveTree (Criterion.Link.Cod,TOS))
|
||||
{
|
||||
RecursiveTree = true;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/***** Free structure that stores the query result *****/
|
||||
DB_FreeMySQLResult (&mysql_res);
|
||||
|
||||
/***** Pop rubric code from stack *****/
|
||||
free (TOS);
|
||||
Rub_PopRubCod (TOS);
|
||||
}
|
||||
|
||||
return TreeOk;
|
||||
return RecursiveTree;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
|
|
@ -78,7 +78,7 @@ void Rub_PutFormsOneRubric (struct Rub_Rubrics *Rubrics,
|
|||
|
||||
void Rub_ReceiveFormRubric (void);
|
||||
|
||||
bool Rub_CheckRubricsTree (long RubCod,struct Node *TOS);
|
||||
bool Rub_CheckIfRecursiveTree (long RubCod,struct Node **TOS);
|
||||
|
||||
//-------------------------------- Figures ------------------------------------
|
||||
void Rub_GetAndShowRubricsStats (void);
|
||||
|
|
|
@ -109,6 +109,7 @@ static void RubCri_ListOneOrMoreCriteriaForEdition (struct Rub_Rubrics *Rubrics,
|
|||
unsigned NumCriteria,
|
||||
MYSQL_RES *mysql_res);
|
||||
static void RubCri_ListOneOrMoreCriteriaInProject (struct Prj_Projects *Projects,
|
||||
struct Node **TOS,
|
||||
bool ICanFill,
|
||||
unsigned NumCriteria,
|
||||
MYSQL_RES *mysql_res);
|
||||
|
@ -121,8 +122,8 @@ static void RubCri_WriteWeight (const struct RubCri_Criterion *Criterion);
|
|||
static void RubCri_WriteTotalLabel (unsigned ColSpan);
|
||||
static void RubCri_WriteTotalValue (double Total);
|
||||
|
||||
static double RubCri_ComputeScore (long PrjCod,
|
||||
const struct RubCri_Criterion *Criterion);
|
||||
static bool RubCri_ComputeRubricScore (long PrjCod,struct Node **TOS,long RubCod,
|
||||
double *RubricScore);
|
||||
|
||||
static void RubCri_PutTableHeadingForCriteria (RubCri_PutColumnForIcons_t PutColumnForIcons,
|
||||
RubCri_PutColumnsForScore_t PutColumnsForScore);
|
||||
|
@ -574,15 +575,25 @@ void RubCri_ListCriteriaInProject (struct Prj_Projects *Projects,long RubCod,
|
|||
{
|
||||
MYSQL_RES *mysql_res;
|
||||
unsigned NumCriteria;
|
||||
struct Node *TOS;
|
||||
|
||||
/***** Get data of rubric criteria from database *****/
|
||||
NumCriteria = Rub_DB_GetCriteria (&mysql_res,RubCod);
|
||||
|
||||
/***** Show table with rubric criteria *****/
|
||||
if (NumCriteria)
|
||||
RubCri_ListOneOrMoreCriteriaInProject (Projects,ICanFill,
|
||||
{
|
||||
/* Push rubric code in stack */
|
||||
Rub_PushRubCod (&TOS,RubCod);
|
||||
|
||||
/* List rubric criteria */
|
||||
RubCri_ListOneOrMoreCriteriaInProject (Projects,&TOS,ICanFill,
|
||||
NumCriteria,mysql_res);
|
||||
|
||||
/* Pop rubric code from stack */
|
||||
Rub_PopRubCod (&TOS);
|
||||
}
|
||||
|
||||
/***** Free structure that stores the query result *****/
|
||||
DB_FreeMySQLResult (&mysql_res);
|
||||
}
|
||||
|
@ -795,6 +806,7 @@ static void RubCri_ListOneOrMoreCriteriaForEdition (struct Rub_Rubrics *Rubrics,
|
|||
/*****************************************************************************/
|
||||
|
||||
static void RubCri_ListOneOrMoreCriteriaInProject (struct Prj_Projects *Projects,
|
||||
struct Node **TOS,
|
||||
bool ICanFill,
|
||||
unsigned NumCriteria,
|
||||
MYSQL_RES *mysql_res)
|
||||
|
@ -803,7 +815,7 @@ static void RubCri_ListOneOrMoreCriteriaInProject (struct Prj_Projects *Projects
|
|||
struct RubCri_Criterion Criterion;
|
||||
unsigned NumCriterion;
|
||||
char *Anchor;
|
||||
double Score;
|
||||
double CriterionScore;
|
||||
double WeightedScore;
|
||||
double SumOfWeights = 0.0;
|
||||
double SumOfScores = 0.0;
|
||||
|
@ -820,13 +832,6 @@ static void RubCri_ListOneOrMoreCriteriaInProject (struct Prj_Projects *Projects
|
|||
{
|
||||
/***** Get criterion data *****/
|
||||
RubCri_GetCriterionDataFromRow (mysql_res,&Criterion);
|
||||
SumOfWeights += Criterion.Weight;
|
||||
|
||||
/***** Compute score *****/
|
||||
Score = RubCri_ComputeScore (Projects->Prj.PrjCod,&Criterion);
|
||||
WeightedScore = Score * Criterion.Weight;
|
||||
SumOfScores += Score;
|
||||
WeightedSum += WeightedScore;
|
||||
|
||||
/***** Build anchor string *****/
|
||||
Frm_SetAnchorStr (Criterion.CriCod,&Anchor);
|
||||
|
@ -849,6 +854,7 @@ static void RubCri_ListOneOrMoreCriteriaInProject (struct Prj_Projects *Projects
|
|||
switch (Criterion.Link.Type)
|
||||
{
|
||||
case Rsc_NONE:
|
||||
CriterionScore = Prj_DB_GetScore (Projects->Prj.PrjCod,Criterion.CriCod);
|
||||
if (ICanFill)
|
||||
{
|
||||
Frm_BeginFormAnchor (ActChgPrjSco,Anchor);
|
||||
|
@ -858,7 +864,7 @@ static void RubCri_ListOneOrMoreCriteriaInProject (struct Prj_Projects *Projects
|
|||
Criterion.Values[RubCri_MIN],
|
||||
Criterion.Values[RubCri_MAX],
|
||||
RubCri_SCORE_STEP,
|
||||
Score,
|
||||
CriterionScore,
|
||||
HTM_SUBMIT_ON_CHANGE,false,
|
||||
" class=\"INPUT_FLOAT INPUT_%s\""
|
||||
" required=\"required\"",
|
||||
|
@ -866,10 +872,15 @@ static void RubCri_ListOneOrMoreCriteriaInProject (struct Prj_Projects *Projects
|
|||
Frm_EndForm ();
|
||||
}
|
||||
else
|
||||
HTM_Double2Decimals (Score);
|
||||
HTM_Double2Decimals (CriterionScore);
|
||||
break;
|
||||
case Rsc_RUBRIC:
|
||||
HTM_Double2Decimals (Score);
|
||||
if (RubCri_ComputeRubricScore (Projects->Prj.PrjCod,TOS,
|
||||
Criterion.Link.Cod,
|
||||
&CriterionScore))
|
||||
Err_RecursiveRubric ();
|
||||
else
|
||||
HTM_Double2Decimals (CriterionScore);
|
||||
break;
|
||||
default:
|
||||
Err_NoPermission ();
|
||||
|
@ -881,11 +892,17 @@ static void RubCri_ListOneOrMoreCriteriaInProject (struct Prj_Projects *Projects
|
|||
HTM_TD_Begin ("class=\"RT DAT_%s %s\"",
|
||||
The_GetSuffix (),
|
||||
The_GetColorRows ());
|
||||
WeightedScore = CriterionScore * Criterion.Weight;
|
||||
HTM_Double2Decimals (WeightedScore);
|
||||
HTM_TD_End ();
|
||||
|
||||
/***** End row *****/
|
||||
HTM_TR_End ();
|
||||
|
||||
/***** Update totals *****/
|
||||
SumOfWeights += Criterion.Weight;
|
||||
SumOfScores += CriterionScore;
|
||||
WeightedSum += WeightedScore;
|
||||
}
|
||||
|
||||
/***** Write total row *****/
|
||||
|
@ -989,50 +1006,119 @@ static void RubCri_WriteTotalValue (double Total)
|
|||
/*****************************************************************************/
|
||||
/********** Recursive function to compute the score of a criterion ***********/
|
||||
/*****************************************************************************/
|
||||
// Return true if rubric tree is recursive
|
||||
|
||||
static double RubCri_ComputeScore (long PrjCod,
|
||||
const struct RubCri_Criterion *Criterion)
|
||||
static bool RubCri_ComputeRubricScore (long PrjCod,struct Node **TOS,long RubCod,
|
||||
double *RubricScore)
|
||||
{
|
||||
bool RecursiveTree;
|
||||
MYSQL_RES *mysql_res;
|
||||
unsigned NumCriteria;
|
||||
unsigned NumCriterion;
|
||||
struct RubCri_Criterion CriterionChild;
|
||||
double ScoreChild;
|
||||
double Score;
|
||||
struct RubCri_Criterion Criterion;
|
||||
double CriterionScore;
|
||||
|
||||
switch (Criterion->Link.Type)
|
||||
/***** Initialize rubric score *****/
|
||||
*RubricScore = 0.0;
|
||||
|
||||
/***** Check that rubric is not yet in the stack *****/
|
||||
RecursiveTree = Rub_FindRubCodInStack (*TOS,RubCod);
|
||||
|
||||
if (!RecursiveTree)
|
||||
{
|
||||
case Rsc_NONE:
|
||||
Score = Prj_DB_GetScore (PrjCod,Criterion->CriCod);
|
||||
break;
|
||||
case Rsc_RUBRIC:
|
||||
Score = 0.0;
|
||||
/***** Push rubric code in stack *****/
|
||||
Rub_PushRubCod (TOS,RubCod);
|
||||
|
||||
/***** Get data of rubric criteria from database *****/
|
||||
NumCriteria = Rub_DB_GetCriteria (&mysql_res,Criterion->Link.Cod);
|
||||
NumCriteria = Rub_DB_GetCriteria (&mysql_res,RubCod);
|
||||
for (NumCriterion = 0;
|
||||
NumCriterion < NumCriteria;
|
||||
NumCriterion++)
|
||||
{
|
||||
/***** Get criterion data *****/
|
||||
RubCri_GetCriterionDataFromRow (mysql_res,&CriterionChild);
|
||||
RubCri_GetCriterionDataFromRow (mysql_res,&Criterion);
|
||||
|
||||
/* Get/compute criterion score */
|
||||
CriterionScore = 0.0;
|
||||
switch (Criterion.Link.Type)
|
||||
{
|
||||
case Rsc_NONE:
|
||||
CriterionScore = Prj_DB_GetScore (PrjCod,Criterion.CriCod);
|
||||
break;
|
||||
case Rsc_RUBRIC:
|
||||
if (RubCri_ComputeRubricScore (PrjCod,TOS,Criterion.Link.Cod,
|
||||
&CriterionScore))
|
||||
RecursiveTree = true;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
/***** Compute score of this criterion in the child rubric *****/
|
||||
ScoreChild = RubCri_ComputeScore (PrjCod,&CriterionChild);
|
||||
|
||||
/***** Update weighted sum *****/
|
||||
Score += CriterionChild.Weight * ScoreChild;
|
||||
*RubricScore += Criterion.Weight * CriterionScore; // Update weighted sum
|
||||
}
|
||||
|
||||
/***** Free structure that stores the query result *****/
|
||||
DB_FreeMySQLResult (&mysql_res);
|
||||
break;
|
||||
default:
|
||||
Score = 0.0;
|
||||
break;
|
||||
|
||||
/***** Pop rubric code from stack *****/
|
||||
Rub_PopRubCod (TOS);
|
||||
}
|
||||
|
||||
return Score;
|
||||
return RecursiveTree;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/********************** Push/pop rubric code in stack ************************/
|
||||
/*****************************************************************************/
|
||||
|
||||
void Rub_PushRubCod (struct Node **TOS,long RubCod)
|
||||
{
|
||||
struct Node *Node;
|
||||
|
||||
/***** Save current top of stack *****/
|
||||
Node = *TOS;
|
||||
|
||||
/***** Create top of stack node *****/
|
||||
if ((*TOS = malloc (sizeof (struct Node))) == NULL)
|
||||
Err_NotEnoughMemoryExit ();
|
||||
(*TOS)->RubCod = RubCod;
|
||||
(*TOS)->Prev = Node; // Link to previous top of stack
|
||||
}
|
||||
|
||||
void Rub_PopRubCod (struct Node **TOS)
|
||||
{
|
||||
struct Node *Node;
|
||||
|
||||
if (*TOS)
|
||||
{
|
||||
/***** Save current top of stack *****/
|
||||
Node = (*TOS)->Prev;
|
||||
|
||||
/***** Free current top of stack node *****/
|
||||
free (*TOS);
|
||||
|
||||
/***** Assign new top of stack *****/
|
||||
*TOS = Node;
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/************************ Find rubric code in stack **************************/
|
||||
/*****************************************************************************/
|
||||
// Return true if found
|
||||
|
||||
bool Rub_FindRubCodInStack (const struct Node *TOS,long RubCod)
|
||||
{
|
||||
while (TOS)
|
||||
{
|
||||
if (TOS->RubCod == RubCod)
|
||||
return true;
|
||||
|
||||
TOS = TOS->Prev;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
|
|
@ -47,6 +47,10 @@ void RubCri_ListCriteriaForEdition (struct Rub_Rubrics *Rubrics);
|
|||
void RubCri_ListCriteriaInProject (struct Prj_Projects *Projects,long RubCod,
|
||||
bool ICanFill);
|
||||
|
||||
void Rub_PushRubCod (struct Node **TOS,long RubCod);
|
||||
void Rub_PopRubCod (struct Node **TOS);
|
||||
bool Rub_FindRubCodInStack (const struct Node *TOS,long RubCod);
|
||||
|
||||
double RubCri_GetParScore (void);
|
||||
|
||||
void RubCri_GetCriterionDataFromRow (MYSQL_RES *mysql_res,
|
||||
|
|
Loading…
Reference in New Issue