From ec9210c48f26e609e8701e646a8fbfbf22c78f55 Mon Sep 17 00:00:00 2001
From: Artem Baranovskyi <artem.baranovsky1980@gmail.com>
Date: Wed, 26 Jun 2024 23:32:48 +0300
Subject: [PATCH] Fixed Supervisor & Flask infrastructure issues. Added Plugin
 DB Migration. -----------------------------------------------------------
 TODO: Create an API to use script run_LR_SBERT.py on
 http://127.0.0.1:5000/api/data or like that.

---
 .env                                       |  4 ++-
 Dockerfile                                 |  7 ++---
 api.py                                     | 21 ++++++++++---
 asyst/Source/Skript/german/run_LR_SBERT.py | 28 ++++++++++--------
 docker-compose.yml                         |  9 ++----
 install_moodle.sh                          |  4 +--
 readme.md                                  |  9 ++++--
 supervisord.conf                           |  8 +++--
 yourplugin/db/install.xml                  | 22 ++++++++++++++
 yourplugin/lang/en/yourplugin.php          | 34 ++++++++++++----------
 yourplugin/lib.php                         | 27 +++++++++++++++++
 yourplugin/version.php                     |  6 ++--
 12 files changed, 127 insertions(+), 52 deletions(-)
 create mode 100644 yourplugin/db/install.xml
 create mode 100644 yourplugin/lib.php

diff --git a/.env b/.env
index 98be37a..80ed354 100755
--- a/.env
+++ b/.env
@@ -13,4 +13,6 @@ MOODLE_BASE_DIR_DATA=/var/www/html/moodledata
 
 MOODLE_WWWROOT=https://www.moodle.loc
 MOODLE_FULLNAME="Moodle LMS Site"
-MOODLE_SHORTNAME="Moodle"
\ No newline at end of file
+MOODLE_SHORTNAME="Moodle"
+
+FLASK_APP=/var/www/html/moodle/api.py
\ No newline at end of file
diff --git a/Dockerfile b/Dockerfile
index ab9cf7d..f9d3e65 100755
--- a/Dockerfile
+++ b/Dockerfile
@@ -44,6 +44,8 @@ RUN python3 -m venv /opt/myenv
 RUN /opt/myenv/bin/python3 -m pip install --upgrade pip
 #RUN /opt/myenv/bin/python3 -m pip install matplotlib Flask torch sklearn-learn
 COPY requirements.txt /opt/myenv/
+COPY sentence-transformers-paraphrase-multilingual-MiniLM-L12-v2 /var/www/html/moodle/sentence-transformers-paraphrase-multilingual-MiniLM-L12-v2
+WORKDIR /var/www/html/moodle
 RUN /opt/myenv/bin/python3 -m pip install -r /opt/myenv/requirements.txt
 RUN /opt/myenv/bin/python3 -m pip install --upgrade setuptools wheel
 
@@ -149,11 +151,6 @@ RUN a2enmod ssl
 #Opening ports
 EXPOSE 80 443 5000
 
-#RUN /var/www/html/moodle/install_moodle.sh
-# Run the Flask app (modify entrypoint or use a custom script if needed)
-#CMD ["bash", "-c", "service apache2 start && source /opt/myenv/bin/activate && python3 /var/www/html/moodle/install_moodle.sh /var/www/html/moodle/api.py "]
-#CMD ["bash", "-c", "service apache2 start && source /opt/myenv/bin/activate && python3 /var/www/html/moodle/api.py && /var/www/html/moodle/install_moodle.sh"]
-
 # Setting up supervisord
 COPY supervisord.conf /etc/supervisor/conf.d/supervisord.conf
 
diff --git a/api.py b/api.py
index 65c8f17..43e1490 100755
--- a/api.py
+++ b/api.py
@@ -2,20 +2,33 @@
 
 from flask import Flask, jsonify
 
+# TODO: Adding correct path to ASYST script run_LR_SBERT.py
+# from run_LR_SBERT import main
+
+# sys.path.append(os.path.join(os.path.dirname(__file__), 'asyst/Source/Skript/german'))
+
 app = Flask(__name__)
 
-# Example of an endpoint returning JSON data
 @app.route('/api/data', methods=['GET'])
 def get_data():
