Skip to content

Commit

Permalink
1817 aval entity warning (#1881)
Browse files Browse the repository at this point in the history
* add draft for aval testing

* add aval implementation

* fix mad method name  for aval testing

* add position for AVAL warnings

* add subsection to mval/aval warnings

* Add warning position subsection enum

* Implement search for multiple aval warnings

* Add aval variability to the warning message

* Add subsections to the statement warnings

* Separate relation and valency warnings in detail

* Unify warning messages

---------

Co-authored-by: adammertel <[email protected]>
  • Loading branch information
jancimertel and adammertel authored Nov 3, 2023
1 parent c040128 commit 1d728df
Show file tree
Hide file tree
Showing 9 changed files with 209 additions and 33 deletions.
24 changes: 18 additions & 6 deletions packages/client/src/components/basic/Message/Message.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,9 @@ export const Message: React.FC<Message> = ({ warning, entities }) => {
<span>
<b style={{ whiteSpace: "nowrap" }}>
Missing{" "}
{position?.section ? positionObject[position?.section] : "actant"}
{position?.subSection
? positionObject[position?.subSection]
: "actant"}
:{" "}
</b>
{"at least one actant of a matching type should be used"}
Expand All @@ -59,7 +61,8 @@ export const Message: React.FC<Message> = ({ warning, entities }) => {
return (
<span>
<b>{`Actant's entity type does not match the Action`}</b>
{position?.section && ` - ${positionObject[position?.section]}`}
{position?.subSection &&
` - ${positionObject[position?.subSection]}`}
{entity &&
` - [${entity.class}: ${getShortLabelByLetterCount(
entity.label,
Expand All @@ -71,7 +74,8 @@ export const Message: React.FC<Message> = ({ warning, entities }) => {
return (
<span>
<b>{`This actant position allows no actant`}</b>
{position?.section && ` - ${positionObject[position?.section]}`}
{position?.subSection &&
` - ${positionObject[position?.subSection]}`}
{entity &&
` - [${entity.class}: ${getShortLabelByLetterCount(
entity.label,
Expand All @@ -83,14 +87,16 @@ export const Message: React.FC<Message> = ({ warning, entities }) => {
return (
<span>
<b>{`Entity type valencies of the actions not matching`}</b>
{position?.section && ` - ${positionObject[position?.section]}`}
{position?.subSection &&
` - ${positionObject[position?.subSection]}`}
</span>
);
case WarningTypeEnums.AVU:
return (
<span>
<b>{`Action valency not defined`}</b>
{position?.section && ` - ${positionObject[position?.section]}`}
{position?.subSection &&
` - ${positionObject[position?.subSection]}`}
{entity &&
` - [${entity.class}: ${getShortLabelByLetterCount(
entity.label,
Expand All @@ -111,7 +117,13 @@ export const Message: React.FC<Message> = ({ warning, entities }) => {
case WarningTypeEnums.MVAL:
return <b>Missing at least one entity-type valency</b>;
case WarningTypeEnums.AVAL:
return <b>Asymmetrical valency</b>;
return (
<span>
<b>Asymmetrical valency </b>
{position?.subSection &&
` - ${positionObject[position?.subSection]}`}
</span>
);
case WarningTypeEnums.MAEE:
return <b>Missing action/event equivalent</b>;
default:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ import {
StyledDetailSectionContentUsedIn,
StyledDetailSectionEntityList,
StyledDetailSectionHeader,
StyledDetailWarnings,
StyledDetailWrapper,
StyledPropGroupWrap,
StyledUsedAsHeading,
Expand All @@ -50,6 +51,7 @@ import { EntityDetailMetaPropsTable } from "./EntityDetailUsedInTable/EntityDeta
import { EntityDetailStatementPropsTable } from "./EntityDetailUsedInTable/EntityDetailStatementPropsTable/EntityDetailStatementPropsTable";
import { EntityDetailStatementsTable } from "./EntityDetailUsedInTable/EntityDetailStatementsTable/EntityDetailStatementsTable";
import { EntityDetailValency } from "./EntityDetailValency/EntityDetailValency";
import { IWarningPositionSection } from "@shared/types/warning";

const allowedEntityChangeClasses = [
EntityEnums.Class.Value,
Expand Down Expand Up @@ -621,6 +623,18 @@ export const EntityDetail: React.FC<EntityDetail> = ({ detailId }) => {
{entity.class === EntityEnums.Class.Action && (
<StyledDetailSection>
<StyledDetailSectionHeader>Valency</StyledDetailSectionHeader>
<StyledDetailWarnings>
{entity.warnings &&
entity.warnings
.filter(
(w) =>
w.position?.section ===
IWarningPositionSection.Valencies
)
.map((warning, key) => {
return <Message key={key} warning={warning} />;
})}
</StyledDetailWarnings>
<StyledDetailSectionContent>
<EntityDetailValency
entity={entity}
Expand All @@ -637,10 +651,18 @@ export const EntityDetail: React.FC<EntityDetail> = ({ detailId }) => {
{/* Relations */}
<StyledDetailSection>
<StyledDetailSectionHeader>Relations</StyledDetailSectionHeader>
{entity.warnings &&
entity.warnings.map((warning, key) => {
return <Message key={key} warning={warning} />;
})}
<StyledDetailWarnings>
{entity.warnings &&
entity.warnings
.filter(
(w) =>
w.position?.section ===
IWarningPositionSection.Relations
)
.map((warning, key) => {
return <Message key={key} warning={warning} />;
})}
</StyledDetailWarnings>
<StyledDetailSectionContent>
<EntityDetailRelations
entity={entity}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,12 @@ export const StyledDetailSectionHeader = styled.div<StyledDetailSectionHeader>`
color: ${({ theme }) => theme.color["primary"]};
`;

export const StyledDetailWarnings = styled.div`
display: grid;
grid-gap: ${({ theme }) => theme.space["1"]};
grid-auto-flow: row;
`;

export const StyledDetailContentRowValueID = styled.div`
display: inline-flex;
font-style: italic;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ import { getEntityLabel, getShortLabelByLetterCount } from "utils";
import { EntityReferenceTable } from "../../EntityReferenceTable/EntityReferenceTable";
import {
StyledBreadcrumbWrap,
StyledDetailWarnings,
StyledEditorContentRow,
StyledEditorContentRowLabel,
StyledEditorContentRowValue,
Expand Down Expand Up @@ -700,6 +701,7 @@ export const StatementEditor: React.FC<StatementEditor> = ({

{statement.warnings.length > 0 && (
<StyledEditorSection>

<StyledEditorSectionHeader>
<StyledEditorSectionHeading>
{statement.warnings.length} Warnings{" "}
Expand All @@ -718,6 +720,7 @@ export const StatementEditor: React.FC<StatementEditor> = ({
/>
</StyledEditorSectionHeader>
<StyledEditorSectionContent>
<StyledDetailWarnings>
{showWarnings &&
statement.warnings
.sort((a, b) => a.type.localeCompare(b.type))
Expand All @@ -730,6 +733,7 @@ export const StatementEditor: React.FC<StatementEditor> = ({
/>
);
})}
</StyledDetailWarnings>
</StyledEditorSectionContent>
</StyledEditorSection>
)}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,12 @@ export const StyledEditorSection = styled.div<StyledEditorSection>`
}
`;

export const StyledDetailWarnings = styled.div`
display: grid;
grid-gap: ${({ theme }) => theme.space["1"]};
grid-auto-flow: row;
`;

interface StyledEditorSectionHeader {}
export const StyledEditorSectionHeader = styled.div<StyledEditorSectionHeader>`
display: flex;
Expand Down
25 changes: 25 additions & 0 deletions packages/server/src/models/entity/warnings.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -268,4 +268,29 @@ describe("models/entity/warnings", function () {
expect(maee).toBeFalsy();
});
});

describe("test hasAVAL", function () {
const db = new Db();
const [, actionEntity] = prepareEntity(EntityEnums.Class.Action);
const [, aee] = prepareRelation(RelationEnums.Type.ActionEventEquivalent);
aee.entityIds = [actionEntity.id, "random"];

beforeAll(async () => {
await db.initDb();
await aee.save(db.connection);
await actionEntity.save(db.connection);
});

afterAll(async () => {
await clean(db);
});

it("should test 1", async () => {
const sclm = await new EntityWarnings(
actionEntity.id,
actionEntity.class
).hasAVAL(db.connection);
expect(sclm).toBeFalsy();
});
});
});
108 changes: 97 additions & 11 deletions packages/server/src/models/entity/warnings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@ import Superclass from "@models/relation/superclass";
import { findEntityById } from "@service/shorthands";
import { EntityEnums, RelationEnums, WarningTypeEnums } from "@shared/enums";
import { IAction, IWarning } from "@shared/types";
import { IActionValency } from "@shared/types/action";
import { InternalServerError } from "@shared/types/errors";
import { IWarningPositionSection } from "@shared/types/warning";
import { Connection } from "rethinkdb-ts";

export default class EntityWarnings {
Expand All @@ -21,10 +23,18 @@ export default class EntityWarnings {
* @param relId
* @returns new instance of warning
*/
newWarning(warningType: WarningTypeEnums, relId?: string): IWarning {
newWarning(
warningType: WarningTypeEnums,
section: IWarningPositionSection,
pos?: keyof IActionValency
): IWarning {
return {
type: warningType,
origin: relId || "",
position: {
section: section,
subSection: pos,
},
origin: "",
};
}

Expand All @@ -51,6 +61,11 @@ export default class EntityWarnings {
warnings.push(mvalWarning);
}

const avalWarnings = await this.hasAVAL(conn);
if (avalWarnings) {
avalWarnings.forEach((w) => warnings.push(w));
}

const maeeWarning = await this.hasMAEE(conn);
if (maeeWarning) {
warnings.push(maeeWarning);
Expand Down Expand Up @@ -78,7 +93,7 @@ export default class EntityWarnings {
);

const gotSCL = !!scls.find((s) => s.entityIds[0] === this.entityId);
return gotSCL ? null : this.newWarning(WarningTypeEnums.SCLM);
return gotSCL ? null : this.newWarning(WarningTypeEnums.SCLM, IWarningPositionSection.Relations);
}

/**
Expand Down Expand Up @@ -135,19 +150,14 @@ export default class EntityWarnings {
for (const baseClassIds of Object.values(baseIdsPerConcept)) {
if (baseClassIds.indexOf(requiredBaseClassId) === -1) {
// required base class is not present for this concept
return this.newWarning(WarningTypeEnums.ISYNC);
return this.newWarning(WarningTypeEnums.ISYNC, IWarningPositionSection.Relations);
}
}
}

return null;
}

/**
* Tests if there is MVAL warning and returns it
* @param conn
* @returns
*/
async hasMVAL(conn: Connection): Promise<IWarning | null> {
if (this.class !== EntityEnums.Class.Action) {
return null;
Expand All @@ -166,12 +176,88 @@ export default class EntityWarnings {
action.data.entities.a2 === undefined &&
action.data.entities.s === undefined)
) {
return this.newWarning(WarningTypeEnums.MVAL);
return this.newWarning(WarningTypeEnums.MVAL, IWarningPositionSection.Valencies);
}

return null;
}

/**
* Tests if there is AVAL warning and returns it
* @param conn
* @returns
*/
async hasAVAL(conn: Connection): Promise<IWarning[] | null> {
if (this.class !== EntityEnums.Class.Action) {
return null;
}

const action = await findEntityById<IAction>(conn, this.entityId);
if (!action) {
throw new InternalServerError(
"action not found while checking MVAL warning"
);
}

const relations = (
await Relation.findForEntity(conn, this.entityId)
).filter(
(r) =>
[
RelationEnums.Type.SubjectSemantics,
RelationEnums.Type.Actant1Semantics,
RelationEnums.Type.Actant2Semantics,
].indexOf(r.type) !== -1
);
const warnings = []

for (const pos of Object.keys(
action.data.valencies
) as (keyof IActionValency)[]) {
const types = action.data.entities[pos];
const valency = action.data.valencies[pos];
const morphosValid = valency && valency.length > 0;
const relIds = relations
.filter((r) => {
if (pos === "s") {
return r.type === RelationEnums.Type.SubjectSemantics;
} else if (pos === "a1") {
return r.type === RelationEnums.Type.Actant1Semantics;
} else {
return r.type === RelationEnums.Type.Actant2Semantics;
}
})
.reduce((acc, curr) => {
acc = acc.concat(curr.entityIds);
return acc;
}, [] as string[])
.filter((id) => id !== this.entityId);

const semantFilled = relIds.length > 0;
const onlyEmptyAllowed =
!types ||
!types.length ||
(types.length === 1 && types[0] === EntityEnums.Extension.Empty);
if (!morphosValid && onlyEmptyAllowed && !relIds.length) {
continue;
}

const entitiesSet =
relIds.length > 0 &&
(types || []).length > 0 &&
types?.find((t) => t !== EntityEnums.Extension.Empty);

if (morphosValid && semantFilled && entitiesSet) {
continue;
}

const newWarning = this.newWarning(WarningTypeEnums.AVAL, IWarningPositionSection.Valencies, pos);
warnings.push(newWarning)
}

return warnings;
}

/**
* Tests if there is MAEE warning and returns it
* @param conn
Expand All @@ -191,7 +277,7 @@ export default class EntityWarnings {
);

if (!aee || !aee.length) {
return this.newWarning(WarningTypeEnums.MAEE);
return this.newWarning(WarningTypeEnums.MAEE, IWarningPositionSection.Relations);
}

return null;
Expand Down
Loading

0 comments on commit 1d728df

Please sign in to comment.