Feat: Architecture redesign for Assessments, Commands, Modalities, Training Techniques, Reinforcement Schedules, Distractions, and Assessment Responses.

This commit is contained in:
2025-09-06 12:13:16 +01:00
parent 12f5fc994f
commit 2da465935d
158 changed files with 14781 additions and 3477 deletions

View File

@@ -16,7 +16,7 @@ from business_objects.dog.dog import Dog
from business_objects.dog.response_quality_metric import Response_Quality_Metric
from business_objects.dog.obedience_level import Obedience_Level
from business_objects.dog.obedience_level import Obedience_Level
from business_objects.dog.assessment_command_modality_link import Assessment_Command_Modality_Link
from business_objects.dog.assessment_command_link import Assessment_Command_Link
from business_objects.dog.user import User
from extensions import db
from forms.dog.assessment import Filters_Assessment
@@ -29,7 +29,7 @@ from typing import ClassVar, Optional
class Assessment_Response(SQLAlchemy_ABC, Base):
ATTR_ID_ASSESSMENT_RESPONSE: ClassVar[str] = 'id_response'
FLAG_ASSESSMENT_RESPONSE: ClassVar[str] = Assessment_Command_Modality_Link.FLAG_ASSESSMENT_RESPONSE
FLAG_ASSESSMENT_RESPONSE: ClassVar[str] = Assessment_Command_Link.FLAG_ASSESSMENT_RESPONSE
FLAG_VALUE_MEASURED: ClassVar[str] = 'value-measured'
NAME_ATTR_OPTION_VALUE: ClassVar[str] = ATTR_ID_ASSESSMENT_RESPONSE
NAME_ATTR_OPTION_TEXT: ClassVar[str] = ATTR_ID_ASSESSMENT_RESPONSE
@@ -38,7 +38,7 @@ class Assessment_Response(SQLAlchemy_ABC, Base):
__table_args__ = { 'extend_existing': True }
id_response = db.Column(db.Integer, primary_key=True)
id_assessment_command_modality_link = db.Column(db.Integer)
id_assessment_command_link = db.Column(db.Integer)
id_response_quality_metric = db.Column(db.Integer)
id_obedience_level = db.Column(db.Integer)
value_measured = db.Column(db.Float)
@@ -49,7 +49,7 @@ class Assessment_Response(SQLAlchemy_ABC, Base):
def __init__(self):
self.id_response = 0
self.is_new = False
self.assessment_command_modality_link = None
self.assessment_command_link = None
self.response_quality_metric = None
self.obedience_level = None
super().__init__()
@@ -59,14 +59,14 @@ class Assessment_Response(SQLAlchemy_ABC, Base):
_m = f'{cls.__qualname__}.from_db_assessment_response'
assessment_response = cls()
assessment_response.id_response = query_row[0]
assessment_response.id_assessment_command_modality_link = query_row[1]
assessment_response.id_assessment_command_link = query_row[1]
assessment_response.id_response_quality_metric = query_row[2]
assessment_response.id_obedience_level = query_row[5]
assessment_response.value_measured = query_row[7]
assessment_response.notes = query_row[8]
assessment_response.active = av.input_bool(query_row[9], 'active', _m)
assessment_response.assessment_command_modality_link = Assessment_Command_Modality_Link.from_db_assessment_response(query_row)
assessment_response.assessment_command_link = Assessment_Command_Link.from_db_assessment_response(query_row)
assessment_response.response_quality_metric = Response_Quality_Metric.from_db_assessment_response(query_row)
assessment_response.obedience_level = Obedience_Level.from_db_assessment_response(query_row)
return assessment_response
@@ -77,7 +77,7 @@ class Assessment_Response(SQLAlchemy_ABC, Base):
assessment_response = cls()
if json is None: return assessment_response
assessment_response.id_response = json.get(Assessment_Response.ATTR_ID_ASSESSMENT_RESPONSE, -1)
assessment_response.id_assessment_command_modality_link = json[Assessment_Command_Modality_Link.ATTR_ID_ASSESSMENT_COMMAND_MODALITY_LINK]
assessment_response.id_assessment_command_link = json[Assessment_Command_Link.ATTR_ID_ASSESSMENT_COMMAND_LINK]
assessment_response.id_response_quality_metric = json[Response_Quality_Metric.ATTR_ID_RESPONSE_QUALITY_METRIC]
assessment_response.id_obedience_level = json[Obedience_Level.ATTR_ID_OBEDIENCE_LEVEL]
assessment_response.value_measured = json[cls.FLAG_VALUE_MEASURED]
@@ -90,7 +90,7 @@ class Assessment_Response(SQLAlchemy_ABC, Base):
as_json = {
**self.get_shared_json_attributes(self)
, self.ATTR_ID_ASSESSMENT_RESPONSE: self.id_response
, Assessment_Command_Modality_Link.ATTR_ID_ASSESSMENT_COMMAND_MODALITY_LINK: { Assessment_Command_Modality_Link.ATTR_ID_ASSESSMENT_COMMAND_MODALITY_LINK: None } if self.assessment_command_modality_link is None else self.assessment_command_modality_link.to_json()
, Assessment_Command_Link.ATTR_ID_ASSESSMENT_COMMAND_LINK: { Assessment_Command_Link.ATTR_ID_ASSESSMENT_COMMAND_LINK: None } if self.assessment_command_link is None else self.assessment_command_link.to_json()
, Response_Quality_Metric.ATTR_ID_RESPONSE_QUALITY_METRIC: { Response_Quality_Metric.ATTR_ID_RESPONSE_QUALITY_METRIC: None } if self.response_quality_metric is None else self.response_quality_metric.to_json()
, Obedience_Level.ATTR_ID_OBEDIENCE_LEVEL: { Obedience_Level.ATTR_ID_OBEDIENCE_LEVEL: None } if self.obedience_level is None else self.obedience_level.to_json()
, self.FLAG_VALUE_MEASURED: self.value_measured
@@ -104,7 +104,7 @@ class Assessment_Response(SQLAlchemy_ABC, Base):
return f'''
{self.__class__.__name__}(
{self.FLAG_ASSESSMENT_RESPONSE}: {self.id_response}
{Assessment_Command_Modality_Link.FLAG_ASSESSMENT_COMMAND_MODALITY_LINK}: {self.assessment_command_modality_link}
{Assessment_Command_Link.FLAG_ASSESSMENT_COMMAND_LINK}: {self.assessment_command_link}
{Response_Quality_Metric.FLAG_RESPONSE_QUALITY_METRIC}: {self.response_quality_metric}
{Obedience_Level.FLAG_OBEDIENCE_LEVEL}: {self.obedience_level}
{self.FLAG_VALUE_MEASURED}: {self.value_measured}
@@ -120,7 +120,7 @@ class Assessment_Response_Temp(db.Model, Base):
__table_args__ = { 'extend_existing': True }
id_temp = db.Column(db.Integer, primary_key=True)
id_response = db.Column(db.Integer)
id_assessment_command_modality_link = db.Column(db.Integer)
id_assessment_command_link = db.Column(db.Integer)
id_response_quality_metric = db.Column(db.Integer)
id_obedience_level = db.Column(db.Integer)
value_measured = db.Column(db.Float)
@@ -137,7 +137,7 @@ class Assessment_Response_Temp(db.Model, Base):
_m = 'Assessment_Response_Temp.from_assessment_response'
temp = cls()
temp.id_response = assessment_response.id_response
temp.id_assessment_command_modality_link = assessment_response.id_assessment_command_modality_link
temp.id_assessment_command_link = assessment_response.id_assessment_command_link
temp.id_response_quality_metric = assessment_response.id_response_quality_metric
temp.id_obedience_level = assessment_response.id_obedience_level
temp.value_measured = assessment_response.value_measured
@@ -155,23 +155,28 @@ class Parameters_Assessment_Response(Get_Many_Parameters_Base):
min_value_measured_assessment_response: Optional[float]
max_value_measured_assessment_response: Optional[float]
get_all_ACM_link: bool
get_inactive_ACM_link: bool
ids_ACM_link: str
min_distance_from_handler_metres_ACM_link: Optional[float]
max_distance_from_handler_metres_ACM_link: Optional[float]
value_is_in_sight_of_handler_ACM_link: Optional[bool]
value_is_in_scent_range_of_handler_ACM_link: Optional[bool]
value_is_in_hearing_range_of_handler_ACM_link: Optional[bool]
value_is_on_lead_ACM_link: Optional[bool]
min_trial_count_ACM_link: Optional[float]
max_trial_count_ACM_link: Optional[float]
get_all_AC_link: bool
get_inactive_AC_link: bool
ids_AC_link: str
min_distance_from_handler_metres_AC_link: Optional[float]
max_distance_from_handler_metres_AC_link: Optional[float]
value_is_in_sight_of_handler_AC_link: Optional[bool]
value_is_in_scent_range_of_handler_AC_link: Optional[bool]
value_is_in_hearing_range_of_handler_AC_link: Optional[bool]
value_is_on_lead_AC_link: Optional[bool]
min_trial_count_AC_link: Optional[float]
max_trial_count_AC_link: Optional[float]
get_all_assessment: bool
get_inactive_assessment: bool
ids_assessment: str
notes_assessment: str
min_temperature_assessment: Optional[float]
max_temperature_assessment: Optional[float]
get_all_assessment_type: bool
get_inactive_assessment_type: bool
ids_assessment_type: str
names_assessment_type: str
get_all_weather: bool
get_inactive_weather: bool
ids_weather: str
@@ -190,6 +195,7 @@ class Parameters_Assessment_Response(Get_Many_Parameters_Base):
#auth0_ids_user_handler: str
names_user_handler: str
emails_user_handler: str
get_all_command_category: bool
get_inactive_command_category: bool
ids_command_category: str
@@ -200,14 +206,11 @@ class Parameters_Assessment_Response(Get_Many_Parameters_Base):
names_command: str
hand_signal_default_descriptions_command: str
notes_command: str
get_all_command_modality: bool
get_inactive_command_modality: bool
ids_command_modality: str
names_command_modality: str
get_all_bribe: bool
get_inactive_bribe: bool
ids_bribe: str
names_bribe: str
get_all_reinforcement_schedule: bool
get_inactive_reinforcement_schedule: bool
ids_reinforcement_schedule: str
names_reinforcement_schedule: str
get_all_response_quality_metric: bool
get_inactive_response_quality_metric: bool
@@ -234,23 +237,28 @@ class Parameters_Assessment_Response(Get_Many_Parameters_Base):
, min_value_measured_assessment_response = None
, max_value_measured_assessment_response = None
, get_all_ACM_link = True
, get_inactive_ACM_link = False
, ids_ACM_link = ''
, min_distance_from_handler_metres_ACM_link = None
, max_distance_from_handler_metres_ACM_link = None
, value_is_in_sight_of_handler_ACM_link = None
, value_is_in_scent_range_of_handler_ACM_link = None
, value_is_in_hearing_range_of_handler_ACM_link = None
, value_is_on_lead_ACM_link = None
, min_trial_count_ACM_link = None
, max_trial_count_ACM_link = None
, get_all_AC_link = True
, get_inactive_AC_link = False
, ids_AC_link = ''
, min_distance_from_handler_metres_AC_link = None
, max_distance_from_handler_metres_AC_link = None
, value_is_in_sight_of_handler_AC_link = None
, value_is_in_scent_range_of_handler_AC_link = None
, value_is_in_hearing_range_of_handler_AC_link = None
, value_is_on_lead_AC_link = None
, min_trial_count_AC_link = None
, max_trial_count_AC_link = None
, get_all_assessment = True
, get_inactive_assessment = False
, ids_assessment = ''
, notes_assessment = ''
, min_temperature_assessment = None
, max_temperature_assessment = None
, get_all_assessment_type = True
, get_inactive_assessment_type = False
, ids_assessment_type = ''
, names_assessment_type = ''
, get_all_weather = True
, get_inactive_weather = False
, ids_weather = ''
@@ -269,6 +277,7 @@ class Parameters_Assessment_Response(Get_Many_Parameters_Base):
# , auth0_ids_user_handler = ''
, names_user_handler = ''
, emails_user_handler = ''
, get_all_command_category = True
, get_inactive_command_category = False
, ids_command_category = ''
@@ -279,14 +288,11 @@ class Parameters_Assessment_Response(Get_Many_Parameters_Base):
, names_command = ''
, hand_signal_default_descriptions_command = ''
, notes_command = ''
, get_all_command_modality = True
, get_inactive_command_modality = False
, ids_command_modality = ''
, names_command_modality = ''
, get_all_bribe = True
, get_inactive_bribe = False
, ids_bribe = ''
, names_bribe = ''
, get_all_reinforcement_schedule = True
, get_inactive_reinforcement_schedule = False
, ids_reinforcement_schedule = ''
, names_reinforcement_schedule = ''
, get_all_response_quality_metric = True
, get_inactive_response_quality_metric = False
@@ -314,24 +320,29 @@ class Parameters_Assessment_Response(Get_Many_Parameters_Base):
, min_value_measured_assessment_response = json.get('a_min_value_measured_assessment_response', None)
, max_value_measured_assessment_response = json.get('a_max_value_measured_assessment_response', None)
, get_all_ACM_link = json.get('a_get_all_ACM_link', False)
, get_inactive_ACM_link = json.get('a_get_inactive_ACM_link', False)
, ids_ACM_link = json.get('a_ids_ACM_link', '')
, notes_assessment_command_modality_link = json.get('a_notes_assessment_command_modality_link', '')
, min_distance_from_handler_metres_ACM_link = json.get('a_min_distance_from_handler_metres_ACM_link', None)
, max_distance_from_handler_metres_ACM_link = json.get('a_max_distance_from_handler_metres_ACM_link', None)
, value_is_in_sight_of_handler_ACM_link = json.get('a_value_is_in_sight_of_handler_ACM_link', None)
, value_is_in_scent_range_of_handler_ACM_link = json.get('a_value_is_in_scent_range_of_handler_ACM_link', None)
, value_is_in_hearing_range_of_handler_ACM_link = json.get('a_value_is_in_hearing_range_of_handler_ACM_link', None)
, value_is_on_lead_ACM_link = json.get('a_value_is_on_lead_ACM_link', None)
, min_trial_count_ACM_link = json.get('a_min_trial_count_ACM_link', None)
, max_trial_count_ACM_link = json.get('a_max_trial_count_ACM_link', None)
, get_all_AC_link = json.get('a_get_all_AC_link', False)
, get_inactive_AC_link = json.get('a_get_inactive_AC_link', False)
, ids_AC_link = json.get('a_ids_AC_link', '')
, notes_assessment_command_modality_AC_link = json.get('a_notes_assessment_command_modality_AC_link', '')
, min_distance_from_handler_metres_AC_link = json.get('a_min_distance_from_handler_metres_AC_link', None)
, max_distance_from_handler_metres_AC_link = json.get('a_max_distance_from_handler_metres_AC_link', None)
, value_is_in_sight_of_handler_AC_link = json.get('a_value_is_in_sight_of_handler_AC_link', None)
, value_is_in_scent_range_of_handler_AC_link = json.get('a_value_is_in_scent_range_of_handler_AC_link', None)
, value_is_in_hearing_range_of_handler_AC_link = json.get('a_value_is_in_hearing_range_of_handler_AC_link', None)
, value_is_on_lead_AC_link = json.get('a_value_is_on_lead_AC_link', None)
, min_trial_count_AC_link = json.get('a_min_trial_count_AC_link', None)
, max_trial_count_AC_link = json.get('a_max_trial_count_AC_link', None)
, get_all_assessment = json.get('a_get_all_assessment', False)
, get_inactive_assessment = json.get('a_get_inactive_assessment', False)
, ids_assessment = json.get('a_ids_assessment', '')
, notes_assessment = json.get('a_notes_assessment', '')
, min_temperature_assessment = json.get('a_min_temperature_assessment', None)
, max_temperature_assessment = json.get('a_max_temperature_assessment', None)
, get_all_assessment_type = json.get('a_get_all_assessment_type', False)
, get_inactive_assessment_type = json.get('a_get_inactive_assessment_type', False)
, ids_assessment_type = json.get('a_ids_assessment_type', '')
, names_assessment_type = json.get('a_names_assessment_type', '')
, get_all_weather = json.get('a_get_all_weather', False)
, get_inactive_weather = json.get('a_get_inactive_weather', False)
, ids_weather = json.get('a_ids_weather', '')
@@ -350,6 +361,7 @@ class Parameters_Assessment_Response(Get_Many_Parameters_Base):
# , auth0_ids_user_handler = json.get('a_ids_user_handler', '')
, names_user_handler = json.get('a_names_user_handler', '')
, emails_user_handler = json.get('a_emails_user_handler', '')
, get_all_command_category = json.get('a_get_all_command_category', False)
, get_inactive_command_category = json.get('a_get_inactive_command_category', False)
, ids_command_category = json.get('a_ids_command_category', '')
@@ -360,14 +372,11 @@ class Parameters_Assessment_Response(Get_Many_Parameters_Base):
, names_command = json.get('a_names_command', '')
, hand_signal_default_descriptions_command = json.get('a_hand_signal_default_descriptions_command', '')
, notes_command = json.get('a_notes_command', '')
, get_all_command_modality = json.get('a_get_all_command_modality', False)
, get_inactive_command_modality = json.get('a_get_inactive_command_modality', False)
, ids_command_modality = json.get('a_ids_command_modality', '')
, names_command_modality = json.get('a_names_command_modality', '')
, get_all_bribe = json.get('a_get_all_bribe', False)
, get_inactive_bribe = json.get('a_get_inactive_bribe', False)
, ids_bribe = json.get('a_ids_bribe', '')
, names_bribe = json.get('a_names_bribe', '')
, get_all_reinforcement_schedule = json.get('a_get_all_reinforcement_schedule', False)
, get_inactive_reinforcement_schedule = json.get('a_get_inactive_reinforcement_schedule', False)
, ids_reinforcement_schedule = json.get('a_ids_reinforcement_schedule', '')
, names_reinforcement_schedule = json.get('a_names_reinforcement_schedule', '')
, get_all_response_quality_metric = json.get('a_get_all_response_quality_metric', False)
, get_inactive_response_quality_metric = json.get('a_get_inactive_response_quality_metric', False)
@@ -390,7 +399,7 @@ class Parameters_Assessment_Response(Get_Many_Parameters_Base):
_m = f'{cls.__qualname__}.from_form_filters_assessment'
av.val_instance(form, 'form', _m, Filters_Assessment)
has_filter_search_text = not (form.search.data == '' or form.search.data is None)
has_filter_assessment_command_modality_link = False
has_filter_assessment_command_link = False
has_filter_response_quality_metric = False
has_filter_obedience_level = False
has_filter_user_handler = False
@@ -401,9 +410,20 @@ class Parameters_Assessment_Response(Get_Many_Parameters_Base):
filters.get_all_assessment_response = True
filters.get_inactive_assessment_response = not active_only
filters.ids_assessment_response = ''
filters.get_all_ACM_link = not has_filter_assessment_command_modality_link
filters.get_inactive_ACM_link = not active_only
filters.ids_ACM_link = ''
filters.get_all_AC_link = True
filters.get_inactive_AC_link = not active_only
filters.ids_AC_link = ''
filters.get_all_assessment = not has_filter_assessment
filters.get_inactive_assessment = not active_only
filters.ids_assessment = form.id_assessment.data if has_filter_assessment else ''
filters.get_all_command = True
filters.get_inactive_command = not active_only
filters.ids_command = ''
filters.names_command = form.search.data if has_filter_search_text else ''
filters.get_all_reinforcement_schedule = True
filters.get_inactive_reinforcement_schedule = not active_only
filters.ids_reinforcement_schedule = ''
filters.names_reinforcement_schedule = form.search.data if has_filter_search_text else ''
filters.get_all_response_quality_metric = not has_filter_response_quality_metric
filters.get_inactive_response_quality_metric = not active_only
filters.ids_response_quality_metric = ''
@@ -431,23 +451,28 @@ class Parameters_Assessment_Response(Get_Many_Parameters_Base):
, 'a_min_value_measured_assessment_response': self.min_value_measured_assessment_response
, 'a_max_value_measured_assessment_response': self.max_value_measured_assessment_response
, 'a_get_all_ACM_link': self.get_all_ACM_link
, 'a_get_inactive_ACM_link': self.get_inactive_ACM_link
, 'a_ids_ACM_link': self.ids_ACM_link
, 'a_min_distance_from_handler_metres_ACM_link': self.min_distance_from_handler_metres_ACM_link
, 'a_max_distance_from_handler_metres_ACM_link': self.max_distance_from_handler_metres_ACM_link
, 'a_value_is_in_sight_of_handler_ACM_link': self.value_is_in_sight_of_handler_ACM_link
, 'a_value_is_in_scent_range_of_handler_ACM_link': self.value_is_in_scent_range_of_handler_ACM_link
, 'a_value_is_in_hearing_range_of_handler_ACM_link': self.value_is_in_hearing_range_of_handler_ACM_link
, 'a_value_is_on_lead_ACM_link': self.value_is_on_lead_ACM_link
, 'a_min_trial_count_ACM_link': self.min_trial_count_ACM_link
, 'a_max_trial_count_ACM_link': self.max_trial_count_ACM_link
, 'a_get_all_AC_link': self.get_all_AC_link
, 'a_get_inactive_AC_link': self.get_inactive_AC_link
, 'a_ids_AC_link': self.ids_AC_link
, 'a_min_distance_from_handler_metres_AC_link': self.min_distance_from_handler_metres_AC_link
, 'a_max_distance_from_handler_metres_AC_link': self.max_distance_from_handler_metres_AC_link
, 'a_value_is_in_sight_of_handler_AC_link': self.value_is_in_sight_of_handler_AC_link
, 'a_value_is_in_scent_range_of_handler_AC_link': self.value_is_in_scent_range_of_handler_AC_link
, 'a_value_is_in_hearing_range_of_handler_AC_link': self.value_is_in_hearing_range_of_handler_AC_link
, 'a_value_is_on_lead_AC_link': self.value_is_on_lead_AC_link
, 'a_min_trial_count_AC_link': self.min_trial_count_AC_link
, 'a_max_trial_count_AC_link': self.max_trial_count_AC_link
, 'a_get_all_assessment': self.get_all_assessment
, 'a_get_inactive_assessment': self.get_inactive_assessment
, 'a_ids_assessment': self.ids_assessment
, 'a_notes_assessment': self.notes_assessment
, 'a_min_temperature_assessment': self.min_temperature_assessment
, 'a_max_temperature_assessment': self.max_temperature_assessment
, 'a_get_all_assessment_type': self.get_all_assessment_type
, 'a_get_inactive_assessment_type': self.get_inactive_assessment_type
, 'a_ids_assessment_type': self.ids_assessment_type
, 'a_names_assessment_type': self.names_assessment_type
, 'get_all_weather': self.get_all_weather
, 'get_inactive_weather': self.get_inactive_weather
, 'ids_weather': self.ids_weather
@@ -466,6 +491,7 @@ class Parameters_Assessment_Response(Get_Many_Parameters_Base):
#, 'auth0_ids_user_handler': self.ids_user_handler
, 'names_user_handler': self.names_user_handler
, 'emails_user_handler': self.emails_user_handler
, 'a_get_all_command_category': self.get_all_command_category
, 'a_get_inactive_command_category': self.get_inactive_command_category
, 'a_ids_command_category': self.ids_command_category
@@ -476,14 +502,11 @@ class Parameters_Assessment_Response(Get_Many_Parameters_Base):
, 'a_names_command': self.names_command
, 'a_hand_signal_default_descriptions_command': self.hand_signal_default_descriptions_command
, 'a_notes_command': self.notes_command
, 'a_get_all_command_modality': self.get_all_command_modality
, 'a_get_inactive_command_modality': self.get_inactive_command_modality
, 'a_ids_command_modality': self.ids_command_modality
, 'a_names_command_modality': self.names_command_modality
, 'a_get_all_bribe': self.get_all_bribe
, 'a_get_inactive_bribe': self.get_inactive_bribe
, 'a_ids_bribe': self.ids_bribe
, 'a_names_bribe': self.names_bribe
, 'a_get_all_reinforcement_schedule': self.get_all_reinforcement_schedule
, 'a_get_inactive_reinforcement_schedule': self.get_inactive_reinforcement_schedule
, 'a_ids_reinforcement_schedule': self.ids_reinforcement_schedule
, 'a_names_reinforcement_schedule': self.names_reinforcement_schedule
, 'a_get_all_response_quality_metric': self.get_all_response_quality_metric
, 'a_get_inactive_response_quality_metric': self.get_inactive_response_quality_metric