sql-assignment-generator 0.0.12__tar.gz → 0.0.13__tar.gz

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 (129) hide show
  1. {sql_assignment_generator-0.0.12 → sql_assignment_generator-0.0.13}/PKG-INFO +1 -1
  2. {sql_assignment_generator-0.0.12 → sql_assignment_generator-0.0.13}/pyproject.toml +1 -1
  3. {sql_assignment_generator-0.0.12 → sql_assignment_generator-0.0.13}/src/sql_assignment_generator/__init__.py +18 -11
  4. {sql_assignment_generator-0.0.12 → sql_assignment_generator-0.0.13}/test.py +1 -0
  5. {sql_assignment_generator-0.0.12 → sql_assignment_generator-0.0.13}/.env.template +0 -0
  6. {sql_assignment_generator-0.0.12 → sql_assignment_generator-0.0.13}/.gitattributes +0 -0
  7. {sql_assignment_generator-0.0.12 → sql_assignment_generator-0.0.13}/.gitignore +0 -0
  8. {sql_assignment_generator-0.0.12 → sql_assignment_generator-0.0.13}/.readthedocs.yaml +0 -0
  9. {sql_assignment_generator-0.0.12 → sql_assignment_generator-0.0.13}/LICENSE +0 -0
  10. {sql_assignment_generator-0.0.12 → sql_assignment_generator-0.0.13}/Makefile +0 -0
  11. {sql_assignment_generator-0.0.12 → sql_assignment_generator-0.0.13}/README.md +0 -0
  12. {sql_assignment_generator-0.0.12 → sql_assignment_generator-0.0.13}/docs/Makefile +0 -0
  13. {sql_assignment_generator-0.0.12 → sql_assignment_generator-0.0.13}/docs/conf.py +0 -0
  14. {sql_assignment_generator-0.0.12 → sql_assignment_generator-0.0.13}/docs/index.rst +0 -0
  15. {sql_assignment_generator-0.0.12 → sql_assignment_generator-0.0.13}/docs/make.bat +0 -0
  16. {sql_assignment_generator-0.0.12 → sql_assignment_generator-0.0.13}/docs/requirements.txt +0 -0
  17. {sql_assignment_generator-0.0.12 → sql_assignment_generator-0.0.13}/requirements.txt +0 -0
  18. {sql_assignment_generator-0.0.12 → sql_assignment_generator-0.0.13}/src/sql_assignment_generator/assignments/__init__.py +0 -0
  19. {sql_assignment_generator-0.0.12 → sql_assignment_generator-0.0.13}/src/sql_assignment_generator/assignments/assignment.py +0 -0
  20. {sql_assignment_generator-0.0.12 → sql_assignment_generator-0.0.13}/src/sql_assignment_generator/assignments/dataset/__init__.py +0 -0
  21. {sql_assignment_generator-0.0.12 → sql_assignment_generator-0.0.13}/src/sql_assignment_generator/assignments/dataset/dataset.py +0 -0
  22. {sql_assignment_generator-0.0.12 → sql_assignment_generator-0.0.13}/src/sql_assignment_generator/assignments/dataset/strings.py +0 -0
  23. {sql_assignment_generator-0.0.12 → sql_assignment_generator-0.0.13}/src/sql_assignment_generator/assignments/exercise/__init__.py +0 -0
  24. {sql_assignment_generator-0.0.12 → sql_assignment_generator-0.0.13}/src/sql_assignment_generator/assignments/exercise/exercise.py +0 -0
  25. {sql_assignment_generator-0.0.12 → sql_assignment_generator-0.0.13}/src/sql_assignment_generator/assignments/exercise/strings.py +0 -0
  26. {sql_assignment_generator-0.0.12 → sql_assignment_generator-0.0.13}/src/sql_assignment_generator/constraints/__init__.py +0 -0
  27. {sql_assignment_generator-0.0.12 → sql_assignment_generator-0.0.13}/src/sql_assignment_generator/constraints/base.py +0 -0
  28. {sql_assignment_generator-0.0.12 → sql_assignment_generator-0.0.13}/src/sql_assignment_generator/constraints/costraintType.py +0 -0
  29. {sql_assignment_generator-0.0.12 → sql_assignment_generator-0.0.13}/src/sql_assignment_generator/constraints/query/__init__.py +0 -0
  30. {sql_assignment_generator-0.0.12 → sql_assignment_generator-0.0.13}/src/sql_assignment_generator/constraints/query/aggregation.py +0 -0
  31. {sql_assignment_generator-0.0.12 → sql_assignment_generator-0.0.13}/src/sql_assignment_generator/constraints/query/base.py +0 -0
  32. {sql_assignment_generator-0.0.12 → sql_assignment_generator-0.0.13}/src/sql_assignment_generator/constraints/query/clause_from.py +0 -0
  33. {sql_assignment_generator-0.0.12 → sql_assignment_generator-0.0.13}/src/sql_assignment_generator/constraints/query/clause_group_by.py +0 -0
  34. {sql_assignment_generator-0.0.12 → sql_assignment_generator-0.0.13}/src/sql_assignment_generator/constraints/query/clause_having.py +0 -0
  35. {sql_assignment_generator-0.0.12 → sql_assignment_generator-0.0.13}/src/sql_assignment_generator/constraints/query/clause_order_by.py +0 -0
  36. {sql_assignment_generator-0.0.12 → sql_assignment_generator-0.0.13}/src/sql_assignment_generator/constraints/query/clause_select.py +0 -0
  37. {sql_assignment_generator-0.0.12 → sql_assignment_generator-0.0.13}/src/sql_assignment_generator/constraints/query/clause_where.py +0 -0
  38. {sql_assignment_generator-0.0.12 → sql_assignment_generator-0.0.13}/src/sql_assignment_generator/constraints/query/rows.py +0 -0
  39. {sql_assignment_generator-0.0.12 → sql_assignment_generator-0.0.13}/src/sql_assignment_generator/constraints/query/set_operations.py +0 -0
  40. {sql_assignment_generator-0.0.12 → sql_assignment_generator-0.0.13}/src/sql_assignment_generator/constraints/query/subquery.py +0 -0
  41. {sql_assignment_generator-0.0.12 → sql_assignment_generator-0.0.13}/src/sql_assignment_generator/constraints/schema/__init__.py +0 -0
  42. {sql_assignment_generator-0.0.12 → sql_assignment_generator-0.0.13}/src/sql_assignment_generator/constraints/schema/base.py +0 -0
  43. {sql_assignment_generator-0.0.12 → sql_assignment_generator-0.0.13}/src/sql_assignment_generator/constraints/schema/tables.py +0 -0
  44. {sql_assignment_generator-0.0.12 → sql_assignment_generator-0.0.13}/src/sql_assignment_generator/constraints/schema/values.py +0 -0
  45. {sql_assignment_generator-0.0.12 → sql_assignment_generator-0.0.13}/src/sql_assignment_generator/difficulty_level.py +0 -0
  46. {sql_assignment_generator-0.0.12 → sql_assignment_generator-0.0.13}/src/sql_assignment_generator/domains.py +0 -0
  47. {sql_assignment_generator-0.0.12 → sql_assignment_generator-0.0.13}/src/sql_assignment_generator/error_requirements/__init__.py +0 -0
  48. {sql_assignment_generator-0.0.12 → sql_assignment_generator-0.0.13}/src/sql_assignment_generator/error_requirements/base.py +0 -0
  49. {sql_assignment_generator-0.0.12 → sql_assignment_generator-0.0.13}/src/sql_assignment_generator/error_requirements/err_002.py +0 -0
  50. {sql_assignment_generator-0.0.12 → sql_assignment_generator-0.0.13}/src/sql_assignment_generator/error_requirements/err_004.py +0 -0
  51. {sql_assignment_generator-0.0.12 → sql_assignment_generator-0.0.13}/src/sql_assignment_generator/error_requirements/err_007.py +0 -0
  52. {sql_assignment_generator-0.0.12 → sql_assignment_generator-0.0.13}/src/sql_assignment_generator/error_requirements/err_009.py +0 -0
  53. {sql_assignment_generator-0.0.12 → sql_assignment_generator-0.0.13}/src/sql_assignment_generator/error_requirements/err_010.py +0 -0
  54. {sql_assignment_generator-0.0.12 → sql_assignment_generator-0.0.13}/src/sql_assignment_generator/error_requirements/err_011.py +0 -0
  55. {sql_assignment_generator-0.0.12 → sql_assignment_generator-0.0.13}/src/sql_assignment_generator/error_requirements/err_012.py +0 -0
  56. {sql_assignment_generator-0.0.12 → sql_assignment_generator-0.0.13}/src/sql_assignment_generator/error_requirements/err_015.py +0 -0
  57. {sql_assignment_generator-0.0.12 → sql_assignment_generator-0.0.13}/src/sql_assignment_generator/error_requirements/err_019.py +0 -0
  58. {sql_assignment_generator-0.0.12 → sql_assignment_generator-0.0.13}/src/sql_assignment_generator/error_requirements/err_021.py +0 -0
  59. {sql_assignment_generator-0.0.12 → sql_assignment_generator-0.0.13}/src/sql_assignment_generator/error_requirements/err_026.py +0 -0
  60. {sql_assignment_generator-0.0.12 → sql_assignment_generator-0.0.13}/src/sql_assignment_generator/error_requirements/err_035.py +0 -0
  61. {sql_assignment_generator-0.0.12 → sql_assignment_generator-0.0.13}/src/sql_assignment_generator/error_requirements/err_039.py +0 -0
  62. {sql_assignment_generator-0.0.12 → sql_assignment_generator-0.0.13}/src/sql_assignment_generator/error_requirements/err_040.py +0 -0
  63. {sql_assignment_generator-0.0.12 → sql_assignment_generator-0.0.13}/src/sql_assignment_generator/error_requirements/err_041.py +0 -0
  64. {sql_assignment_generator-0.0.12 → sql_assignment_generator-0.0.13}/src/sql_assignment_generator/error_requirements/err_042.py +0 -0
  65. {sql_assignment_generator-0.0.12 → sql_assignment_generator-0.0.13}/src/sql_assignment_generator/error_requirements/err_043.py +0 -0
  66. {sql_assignment_generator-0.0.12 → sql_assignment_generator-0.0.13}/src/sql_assignment_generator/error_requirements/err_044.py +0 -0
  67. {sql_assignment_generator-0.0.12 → sql_assignment_generator-0.0.13}/src/sql_assignment_generator/error_requirements/err_045.py +0 -0
  68. {sql_assignment_generator-0.0.12 → sql_assignment_generator-0.0.13}/src/sql_assignment_generator/error_requirements/err_046.py +0 -0
  69. {sql_assignment_generator-0.0.12 → sql_assignment_generator-0.0.13}/src/sql_assignment_generator/error_requirements/err_049.py +0 -0
  70. {sql_assignment_generator-0.0.12 → sql_assignment_generator-0.0.13}/src/sql_assignment_generator/error_requirements/err_052.py +0 -0
  71. {sql_assignment_generator-0.0.12 → sql_assignment_generator-0.0.13}/src/sql_assignment_generator/error_requirements/err_053.py +0 -0
  72. {sql_assignment_generator-0.0.12 → sql_assignment_generator-0.0.13}/src/sql_assignment_generator/error_requirements/err_054.py +0 -0
  73. {sql_assignment_generator-0.0.12 → sql_assignment_generator-0.0.13}/src/sql_assignment_generator/error_requirements/err_055.py +0 -0
  74. {sql_assignment_generator-0.0.12 → sql_assignment_generator-0.0.13}/src/sql_assignment_generator/error_requirements/err_057.py +0 -0
  75. {sql_assignment_generator-0.0.12 → sql_assignment_generator-0.0.13}/src/sql_assignment_generator/error_requirements/err_058.py +0 -0
  76. {sql_assignment_generator-0.0.12 → sql_assignment_generator-0.0.13}/src/sql_assignment_generator/error_requirements/err_059.py +0 -0
  77. {sql_assignment_generator-0.0.12 → sql_assignment_generator-0.0.13}/src/sql_assignment_generator/error_requirements/err_060.py +0 -0
  78. {sql_assignment_generator-0.0.12 → sql_assignment_generator-0.0.13}/src/sql_assignment_generator/error_requirements/err_062.py +0 -0
  79. {sql_assignment_generator-0.0.12 → sql_assignment_generator-0.0.13}/src/sql_assignment_generator/error_requirements/err_063.py +0 -0
  80. {sql_assignment_generator-0.0.12 → sql_assignment_generator-0.0.13}/src/sql_assignment_generator/error_requirements/err_064.py +0 -0
  81. {sql_assignment_generator-0.0.12 → sql_assignment_generator-0.0.13}/src/sql_assignment_generator/error_requirements/err_066.py +0 -0
  82. {sql_assignment_generator-0.0.12 → sql_assignment_generator-0.0.13}/src/sql_assignment_generator/error_requirements/err_067.py +0 -0
  83. {sql_assignment_generator-0.0.12 → sql_assignment_generator-0.0.13}/src/sql_assignment_generator/error_requirements/err_068.py +0 -0
  84. {sql_assignment_generator-0.0.12 → sql_assignment_generator-0.0.13}/src/sql_assignment_generator/error_requirements/err_069.py +0 -0
  85. {sql_assignment_generator-0.0.12 → sql_assignment_generator-0.0.13}/src/sql_assignment_generator/error_requirements/err_070.py +0 -0
  86. {sql_assignment_generator-0.0.12 → sql_assignment_generator-0.0.13}/src/sql_assignment_generator/error_requirements/err_071.py +0 -0
  87. {sql_assignment_generator-0.0.12 → sql_assignment_generator-0.0.13}/src/sql_assignment_generator/error_requirements/err_072.py +0 -0
  88. {sql_assignment_generator-0.0.12 → sql_assignment_generator-0.0.13}/src/sql_assignment_generator/error_requirements/err_073.py +0 -0
  89. {sql_assignment_generator-0.0.12 → sql_assignment_generator-0.0.13}/src/sql_assignment_generator/error_requirements/err_074.py +0 -0
  90. {sql_assignment_generator-0.0.12 → sql_assignment_generator-0.0.13}/src/sql_assignment_generator/error_requirements/err_075.py +0 -0
  91. {sql_assignment_generator-0.0.12 → sql_assignment_generator-0.0.13}/src/sql_assignment_generator/error_requirements/err_076.py +0 -0
  92. {sql_assignment_generator-0.0.12 → sql_assignment_generator-0.0.13}/src/sql_assignment_generator/error_requirements/err_077.py +0 -0
  93. {sql_assignment_generator-0.0.12 → sql_assignment_generator-0.0.13}/src/sql_assignment_generator/error_requirements/err_078.py +0 -0
  94. {sql_assignment_generator-0.0.12 → sql_assignment_generator-0.0.13}/src/sql_assignment_generator/error_requirements/err_079.py +0 -0
  95. {sql_assignment_generator-0.0.12 → sql_assignment_generator-0.0.13}/src/sql_assignment_generator/error_requirements/err_080.py +0 -0
  96. {sql_assignment_generator-0.0.12 → sql_assignment_generator-0.0.13}/src/sql_assignment_generator/error_requirements/err_081.py +0 -0
  97. {sql_assignment_generator-0.0.12 → sql_assignment_generator-0.0.13}/src/sql_assignment_generator/error_requirements/err_083.py +0 -0
  98. {sql_assignment_generator-0.0.12 → sql_assignment_generator-0.0.13}/src/sql_assignment_generator/error_requirements/err_084.py +0 -0
  99. {sql_assignment_generator-0.0.12 → sql_assignment_generator-0.0.13}/src/sql_assignment_generator/error_requirements/err_086.py +0 -0
  100. {sql_assignment_generator-0.0.12 → sql_assignment_generator-0.0.13}/src/sql_assignment_generator/error_requirements/err_088.py +0 -0
  101. {sql_assignment_generator-0.0.12 → sql_assignment_generator-0.0.13}/src/sql_assignment_generator/error_requirements/err_089.py +0 -0
  102. {sql_assignment_generator-0.0.12 → sql_assignment_generator-0.0.13}/src/sql_assignment_generator/error_requirements/err_091.py +0 -0
  103. {sql_assignment_generator-0.0.12 → sql_assignment_generator-0.0.13}/src/sql_assignment_generator/error_requirements/err_093.py +0 -0
  104. {sql_assignment_generator-0.0.12 → sql_assignment_generator-0.0.13}/src/sql_assignment_generator/error_requirements/err_095.py +0 -0
  105. {sql_assignment_generator-0.0.12 → sql_assignment_generator-0.0.13}/src/sql_assignment_generator/error_requirements/err_096.py +0 -0
  106. {sql_assignment_generator-0.0.12 → sql_assignment_generator-0.0.13}/src/sql_assignment_generator/error_requirements/err_097.py +0 -0
  107. {sql_assignment_generator-0.0.12 → sql_assignment_generator-0.0.13}/src/sql_assignment_generator/error_requirements/err_098.py +0 -0
  108. {sql_assignment_generator-0.0.12 → sql_assignment_generator-0.0.13}/src/sql_assignment_generator/error_requirements/err_099.py +0 -0
  109. {sql_assignment_generator-0.0.12 → sql_assignment_generator-0.0.13}/src/sql_assignment_generator/error_requirements/err_102.py +0 -0
  110. {sql_assignment_generator-0.0.12 → sql_assignment_generator-0.0.13}/src/sql_assignment_generator/error_requirements/err_104.py +0 -0
  111. {sql_assignment_generator-0.0.12 → sql_assignment_generator-0.0.13}/src/sql_assignment_generator/error_requirements/err_105.py +0 -0
  112. {sql_assignment_generator-0.0.12 → sql_assignment_generator-0.0.13}/src/sql_assignment_generator/exceptions.py +0 -0
  113. {sql_assignment_generator-0.0.12 → sql_assignment_generator-0.0.13}/src/sql_assignment_generator/llm/__init__.py +0 -0
  114. {sql_assignment_generator-0.0.12 → sql_assignment_generator-0.0.13}/src/sql_assignment_generator/llm/chatgpt.py +0 -0
  115. {sql_assignment_generator-0.0.12 → sql_assignment_generator-0.0.13}/src/sql_assignment_generator/llm/message.py +0 -0
  116. {sql_assignment_generator-0.0.12 → sql_assignment_generator-0.0.13}/src/sql_assignment_generator/llm/models.py +0 -0
  117. {sql_assignment_generator-0.0.12 → sql_assignment_generator-0.0.13}/tests/constraints/query/test_aggregation.py +0 -0
  118. {sql_assignment_generator-0.0.12 → sql_assignment_generator-0.0.13}/tests/constraints/query/test_clause_from.py +0 -0
  119. {sql_assignment_generator-0.0.12 → sql_assignment_generator-0.0.13}/tests/constraints/query/test_clause_group_by.py +0 -0
  120. {sql_assignment_generator-0.0.12 → sql_assignment_generator-0.0.13}/tests/constraints/query/test_clause_having.py +0 -0
  121. {sql_assignment_generator-0.0.12 → sql_assignment_generator-0.0.13}/tests/constraints/query/test_clause_order_by.py +0 -0
  122. {sql_assignment_generator-0.0.12 → sql_assignment_generator-0.0.13}/tests/constraints/query/test_clause_select.py +0 -0
  123. {sql_assignment_generator-0.0.12 → sql_assignment_generator-0.0.13}/tests/constraints/query/test_clause_where.py +0 -0
  124. {sql_assignment_generator-0.0.12 → sql_assignment_generator-0.0.13}/tests/constraints/query/test_rows.py +0 -0
  125. {sql_assignment_generator-0.0.12 → sql_assignment_generator-0.0.13}/tests/constraints/query/test_set_operation.py +0 -0
  126. {sql_assignment_generator-0.0.12 → sql_assignment_generator-0.0.13}/tests/constraints/query/test_subquery.py +0 -0
  127. {sql_assignment_generator-0.0.12 → sql_assignment_generator-0.0.13}/tests/constraints/schema/__init__.py +0 -0
  128. {sql_assignment_generator-0.0.12 → sql_assignment_generator-0.0.13}/tests/constraints/schema/test_tables.py +0 -0
  129. {sql_assignment_generator-0.0.12 → sql_assignment_generator-0.0.13}/tests/constraints/schema/test_values.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: sql_assignment_generator