-# TODO: use run_LR_SBERT.py ASYST script instead
-    data = {
+    # Using path to data and model
+    data_path = '/var/www/html/moodle/asyst/Source/Skript/outputs/test.tsv'
+    model_dir = '/var/www/html/moodle/asyst/Source/Skript/german/models'
+
+    # Obtaining results from run_asyst function
+#     results => run_asyst(data_path, model_dir)
+
+    # Demo dummy API output
+    results = {
         'message': 'Hello from Python API!',
         'data': {
             'key1': 'value1',
             'key2': 'value2'
         }
     }
-    return jsonify(data)
+
+    # Returning result in JSON format
+    return jsonify(results)
 
 if __name__ == '__main__':
     app.run(host='0.0.0.0', port=5000, debug=True)
\ No newline at end of file
diff --git a/asyst/Source/Skript/german/run_LR_SBERT.py b/asyst/Source/Skript/german/run_LR_SBERT.py
index e4f169e..1f01ac6 100755
--- a/asyst/Source/Skript/german/run_LR_SBERT.py
+++ b/asyst/Source/Skript/german/run_LR_SBERT.py
@@ -36,7 +36,6 @@ def main():
         #default=None,
         default="/var/www/html/moodle/asyst/Source/Skript/outputs/test.tsv",
         type=str,
-        # required=True,
         required=False,
         help="The input data file for the task.",
     )
@@ -45,7 +44,6 @@ def main():
         # default=None,
         default="/var/www/html/moodle/asyst/Source/Skript/outputs",
         type=str,
-        # required=True,
         required=False,
         help="The output directory where predictions will be written.",
     )
@@ -54,32 +52,38 @@ def main():
         # default=None,
         default=location+"/Skript/german/models",
         type=str,
-        # required=True,
         required=False,
         help="The directory where the ML models are stored.",
     )
+    parser.add_argument(
+        "--transformer_model_dir",
+        default="/var/www/html/moodle/sentence-transformers-paraphrase-multilingual-MiniLM-L12-v2",
+        type=str,
+        required=False,
+        help="The directory where the SentenceTransformer model is stored.",
+    )
     args = parser.parse_args()
 
     # open a log file next to the executable with line buffering
     # out = open("log.txt", "a",buffering=1);
 
-    # print("Started German processing in",location,file=out);
+    # print("Started German processing in", location, file=out);
 
     # import SentenceTransformer-model
     start_time = time.time()
 
-    # print("Reading from",args.data, file=out);
+    # print("Reading from", args.data, file=out);
 
-    with open(os.path.join(location,args.data)) as ft:
+    with open(args.data) as ft:
         dft = pd.read_csv(ft, delimiter='\t')
 
     # Sentences we want sentence embeddings for
     sentences1_test = dft['referenceAnswer'].values.tolist()
     sentences2_test = dft['studentAnswer'].values.tolist()
-    # print("Input read:",sentences2_test, file=out);
+    # print("Input read:", sentences2_test, file=out);
 
     # Use BERT for mapping tokens to embeddings
-    word_embedding_model = models.Transformer('sentence-transformers/paraphrase-multilingual-MiniLM-L12-v2')
+    word_embedding_model = models.Transformer(args.transformer_model_dir)
     # pooling operation can choose by setting true (Apply mean pooling to get one fixed sized sentence vector)
     pooling_model = models.Pooling(word_embedding_model.get_word_embedding_dimension(),
                                    pooling_mode_mean_tokens=True,
@@ -91,7 +95,7 @@ def main():
     # print("Model loaded", file=out);
 
     sentence_embeddings1_test = model.encode(sentences1_test, convert_to_tensor=True, show_progress_bar=False)
-    # print("Embeddings RefA:",sentence_embeddings1_test,file=out);
+    # print("Embeddings RefA:", sentence_embeddings1_test, file=out);
 
     sentence_embeddings2_test = model.encode(sentences2_test, convert_to_tensor=True, show_progress_bar=False)
     # print("Embeddings found", file=out);
@@ -107,7 +111,7 @@ def main():
     # calls the similarity function and get the concatenated values between the sentence embeddings
     computed_simis_test = similarity(sentence_embeddings1_test, sentence_embeddings2_test)
 
-    # get the sentence embeddings and the labels fpr train and test
+    # get the sentence embeddings and the labels for train and test
 
     X_test = computed_simis_test
     # Y_test = np.array(dft['label'])
@@ -115,12 +119,12 @@ def main():
     # UP: read pre-trained LR model
     clf_log = pickle.load(open("/var/www/html/moodle/asyst/Source/Skript/german/models/clf_BERT.pickle", "rb"))
 
-
     # print('--------Evaluate on Testset------- ', file=out)
     predictions = clf_log.predict(X_test)
 
     # UP print results
     with open(args.output_dir + "/predictions.txt", "w") as writer:
+        # TODO: write results to plugins DB Table
         writer.write("question\treferenceAnswer\tstudentAnswer\tsuggested grade\tobserved grade\n")
         for i in range(len(dft)):
             hrpred = "incorrect"
@@ -139,7 +143,7 @@ def main():
                 + "\n"
             )
 
