-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add src/2023/2023-10-30-tests-for-migration-for-merging-solutions.ipynb
- Loading branch information
Showing
1 changed file
with
265 additions
and
0 deletions.
There are no files selected for viewing
265 changes: 265 additions & 0 deletions
265
src/2023/2023-10-30-tests-for-migration-for-merging-solutions.ipynb
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,265 @@ | ||
{ | ||
"cells": [ | ||
{ | ||
"cell_type": "code", | ||
"execution_count": 40, | ||
"id": "157389d2", | ||
"metadata": {}, | ||
"outputs": [], | ||
"source": [ | ||
"from sqlalchemy import create_engine\n", | ||
"from sqlalchemy import text\n", | ||
"\n", | ||
"#engine_remote = create_engine(\n", | ||
"# f\"mysql+mysqlconnector://serlo:{PASSWORD}@localhost:7777/serlo?charset=utf8mb4\"\n", | ||
"#)\n", | ||
"\n", | ||
"engine_local = create_engine(\n", | ||
" f\"mysql+mysqlconnector://root:secret@localhost:3306/serlo?charset=latin1\"\n", | ||
")\n", | ||
"\n", | ||
"class MySQLSession:\n", | ||
" def __init__(self, engine):\n", | ||
" self.engine = engine\n", | ||
" \n", | ||
" def __enter__(self):\n", | ||
" self.connection = self.engine.connect()\n", | ||
" return self\n", | ||
" \n", | ||
" def __exit__(self, *args):\n", | ||
" self.connection.commit()\n", | ||
" self.connection.close()\n", | ||
" \n", | ||
" def execute(self, statement, **kwargs):\n", | ||
" return self.connection.execute(text(statement), kwargs)\n", | ||
"\n", | ||
" def query(self, statement, **kwargs):\n", | ||
" return list(self.execute(statement, **kwargs))\n", | ||
" \n", | ||
" def begin(self):\n", | ||
" return self.connection.begin()\n", | ||
" \n", | ||
"with MySQLSession(engine_local) as session:\n", | ||
" pass" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": 7, | ||
"id": "b68146a7", | ||
"metadata": {}, | ||
"outputs": [], | ||
"source": [ | ||
"EXAMPLE_ENTITY_ID=54210" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": 15, | ||
"id": "e643d031", | ||
"metadata": {}, | ||
"outputs": [ | ||
{ | ||
"name": "stdout", | ||
"output_type": "stream", | ||
"text": [ | ||
"[54227]\n" | ||
] | ||
} | ||
], | ||
"source": [ | ||
"def select_first(row):\n", | ||
" assert len(row) == 1\n", | ||
"\n", | ||
" return row[0]\n", | ||
"\n", | ||
"def select_first_elements(elements):\n", | ||
" return [select_first(e) for e in elements]\n", | ||
"\n", | ||
"def get_children(session, entity_id, child_type):\n", | ||
" return select_first_elements(session.query(\"\"\"\n", | ||
" select child_id\n", | ||
" from entity_link\n", | ||
" join entity child on child.id = entity_link.child_id\n", | ||
" join type child_type on child_type.id = child.type_id\n", | ||
" where parent_id = :parent_id and child_type.name = :child_type\n", | ||
" \"\"\", parent_id=entity_id, child_type=child_type))\n", | ||
"\n", | ||
"with MySQLSession(engine_local) as session:\n", | ||
" print(get_children(session, EXAMPLE_ENTITY_ID, \"text-solution\"))" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": 17, | ||
"id": "70ca37d1", | ||
"metadata": {}, | ||
"outputs": [ | ||
{ | ||
"name": "stdout", | ||
"output_type": "stream", | ||
"text": [ | ||
"182709\n" | ||
] | ||
} | ||
], | ||
"source": [ | ||
"def get_current_revision(session, entity_id):\n", | ||
" result = session.query(\"\"\"\n", | ||
" select current_revision_id from entity where id = :entity_id\n", | ||
" \"\"\", entity_id = entity_id)\n", | ||
" \n", | ||
" return select_first(select_first(result))\n", | ||
"\n", | ||
"with MySQLSession(engine_local) as session:\n", | ||
" print(get_current_revision(session, EXAMPLE_ENTITY_ID))" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": 22, | ||
"id": "d01103d5", | ||
"metadata": {}, | ||
"outputs": [ | ||
{ | ||
"name": "stdout", | ||
"output_type": "stream", | ||
"text": [ | ||
"{'plugin': 'exercise', 'state': {'content': {'plugin': 'rows', 'state': [{'plugin': 'text', 'state': [{'type': 'p', 'children': [{'text': 'Ordne folgendem Graphen die richtige Funktionsgleichung zu:'}]}]}, {'plugin': 'image', 'state': {'src': 'https://assets.serlo.org/legacy/56e92eda3e891_00804a4cae5eaff522ae3b59cf859b06ca6a47b0.png', 'alt': 'Graph', 'caption': {'plugin': 'text', 'state': [{'type': 'p', 'children': [{}]}]}}}]}, 'interactive': {'plugin': 'scMcExercise', 'state': {'isSingleChoice': True, 'answers': [{'content': {'plugin': 'text', 'state': [{'type': 'p', 'children': [{'text': ''}, {'type': 'math', 'src': 'f(x)=4\\\\cdot\\\\sin(x)', 'inline': True, 'children': [{'text': 'f(x)=4\\\\cdot\\\\sin(x)'}]}, {'text': ''}]}]}, 'isCorrect': True, 'feedback': {'plugin': 'text', 'state': [{'type': 'p', 'children': [{'text': 'Richtig! Der Nobelpreis ist ganz nah ;-)'}]}]}}, {'content': {'plugin': 'text', 'state': [{'type': 'p', 'children': [{'text': ''}, {'type': 'math', 'src': 'f(x)=4\\\\cdot\\\\cos(x)', 'inline': True, 'children': [{'text': 'f(x)=4\\\\cdot\\\\cos(x)'}]}, {'text': ''}]}]}, 'isCorrect': False, 'feedback': {'plugin': 'text', 'state': [{'type': 'p', 'children': [{'text': 'Leider falsch! Du denkst wahrscheinlich schon in die richtige Richtung, aber schaue dir noch einmal die Unterschiede der '}, {'type': 'a', 'href': '/1909', 'children': [{'text': 'trigonometrischen Funktionen'}]}, {'text': ' an.'}]}]}}, {'content': {'plugin': 'text', 'state': [{'type': 'p', 'children': [{'text': ''}, {'type': 'math', 'src': 'f(x)=5\\\\cdot\\\\cos(x)', 'inline': True, 'children': [{'text': 'f(x)=5\\\\cdot\\\\cos(x)'}]}, {'text': ''}]}]}, 'isCorrect': False, 'feedback': {'plugin': 'text', 'state': [{'type': 'p', 'children': [{'text': 'Da solltest du noch einmal nachdenken. Die Funktionsgleichung hat leider so gar nichts mit dem Graphen zu tun!'}]}]}}, {'content': {'plugin': 'text', 'state': [{'type': 'p', 'children': [{'text': ''}, {'type': 'math', 'src': 'f(x)=12\\\\cdot\\\\sin(x)', 'inline': True, 'children': [{'text': 'f(x)=12\\\\cdot\\\\sin(x)'}]}, {'text': ''}]}]}, 'isCorrect': False, 'feedback': {'plugin': 'text', 'state': [{'type': 'p', 'children': [{'text': 'Leider falsch! Du hast mit der Sinus-Funktion schon den richtigen Riecher. Allerdings ist mal '}, {'type': 'math', 'src': '12', 'inline': True, 'children': [{'text': '12'}]}, {'text': ' falsch. Schau mal, wie weit die Kurve auf der y-Achse ausschlägt.'}]}]}}]}}}}\n" | ||
] | ||
} | ||
], | ||
"source": [ | ||
"import json\n", | ||
"\n", | ||
"def get_content(session, revision_id):\n", | ||
" result = session.query(\"\"\"\n", | ||
" select value from entity_revision_field where entity_revision_id = :revision_id\n", | ||
" and field=\"content\"\n", | ||
" \"\"\", revision_id=revision_id)\n", | ||
" \n", | ||
" return json.loads(select_first(select_first(result)))\n", | ||
"\n", | ||
"with MySQLSession(engine_local) as session:\n", | ||
" print(get_content(session, 182709))" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": 25, | ||
"id": "8608cb13", | ||
"metadata": {}, | ||
"outputs": [ | ||
{ | ||
"name": "stdout", | ||
"output_type": "stream", | ||
"text": [ | ||
"182709\n" | ||
] | ||
} | ||
], | ||
"source": [ | ||
"def get_license_id(session, entity_id):\n", | ||
" result = session.query(\"\"\"\n", | ||
" select license_id from entity where id = :entity_id\n", | ||
" \"\"\", entity_id = entity_id)\n", | ||
" \n", | ||
" return select_first(select_first(result))\n", | ||
"\n", | ||
"with MySQLSession(engine_local) as session:\n", | ||
" print(get_current_revision(session, EXAMPLE_ENTITY_ID))" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": 41, | ||
"id": "93e2b106", | ||
"metadata": {}, | ||
"outputs": [ | ||
{ | ||
"name": "stdout", | ||
"output_type": "stream", | ||
"text": [ | ||
"updated: 182709\n" | ||
] | ||
} | ||
], | ||
"source": [ | ||
"has_state = lambda x: \"state\" in x and isinstance(x[\"state\"], dict)\n", | ||
"\n", | ||
"def update_exercise(session, exercise_id):\n", | ||
" solution_id = select_first(get_children(session, exercise_id, \"text-solution\"))\n", | ||
" \n", | ||
" exercise_revision_id = get_current_revision(session, exercise_id)\n", | ||
" solution_revision_id = get_current_revision(session, solution_id)\n", | ||
" \n", | ||
" exercise_content = get_content(session, exercise_revision_id)\n", | ||
" solution_content = get_content(session, solution_revision_id) \n", | ||
" \n", | ||
" exercise_license_id = get_license_id(session, exercise_id)\n", | ||
" solution_license_id = get_license_id(session, solution_id)\n", | ||
" \n", | ||
" assert has_state(solution_content)\n", | ||
" \n", | ||
" if solution_license_id != exercise_license_id:\n", | ||
" solution_content[\"state\"][\"licenseId\"] = solution_license_id\n", | ||
" \n", | ||
" assert has_state(exercise_content) and exercise_content[\"plugin\"] == \"exercise\"\n", | ||
" \n", | ||
" if \"solution\" not in exercise_content[\"state\"]:\n", | ||
" exercise_content[\"state\"][\"solution\"] = solution_content\n", | ||
" \n", | ||
" session.execute(\"\"\"\n", | ||
" update entity_revision_field set value = :content\n", | ||
" where entity_revision_id = :revision_id\n", | ||
" and field=\"content\" \n", | ||
" \"\"\", revision_id = exercise_revision_id, content=json.dumps(exercise_content, indent=2))\n", | ||
" \n", | ||
" print(\"updated: \", exercise_revision_id)\n", | ||
" \n", | ||
"with MySQLSession(engine_local) as session:\n", | ||
" update_exercise(session, 54210)" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": 42, | ||
"id": "aa53ac4d", | ||
"metadata": {}, | ||
"outputs": [ | ||
{ | ||
"name": "stdout", | ||
"output_type": "stream", | ||
"text": [ | ||
"updated: 170171\n" | ||
] | ||
} | ||
], | ||
"source": [ | ||
"with MySQLSession(engine_local) as session:\n", | ||
" update_exercise(session, 10129)" | ||
] | ||
} | ||
], | ||
"metadata": { | ||
"kernelspec": { | ||
"display_name": "Python 3", | ||
"language": "python", | ||
"name": "python3" | ||
}, | ||
"language_info": { | ||
"codemirror_mode": { | ||
"name": "ipython", | ||
"version": 3 | ||
}, | ||
"file_extension": ".py", | ||
"mimetype": "text/x-python", | ||
"name": "python", | ||
"nbconvert_exporter": "python", | ||
"pygments_lexer": "ipython3", | ||
"version": "3.9.1" | ||
} | ||
}, | ||
"nbformat": 4, | ||
"nbformat_minor": 5 | ||
} |