3
- Version: 0.0.12
3
+ Version: 0.0.13
4
4
  Summary: This project generates SQL assignments based on common mistakes made by learners.
5
5
  Project-URL: Repository, https://github.com/DavidePonzini/sql_assignment_generator
6
6
  Project-URL: Documentation, https://sql-assignment-generator.readthedocs.io/en/latest/index.html
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "sql_assignment_generator"
7
- version = "0.0.12"
7
+ version = "0.0.13"
8
8
  authors = [
9
9
  { name="Davide Ponzini", email="davide.ponzini95@gmail.com" },
10
10
  ]
@@ -45,22 +45,29 @@ def generate_assignment(
45
45
  Returns:
46
46
  Assignment: The generated assignment (stable order).
47
47
  '''
48
+
49
+ # filter only supported errors
50
+ supported_errors: list[tuple[SqlErrors, DifficultyLevel]] = []
51
+ for error, difficulty in errors:
52
+ if error in ERROR_REQUIREMENTS_MAP:
53
+ supported_errors.append((error, difficulty))
54
+ else:
55
+ dav_tools.messages.warning(f'Skipping unsupported error: {error.name}')
48
56
 
49
- dav_tools.messages.info(f'Starting assignment generation for {len(errors)} exercises...')
57
+ if not supported_errors:
58
+ raise ValueError('No supported errors provided for assignment generation.')
50
59
 
51
60
  if domain is None:
52
61
  domain = random_domain()
53
62
 
54
63
  if shuffle_exercises:
55
64
  random.shuffle(errors)
65
+
66
+
67
+ dav_tools.messages.info(f'Starting assignment generation for {len(supported_errors)} exercises (out of {len(errors)} requested)')
56
68
 
57
69
  # convert SqlErrors -> SqlErrorRequirements, keeping difficulty levels
58
- requirements: list[tuple[SqlErrors, SqlErrorRequirements, DifficultyLevel]] = []
59
- for error, difficulty in errors:
60
- if error not in ERROR_REQUIREMENTS_MAP:
61
- raise NotImplementedError(f'Error requirements not implemented for error: {error.name}')
62
-
63
- requirements.append((error, ERROR_REQUIREMENTS_MAP[error], difficulty))
70
+ requirements: list[tuple[SqlErrors, SqlErrorRequirements, DifficultyLevel]] = [(error, ERROR_REQUIREMENTS_MAP[error], difficulty) for error, difficulty in supported_errors]
64
71
 
65
72
  # initialize requirements and extra details
66
73
  dataset_requirements: list[SchemaConstraint] = []
@@ -126,7 +133,7 @@ def generate_assignment(
126
133
  return (idx, None)
127
134
 
128
135
  # Pre-allocate so we can preserve ordering no matter completion order.
129
- ordered_results: list[Exercise | None] = [None] * len(errors)
136
+ ordered_results: list[Exercise | None] = [None] * len(supported_errors)
130
137
 
131
138
  if max_workers == 1:
132
139
  for idx, (error, requirement, difficulty) in enumerate(requirements):
@@ -144,10 +151,10 @@ def generate_assignment(
144
151
 
145
152
  exercises: list[Exercise] = [ex for ex in ordered_results if ex is not None]
146
153
 
147
- if len(exercises) < len(errors):
148
- dav_tools.messages.warning(f'Finished generating exercises with some failures. Generated {len(exercises)} out of {len(errors)} requested.')
154
+ if len(exercises) < len(supported_errors):
155
+ dav_tools.messages.warning(f'Finished generating exercises with some failures. Generated: {len(exercises)}. Unsupported: {len(errors) - len(supported_errors)}. Failed: {len(supported_errors) - len(exercises)}.')
149
156
  else:
150
- dav_tools.messages.success(f'Successfully generated all {len(exercises)} exercises.')
157
+ dav_tools.messages.success(f'Successfully generated all {len(exercises)} exercises. Unsupported: {len(errors) - len(supported_errors)}.')
151
158
 
152
159
  return Assignment(
153
160
  dataset=dataset,
@@ -14,6 +14,7 @@ if __name__ == '__main__':
14
14
  # change these values as needed
15
15
  domain = None
16
16
  errors = [
17
+ (SqlErrors.SYN_22_OMITTING_THE_SEMICOLON, DifficultyLevel.EASY),
17
18
  (SqlErrors.SYN_2_AMBIGUOUS_COLUMN, DifficultyLevel.EASY),
18
19
  ]*3
19
20