From 8671e7b7dd0705e1476108a984a4f35f09eb8345 Mon Sep 17 00:00:00 2001
From: Pierre-Antoine Rouby <pierre-antoine.rouby@inrae.fr>
Date: Fri, 30 Jun 2023 16:04:03 +0200
Subject: [PATCH] Model, SolverParameters: Add SQL export for solver
 parameters.

---
 src/Model/River.py                            | 14 ++-
 .../SolverParameters/SolverParametersList.py  | 88 +++++++++++++++++--
 src/Solver/ASolver.py                         |  2 +
 src/Solver/GenericSolver.py                   |  2 +
 src/Solver/Mage.py                            |  6 ++
 5 files changed, 106 insertions(+), 6 deletions(-)

diff --git a/src/Model/River.py b/src/Model/River.py
index 2b8f88fa..8a4f6fc6 100644
--- a/src/Model/River.py
+++ b/src/Model/River.py
@@ -184,7 +184,7 @@ class River(Graph, SQLSubModel):
         LateralContributionList,
         # InitialConditionsDict,
         StricklersList,
-        # SolverParametersList,
+        SolverParametersList,
     ]
 
     def __init__(self, status=None):
@@ -232,15 +232,25 @@ class River(Graph, SQLSubModel):
             execute,
             data
         )
+        # Lateral Contribution
         new._lateral_contribution = LateralContributionList._sql_load(
             execute,
             data
         )
+        # Stricklers
         new._stricklers = StricklersList._sql_load(
             execute,
             data
         )
 
+        # Parameters
+        for solver in new._parameters:
+            data["solver"] = solver
+            new._parameters[solver] = SolverParametersList(
+                execute,
+                data
+            )
+
         return new
 
     def _sql_save(self, execute, data = None):
@@ -248,6 +258,8 @@ class River(Graph, SQLSubModel):
         objs.append(self._boundary_condition)
         objs.append(self._lateral_contribution)
         objs.append(self._stricklers)
+        for solver in self._parameters:
+            objs.append(self._parameters[solver])
 
         self._save_submodel(execute, objs, data)
         return True
diff --git a/src/Model/SolverParameters/SolverParametersList.py b/src/Model/SolverParameters/SolverParametersList.py
index ee3b9b40..abac7c40 100644
--- a/src/Model/SolverParameters/SolverParametersList.py
+++ b/src/Model/SolverParameters/SolverParametersList.py
@@ -3,12 +3,16 @@
 from copy import copy
 from tools import trace, timer
 
-class Parameter(object):
-    def __init__(self, status = None):
+from Model.DB import SQLSubModel
+
+class Parameter():
+    def __init__(self,
+                 name = "", value = "",
+                 status = None):
         self._status = status
 
-        self._name = ""
-        self._value = ""
+        self._name = name
+        self._value = value
 
     @property
     def name(self):
@@ -42,11 +46,12 @@ class Parameter(object):
 
         return new
 
-class SolverParametersList(object):
+class SolverParametersList(SQLSubModel):
     def __init__(self, solver_type = None, status = None):
         super(SolverParametersList, self).__init__()
 
         self._status = status
+        self._solver = solver_type
         self._parameters = list(
             map(
                 lambda t: Parameter.from_tuple(t, self._status),
@@ -54,6 +59,79 @@ class SolverParametersList(object):
             )
         )
 
+
+    @classmethod
+    def _sql_create(cls, execute):
+        execute("""
+          CREATE TABLE solver_parameter(
+            id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
+            ind INTEGER NOT NULL,
+            name TEXT NOT NULL,
+            value TEXT NOT NULL,
+            solver TEXT NOT NULL
+          )
+        """)
+
+        return cls._create_submodel(execute)
+
+    @classmethod
+    def _sql_update(cls, execute, version):
+        return cls._update_submodel(execute, version)
+
+    @classmethod
+    def _sql_load(cls, execute, data = None):
+        status = data["status"]
+        solver = data["solver"]
+
+        new = cls(solver_type = solver, status = status)
+
+        table = execute(
+            "SELECT ind, name, value " +
+            "FROM solver_parameter " +
+            f"WHERE solver = '{solver.type}'"
+        )
+
+        for _ in table:
+            new._parameters.append(None)
+
+        for row in table:
+            ind = row[0]
+            name = row[1]
+            value = row[2]
+
+            p = cls(
+                name = name,
+                value = value,
+                status = status
+            )
+            new._parameters[ind] = p
+
+        return stricklers
+
+    def _sql_save(self, execute, data = None):
+        t = self._solver._type
+        execute(
+            "DELETE FROM solver_parameter " +
+            f"WHERE solver = '{t}'"
+        )
+
+        ind = 0
+        for param in self._parameters:
+            sql = (
+                "INSERT INTO " +
+                "solver_parameter(ind, name, value, solver) "+
+                "VALUES (" +
+                f"{ind}, " +
+                f"'{self._sql_format(param.name)}', " +
+                f"'{self._sql_format(param.value)}', " +
+                f"'{self._sql_format(t)}'" +
+                ")"
+            )
+            execute(sql)
+            ind += 1
+
+        return True
+
     def __len__(self):
         return len(self._parameters)
 
diff --git a/src/Solver/ASolver.py b/src/Solver/ASolver.py
index 66689a24..3b8419c7 100644
--- a/src/Solver/ASolver.py
+++ b/src/Solver/ASolver.py
@@ -19,6 +19,8 @@ class STATUS(Enum):
     PAUSED = 5
 
 class AbstractSolver(object):
+    _type = ""
+
     def __init__(self, name):
         super(AbstractSolver, self).__init__()
 
diff --git a/src/Solver/GenericSolver.py b/src/Solver/GenericSolver.py
index 7cf3e332..a80adf23 100644
--- a/src/Solver/GenericSolver.py
+++ b/src/Solver/GenericSolver.py
@@ -5,6 +5,8 @@ from Solver.ASolver import (
 )
 
 class GenericSolver(AbstractSolver):
+    _type = "generic"
+
     def __init__(self, name):
         super(GenericSolver, self).__init__(name)
 
diff --git a/src/Solver/Mage.py b/src/Solver/Mage.py
index 6c164d0f..78a89931 100644
--- a/src/Solver/Mage.py
+++ b/src/Solver/Mage.py
@@ -8,6 +8,8 @@ from Solver.ASolver import AbstractSolver
 from Checker.Mage import MageNetworkGraphChecker
 
 class Mage(AbstractSolver):
+    _type = "mage"
+
     def __init__(self, name):
         super(Mage, self).__init__(name)
 
@@ -310,6 +312,8 @@ class Mage(AbstractSolver):
 ##########
 
 class Mage7(Mage):
+    _type = "mage7"
+
     def __init__(self, name):
         super(Mage7, self).__init__(name)
 
@@ -326,6 +330,8 @@ class Mage7(Mage):
 ##########
 
 class Mage8(Mage):
+    _type = "mage8"
+
     def __init__(self, name):
         super(Mage8, self).__init__(name)
 
-- 
GitLab