# Friction.py -- Pamhyr # Copyright (C) 2023-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 -*- import logging from tools import trace, timer from Model.Tools.PamhyrDB import SQLSubModel logger = logging.getLogger() class Friction(SQLSubModel): _id_cnt = 0 def __init__(self, id: int = -1, name: str = "", status=None): super(Friction, self).__init__() self._status = status if id == -1: self.id = Friction._id_cnt else: self.id = id Friction._id_cnt = max(self.id, Friction._id_cnt+1) self._name = name self._edge = None self._begin_kp = 0.0 self._end_kp = 0.0 self._begin_strickler = None self._end_strickler = None @classmethod def _db_create(cls, execute): execute(""" CREATE TABLE friction( id INTEGER NOT NULL PRIMARY KEY, ind INTEGER NOT NULL, begin_kp REAL NOT NULL, end_kp REAL NOT NULL, reach INTEGER NOT NULL, begin_strickler INTEGER NOT NULL, end_strickler INTEGER NOT NULL, FOREIGN KEY(reach) REFERENCES river_reach(id), FOREIGN KEY(begin_strickler) REFERENCES stricklers(id), FOREIGN KEY(end_strickler) REFERENCES stricklers(id) ) """) return True @classmethod def _db_update(cls, execute, version): return True @classmethod def _db_load(cls, execute, data=None): new = [] reach = data["reach"] status = data["status"] stricklers = data["stricklers"].stricklers table = execute( "SELECT id, ind, begin_kp, end_kp, " + "begin_strickler, end_strickler " + f"FROM friction WHERE reach = {reach.id}" ) for row in table: id = row[0] ind = row[1] # Get stricklers if int(row[4]) == -1: bs = None else: bs = next(filter(lambda s: s.id == row[4], stricklers)) if int(row[5]) == -1: es = None else: es = next(filter(lambda s: s.id == row[5], stricklers)) # Create friction sec = cls(status=status) sec.edge = reach sec.begin_kp = row[2] sec.end_kp = row[3] sec.begin_strickler = bs sec.end_strickler = es new.append((ind, sec)) return new def _db_save(self, execute, data=None): ind = data["ind"] b_s_id = -1 e_s_id = -1 if self._begin_strickler is not None: b_s_id = self._begin_strickler.id if self._end_strickler is not None: e_s_id = self._end_strickler.id execute( "INSERT INTO " + "friction(id, ind, begin_kp, end_kp, " + "reach, begin_strickler, end_strickler) " + "VALUES (" + f"{self.id}, {ind}, " + f"{self._begin_kp}, {self._end_kp}, " + f"{self._edge.id}, " + f"{b_s_id}, {e_s_id}" + ")" ) return True @property def name(self): return self._name @name.setter def name(self, name): self._name = name self._status.modified() @property def edge(self): return self._edge @property def reach(self): return self._edge @edge.setter def edge(self, edge): self._edge = edge if (edge is not None and self._begin_kp == 0.0 and self._end_kp == 0.0): self._begin_kp = self._edge.reach.get_kp_min() self._end_kp = self._edge.reach.get_kp_max() self._status.modified() def has_edge(self): return self._edge is not None def has_coefficient(self): return ( self._begin_strickler is not None and self._end_strickler is not None ) def is_full_defined(self): return self.has_edge() and self.has_coefficient() @property def begin_kp(self): return self._begin_kp @begin_kp.setter def begin_kp(self, begin_kp): if self._edge is None: self._begin_kp = begin_kp else: _min = self._edge.reach.get_kp_min() _max = self._edge.reach.get_kp_max() if _min <= begin_kp <= _max: self._begin_kp = begin_kp self._status.modified() @property def end_kp(self): return self._end_kp @end_kp.setter def end_kp(self, end_kp): if self._edge is None: self._end_kp = end_kp else: _min = self._edge.reach.get_kp_min() _max = self._edge.reach.get_kp_max() if _min <= end_kp <= _max: self._end_kp = end_kp self._status.modified() def __contains__(self, kp): return self.contains_kp(kp) def contains_kp(self, kp): return ( self._begin_kp <= kp <= self._end_kp ) @property def begin_strickler(self): return self._begin_strickler @begin_strickler.setter def begin_strickler(self, strickler): self._begin_strickler = strickler self._status.modified() @property def end_strickler(self): return self._end_strickler @end_strickler.setter def end_strickler(self, strickler): self._end_strickler = strickler self._status.modified()