tricc-oo 1.0.1__py3-none-any.whl → 1.4.15__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (66) hide show
  1. tests/build.py +213 -0
  2. tests/test_cql.py +197 -0
  3. tests/to_ocl.py +51 -0
  4. {tricc → tricc_oo}/__init__.py +3 -1
  5. tricc_oo/converters/codesystem_to_ocl.py +169 -0
  6. tricc_oo/converters/cql/cqlLexer.py +822 -0
  7. tricc_oo/converters/cql/cqlListener.py +1632 -0
  8. tricc_oo/converters/cql/cqlParser.py +11204 -0
  9. tricc_oo/converters/cql/cqlVisitor.py +913 -0
  10. tricc_oo/converters/cql_to_operation.py +402 -0
  11. tricc_oo/converters/datadictionnary.py +115 -0
  12. tricc_oo/converters/drawio_type_map.py +222 -0
  13. tricc_oo/converters/tricc_to_xls_form.py +61 -0
  14. tricc_oo/converters/utils.py +65 -0
  15. tricc_oo/converters/xml_to_tricc.py +1003 -0
  16. tricc_oo/models/__init__.py +4 -0
  17. tricc_oo/models/base.py +732 -0
  18. tricc_oo/models/calculate.py +216 -0
  19. tricc_oo/models/ocl.py +281 -0
  20. tricc_oo/models/ordered_set.py +125 -0
  21. tricc_oo/models/tricc.py +418 -0
  22. tricc_oo/parsers/xml.py +138 -0
  23. tricc_oo/serializers/__init__.py +0 -0
  24. tricc_oo/serializers/xls_form.py +745 -0
  25. tricc_oo/strategies/__init__.py +0 -0
  26. tricc_oo/strategies/input/__init__.py +0 -0
  27. tricc_oo/strategies/input/base_input_strategy.py +111 -0
  28. tricc_oo/strategies/input/drawio.py +317 -0
  29. tricc_oo/strategies/output/base_output_strategy.py +148 -0
  30. tricc_oo/strategies/output/spice.py +365 -0
  31. tricc_oo/strategies/output/xls_form.py +697 -0
  32. tricc_oo/strategies/output/xlsform_cdss.py +189 -0
  33. tricc_oo/strategies/output/xlsform_cht.py +200 -0
  34. tricc_oo/strategies/output/xlsform_cht_hf.py +334 -0
  35. tricc_oo/visitors/__init__.py +0 -0
  36. tricc_oo/visitors/tricc.py +2198 -0
  37. tricc_oo/visitors/utils.py +17 -0
  38. tricc_oo/visitors/xform_pd.py +264 -0
  39. tricc_oo-1.4.15.dist-info/METADATA +219 -0
  40. tricc_oo-1.4.15.dist-info/RECORD +46 -0
  41. {tricc_oo-1.0.1.dist-info → tricc_oo-1.4.15.dist-info}/WHEEL +1 -1
  42. tricc_oo-1.4.15.dist-info/top_level.txt +2 -0
  43. tricc/converters/mc_to_tricc.py +0 -542
  44. tricc/converters/tricc_to_xls_form.py +0 -553
  45. tricc/converters/utils.py +0 -44
  46. tricc/converters/xml_to_tricc.py +0 -740
  47. tricc/models/tricc.py +0 -1093
  48. tricc/parsers/xml.py +0 -81
  49. tricc/serializers/xls_form.py +0 -364
  50. tricc/strategies/input/base_input_strategy.py +0 -80
  51. tricc/strategies/input/drawio.py +0 -246
  52. tricc/strategies/input/medalcreator.py +0 -168
  53. tricc/strategies/output/base_output_strategy.py +0 -92
  54. tricc/strategies/output/xls_form.py +0 -194
  55. tricc/strategies/output/xlsform_cdss.py +0 -46
  56. tricc/strategies/output/xlsform_cht.py +0 -106
  57. tricc/visitors/tricc.py +0 -375
  58. tricc_oo-1.0.1.dist-info/LICENSE +0 -78
  59. tricc_oo-1.0.1.dist-info/METADATA +0 -229
  60. tricc_oo-1.0.1.dist-info/RECORD +0 -26
  61. tricc_oo-1.0.1.dist-info/top_level.txt +0 -2
  62. venv/bin/vba_extract.py +0 -78
  63. {tricc → tricc_oo}/converters/__init__.py +0 -0
  64. {tricc → tricc_oo}/models/lang.py +0 -0
  65. {tricc/serializers → tricc_oo/parsers}/__init__.py +0 -0
  66. {tricc → tricc_oo}/serializers/planuml.py +0 -0
