From 54a3133061e3dde3dc8712ada0d6c553a7f894a6 Mon Sep 17 00:00:00 2001 From: "Karl O. Pinc kop@karlpinc.com" Date: Wed, 13 May 2026 03:34:39 +0000 Subject: [PATCH] Create table, document table, and implement rules for AGGRESSIONS table --- db/schemas/lib/triggers/Makefile | 3 +- db/schemas/lib/triggers/create/aggressions.m4 | 136 ++++++++ db/schemas/lib/triggers/create/roles.m4 | 183 +++++++++++ db/schemas/lib/triggers/drop/aggressions.m4 | 23 ++ db/schemas/sokwedb/tables/Makefile | 1 + .../sokwedb/tables/create/aggressions.m4 | 52 +++ db/schemas/sokwedb/tables/create/events.m4 | 3 + doc/src/epilog.inc.m4 | 32 ++ doc/src/tables.m4 | 1 + doc/src/tables/aggression_event_log.m4 | 2 +- doc/src/tables/aggressions.m4 | 302 ++++++++++++++++++ doc/src/tables/events.m4 | 33 +- include/global_constants.m4 | 10 + 13 files changed, 778 insertions(+), 3 deletions(-) create mode 100644 db/schemas/lib/triggers/create/aggressions.m4 create mode 100644 db/schemas/lib/triggers/drop/aggressions.m4 create mode 100644 db/schemas/sokwedb/tables/create/aggressions.m4 create mode 100644 doc/src/tables/aggressions.m4 diff --git a/db/schemas/lib/triggers/Makefile b/db/schemas/lib/triggers/Makefile index c649d09..e08767d 100644 --- a/db/schemas/lib/triggers/Makefile +++ b/db/schemas/lib/triggers/Makefile @@ -32,7 +32,8 @@ ORDER := comm_ids \ follows \ events \ roles \ - arrivals + arrivals \ + aggressions DROP_EXISTING := true diff --git a/db/schemas/lib/triggers/create/aggressions.m4 b/db/schemas/lib/triggers/create/aggressions.m4 new file mode 100644 index 0000000..7f42024 --- /dev/null +++ b/db/schemas/lib/triggers/create/aggressions.m4 @@ -0,0 +1,136 @@ +dnl Copyright (C) 2026 The Meme Factory, Inc. http://www.karlpinc.com/ +dnl +dnl This program is free software: you can redistribute it and/or modify it +dnl under the terms of the GNU Affero General Public License as published by +dnl the Free Software Foundation, either version 3 of the License, or +dnl (at your option) any later version. +dnl +dnl This program is distributed in the hope that it will be useful, +dnl but WITHOUT ANY WARRANTY; without even the implied warranty of +dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +dnl GNU Affero General Public License for more details. +dnl +dnl You should have received a copy of the GNU Affero General Public License +dnl along with this program. If not, see . +dnl +dnl Triggers for the aggressions table +dnl +dnl Karl O. Pinc + +dnl m4 includes +include(`copyright.m4')dnl +include(`constants.m4')dnl +include(`macros.m4')dnl + + +RAISE INFO 'aggressions_func'; +CREATE OR REPLACE FUNCTION aggressions_func () + RETURNS trigger + LANGUAGE plpgsql + sdb_function_set_search_path + AS $$ + BEGIN + -- Function for aggressions insert and update triggers + -- + -- AGPL_notice(` --', `2026', + `The Meme Factory, Inc., www.karlpinc.com') + + IF TG_OP = 'UPDATE' THEN + cannot_change(`AGGRESSIONS', `AgID') + END IF; + + -- The EVENTS.Behavior must be sdb_aggression + IF TG_OP = 'INSERT' + OR NEW.EID <> OLD.EID THEN + DECLARE + -- EVENTS + a_behavior events.behavior%TYPE; + a_start events.start%TYPE; + a_stop events.stop%TYPE; + -- FOLLOWS + a_fid follows.fid%TYPE; + a_focal follows.focal%TYPE; + a_date follows.date%TYPE; + -- ROLES + a_pid roles.pid%TYPE; + a_role roles.role%TYPE; + a_participant roles.participant%TYPE; + + BEGIN + SELECT events.behavior, events.start, events.stop + , follows.fid, follows.focal, follows.date + , roles.pid, roles.role, roles.participant + INTO a_behavior , a_start , a_stop + , a_fid , a_focal , a_date + , a_pid , a_role , a_participant + FROM events + JOIN follows ON (follows.fid = events.fid) + LEFT OUTER JOIN roles ON (roles.eid = events.eid) + WHERE events.eid = NEW.eid + AND events.behavior <> 'sdb_aggression'; + IF FOUND THEN + RAISE EXCEPTION integrity_constraint_violation USING + MESSAGE = 'Error on ' || TG_OP || ' of AGGRESSIONS' + , DETAIL = 'Aggressions can only be related to an event with an' + || ' EVENTS.Behavior value of (sdb_aggression)' + || ': Key (AgID = (' + || NEW.agid + || '): Value (Decided) = (' + || NEW.Decided + || '): Value (MultiAggressors) = (' + || NEW.multiaggressors + || '): Value (MultiRecipients) = (' + || NEW.multirecipients + || '): Value (BadObs) = (' + || NEW.badobs + || '): Value (Bristle) = (' + || NEW.bristle + || '): Value (Display) = (' + || NEW.display + || '): Value (Chase) = (' + || NEW.chase + || '): Value (Contact) = (' + || NEW.contact + || '): Value (Vocal) = (' + || NEW.vocal + || '): Value (severity) = (' + || NEW.severity + || '): Value (Community) = (' + || NEW.community + || '): Value (ExtractedBy) = (' + || NEW.extractedby + || '): Key (ROLES.PID) = (' + || textualize(`a_pid') + || '), Value (ROLES.Role) = (' + || textualize(`a_role') + || '), Value (ROLES.Participant) = (' + || textualize(`a_participant') + || '): Key (EVENTS.EID) = (' + || NEW.eid + || '): Value (EVENTS.Behavior) = (' + || a_behavior + || '), Value (EVENTS.Start) = (' + || a_start + || '), Value (EVENTS.Stop) = (' + || a_stop + || '): Key (FOLLOWS.FID) = (' + || a_fid + || '), Value (FOLLOWS.Focal) = (' + || a_focal + || '), Value (FOLLOWS.Date) = (' + || a_date + || ')'; + END IF; + END; + END IF; + + RETURN NULL; + END; +$$; + + +RAISE INFO 'aggressions_trigger'; +CREATE TRIGGER aggressions_trigger + AFTER INSERT OR UPDATE + ON aggressions FOR EACH ROW + EXECUTE PROCEDURE aggressions_func(); diff --git a/db/schemas/lib/triggers/create/roles.m4 b/db/schemas/lib/triggers/create/roles.m4 index ce83ff7..4fb22b3 100644 --- a/db/schemas/lib/triggers/create/roles.m4 +++ b/db/schemas/lib/triggers/create/roles.m4 @@ -221,6 +221,189 @@ CREATE OR REPLACE FUNCTION roles_func () END; END IF; + -- + -- Validate aggression events + -- + IF TG_OP = 'INSERT' + AND a_behavior = 'sdb_aggression' THEN + DECLARE + a_pid roles.pid%TYPE; + a_role roles.role%TYPE; + a_participant roles.participant%TYPE; + a_focal follows.focal%TYPE; + a_date follows.date%TYPE; + a_community follows.community%TYPE; + + BEGIN + -- + -- Validate ROLES.Role for aggression events + -- + IF NEW.role <> 'sdb_actor' + AND NEW.role <> 'sdb_actee' THEN + -- The ROLES rows for aggression events must have a role of sdb_actor + -- or sdb_actee. + SELECT follows.focal, follows.date, follows.community + INTO a_focal , a_date , a_community + FROM follows + WHERE follows.fid = a_fid; + IF FOUND THEN + RAISE EXCEPTION integrity_constraint_violation USING + MESSAGE = 'Error on INSERT of ROLES' + , DETAIL = 'Invalid Role value:' + || ' Inserting: Key (PID) = (' + || NEW.pid + || '), Value (EID) = (' + || NEW.eid + || '), Value (Role) = (' + || NEW.role + || '), Value (Participant) = (' + || NEW.participant + || '), Value (EVENTS.Behavior) = (' + || a_behavior + || '), Value (EVENTS.Start) = (' + || a_start + || '), Value (EVENTS.Stop) = (' + || a_stop + || '), Value (FOLLOWS.FID) = (' + || a_fid + || '), Value (FOLLOWS.Focal) = (' + || a_focal + || '), Value (FOLLOWS.Date) = (' + || a_date + || '), Value (FOLLOWS.Community) = (' + || a_community + || ')' + , HINT = 'The ROLES.Role must be either (sdb_actor)' + || ' or (sdb_actee) for an event' + || ' with a EVENTS.Behavior of (sdb_aggression).'; + END IF; + END IF; + + -- There can be only one row with each aggression role per + -- aggression event. + SELECT roles.pid, roles.role, roles.participant + , follows.focal, follows.date, follows.community + INTO a_pid , a_role , a_participant + , a_focal , a_date , a_community + FROM roles + , follows + WHERE roles.eid = NEW.eid + AND roles.pid <> NEW.pid + AND roles.role = NEW.role + AND follows.fid = a_fid; + IF FOUND THEN + RAISE EXCEPTION integrity_constraint_violation USING + MESSAGE = 'Error on INSERT of ROLES' + , DETAIL = 'There cannot be more than one row on ROLES' + || ' with a ROLES.Role value of (' + || NEW.role + || ') for an' + || ' event with a EVENTS.Behavior of (sdb_arrival):' + || ' Inserting: Key (PID) = (' + || NEW.pid + || '), Value (EID) = (' + || NEW.eid + || '), Value (Role) = (' + || NEW.role + || '), Value (Participant) = (' + || NEW.participant + || '): But the following ROLES row already exists:' + || ': Key (PID) = (' + || a_pid + || '), Value (Role) = (' + || a_role + || '), Value (Participant) = (' + || a_participant + || '), Value (EVENTS.Behavior) = (' + || a_behavior + || '), Value (EVENTS.Start) = (' + || a_start + || '), Value (EVENTS.Stop) = (' + || a_stop + || '), Value (FOLLOWS.FID) = (' + || a_fid + || '), Value (FOLLOWS.Focal) = (' + || a_focal + || '), Value (FOLLOWS.Date) = (' + || a_date + || '), Value (FOLLOWS.Community) = (' + || a_community + || ')'; + END IF; + END; + END IF; + + -- + -- Depending on the behavior, when there are multiple participants + -- each must be distinct. + -- + IF TG_OP = 'INSERT' + AND a_behavior = 'sdb_aggression' THEN + DECLARE + a_pid roles.pid%TYPE; + a_role roles.role%TYPE; + a_focal follows.focal%TYPE; + a_date follows.date%TYPE; + a_community follows.community%TYPE; + + BEGIN + SELECT roles.pid, roles.role + , follows.focal, follows.date, follows.community + INTO a_pid , a_role + , a_focal , a_date , a_community + FROM roles + , follows + WHERE roles.eid = NEW.eid + AND roles.pid <> NEW.pid + AND roles.role = NEW.role + AND roles.participant = NEW.participant + AND follows.fid = a_fid; + IF FOUND THEN + RAISE EXCEPTION integrity_constraint_violation USING + MESSAGE = 'Error on INSERT of ROLES' + , DETAIL = 'There cannot be more than one row on ROLES' + || ' with a ROLES.Participant value of (' + || NEW.participant + || ') related to a single ' + || a_behavior + || ' EVENTS row:' + || ' Inserting: Key (PID) = (' + || NEW.pid + || '), Value (EID) = (' + || NEW.eid + || '), Value (Role) = (' + || NEW.role + || '), Value (Participant) = (' + || NEW.participant + || '): But the following ROLES row already exists:' + || ': Key (PID) = (' + || a_pid + || '), Value (Role) = (' + || a_role + || '), Value (Participant) = (' + || NEW.participant + || '), Value (EVENTS.Behavior) = (' + || a_behavior + || '), Value (EVENTS.Start) = (' + || a_start + || '), Value (EVENTS.Stop) = (' + || a_stop + || '), Value (FOLLOWS.FID) = (' + || a_fid + || '), Value (FOLLOWS.Focal) = (' + || a_focal + || '), Value (FOLLOWS.Date) = (' + || a_date + || '), Value (FOLLOWS.Community) = (' + || a_community + || ')' + , HINT = 'The participants in an ' + || a_behavior + || ' event must be unique.'; + END IF; + END; + END IF; + RETURN NULL; END; $$; diff --git a/db/schemas/lib/triggers/drop/aggressions.m4 b/db/schemas/lib/triggers/drop/aggressions.m4 new file mode 100644 index 0000000..c036684 --- /dev/null +++ b/db/schemas/lib/triggers/drop/aggressions.m4 @@ -0,0 +1,23 @@ +dnl Copyright (C) 2026 The Meme Factory, Inc. http://www.karlpinc.com/ +dnl +dnl This program is free software: you can redistribute it and/or modify +dnl it under the terms of the GNU Affero General Public License as published by +dnl the Free Software Foundation, either version 3 of the License, or +dnl (at your option) any later version. +dnl +dnl This program is distributed in the hope that it will be useful, +dnl but WITHOUT ANY WARRANTY; without even the implied warranty of +dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +dnl GNU Affero General Public License for more details. +dnl +dnl You should have received a copy of the GNU Affero General Public License +dnl along with this program. If not, see . +dnl +dnl Drop triggers for aggressions table +dnl +dnl Karl O. Pinc + +dnl m4 includes +include(`copyright.m4')dnl + +DROP FUNCTION IF EXISTS aggressions_func() CASCADE; diff --git a/db/schemas/sokwedb/tables/Makefile b/db/schemas/sokwedb/tables/Makefile index fd3951f..d182209 100644 --- a/db/schemas/sokwedb/tables/Makefile +++ b/db/schemas/sokwedb/tables/Makefile @@ -35,6 +35,7 @@ ORDER := biography_data \ humans \ species_present \ arrivals \ + aggressions \ aggression_event_log ## ## CAUTION: This Makefile is not designed to be run directly. It is normally diff --git a/db/schemas/sokwedb/tables/create/aggressions.m4 b/db/schemas/sokwedb/tables/create/aggressions.m4 new file mode 100644 index 0000000..bb7d905 --- /dev/null +++ b/db/schemas/sokwedb/tables/create/aggressions.m4 @@ -0,0 +1,52 @@ +dnl Copyright (C) 2026 The Meme Factory, Inc., http://www.karlpinc.com/ +dnl +dnl This program is free software: you can redistribute it and/or modify +dnl it under the terms of the GNU Affero General Public License as published +dnl by the Free Software Foundation, either version 3 of the License, or +dnl (at your option) any later version. +dnl +dnl This program is distributed in the hope that it will be useful, +dnl but WITHOUT ANY WARRANTY; without even the implied warranty of +dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +dnl GNU Affero General Public License for more details. +dnl +dnl You should have received a copy of the GNU Affero General Public License +dnl along with this program. If not, see . +dnl +dnl Karl O. Pinc +dnl +dnl +dnl m4 includes +include(`copyright.m4')dnl +include(`constants.m4')dnl +include(`tablemacros.m4')dnl +include(`grants.m4')dnl +dnl + +CREATE TABLE aggressions ( + key_column(`AGGRESSIONS', `AgID', INTEGER) + ,eid INTEGER NOT NULL + REFERENCES events + ,decided BOOLEAN NOT NULL + ,multiaggressors BOOLEAN NOT NULL + ,multirecipients BOOLEAN NOT NULL + ,badobs BOOLEAN NOT NULL + ,bristle BOOLEAN NOT NULL + ,display BOOLEAN NOT NULL + ,chase BOOLEAN NOT NULL + ,contact BOOLEAN NOT NULL + ,vocal BOOLEAN NOT NULL + ,severity INTEGER NOT NULL + CONSTRAINT + "Severity must be one of: sdb_no_severity, sdb_low_severity, sdb_medium_severity, sdb_high_severity" + CHECK (severity = sdb_no_severity + OR severity = sdb_low_severity + OR severity = sdb_medium_severity + OR severity = sdb_high_severity) + ,community TEXT NOT NULL + REFERENCES comm_ids + ,extractedby TEXT NOT NULL + REFERENCES people +); + +grant_priv(`ARRIVALS') diff --git a/db/schemas/sokwedb/tables/create/events.m4 b/db/schemas/sokwedb/tables/create/events.m4 index 8fb2a19..608be3c 100644 --- a/db/schemas/sokwedb/tables/create/events.m4 +++ b/db/schemas/sokwedb/tables/create/events.m4 @@ -51,6 +51,9 @@ CREATE TABLE events ( CONSTRAINT "Start cannot be after Stop" CHECK (start <= stop) + CONSTRAINT "When the Behavior is (sdb_aggression) Start must equal Stop" + CHECK (behavior <> 'sdb_aggression' + OR start = stop) ); grant_priv(`EVENTS') diff --git a/doc/src/epilog.inc.m4 b/doc/src/epilog.inc.m4 index da8ff32..f4cdd9c 100644 --- a/doc/src/epilog.inc.m4 +++ b/doc/src/epilog.inc.m4 @@ -81,6 +81,38 @@ sdb_generated_rst()dnl replace:: :ref:`Notes ` +.. |AGGRESSIONS| + replace:: :ref:`AGGRESSIONS ` +.. |AGGRESSIONS.AgID| + replace:: :ref:`AgID ` +.. |AGGRESSIONS.EID| + replace:: :ref:`EID ` +.. |AGGRESSIONS.Decided| + replace:: :ref:`EID ` +.. |AGGRESSIONS.MultiAggressors| + replace:: :ref:`EID ` +.. |AGGRESSIONS.MultiRecipients| + replace:: :ref:`EID ` +.. |AGGRESSIONS.BadObs| + replace:: :ref:`EID ` +.. |AGGRESSIONS.Bristle| + replace:: :ref:`EID ` +.. |AGGRESSIONS.Display| + replace:: :ref:`EID ` +.. |AGGRESSIONS.Chase| + replace:: :ref:`EID ` +.. |AGGRESSIONS.Contact| + replace:: :ref:`EID ` +.. |AGGRESSIONS.Vocal| + replace:: :ref:`EID ` +.. |AGGRESSIONS.Severity| + replace:: :ref:`EID ` +.. |AGGRESSIONS.Community| + replace:: :ref:`EID ` +.. |AGGRESSIONS.ExtractedBy| + replace:: :ref:`EID ` + + .. |ARRIVALS| replace:: :ref:`ARRIVALS ` .. |ARRIVALS.ArID| diff --git a/doc/src/tables.m4 b/doc/src/tables.m4 index 4e1d5d4..ba19d30 100644 --- a/doc/src/tables.m4 +++ b/doc/src/tables.m4 @@ -33,6 +33,7 @@ and are therefore the result of at least a rudimentary analytical process. :maxdepth: 3 tables/aggression_event_log.rst + tables/aggressions.rst tables/arrivals.rst tables/biography_data.rst tables/biography_log.rst diff --git a/doc/src/tables/aggression_event_log.m4 b/doc/src/tables/aggression_event_log.m4 index 8926be7..2dc001f 100644 --- a/doc/src/tables/aggression_event_log.m4 +++ b/doc/src/tables/aggression_event_log.m4 @@ -27,7 +27,7 @@ AGGRESSION_EVENT_LOG .. |AGGRESSION_EVENT_LOG_summary| replace:: Each row contains information on the source of the data in the - AGGRESSIONS table. + |AGGRESSIONS| table. There is, at most, one row per-community, per-year. |AGGRESSION_EVENT_LOG_summary| diff --git a/doc/src/tables/aggressions.m4 b/doc/src/tables/aggressions.m4 new file mode 100644 index 0000000..73aa230 --- /dev/null +++ b/doc/src/tables/aggressions.m4 @@ -0,0 +1,302 @@ +.. Copyright (C) 2026 The Meme Factory, Inc. www.karlpinc.com + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero 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 Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . + +.. M4 setup +include(constants.m4)dnl +include(macros.m4)dnl +sdb_rst_quotes(`on')dnl +sdb_generated_rst()dnl + +.. _AGGRESSIONS: + +AGGRESSIONS +----------- + +.. |AGGRESSIONS_summary| replace:: + Each row, taken together with the related |EVENTS| row, represents + an aggression event recording during a follow. + Aggressions are recorded as dyadic pairs. + +|AGGRESSIONS_summary| + +When there are multiple individuals, whether aggressor or recipient, +involved in simultaneous aggressive behavior, there should be multiple +rows in the AGGRESSIONS table. +There should be one row for each dyad. +When mutiple individuals are involved in aggressive behavior this is +flagged in the |AGGRESSIONS.MultiAggressors| and +|AGGRESSIONS.MultiRecipients| columns. +The system generates a warning when either of these columns are |true| +and there are not multiple dyads present, having identical follow and +time information, and sharing one of the individuals involved. + +.. caution:: + + The system's design cannot distinguish between multiple multi-party + aggression events that are recorded as part of a single follow and + occur at a given time, and a single, larger, multi-party aggression + event recorded in the given follow at the given time.\ [#f1]_ [#f2]_ + +The related |EVENTS| row must be an aggression event; it must have an +|EVENTS|.\ |EVENTS.Behavior| value of ``sdb_aggression``. +This related |EVENTS| row supplies the time of the aggression and +relates to the follow, and the |ROLES| role related to the event +supplies information on the individual arriving and departing. + +The system will generate a warning if a participant in the aggression +is not present at the time of the aggression. +This means that the related |ROLES|.\ |ROLES.Participant| must have +been recorded in the follow as an arriving individual and the |EVENTS| +row related to the arrival has an |EVENTS|.\ |EVENTS.Start| that is +the same as or before the aggression time and an |EVENTS|.\ +|EVENTS.Stop| that is the same or after the aggression time. + +For further information, including additional data integrity rules, +see the documentation of the :ref:`EVENTS ` +table. + +.. contents:: + :depth: 2 + + +.. _AGGRESSIONS.AgID: + +AgID (Aggression ID) +```````````````````` + +.. |AGGRESSIONS.AgID_summary| replace:: |idcol| + +|AGGRESSIONS.AgID_summary| |notnull| + + +.. _AGGRESSIONS.EID: + +EID (Event ID) +`````````````` + +.. |AGGRESSIONS.EID_summary| replace:: + The |EVENTS|.\ |EVENTS.EID| identifying the aggression event. + +|AGGRESSIONS.EID_summary| +The related event contains information on the time of the aggression +and is related to the participants in the aggression event. + +|notnull| + + +.. _AGGRESSIONS.Decided: + +Decided +``````` + +.. |AGGRESSIONS.Decided_summary| replace:: + A |boolean|, |true| when there was a clear winner or loser. + |false| when there was not, or when there is no data. + +|AGGRESSIONS.Decided_summary| +See the |AGGRESSION_EVENT_LOG| table for information as to whether or +not this column contains useful information. + +|notnull| + + +.. _AGGRESSIONS.MultiAggressors: + +MultiAggressors +``````````````` + +.. |AGGRESSIONS.MultiAggressors_summary| replace:: + A |boolean|, whether or not there were multiple aggressors. + True when there were multiple aggressors. + False when there were not multiple aggressors. + +|AGGRESSIONS.MultiAggressors_summary| |notnull| + + +.. _AGGRESSIONS.MultiRecipients: + +MultiRecipients +``````````````` + +.. |AGGRESSIONS.MultiRecipients_summary| replace:: + A |boolean|, whether or not there were multiple recipients of + aggression. + True when there were multiple recipients of aggression. + False when there were not multiple recipients of aggression, and + for rows representing recordkeeping before the tracking of multiple + recipients was systematized. + This column is only valid from 1994 onward, with the exception of + female-to-female decided aggression. + +|AGGRESSIONS.MultiRecipients_summary| |notnull| + + +.. _AGGRESSIONS.BadObs: + +BadObs (BAD OBserversion) +````````````````````````` + +.. |AGGRESSIONS.BadObs_summary| replace:: + A |boolean|, whether or not the record of the observation was complete. + +|AGGRESSIONS.BadObs_summary| |notnull| + + +.. _AGGRESSIONS.Bristle: + +Bristle +``````` + +.. |AGGRESSIONS.Bristle_summary| replace:: + A |boolean|, whether or not the one of the participants was + recorded as bristling. + True when bristling occurred. + False when bristling did not occur, and for rows representing + recordkeeping before the tracking of bristling was systematized. + This column is only valid from 1994 onward. + +|AGGRESSIONS.Bristle_summary| |notnull| + + +.. _AGGRESSIONS.Display: + +Display +``````` + +.. |AGGRESSIONS.Display_summary| replace:: + A |boolean|, whether or not the one of the participants was + recorded as displaying. + True when a display occurred. + False when a display did not occur, and for rows representing + recordkeeping before display tracking was systematized. + This column is only valid from 1994 onward. + +|AGGRESSIONS.Display_summary| |notnull| + + +.. _AGGRESSIONS.Chase: + +Chase +````` + +.. |AGGRESSIONS.Chase_summary| replace:: + A |boolean|, whether or not the one of the participants was + recorded as chaseing. + True when a chase occurred. + False when a chase did not occur, and for rows representing + recordkeeping before the tracking of chasing was systematized. + This column is only valid from 1994 onward. + +|AGGRESSIONS.Chase_summary| |notnull| + + +.. _AGGRESSIONS.Contact: + +Contact +``````` + +.. |AGGRESSIONS.Contact_summary| replace:: + A |boolean|, whether or not the one of the participants was + recorded as contacting. + True when contact occurred. + False when contact did not occur, and for rows representing + recordkeeping before the tracking of contact was systematized. + This column is only valid from 1994 onward. + +|AGGRESSIONS.Contact_summary| |notnull| + + +.. _AGGRESSIONS.Vocal: + +Vocal +````` + +.. |AGGRESSIONS.Vocal_summary| replace:: + A |boolean|, whether or not the one of the participants was + recorded as vocalizing. + True when vocalization occurred. + False when vocalization did not occur, and for rows representing + recordkeeping before the tracking of vocalization was systematized. + This column is only valid from 1994 onward. + +|AGGRESSIONS.Vocal_summary| |notnull| + + +.. _AGGRESSIONS.Severity: + +Severity +```````` + +.. |AGGRESSIONS.Severity_summary| replace:: + An integer indicating the severity of the aggression. + One of: ``sdb_no_severity``, ``sdb_low_severity``, + ``sdb_medium_severity``, ``sdb_high_severity`` + The value ``sdb_no_severity`` indicates the lack of an assigned + severity. + +|AGGRESSIONS.Severity_summary| + +|notnull| + + +.. _AGGRESSIONS.Community: + +Community +````````` + +.. |AGGRESSIONS.Community_summary| replace:: + The community of the focal, retained as part of the data collected + on aggression for historical purposes. + +|AGGRESSIONS.Community_summary| +The |COMM_IDS|.\ |COMM_IDS.CommID| of the of the focal. + +.. note:: + This is not the canonical source of information on the focal's + community at the time of observeration or :ref:`the community under + observation when the data was collected `. + It may, in fact, differ from the community recorded elsewhere. + +|notnull| + + +.. _AGGRESSIONS.Extractedby: + +Extractedby +``````````` + +.. |AGGRESSIONS.Extractedby_summary| replace:: + The person who extracted the aggression information from the + written records and prepared it for data entry into the database. + +|AGGRESSIONS.Extractedby_summary| |notnull| + + +.. ::rubric:: Footnotes + +.. [#f1] + This is because this information has not been systematically + entered into a computerized database, so the cost/benefit ratio + does not warrant designing SoweDB in a manner that allows it to + track such information. + +.. [#f2] + Individual aggression events recorded within a single follow that + occur at the same time as other individual aggression events + occurring at the given time in the given follow are distinguished + from each other, and from multi-party aggeression events occuring + at the given time in the given follow, only because their + |AGGRESSIONS.MultiAggressors| and |AGGRESSIONS.MultiRecipients| + values are |false|. diff --git a/doc/src/tables/events.m4 b/doc/src/tables/events.m4 index afe4dc5..0c1b979 100644 --- a/doc/src/tables/events.m4 +++ b/doc/src/tables/events.m4 @@ -42,7 +42,38 @@ The following table lists these rules and implications: .. _EVENTS_aggression_code: ``sdb_aggression`` (Aggression) - A row must exist on AGGRESSIONS. + A related row must exist on |AGGRESSIONS|; there should be a row on + |AGGRESSIONS| with an |AGGRESSIONS.EID| value of the event's + |EVENTS.EID|. + There may be at most one of these related |AGGRESSIONS| rows. + The system will generate a warning when there is no |AGGRESSIONS| + row related to the aggression event. + + The |ROLES| rows related to the event, the rows with a |ROLES.EID| + value equal to the |EVENTS.EID| value, designates the + individuals involved in the aggression event. + The |ROLES|.\ |ROLES.Role| code of each individual that the |ROLES| + table relates to the aggression event describes whether that + individual aggressed or was aggressed upon during the aggression + event. + + There should be exactly two |ROLES| row related to the aggression event. + The only two |ROLES|.\ |ROLES.Role| codes allowed are ``sdb_actor`` and + ``sdb_actee``. + One of those two roles must be ``sdb_actor`` and the other must be + ``sdb_actee``. + The system will generate a warning when there are not exactly two + |ROLES| rows related to an aggression event. + + The two participants in an aggression event must be different + individuals. + This means that their |ROLES|.\ |ROLES.Participant| values must + differ. + + Both the |EVENTS|.\ |EVENTS.Start| and |EVENTS|.\ |EVENTS.Stop| + columns record the time of the aggression event. + This means the value of the EVENTS.\ |EVENTS.Start| column must + equal the value of the |EVENTS|.\ |EVENTS.Stop| column. .. _EVENTS_arrival_code: diff --git a/include/global_constants.m4 b/include/global_constants.m4 index 8bab738..11de483 100644 --- a/include/global_constants.m4 +++ b/include/global_constants.m4 @@ -50,6 +50,16 @@ dnl dnl Special values, table-specific -- hardcoded constants dnl +dnl +dnl AGGRESSIONS +dnl + +dnl The Severity levels +define(`sdb_no_severity', -1) +define(`sdb_low_severity', 0) +define(`sdb_medium_severity', 1) +define(`sdb_high_severity', 2) + dnl dnl BIOGRAPHY dnl -- 2.34.1