tests
This commit is contained in:
parent
43031d22fb
commit
4941b5a154
|
@ -0,0 +1,9 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module type="JAVA_MODULE" version="4">
|
||||
<component name="NewModuleRootManager" inherit-compiler-output="true">
|
||||
<exclude-output />
|
||||
<content url="file://$MODULE_DIR$" />
|
||||
<orderEntry type="inheritedJdk" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
</component>
|
||||
</module>
|
|
@ -0,0 +1,8 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ProjectModuleManager">
|
||||
<modules>
|
||||
<module fileurl="file://$PROJECT_DIR$/.idea/fastapi_gen.iml" filepath="$PROJECT_DIR$/.idea/fastapi_gen.iml" />
|
||||
</modules>
|
||||
</component>
|
||||
</project>
|
|
@ -0,0 +1,6 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="VcsDirectoryMappings">
|
||||
<mapping directory="" vcs="Git" />
|
||||
</component>
|
||||
</project>
|
|
@ -0,0 +1,84 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ChangeListManager">
|
||||
<list default="true" id="a539d37a-9d57-43b3-91cf-30110de7e657" name="Changes" comment="">
|
||||
<change beforePath="$PROJECT_DIR$/backend/api/database/db.py" beforeDir="false" afterPath="$PROJECT_DIR$/backend/api/database/db.py" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/backend/api/database/exercices/models.py" beforeDir="false" afterPath="$PROJECT_DIR$/backend/api/database/exercices/models.py" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/backend/api/database/room/crud.py" beforeDir="false" afterPath="$PROJECT_DIR$/backend/api/database/room/crud.py" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/backend/api/database/room/models.py" beforeDir="false" afterPath="$PROJECT_DIR$/backend/api/database/room/models.py" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/backend/api/generateur/generateur_main.py" beforeDir="false" afterPath="$PROJECT_DIR$/backend/api/generateur/generateur_main.py" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/backend/api/main.py" beforeDir="false" afterPath="$PROJECT_DIR$/backend/api/main.py" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/backend/api/routes/auth/routes.py" beforeDir="false" afterPath="$PROJECT_DIR$/backend/api/routes/auth/routes.py" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/backend/api/routes/exercices/routes.py" beforeDir="false" afterPath="$PROJECT_DIR$/backend/api/routes/exercices/routes.py" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/backend/api/routes/room/consumer.py" beforeDir="false" afterPath="$PROJECT_DIR$/backend/api/routes/room/consumer.py" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/backend/api/routes/room/manager.py" beforeDir="false" afterPath="$PROJECT_DIR$/backend/api/routes/room/manager.py" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/backend/api/routes/room/routes.py" beforeDir="false" afterPath="$PROJECT_DIR$/backend/api/routes/room/routes.py" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/backend/api/services/websocket.py" beforeDir="false" afterPath="$PROJECT_DIR$/backend/api/services/websocket.py" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/backend/api/tests/test_exos.py" beforeDir="false" afterPath="$PROJECT_DIR$/backend/api/tests/test_exos.py" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/backend/api/tests/test_room.py" beforeDir="false" afterPath="$PROJECT_DIR$/backend/api/tests/test_room.py" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/backend/api/tests/testing_exo_source/exo_source_web_only.py" beforeDir="false" afterPath="$PROJECT_DIR$/backend/api/tests/testing_exo_source/exo_source_web_only.py" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/frontend/package.json" beforeDir="false" afterPath="$PROJECT_DIR$/frontend/package.json" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/frontend/pnpm-lock.yaml" beforeDir="false" afterPath="$PROJECT_DIR$/frontend/pnpm-lock.yaml" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/frontend/src/apis/exo.api.ts" beforeDir="false" afterPath="$PROJECT_DIR$/frontend/src/apis/exo.api.ts" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/frontend/src/app.scss" beforeDir="false" afterPath="$PROJECT_DIR$/frontend/src/app.scss" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/frontend/src/components/exos/Card.svelte" beforeDir="false" afterPath="$PROJECT_DIR$/frontend/src/components/exos/Card.svelte" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/frontend/src/components/exos/CreateCard.svelte" beforeDir="false" afterPath="$PROJECT_DIR$/frontend/src/components/exos/CreateCard.svelte" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/frontend/src/components/exos/DownloadForm.svelte" beforeDir="false" afterPath="$PROJECT_DIR$/frontend/src/components/exos/DownloadForm.svelte" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/frontend/src/components/exos/EditForm.svelte" beforeDir="false" afterPath="$PROJECT_DIR$/frontend/src/components/exos/EditForm.svelte" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/frontend/src/components/exos/Feed.svelte" beforeDir="false" afterPath="$PROJECT_DIR$/frontend/src/components/exos/Feed.svelte" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/frontend/src/components/exos/Head.svelte" beforeDir="false" afterPath="$PROJECT_DIR$/frontend/src/components/exos/Head.svelte" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/frontend/src/components/exos/Pagination.svelte" beforeDir="false" afterPath="$PROJECT_DIR$/frontend/src/components/exos/Pagination.svelte" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/frontend/src/components/exos/Tag.svelte" beforeDir="false" afterPath="$PROJECT_DIR$/frontend/src/components/exos/Tag.svelte" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/frontend/src/components/exos/TagContainer.svelte" beforeDir="false" afterPath="$PROJECT_DIR$/frontend/src/components/exos/TagContainer.svelte" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/frontend/src/components/forms/FileInput.svelte" beforeDir="false" afterPath="$PROJECT_DIR$/frontend/src/components/forms/FileInput.svelte" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/frontend/src/components/forms/InputWithLabel.svelte" beforeDir="false" afterPath="$PROJECT_DIR$/frontend/src/components/forms/InputWithLabel.svelte" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/frontend/src/components/forms/Item.svelte" beforeDir="false" afterPath="$PROJECT_DIR$/frontend/src/components/forms/Item.svelte" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/frontend/src/components/forms/TagSelector.svelte" beforeDir="false" afterPath="$PROJECT_DIR$/frontend/src/components/forms/TagSelector.svelte" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/frontend/src/context/Auth.svelte" beforeDir="false" afterPath="$PROJECT_DIR$/frontend/src/context/Auth.svelte" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/frontend/src/context/Modal.svelte" beforeDir="false" afterPath="$PROJECT_DIR$/frontend/src/context/Modal.svelte" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/frontend/src/context/Navigation.svelte" beforeDir="false" afterPath="$PROJECT_DIR$/frontend/src/context/Navigation.svelte" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/frontend/src/requests/auth.request.ts" beforeDir="false" afterPath="$PROJECT_DIR$/frontend/src/requests/auth.request.ts" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/frontend/src/routes/+layout.svelte" beforeDir="false" afterPath="$PROJECT_DIR$/frontend/src/routes/+layout.svelte" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/frontend/src/routes/+page.svelte" beforeDir="false" afterPath="$PROJECT_DIR$/frontend/src/routes/+page.svelte" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/frontend/src/routes/exercices/[[slug]]/+page.svelte" beforeDir="false" afterPath="$PROJECT_DIR$/frontend/src/routes/exercices/[[slug]]/+page.svelte" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/frontend/src/routes/signup/+page.svelte" beforeDir="false" afterPath="$PROJECT_DIR$/frontend/src/routes/signup/+page.svelte" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/frontend/src/types/exo.type.ts" beforeDir="false" afterPath="$PROJECT_DIR$/frontend/src/types/exo.type.ts" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/frontend/src/utils/forms.ts" beforeDir="false" afterPath="$PROJECT_DIR$/frontend/src/utils/forms.ts" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/frontend/src/utils/utils.ts" beforeDir="false" afterPath="$PROJECT_DIR$/frontend/src/utils/utils.ts" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/frontend/src/variables.scss" beforeDir="false" afterPath="$PROJECT_DIR$/frontend/src/variables.scss" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/frontend/vite.config.js" beforeDir="false" afterPath="$PROJECT_DIR$/frontend/vite.config.js" afterDir="false" />
|
||||
</list>
|
||||
<option name="SHOW_DIALOG" value="false" />
|
||||
<option name="HIGHLIGHT_CONFLICTS" value="true" />
|
||||
<option name="HIGHLIGHT_NON_ACTIVE_CHANGELIST" value="false" />
|
||||
<option name="LAST_RESOLUTION" value="IGNORE" />
|
||||
</component>
|
||||
<component name="Git.Settings">
|
||||
<option name="RECENT_GIT_ROOT_PATH" value="$PROJECT_DIR$" />
|
||||
</component>
|
||||
<component name="ProjectId" id="2LnGvp3nb4X9GdPKgjfvgSHhKvw" />
|
||||
<component name="ProjectViewState">
|
||||
<option name="hideEmptyMiddlePackages" value="true" />
|
||||
<option name="showLibraryContents" value="true" />
|
||||
</component>
|
||||
<component name="PropertiesComponent"><![CDATA[{
|
||||
"keyToString": {
|
||||
"RunOnceActivity.OpenProjectViewOnStart": "true",
|
||||
"RunOnceActivity.ShowReadmeOnStart": "true",
|
||||
"WebServerToolWindowFactoryState": "false",
|
||||
"vue.rearranger.settings.migration": "true"
|
||||
}
|
||||
}]]></component>
|
||||
<component name="SpellCheckerSettings" RuntimeDictionaries="0" Folders="0" CustomDictionaries="0" DefaultDictionary="application-level" UseSingleDictionary="true" transferred="true" />
|
||||
<component name="TaskManager">
|
||||
<task active="true" id="Default" summary="Default task">
|
||||
<changelist id="a539d37a-9d57-43b3-91cf-30110de7e657" name="Changes" comment="" />
|
||||
<created>1676499669960</created>
|
||||
<option name="number" value="Default" />
|
||||
<option name="presentableId" value="Default" />
|
||||
<updated>1676499669960</updated>
|
||||
<workItem from="1676499673827" duration="6000" />
|
||||
</task>
|
||||
<servers />
|
||||
</component>
|
||||
</project>
|
|
@ -0,0 +1,8 @@
|
|||
# Default ignored files
|
||||
/shelf/
|
||||
/workspace.xml
|
||||
# Editor-based HTTP Client requests
|
||||
/httpRequests/
|
||||
# Datasource local storage ignored files
|
||||
/dataSources/
|
||||
/dataSources.local.xml
|
|
@ -0,0 +1,11 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module type="JAVA_MODULE" version="4">
|
||||
<component name="NewModuleRootManager" inherit-compiler-output="true">
|
||||
<exclude-output />
|
||||
<content url="file://$MODULE_DIR$">
|
||||
<excludeFolder url="file://$MODULE_DIR$/venv" />
|
||||
</content>
|
||||
<orderEntry type="inheritedJdk" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
</component>
|
||||
</module>
|
|
@ -0,0 +1,5 @@
|
|||
<component name="ProjectCodeStyleConfiguration">
|
||||
<state>
|
||||
<option name="PREFERRED_PROJECT_CODE_STYLE" value="Default" />
|
||||
</state>
|
||||
</component>
|
|
@ -0,0 +1,24 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="DataSourceManagerImpl" format="xml" multifile-model="true">
|
||||
<data-source source="LOCAL" name="database" uuid="384abd64-7cbf-4b69-a4ff-253dfdd48393">
|
||||
<driver-ref>sqlite.xerial</driver-ref>
|
||||
<synchronize>true</synchronize>
|
||||
<jdbc-driver>org.sqlite.JDBC</jdbc-driver>
|
||||
<jdbc-url>jdbc:sqlite:$PROJECT_DIR$/database.db</jdbc-url>
|
||||
<working-dir>$ProjectFileDir$</working-dir>
|
||||
</data-source>
|
||||
<data-source source="LOCAL" name="database7" uuid="a2cbf379-d945-498f-a48c-23b53a5d1d5f">
|
||||
<driver-ref>sqlite.xerial</driver-ref>
|
||||
<synchronize>true</synchronize>
|
||||
<jdbc-driver>org.sqlite.JDBC</jdbc-driver>
|
||||
<jdbc-url>jdbc:sqlite:$PROJECT_DIR$/database7.db</jdbc-url>
|
||||
<working-dir>$ProjectFileDir$</working-dir>
|
||||
<libraries>
|
||||
<library>
|
||||
<url>file://$APPLICATION_CONFIG_DIR$/jdbc-drivers/Xerial SQLiteJDBC/3.39.2/sqlite-jdbc-3.39.2.jar</url>
|
||||
</library>
|
||||
</libraries>
|
||||
</data-source>
|
||||
</component>
|
||||
</project>
|
|
@ -0,0 +1,423 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="DBNavigator.Project.DataEditorManager">
|
||||
<record-view-column-sorting-type value="BY_INDEX" />
|
||||
<value-preview-text-wrapping value="false" />
|
||||
<value-preview-pinned value="false" />
|
||||
</component>
|
||||
<component name="DBNavigator.Project.DatabaseEditorStateManager">
|
||||
<last-used-providers />
|
||||
</component>
|
||||
<component name="DBNavigator.Project.DatabaseFileManager">
|
||||
<open-files />
|
||||
</component>
|
||||
<component name="DBNavigator.Project.ExecutionManager">
|
||||
<retain-sticky-names value="false" />
|
||||
</component>
|
||||
<component name="DBNavigator.Project.Settings">
|
||||
<connections />
|
||||
<browser-settings>
|
||||
<general>
|
||||
<display-mode value="TABBED" />
|
||||
<navigation-history-size value="100" />
|
||||
<show-object-details value="false" />
|
||||
</general>
|
||||
<filters>
|
||||
<object-type-filter>
|
||||
<object-type name="SCHEMA" enabled="true" />
|
||||
<object-type name="USER" enabled="true" />
|
||||
<object-type name="ROLE" enabled="true" />
|
||||
<object-type name="PRIVILEGE" enabled="true" />
|
||||
<object-type name="CHARSET" enabled="true" />
|
||||
<object-type name="TABLE" enabled="true" />
|
||||
<object-type name="VIEW" enabled="true" />
|
||||
<object-type name="MATERIALIZED_VIEW" enabled="true" />
|
||||
<object-type name="NESTED_TABLE" enabled="true" />
|
||||
<object-type name="COLUMN" enabled="true" />
|
||||
<object-type name="INDEX" enabled="true" />
|
||||
<object-type name="CONSTRAINT" enabled="true" />
|
||||
<object-type name="DATASET_TRIGGER" enabled="true" />
|
||||
<object-type name="DATABASE_TRIGGER" enabled="true" />
|
||||
<object-type name="SYNONYM" enabled="true" />
|
||||
<object-type name="SEQUENCE" enabled="true" />
|
||||
<object-type name="PROCEDURE" enabled="true" />
|
||||
<object-type name="FUNCTION" enabled="true" />
|
||||
<object-type name="PACKAGE" enabled="true" />
|
||||
<object-type name="TYPE" enabled="true" />
|
||||
<object-type name="TYPE_ATTRIBUTE" enabled="true" />
|
||||
<object-type name="ARGUMENT" enabled="true" />
|
||||
<object-type name="DIMENSION" enabled="true" />
|
||||
<object-type name="CLUSTER" enabled="true" />
|
||||
<object-type name="DBLINK" enabled="true" />
|
||||
</object-type-filter>
|
||||
</filters>
|
||||
<sorting>
|
||||
<object-type name="COLUMN" sorting-type="NAME" />
|
||||
<object-type name="FUNCTION" sorting-type="NAME" />
|
||||
<object-type name="PROCEDURE" sorting-type="NAME" />
|
||||
<object-type name="ARGUMENT" sorting-type="POSITION" />
|
||||
<object-type name="TYPE ATTRIBUTE" sorting-type="POSITION" />
|
||||
</sorting>
|
||||
<default-editors>
|
||||
<object-type name="VIEW" editor-type="SELECTION" />
|
||||
<object-type name="PACKAGE" editor-type="SELECTION" />
|
||||
<object-type name="TYPE" editor-type="SELECTION" />
|
||||
</default-editors>
|
||||
</browser-settings>
|
||||
<navigation-settings>
|
||||
<lookup-filters>
|
||||
<lookup-objects>
|
||||
<object-type name="SCHEMA" enabled="true" />
|
||||
<object-type name="USER" enabled="false" />
|
||||
<object-type name="ROLE" enabled="false" />
|
||||
<object-type name="PRIVILEGE" enabled="false" />
|
||||
<object-type name="CHARSET" enabled="false" />
|
||||
<object-type name="TABLE" enabled="true" />
|
||||
<object-type name="VIEW" enabled="true" />
|
||||
<object-type name="MATERIALIZED VIEW" enabled="true" />
|
||||
<object-type name="INDEX" enabled="true" />
|
||||
<object-type name="CONSTRAINT" enabled="true" />
|
||||
<object-type name="DATASET TRIGGER" enabled="true" />
|
||||
<object-type name="DATABASE TRIGGER" enabled="true" />
|
||||
<object-type name="SYNONYM" enabled="false" />
|
||||
<object-type name="SEQUENCE" enabled="true" />
|
||||
<object-type name="PROCEDURE" enabled="true" />
|
||||
<object-type name="FUNCTION" enabled="true" />
|
||||
<object-type name="PACKAGE" enabled="true" />
|
||||
<object-type name="TYPE" enabled="true" />
|
||||
<object-type name="DIMENSION" enabled="false" />
|
||||
<object-type name="CLUSTER" enabled="false" />
|
||||
<object-type name="DBLINK" enabled="true" />
|
||||
</lookup-objects>
|
||||
<force-database-load value="false" />
|
||||
<prompt-connection-selection value="true" />
|
||||
<prompt-schema-selection value="true" />
|
||||
</lookup-filters>
|
||||
</navigation-settings>
|
||||
<dataset-grid-settings>
|
||||
<general>
|
||||
<enable-zooming value="true" />
|
||||
<enable-column-tooltip value="true" />
|
||||
</general>
|
||||
<sorting>
|
||||
<nulls-first value="true" />
|
||||
<max-sorting-columns value="4" />
|
||||
</sorting>
|
||||
<audit-columns>
|
||||
<column-names value="" />
|
||||
<visible value="true" />
|
||||
<editable value="false" />
|
||||
</audit-columns>
|
||||
</dataset-grid-settings>
|
||||
<dataset-editor-settings>
|
||||
<text-editor-popup>
|
||||
<active value="false" />
|
||||
<active-if-empty value="false" />
|
||||
<data-length-threshold value="100" />
|
||||
<popup-delay value="1000" />
|
||||
</text-editor-popup>
|
||||
<values-actions-popup>
|
||||
<show-popup-button value="true" />
|
||||
<element-count-threshold value="1000" />
|
||||
<data-length-threshold value="250" />
|
||||
</values-actions-popup>
|
||||
<general>
|
||||
<fetch-block-size value="100" />
|
||||
<fetch-timeout value="30" />
|
||||
<trim-whitespaces value="true" />
|
||||
<convert-empty-strings-to-null value="true" />
|
||||
<select-content-on-cell-edit value="true" />
|
||||
<large-value-preview-active value="true" />
|
||||
</general>
|
||||
<filters>
|
||||
<prompt-filter-dialog value="true" />
|
||||
<default-filter-type value="BASIC" />
|
||||
</filters>
|
||||
<qualified-text-editor text-length-threshold="300">
|
||||
<content-types>
|
||||
<content-type name="Text" enabled="true" />
|
||||
<content-type name="Properties" enabled="true" />
|
||||
<content-type name="XML" enabled="true" />
|
||||
<content-type name="DTD" enabled="true" />
|
||||
<content-type name="HTML" enabled="true" />
|
||||
<content-type name="XHTML" enabled="true" />
|
||||
<content-type name="CSS" enabled="true" />
|
||||
<content-type name="Java" enabled="true" />
|
||||
<content-type name="SQL" enabled="true" />
|
||||
<content-type name="PL/SQL" enabled="true" />
|
||||
<content-type name="JavaScript" enabled="true" />
|
||||
<content-type name="JSON" enabled="true" />
|
||||
<content-type name="JSON5" enabled="true" />
|
||||
<content-type name="JSP" enabled="true" />
|
||||
<content-type name="JSPx" enabled="true" />
|
||||
<content-type name="Groovy" enabled="true" />
|
||||
<content-type name="FTL" enabled="true" />
|
||||
<content-type name="VTL" enabled="true" />
|
||||
<content-type name="AIDL" enabled="true" />
|
||||
<content-type name="YAML" enabled="true" />
|
||||
<content-type name="Manifest" enabled="true" />
|
||||
</content-types>
|
||||
</qualified-text-editor>
|
||||
<record-navigation>
|
||||
<navigation-target value="VIEWER" />
|
||||
</record-navigation>
|
||||
</dataset-editor-settings>
|
||||
<code-editor-settings>
|
||||
<general>
|
||||
<show-object-navigation-gutter value="false" />
|
||||
<show-spec-declaration-navigation-gutter value="true" />
|
||||
<enable-spellchecking value="true" />
|
||||
<enable-reference-spellchecking value="false" />
|
||||
</general>
|
||||
<confirmations>
|
||||
<save-changes value="false" />
|
||||
<revert-changes value="true" />
|
||||
</confirmations>
|
||||
</code-editor-settings>
|
||||
<code-completion-settings>
|
||||
<filters>
|
||||
<basic-filter>
|
||||
<filter-element type="RESERVED_WORD" id="keyword" selected="true" />
|
||||
<filter-element type="RESERVED_WORD" id="function" selected="true" />
|
||||
<filter-element type="RESERVED_WORD" id="parameter" selected="true" />
|
||||
<filter-element type="RESERVED_WORD" id="datatype" selected="true" />
|
||||
<filter-element type="RESERVED_WORD" id="exception" selected="true" />
|
||||
<filter-element type="OBJECT" id="schema" selected="true" />
|
||||
<filter-element type="OBJECT" id="role" selected="true" />
|
||||
<filter-element type="OBJECT" id="user" selected="true" />
|
||||
<filter-element type="OBJECT" id="privilege" selected="true" />
|
||||
<user-schema>
|
||||
<filter-element type="OBJECT" id="table" selected="true" />
|
||||
<filter-element type="OBJECT" id="view" selected="true" />
|
||||
<filter-element type="OBJECT" id="materialized view" selected="true" />
|
||||
<filter-element type="OBJECT" id="index" selected="true" />
|
||||
<filter-element type="OBJECT" id="constraint" selected="true" />
|
||||
<filter-element type="OBJECT" id="trigger" selected="true" />
|
||||
<filter-element type="OBJECT" id="synonym" selected="false" />
|
||||
<filter-element type="OBJECT" id="sequence" selected="true" />
|
||||
<filter-element type="OBJECT" id="procedure" selected="true" />
|
||||
<filter-element type="OBJECT" id="function" selected="true" />
|
||||
<filter-element type="OBJECT" id="package" selected="true" />
|
||||
<filter-element type="OBJECT" id="type" selected="true" />
|
||||
<filter-element type="OBJECT" id="dimension" selected="true" />
|
||||
<filter-element type="OBJECT" id="cluster" selected="true" />
|
||||
<filter-element type="OBJECT" id="dblink" selected="true" />
|
||||
</user-schema>
|
||||
<public-schema>
|
||||
<filter-element type="OBJECT" id="table" selected="false" />
|
||||
<filter-element type="OBJECT" id="view" selected="false" />
|
||||
<filter-element type="OBJECT" id="materialized view" selected="false" />
|
||||
<filter-element type="OBJECT" id="index" selected="false" />
|
||||
<filter-element type="OBJECT" id="constraint" selected="false" />
|
||||
<filter-element type="OBJECT" id="trigger" selected="false" />
|
||||
<filter-element type="OBJECT" id="synonym" selected="false" />
|
||||
<filter-element type="OBJECT" id="sequence" selected="false" />
|
||||
<filter-element type="OBJECT" id="procedure" selected="false" />
|
||||
<filter-element type="OBJECT" id="function" selected="false" />
|
||||
<filter-element type="OBJECT" id="package" selected="false" />
|
||||
<filter-element type="OBJECT" id="type" selected="false" />
|
||||
<filter-element type="OBJECT" id="dimension" selected="false" />
|
||||
<filter-element type="OBJECT" id="cluster" selected="false" />
|
||||
<filter-element type="OBJECT" id="dblink" selected="false" />
|
||||
</public-schema>
|
||||
<any-schema>
|
||||
<filter-element type="OBJECT" id="table" selected="true" />
|
||||
<filter-element type="OBJECT" id="view" selected="true" />
|
||||
<filter-element type="OBJECT" id="materialized view" selected="true" />
|
||||
<filter-element type="OBJECT" id="index" selected="true" />
|
||||
<filter-element type="OBJECT" id="constraint" selected="true" />
|
||||
<filter-element type="OBJECT" id="trigger" selected="true" />
|
||||
<filter-element type="OBJECT" id="synonym" selected="true" />
|
||||
<filter-element type="OBJECT" id="sequence" selected="true" />
|
||||
<filter-element type="OBJECT" id="procedure" selected="true" />
|
||||
<filter-element type="OBJECT" id="function" selected="true" />
|
||||
<filter-element type="OBJECT" id="package" selected="true" />
|
||||
<filter-element type="OBJECT" id="type" selected="true" />
|
||||
<filter-element type="OBJECT" id="dimension" selected="true" />
|
||||
<filter-element type="OBJECT" id="cluster" selected="true" />
|
||||
<filter-element type="OBJECT" id="dblink" selected="true" />
|
||||
</any-schema>
|
||||
</basic-filter>
|
||||
<extended-filter>
|
||||
<filter-element type="RESERVED_WORD" id="keyword" selected="true" />
|
||||
<filter-element type="RESERVED_WORD" id="function" selected="true" />
|
||||
<filter-element type="RESERVED_WORD" id="parameter" selected="true" />
|
||||
<filter-element type="RESERVED_WORD" id="datatype" selected="true" />
|
||||
<filter-element type="RESERVED_WORD" id="exception" selected="true" />
|
||||
<filter-element type="OBJECT" id="schema" selected="true" />
|
||||
<filter-element type="OBJECT" id="user" selected="true" />
|
||||
<filter-element type="OBJECT" id="role" selected="true" />
|
||||
<filter-element type="OBJECT" id="privilege" selected="true" />
|
||||
<user-schema>
|
||||
<filter-element type="OBJECT" id="table" selected="true" />
|
||||
<filter-element type="OBJECT" id="view" selected="true" />
|
||||
<filter-element type="OBJECT" id="materialized view" selected="true" />
|
||||
<filter-element type="OBJECT" id="index" selected="true" />
|
||||
<filter-element type="OBJECT" id="constraint" selected="true" />
|
||||
<filter-element type="OBJECT" id="trigger" selected="true" />
|
||||
<filter-element type="OBJECT" id="synonym" selected="true" />
|
||||
<filter-element type="OBJECT" id="sequence" selected="true" />
|
||||
<filter-element type="OBJECT" id="procedure" selected="true" />
|
||||
<filter-element type="OBJECT" id="function" selected="true" />
|
||||
<filter-element type="OBJECT" id="package" selected="true" />
|
||||
<filter-element type="OBJECT" id="type" selected="true" />
|
||||
<filter-element type="OBJECT" id="dimension" selected="true" />
|
||||
<filter-element type="OBJECT" id="cluster" selected="true" />
|
||||
<filter-element type="OBJECT" id="dblink" selected="true" />
|
||||
</user-schema>
|
||||
<public-schema>
|
||||
<filter-element type="OBJECT" id="table" selected="true" />
|
||||
<filter-element type="OBJECT" id="view" selected="true" />
|
||||
<filter-element type="OBJECT" id="materialized view" selected="true" />
|
||||
<filter-element type="OBJECT" id="index" selected="true" />
|
||||
<filter-element type="OBJECT" id="constraint" selected="true" />
|
||||
<filter-element type="OBJECT" id="trigger" selected="true" />
|
||||
<filter-element type="OBJECT" id="synonym" selected="true" />
|
||||
<filter-element type="OBJECT" id="sequence" selected="true" />
|
||||
<filter-element type="OBJECT" id="procedure" selected="true" />
|
||||
<filter-element type="OBJECT" id="function" selected="true" />
|
||||
<filter-element type="OBJECT" id="package" selected="true" />
|
||||
<filter-element type="OBJECT" id="type" selected="true" />
|
||||
<filter-element type="OBJECT" id="dimension" selected="true" />
|
||||
<filter-element type="OBJECT" id="cluster" selected="true" />
|
||||
<filter-element type="OBJECT" id="dblink" selected="true" />
|
||||
</public-schema>
|
||||
<any-schema>
|
||||
<filter-element type="OBJECT" id="table" selected="true" />
|
||||
<filter-element type="OBJECT" id="view" selected="true" />
|
||||
<filter-element type="OBJECT" id="materialized view" selected="true" />
|
||||
<filter-element type="OBJECT" id="index" selected="true" />
|
||||
<filter-element type="OBJECT" id="constraint" selected="true" />
|
||||
<filter-element type="OBJECT" id="trigger" selected="true" />
|
||||
<filter-element type="OBJECT" id="synonym" selected="true" />
|
||||
<filter-element type="OBJECT" id="sequence" selected="true" />
|
||||
<filter-element type="OBJECT" id="procedure" selected="true" />
|
||||
<filter-element type="OBJECT" id="function" selected="true" />
|
||||
<filter-element type="OBJECT" id="package" selected="true" />
|
||||
<filter-element type="OBJECT" id="type" selected="true" />
|
||||
<filter-element type="OBJECT" id="dimension" selected="true" />
|
||||
<filter-element type="OBJECT" id="cluster" selected="true" />
|
||||
<filter-element type="OBJECT" id="dblink" selected="true" />
|
||||
</any-schema>
|
||||
</extended-filter>
|
||||
</filters>
|
||||
<sorting enabled="true">
|
||||
<sorting-element type="RESERVED_WORD" id="keyword" />
|
||||
<sorting-element type="RESERVED_WORD" id="datatype" />
|
||||
<sorting-element type="OBJECT" id="column" />
|
||||
<sorting-element type="OBJECT" id="table" />
|
||||
<sorting-element type="OBJECT" id="view" />
|
||||
<sorting-element type="OBJECT" id="materialized view" />
|
||||
<sorting-element type="OBJECT" id="index" />
|
||||
<sorting-element type="OBJECT" id="constraint" />
|
||||
<sorting-element type="OBJECT" id="trigger" />
|
||||
<sorting-element type="OBJECT" id="synonym" />
|
||||
<sorting-element type="OBJECT" id="sequence" />
|
||||
<sorting-element type="OBJECT" id="procedure" />
|
||||
<sorting-element type="OBJECT" id="function" />
|
||||
<sorting-element type="OBJECT" id="package" />
|
||||
<sorting-element type="OBJECT" id="type" />
|
||||
<sorting-element type="OBJECT" id="dimension" />
|
||||
<sorting-element type="OBJECT" id="cluster" />
|
||||
<sorting-element type="OBJECT" id="dblink" />
|
||||
<sorting-element type="OBJECT" id="schema" />
|
||||
<sorting-element type="OBJECT" id="role" />
|
||||
<sorting-element type="OBJECT" id="user" />
|
||||
<sorting-element type="RESERVED_WORD" id="function" />
|
||||
<sorting-element type="RESERVED_WORD" id="parameter" />
|
||||
</sorting>
|
||||
<format>
|
||||
<enforce-code-style-case value="true" />
|
||||
</format>
|
||||
</code-completion-settings>
|
||||
<execution-engine-settings>
|
||||
<statement-execution>
|
||||
<fetch-block-size value="100" />
|
||||
<execution-timeout value="20" />
|
||||
<debug-execution-timeout value="600" />
|
||||
<focus-result value="false" />
|
||||
<prompt-execution value="false" />
|
||||
</statement-execution>
|
||||
<script-execution>
|
||||
<command-line-interfaces />
|
||||
<execution-timeout value="300" />
|
||||
</script-execution>
|
||||
<method-execution>
|
||||
<execution-timeout value="30" />
|
||||
<debug-execution-timeout value="600" />
|
||||
<parameter-history-size value="10" />
|
||||
</method-execution>
|
||||
</execution-engine-settings>
|
||||
<operation-settings>
|
||||
<transactions>
|
||||
<uncommitted-changes>
|
||||
<on-project-close value="ASK" />
|
||||
<on-disconnect value="ASK" />
|
||||
<on-autocommit-toggle value="ASK" />
|
||||
</uncommitted-changes>
|
||||
<multiple-uncommitted-changes>
|
||||
<on-commit value="ASK" />
|
||||
<on-rollback value="ASK" />
|
||||
</multiple-uncommitted-changes>
|
||||
</transactions>
|
||||
<session-browser>
|
||||
<disconnect-session value="ASK" />
|
||||
<kill-session value="ASK" />
|
||||
<reload-on-filter-change value="false" />
|
||||
</session-browser>
|
||||
<compiler>
|
||||
<compile-type value="KEEP" />
|
||||
<compile-dependencies value="ASK" />
|
||||
<always-show-controls value="false" />
|
||||
</compiler>
|
||||
<debugger>
|
||||
<debugger-type value="ASK" />
|
||||
<use-generic-runners value="true" />
|
||||
</debugger>
|
||||
</operation-settings>
|
||||
<ddl-file-settings>
|
||||
<extensions>
|
||||
<mapping file-type-id="VIEW" extensions="vw" />
|
||||
<mapping file-type-id="TRIGGER" extensions="trg" />
|
||||
<mapping file-type-id="PROCEDURE" extensions="prc" />
|
||||
<mapping file-type-id="FUNCTION" extensions="fnc" />
|
||||
<mapping file-type-id="PACKAGE" extensions="pkg" />
|
||||
<mapping file-type-id="PACKAGE_SPEC" extensions="pks" />
|
||||
<mapping file-type-id="PACKAGE_BODY" extensions="pkb" />
|
||||
<mapping file-type-id="TYPE" extensions="tpe" />
|
||||
<mapping file-type-id="TYPE_SPEC" extensions="tps" />
|
||||
<mapping file-type-id="TYPE_BODY" extensions="tpb" />
|
||||
</extensions>
|
||||
<general>
|
||||
<lookup-ddl-files value="true" />
|
||||
<create-ddl-files value="false" />
|
||||
<synchronize-ddl-files value="true" />
|
||||
<use-qualified-names value="false" />
|
||||
<make-scripts-rerunnable value="true" />
|
||||
</general>
|
||||
</ddl-file-settings>
|
||||
<general-settings>
|
||||
<regional-settings>
|
||||
<date-format value="MEDIUM" />
|
||||
<number-format value="UNGROUPED" />
|
||||
<locale value="SYSTEM_DEFAULT" />
|
||||
<use-custom-formats value="false" />
|
||||
</regional-settings>
|
||||
<environment>
|
||||
<environment-types>
|
||||
<environment-type id="development" name="Development" description="Development environment" color="-2430209/-12296320" readonly-code="false" readonly-data="false" />
|
||||
<environment-type id="integration" name="Integration" description="Integration environment" color="-2621494/-12163514" readonly-code="true" readonly-data="false" />
|
||||
<environment-type id="production" name="Production" description="Productive environment" color="-11574/-10271420" readonly-code="true" readonly-data="true" />
|
||||
<environment-type id="other" name="Other" description="" color="-1576/-10724543" readonly-code="false" readonly-data="false" />
|
||||
</environment-types>
|
||||
<visibility-settings>
|
||||
<connection-tabs value="true" />
|
||||
<dialog-headers value="true" />
|
||||
<object-editor-tabs value="true" />
|
||||
<script-editor-tabs value="false" />
|
||||
<execution-result-tabs value="true" />
|
||||
</visibility-settings>
|
||||
</environment>
|
||||
</general-settings>
|
||||
</component>
|
||||
</project>
|
|
@ -0,0 +1,6 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_19" project-jdk-name="Python 3.10 (env)" project-jdk-type="Python SDK">
|
||||
<output url="file://$PROJECT_DIR$/out" />
|
||||
</component>
|
||||
</project>
|
|
@ -0,0 +1,8 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ProjectModuleManager">
|
||||
<modules>
|
||||
<module fileurl="file://$PROJECT_DIR$/.idea/api.iml" filepath="$PROJECT_DIR$/.idea/api.iml" />
|
||||
</modules>
|
||||
</component>
|
||||
</project>
|
|
@ -0,0 +1,6 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="VcsDirectoryMappings">
|
||||
<mapping directory="$PROJECT_DIR$/../.." vcs="Git" />
|
||||
</component>
|
||||
</project>
|
|
@ -1,9 +1,14 @@
|
|||
import uuid
|
||||
from services.password import get_password_hash
|
||||
from database.auth.models import User, UserEdit
|
||||
from sqlmodel import Session, select
|
||||
|
||||
from jose import jwt, exceptions
|
||||
from sqlmodel import Session, select
|
||||
|
||||
from config import SECRET_KEY, ALGORITHM
|
||||
from database.auth.models import User, UserEdit
|
||||
from database.room.models import Member
|
||||
from services.password import get_password_hash
|
||||
|
||||
|
||||
def create_user_db(username:str , password: str, db: Session):
|
||||
user = User(username=username, hashed_password=password, clientId=uuid.uuid4())
|
||||
db.add(user)
|
||||
|
@ -84,3 +89,7 @@ def change_user_uuid(id: int, db: Session):
|
|||
db.refresh(user)
|
||||
return user.clientId
|
||||
|
||||
|
||||
def parse_user_rooms(user: User, db: Session):
|
||||
members = db.exec(select(Member).where(Member.user_id == user.id)).all()
|
||||
return [{"name": m.room.name, "id_code": m.room.id_code, "admin": m.is_admin} for m in members]
|
||||
|
|
|
@ -1,9 +1,11 @@
|
|||
from typing import List, Optional
|
||||
import uuid
|
||||
from typing import List
|
||||
from typing import TYPE_CHECKING, Optional
|
||||
from uuid import UUID
|
||||
import uuid
|
||||
from sqlmodel import Field, SQLModel, Relationship
|
||||
|
||||
from pydantic import validator, BaseModel
|
||||
from sqlmodel import Field, SQLModel, Relationship
|
||||
|
||||
from services.password import validate_password
|
||||
from services.schema import as_form
|
||||
|
||||
|
@ -29,9 +31,16 @@ class User(UserBase, table=True):
|
|||
@as_form
|
||||
class UserEdit(UserBase):
|
||||
pass
|
||||
|
||||
class UsersRoom(BaseModel):
|
||||
name: str
|
||||
id_code: str
|
||||
admin: bool = False
|
||||
class UserRead(UserBase):
|
||||
id: int
|
||||
rooms: List[UsersRoom] = []
|
||||
class UserEditRead(UserBase):
|
||||
id: int
|
||||
#rooms: List[UsersRoom] = []
|
||||
|
||||
|
||||
@as_form
|
||||
|
|
|
@ -2,7 +2,7 @@ import pydantic.json
|
|||
import json
|
||||
from sqlmodel import SQLModel, create_engine, Session, select
|
||||
|
||||
sqlite_file_name = "database.db"
|
||||
sqlite_file_name = "database7.db"
|
||||
sqlite_url = f"sqlite:///{sqlite_file_name}"
|
||||
|
||||
|
||||
|
@ -19,6 +19,6 @@ def create_db_and_tables():
|
|||
SQLModel.metadata.create_all(engine)
|
||||
|
||||
def get_session():
|
||||
with Session(engine) as s:
|
||||
with Session(engine, expire_on_commit=False) as s:
|
||||
yield s
|
||||
|
||||
|
|
|
@ -18,7 +18,7 @@ if TYPE_CHECKING:
|
|||
from database.auth.models import User
|
||||
|
||||
|
||||
class ExampleEnum(Enum):
|
||||
class ExampleEnum(str, Enum):
|
||||
csv = 'csv'
|
||||
pdf = 'pdf'
|
||||
web = 'web'
|
||||
|
|
|
@ -1,17 +1,21 @@
|
|||
from services.auth import get_current_user_optional
|
||||
from services.misc import noteOn20
|
||||
from copy import deepcopy
|
||||
from typing import Dict, List
|
||||
import uuid
|
||||
from fastapi import Body, Depends, HTTPException, status
|
||||
from copy import deepcopy
|
||||
from typing import List
|
||||
|
||||
from fastapi import Depends, HTTPException, status, Query
|
||||
from pydantic import BaseModel
|
||||
from sqlmodel import Session, delete, select, col, table
|
||||
from database.db import get_session
|
||||
from database.room.models import Anonymous, Challenge, Challenges, CorrigedGeneratorOut, Exercices, ExercicesCreate, Member, Note, Parcours, ParcoursCreate, ParcoursReadShort, ParsedGeneratorOut, Room, RoomCreate, RoomInfo, RoomRead, TmpCorrection, Waiter, MemberRead
|
||||
from database.auth.models import User
|
||||
from services.database import generate_unique_code
|
||||
from sqlalchemy import func
|
||||
from sqlmodel import Session, delete, select, col
|
||||
|
||||
from database.auth.crud import get_user_from_token
|
||||
from database.auth.models import User
|
||||
from database.db import get_session
|
||||
from database.exercices.models import Exercice
|
||||
from database.room.models import Anonymous, Challenge, Challenges, CorrigedGeneratorOut, Exercices, ExercicesCreate, \
|
||||
Member, Note, Parcours, ParcoursCreate, ParcoursReadShort, ParsedGeneratorOut, Room, RoomCreate, RoomInfo, \
|
||||
TmpCorrection, Waiter, MemberRead, CorrigedData, CorrectionData, Challenger
|
||||
from services.auth import get_current_user_optional
|
||||
from services.database import generate_unique_code
|
||||
|
||||
|
||||
def create_room_db(*, room: RoomCreate, user: User | None = None, username: str | None = None, db: Session):
|
||||
|
@ -38,12 +42,15 @@ def create_room_db(*, room: RoomCreate, user: User | None = None, username: str
|
|||
|
||||
return {"room": room_obj, "member": member}
|
||||
|
||||
|
||||
def change_room_name(room: Room, name: str, db: Session):
|
||||
room.name = name
|
||||
db.add(room)
|
||||
db.commit()
|
||||
db.refresh(room)
|
||||
return room
|
||||
|
||||
|
||||
def change_room_status(room: Room, public: bool, db: Session):
|
||||
room.public = public
|
||||
db.add(room)
|
||||
|
@ -51,6 +58,7 @@ def change_room_status(room: Room, public: bool, db: Session):
|
|||
db.refresh(room)
|
||||
return room
|
||||
|
||||
|
||||
def get_member_from_user(user_id: int, room_id: int, db: Session):
|
||||
member = db.exec(select(Member).where(Member.room_id ==
|
||||
room_id, Member.user_id == user_id)).first()
|
||||
|
@ -86,6 +94,7 @@ def get_anonymous_from_code(reconnect_code: str, db: Session):
|
|||
Anonymous.reconnect_code == reconnect_code)).first()
|
||||
return anonymous
|
||||
|
||||
|
||||
def get_anonymous_from_clientId(clientId: str, db: Session):
|
||||
anonymous = db.exec(select(Anonymous).where(
|
||||
Anonymous.clientId == clientId)).first()
|
||||
|
@ -102,20 +111,23 @@ def get_member_from_clientId(clientId: str, room_id: int, db: Session):
|
|||
|
||||
def create_member(*, room: Room, user: User | None = None, anonymous: Anonymous | None = None, waiting: bool = False, db: Session):
|
||||
member_id = generate_unique_code(Member, s=db)
|
||||
member = Member(room=room, user=user, anonymous=anonymous, waiting=waiting,
|
||||
member = Member(room=room, user=user, anonymous=anonymous, waiting=waiting,
|
||||
id_code=member_id)
|
||||
member.online = True
|
||||
db.add(member)
|
||||
db.commit()
|
||||
db.refresh(member)
|
||||
return member
|
||||
|
||||
|
||||
def get_or_create_member(*, room: Room, user: User | None = None, anonymous: Anonymous | None = None, waiting: bool = False, db: Session):
|
||||
member = user is not None and get_member_from_user(user.id, room.id, db)
|
||||
def get_or_create_member(*, room: Room, user: User | None = None, anonymous: Anonymous | None = None,
|
||||
waiting: bool = False, db: Session):
|
||||
member = user is not None and get_member_from_user(user.id, room.id, db)
|
||||
if member is not None and member is not False:
|
||||
return member
|
||||
member= create_member(room=room, user=user, anonymous=anonymous, waiting=waiting, db=db)
|
||||
|
||||
member = create_member(room=room, user=user,
|
||||
anonymous=anonymous, waiting=waiting, db=db)
|
||||
|
||||
|
||||
def connect_member(member: Member, db: Session):
|
||||
member.online = True
|
||||
|
@ -128,10 +140,10 @@ def connect_member(member: Member, db: Session):
|
|||
def disconnect_member(member: Member, db: Session):
|
||||
if member.waiting == False:
|
||||
member.online = False
|
||||
|
||||
|
||||
if member.anonymous is not None:
|
||||
change_anonymous_clientId(member.anonymous,db)
|
||||
|
||||
change_anonymous_clientId(member.anonymous, db)
|
||||
|
||||
db.add(member)
|
||||
db.commit()
|
||||
db.refresh(member)
|
||||
|
@ -167,6 +179,7 @@ def create_anonymous_member(username: str, room: Room, db: Session):
|
|||
db.refresh(member)
|
||||
return member
|
||||
|
||||
|
||||
def create_anonymous(username: str, room: Room, db: Session):
|
||||
username = validate_username(username, room, db)
|
||||
if username is None:
|
||||
|
@ -179,10 +192,13 @@ def create_anonymous(username: str, room: Room, db: Session):
|
|||
db.refresh(anonymous)
|
||||
return anonymous
|
||||
|
||||
|
||||
def check_user_in_room(user_id: int, room_id: int, db: Session):
|
||||
user = db.exec(select(Member).where(Member.user_id==user_id, Member.room_id == room_id)).first()
|
||||
user = db.exec(select(Member).where(Member.user_id ==
|
||||
user_id, Member.room_id == room_id)).first()
|
||||
return user
|
||||
|
||||
|
||||
def create_user_member(user: User, room: Room, db: Session):
|
||||
member = get_member_from_user(user.id, room.id, db)
|
||||
if member is not None:
|
||||
|
@ -194,6 +210,7 @@ def create_user_member(user: User, room: Room, db: Session):
|
|||
db.refresh(member)
|
||||
return member
|
||||
|
||||
|
||||
def create_anonymous_waiter(username: str, room: Room, db: Session):
|
||||
username = validate_username(username, room, db)
|
||||
if username is None:
|
||||
|
@ -210,6 +227,7 @@ def create_anonymous_waiter(username: str, room: Room, db: Session):
|
|||
db.refresh(member)
|
||||
return member
|
||||
|
||||
|
||||
def create_user_waiter(user: User, room: Room, db: Session):
|
||||
member = get_member_from_user(user.id, room.id, db)
|
||||
if member is not None:
|
||||
|
@ -219,6 +237,7 @@ def create_user_waiter(user: User, room: Room, db: Session):
|
|||
db=db)
|
||||
return member
|
||||
|
||||
|
||||
def get_waiter(waiter_code: str, db: Session):
|
||||
return db.exec(select(Member).where(Member.id_code == waiter_code, Member.waiting == True)).first()
|
||||
|
||||
|
@ -236,6 +255,7 @@ def delete_member(member: Member, db: Session):
|
|||
def accept_waiter(member: Member, db: Session):
|
||||
member.waiting = False
|
||||
member.waiter_code = None
|
||||
member.online = True
|
||||
db.add(member)
|
||||
db.commit()
|
||||
db.refresh(member)
|
||||
|
@ -254,39 +274,173 @@ def leave_room(member: Member, db: Session):
|
|||
return None
|
||||
|
||||
|
||||
|
||||
def serialize_member(member: Member) -> MemberRead | Waiter:
|
||||
def serialize_member(member: Member, private: bool = False, admin: bool = False,
|
||||
m2: Member | None = None) -> MemberRead | Waiter:
|
||||
member_obj = member.user or member.anonymous
|
||||
if member.waiting == False:
|
||||
return MemberRead(username=member_obj.username, reconnect_code=getattr(member_obj, "reconnect_code", ""), isUser=member.user_id != None, isAdmin=member.is_admin, id_code=member.id_code).dict()
|
||||
if member.waiting == True:
|
||||
print("OHLA", member_obj, private, member.user_id == None)
|
||||
if not member.waiting:
|
||||
return MemberRead(username=member_obj.username, online=member.online,
|
||||
clientId=str(member_obj.clientId) if (private == True and member.user_id == None) else "",
|
||||
reconnect_code=getattr(member_obj, "reconnect_code", "") if (admin or m2 == member) else "",
|
||||
isUser=member.user_id != None, isAdmin=member.is_admin, id_code=member.id_code).dict()
|
||||
if member.waiting:
|
||||
return Waiter(username=member_obj.username, waiter_id=member.id_code).dict()
|
||||
|
||||
|
||||
def serialize_parcours_short(parcours: Parcours, member: Member, db: Session):
|
||||
best_note = db.exec(select(Challenge.note, Challenge.time).where(Challenge.parcours_id == parcours.id, Challenge.challenger_id == member.id).order_by(col(Challenge.note).desc()).limit(1)).first()
|
||||
note = None
|
||||
if best_note is not None:
|
||||
best_note=best_note[0]
|
||||
note = Note(note=best_note[0], time=best_note[1])
|
||||
return ParcoursReadShort(**parcours.dict(exclude_unset=True), best_note=note)
|
||||
challenger = getChallenger(parcours, member, db)
|
||||
|
||||
return ParcoursReadShort(name=parcours.name, id_code=parcours.id_code, best_note=challenger.best,
|
||||
validated=challenger.validated)
|
||||
|
||||
|
||||
def serialize_challenge(challenge: Challenge):
|
||||
return Challenges(name=challenge.challenger.user.username if challenge.challenger.user is not None else challenge.challenger.anonymous.username, value=Note(note=challenge.note, time=challenge.time), isCorriged=challenge.isCorriged, canCorrige=challenge.data is not None)
|
||||
return Challenges(
|
||||
name=challenge.challenger.user.username if challenge.challenger.user is not None else challenge.challenger.anonymous.username,
|
||||
value=Note(note=challenge.note, time=challenge.time), isCorriged=challenge.isCorriged,
|
||||
canCorrige=challenge.data is not None)
|
||||
|
||||
def serialize_parcours_short(parcours: Parcours, member: Member, db: Session):
|
||||
if member.is_member == False:
|
||||
challenges = db.exec(select(Challenge).where(Challenge.parcours_id == parcours.id, Challenge.challenger_id == member.id)).all()
|
||||
else:
|
||||
challenges = db.exec(select(Challenge).where(
|
||||
Challenge.parcours_id == parcours.id)).all()
|
||||
|
||||
challenges = [serialize_challenge(c) for c in challenges]
|
||||
return Parcours(**parcours.dict(), challenges=challenges)
|
||||
|
||||
|
||||
|
||||
def serialize_room(room: Room, member: Member, db: Session):
|
||||
return RoomInfo(**room.dict(), parcours=[serialize_parcours_short(p, member, db) for p in room.parcours], members=[serialize_member(m) for m in room.members])
|
||||
return RoomInfo(**room.dict(), parcours=[serialize_parcours_short(p, member, db) for p in room.parcours],
|
||||
members=[serialize_member(m, admin=member.is_admin, m2=member) for m in room.members])
|
||||
|
||||
|
||||
def getUsername(m: Member):
|
||||
return m.user.username if m.user is not None else m.anonymous.username
|
||||
|
||||
|
||||
def getChallengerInfo(c: Challenge, db: Session):
|
||||
challenger = db.exec(select(Challenger).where(Challenger.member_id ==
|
||||
c.challenger_mid, Challenger.parcours_id == c.challenger_pid)).first()
|
||||
if challenger is not None:
|
||||
member = challenger.member
|
||||
return {"name": getUsername(member), "id_code": member.id_code}
|
||||
|
||||
|
||||
def getChallenges(c: Challenger, db: Session):
|
||||
challenges = db.exec(select(Challenge).where(Challenge.challenger_mid == c.member_id,
|
||||
Challenge.challenger_pid == c.parcours_id)).all()
|
||||
return challenges
|
||||
|
||||
|
||||
def getTops(p: Parcours, db: Session):
|
||||
tops = db.exec(select(Challenge).where(Challenge.parcours_id == p.id_code).order_by(
|
||||
col(Challenge.mistakes), col(Challenge.time)).limit(3)).all()
|
||||
|
||||
tops = [{"challenger": getChallengerInfo(
|
||||
t, db), "mistakes": t.mistakes, "time": t.time} for t in tops]
|
||||
return tops
|
||||
|
||||
|
||||
def getAvgTops(p: Parcours, db: Session):
|
||||
avgTop = db.exec(select(Challenger).where(Challenger.parcours_id ==
|
||||
p.id).order_by(col(Challenger.avg)).limit(3)).all()
|
||||
|
||||
avgTop = [{"id_code": t.member.id_code, "avg": t.avg,
|
||||
"name": getUsername(t.member)} for t in avgTop]
|
||||
return avgTop
|
||||
|
||||
|
||||
def getRank(c: Challenger, p: Parcours, db: Session):
|
||||
noteRank = db.exec(select([func.count(Challenge.id)]).where(Challenge.parcours_id == p.id_code).order_by(
|
||||
col(Challenge.mistakes), col(Challenge.time)).where(Challenge.mistakes <= c.best,
|
||||
Challenge.time < c.best_time)).one()
|
||||
return noteRank + 1
|
||||
|
||||
|
||||
def getAvgRank(c: Challenger, p: Parcours, db: Session):
|
||||
avgRank = db.exec(select([func.count(Challenger.member_id)]).where(
|
||||
Challenger.parcours_id == p.id).order_by(col(Challenger.avg)).where(Challenger.avg < c.avg)).one()
|
||||
return avgRank + 1
|
||||
|
||||
|
||||
def getMemberRank(m: Member, p: Parcours, db: Session):
|
||||
challenger = db.exec(select(Challenger).where(Challenger.member_id == m.id)).first()
|
||||
if challenger is None or challenger.best is None:
|
||||
return None
|
||||
return getRank(challenger, p, db)
|
||||
|
||||
|
||||
def getMemberAvgRank(m: Member, p: Parcours, db: Session):
|
||||
challenger = db.exec(select(Challenger).where(Challenger.member_id == m.id)).first()
|
||||
print('CHALLE', challenger)
|
||||
if challenger is None or challenger.avg is None:
|
||||
return None
|
||||
return getAvgRank(challenger, p, db)
|
||||
|
||||
|
||||
def serialize_parcours(parcours: Parcours, member: Member, db: Session):
|
||||
tops = getTops(parcours, db)
|
||||
avgTop = getAvgTops(parcours, db)
|
||||
|
||||
challenger = db.exec(select(Challenger).where(
|
||||
Challenger.member_id == member.id, Challenger.parcours_id == parcours.id)).first()
|
||||
|
||||
noteRank = None
|
||||
avgRank = None
|
||||
pb = None
|
||||
if challenger is not None and challenger.avg is not None and challenger.best is not None:
|
||||
noteRank = getRank(challenger, parcours, db)
|
||||
avgRank = getAvgRank(challenger, parcours, db)
|
||||
pb = {"mistakes": challenger.best, "time": challenger.best_time}
|
||||
|
||||
statement = select(Challenger).where(Challenger.parcours_id == parcours.id)
|
||||
if not member.is_admin:
|
||||
statement = statement.where(Challenger.member_id == member.id)
|
||||
|
||||
challengers = db.exec(statement).all()
|
||||
|
||||
challs = {c.member.id_code: {
|
||||
"challenger": {"id_code": c.member.id_code, "name": getUsername(c.member)},
|
||||
# 'validated': chall.mistakes <= parcours.max_mistakes
|
||||
"challenges": [Challenges(**{**chall.dict(), "canCorrige": chall.data != []}) for chall in getChallenges(c, db)]
|
||||
} for c in challengers}
|
||||
|
||||
return {**parcours.dict(), "pb": pb, "tops": tops, "challenges": challs, "rank": noteRank, "memberRank": avgRank,
|
||||
"validated": challenger.validated if challenger != None else False, "ranking": avgTop}
|
||||
tops = []
|
||||
challs = {}
|
||||
challenges = sorted(parcours.challenges, key=lambda x: (
|
||||
x.note['value'], x.time), reverse=True)
|
||||
memberRank = None
|
||||
rank = None
|
||||
pb = None
|
||||
validated = False
|
||||
|
||||
total = 0
|
||||
|
||||
for i, chall in enumerate(challenges):
|
||||
total += chall.note['value']
|
||||
id = chall.challenger.id_code
|
||||
name = chall.challenger.user.username if chall.challenger.user_id != None else chall.challenger.anonymous.username
|
||||
if i <= 2:
|
||||
tops.append({"challenger": {"id_code": id, "name": name},
|
||||
"note": chall.note, "time": chall.time})
|
||||
|
||||
if id == member.id_code:
|
||||
if challs.get(id) is None:
|
||||
rank = i + 1
|
||||
memberRank = len(challs) + 1
|
||||
pb = {"note": chall.note, "time": chall.time}
|
||||
if validated is False and chall.validated:
|
||||
validated = True
|
||||
|
||||
if member.is_admin or chall.challenger.id_code == member.id_code:
|
||||
t = challs.get(id, {"total": 0})['total']
|
||||
challs[id] = {"challenger": {"id_code": id, "name": name
|
||||
}, "challenges": [*challs.get(id, {'challenges': []})['challenges'],
|
||||
Challenges(
|
||||
**{**chall.dict(), "canCorrige": chall.data != []})],
|
||||
"total": t + chall.note['value']}
|
||||
|
||||
topMembers = [{**c['challenger'], "avg": c['total'] /
|
||||
len(c['challenges'])} for id, c in challs.items()]
|
||||
topMembers.sort(key=lambda x: x['avg'], reverse=True)
|
||||
return {**parcours.dict(), "tops": tops, "challenges": challs, "rank": rank, "memberRank": memberRank, "pb": pb,
|
||||
"validated": validated,
|
||||
'avg': None if len(parcours.challenges) == 0 else round(total / len(parcours.challenges), 2),
|
||||
"ranking": topMembers}
|
||||
|
||||
|
||||
def change_anonymous_clientId(anonymous: Anonymous, db: Session):
|
||||
|
@ -298,20 +452,49 @@ def change_anonymous_clientId(anonymous: Anonymous, db: Session):
|
|||
return anonymous
|
||||
|
||||
|
||||
#Parcours
|
||||
def validate_exercices(exos: List[ExercicesCreate], db: Session ):
|
||||
exercices = db.exec(select(Exercice).where(Exercice.web == True).where(col(Exercice.id_code).in_([e.exercice_id for e in exos]))).all()
|
||||
exos_id_list = [e.exercice_id for e in exos]
|
||||
exercices.sort(key=lambda e: exos_id_list.index(e.id_code))
|
||||
return [Exercices(exercice_id=e.id_code, name=e.name, quantity=[ex for ex in exos if ex.exercice_id == e.id_code][0].quantity).dict() for e in exercices]
|
||||
# Parcours
|
||||
from services.io import add_fast_api_root
|
||||
from generateur.generateur_main import generate_from_path, parseGeneratorOut
|
||||
|
||||
def create_parcours_db(parcours: ParcoursCreate,room_id: int, db: Session):
|
||||
|
||||
def countInput(ex: Exercice, q: int):
|
||||
exo = parseGeneratorOut(generate_from_path(add_fast_api_root(
|
||||
ex.exo_source), 1, "web"))
|
||||
return len(exo.inputs) * q
|
||||
|
||||
|
||||
class ExoToCount(BaseModel):
|
||||
ex: Exercice
|
||||
q: int
|
||||
|
||||
|
||||
def getTotal(exs: list[ExoToCount]):
|
||||
total = 0
|
||||
for e in exs:
|
||||
total += countInput(e.ex, e.q)
|
||||
return total
|
||||
|
||||
|
||||
def validate_exercices(exos: List[ExercicesCreate], db: Session):
|
||||
exercices = db.exec(select(Exercice).where(Exercice.web == True).where(
|
||||
col(Exercice.id_code).in_([e.exercice_id for e in exos]))).all()
|
||||
exos_id_list = [e.exercice_id for e in exos]
|
||||
# exoToCountList = [ExoToCount(ex=e, q=q) for e, q in zip(exercices, [c.quantity for c in exos])]
|
||||
exercices.sort(key=lambda e: exos_id_list.index(e.id_code))
|
||||
return [Exercices(exercice_id=e.id_code, name=e.name,
|
||||
quantity=[ex for ex in exos if ex.exercice_id == e.id_code][0].quantity,
|
||||
examples=e.examples).dict() for e in exercices]
|
||||
|
||||
|
||||
def create_parcours_db(parcours: ParcoursCreate, room_id: int, db: Session):
|
||||
exercices = validate_exercices(parcours.exercices, db)
|
||||
if len(exercices) == 0:
|
||||
return "Veuillez entrer au moins un exercice valide"
|
||||
id_code = generate_unique_code(Parcours, s=db)
|
||||
parcours_obj = Parcours(**{**parcours.dict(), "exercices": exercices}, room_id=room_id, id_code=id_code)
|
||||
print(parcours_obj)
|
||||
|
||||
parcours_obj = Parcours(
|
||||
**{**parcours.dict(), "exercices": exercices}, room_id=room_id, id_code=id_code)
|
||||
|
||||
db.add(parcours_obj)
|
||||
db.commit()
|
||||
db.refresh(parcours_obj)
|
||||
|
@ -320,24 +503,80 @@ def create_parcours_db(parcours: ParcoursCreate,room_id: int, db: Session):
|
|||
|
||||
def deleteParcoursRelated(parcours: Parcours, db: Session):
|
||||
db.exec(delete(Challenge).where(Challenge.parcours_id == parcours.id_code))
|
||||
db.exec(delete(TmpCorrection).where(TmpCorrection.parcours_id == parcours.id_code))
|
||||
db.exec(delete(TmpCorrection).where(
|
||||
TmpCorrection.parcours_id == parcours.id_code))
|
||||
db.exec(delete(Challenger).where(Challenger.parcours_id == parcours.id))
|
||||
|
||||
db.commit()
|
||||
|
||||
|
||||
|
||||
def change_challengers_validation(p: Parcours, validation: int, db: Session):
|
||||
challengers = db.exec(select(Challenger).where(
|
||||
Challenger.parcours_id == p.id)).all()
|
||||
challs = []
|
||||
for c in challengers:
|
||||
validated = c.best <= validation
|
||||
if validated != c.validated:
|
||||
c.validated = validated
|
||||
challs.append(c)
|
||||
|
||||
db.bulk_save_objects(challs)
|
||||
db.commit()
|
||||
|
||||
|
||||
def change_challenges_validation(p: Parcours, validation: int, db: Session):
|
||||
print('cHANGE')
|
||||
challenges = db.exec(select(Challenge).where(
|
||||
Challenge.parcours_id == p.id_code)).all()
|
||||
print('CHALLS', challenges)
|
||||
challs = []
|
||||
for c in challenges:
|
||||
validated = c.mistakes <= validation
|
||||
print('CHAL', validated, c.validated, c)
|
||||
if validated != c.validated:
|
||||
c.validated = validated
|
||||
challs.append(c)
|
||||
|
||||
db.bulk_save_objects(challs)
|
||||
db.commit()
|
||||
|
||||
|
||||
def changeValidation(p: Parcours, validation: int, db: Session):
|
||||
change_challengers_validation(p, validation, db)
|
||||
change_challenges_validation(p, validation, db)
|
||||
|
||||
|
||||
def compareExercices(old: list[Exercices], new: list[ExercicesCreate]):
|
||||
old = [{"id": o['exercice_id'], "q": o['quantity']} for o in old]
|
||||
new = [{"id": n.exercice_id, "q": n.quantity} for n in new]
|
||||
return old == new
|
||||
|
||||
|
||||
def update_parcours_db(parcours: ParcoursCreate, parcours_obj: Parcours, db: Session):
|
||||
exercices = validate_exercices(parcours.exercices, db)
|
||||
if len(exercices) == 0:
|
||||
return "Veuillez entrer au moins un exercice valide"
|
||||
|
||||
parcours_data = parcours.dict(exclude_unset=True)
|
||||
for key, value in parcours_data.items():
|
||||
setattr(parcours_obj, key, value)
|
||||
parcours_obj.exercices = exercices
|
||||
update_challenges = False
|
||||
|
||||
if not compareExercices(parcours_obj.exercices, parcours.exercices):
|
||||
exercices = validate_exercices(parcours.exercices, db)
|
||||
if len(exercices) == 0:
|
||||
return "Veuillez entrer au moins un exercice valide"
|
||||
deleteParcoursRelated(parcours_obj, db)
|
||||
update_challenges = True
|
||||
parcours_obj.exercices = exercices
|
||||
|
||||
if parcours_obj.max_mistakes != parcours.max_mistakes:
|
||||
changeValidation(parcours_obj, parcours.max_mistakes, db)
|
||||
|
||||
parcours_obj.name = parcours.name
|
||||
parcours_obj.time = parcours.time
|
||||
parcours_obj.max_mistakes = parcours.max_mistakes
|
||||
|
||||
db.add(parcours_obj)
|
||||
db.commit()
|
||||
deleteParcoursRelated(parcours_obj, db)
|
||||
|
||||
db.refresh(parcours_obj)
|
||||
|
||||
return parcours_obj
|
||||
|
||||
return parcours_obj, update_challenges
|
||||
|
||||
|
||||
def delete_parcours_db(parcours: Parcours, db: Session):
|
||||
db.delete(parcours)
|
||||
|
@ -347,138 +586,210 @@ def delete_parcours_db(parcours: Parcours, db: Session):
|
|||
|
||||
class CorrigedChallenge(BaseModel):
|
||||
data: List[List[CorrigedGeneratorOut]]
|
||||
note: Note
|
||||
mistakes: int
|
||||
isCorriged: bool
|
||||
|
||||
|
||||
def create_tmp_correction(data: List[List[CorrigedGeneratorOut]], parcours_id: str, member: Member, db: Session):
|
||||
def create_tmp_correction(data: List[CorrigedData], parcours_id: str, member: Member, db: Session):
|
||||
code = generate_unique_code(TmpCorrection, s=db)
|
||||
tmpCorr = TmpCorrection(data=data, id_code=code,
|
||||
member=member, parcours_id=parcours_id)
|
||||
db.add(tmpCorr)
|
||||
db.commit()
|
||||
db.refresh(tmpCorr)
|
||||
|
||||
return tmpCorr
|
||||
|
||||
def change_challenge(challenge: Challenge, corriged: CorrigedChallenge, db: Session):
|
||||
challenge.data = corriged['data']
|
||||
challenge.note = corriged['note']
|
||||
challenge.isCorriged = corriged['isCorriged']
|
||||
challenge.validated = noteOn20(
|
||||
corriged['note']['value'], corriged['note']['total']) > challenge.parcours.validate_condition
|
||||
|
||||
db.add(challenge)
|
||||
db.commit()
|
||||
db.refresh(challenge)
|
||||
|
||||
return challenge
|
||||
|
||||
|
||||
def validate_challenge_input(obj: List[List[ParsedGeneratorOut]], corr: TmpCorrection):
|
||||
def validate_challenge_input(obj: List[CorrectionData], corr: TmpCorrection):
|
||||
data = corr.data
|
||||
if len(obj) != len(data):
|
||||
return False
|
||||
for i in range(len(data)):
|
||||
exo_corr = data[i]
|
||||
exo = obj[i]
|
||||
if len(exo) != len(exo_corr):
|
||||
print('EXO', exo)
|
||||
print('EXO', exo.data)
|
||||
if len(exo.data) != len(exo_corr['data']):
|
||||
return
|
||||
zipped = zip(exo_corr, exo)
|
||||
same = all([e['calcul'] == f.calcul and len(e['inputs']) == len(f.inputs) for e,f in zipped])
|
||||
zipped = zip(exo_corr['data'], exo.data)
|
||||
same = all([e['calcul'] == f.calcul and len(e['inputs'])
|
||||
== len(f.inputs) for e, f in zipped])
|
||||
if not same:
|
||||
return False
|
||||
return True
|
||||
|
||||
def validate_challenge_correction(obj: List[List[CorrigedGeneratorOut]], chall: Challenge):
|
||||
|
||||
def validate_challenge_correction(obj: List[CorrigedData], chall: Challenge):
|
||||
data = chall.data
|
||||
if len(obj) != len(data):
|
||||
return False
|
||||
for i in range(len(data)):
|
||||
exo_corr = data[i]
|
||||
exo = obj[i]
|
||||
if len(exo) != len(exo_corr):
|
||||
if len(exo.data) != len(exo_corr['data']):
|
||||
return
|
||||
zipped = zip(exo_corr, exo)
|
||||
same = all([e['calcul'] == f.calcul and len(e['inputs']) == len(f.inputs) for e,f in zipped])
|
||||
< |