-    # print('\nExecution time:', time.strftime("%H:%M:%S", time.gmtime(time.time() - start_time)),file=out)
+    # print('\nExecution time:', time.strftime("%H:%M:%S", time.gmtime(time.time() - start_time)), file=out)
 
 
 if __name__ == "__main__":
diff --git a/docker-compose.yml b/docker-compose.yml
index 0932d69..0f8c399 100755
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -42,6 +42,9 @@ services:
       - 80:80
       - 443:443
       - 5000:5000
+    dns:
+      - 8.8.8.8
+      - 8.8.4.4
     depends_on: # Dependency from MariaDB service
       - mariadb
     volumes:
@@ -51,12 +54,6 @@ services:
       - moodledata:${MOODLE_BASE_DIR_DATA}  # Том для данных Moodle
     networks:
       - network  # Добавление к сети
-    healthcheck:
-      test: /bin/bash -c 'while ! nc -z mariadb 3306; do echo "Ждем подключения к базе данных..."; sleep 5; done'
-      interval: 10s
-      timeout: 5s
-      retries: 5
-    command: [ "bash", "-c", "apache2ctl -D FOREGROUND" ]
 volumes:
   moodledata:
     driver: local  # Локальный драйвер томов
diff --git a/install_moodle.sh b/install_moodle.sh
index c261025..49744e2 100755
--- a/install_moodle.sh
+++ b/install_moodle.sh
@@ -24,8 +24,8 @@ docker-compose exec moodle php ${MOODLE_BASE_DIR}/admin/cli/install.php \
 docker-compose exec moodle chmod -R 755 /var/www/html/moodle
 
 # Set correct access rules for the plugin
-#docker-compose exec moodle chown -R www-data:www-data /var/www/html/moodle/mod/yourplugin
-#docker-compose exec moodle chmod -R 775 /var/www/html/moodle/mod/yourplugin
+docker-compose exec moodle chown -R www-data:www-data /var/www/html/moodle/mod/yourplugin
+docker-compose exec moodle chmod -R 775 /var/www/html/moodle/mod/yourplugin
 
 # Create the run_sag script file
 docker-compose exec moodle bash -c 'echo "#!/bin/bash" > /usr/local/bin/run_sag'
diff --git a/readme.md b/readme.md
index f3c8a29..46c67b3 100755
--- a/readme.md
+++ b/readme.md
@@ -4,11 +4,16 @@ Run these commands at CLI to use ASYST with universal BERT model based on German
 
 ~~~bash
 docker-compose up -d --build
-install_moodle
+/bin/bash install_moodle.sh
 ~~~
 
+Use these creds to access Moodle admin page
+admin:rootpassword
+
+Database connection URL: jdbc:mariadb://localhost:3306/moodle
+
 It is suggested to use our moodle plugin to communicate with ASYST script using such a
-route http://127.0.0.1:5000/api/data
+route http://127.0.0.1:5000
 
 Now the preinstalled MOODLE LMS is available at https://www.moodle.loc
 
diff --git a/supervisord.conf b/supervisord.conf
index 8cc191d..a5d4e26 100644
--- a/supervisord.conf
+++ b/supervisord.conf
@@ -5,9 +5,13 @@ nodaemon=true
 command=/usr/sbin/apache2ctl -D FOREGROUND
 autostart=true
 autorestart=true
+stdout_logfile=/var/log/supervisor/flask.log
+stderr_logfile=/var/log/supervisor/flask_err.log
 
 [program:flask]
-command=/opt/myenv/bin/python /var/www/html/moodle/api.py
+command=/bin/bash -c 'source /opt/myenv/bin/activate && FLASK_APP=/var/www/html/moodle/api.py /opt/myenv/bin/flask run --host=0.0.0.0'
 directory=/var/www/html/moodle
 autostart=true
