Scenarios: Add scenarios table in db and default scenario in study.

scenarios
Pierre-Antoine Rouby 2024-07-17 16:04:49 +02:00
parent 4c25355be9
commit 3ecf97ac82
4 changed files with 268 additions and 14 deletions

View File

@ -39,7 +39,9 @@ class Friction(SQLSubModel):
else: else:
self.id = id self.id = id
Friction._id_cnt = max(self.id, Friction._id_cnt+1) Friction._id_cnt = max(
self.id, Friction._id_cnt + 1
)
self._name = name self._name = name
self._edge = None self._edge = None

161
src/Model/Scenario.py Normal file
View File

@ -0,0 +1,161 @@
# Scenario.py -- Pamhyr
# Copyright (C) 2024 INRAE
#
# This program 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.
#
# This program 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 this program. If not, see <https://www.gnu.org/licenses/>.
# -*- coding: utf-8 -*-
from tools import logger_exception
from Model.Tools.PamhyrDB import SQLSubModel
class Scenario(SQLSubModel):
_id_cnt = 0
_sub_classes = []
def __init__(self,
id: int = -1,
name: str = "",
description: str = "",
revision:int = 0,
parent=None,
status=None):
super(Scenario, self).__init__()
self._set_id(id)
self._name = name
self._description = description
self._revision = revision
self._parent = parent
self._status = status
def _set_id(self, id):
if id == -1:
self._id = Scenario._id_cnt
else:
self._id = id
Scenario._id_cnt = max(
self._id + 1, Scenario._id_cnt + 1
)
@classmethod
def _db_create(cls, execute):
execute("""
CREATE TABLE scenario(
id INTEGER PRIMARY KEY,
name TEXT NOT NULL,
description TEXT NOT NULL,
revision INTEGER NOT NULL,
parent_id INTEGER REFERENCES scenario(id)
)
""")
cls._create_submodel(execute)
return True
@classmethod
def _db_add_default(cls, execute):
execute(
"INSERT OR REPLACE INTO " +
"scenario(id, name, description, revision, parent_id) " +
"VALUES (" +
" 0, 'default', 'Default scenario',\n" +
" 0, NULL" +
")"
)
@classmethod
def _db_update(cls, execute, version):
major, minor, release = version.strip().split(".")
if major == minor == "0":
if int(release) < 12:
cls._db_create(execute)
cls._db_add_default(execute)
return True
@classmethod
def _db_load(cls, execute, data=None):
scenarios = {}
table = execute(
"SELECT id, name, description, revision, parent_id " +
"FROM scenario " +
"ORDER BY id ASC"
)
for row in table:
it = iter(row)
id = next(it)
name = next(it)
desc = next(it)
revi = next(it)
parent = next(it)
if parent is not None:
parent = scenarios[parent]
new = cls(
id=id, name=name, description=desc,
revision=revi, parent=parent,
status=data["status"]
)
scenarios[id] = new
return scenarios
def _db_save(self, execute, data=None):
parent = 'NULL'
if self.parent is not None:
parent = self.parent._id
sql = (
"INSERT OR REPLACE INTO " +
"scenario(id, name, description, revision, parent_id) " +
"VALUES (" +
f"{self._id}, "+
f"'{self._db_format(self.name)}', " +
f"'{self._db_format(self.description)}', " +
f"{self._revision}, " +
f"{parent}" +
")"
)
execute(sql)
return True
@property
def name(self):
if self._name == "":
return f"Child of '{self._parent.name}'"
return self._name
@property
def description(self):
if self._description == "":
return f"Child of '{self._parent.name}'"
return self._description
@property
def revision(self):
return self._revision
@property
def parent(self):
return self._parent

60
src/Model/Scenarios.py Normal file
View File