@@ -0,0 +1,745 @@
1
+ import logging
2
+ import hashlib
3
+
4
+ # from bs4 import BeautifulSoup
5
+ from tricc_oo.converters.tricc_to_xls_form import (
6
+ negate_term,
7
+ VERSION_SEPARATOR,
8
+ INSTANCE_SEPARATOR,
9
+ get_export_name,
10
+ )
11
+ from tricc_oo.converters.utils import clean_name, remove_html
12
+ from tricc_oo.models.lang import SingletonLangClass
13
+ from tricc_oo.models import *
14
+ import re
15
+ from tricc_oo.visitors.tricc import (
16
+ is_ready_to_process,
17
+ process_reference,
18
+ add_calculate,
19
+ TRICC_TRUE_VALUE,
20
+ TRICC_FALSE_VALUE,
21
+ )
22
+
23
+ logger = logging.getLogger("default")
24
+
25
+ langs = SingletonLangClass()
26
+ TRICC_CALC_EXPRESSION = "${{{0}}}>0"
27
+
28
+ BOOLEAN_MAP = {
29
+ str(TRICC_TRUE_VALUE): 1,
30
+ str(TRICC_FALSE_VALUE): 0,
31
+ }
32
+
33
+
34
+ def start_group(
35
+ strategy, cur_group, groups, df_survey, df_calculate, relevance=False, **kwargs
36
+ ):
37
+ name = get_export_name(cur_group)
38
+
39
+ if name in groups:
40
+ groups[name] += 1
41
+ name = name + "_" + str(groups[name])
42
+
43
+ else:
44
+ groups[name] = 0
45
+ is_activity = isinstance(cur_group, TriccNodeActivity)
46
+ relevance = (
47
+ relevance and cur_group.relevance is not None and cur_group.relevance != ""
48
+ )
49
+
50
+ group_calc_required = (
51
+ False and relevance and not is_activity and len(relevance) > 100
52
+ )
53
+
54
+ relevance_expression = cur_group.relevance
55
+ if not relevance:
56
+ relevance_expression = ""
57
+ elif isinstance(relevance_expression, TriccOperation):
58
+ relevance_expression = strategy.get_tricc_operation_expression(
59
+ relevance_expression
60
+ )
61
+ elif isinstance(relevance_expression, TriccStatic):
62
+ relevance_expression = str(relevance_expression.value)
63
+
64
+ # elif is_activity:
65
+ # relevance_expression = TRICC_CALC_EXPRESSION.format(get_export_name(cur_group.root))
66
+ elif group_calc_required:
67
+ relevance_expression = TRICC_CALC_EXPRESSION.format("gcalc_" + name)
68
+
69
+ ## group
70
+ values = []
71
+ for column in SURVEY_MAP:
72
+ if column == "type":
73
+ values.append("begin group")
74
+ elif column == "name":
75
+ values.append(name)
76
+ elif column == "appearance":
77
+ values.append("field-list")
78
+ elif column == "relevance":
79
+ if relevance_expression is True:
80
+ values.append("")
81
+ else:
82
+ values.append(relevance_expression)
83
+
84
+ else:
85
+ values.append(get_xfrom_trad(strategy, cur_group, column, SURVEY_MAP))
86
+ df_survey.loc[len(df_survey)] = values
87
+
88
+ ### calc
89
+ if (
90
+ group_calc_required
91
+ and len(df_calculate[df_calculate["name"] == "gcalc_" + name]) == 0
92
+ ):
93
+ calc_values = []
94
+ for column in SURVEY_MAP:
95
+ if column == "type":
96
+ calc_values.append("calculate")
97
+ elif column == "name":
98
+ value = "gcalc_" + name
99
+ calc_values.append(value)
100
+ elif column == "calculation":
101
+ calc_values.append(
102
+ get_attr_if_exists(strategy, cur_group, "relevance", SURVEY_MAP)
103
+ )
104
+ elif column == "relevance":
105
+ calc_values.append("")
106
+ else:
107
+ calc_values.append(
108
+ get_xfrom_trad(strategy, cur_group, column, SURVEY_MAP)
109
+ )
110
+
111
+ df_calculate.loc[len(df_calculate)] = calc_values
112
+
113
+
114
+ # def add_background_color(input_string, color):
115
+ # """
116
+ # Adds a background color to an HTML string or wraps a plain string in a <p> tag with the background color.
117
+
118
+ # Args:
119
+ # input_string (str): The input string, either plain text or HTML.
120
+ # color (str): The background color to apply (e.g., 'yellow', '#ffcc00').
121
+
122
+ # Returns:
123
+ # str: The resulting HTML string with the background color applied.
124
+ # """
125
+ # if not input_string:
126
+ # return input_string
127
+ # # Parse the input string using BeautifulSoup
128
+ # soup = BeautifulSoup(input_string, 'html.parser')
129
+
130
+ # # Check if the input is already an HTML structure
131
+ # if soup.find(): # If there are any tags in the input
132
+ # # Add the background color to the root element's style attribute
133
+ # root = soup.find() # Get the first (root) element
134
+ # existing_style = root.get('style', '')
135
+ # root['style'] = f"{existing_style} background-color: {color};".strip()
136
+ # else:
137
+ # # Wrap the plain text in a <p> tag with the background color
138
+ # soup = BeautifulSoup(f'<p style="background-color: {color};">{input_string}</p>', 'html.parser')
139
+
140
+ # return str(soup)
141
+
142
+
143
+ def end_group(strategy, cur_group, groups, df_survey, **kwargs):
144
+ values = []
145
+ for column in SURVEY_MAP:
146
+ if column == "type":
147
+ values.append("end group")
148
+ elif column == "relevance":
149
+ values.append("")
150
+ elif column in ("name"):
151
+ value = get_attr_if_exists(strategy, cur_group, column, SURVEY_MAP)
152
+
153
+ if get_export_name(cur_group) in groups:
154
+ value = value + "_" + str(groups[get_export_name(cur_group)]) + "_end"
155
+ values.append(value)
156
+ else:
157
+ values.append(get_xfrom_trad(strategy, cur_group, column, SURVEY_MAP))
158
+ df_survey.loc[len(df_survey)] = values
159
+
160
+ # waltk thought the node,
161
+ # if node has group, open the group (and parent group)
162
+ # check process the next_node with the same group first, then process the other
163
+
164
+ # if node has another group (not current) close the group
165
+ # if node is an activity close the group
166
+
167
+ # during tricc object building/ or par of the stategy
168
+ # static calculte node with same name:
169
+ # follow same approach as the dynamic
170
+ # if reference not in used_saves
171
+ # , then create calculate node reference_1 # and save is used_saves 'reference' : 1
172
+ # else create calculate node reference_(used_saves['reference']+1) # and update used_saves['reference'] += 1
173
+ # once done, walkthrough again and remame reference_(used_saves['reference']) to reference and create the other save
174
+
175
+
176
+ ODK_TRICC_TYPE_MAP = {
177
+ "note": "note",
178
+ "calculate": "calculate",
179
+ "select_multiple": "select_multiple",
180
+ "select_one": "select_one",
181
+ "decimal": "decimal",
182
+ "integer": "integer",
183
+ "text": "text",
184
+ "rhombus": "calculate",
185
+ "goto": "", #: start the linked activity within the target activity
186
+ "start": "",
187
+ "activity_start": "calculate",
188
+ "link_in": "",
189
+ "link_out": "",
190
+ "count": "calculate",
191
+ "add": "calculate",
192
+ "container_hint_media": "",
193
+ "activity": "",
194
+ "select_option": "",
195
+ "hint": "",
196
+ "help": "",
197
+ "exclusive": "calculate",
198
+ "end": "calculate",
199
+ "activity_end": "calculate",
200
+ "edge": "",
201
+ "page": "",
202
+ "bridge": "calculate",
203
+ "date": "date",
204
+ "diagnosis": "calculate",
205
+ "proposed_diagnosis": "calculate",
206
+ "input": "",
207
+ }
208
+
209
+ GROUP_TRICC_TYPE = [TriccNodeType.page, TriccNodeType.activity]
210
+
211
+ SURVEY_MAP = {
212
+ "type": ODK_TRICC_TYPE_MAP,
213
+ "name": "name",
214
+ **langs.get_trads_map("label"),
215
+ **langs.get_trads_map("hint"),
216
+ **langs.get_trads_map("help"),
217
+ "default": "default",
218
+ "appearance": "appearance",
219
+ "constraint": "constraint",
220
+ **langs.get_trads_map("constraint_message"),
221
+ "relevance": "relevance",
222
+ "disabled": "disabled",
223
+ "required": "required",
224
+ **langs.get_trads_map("required_message"),
225
+ "read only": "read only",
226
+ "calculation": "expression",
227
+ "repeat_count": "repeat_count",
228
+ "media::image": "image",
229
+ "choice_filter": "",
230
+ }
231
+ CHOICE_MAP = {
232
+ "list_name": "list_name",
233
+ "value": "name",
234
+ **langs.get_trads_map("label"),
235
+ "media::image": "image",
236
+ "choice_filter": "",
237
+ "y_min": "",
238
+ "y_max": "",
239
+ "l": "",
240
+ "s": "",
241
+ "m": "",
242
+ }
243
+
244
+
245
+ TRAD_MAP = ["label", "constraint_message", "required_message", "hint", "help"]
246
+
247
+
248
+ def get_xfrom_trad(strategy, node, column, mapping, clean_html=False):
249
+ arr = column.split("::")
250
+ new_column = arr[0] if arr[0] != "media" else "::".join(arr[0:2])
251
+ trad = arr[-1] if new_column != column else None
252
+ value = get_attr_if_exists(strategy, node, new_column, mapping)
253
+ # the pattern is to look for if that define a string if(test>0, 'strin')
254
+ pattern = r"concat\(|[^\}] *, *'[^']"
255
+ if (
256
+ issubclass(node.__class__, TriccNodeDisplayCalculateBase)
257
+ and column == "calculation"
258
+ and isinstance(value, str)
259
+ and not value.startswith("number")
260
+ and getattr(node, "expression", None)
261
+ and node.expression.get_datatype() in ("number", "boolean")
262
+ ):
263
+ value = f"number({value})" if str(value) not in ["0", "1"] else value
264
+ if clean_html and isinstance(value, str):
265
+ value = remove_html(value)
266
+ if column in TRAD_MAP:
267
+ value = langs.get_trads(value, trad=trad)
268
+ elif column == "appearance":
269
+ if (
270
+ isinstance(node, TriccNodeSelect)
271
+ and len(node.options) > 9
272
+ and not any(o.image or o.hint for o in node.options.values())
273
+ ):
274
+ value = "autocomplete"
275
+ elif isinstance(node, TriccNodeNote) and "countdown-timer" in node.name:
276
+ value = "countdown-timer"
277
+ elif (
278
+ column == "appearance"
279
+ and isinstance(node, TriccNodeAcceptDiagnostic)
280
+ and node.severity
281
+ and not value
282
+ ):
283
+ if node.severity == "severe":
284
+ value = "severe"
285
+ elif node.severity == "moderate":
286
+ value = "moderate"
287
+ elif node.severity == "light":
288
+ value == "light"
289
+
290
+ return value
291
+
292
+
293
+ def gen_operation_hash(op):
294
+ if op:
295
+ h = hashlib.blake2b(digest_size=6)
296
+ h.update(str(op).encode("utf-8"))
297
+ return h.hexdigest()
298
+
299
+
300
+ def generate_choice_filter(strategy, node):
301
+ if isinstance(node, TriccNodeSelectOption) and node.relevance:
302
+ return gen_operation_hash(node.relevance)
303
+ if not isinstance(node, (TriccNodeSelectMultiple, TriccNodeSelectOne)):
304
+ return
305
+ relevances = {}
306
+ option_filter = {}
307
+ for o in node.options.values():
308
+ if o.relevance:
309
+ key = gen_operation_hash(o.relevance)
310
+ if key not in relevances:
311
+ relevances[key] = o.relevance
312
+ if relevances:
313
+ basic = "string-length(choice_filter)=0"
314
+ # TODO remove when the bug regarding filter + image will be fixed
315
+ if any(i.image is not None for i in node.options.values()):
316
+ basic = TriccOperation(
317
+ TriccOperator.AND, ["string-length(choice_filter)=0", node.relevance]
318
+ )
319
+
320
+ choice_filter = TriccOperation(TriccOperator.OR, [basic])
321
+ for k, op in relevances.items():
322
+ choice_filter.append(
323
+ TriccOperation(
324
+ TriccOperator.AND,
325
+ [
326
+ TriccOperation(
327
+ TriccOperator.EQUAL,
328
+ [
329
+ "choice_filter",
330
+ TriccStatic(k),
331
+ ],
332
+ ),
333
+ op,
334
+ ],
335
+ )
336
+ )
337
+ return strategy.get_tricc_operation_expression(choice_filter)
338
+
339
+
340
+ def get_attr_if_exists(strategy, node, column, map_array):
341
+ if column in map_array:
342
+ mapping = map_array[column]
343
+ if (
344
+ isinstance(mapping, Dict)
345
+ and getattr(node, "tricc_type", None) in map_array[column]
346
+ ):
347
+ tricc_type = map_array[column][node.tricc_type]
348
+ if tricc_type[:6] == "select":
349
+ return tricc_type + " " + node.list_name
350
+ else:
351
+ return tricc_type
352
+ elif hasattr(node, map_array[column]):
353
+ value = getattr(node, map_array[column])
354
+ if (
355
+ column == "calculation"
356
+ and len(node.prev_nodes) == 0
357
+ and value
358
+ and isinstance(
359
+ getattr(node, "applicability", None),
360
+ (TriccOperation, TriccStatic, TriccReference),
361
+ )
362
+ ):
363
+ if value.get_datatype() == "boolean" and node.applicability.get_datatype() == "boolean":
364
+ value = and_join([node.applicability, value])
365
+ else:
366
+ value = TriccOperation(
367
+ TriccOperator.IF,
368
+ [
369
+ node.applicability,
370
+ value,
371
+ (
372
+ TriccStatic(False)
373
+ if node.applicability.get_datatype() == "boolean"
374
+ else TriccStatic("")
375
+ ),
376
+ ],
377
+ )
378
+ if column == "name":
379
+ if issubclass(value.__class__, (TriccNodeBaseModel)):
380
+ return get_export_name(value)
381
+ else:
382
+ return get_export_name(node)
383
+ # convert value to boolean
384
+ if column == "value" and str(value) in BOOLEAN_MAP:
385
+ return BOOLEAN_MAP[str(value)]
386
+
387
+ elif isinstance(value, (TriccOperation, TriccStatic, TriccReference)):
388
+ expression = strategy.get_tricc_operation_expression(value)
389
+ return (
390
+ expression.replace("$this", ".")
391
+ if isinstance(expression, str)
392
+ else expression
393
+ )
394
+ elif value is not None:
395
+ return str(value) if not isinstance(value, dict) else value
396
+ else:
397
+ return ""
398
+ elif column == "choice_filter":
399
+ return generate_choice_filter(strategy, node)
400
+
401
+ else:
402
+ return ""
403
+ elif hasattr(node, column) and getattr(node, column) is not None:
404
+ value = getattr(node, column)
405
+ return str(value) if not isinstance(value, dict) else value
406
+ else:
407
+ return ""
408
+
409
+
410
+ def get_more_info_select(strategy, node):
411
+ values = []
412
+ for column in SURVEY_MAP:
413
+ if column == "type":
414
+ values.append("select_one more_info")
415
+ elif column == "label":
416
+ values.append("NO_LABEL")
417
+ elif column == "name":
418
+ values.append(get_export_name(node) + "_optin")
419
+ elif column == "hint":
420
+ print(get_xfrom_trad(strategy, node, column, SURVEY_MAP, clean_html=True))
421
+ values.append(
422
+ get_xfrom_trad(strategy, node, column, SURVEY_MAP, clean_html=True)
423
+ )
424
+ elif column == "relevance":
425
+ values.append(get_xfrom_trad(strategy, node.parent, column, SURVEY_MAP))
426
+ else:
427
+ values.append(get_xfrom_trad(strategy, None, column, SURVEY_MAP))
428
+ return values
429
+
430
+
431
+ def get_more_info_message(strategy, node):
432
+ values = []
433
+ for column in SURVEY_MAP:
434
+ if column == "type":
435
+ values.append("note")
436
+ elif column == "relevance":
437
+ values.append(f"${{{get_export_name(node)}_optin}} = 1")
438
+ elif column.startswith("hint"):
439
+ values.append(langs.get_trads("", trad=None))
440
+ else:
441
+ values.append(
442
+ get_xfrom_trad(strategy, node, column, SURVEY_MAP, clean_html=True)
443
+ )
444
+ return values
445
+
446
+
447
+ def get_more_info_choice(strategy):
448
+ values = []
449
+ for column in CHOICE_MAP:
450
+ if column == "list_name":
451
+ values.append("more_info")
452
+ elif column == "value":
453
+ values.append("1")
454
+ elif column.startswith("label"):
455
+ arr = column.split("::")
456
+ column = arr[0]
457
+ trad = arr[1] if len(arr) == 2 else None
458
+ values.append(langs.get_trads("More information", trad=trad))
459
+ else:
460
+ values.append(get_xfrom_trad(strategy, None, column, CHOICE_MAP, True))
461
+ return values
462
+
463
+
464
+ def generate_xls_form_export(
465
+ strategy,
466
+ node,
467
+ processed_nodes,
468
+ stashed_nodes,
469
+ df_survey,
470
+ df_choice,
471
+ df_calculate,
472
+ cur_group,
473
+ calculates,
474
+ **kwargs,
475
+ ):
476
+ # check that all prev nodes were processed
477
+ if is_ready_to_process(node, processed_nodes, strict=True) and process_reference(
478
+ node,
479
+ processed_nodes,
480
+ calculates,
481
+ replace_reference=False,
482
+ codesystems=kwargs.get("codesystems", None),
483
+ ):
484
+ if node not in processed_nodes:
485
+ add_calculate(calculates, node)
486
+ if node.group != cur_group and not isinstance(node, TriccNodeSelectOption):
487
+ return False
488
+ if kwargs.get("warn", True):
489
+ logger.debug("printing node {}".format(node.get_name()))
490
+ # clean stashed node when processed
491
+ if node in stashed_nodes:
492
+ stashed_nodes.remove(node)
493
+ if kwargs.get("warn", True):
494
+ logger.debug(
495
+ "generate_xls_form_export: unstashing processed node{} ".format(
496
+ node.get_name()
497
+ )
498
+ )
499
+ if issubclass(
500
+ node.__class__, (TriccNodeDisplayCalculateBase, TriccNodeDisplayModel)
501
+ ):
502
+ if isinstance(node, TriccNodeSelectOption):
503
+ values = []
504
+ for column in CHOICE_MAP:
505
+ values.append(
506
+ get_xfrom_trad(strategy, node, column, CHOICE_MAP, True)
507
+ )
508
+ # add only if not existing
509
+ if (
510
+ len(
511
+ df_choice[
512
+ (df_choice["list_name"] == node.list_name)
513
+ & (
514
+ df_choice["value"]
515
+ == BOOLEAN_MAP.get(str(node.name), node.name)
516
+ )
517
+ ]
518
+ )
519
+ == 0
520
+ ):
521
+ df_choice.loc[len(df_choice)] = values
522
+ elif isinstance(node, TriccNodeMoreInfo):
523
+ df_survey.loc[len(df_survey)] = get_more_info_select(strategy, node)
524
+ df_survey.loc[len(df_survey)] = get_more_info_message(
525
+ strategy, node
526
+ )
527
+ if len(df_choice[(df_choice["list_name"] == "more_info")]) == 0:
528
+ df_choice.loc[len(df_choice)] = get_more_info_choice(strategy)
529
+ elif (
530
+ node.tricc_type in ODK_TRICC_TYPE_MAP
531
+ and ODK_TRICC_TYPE_MAP[node.tricc_type] is not None
532
+ ):
533
+ if ODK_TRICC_TYPE_MAP[node.tricc_type] == "calculate":
534
+ values = []
535
+ for column in SURVEY_MAP:
536
+ value = get_xfrom_trad(strategy, node, column, SURVEY_MAP)
537
+ if (
538
+ column == "default"
539
+ and issubclass(
540
+ node.__class__, TriccNodeDisplayCalculateBase
541
+ )
542
+ and value == ""
543
+ ):
544
+ value = 0
545
+ values.append(value)
546
+ if (
547
+ len(
548
+ df_calculate[df_calculate.name == get_export_name(node)]
549
+ )
550
+ == 0
551
+ ):
552
+ df_calculate.loc[len(df_calculate)] = values
553
+ else:
554
+ df_calculate.loc[len(df_calculate)] = values
555
+ logger.critical("name {} found twice".format(node.name))
556
+ elif ODK_TRICC_TYPE_MAP[node.tricc_type] != "":
557
+ values = []
558
+ for column in SURVEY_MAP:
559
+ values.append(
560
+ get_xfrom_trad(strategy, node, column, SURVEY_MAP)
561
+ )
562
+ df_survey.loc[len(df_survey)] = values
563
+ else:
564
+ logger.warning(
565
+ "node {} have an unmapped type {}".format(
566
+ node.get_name(), node.tricc_type
567
+ )
568
+ )
569
+ else:
570
+ logger.warning(
571
+ "node {} have an unsupported type {}".format(
572
+ node.get_name(), node.tricc_type
573
+ )
574
+ )
575
+ # continue walk °
576
+ return True
577
+ return False
578
+
579
+
580
+ def get_input_line(node, replace_dots=True):
581
+ label = langs.get_trads(node.label, force_dict=True)
582
+ empty = langs.get_trads("", force_dict=True)
583
+ return [
584
+ "hidden",
585
+ clean_name(node.name, replace_dots=True),
586
+ *list(empty.values()),
587
+ *list(empty.values()), # hint
588
+ *list(empty.values()), # help
589
+ "", # default
590
+ "hidden", #'appearance', clean_name
591
+ "", #'constraint',
592
+ *list(empty.values()), #'constraint_message'
593
+ "", #'relevance'
594
+ "", #'disabled'
595
+ "", #'required'
596
+ *list(empty.values()), #'required message'
597
+ "", #'read only'
598
+ "", #'expression'
599
+ "", #'repeat_count'
600
+ "", #'image'
601
+ "",
602
+ ]
603
+
604
+
605
+ def get_input_calc_line(node, replace_dots=True):
606
+ label = langs.get_trads(node.label, force_dict=True)
607
+ empty = langs.get_trads("", force_dict=True)
608
+ return [
609
+ "calculate",
610
+ get_export_name(node),
611
+ *list(empty.values()),
612
+ *list(empty.values()), # hint
613
+ *list(empty.values()), # help
614
+ "", # default
615
+ "", #'appearance', clean_name
616
+ "", #'constraint',
617
+ *list(empty.values()), #'constraint_message'
618
+ "", #'relevance'
619
+ "", #'disabled'
620
+ "", #'required'
621
+ *list(empty.values()), #'required message'
622
+ "", #'read only'
623
+ "../inputs/contact/"
624
+ + clean_name(node.name, replace_dots=replace_dots), #'expression'
625
+ "", #'repeat_count'
626
+ "", #'image'
627
+ "", # choice filter
628
+ ]
629
+
630
+
631
+ def get_diagnostic_start_group_line():
632
+ label = langs.get_trads("List of diagnostics", force_dict=True)
633
+ empty = langs.get_trads("", force_dict=True)
634
+ return [
635
+ "begin group",
636
+ "l_diag_list25",
637
+ *list(label.values()),
638
+ *list(empty.values()), # hint
639
+ *list(empty.values()), # help
640
+ "", # default
641
+ "field-list", #'appearance',
642
+ "", #'constraint',
643
+ *list(empty.values()), #'constraint_message'
644
+ "", #'relevance'
645
+ "", #'disabled'
646
+ "", #'required'
647
+ *list(empty.values()), #'required message'
648
+ "", #'read only'
649
+ "", #'expression'
650
+ "", #'repeat_count'
651
+ "", #'image'
652
+ "",
653
+ ]
654
+
655
+
656
+ def get_diagnostic_add_line(diags, df_choice):
657
+ for diag in diags:
658
+ df_choice.loc[len(df_choice)] = [
659
+ "tricc_diag_add",
660
+ get_export_name(diag),
661
+ *list(langs.get_trads(diag.label, True).values()),
662
+ "", # filter
663
+ "", # min y
664
+ "", # max Y
665
+ "", # l
666
+ "", # m
667
+ "", # s
668
+ ]
669
+ label = langs.get_trads("Add a missing diagnostic", force_dict=True)
670
+ empty = langs.get_trads("", force_dict=True)
671
+ return [
672
+ "select_multiple tricc_diag_add",
673
+ "new_diag",
674
+ *list(label.values()),
675
+ *list(empty.values()), # hint
676
+ *list(empty.values()), # help
677
+ "", # default
678
+ "minimal", #'appearance',
679
+ "", #'constraint',
680
+ *list(empty.values()), #'constraint_message',
681
+ "", #'relevance'
682
+ "", #'disabled'
683
+ "", #'required'
684
+ *list(empty.values()), #'required message'
685
+ "", #'read only'
686
+ "", #'expression'
687
+ "", #'repeat_count'
688
+ "", #'image'
689
+ "",
690
+ ]
691
+
692
+
693
+ def get_diagnostic_none_line(diags):
694
+ relevance = ""
695
+ for diag in diags:
696
+ relevance += TRICC_CALC_EXPRESSION.format(get_export_name(diag)) + " or "
697
+ label = langs.get_trads(
698
+ "Aucun diagnostic trouvé par l'outil mais cela ne veut pas dire que le patient est en bonne santé",
699
+ force_dict=True,
700
+ )
701
+ empty = langs.get_trads("", force_dict=True)
702
+ return [
703
+ "note",
704
+ "l_diag_none25",
705
+ *list(label.values()),
706
+ *list(empty.values()),
707
+ *list(empty.values()),
708
+ "", # default
709
+ "", #'appearance',
710
+ "", #'constraint',
711
+ *list(empty.values()),
712
+ f"not({relevance[:-4]})", #'relevance'
713
+ "", #'disabled'
714
+ "", #'required'
715
+ *list(empty.values()),
716
+ "", #'read only'
717
+ "", #'expression'
718
+ "", #'repeat_count'
719
+ "", #'image' TRICC_NEGATE
720
+ "",
721
+ ]
722
+
723
+
724
+ def get_diagnostic_stop_group_line():
725
+ label = langs.get_trads("", force_dict=True)
726
+ return [
727
+ "end group",
728
+ "l_diag_list25",
729
+ *list(label.values()),
730
+ *list(label.values()),
731
+ *list(label.values()), # help
732
+ "", # default
733
+ "", #'appearance',
734
+ "", #'constraint',
735
+ *list(label.values()),
736
+ "", #'relevance'
737
+ "", #'disabled'
738
+ "", #'required'
739
+ *list(label.values()),
740
+ "", #'read only'
741
+ "", #'expression'
742
+ "", #'repeat_count'
743
+ "", #'image'
744
+ "",
745
+ ]