""" Project: PARTS Website Author: Edward Middleton-Smith Precision And Research Technology Systems Limited Technology: Business Objects Feature: Assessment_Command_Link Command Modality Link Business Object """ # internal from business_objects.base import Base from business_objects.dog.assessment import Assessment # from business_objects.dog.bribe import Bribe from business_objects.dog.command import Command # from business_objects.dog.command_category import Command_Category from business_objects.db_base import SQLAlchemy_ABC, Get_Many_Parameters_Base from business_objects.dog.dog import Dog from business_objects.dog.obedience_level import Obedience_Level from business_objects.dog.reinforcement_schedule import Reinforcement_Schedule from business_objects.dog.user import User from extensions import db from forms.dog.assessment import Filters_Assessment # from forms.dog.assessment_command_link import Filters_Assessment_Command_Link from helpers.helper_app import Helper_App import lib.argument_validation as av # external from dataclasses import dataclass from typing import ClassVar, Optional class Assessment_Command_Link(SQLAlchemy_ABC, Base): ATTR_ID_ASSESSMENT_COMMAND_LINK: ClassVar[str] = 'id_link' FLAG_ASSESSMENT_COMMAND_LINK: ClassVar[str] = Assessment.FLAG_ASSESSMENT_COMMAND_LINK FLAG_ASSESSMENT_COMMAND_MODALITY_LINK: ClassVar[str] = 'assessment_command_modality_link' FLAG_ASSESSMENT_COMMAND_TECHNIQUE_LINK: ClassVar[str] = 'assessment_command_technique_link' FLAG_ASSESSMENT_RESPONSE: ClassVar[str] = 'assessment_response' FLAG_DISTANCE_FROM_HANDLER_METRES: ClassVar[str] = 'distance-from-handler-metres' FLAG_IS_IN_HEARING_RANGE_OF_HANDLER: ClassVar[str] = 'is-in-hearing-range-of-handler' FLAG_IS_IN_SCENT_RANGE_OF_HANDLER: ClassVar[str] = 'is-in-scent-range-of-handler' FLAG_IS_IN_SIGHT_OF_HANDLER: ClassVar[str] = 'is-in-sight-of-handler' FLAG_IS_ON_LEAD: ClassVar[str] = 'is-on-lead' FLAG_TRIAL_COUNT: ClassVar[str] = 'trial-count' NAME_ATTR_OPTION_VALUE: ClassVar[str] = ATTR_ID_ASSESSMENT_COMMAND_LINK NAME_ATTR_OPTION_TEXT: ClassVar[str] = ATTR_ID_ASSESSMENT_COMMAND_LINK __tablename__ = 'DOG_Assessment_Command_Link' __table_args__ = { 'extend_existing': True } id_link = db.Column(db.Integer, primary_key=True) id_assessment = db.Column(db.Integer) id_command = db.Column(db.Integer) id_reinforcement_schedule = db.Column(db.Integer) distance_from_handler_metres = db.Column(db.Float) is_in_hearing_range_of_handler = db.Column(db.Boolean) is_in_scent_range_of_handler = db.Column(db.Boolean) is_in_sight_of_handler = db.Column(db.Boolean) is_on_lead = db.Column(db.Boolean) trial_count = db.Column(db.Integer) active = db.Column(db.Boolean) created_on = db.Column(db.DateTime) def __init__(self): self.id_link = 0 self.is_new = False self.assessment = None self.command = None self.reinforcement_schedule = None self.assessment_command_modality_links = None self.assessment_command_technique_links = None self.assessment_responses = None super().__init__() @classmethod def from_db_assessment_command_link(cls, query_row): _m = f'{cls.__qualname__}.from_db_assessment_command_link' assessment_command_link = cls() assessment_command_link.id_link = query_row[0] assessment_command_link.id_assessment = query_row[1] assessment_command_link.id_command = query_row[5] assessment_command_link.id_reinforcement_schedule = query_row[7] assessment_command_link.distance_from_handler_metres = query_row[11] assessment_command_link.is_in_hearing_range_of_handler = av.input_bool(query_row[12], 'is_in_hearing_range_of_handler', _m) assessment_command_link.is_in_scent_range_of_handler = av.input_bool(query_row[13], 'is_in_scent_range_of_handler', _m) assessment_command_link.is_in_sight_of_handler = av.input_bool(query_row[14], 'is_in_sight_of_handler', _m) assessment_command_link.is_on_lead = av.input_bool(query_row[15], 'is_on_lead', _m) assessment_command_link.trial_count = query_row[16] assessment_command_link.active = av.input_bool(query_row[17], 'active', _m) assessment_command_link.assessment = Assessment.from_db_assessment_command_link(query_row) assessment_command_link.command = Command.from_db_assessment_command_link(query_row) assessment_command_link.reinforcement_schedule = Reinforcement_Schedule.from_db_assessment_command_link(query_row) return assessment_command_link @classmethod def from_db_assessment_response(cls, query_row): _m = f'{cls.__qualname__}.from_db_assessment_response' assessment_command_link = cls() assessment_command_link.id_link = query_row[1] return assessment_command_link @classmethod def from_json(cls, json): _m = f'{cls.__qualname__}.from_json' assessment_command_link = cls() if json is None: return assessment_command_link assessment_command_link.id_link = json.get(Assessment_Command_Link.ATTR_ID_ASSESSMENT_COMMAND_LINK, -1) assessment_command_link.id_assessment = json[Assessment.ATTR_ID_ASSESSMENT] assessment_command_link.id_command = json[Command.ATTR_ID_COMMAND] assessment_command_link.id_reinforcement_schedule = json[Reinforcement_Schedule.ATTR_ID_REINFORCEMENT_SCHEDULE] assessment_command_link.distance_from_handler_metres = json[cls.FLAG_DISTANCE_FROM_HANDLER_METRES] assessment_command_link.is_in_hearing_range_of_handler = av.input_bool(json[cls.FLAG_IS_IN_HEARING_RANGE_OF_HANDLER], cls.FLAG_IS_IN_HEARING_RANGE_OF_HANDLER, _m) assessment_command_link.is_in_scent_range_of_handler = av.input_bool(json[cls.FLAG_IS_IN_SCENT_RANGE_OF_HANDLER], cls.FLAG_IS_IN_SCENT_RANGE_OF_HANDLER, _m) assessment_command_link.is_in_sight_of_handler = av.input_bool(json[cls.FLAG_IS_IN_SIGHT_OF_HANDLER], cls.FLAG_IS_IN_SIGHT_OF_HANDLER, _m) assessment_command_link.is_on_lead = av.input_bool(json[cls.FLAG_IS_ON_LEAD], cls.FLAG_IS_ON_LEAD, _m) assessment_command_link.trial_count = json.get(cls.FLAG_TRIAL_COUNT) assessment_command_link.active = av.input_bool(json[cls.FLAG_ACTIVE], cls.FLAG_ACTIVE, _m) assessment_command_link.created_on = json.get(cls.FLAG_CREATED_ON, None) return assessment_command_link def to_json(self): as_json = { **self.get_shared_json_attributes(self) , self.ATTR_ID_ASSESSMENT_COMMAND_LINK: self.id_link , Assessment.ATTR_ID_ASSESSMENT: { Assessment.ATTR_ID_ASSESSMENT: None } if self.assessment is None else self.assessment.to_json() , Command.ATTR_ID_COMMAND: { Command.ATTR_ID_COMMAND: None } if self.command is None else self.command.to_json() , Reinforcement_Schedule.ATTR_ID_REINFORCEMENT_SCHEDULE: { Reinforcement_Schedule.ATTR_ID_REINFORCEMENT_SCHEDULE: None } if self.reinforcement_schedule is None else self.reinforcement_schedule.to_json() , self.FLAG_DISTANCE_FROM_HANDLER_METRES: self.distance_from_handler_metres , self.FLAG_IS_IN_HEARING_RANGE_OF_HANDLER: self.is_in_hearing_range_of_handler , self.FLAG_IS_IN_SCENT_RANGE_OF_HANDLER: self.is_in_scent_range_of_handler , self.FLAG_IS_IN_SIGHT_OF_HANDLER: self.is_in_sight_of_handler , self.FLAG_IS_ON_LEAD: self.is_on_lead , self.FLAG_TRIAL_COUNT: self.trial_count , self.FLAG_ACTIVE: self.active , self.FLAG_CREATED_ON: self.created_on , self.FLAG_ASSESSMENT_RESPONSE: [] if self.assessment_responses is None else [response.to_json() for response in self.assessment_responses] } return as_json def __repr__(self): return f''' {self.__class__.__name__}( {self.FLAG_ASSESSMENT_COMMAND_LINK}: {self.id_link} {Assessment.FLAG_ASSESSMENT}: {self.assessment} {Command.FLAG_COMMAND}: {self.command} {Reinforcement_Schedule.FLAG_REINFORCEMENT_SCHEDULE}: {self.reinforcement_schedule} {self.FLAG_DISTANCE_FROM_HANDLER_METRES}: {self.distance_from_handler_metres} {self.FLAG_IS_IN_HEARING_RANGE_OF_HANDLER}: {self.is_in_hearing_range_of_handler} {self.FLAG_IS_IN_SCENT_RANGE_OF_HANDLER}: {self.is_in_scent_range_of_handler} {self.FLAG_IS_IN_SIGHT_OF_HANDLER}: {self.is_in_sight_of_handler} {self.FLAG_IS_ON_LEAD}: {self.is_on_lead} {self.FLAG_TRIAL_COUNT}: {self.trial_count} {self.FLAG_ACTIVE}: {self.active} {self.FLAG_CREATED_ON}: {self.created_on} ) ''' # {Command_Category.FLAG_COMMAND_CATEGORY}: {self.id_command_category} class Assessment_Command_Link_Temp(db.Model, Base): __tablename__ = 'DOG_Assessment_Command_Link_Temp' __table_args__ = { 'extend_existing': True } id_temp = db.Column(db.Integer, primary_key=True) id_link = db.Column(db.Integer) id_assessment = db.Column(db.Integer) id_command = db.Column(db.Integer) id_reinforcement_schedule = db.Column(db.Integer) distance_from_handler_metres = db.Column(db.Float) is_in_hearing_range_of_handler = db.Column(db.Boolean) is_in_scent_range_of_handler = db.Column(db.Boolean) is_in_sight_of_handler = db.Column(db.Boolean) is_on_lead = db.Column(db.Boolean) trial_count = db.Column(db.Integer) active = db.Column(db.Boolean) # created_on = db.Column(db.DateTime) guid: str = db.Column(db.String(36)) def __init__(self): super().__init__() @classmethod def from_assessment_command_link(cls, assessment_command_link): _m = f'{cls.__qualname__}.from_assessment_command_link' temp = cls() temp.id_link = assessment_command_link.id_link temp.id_assessment = assessment_command_link.id_assessment temp.id_command = assessment_command_link.id_command temp.id_reinforcement_schedule = assessment_command_link.id_reinforcement_schedule temp.distance_from_handler_metres = assessment_command_link.distance_from_handler_metres temp.is_in_hearing_range_of_handler = assessment_command_link.is_in_hearing_range_of_handler temp.is_in_scent_range_of_handler = assessment_command_link.is_in_scent_range_of_handler temp.is_in_sight_of_handler = assessment_command_link.is_in_sight_of_handler temp.is_on_lead = assessment_command_link.is_on_lead temp.trial_count = assessment_command_link.trial_count temp.active = assessment_command_link.active # temp.created_on = assessment_command_link.created_on return temp class Parameters_Assessment_Command_Link(Get_Many_Parameters_Base): get_all_link: bool get_inactive_link: bool ids_link: str min_distance_from_handler_metres_link: Optional[float] max_distance_from_handler_metres_link: Optional[float] value_is_in_sight_of_handler_link: Optional[bool] value_is_in_scent_range_of_handler_link: Optional[bool] value_is_in_hearing_range_of_handler_link: Optional[bool] value_is_on_lead_link: Optional[bool] min_trial_count_link: Optional[float] max_trial_count_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 names_weather: str get_all_lighting_level: bool get_inactive_lighting_level: bool ids_lighting_level: str names_lighting_level: str get_all_location: bool get_inactive_location: bool ids_location: str names_location: str get_all_user_handler: bool get_inactive_user_handler: bool ids_user_handler: str #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 names_command_category: str get_all_command: bool get_inactive_command: bool ids_command: str names_command: str hand_signal_default_descriptions_command: str notes_command: str get_all_reinforcement_schedule: bool get_inactive_reinforcement_schedule: bool ids_reinforcement_schedule: str names_reinforcement_schedule: str require_all_id_search_filters_met: bool require_any_id_search_filters_met: bool require_all_non_id_search_filters_met: bool require_any_non_id_search_filters_met: bool @classmethod def get_default(cls): return cls( get_all_link = True , get_inactive_link = False , ids_link = '' , min_distance_from_handler_metres_link = None , max_distance_from_handler_metres_link = None , value_is_in_sight_of_handler_link = None , value_is_in_scent_range_of_handler_link = None , value_is_in_hearing_range_of_handler_link = None , value_is_on_lead_link = None , min_trial_count_link = None , max_trial_count_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 = '' , names_weather = '' , get_all_lighting_level = True , get_inactive_lighting_level = False , ids_lighting_level = '' , names_lighting_level = '' , get_all_location = True , get_inactive_location = False , ids_location = '' , names_location = '' , get_all_user_handler = True , get_inactive_user_handler = False , ids_user_handler = '' # , auth0_ids_user_handler = '' , names_user_handler = '' , emails_user_handler = '' , get_all_command_category = True , get_inactive_command_category = False , ids_command_category = '' , names_command_category = '' , get_all_command = True , get_inactive_command = False , ids_command = '' , names_command = '' , hand_signal_default_descriptions_command = '' , notes_command = '' , get_all_reinforcement_schedule = True , get_inactive_reinforcement_schedule = False , ids_reinforcement_schedule = '' , names_reinforcement_schedule = '' , require_all_id_search_filters_met = True , require_any_id_search_filters_met = True , require_all_non_id_search_filters_met = False , require_any_non_id_search_filters_met = True ) @classmethod def from_json(cls, json): return cls( get_all_link = json.get('a_get_all_link', False) , get_inactive_link = json.get('a_get_inactive_link', False) , ids_link = json.get('a_ids_link', '') , notes_assessment_command_link = json.get('a_notes_assessment_command_link', '') , min_distance_from_handler_metres_link = json.get('a_min_distance_from_handler_metres_link', None) , max_distance_from_handler_metres_link = json.get('a_max_distance_from_handler_metres_link', None) , value_is_in_sight_of_handler_link = json.get('a_value_is_in_sight_of_handler_link', None) , value_is_in_scent_range_of_handler_link = json.get('a_value_is_in_scent_range_of_handler_link', None) , value_is_in_hearing_range_of_handler_link = json.get('a_value_is_in_hearing_range_of_handler_link', None) , value_is_on_lead_link = json.get('a_value_is_on_lead_link', None) , min_trial_count_link = json.get('a_min_trial_count_link', None) , max_trial_count_link = json.get('a_max_trial_count_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', '') , names_weather = json.get('a_names_weather', '') , get_all_lighting_level = json.get('a_get_all_lighting_level', False) , get_inactive_lighting_level = json.get('a_get_inactive_lighting_level', False) , ids_lighting_level = json.get('a_ids_lighting_level', '') , names_lighting_level = json.get('a_names_lighting_level', '') , get_all_location = json.get('a_get_all_location', False) , get_inactive_location = json.get('a_get_inactive_location', False) , ids_location = json.get('a_ids_location', '') , names_location = json.get('a_names_location', '') , get_all_user_handler = json.get('a_get_all_user_handler', False) , get_inactive_user_handler = json.get('a_get_inactive_user_handler', False) , ids_user_handler = json.get('a_ids_user_handler', '') # , 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', '') , names_command_category = json.get('a_names_command_category', '') , get_all_command = json.get('a_get_all_command', False) , get_inactive_command = json.get('a_get_inactive_command', False) , ids_command = json.get('a_ids_command', '') , 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_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', '') , require_all_id_search_filters_met = json.get('a_require_all_id_search_filters_met', True) , require_any_id_search_filters_met = json.get('a_require_any_id_search_filters_met', True) , require_all_non_id_search_filters_met = json.get('a_require_all_non_id_search_filters_met', False) , require_any_non_id_search_filters_met = json.get('a_require_any_non_id_search_filters_met', True) ) @classmethod def from_form_filters_assessment(cls, form): _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 = not (form.id_assessment.data == '0' or form.id_assessment.data == '' or form.id_assessment.data is None) has_filter_command = False has_filter_reinforcement_schedule = False active_only = av.input_bool(form.active_only.data, "active", _m) filters = cls.get_default() filters.get_all_link = True filters.get_inactive_link = not active_only filters.ids_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 = not has_filter_command 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 = not has_filter_reinforcement_schedule 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 '' return filters def to_json(self): return { 'a_get_all_link': self.get_all_link , 'a_get_inactive_link': self.get_inactive_link , 'a_ids_link': self.ids_link , 'a_min_distance_from_handler_metres_link': self.min_distance_from_handler_metres_link , 'a_max_distance_from_handler_metres_link': self.max_distance_from_handler_metres_link , 'a_value_is_in_sight_of_handler_link': self.value_is_in_sight_of_handler_link , 'a_value_is_in_scent_range_of_handler_link': self.value_is_in_scent_range_of_handler_link , 'a_value_is_in_hearing_range_of_handler_link': self.value_is_in_hearing_range_of_handler_link , 'a_value_is_on_lead_link': self.value_is_on_lead_link , 'a_min_trial_count_link': self.min_trial_count_link , 'a_max_trial_count_link': self.max_trial_count_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 , 'names_weather': self.names_weather , 'get_all_lighting_level': self.get_all_lighting_level , 'get_inactive_lighting_level': self.get_inactive_lighting_level , 'ids_lighting_level': self.ids_lighting_level , 'names_lighting_level': self.names_lighting_level , 'get_all_location': self.get_all_location , 'get_inactive_location': self.get_inactive_location , 'ids_location': self.ids_location , 'names_location': self.names_location , 'get_all_user_handler': self.get_all_user_handler , 'get_inactive_user_handler': self.get_inactive_user_handler , 'ids_user_handler': self.ids_user_handler #, '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 , 'a_names_command_category': self.names_command_category , 'a_get_all_command': self.get_all_command , 'a_get_inactive_command': self.get_inactive_command , 'a_ids_command': self.ids_command , '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_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_require_all_id_search_filters_met': self.require_all_id_search_filters_met , 'a_require_any_id_search_filters_met': self.require_any_id_search_filters_met , 'a_require_all_non_id_search_filters_met': self.require_all_non_id_search_filters_met , 'a_require_any_non_id_search_filters_met': self.require_any_non_id_search_filters_met }