@ -0,0 +1,60 @@
# Scenarios.py -- Pamhyr
# Copyright (C) 2024 INRAE
#
# This program 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.
#
# This program 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 this program. If not, see <https://www.gnu.org/licenses/>.
# -*- coding: utf-8 -*-
from tools import logger_exception
from Model.Tools.PamhyrDict import PamhyrModelDict
from Model.Scenario import Scenario
class Scenarios(PamhyrModelDict):
_sub_classes = [
Scenario,
]
@classmethod
def _db_load(cls, execute, data=None):
new = cls(status=data["status"])
new._dict = Scenario._db_load(
execute,
data=data
)
return new
def _db_save(self, execute, data=None):
ok = True
if data is None:
data = {}
scenarios = self._dict
for sid in scenarios:
ok &= scenarios[sid]._db_save(execute, data)
return ok
def get(self, key):
if key in self._dict:
return self._dict[key]
return None
def new(self, parent):
new = Scenario(parent=parent, status=self._status)
self.set(new._id, new)
return new

View File

@ -24,6 +24,8 @@ from datetime import datetime
from tools import timer, timestamp from tools import timer, timestamp
from Model.Tools.PamhyrDB import SQLModel from Model.Tools.PamhyrDB import SQLModel
from Model.Scenarios import Scenarios
from Model.Scenario import Scenario
from Model.Saved import SavedStatus from Model.Saved import SavedStatus
from Model.Serializable import Serializable from Model.Serializable import Serializable
from Model.Except import NotImplementedMethodeError from Model.Except import NotImplementedMethodeError
@ -36,12 +38,13 @@ logger = logging.getLogger()
class Study(SQLModel): class Study(SQLModel):
_sub_classes = [ _sub_classes = [
Scenario,
River, River,
] ]
def __init__(self, filename=None, init_new=True): def __init__(self, filename=None, init_new=True):
# Metadata # Metadata
self._version = "0.0.11" self._version = "0.0.12"
self.creation_date = datetime.now() self.creation_date = datetime.now()
self.last_modification_date = datetime.now() self.last_modification_date = datetime.now()
self.last_save_date = datetime.now() self.last_save_date = datetime.now()
@ -60,6 +63,15 @@ class Study(SQLModel):
if init_new: if init_new:
# Study data # Study data
self.scenarios = Scenarios(status=self.status)
self.scenarios.set(
0,
Scenario(
id=0, name='default',
description='Default scenario',
status=self.status,
)
)
self._river = River(status=self.status) self._river = River(status=self.status)
else: else:
self._init_db_file(filename, is_new=False) self._init_db_file(filename, is_new=False)
@ -289,22 +301,36 @@ class Study(SQLModel):
) )
new.creation_date = datetime.fromtimestamp( new.creation_date = datetime.fromtimestamp(
float(new.execute( float(
"SELECT value FROM info WHERE key='creation_date'")[0]) new.execute(
"SELECT value FROM info WHERE key='creation_date'"
)[0]
)
) )
new.last_save_date = datetime.fromtimestamp( new.last_save_date = datetime.fromtimestamp(
float(new.execute( float(
"SELECT value FROM info WHERE key='last_save_date'")[0]) new.execute(
"SELECT value FROM info WHERE key='last_save_date'"
)[0]
)
)
data = {"status": new.status}
sql_exec = lambda sql: new.execute(
sql,
fetch_one=False,
commit=True
)
new.scenarios = Scenario._db_load(
sql_exec,
data=data
) )
# Load river data # Load river data
new._river = River._db_load( new._river = River._db_load(
lambda sql: new.execute( sql_exec,
sql, data=data
fetch_one=False,
commit=True
),
data={"status": new.status}
) )
return new return new
@ -351,14 +377,19 @@ class Study(SQLModel):
) )
progress() progress()
self._save_submodel([self._river], data=progress) self._save_submodel(
[self.scenarios, self._river],
data=progress
)
self.commit() self.commit()
def sql_save_request_count(self): def sql_save_request_count(self):
return self._count() return self._count()
def _count(self): def _count(self):
cnt = self._save_count([self._river]) cnt = self._save_count(
[self.scenarios, self._river]
)
logger.debug(cnt) logger.debug(cnt)
return cnt + 6 return cnt + 6