Open romaintailhurat opened 1 year ago
Pour le rond-point, je ne sais pas s'il faut en faire une séquence ou un attribut de la boucle qu'il introduit. Je ne sais pas ce que l'on souhaite mettre exactement sur la page de rond-point à part :
Si l'on ne souhaite pas afficher davantage, le label de la boucle (qui n'est a priori pas utilisé) peut suffire comme label pour la page (ou du tableau des occurrences de boucle) et le reste peut s'en déduire...
Pour identifier la meilleure modélisation, il faudrait un exemple de ce que l'on souhaite obtenir avec l'orchestrateur. Le but est moins d'identifier ce à quoi cette page devra ressembler (l'UX design pourra la faire évoluer) que d'identifier quelles informations devront être fournies par Pogues, donc quelles informations devront figurer dans les modèles Pogues, DDI et Lunatic.
Pour avancer :
En terme d'usage du rond-point, deux éléments de configuration au moins :
"expressions": {
"unnecessary": {
"value": "AGE < 13",
"type": "VTL"
},
"complete": {
"value": "not(isnull(KNOWREC)) and not(isnull(SEXE)) and not(isnull(SOMETHING))",
"type": "VTL"
},
"partial": {
"value": "not(isnull(KNOWREC)) or not(isnull(SEXE)) or not(isnull(SOMETHING))",
"type": "VTL"
},
"label": {
"value": "\"Série de question pour \" || PRENOMS",
"type": "VTL"
}
}
la liste des composants pour chaque sous-questionnaire.
"components": [
{
"id": "radio",
"componentType": "Radio",
"mandatory": false,
"page": "4.1",
"label": {
"value": "\"Connaissez-vous le recensement de la population ?\"",
"type": "VTL|MD"
},
"conditionFilter": { "value": "true", "type": "VTL" },
"options": [
{ "value": "1", "label": { "value": "\"oui\"", "type": "VTL|MD" } },
{ "value": "2", "label": { "value": "\"non\"", "type": "VTL|MD" } }
],
"response": { "name": "KNOWREC" }
},
{
"id": "jsygk7m7",
"componentType": "Subsequence",
"page": "4.2",
"label": {
"value": "\"Deuxième page de questions pour \"|| PRENOMS",
"type": "VTL|MD"
},
"conditionFilter": { "value": "true", "type": "VTL" }
},
...
]
A priori, on inclut uniquement des sous-séquences et des questions comme enfants du rond-point.
Asking @renaud23 if subsequence is the higher component level or not.
UPDATE : same constraint as for paged loop ("boucles paginées"), so any component seems good.
De ce que je vois au niveau du modèle Lunatic présent en lien, on est assez près de la boucle liée :
Il manque :
Dans le cas d'une boucle liée avec filtre sur les occurrences, on était parti sur une Loop référençant un filtre, référençant lui-même une séquence -> ce sont les 3 éléments que l'on peut enrichir pour avoir les informations manquantes (mais il faudrait pour Eno indiquer dans la Loop qu'il s'agit d'un rond-point)
Would the following be a good design ?
<d:Loop>
<r:Agency>fr.insee</r:Agency>
<r:ID>lmomdlun</r:ID>
<r:Version>1</r:Version>
<d:ConstructName>
<r:String xml:lang="fr-FR">B2</r:String>
</d:ConstructName>
<d:ControlConstructReference>
<r:Agency>fr.insee</r:Agency>
<r:ID>lmommfe7</r:ID>
<r:Version>1</r:Version>
<r:TypeOfObject>Sequence</r:TypeOfObject>
</d:ControlConstructReference>
<r:UserAttributePair>
<r:AttributeKey>Navigation</r:AttributeKey>
<r:AttributeValue>Roundabout</r:AttributeValue>
</r:UserAttributePair>
<r:UserAttributePair>
<r:AttributeKey>RoundaboutConfiguration</r:AttributeKey>
<r:AttributeValue><![CDATA[
"expressions": {
"unnecessary": {
"value": "AGE < 13",
"type": "VTL"
},
"complete": {
"value": "not(isnull(KNOWREC)) and not(isnull(SEXE)) and not(isnull(SOMETHING))",
"type": "VTL"
},
"partial": {
"value": "not(isnull(KNOWREC)) or not(isnull(SEXE)) or not(isnull(SOMETHING))",
"type": "VTL"
},
"label": {
"value": "\"Série de question pour \" || PRENOMS",
"type": "VTL"
}
}
]]></r:AttributeValue>
</r:UserAttributePair>
</d:Loop>
As suggested by @BulotF we are reusing here the DDI design for linked loops, adding two <r:UserAttributePair>
:
Asking for validation @BulotF and @laurentC35 🤗
There are sevreal problem with the second element :
VTL code is written "as is" as it is an example provided by a Lunatic roundabout developer.
So if i understand correctly, the configuration part of the Roundabout would be produced by scanning part of the DDI? Or all?
Alternative design : A round-about is a mono-paged loop or a QuestionGrid with a roster. Still with something indicating that that component is a roundabout.
That component may be inside a Sequence with label "Libellé du rondpoint".
If it is a Loop, its content should be a unique ControlConstruct, but I don't know which kind of element inside : a StatementItem ?
If it is a QuestionGrid, probably a noDataByDefinition in each cell with a label containing the complete and partial formulas. Maybe with several columns if there are several linked loops.
It seems to me that if really makes sense to use a Loop as the base construct for the Roundabout 😃
The main idea is to design the roundabout as a Loop that contains a Sequence which itself contains a StatementItem and three ComputationItems, one for each Roundabout parameter:
Loop
Sequence
StatementItem
ComputationItem[unnecessary]
ComputationItem[partial]
ComputationItem[complete]
<d:Loop>
<r:Agency>fr.insee</r:Agency>
<r:ID>lnbp643q</r:ID>
<r:Version>1</r:Version>
<r:UserAttributePair>
<r:AttributeKey>ROUNDABOUT_OBJECT</r:AttributeKey>
<r:AttributeValue>ROUNDABOUT_LOOP</r:AttributeValue>
</r:UserAttributePair>
<d:ConstructName>
<r:String xml:lang="fr-FR">B_RONDPOINT</r:String>
</d:ConstructName>
<d:ControlConstructReference>
<r:Agency>fr.insee</r:Agency>
<r:ID>lnbpayrw</r:ID>
<r:Version>1</r:Version>
<r:TypeOfObject>Sequence</r:TypeOfObject>
</d:ControlConstructReference>
</d:Loop>
<d:Sequence>
<r:Agency>fr.insee</r:Agency>
<r:ID>lnbpayrw</r:ID>
<r:Version>1</r:Version>
<d:ConstructName>
<r:String xml:lang="fr-FR">RONDPOINT</r:String>
</d:ConstructName>
<d:ControlConstructReference>[StatementItem]</d:ControlConstructReference>
<d:ControlConstructReference>[ComputationItem]</d:ControlConstructReference>
<d:ControlConstructReference>[ComputationItem]</d:ControlConstructReference>
<d:ControlConstructReference>[ComputationItem]</d:ControlConstructReference>
</d:Sequence>
<d:StatementItem>
<r:Agency>fr.insee</r:Agency>
<r:ID>LABEL_ET_BOUTON</r:ID>
<r:Version>1</r:Version>
<r:UserAttributePair>
<r:AttributeKey>ROUNDABOUT_OBJECT</r:AttributeKey>
<r:AttributeValue>LABEL_AND_BUTTON</r:AttributeValue>
</r:UserAttributePair>
<r:Label>
<r:Content>Le libellé au-dessus du bouton</r:Content>
</r:Label>
</d:StatementItem>
In order to describe completion parameters we use <d:ComputationItem>
. For example here, for the unnecessary
Lunatic Parameter:
<d:ComputationItem>
<r:Agency>fr.insee</r:Agency>
<r:ID>lahvkp0z-CI-0</r:ID>
<r:Version>1</r:Version>
<d:ConstructName>
<r:String xml:lang="fr-FR">ROUNDABOUT_UNNECESSARY</r:String>
</d:ConstructName>
<r:Description>
<r:Content xml:lang="fr-FR">Rond-point - Les itérations à masquer.</r:Content>
</r:Description>
<d:InterviewerInstructionReference>
<r:Agency>fr.insee</r:Agency>
<r:ID>lahvkp0z-CI-0-II-0</r:ID>
<r:Version>1</r:Version>
<r:TypeOfObject>Instruction</r:TypeOfObject>
</d:InterviewerInstructionReference>
<d:TypeOfComputationItem controlledVocabularyID="INSEE-LUNATIC">roundabout-unnecessary</d:TypeOfComputationItem>
<r:CommandCode>
<r:Command>
<r:ProgramLanguage>vtl</r:ProgramLanguage>
<r:CommandContent>AGE ;< 13</r:CommandContent>
</r:Command>
</r:CommandCode>
</d:ComputationItem>
1) To specify the type of loop, I would prefer :
<r:UserAttributePair>
<r:AttributeKey>loopType</r:AttributeKey>
<r:AttributeValue>roundabout</r:AttributeValue>
</r:UserAttributePair>
2) For the StatementItem :
<r:UserAttributePair>
<r:AttributeKey>button</r:AttributeKey>
<r:AttributeValue>roundabout-link</r:AttributeValue>
</r:UserAttributePair>
3) The controlledVocabulary for TypeOfComputationItem would be : roundabout-unnecessary roundabout-complete roundabout-partial
4) ComputationItem have no InterviewerInstructionReference
4) For at least dynamic arrays (QuestionGrid with 2 dimensions for which the first dimension is a roster and the second one is a codeList), I'd use a Variable to indicate where the buttons should be displayed. It would be mandatory when there is at least 2 buttons, to assign correctly the computation items to each. Alternative in the component that displays the link, I'd like to have a reference (basedOn ?) to the 3 parameters ComputationItem...
ComputationItem have no InterviewerInstructionReference
Yes, i just forgot to delete this part 😉
Maybe it could be important to fill a controlled vocabulary for attributevaluekeys too I don't see how the choice is made between the partial label and complet label , when all the fields are completed I change my previous comment. two possibilities. the basedOnObject cardinality is 0 1. it can contain several basedOnReferences we could type with RserAttributPair. Why not using inparameter instead to get computation item value ?
I thought that controlled vocabulary's AttributeKeys was specified in the DDI profile (and only in it)
InParameter is a better alternative. Nice.
I agree in the DDI profile it's fine ! not the same status as a value
So it seems that we have an agreement on the design, i propose to add that to a proper and versionned document.
The implementation can start.
I wrapped up our comments in this document 👇
I don't think we need an alternative QuestionGrid based design with this. But:
a suggestion of identifying the used suggester also by a version number , if it evolves over time
A last review by @BulotF is in progress.
Reprise des réflexions sur le rond-point... J'écris en français pour permettre aux participations à la discussion de ne pas alourdir la compréhension de mes explications avec la traduction.
Résumé de ma vision du rond-point du point de vue métier : Lorsqu'on est sur un questionnaire sans rond-point, l'avancement dans le questionnaire ne peut être que linéaire : Au niveau des boucles, on répond aux occurrences dans l'ordre et on attend d'en finir une avant d'entamer la suivante.
Avec le rond-point, on se donne la possibilité de basculer d'une occurrence à une autre, dans un ordre déterminé par le(s) répondant(s) et sans forcément avoir terminé une occurrence avant de basculer à une autre.
Pour faire un parallèle : le questionnaire global est le processus principal. On le met en pause pour lancer plusieurs petits processus parallèles. On le reprend lorsque tous ces petits processus sont terminés.
Pour avoir une expérience utilisateur la plus claire possible, on a besoin des éléments suivants :
Le rond-point peut être vu comme un conteneur de boucle(s), plutôt que comme un type de boucle particulier. Le définir comme une séquence de typeOfSequence = "roundabout" offre plusieurs possibilités intéressantes :
Par ailleurs, je pense que le filtre d'occurrence que l'on indiquait sous la forme d'un ComputationItem "unnecessary" mérite de redevenir un filtre (ce qu'il est déjà avec les boucles hors rond-point). Je conserverais les ComputationItem "complete" et "partial" tels quels.
Au niveau StatementItem, outre le libellé pour désigner l'occurrence, j'utiliserais des StatementItem pour les boutons "Ajouter une occurrence" (actuellement, on utiliser le label de la Loop et c'est assez moyen) et "supprimer une occurrence". Si on choisit de les indiquer au sein de la Sequence qui dépend directement de la Loop, on peut même choisir d'en faire des d:Instruction et donc de leur donner des InstructionName correspondant à leur statut : Loop.InstanceLabel ; Loop.Add ; Loop.Remove
Si on souhaite modéliser l'exemple suivant :
N.B. Modélisation en mode déréférencé (je remplace la référence par l'objet) qui n'indiquerait que les éléments utiles...
<d:Sequence>
<r:Label>Liens vers les différentes personnes du ménage :</r:Label>
<d:Instruction>
<d:InstructionName>help</d:InstructionName>
<d:InstructionText>Cette page permet d’accéder aux questionnaires des différentes personnes du ménage.
Vous pouvez revenir à cette page en appuyant sur le bouton « revenir au rond-point »</d:InstructionText>
</d:Instruction>
<d:TypeOfSequence controlledVocabularyID="INSEE-TOS-CL-1">roundabout</d:TypeOfSequence>
<d:Loop>
<r:Label>Questions individuelles</r:Label>
<d:Sequence>
<d:Instruction>
<d:InstructionName>Loop.InstanceLabel</d:InstructionName>
<d:InstructionText>¤PRENOM¤</d:InstructionText>
</d:Instruction>
<d:Instruction>
<d:InstructionName>Loop.Add</d:InstructionName>
<d:InstructionText>Ajouter un individu</d:InstructionText>
</d:Instruction>
<d:Instruction>
<d:InstructionName>Loop.Remove</d:InstructionName>
<d:InstructionText>Supprimer un individu</d:InstructionText>
</d:Instruction>
<d:TypeOfSequence controlledVocabularyID="INSEE-TOS-CL-1">loopContent</d:TypeOfSequence>
<d:ComputationItem>
<d:TypeOfComputationItem controlledVocabularyID="INSEE-TOCI-CL-1">loop.complete</d:TypeOfComputationItem>
<r:CommandCode>Tout est renseigné</r:CommandCode>
</d:ComputationItem>
<d:ComputationItem>
<d:TypeOfComputationItem controlledVocabularyID="INSEE-TOCI-CL-1">loop.partial</d:TypeOfComputationItem>
<r:CommandCode>Au moins une variable est renseignés</r:CommandCode>
</d:ComputationItem>
... Contenu de la boucle questions individuelles ...
</d:Sequence>
</d:Loop>
<d:Loop>
<r:Label>Questions sur les majeurs</r:Label>
<d:IfThenElse>
<d:IfCondition>AGE >= 18</d:IfCondition>
<d:Sequence>
<d:TypeOfSequence controlledVocabularyID="INSEE-TOS-CL-1">filteredLoopContent</d:TypeOfSequence>
<d:ComputationItem>
<d:TypeOfComputationItem controlledVocabularyID="INSEE-TOCI-CL-1">loop.complete</d:TypeOfComputationItem>
<r:CommandCode>Tout est renseigné</r:CommandCode>
</d:ComputationItem>
<d:ComputationItem>
<d:TypeOfComputationItem controlledVocabularyID="INSEE-TOCI-CL-1">loop.partial</d:TypeOfComputationItem>
<r:CommandCode>Au moins une variable est renseignés</r:CommandCode>
</d:ComputationItem>
... Contenu de la boucle questions sur les majeurs ...
</d:Sequence>
</d:IfThenElse>
</d:Loop>
<d:Loop>
<r:Label>Cœur de l’enquête</r:Label>
<d:IfThenElse>
<d:IfCondition>Indiv = Kish</d:IfCondition>
<d:Sequence>
<d:TypeOfSequence controlledVocabularyID="INSEE-TOS-CL-1">filteredLoopContent</d:TypeOfSequence>
<d:ComputationItem>
<d:TypeOfComputationItem controlledVocabularyID="INSEE-TOCI-CL-1">loop.complete</d:TypeOfComputationItem>
<r:CommandCode>Tout est renseigné</r:CommandCode>
</d:ComputationItem>
<d:ComputationItem>
<d:TypeOfComputationItem controlledVocabularyID="INSEE-TOCI-CL-1">loop.partial</d:TypeOfComputationItem>
<r:CommandCode>Au moins une variable est renseignés</r:CommandCode>
</d:ComputationItem>
... Contenu de la boucle cœur de l’enquête ...
</d:Sequence>
</d:IfThenElse>
</d:Loop>
</d:Sequence>
Eléments de vocabulaire qui n'existent pas encore, mais auraient de l'intérêt pour les séquences : ajouter des valeurs à typeOfSequence : filterContent ; loopContent et filteredLoopContent (contenu d'une boucle dont les occurrences sont filtrées)
Cette description a l'avantage de ne pas utiliser r:UserAttributePair. L'enrichissement de la sémantique est porté par les modalités de TypeOfSequence ; InstructionName ; TypeOfComputationItem
à documenter ailleurs qu'ici Faire une issue Pogues-Model + Eno
Modification des besoins Lunatic :
quelques remarques -je suis d'accord sur le fait que dans le DDI il n'est pas nécessaire de mettre tous les objets techniques pour gérer l'affichage, l'essentiel c'est d'avoir l'information logique/métier de la passation -je suis ok sur la présentation du ddi de l'exemple du 13 mars, il faudra voir avec les imports dans Colectica que les instructions des séquences sont bien importées (actuellement non décrits dans Designer), on est plutot sur interviewerinstruction il me semble -sur les exemples ce serait pratique de mentionner la version de DDI utilisé, ddi3_2 ou ddi3_3 et par la suite ddi3_4
This could be modelled as a DDI Sequence with a TypeOfSequence with value "roundabout".