-autorestart=true
\ No newline at end of file
+autorestart=true
+stdout_logfile=/var/log/supervisor/moodle.log
+stderr_logfile=/var/log/supervisor/moodle_err.log
\ No newline at end of file
diff --git a/yourplugin/db/install.xml b/yourplugin/db/install.xml
new file mode 100644
index 0000000..5c484d0
--- /dev/null
+++ b/yourplugin/db/install.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<XMLDB PATH="mod/yourplugin/db" VERSION="2024032201" COMMENT="XMLDB file for mod yourplugin plugin"
+       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+       xsi:noNamespaceSchemaLocation="../../../lib/xmldb/xmldb.xsd"
+>
+    <TABLES>
+        <TABLE NAME="mod_yourplugin" COMMENT="Table for storing yourplugin data">
+            <FIELDS>
+                <FIELD NAME="id" TYPE="int" LENGTH="10" NOTNULL="true" UNSIGNED="true" SEQUENCE="true"/>
+                <FIELD NAME="question" TYPE="text" NOTNULL="true"/>
+                <FIELD NAME="referenceanswer" TYPE="text" NOTNULL="true"/>
+                <FIELD NAME="studentanswer" TYPE="text" NOTNULL="true"/>
+                <FIELD NAME="observed_grade" TYPE="int" LENGTH="3" NOTNULL="true"/>
+                <FIELD NAME="studentid" TYPE="int" LENGTH="10" NOTNULL="false"/>
+                <FIELD NAME="recordid" TYPE="int" LENGTH="10" NOTNULL="false"/>
+            </FIELDS>
+            <KEYS>
+                <KEY NAME="primary" TYPE="primary" FIELDS="id"/>
+            </KEYS>
+        </TABLE>
+    </TABLES>
+</XMLDB>
diff --git a/yourplugin/lang/en/yourplugin.php b/yourplugin/lang/en/yourplugin.php
index 28c38a6..9968e15 100755
--- a/yourplugin/lang/en/yourplugin.php
+++ b/yourplugin/lang/en/yourplugin.php
@@ -10,32 +10,36 @@
 $string['pluginname'] = 'New local plugin';
 
 // Path to the Python 3 executable
-$python_executable = '/usr/bin/python3';
+$python_executable = '/opt/myenv/bin/python3';
 
 // Path to the moodlemlbackend script to be executed. First we use test API api.py, then run_LR_SBERT.py
 $python_script = '/var/www/html/moodle/api.py';
 //$python_script = '/var/www/html/moodle/asyst/Source/Skript/german/run_LR_SBERT.py';
 
 // Python command you want to execute
-$python_command = 'print("Hello, world!!!")';
+//$python_command = 'print("Hello, world!!!")';
+// Execution the command and getting the result
+//shell_exec($python_command);
 
 // Formation of a command to execute
 //$full_command = $python_executable . ' -c \'' . $python_command . '\'';
-$full_command = $python_executable . ' ' . $python_script;
+//$full_command = $python_executable . ' ' . $python_script;
 
-// Execution the command and getting the result
-$result = shell_exec($full_command);
+// Now call the API
+$api_url  = 'http://127.0.0.1:5000/api/data';
+$response = file_get_contents($api_url);
 
-// Output the result
-echo $result;
-// Output the result (assuming moodlemlbackend returns JSON)
-$data = json_decode($result, true);
-if ($data !== null) {
+// Output the result (assuming backend returns JSON)
+if ($response !== false) {
+    $data = json_decode($response, true);
+    if ($data !== null) {
 // Data processing
-// Example: output results
-    echo "<pre>";
-    print_r($data);
-    echo "</pre>";
+// Example: output results        echo "<pre>";
+        print_r($data);
+        echo "</pre>";
+    } else {
+        echo "Error on data processing from moodlemlbackend!";
+    }
 } else {
-    echo "Error on data processing from moodlemlbackend!";
+    echo "Execution error: result is not a string.";
 }
diff --git a/yourplugin/lib.php b/yourplugin/lib.php
new file mode 100644
index 0000000..d495ebd
--- /dev/null
+++ b/yourplugin/lib.php
@@ -0,0 +1,27 @@
+<?php
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+/**
+ * @package     mod_yourplugin
+ * @author      Artem Baranovskyi
+ * @license     http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+function mod_yourplugin_before_footer()
+{
+    if (!get_config('mod_yourplugin', 'enabled')) {
+        return;
+    }
+}
\ No newline at end of file
diff --git a/yourplugin/version.php b/yourplugin/version.php
index 452923b..26404c9 100755
--- a/yourplugin/version.php
+++ b/yourplugin/version.php
@@ -2,14 +2,14 @@
 /**
  * Version details.
  *
- * @package   local_yourplugin
+ * @package   mod_yourplugin
  * @copyright 2024 Artem Baranovskyi
  * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  */
 
 defined('MOODLE_INTERNAL') || die();
 
-$plugin->version   = 2022051101;      // The current module version (Date: YYYYMMDDXX).
+$plugin->version   = 2024032201;      // The current module version (Date: YYYYMMDDXX).
 $plugin->requires  = 2014050800;      // Requires this Moodle version.
-$plugin->component = 'yourplugin';// Full name of the plugin (used for diagnostics).
+$plugin->component = 'mod_yourplugin';    // Full name of the plugin (used for diagnostics).
 $plugin->cron      = 0;
-- 
GitLab