From c2d6ca6b70b8e8a37982f9cf607e7f0f908c859f Mon Sep 17 00:00:00 2001 From: KamyaPA <92309613+KamyaPA@users.noreply.github.com> Date: Thu, 28 Sep 2023 11:05:12 +0200 Subject: [PATCH] Json xml (#26) * Location, Edge, Component and System data structures done, no testing * Component, System, Location and Edge done with tests * Queries, Query and Declarations parsed an finished. * Fixed missing comma after merge conflict * After yarn format * After yarn format * LINT FIX * New file structure with smaller files * fixed import error * added more subfiles * New filescructure and JsDoc documentation * yarn.lock * removed lodash and replaced with strict equal * removed @types/lodash --------- Co-authored-by: AlbertHald <43075950+AlbertHald@users.noreply.github.com> --- src/lib/classes/automaton.test.ts | 568 ++++++++++++++++++ src/lib/classes/automaton.ts | 38 ++ src/lib/classes/automaton/backend.ts | 9 + src/lib/classes/automaton/component.ts | 131 ++++ .../classes/automaton/component_instance.ts | 29 + src/lib/classes/automaton/declaration.ts | 42 ++ src/lib/classes/automaton/declaration_type.ts | 4 + src/lib/classes/automaton/edge.ts | 171 ++++++ src/lib/classes/automaton/invariant.ts | 19 + src/lib/classes/automaton/location.ts | 105 ++++ src/lib/classes/automaton/location_type.ts | 36 ++ src/lib/classes/automaton/nickname.ts | 21 + src/lib/classes/automaton/operator.ts | 34 ++ src/lib/classes/automaton/operator_type.ts | 10 + src/lib/classes/automaton/property.ts | 22 + src/lib/classes/automaton/property_type.ts | 30 + src/lib/classes/automaton/query.ts | 114 ++++ src/lib/classes/automaton/raw.ts | 30 + src/lib/classes/automaton/raw/component.ts | 19 + src/lib/classes/automaton/raw/declaration.ts | 7 + src/lib/classes/automaton/raw/edge.ts | 22 + src/lib/classes/automaton/raw/location.ts | 17 + src/lib/classes/automaton/raw/query.ts | 11 + src/lib/classes/automaton/raw/system.ts | 29 + src/lib/classes/automaton/status.ts | 9 + src/lib/classes/automaton/system.ts | 165 +++++ src/lib/classes/automaton/system_edge.ts | 19 + src/lib/classes/automaton/urgency.ts | 25 + src/lib/classes/draw.ts | 2 + src/lib/classes/draw/dimensions.ts | 12 + src/lib/classes/draw/point.ts | 12 + 31 files changed, 1762 insertions(+) create mode 100644 src/lib/classes/automaton.test.ts create mode 100644 src/lib/classes/automaton.ts create mode 100644 src/lib/classes/automaton/backend.ts create mode 100644 src/lib/classes/automaton/component.ts create mode 100644 src/lib/classes/automaton/component_instance.ts create mode 100644 src/lib/classes/automaton/declaration.ts create mode 100644 src/lib/classes/automaton/declaration_type.ts create mode 100644 src/lib/classes/automaton/edge.ts create mode 100644 src/lib/classes/automaton/invariant.ts create mode 100644 src/lib/classes/automaton/location.ts create mode 100644 src/lib/classes/automaton/location_type.ts create mode 100644 src/lib/classes/automaton/nickname.ts create mode 100644 src/lib/classes/automaton/operator.ts create mode 100644 src/lib/classes/automaton/operator_type.ts create mode 100644 src/lib/classes/automaton/property.ts create mode 100644 src/lib/classes/automaton/property_type.ts create mode 100644 src/lib/classes/automaton/query.ts create mode 100644 src/lib/classes/automaton/raw.ts create mode 100644 src/lib/classes/automaton/raw/component.ts create mode 100644 src/lib/classes/automaton/raw/declaration.ts create mode 100644 src/lib/classes/automaton/raw/edge.ts create mode 100644 src/lib/classes/automaton/raw/location.ts create mode 100644 src/lib/classes/automaton/raw/query.ts create mode 100644 src/lib/classes/automaton/raw/system.ts create mode 100644 src/lib/classes/automaton/status.ts create mode 100644 src/lib/classes/automaton/system.ts create mode 100644 src/lib/classes/automaton/system_edge.ts create mode 100644 src/lib/classes/automaton/urgency.ts create mode 100644 src/lib/classes/draw.ts create mode 100644 src/lib/classes/draw/dimensions.ts create mode 100644 src/lib/classes/draw/point.ts diff --git a/src/lib/classes/automaton.test.ts b/src/lib/classes/automaton.test.ts new file mode 100644 index 00000000..da97e8c2 --- /dev/null +++ b/src/lib/classes/automaton.test.ts @@ -0,0 +1,568 @@ +import { describe, it, expect } from 'vitest'; +import { Location, Edge, Component, System, Queries, Declaration } from './automaton'; +import type { + RawLocation, + RawEdge, + RawComponent, + RawSystem, + RawQuery, + RawDeclaration +} from './automaton'; + +describe('Location test', () => { + it('serializes into location', () => { + const location = Location.deserializeRaw(locationData); + const raw: RawLocation = JSON.parse(locationData); + expect(location.id).toBe(raw.id); + expect(location.urgency).toBe(raw.urgency); + expect(location.color).toBe(raw.color); + expect(location.position.x).toBe(raw.x); + expect(location.position.y).toBe(raw.y); + expect(location.type).toBe(raw.type); + expect(location.nickname.name).toBe(raw.nickname); + expect(location.nickname.position.x).toBe(raw.nicknameX); + expect(location.nickname.position.y).toBe(raw.nicknameY); + expect(location.invariant.fn).toBe(raw.invariant); + expect(location.invariant.position.x).toBe(raw.invariantX); + expect(location.invariant.position.y).toBe(raw.invariantY); + }); + + it('serializes and deserializes to the same object', () => { + const o = Location.deserializeRaw(locationData); + const rawObj = o.toRaw(); + const rawParse = JSON.parse(locationData); + expect(rawObj).toStrictEqual(rawParse); + }); +}); + +describe('Edge test', () => { + it('serializes into an Edge', () => { + const edge = Edge.deserializeRaw(edgeData); + const data: RawEdge = JSON.parse(edgeData); + expect(edge.id).toBe(data.id); + expect(edge.sync).toBe(data.sync); + expect(edge.group).toBe(data.group); + expect(edge.guard).toBe(data.guard); + expect(edge.select).toBe(data.select); + expect(edge.status).toBe(data.status); + expect(edge.update).toBe(data.update); + expect(edge.isLocked).toBe(data.isLocked); + expect(edge.sourceLocation).toBe(data.sourceLocation); + expect(edge.targetLocation).toBe(data.targetLocation); + expect(edge.nails.length).toBe(data.nails.length); + expect(edge.nails[0].position.x).toBe(data.nails[0].x); + expect(edge.nails[0].position.y).toBe(data.nails[0].y); + expect(edge.nails[0].property.type).toBe(data.nails[0].propertyType); + expect(edge.nails[0].property.position.x).toBe(data.nails[0].propertyX); + expect(edge.nails[0].property.position.y).toBe(data.nails[0].propertyY); + }); + + it('serializes and deserializes to the same object', () => { + const o = Edge.deserializeRaw(edgeData); + const rawObj = o.toRaw(); + const rawParse = JSON.parse(edgeData); + expect(rawObj).toStrictEqual(rawParse); + }); +}); + +describe('Component test', () => { + it('serializes into a Component', () => { + const component = Component.deserializeRaw(componentData); + const data: RawComponent = JSON.parse(componentData); + expect(component.name).toBe(data.name); + expect(component.declarations).toBe(data.declarations); + expect(component.locations.length).toBe(data.locations.length); + expect(component.edges.length).toBe(data.edges.length); + expect(component.description).toBe(data.description); + expect(component.position.x).toBe(data.x); + expect(component.position.y).toBe(data.y); + expect(component.dimensions.width).toBe(data.width); + expect(component.dimensions.height).toBe(data.height); + expect(component.color).toBe(data.color); + expect(component.includeInPeriodicCheck).toBe(data.includeInPeriodicCheck); + }); + + it('serializes and deserializes to the same object', () => { + const o = Component.deserializeRaw(componentData); + const rawObj = o.toRaw(); + const rawParse = JSON.parse(componentData); + expect(rawObj).toStrictEqual(rawParse); + }); +}); + +describe('System test', () => { + it('serializes into a system', () => { + const system = System.deserializeRaw(systemData); + const data: RawSystem = JSON.parse(systemData); + expect(system.name).toBe(data.name); + expect(system.description).toBe(data.description); + expect(system.position.x).toBe(data.x); + expect(system.position.y).toBe(data.y); + expect(system.color).toBe(data.color); + expect(system.systemRootX).toBe(data.systemRootX); + expect(system.componentInstances.length).toBe(data.componentInstances.length); + expect(system.componentInstances[0].name).toBe(data.componentInstances[0].componentName); + expect(system.componentInstances[0].id).toBe(data.componentInstances[0].id); + expect(system.componentInstances[0].position.x).toBe(data.componentInstances[0].x); + expect(system.componentInstances[0].position.y).toBe(data.componentInstances[0].y); + expect(system.operators.length).toBe(data.operators.length); + expect(system.operators[0].id).toBe(data.operators[0].id); + expect(system.operators[0].position.x).toBe(data.operators[0].x); + expect(system.operators[0].position.y).toBe(data.operators[0].y); + expect(system.operators[0].type.toLowerCase()).toBe(data.operators[0].type); + expect(system.edges.length).toBe(data.edges.length); + expect(system.edges[0].parent).toBe(data.edges[0].parent); + expect(system.edges[0].child).toBe(data.edges[0].child); + }); + + it('serializes and deserializes to the same object', () => { + const o = System.deserializeRaw(systemData); + const rawObj = o.toRaw(); + const rawParse = JSON.parse(systemData); + expect(rawObj).toStrictEqual(rawParse); + }); +}); + +describe('Queries test', () => { + it('serializes into a query array', () => { + const queries = Queries.deserializeRaw(queriesData); + const data: RawQuery[] = JSON.parse(queriesData); + + expect(queries.arr.length).toBe(data.length); + for (let i = 0; i < queries.arr.length; i++) { + expect(queries.arr[i].query).toBe(data[i].query); + expect(queries.arr[i].backend).toBe(data[i].backend); + expect(queries.arr[i].comment).toBe(data[i].comment); + expect(queries.arr[i].isPeriodic).toBe(data[i].isPeriodic); + } + }); + + it('serializes and deserializes to the same object', () => { + const o = Queries.deserializeRaw(queriesData); + const rawObj = o.toRaw(); + const rawParse = JSON.parse(queriesData); + expect(rawObj).toStrictEqual(rawParse); + }); +}); + +describe('Declarations test', () => { + it('serializes into a declaration', () => { + const queries = Declaration.deserializeRaw(declarationData); + const data: RawDeclaration = JSON.parse(declarationData); + + expect(queries.declarations).toBe(data.declarations); + expect(queries.type).toStrictEqual(data.name); + }); + + it('serializes and deserializes to the same object', () => { + const o = Declaration.deserializeRaw(declarationData); + const rawObj = o.toRaw(); + const rawParse = JSON.parse(declarationData); + + expect(rawObj).toStrictEqual(rawParse); + }); +}); + +/*******************************\ + * DATA * +\*******************************/ + +const locationData = ` +{ + "id": "L5", + "nickname": "nickname", + "invariant": "invariant", + "type": "INITIAL", + "urgency": "NORMAL", + "x": 140.0, + "y": 100.0, + "color": "7", + "nicknameX": 30.0, + "nicknameY": -10.0, + "invariantX": 20.0, + "invariantY": 10.0 +} +`; + +const edgeData = ` +{ + "id": "E20", + "group": "group", + "sourceLocation": "L19", + "targetLocation": "L8", + "status": "OUTPUT", + "select": "select", + "guard": "y \u003e\u003d 4", + "update": "update", + "sync": "cof", + "isLocked": false, + "nails": [ + { + "x": 150.0, + "y": 380.0, + "propertyType": "GUARD", + "propertyX": -60.0, + "propertyY": -10.0 + }, + { + "x": 156.0, + "y": 350.0, + "propertyType": "SYNCHRONIZATION", + "propertyX": -50.0, + "propertyY": -20.0 + } + ] +} +`; + +const componentData = ` +{ + "name": "Machine", + "declarations": "clock y;", + "locations": [ + { + "id": "L4", + "nickname": "", + "invariant": "y\u003c\u003d6", + "type": "NORMAL", + "urgency": "NORMAL", + "x": 140.0, + "y": 300.0, + "color": "7", + "nicknameX": 30.0, + "nicknameY": -10.0, + "invariantX": 30.0, + "invariantY": -10.0 + }, + { + "id": "L5", + "nickname": "", + "invariant": "", + "type": "INITIAL", + "urgency": "NORMAL", + "x": 140.0, + "y": 100.0, + "color": "7", + "nicknameX": 30.0, + "nicknameY": -10.0, + "invariantX": 30.0, + "invariantY": 10.0 + } + ], + "edges": [ + { + "id": "E25", + "group": "", + "sourceLocation": "L4", + "targetLocation": "L5", + "status": "OUTPUT", + "select": "", + "guard": "y\u003e\u003d4", + "update": "", + "sync": "cof", + "isLocked": false, + "nails": [ + { + "x": 100.0, + "y": 230.0, + "propertyType": "GUARD", + "propertyX": -70.0, + "propertyY": -10.0 + }, + { + "x": 100.0, + "y": 180.0, + "propertyType": "SYNCHRONIZATION", + "propertyX": -70.0, + "propertyY": -10.0 + } + ] + }, + { + "id": "E26", + "group": "", + "sourceLocation": "L4", + "targetLocation": "L5", + "status": "OUTPUT", + "select": "", + "guard": "", + "update": "", + "sync": "tea", + "isLocked": false, + "nails": [ + { + "x": 210.0, + "y": 200.0, + "propertyType": "SYNCHRONIZATION", + "propertyX": 20.0, + "propertyY": -10.0 + } + ] + }, + { + "id": "E27", + "group": "", + "sourceLocation": "L5", + "targetLocation": "L4", + "status": "INPUT", + "select": "", + "guard": "", + "update": "y\u003d0", + "sync": "coin", + "isLocked": false, + "nails": [ + { + "x": 140.0, + "y": 220.0, + "propertyType": "SYNCHRONIZATION", + "propertyX": 20.0, + "propertyY": -10.0 + }, + { + "x": 140.0, + "y": 190.0, + "propertyType": "UPDATE", + "propertyX": 10.0, + "propertyY": -10.0 + } + ] + }, + { + "id": "E28", + "group": "", + "sourceLocation": "L4", + "targetLocation": "L4", + "status": "INPUT", + "select": "", + "guard": "", + "update": "", + "sync": "coin", + "isLocked": false, + "nails": [ + { + "x": 130.0, + "y": 350.0, + "propertyType": "SYNCHRONIZATION", + "propertyX": -60.0, + "propertyY": -10.0 + }, + { + "x": 160.0, + "y": 350.0, + "propertyType": "NONE", + "propertyX": 0.0, + "propertyY": 0.0 + } + ] + }, + { + "id": "E29", + "group": "g", + "sourceLocation": "L5", + "targetLocation": "L5", + "status": "OUTPUT", + "select": "s", + "guard": "y\u003e\u003d2", + "update": "u", + "sync": "tea", + "isLocked": false, + "nails": [ + { + "x": 170.0, + "y": 60.0, + "propertyType": "GUARD", + "propertyX": 10.0, + "propertyY": -20.0 + }, + { + "x": 140.0, + "y": 60.0, + "propertyType": "SYNCHRONIZATION", + "propertyX": -20.0, + "propertyY": -30.0 + } + ] + } + ], + "description": "", + "x": 6.0, + "y": 5.0, + "width": 300.0, + "height": 390.0, + "color": "7", + "includeInPeriodicCheck": false +} +`; + +const systemData = ` +{ + "name": "UniversityExample", + "description": "da", + "x": 4.0, + "y": 5.0, + "width": 540.0, + "height": 410.0, + "color": "5", + "systemRootX": 240.0, + "componentInstances": [ + { + "id": 1, + "componentName": "Machine", + "x": 10.0, + "y": 110.0 + }, + { + "id": 3, + "componentName": "Researcher", + "x": 310.0, + "y": 110.0 + }, + { + "id": 5, + "componentName": "HalfAdm1", + "x": 10.0, + "y": 280.0 + }, + { + "id": 6, + "componentName": "HalfAdm2", + "x": 310.0, + "y": 280.0 + } + ], + "operators": [ + { + "id": 2, + "type": "composition", + "x": 250.0, + "y": 60.0 + }, + { + "id": 4, + "type": "conjunction", + "x": 224159.0, + "y": 21523.0 + }, + { + "id": 232, + "type": "refinement", + "x": 21453.0, + "y": 2315.0 + }, + { + "id": 1003, + "type": "quotient", + "x": 2252.0, + "y": 241.0 + }, + { + "id": 10, + "type": "simple", + "x": 223123.0, + "y": 2.0 + } + ], + "edges": [ + { + "child": 2, + "parent": 0 + }, + { + "child": 1, + "parent": 2 + }, + { + "child": 3, + "parent": 2 + }, + { + "child": 4, + "parent": 2 + }, + { + "child": 5, + "parent": 4 + }, + { + "child": 6, + "parent": 4 + } + ] +} +`; + +const queriesData = ` +[ + { + "query": "specification: (Administration || Machine || Researcher)", + "comment": "", + "isPeriodic": false, + "ignoredInputs": {}, + "ignoredOutputs": {}, + "backend": 1 + }, + { + "query": "specification: Spec", + "comment": "", + "isPeriodic": false, + "ignoredInputs": {}, + "ignoredOutputs": {}, + "backend": 1 + }, + { + "query": "consistency: (Administration || Machine || Researcher)", + "comment": "", + "isPeriodic": false, + "ignoredInputs": {}, + "ignoredOutputs": {}, + "backend": 1 + }, + { + "query": "consistency: (Administration || Machine || Researcher)", + "comment": "", + "isPeriodic": false, + "ignoredInputs": {}, + "ignoredOutputs": {}, + "backend": 1 + }, + { + "query": "refinement: (Administration || Machine || Researcher) \u003c\u003d Spec", + "comment": "", + "isPeriodic": false, + "ignoredInputs": {}, + "ignoredOutputs": {}, + "backend": 1 + }, + { + "query": "refinement: Machine3 \u003c\u003d Machine3", + "comment": "", + "isPeriodic": false, + "ignoredInputs": {}, + "ignoredOutputs": {}, + "backend": 1 + }, + { + "query": "refinement: (HalfAdm1 \u0026\u0026 HalfAdm2) \u003c\u003d Adm2", + "comment": "", + "isPeriodic": false, + "ignoredInputs": {}, + "ignoredOutputs": {}, + "backend": 1 + }, + { + "query": "refinement: Adm2 \u003c\u003d (HalfAdm1 \u0026\u0026 HalfAdm2)", + "comment": "", + "isPeriodic": false, + "ignoredInputs": {}, + "ignoredOutputs": {}, + "backend": 1 + } +] +`; + +const declarationData = ` +{ + "name": "Global Declarations", + "declarations": "broadcast chan pub, grant, patent, coin, tea, cof;" +} +`; diff --git a/src/lib/classes/automaton.ts b/src/lib/classes/automaton.ts new file mode 100644 index 00000000..bd162e1f --- /dev/null +++ b/src/lib/classes/automaton.ts @@ -0,0 +1,38 @@ +// Raw Types +export type { + RawLocation, + RawEdge, + RawComponent, + RawSystem, + RawQuery, + RawDeclaration, + FromRaw, + ToRaw, + SerializeRaw, + DeserializeRaw +} from './automaton/raw'; + +// Enums +export { Backend } from './automaton/backend'; +export { DeclarationType } from './automaton/declaration_type'; +export { Status } from './automaton/status'; +export { LocationType } from './automaton/location_type'; +export { OperatorType } from './automaton/operator_type'; +export { PropertyType } from './automaton/property_type'; +export { Urgency } from './automaton/urgency'; + +// Minor Classes +export { Invariant } from './automaton/invariant'; +export { Nickname } from './automaton/nickname'; +export { Operator } from './automaton/operator'; +export { Property } from './automaton/property'; +export { SystemEdge } from './automaton/system_edge'; +export { ComponentInstance } from './automaton/component_instance'; + +// Major Classes +export { Declaration } from './automaton/declaration'; +export { Component } from './automaton/component'; +export { Edge } from './automaton/edge'; +export { Location } from './automaton/location'; +export { Query, Queries } from './automaton/query'; +export { System } from './automaton/system'; diff --git a/src/lib/classes/automaton/backend.ts b/src/lib/classes/automaton/backend.ts new file mode 100644 index 00000000..c6fbf2ee --- /dev/null +++ b/src/lib/classes/automaton/backend.ts @@ -0,0 +1,9 @@ +/** + * What backend is targeted + * - j-ECDAR or + * - Reveaal + * */ +export enum Backend { + J_ECDAR = 0, + REVEAAL = 1 +} diff --git a/src/lib/classes/automaton/component.ts b/src/lib/classes/automaton/component.ts new file mode 100644 index 00000000..09ab3bec --- /dev/null +++ b/src/lib/classes/automaton/component.ts @@ -0,0 +1,131 @@ +import { Point, Dimensions } from '$lib/classes/draw'; + +import { Edge, Location } from '../automaton'; +import type { SerializeRaw, ToRaw, FromRaw, DeserializeRaw, RawComponent } from '../automaton'; + +/** + * # An Ecdar component + * It stores the edges and locations of a single automaton + * */ +export class Component implements SerializeRaw, ToRaw { + /** + * The name of the component + * */ + name: string = ''; + + /** + * The declarations of the component ex "clock t;" + * */ + declarations: string = ''; + + /** + * A list of Locations in the Component + * */ + locations: Location[] = []; + + /** + * A list of Edges in the Component + * */ + edges: Edge[] = []; + + /** + * A description of the Component + * */ + description: string = ''; + + /** + * The position of the Component + * */ + position = new Point(0, 0); + + /** + * The dimensions of the Component + * */ + dimensions: Dimensions; + + /** + * The color of the Component + * */ + color: string = '0'; + + /** + * Include in periodic checks + * ! Some more information might be needed ! + * */ + includeInPeriodicCheck: boolean = false; + + constructor( + name: string = '', + declarations: string = '', + locations: Location[] = [], + edges: Edge[] = [], + description: string = '', + position = new Point(0, 0), + dimensions = new Dimensions(100, 100), + color: string = '0', + includeInPeriodicCheck: boolean = false + ) { + this.name = name; + this.declarations = declarations; + this.locations = locations; + this.edges = edges; + this.description = description; + this.position = position; + this.dimensions = dimensions; + this.color = color; + this.includeInPeriodicCheck = includeInPeriodicCheck; + } + + toRaw() { + return { + name: this.name, + declarations: this.declarations, + locations: this.locations.map((l) => { + return l.toRaw(); + }), + edges: this.edges.map((e) => { + return e.toRaw(); + }), + description: this.description, + x: this.position.x, + y: this.position.y, + width: this.dimensions.width, + height: this.dimensions.height, + color: this.color, + includeInPeriodicCheck: this.includeInPeriodicCheck + }; + } + + serializeRaw() { + return JSON.stringify(this.toRaw()); + } + + /** + * Converts the Component into a RawComponent + * */ + static fromRaw: FromRaw = (raw) => { + return new Component( + raw.name, + raw.declarations, + raw.locations.map((raw) => { + return Location.fromRaw(raw); + }), + raw.edges.map((raw) => { + return Edge.fromRaw(raw); + }), + raw.description, + new Point(raw.x, raw.y), + new Dimensions(raw.width, raw.height), + raw.color, + raw.includeInPeriodicCheck + ); + }; + + /** + * Creates a Component from a JSON string of a RawComponent + * */ + static deserializeRaw: DeserializeRaw = (input) => { + const raw: RawComponent = JSON.parse(input); + return Component.fromRaw(raw); + }; +} diff --git a/src/lib/classes/automaton/component_instance.ts b/src/lib/classes/automaton/component_instance.ts new file mode 100644 index 00000000..d2859917 --- /dev/null +++ b/src/lib/classes/automaton/component_instance.ts @@ -0,0 +1,29 @@ +import type { Point } from '$lib/classes/draw'; + +/** + * # A Component Instance + * Is used by a System to store what components are used + * */ +export class ComponentInstance { + /** + * The id of the component instance + * This must be unique and is shared by Operators + * */ + id: number; + + /** + * The name of the component this references + * */ + name: string; + + /** + * The position of the component instance + * */ + position: Point; + + constructor(id: number, name: string, position: Point) { + this.id = id; + this.name = name; + this.position = position; + } +} diff --git a/src/lib/classes/automaton/declaration.ts b/src/lib/classes/automaton/declaration.ts new file mode 100644 index 00000000..1c526a8a --- /dev/null +++ b/src/lib/classes/automaton/declaration.ts @@ -0,0 +1,42 @@ +import { + type SerializeRaw, + type ToRaw, + type FromRaw, + type DeserializeRaw, + type RawDeclaration, + DeclarationType +} from '../automaton'; + +/** + * The top level declarations + * */ +export class Declaration implements SerializeRaw, ToRaw { + type: DeclarationType; + declarations: string; + + constructor(type = DeclarationType.GLOBAL, declarations = '') { + this.type = type; + this.declarations = declarations; + } + + static fromRaw: FromRaw = (raw) => { + return new Declaration(raw.name as DeclarationType, raw.declarations); + }; + + static deserializeRaw: DeserializeRaw = (input) => { + const raw = JSON.parse(input); + return Declaration.fromRaw(raw); + }; + + toRaw() { + return { + name: this.type, + declarations: this.declarations + }; + } + + serializeRaw(): string { + const raw = this.toRaw(); + return JSON.stringify(raw); + } +} diff --git a/src/lib/classes/automaton/declaration_type.ts b/src/lib/classes/automaton/declaration_type.ts new file mode 100644 index 00000000..e8ca7a11 --- /dev/null +++ b/src/lib/classes/automaton/declaration_type.ts @@ -0,0 +1,4 @@ +export enum DeclarationType { + GLOBAL = 'Global Declarations', + SYSETEM = 'System Declarations' +} diff --git a/src/lib/classes/automaton/edge.ts b/src/lib/classes/automaton/edge.ts new file mode 100644 index 00000000..6fa2ccb5 --- /dev/null +++ b/src/lib/classes/automaton/edge.ts @@ -0,0 +1,171 @@ +import { Point } from '$lib/classes/draw'; + +import { Status, Property, PropertyType } from '../automaton'; +import type { SerializeRaw, ToRaw, FromRaw, DeserializeRaw, RawEdge } from '../automaton'; + +/** + * # An Ecdar Edge + * Used to define edges in an Ecdar Component + * */ +export class Edge implements SerializeRaw, ToRaw { + /** + * The id of the edge + * - Must be "E" followed by a number and + * - Must be unique + * */ + id: string; + + /** + * # Unused + * */ + group: string; + + /** + * The id of the source location + * */ + sourceLocation: string; + + /** + * The id of the target location + * */ + targetLocation: string; + + /** + * The status of the edge + * - Input or + * - Output + * */ + status: Status; + + /** + * Unused + * */ + select: string; + + /** + * The guard of the edge + * ex "c <= 7" + * */ + guard: string; + + /** + * The update of the edge + * ex "c := 7" + * */ + update: string; + + /** + * The input OR output variable of the edge + * */ + sync: string; + + /** + * Unused + * */ + isLocked: boolean; + + /** + * The nails of the edge + * Modifies the path that the edge takes + * Defines properties on the edge + * */ + nails: { + position: Point; + property: Property; + }[]; + + constructor( + id: string = '', + group: string = '', + sourceLocation: string = '', + targetLocation: string = '', + status: Status = Status.INPUT, + select: string = '', + guard: string = '', + update: string = '', + sync: string = '', + isLocked: boolean = true, + nails: { + position: Point; + property: Property; + }[] = [] + ) { + this.id = id; + this.group = group; + this.sourceLocation = sourceLocation; + this.targetLocation = targetLocation; + this.status = status; + this.select = select; + this.guard = guard; + this.update = update; + this.sync = sync; + this.isLocked = isLocked; + this.nails = nails; + } + + toRaw() { + return { + id: this.id, + group: this.group, + sourceLocation: this.sourceLocation, + targetLocation: this.targetLocation, + status: this.status as string, + select: this.select, + guard: this.guard, + update: this.update, + sync: this.sync, + isLocked: this.isLocked, + nails: this.nails.reduce( + (res, c) => { + res.push({ + x: c.position.x, + y: c.position.y, + propertyType: c.property.type, + propertyX: c.property.position.x, + propertyY: c.property.position.y + }); + return res; + }, + [] + ) + }; + } + serializeRaw() { + return JSON.stringify(this.toRaw()); + } + + /** + * Creates an Edge from a RawEdge + * */ + static fromRaw: FromRaw = (raw) => { + return new Edge( + raw.id, + raw.group, + raw.sourceLocation, + raw.targetLocation, + raw.status as Status, + raw.select, + raw.guard, + raw.update, + raw.sync, + raw.isLocked, + raw.nails.map((nail) => { + return { + position: new Point(nail.x, nail.y), + property: new Property( + nail.propertyType as PropertyType, + new Point(nail.propertyX, nail.propertyY) + ) + }; + }) + ); + }; + + /** + * Creates an Edge from a JSON matching a RawEdge + * */ + static deserializeRaw: DeserializeRaw = (input) => { + const raw: RawEdge = JSON.parse(input); + return Edge.fromRaw(raw); + }; +} diff --git a/src/lib/classes/automaton/invariant.ts b/src/lib/classes/automaton/invariant.ts new file mode 100644 index 00000000..8a620e69 --- /dev/null +++ b/src/lib/classes/automaton/invariant.ts @@ -0,0 +1,19 @@ +import type { Point } from '$lib/classes/draw'; + +export class Invariant { + /** + * The invariant function + * ex c >= 8 + * */ + fn: string; + + /** + * The position of the invariant + * */ + position: Point; + + constructor(fn: string, position: Point) { + this.fn = fn; + this.position = position; + } +} diff --git a/src/lib/classes/automaton/location.ts b/src/lib/classes/automaton/location.ts new file mode 100644 index 00000000..20de6562 --- /dev/null +++ b/src/lib/classes/automaton/location.ts @@ -0,0 +1,105 @@ +import { Point } from '$lib/classes/draw'; +import { Nickname, Invariant, LocationType, Urgency } from '../automaton'; +import type { SerializeRaw, ToRaw, FromRaw, DeserializeRaw, RawLocation } from '../automaton'; + +export class Location implements SerializeRaw, ToRaw { + /** + * The id of the Location + * */ + id: string; + + /** + * The position of the Location + * */ + position: Point; + + /** + * The Nickname of the Location + * */ + nickname: Nickname; + + /** + * The Invariant of the Location + * */ + invariant: Invariant; + + /** + * The Type of the Location + * */ + type: LocationType; + + /** + * The Urgency of the Location + * */ + urgency: Urgency; + + /** + * The Color of the Location + * */ + color: string; + + constructor( + id: string = '', + position: Point = new Point(0, 0), + nickname: Nickname = new Nickname('', new Point(0, 0)), + invariant: Invariant = new Invariant('', new Point(0, 0)), + type: LocationType = LocationType.NORMAL, + urgency: Urgency = Urgency.NORMAL, + color: string = '' + ) { + this.id = id; + this.position = position; + this.nickname = nickname; + this.invariant = invariant; + this.type = type; + this.urgency = urgency; + this.color = color; + } + + /** + * Converts the Location into a RawLocation + * */ + toRaw() { + return { + id: this.id, + nickname: this.nickname.name, + invariant: this.invariant.fn, + type: this.type, + urgency: this.urgency, + x: this.position.x, + y: this.position.y, + color: this.color, + nicknameX: this.nickname.position.x, + nicknameY: this.nickname.position.y, + invariantX: this.invariant.position.x, + invariantY: this.invariant.position.y + }; + } + + serializeRaw() { + return JSON.stringify(this.toRaw()); + } + + /** + * Crates a Location from a RawLocation + * */ + static fromRaw: FromRaw = (raw) => { + return new Location( + raw.id, + new Point(raw.x, raw.y), + new Nickname(raw.nickname, new Point(raw.nicknameX, raw.nicknameY)), + new Invariant(raw.invariant, new Point(raw.invariantX, raw.invariantY)), + raw.type as LocationType, + raw.urgency as Urgency, + raw.color + ); + }; + + /** + * Crates a Location from a JSON string matching a RawLocation + * */ + static deserializeRaw: DeserializeRaw = (input) => { + const raw: RawLocation = JSON.parse(input); + return Location.fromRaw(raw); + }; +} diff --git a/src/lib/classes/automaton/location_type.ts b/src/lib/classes/automaton/location_type.ts new file mode 100644 index 00000000..5b7db1fd --- /dev/null +++ b/src/lib/classes/automaton/location_type.ts @@ -0,0 +1,36 @@ +/** + * The type of a location + * - INITIAL + * - NORMAL + * - UNIVARSAL + * - INCONSISTENT or + * - ANY + * */ +export enum LocationType { + /** + * It is an initial Location + * only one allowed per Component + * */ + INITIAL = 'INITIAL', + + /** + * No modifires + * */ + NORMAL = 'NORMAL', + + /** + * ????? + * */ + UNIVERSAL = 'UNIVERSAL', + + /** + * ????? + * */ + INCONSISTENT = 'INCONSISTENT', + + /** + * DO NOT USE + * Reveaal will panic + * */ + ANY = 'ANY' +} diff --git a/src/lib/classes/automaton/nickname.ts b/src/lib/classes/automaton/nickname.ts new file mode 100644 index 00000000..e7b156e2 --- /dev/null +++ b/src/lib/classes/automaton/nickname.ts @@ -0,0 +1,21 @@ +import type { Point } from '$lib/classes/draw'; + +/** + * A user defined name for the location + * */ +export class Nickname { + /** + * The actual nickname + * */ + name: string; + + /** + * The position of the Nickname + * */ + position: Point; + + constructor(name: string, position: Point) { + this.name = name; + this.position = position; + } +} diff --git a/src/lib/classes/automaton/operator.ts b/src/lib/classes/automaton/operator.ts new file mode 100644 index 00000000..9f57f0fc --- /dev/null +++ b/src/lib/classes/automaton/operator.ts @@ -0,0 +1,34 @@ +import { Point } from '$lib/classes/draw'; + +import { OperatorType } from './operator_type'; + +/** + * Defines an operator for a System + * */ +export class Operator { + /** + * The id of the operator + * must be unique and matches the id of a ComponentInstance + * */ + id: number = 0; + + /** + * The type of operator + * */ + type: OperatorType = OperatorType.COMPOSITION; + + /** + * The position of the operator + * */ + position: Point = new Point(0, 0); + + constructor( + id: number = 0, + type: OperatorType = OperatorType.COMPOSITION, + position: Point = new Point(0, 0) + ) { + this.id = id; + this.type = type; + this.position = position; + } +} diff --git a/src/lib/classes/automaton/operator_type.ts b/src/lib/classes/automaton/operator_type.ts new file mode 100644 index 00000000..a1b52669 --- /dev/null +++ b/src/lib/classes/automaton/operator_type.ts @@ -0,0 +1,10 @@ +/** + * The operator types supported by Ecdar + * */ +export enum OperatorType { + COMPOSITION = 'COMPOSITION', + CONJUNCTION = 'CONJUNCTION', + REFINEMENT = 'REFINEMENT', + QUOTIENT = 'QUOTIENT', + SIMPLE = 'SIMPLE' +} diff --git a/src/lib/classes/automaton/property.ts b/src/lib/classes/automaton/property.ts new file mode 100644 index 00000000..2183aaa5 --- /dev/null +++ b/src/lib/classes/automaton/property.ts @@ -0,0 +1,22 @@ +import { Point } from '$lib/classes/draw'; + +import { PropertyType } from './property_type'; + +/** + * The properties of a nail + * */ +export class Property { + /** + * The type of property + * */ + type: PropertyType = PropertyType.NONE; + + /** + * The position of the property + * */ + position: Point = new Point(0, 0); + constructor(type: PropertyType = PropertyType.NONE, position = new Point(0, 0)) { + this.type = type; + this.position = position; + } +} diff --git a/src/lib/classes/automaton/property_type.ts b/src/lib/classes/automaton/property_type.ts new file mode 100644 index 00000000..ccb315fa --- /dev/null +++ b/src/lib/classes/automaton/property_type.ts @@ -0,0 +1,30 @@ +/** + * The types of Properties that Ecdar suports, + * They match the fields of an Edge + * */ +export enum PropertyType { + /** + * Matches no field + * */ + NONE = 'NONE', + + /** + * Links to the select property of an Edge + * */ + SELECTION = 'SELECTION', + + /** + * Links to the guard property of an Edge + * */ + GUARD = 'GUARD', + + /** + * Links to the sync property of an Edge + * */ + SYNCHRONIZATION = 'SYNCHRONIZATION', + + /** + * Links to the update property of an Edge + * */ + UPDATE = 'UPDATE' +} diff --git a/src/lib/classes/automaton/query.ts b/src/lib/classes/automaton/query.ts new file mode 100644 index 00000000..31981c3b --- /dev/null +++ b/src/lib/classes/automaton/query.ts @@ -0,0 +1,114 @@ +import { Backend } from '../automaton'; +import type { SerializeRaw, ToRaw, FromRaw, DeserializeRaw, RawQuery } from '../automaton'; + +/** + * # An Ecdar Query + * What should the backend do + * */ +export class Query implements SerializeRaw, ToRaw { + /** + * The query string + * */ + query: string; + + /** + * A user defined comment + * */ + comment: string; + + /** + * ??? + * */ + isPeriodic: boolean; + //ignoredInputs + //ignoredOutputs + + /** + * What backend should the query target + * */ + backend: Backend; + + toRaw() { + return { + query: this.query, + comment: this.comment, + isPeriodic: this.isPeriodic, + ignoredInputs: {}, + ignoredOutputs: {}, + backend: this.backend + }; + } + + constructor( + query: string = '', + comment: string = '', + isPeriodic: boolean = false, + backend: Backend = Backend.REVEAAL + ) { + this.query = query; + this.comment = comment; + this.isPeriodic = isPeriodic; + this.backend = backend; + } + + serializeRaw(): string { + const raw = this.toRaw(); + return JSON.stringify(raw); + } + + /** + * Creates a query from a RawQuery + * */ + static fromRaw: FromRaw = (raw) => { + return new Query(raw.query, raw.comment, raw.isPeriodic, raw.backend as Backend); + }; + + /** + * Creates a query from a JSON string matching a RawQuery + * */ + static deserializeRaw: DeserializeRaw = (input) => { + const raw: RawQuery = JSON.parse(input); + return Query.fromRaw(raw); + }; +} + +export class Queries implements SerializeRaw, ToRaw { + /** + * The array of queries + * */ + arr: Query[]; + + constructor(arr: Query[] = []) { + this.arr = arr; + } + + toRaw() { + return this.arr.map((query) => { + return query.toRaw(); + }); + } + + serializeRaw(): string { + const raw = this.toRaw(); + return JSON.stringify(raw); + } + + /** + * Creates all Queries from an JSON array matching an array of RawQuery + * */ + static deserializeRaw: DeserializeRaw = (input) => { + const raw: RawQuery[] = JSON.parse(input); + return Queries.fromRaw(raw); + }; + + /** + * Creates all Queries from an array of RawQuery + * */ + static fromRaw: FromRaw = (raw) => { + return new Queries( + raw.map((rawSingle) => { + return Query.fromRaw(rawSingle); + }) + ); + }; +} diff --git a/src/lib/classes/automaton/raw.ts b/src/lib/classes/automaton/raw.ts new file mode 100644 index 00000000..bb2e8fc4 --- /dev/null +++ b/src/lib/classes/automaton/raw.ts @@ -0,0 +1,30 @@ +export type { RawComponent } from './raw/component'; +export type { RawDeclaration } from './raw/declaration'; +export type { RawEdge } from './raw/edge'; +export type { RawLocation } from './raw/location'; +export type { RawQuery } from './raw/query'; +export type { RawSystem } from './raw/system'; + +export interface SerializeRaw { + /** + * Serializes the object into a JSON string matching its raw counter part + */ + serializeRaw: () => string; +} + +/** + * A function type that should return the object T given a raw JSON string input + * */ +export type DeserializeRaw = (input: string) => T; + +export interface ToRaw { + /** + * Maps the object to its raw counter part + * */ + toRaw: () => R; +} + +/** + * A function type that should return the object T given its raw counterpart R + * */ +export type FromRaw = (raw: R) => T; diff --git a/src/lib/classes/automaton/raw/component.ts b/src/lib/classes/automaton/raw/component.ts new file mode 100644 index 00000000..1fba2fd7 --- /dev/null +++ b/src/lib/classes/automaton/raw/component.ts @@ -0,0 +1,19 @@ +import type { RawLocation } from './location'; +import type { RawEdge } from './edge'; + +/** + * The raw Object for a Component that is used to save and communicate in JSON. + * */ +export type RawComponent = { + name: string; + declarations: string; + locations: RawLocation[]; + edges: RawEdge[]; + description: string; + x: number; + y: number; + width: number; + height: number; + color: string; + includeInPeriodicCheck: boolean; +}; diff --git a/src/lib/classes/automaton/raw/declaration.ts b/src/lib/classes/automaton/raw/declaration.ts new file mode 100644 index 00000000..98a08f01 --- /dev/null +++ b/src/lib/classes/automaton/raw/declaration.ts @@ -0,0 +1,7 @@ +/** + * The raw Object for a Declaration that is used to save and communicate in JSON. + * */ +export type RawDeclaration = { + name: string; + declarations: string; +}; diff --git a/src/lib/classes/automaton/raw/edge.ts b/src/lib/classes/automaton/raw/edge.ts new file mode 100644 index 00000000..f24ad995 --- /dev/null +++ b/src/lib/classes/automaton/raw/edge.ts @@ -0,0 +1,22 @@ +/** + * The raw Object for an Edge that is used to save and communicate in JSON. + * */ +export type RawEdge = { + id: string; + group: string; + sourceLocation: string; + targetLocation: string; + status: string; + select: string; + sync: string; + guard: string; + update: string; + isLocked: boolean; + nails: { + x: number; + y: number; + propertyType: string; + propertyX: number; + propertyY: number; + }[]; +}; diff --git a/src/lib/classes/automaton/raw/location.ts b/src/lib/classes/automaton/raw/location.ts new file mode 100644 index 00000000..fa3d4e60 --- /dev/null +++ b/src/lib/classes/automaton/raw/location.ts @@ -0,0 +1,17 @@ +/** + * The raw Object for a Location that is used to save and communicate in JSON. + * */ +export type RawLocation = { + id: string; + nickname: string; + invariant: string; + type: string; + urgency: string; + x: number; + y: number; + color: string; + nicknameX: number; + nicknameY: number; + invariantX: number; + invariantY: number; +}; diff --git a/src/lib/classes/automaton/raw/query.ts b/src/lib/classes/automaton/raw/query.ts new file mode 100644 index 00000000..8db30c39 --- /dev/null +++ b/src/lib/classes/automaton/raw/query.ts @@ -0,0 +1,11 @@ +/** + * The raw Object for a Query that is used to save and communicate in JSON. + * */ +export type RawQuery = { + query: string; + comment: string; + isPeriodic: boolean; + ignoredInputs: object; // Ignored for now + ignoredOutputs: object; // Ignored for now + backend: number; +}; diff --git a/src/lib/classes/automaton/raw/system.ts b/src/lib/classes/automaton/raw/system.ts new file mode 100644 index 00000000..c47e004d --- /dev/null +++ b/src/lib/classes/automaton/raw/system.ts @@ -0,0 +1,29 @@ +/** + * The raw Object for a System that is used to save and communicate in JSON. + * */ +export type RawSystem = { + name: string; + description: string; + x: number; + y: number; + width: number; + height: number; + color: string; + systemRootX: number; + componentInstances: { + id: number; + componentName: string; + x: number; + y: number; + }[]; + operators: { + id: number; + type: string; + x: number; + y: number; + }[]; + edges: { + child: number; + parent: number; + }[]; +}; diff --git a/src/lib/classes/automaton/status.ts b/src/lib/classes/automaton/status.ts new file mode 100644 index 00000000..024b38e8 --- /dev/null +++ b/src/lib/classes/automaton/status.ts @@ -0,0 +1,9 @@ +/** + * The status of an Edge + * - Input or + * - Output + * */ +export enum Status { + INPUT = 'INPUT', + OUTPUT = 'OUTPUT' +} diff --git a/src/lib/classes/automaton/system.ts b/src/lib/classes/automaton/system.ts new file mode 100644 index 00000000..3cf2c13e --- /dev/null +++ b/src/lib/classes/automaton/system.ts @@ -0,0 +1,165 @@ +import { Point, Dimensions } from '$lib/classes/draw'; +import { Operator, ComponentInstance, SystemEdge } from '../automaton'; +import type { + OperatorType, + SerializeRaw, + ToRaw, + FromRaw, + DeserializeRaw, + RawSystem +} from '../automaton'; + +/** + * An Ecdar System + * */ +export class System implements SerializeRaw, ToRaw { + /** + * The name of the system + * */ + name: string; + + /** + * The description of the system + * */ + description: string; + + /** + * The position of the system + * */ + position: Point; + + /** + * The dimensions of the system + * */ + dimensions: Dimensions; + + /** + * The color of the system + * */ + color: string; + + /** + * The coordinate of root of the system + * */ + systemRootX: number; + + /** + * A list of components in the system + * */ + componentInstances: ComponentInstance[]; + + /** + * A list of operators in the system + * */ + operators: Operator[]; + + /** + * A list of edges in the system + * */ + edges: SystemEdge[]; + + constructor( + name: string = '', + description: string = '', + position: Point = new Point(0, 0), + dimensions: Dimensions = new Dimensions(0, 0), + color: string = '', + systemRootX: number = 0, + componentInstances: ComponentInstance[] = [], + operators: Operator[] = [], + edges: SystemEdge[] = [] + ) { + this.name = name; + this.description = description; + this.position = position; + this.dimensions = dimensions; + this.color = color; + this.systemRootX = systemRootX; + this.componentInstances = componentInstances; + this.operators = operators; + this.edges = edges; + } + + /** + * Converts the System into a RawSystem + * */ + toRaw() { + return { + name: this.name, + description: this.description, + x: this.position.x, + y: this.position.y, + width: this.dimensions.width, + height: this.dimensions.height, + color: this.color, + systemRootX: this.systemRootX, + componentInstances: this.componentInstances.map((instance) => { + return { + id: instance.id, + componentName: instance.name, + x: instance.position.x, + y: instance.position.y + }; + }), + operators: this.operators.map((o) => { + return { + x: o.position.x, + y: o.position.y, + // BECAUSE OF COMPATIBILITY + type: o.type.toLowerCase(), + id: o.id + }; + }), + edges: this.edges.map((e) => { + return { + child: e.child, + parent: e.parent + }; + }) + }; + } + + serializeRaw() { + return JSON.stringify(this.toRaw()); + } + + /** + * Creates a System from an object of type RawSystem + * */ + static fromRaw: FromRaw = (raw) => { + return new System( + raw.name, + raw.description, + new Point(raw.x, raw.y), + new Dimensions(raw.width, raw.height), + raw.color, + raw.systemRootX, + raw.componentInstances.map((instance) => { + return new ComponentInstance( + instance.id, + instance.componentName, + new Point(instance.x, instance.y) + ); + }), + raw.operators.map((o) => { + return new Operator( + o.id, + /// BECAUSE OF COMPATIBILITY + o.type.toUpperCase() as OperatorType, + new Point(o.x, o.y) + ); + }), + raw.edges.map((e) => { + return new SystemEdge(e.parent, e.child); + }) + ); + }; + + /** + * Creates a System from a JSON string of a RawSystem + * */ + static deserializeRaw: DeserializeRaw = (input) => { + const raw = JSON.parse(input); + return System.fromRaw(raw); + }; +} diff --git a/src/lib/classes/automaton/system_edge.ts b/src/lib/classes/automaton/system_edge.ts new file mode 100644 index 00000000..593eeeca --- /dev/null +++ b/src/lib/classes/automaton/system_edge.ts @@ -0,0 +1,19 @@ +/** + * Describes the edges of a system. + * */ +export class SystemEdge { + /** + * The beginning of the edge + * */ + parent: number; + + /** + * The end of the edge + * */ + child: number; + + constructor(parent: number, child: number) { + this.parent = parent; + this.child = child; + } +} diff --git a/src/lib/classes/automaton/urgency.ts b/src/lib/classes/automaton/urgency.ts new file mode 100644 index 00000000..5e13ac79 --- /dev/null +++ b/src/lib/classes/automaton/urgency.ts @@ -0,0 +1,25 @@ +/** + * What the backend should do when visiting a Location + * Not implemented in Reveeal yet + * */ +export enum Urgency { + /** + * Normal TIOA rules apply + * */ + NORMAL = 'NORMAL', + + /** + * ???? + * */ + PROHIBITED = 'PROHIBITED', + + /** + * Make a move instantly no matter the timer + * */ + URGENT = 'URGENT', + + /** + * ???? + * */ + COMMITTED = 'COMMITTED' +} diff --git a/src/lib/classes/draw.ts b/src/lib/classes/draw.ts new file mode 100644 index 00000000..ffca1112 --- /dev/null +++ b/src/lib/classes/draw.ts @@ -0,0 +1,2 @@ +export { Point } from './draw/point'; +export { Dimensions } from './draw/dimensions'; diff --git a/src/lib/classes/draw/dimensions.ts b/src/lib/classes/draw/dimensions.ts new file mode 100644 index 00000000..5945adcf --- /dev/null +++ b/src/lib/classes/draw/dimensions.ts @@ -0,0 +1,12 @@ +/** + * Describes the width and height of an object + * */ +export class Dimensions { + width: number = 0; + height: number = 0; + + constructor(width: number, height: number) { + this.width = width; + this.height = height; + } +} diff --git a/src/lib/classes/draw/point.ts b/src/lib/classes/draw/point.ts new file mode 100644 index 00000000..4f02cd0a --- /dev/null +++ b/src/lib/classes/draw/point.ts @@ -0,0 +1,12 @@ +/** + * Describes a point in a coordinate system + * */ +export class Point { + x: number; + y: number; + + constructor(x: number, y: number) { + this.x = x; + this.y = y; + } +}