Open Ofghanirre opened 1 year ago
Il faudrait faire un lien avec l'existant pour faire le format de réponse sur la base de donnée.
https://github.com/PlatonOrg/platon/blob/main/libs/feature/player/server/src/lib/player.dto.ts
Hello ! Du coup voici le code produis jusque là:
Il y a une version tirée des interfaces PLaTon Une version réalisé originellement sur PL, améliorée à l'occasion
Le schéma des inclusions est le suivant:
On a toujours besoin d'aborder là façon d'obtenir l'activity_id, il me semble que sur platon, c'est plus facile que sur PL
from typing import List
from sqlalchemy import create_engine, inspect
from sqlalchemy.orm import sessionmaker
from sqlalchemy.orm import declarative_base
from sqlalchemy import Text, Integer, ForeignKey, String, PickleType, Date
from sqlalchemy.orm import Mapped
from sqlalchemy.orm import mapped_column, relationship
__Base__ = declarative_base()
# TODO replace this value ?
activity_id = 42
def get_session(table_class, base, db_url = "activities-db", db_name = "activity_db", db_user = "activity_user", db_password = "Dimz80k7X97!"):
engine = create_engine(f"postgresql://{db_user}:{db_password}@{db_url}/{db_name}")
if not inspect(engine).has_table(table_class.__tablename__):
base.metadata.create_all(engine)
return sessionmaker(bind=engine)()
# --------------------------------------------------------------
# BASE COMPONENT
# --------------------------------------------------------------
# Version based off PLaTon ts interface
class ExercisePLayer(__Base__):
__tablename__ = f"db_wc_response_default_{activity_id}"
ressource_type : Mapped[str]= mapped_column(String)
answerId : Mapped[str] = mapped_column(String)
sessionId : Mapped[str] = mapped_column(String)
startedAt : Mapped[Date] = mapped_column(Date)
lastGradedAt : Mapped[Date] = mapped_column(Date)
form : Mapped[str] = mapped_column(String)
title : Mapped[str] = mapped_column(String)
statement: Mapped[str] = mapped_column(String)
hints: Mapped[PickleType] = mapped_column(PickleType) # List[String]
author: Mapped[str] = mapped_column(String)
correction: Mapped[PickleType] = mapped_column(PickleType) # {grade: number, authorId: string, createdAt: Date, updatedAt: Date}
remainingAttemps: Mapped[int] = mapped_column(Integer)
solution: Mapped[str] = mapped_column(String)
settings: Mapped[str] = mapped_column(String)
feedbacks: Mapped[PickleType] = mapped_column(PickleType) # List[{type: string, content: string}]
theories: Mapped[PickleType] = mapped_column(PickleType) # {url : string, title: string}
# For polymorphism
type: Mapped[str] = mapped_column(String)
__mapper_args__ = {
"polymorphic_identity": "WCResponse",
"polymorphic_on": "type",
}
# Custom version
class WCResponse(__Base__):
"""
This class is the super class embodying the response at a db format
It contains all properties that are shared through out the webComponents
of PLaTon
"""
base = __Base__
__tablename__ = f"db_wc_response_default_{activity_id}"
id : Mapped[int] = mapped_column(primary_key=True)
usr_id : Mapped[int] = mapped_column(Integer)
exc_id : Mapped[int] = mapped_column(Integer)
# User Informations:
usr_username : Mapped[str] = mapped_column(String)
usr_firstname : Mapped[str] = mapped_column(String)
usr_lastname : Mapped[str] = mapped_column(String)
usr_email : Mapped[str] = mapped_column(String)
# Exercise Informations:
exc_title : Mapped[str] = mapped_column(String)
exc_text : Mapped[Text] = mapped_column(Text)
# Grade value:
grade : Mapped[int] = mapped_column(Integer)
feedback : Mapped[Text] = mapped_column(Text)
# For polymorphism
__type__: Mapped[str] = mapped_column(String)
__mapper_args__ = {
"polymorphic_identity": "Response",
"polymorphic_on": "__type__",
}
######################
def __str__(self):
return f"{self.usr_username}[{self.usr_id}] a obtenu un score de {self.grade} sur l'exercice {self.exc_id}."
# --------------------------------------------------------------
# FORMAT RESPONSE COMPONENT
# --------------------------------------------------------------
class WCResponseInput(WCResponse):
__tablename__ = f"db_wc_response_input_{activity_id}"
__mapper_args__ = {
"polymorphic_identity": "ResponseInput",
}
id: Mapped[int] = mapped_column(ForeignKey(f"db_wc_response_default_{activity_id}.id"), primary_key=True)
input : Mapped[str] = mapped_column(String)
class WCResponseInputSelect(WCResponse):
__tablename__ = f"db_wc_response_inputSelect_{activity_id}"
__mapper_args__ = {
"polymorphic_identity": "ResponseInput",
}
id: Mapped[int] = mapped_column(ForeignKey(f"db_wc_response_default_{activity_id}.id"), primary_key=True)
input : Mapped[PickleType] = mapped_column(PickleType) # List[{label: string, score: number}]
class WCResponseSelectAssign(WCResponse):
__tablename__ = f"db_wc_response_selectAssign_{activity_id}"
__mapper_args__ = {
"polymorphic_identity": "ResponseInput",
}
id: Mapped[int] = mapped_column(ForeignKey(f"db_wc_response_default_{activity_id}.id"), primary_key=True)
input : Mapped[PickleType] = mapped_column(PickleType) # List[{label: string, score: string}]
# --------------------------------------------------------------
# WEB COMPONENT RESPONSE
# --------------------------------------------------------------
class WCResponseAutomatonEditor(WCResponse):
__tablename__ = f"db_wc_response_AutomatonEditor_{activity_id}"
class WCResponseDragDrop(WCResponse):
__tablename__ = f"db_wc_response_DragDrop_{activity_id}"
class WCResponseJsx(WCResponse):
__tablename__ = f"db_wc_response_Jsx_{activity_id}"
class WCResponseMatrix(WCResponse):
__tablename__ = f"db_wc_response_Matrix_{activity_id}"
class WCResponseTextSelect(WCResponse):
__tablename__ = f"db_wc_response_TextSelect_{activity_id}"
# --------
class WCResponseInputBox(WCResponseInput):
__tablename__ = f"db_wc_response_InputBox_{activity_id}"
class WCResponseMathLive(WCResponseInput):
__tablename__ = f"db_wc_response_MathLive_{activity_id}"
# --------
class WCResponseCodeEditor(WCResponseInput):
__tablename__ = f"db_wc_response_CodeEditor_{activity_id}"
__mapper_args__ = {
"polymorphic_identity": "ResponseCodeEditor",
}
id: Mapped[int] = mapped_column(ForeignKey(f"db_wc_response_input_{activity_id}.id"), primary_key=True)
language : Mapped[str] = mapped_column(String)
# --------
class WCResponseRadioGroup(WCResponseInputSelect):
__tablename__ = f"db_wc_response_InputSelect_{activity_id}"
class WCResponseSortList(WCResponseInputSelect):
__tablename__ = f"db_wc_response_InputSelect_{activity_id}"
class WCResponseCheckboxGroup(WCResponseInputSelect):
__tablename__ = f"db_wc_response_CheckboxGroup_{activity_id}"
# --------
class WCResponseMatchList(WCResponseSelectAssign):
__tablename__ = f"db_wc_response_MatchList_{activity_id}"
Pour les mappers, je propose ce format pour les mappers version Python
On pourra ainsi laisser chacun créer ses propres mappers, avec un nom, une description, et une fonction de mapping qui peut être appliqué sur une méthode map_data
class WCMapper():
def __init__(self, name: str, description: str, mapping_function):
"""
Constructor for a WCMapper, need to be defined with a name, a description (markdown format), and a mapping function
taking a single argument
:param name: The mapper name
:param description: The mapper description (markdown allowed)
:param mapping_function: The mapping function, taking a single parameter
"""
self.mapping_function = mapping_function
self.description = description
self.name = name
def call(self, x):
"""
Function to be called upon a mapping operation for a webComponent
Default is identity: x -> x
:param x: the element for the mapping
:return: the mapped element
"""
return self.mapping_function(x)
def __repr__(self):
return (self.name, self.mapping_function)
def __str__(self):
return f"<WebComponentMapper: {self.name}>\n\nDescription:\n{self.description}"
def map_data(wcmapper: WCMapper, data: list | set):
return list(map(wcmapper.call, data))
Deux problèmatique diférentes: -> la génération de données pour les stats -> l'affichage des réponses pour les corrections.
I. PRESENTATION
Format d'une réponse sur la base:
number
number
string
number
number
Array<Reponse>
Format d'une réponse
Une réponse possèdera toujours des champs tels:
À cela s'ajoute des champs spécifiques aux composants utilisés...
Format d'une réponse en fonction du type de composant
On distingue des composants qui pour l'instant, n'ont pas de champs en plus
On distingue ensuite d'autres composants qui stockent des données de type spécifiques, identifiables comme des familles
string
string
string
Array<selection_unit>
selection_unit
:string
number
Array<assignment_unit>
assignment_unit
:string
string
II. ARGUMENTATION
L'idée derrière ces structures est de pouvoir représenter facilement les données des réponses d'exercices en base afin de pouvoir plus tard, traiter facilement les données à l'aide de graphe, csv et analytics. Le format des données étant variable, il sera nécéssaire de créer des mappers permettant d'uniformiser le format des données et de les adapters pour chaque type de graphe.
Il sera donc plus en amont nécessaire de réaliser des mappers (sur des fichiers PL / Python) permettant la traduction de données BDD en données graphe
Si vous avez des éléments à ajouter ou des questions, n'hésitez pas à les proposers!