From d75a8510cb9356f996c363ac0ae1b7f25139ea3e Mon Sep 17 00:00:00 2001 From: Jenny Gao <jennyg4416@gmail.com> Date: Sun, 26 Mar 2023 20:02:13 -0400 Subject: [PATCH 01/54] =?UTF-8?q?add=20=E2=8A=A4=20and=20=E2=8A=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Jody Sunray <55996087+jssunray34@users.noreply.github.com> --- userguide.md | 2 ++ views/index.pug | 8 ++++++++ 2 files changed, 10 insertions(+) diff --git a/userguide.md b/userguide.md index 6de9325..b2ad00f 100644 --- a/userguide.md +++ b/userguide.md @@ -32,6 +32,8 @@ Symbol|Options [Equivalence](https://en.wikipedia.org/wiki/If_and_only_if)|`iff` `equiv` `↔` `%` `<->` [Universal Quantifier](https://en.wikipedia.org/wiki/Universal_quantification)|`forall` `∀` [Existential Quantifier](https://en.wikipedia.org/wiki/Existential_quantification)|`exists` `∃` +[Tautology](https://en.wikipedia.org/wiki/Tautology_(logic))|`⊤` +[Contradition](https://en.wikipedia.org/wiki/Contradiction)|`⊥` Open Branch|`◯` Closed Branch|`×` diff --git a/views/index.pug b/views/index.pug index 7e087f6..bc62704 100644 --- a/views/index.pug +++ b/views/index.pug @@ -257,6 +257,14 @@ html(lang='en') td ∃ td substitution-recorder(symbol='∃' default='/') + tr + td ⊤ + td + substitution-recorder(symbol='⊤' default='T') + tr + td ⊥ + td + substitution-recorder(symbol='⊥' default='F') tr td ◯ td From 6a510a389d97432f36fde796b15204e1796bedaa Mon Sep 17 00:00:00 2001 From: jssunray34 <55996087+jssunray34@users.noreply.github.com> Date: Sun, 26 Mar 2023 21:09:20 -0400 Subject: [PATCH 02/54] Validate tautology --- src/common/statement.ts | 166 ++++++++++++++++++++++++++++++++++++++++ src/common/tree.ts | 14 ++++ 2 files changed, 180 insertions(+) diff --git a/src/common/statement.ts b/src/common/statement.ts index 46bf53b..9158f0d 100644 --- a/src/common/statement.ts +++ b/src/common/statement.ts @@ -14,6 +14,22 @@ export abstract class Statement { ); } + isTautology(): boolean { + if (this instanceof OrStatement) { + const lhs = this.operands[0]; + const rhs = this.operands[1]; + console.log("lhs: " + lhs); + console.log("rhs: " + rhs); + if (lhs.equals(new NotStatement(rhs))) { + return true; + } else if (rhs.equals(new NotStatement(lhs))) { + return true; + } + } + + return false; + } + /** * Decomposes this statement into an array of branches, where each branch * contains the necessary decomposed statements. @@ -583,3 +599,153 @@ class StatementEquivalenceEvaluator { return false; } } + +export class StatementReducer { + statement: Statement; + + constructor(statement: Statement) { + this.statement = statement; + } + + /** + * Checks if the conclusion is a valid not reduction of this statement + * given the literal. + * @param literal the branch taken (e.g., H or ¬H) + * @param conclusion the predicted conclusion + */ + private checkNotReduction(assertion: Statement, conclusion: Statement): boolean { + if (this.statement instanceof NotStatement) { + console.log("NotStatment!") + console.log(this.statement.operand); + let operand = this.statement.operand; + if (assertion.equals(operand)) { + return conclusion instanceof Contradiction; + } else if (assertion.equals(new NotStatement(operand))) { + return conclusion instanceof Tautology; + } + } + + return false; + } + + /** + * Checks if the conclusion is a valid and reduction of this statement + * given the literal. + * @param literal the branch taken (e.g., H or ¬H) + * @param conclusion the predicted conclusion + */ + private checkAndReduction(assertion: Statement, conclusion: Statement): boolean { + if (this.statement instanceof AndStatement) { + console.log("AndStatement!"); + console.log("left: " + this.statement.operands[0]); + console.log("right: " + this.statement.operands[1]); + let lhs = this.statement.operands[0]; + let rhs = this.statement.operands[1]; + if (assertion.equals(lhs)) { + return conclusion.equals(rhs); + } else if (assertion.equals(rhs)) { + return conclusion.equals(lhs); + } else if (assertion.equals(new NotStatement(lhs))) { + return conclusion instanceof Contradiction; + } else if (assertion.equals(new NotStatement(rhs))) { + return conclusion instanceof Contradiction; + } + } + + return false; + } + + /** + * Checks if the conclusion is a valid or reduction of this statement + * given the literal. + * @param literal the branch taken (e.g., H or ¬H) + * @param conclusion the predicted conclusion + */ + private checkOrReduction(assertion: Statement, conclusion: Statement): boolean { + if (this.statement instanceof OrStatement) { + console.log("OrStatement!"); + console.log("left: " + this.statement.operands[0]); + console.log("right: " + this.statement.operands[1]); + let lhs = this.statement.operands[0]; + let rhs = this.statement.operands[1]; + if (assertion.equals(lhs)) { + return conclusion instanceof Tautology; + } else if (assertion.equals(rhs)) { + return conclusion instanceof Tautology; + } else if (assertion.equals(new NotStatement(lhs))) { + return conclusion.equals(rhs); + } else if (assertion.equals(new NotStatement(rhs))) { + return conclusion.equals(lhs); + } + } + + return false; + } + + /** + * Checks if the conclusion is a valid conditional reduction of this statement + * given the literal. + * @param literal the branch taken (e.g., H or ¬H) + * @param conclusion the predicted conclusion + */ + private checkConditionalReduction(assertion: Statement, conclusion: Statement): boolean { + if (this.statement instanceof ConditionalStatement) { + console.log("ConditionalStatement!"); + console.log("left: " + this.statement.lhs); + console.log("right: " + this.statement.rhs); + let lhs = this.statement.lhs; + let rhs = this.statement.rhs; + if (assertion.equals(lhs)) { + return conclusion.equals(rhs); + } else if (assertion.equals(rhs)) { + return conclusion instanceof Tautology; + } else if (assertion.equals(new NotStatement(lhs))) { + return conclusion instanceof Tautology; + } else if (assertion.equals(new NotStatement(rhs))) { + return conclusion.equals(new NotStatement(lhs)); + } + } + + return false; + } + + /** + * Checks if the conclusion is a valid biconditional reduction of this statement + * given the literal. + * @param literal the branch taken (e.g., H or ¬H) + * @param conclusion the predicted conclusion + */ + private checkBiconditionalReduction(assertion: Statement, conclusion: Statement): boolean { + if (this.statement instanceof BiconditionalStatement) { + console.log("BiconditionalStatement!"); + console.log("left: " + this.statement.lhs); + console.log("right: " + this.statement.rhs); + let lhs = this.statement.lhs; + let rhs = this.statement.rhs; + if (assertion.equals(lhs)) { + return conclusion.equals(rhs); + } else if (assertion.equals(rhs)) { + return conclusion.equals(lhs); + } else if (assertion.equals(new NotStatement(lhs))) { + return conclusion.equals(new NotStatement(rhs)); + } else if (assertion.equals(new NotStatement(rhs))) { + return conclusion.equals(new NotStatement(lhs)); + } + } + + return false; + } + + /** + * Verifies whether the conclusion is a valid reduction (i.e., it must satisfy + * one of the reduction rules). + * @returns true if the conclusion is valid and false otherwise + */ + validateReduction(assertion: Statement, conclusion: Statement): boolean { + return this.checkNotReduction(assertion, conclusion) || + this.checkAndReduction(assertion, conclusion) || + this.checkOrReduction(assertion, conclusion) || + this.checkConditionalReduction(assertion, conclusion) || + this.checkBiconditionalReduction(assertion, conclusion); + } +} diff --git a/src/common/tree.ts b/src/common/tree.ts index 227f274..e61b799 100644 --- a/src/common/tree.ts +++ b/src/common/tree.ts @@ -107,6 +107,7 @@ export class TruthTreeNode { private _text = ''; private _statement: Statement | null = null; premise = false; + isTautology = false; comment: string | null = null; tree: TruthTree; @@ -139,6 +140,7 @@ export class TruthTreeNode { const newNode = new TruthTreeNode(this.id, newTree); newNode.text = this.text; newNode.premise = this.premise; + newNode.isTautology = this.isTautology; newNode.comment = this.comment; newNode.parent = this.parent; newNode.children = [...this.children]; @@ -238,6 +240,9 @@ export class TruthTreeNode { */ set statement(newStatement: Statement | null) { this._statement = newStatement; + if (this._statement?.isTautology()) { + this.isTautology = true; + } this._correctDecomposition = null; // Anything that references this is also invalid. if (this.antecedent !== null) { @@ -589,6 +594,11 @@ export class TruthTreeNode { return true; } + if (this.isTautology) { + // Tautologies are always valid + return true; + } + // Non-premises must have an antecedent for this statement to be valid if (this.antecedent === null || !(this.antecedent in this.tree.nodes)) { return new CorrectnessError('not_logical_consequence'); @@ -939,6 +949,10 @@ export class TruthTreeNode { return 'This statement is a premise.'; } + if (this.isTautology) { + return 'This statement is a tautology.'; + } + if (this.isTerminator()) { if (this.isOpenTerminator()) { return 'This open branch represents a valid assignment.'; From aca67bc4bc578504fa1779064c0ae2c64d573e37 Mon Sep 17 00:00:00 2001 From: jssunray34 <55996087+jssunray34@users.noreply.github.com> Date: Sun, 2 Apr 2023 13:05:57 -0400 Subject: [PATCH 03/54] Create new modifyDecomposition and add call to validateReduction Co-Authored-By: Jenny Gao <29582421+jeninyg@users.noreply.github.com> --- src/client/component/truth-tree-branch.ts | 31 ++++++++++++++++++++++- src/common/tree.ts | 14 ++++++++++ 2 files changed, 44 insertions(+), 1 deletion(-) diff --git a/src/client/component/truth-tree-branch.ts b/src/client/component/truth-tree-branch.ts index d00394e..9db27c6 100644 --- a/src/client/component/truth-tree-branch.ts +++ b/src/client/component/truth-tree-branch.ts @@ -76,6 +76,27 @@ export const TruthTreeBranchComponent = defineComponent({ this.childBranches.push(ref); } }, + modifyDecompositionDP(id: number) { + // TODO: Document this function more + const selectedNode: TruthTreeNode | null = + this.$store.getters.selectedNode; + + if (selectedNode === null || selectedNode.id === id) { + return; + } + + if (selectedNode.decomposition.has(id)) { + selectedNode.decomposition.delete(id); + } else { + selectedNode.decomposition.add(id); + } + const decomp = Array.from(selectedNode.decomposition); + for (let i = 0; i < decomp.length; i++) { + // console.log("hello"); + // console.log(decomp[i]); + console.log(this.tree.nodes[decomp[i]]); + } + }, /** * Adds or removes a given node from the decomposition of the selected node, * or vice-versa depending on the position of the selected node relative to @@ -101,6 +122,14 @@ export const TruthTreeBranchComponent = defineComponent({ } else { selectedNode.decomposition.add(id); } + const decomp = Array.from(selectedNode.decomposition); + for (let i = 0; i < decomp.length; i++) { + // console.log("hello"); + // console.log(decomp[i]); + console.log(this.tree.nodes[decomp[i]]); + } + // let first = decomp[0] + // console.log(this.tree.nodes[decomp[0]]) } else if (selectedNode.isAncestorOf(id)) { // When the selected is BEFORE, it becomes decomposition const otherNode: TruthTreeNode = this.$store.state.tree.nodes[id]; @@ -211,7 +240,7 @@ export const TruthTreeBranchComponent = defineComponent({ <ul class="branch"> <template v-for="id, index in branch"> <li v-if="index === 0 || expanded" - @contextmenu.prevent="modifyDecomposition(id)" + @contextmenu.prevent="modifyDecompositionDP(id)" @click="$store.commit('select', {id: id})" :class="{ selected: selected === id, diff --git a/src/common/tree.ts b/src/common/tree.ts index e61b799..335310e 100644 --- a/src/common/tree.ts +++ b/src/common/tree.ts @@ -7,6 +7,7 @@ import { QuantifierStatement, ExistenceStatement, UniversalStatement, + StatementReducer, } from './statement'; import { deleteMapping, @@ -599,6 +600,19 @@ export class TruthTreeNode { return true; } + if (this._statement) { + let statementReducer = new StatementReducer(this._statement); + let decompositionArr = Array.from(this.decomposition); + let left = decompositionArr[0]; + let right = decompositionArr[0]; + let leftNode = this.tree.nodes[left]; + let rightNode = this.tree.nodes[right]; + if (leftNode._statement && rightNode._statement) { + let res = statementReducer.validateReduction(leftNode._statement, rightNode._statement) || + statementReducer.validateReduction(rightNode._statement, leftNode._statement); + } + } + // Non-premises must have an antecedent for this statement to be valid if (this.antecedent === null || !(this.antecedent in this.tree.nodes)) { return new CorrectnessError('not_logical_consequence'); From c5b800c251e49ea666f40435a6e1aefb82686744 Mon Sep 17 00:00:00 2001 From: jssunray34 <55996087+jssunray34@users.noreply.github.com> Date: Sun, 2 Apr 2023 13:12:21 -0400 Subject: [PATCH 04/54] Fix undefined error Co-Authored-By: Jenny Gao <29582421+jeninyg@users.noreply.github.com> --- src/common/tree.ts | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/src/common/tree.ts b/src/common/tree.ts index 335310e..79b4dcc 100644 --- a/src/common/tree.ts +++ b/src/common/tree.ts @@ -603,13 +603,15 @@ export class TruthTreeNode { if (this._statement) { let statementReducer = new StatementReducer(this._statement); let decompositionArr = Array.from(this.decomposition); - let left = decompositionArr[0]; - let right = decompositionArr[0]; - let leftNode = this.tree.nodes[left]; - let rightNode = this.tree.nodes[right]; - if (leftNode._statement && rightNode._statement) { - let res = statementReducer.validateReduction(leftNode._statement, rightNode._statement) || - statementReducer.validateReduction(rightNode._statement, leftNode._statement); + if (decompositionArr.length == 2) { + let left = decompositionArr[0]; + let right = decompositionArr[1]; + let leftNode = this.tree.nodes[left]; + let rightNode = this.tree.nodes[right]; + if (leftNode._statement && rightNode._statement) { + let res = statementReducer.validateReduction(leftNode._statement, rightNode._statement) || + statementReducer.validateReduction(rightNode._statement, leftNode._statement); + } } } From 2c8523ce11876d64a6cf7fda2ea7c8b368bcae24 Mon Sep 17 00:00:00 2001 From: jssunray34 <55996087+jssunray34@users.noreply.github.com> Date: Sun, 2 Apr 2023 13:16:43 -0400 Subject: [PATCH 05/54] Add reduction rule tests Co-Authored-By: Jenny Gao <29582421+jeninyg@users.noreply.github.com> --- tests/reductionRules.test.ts | 168 +++++++++++++++++++++++++++++++++++ 1 file changed, 168 insertions(+) create mode 100644 tests/reductionRules.test.ts diff --git a/tests/reductionRules.test.ts b/tests/reductionRules.test.ts new file mode 100644 index 0000000..eee8be9 --- /dev/null +++ b/tests/reductionRules.test.ts @@ -0,0 +1,168 @@ +import {Formula} from '../src/common/formula'; +import { + StatementReducer, + AndStatement, + AtomicStatement, + NotStatement, + Contradiction, + OrStatement, + ConditionalStatement, + BiconditionalStatement, + Tautology +} from '../src/common/statement'; + +const notStatementToReduce = new NotStatement(new AtomicStatement(new Formula("H"))); +const andStatementToReduce1 = new AndStatement(new AtomicStatement(new Formula("H")), new AtomicStatement(new Formula("B"))); +const andStatementToReduce2 = new AndStatement(new AtomicStatement(new Formula("B")), new AtomicStatement(new Formula("H"))); +const orStatementToReduce1 = new OrStatement(new AtomicStatement(new Formula("H")), new AtomicStatement(new Formula("B"))); +const orStatementToReduce2 = new OrStatement(new AtomicStatement(new Formula("B")), new AtomicStatement(new Formula("H"))); +const conditionalStatementToReduce1 = new ConditionalStatement(new AtomicStatement(new Formula("H")), new AtomicStatement(new Formula("B"))); +const conditionalStatementToReduce2 = new ConditionalStatement(new AtomicStatement(new Formula("B")), new AtomicStatement(new Formula("H"))); +const biconditionalStatementToReduce1 = new BiconditionalStatement(new AtomicStatement(new Formula("H")), new AtomicStatement(new Formula("B"))); +const biconditionalStatementToReduce2 = new BiconditionalStatement(new AtomicStatement(new Formula("B")), new AtomicStatement(new Formula("H"))); + +const notStatementReducer = new StatementReducer(notStatementToReduce); +const andStatementReducer1 = new StatementReducer(andStatementToReduce1); +const andStatementReducer2 = new StatementReducer(andStatementToReduce2); +const orStatementReducer1 = new StatementReducer(orStatementToReduce1); +const orStatementReducer2 = new StatementReducer(orStatementToReduce2); +const conditionalStatementReducer1 = new StatementReducer(conditionalStatementToReduce1); +const conditionalStatementReducer2 = new StatementReducer(conditionalStatementToReduce2); +const biconditionalStatementReducer1 = new StatementReducer(biconditionalStatementToReduce1); +const biconditionalStatementReducer2 = new StatementReducer(biconditionalStatementToReduce2); + +// NOT reduction rules + +test('¬True should have conclusion False', () => { + const literal = new AtomicStatement(new Formula("H")); + const conclusion = new Contradiction; + const result = notStatementReducer.validateReduction(literal, conclusion); + expect(result).toBeTruthy(); +}); + +test('¬False should have conclusion True', () => { + const literal = new NotStatement(new AtomicStatement(new Formula("H"))); + const conclusion = new Tautology; + const result = notStatementReducer.validateReduction(literal, conclusion); + expect(result).toBeTruthy(); +}); + +// AND reduction rules + +test('True ∧ P should have conclusion P', () => { + const literal = new AtomicStatement(new Formula("H")); + const conclusion = new AtomicStatement(new Formula("B")); + const result = andStatementReducer1.validateReduction(literal, conclusion); + expect(result).toBeTruthy(); +}); + +test('False ∧ P should have conclusion False', () => { + const literal = new NotStatement(new AtomicStatement(new Formula("H"))); + const conclusion = new Contradiction; + const result = andStatementReducer1.validateReduction(literal, conclusion); + expect(result).toBeTruthy(); +}); + +test('P ∧ True should have conclusion P', () => { + const literal = new AtomicStatement(new Formula("H")); + const conclusion = new AtomicStatement(new Formula("B")); + const result = andStatementReducer2.validateReduction(literal, conclusion); + expect(result).toBeTruthy(); +}); + +test('P ∧ False should have conclusion False', () => { + const literal = new NotStatement(new AtomicStatement(new Formula("H"))); + const conclusion = new Contradiction; + const result = andStatementReducer2.validateReduction(literal, conclusion); + expect(result).toBeTruthy(); +}); + +// OR reduction rules + +test('True ∨ P should have conclusion True', () => { + const literal = new AtomicStatement(new Formula("H")); + const conclusion = new Tautology; + const result = orStatementReducer1.validateReduction(literal, conclusion); + expect(result).toBeTruthy(); +}); + +test('False ∨ P should have conclusion P', () => { + const literal = new NotStatement(new AtomicStatement(new Formula("H"))); + const conclusion = new AtomicStatement(new Formula("B")); + const result = orStatementReducer1.validateReduction(literal, conclusion); + expect(result).toBeTruthy(); +}); + +test('P ∨ True should have conclusion P', () => { + const literal = new AtomicStatement(new Formula("H")); + const conclusion = new Tautology; + const result = orStatementReducer2.validateReduction(literal, conclusion); + expect(result).toBeTruthy(); +}); + +test('P ∨ False should have conclusion P', () => { + const literal = new NotStatement(new AtomicStatement(new Formula("H"))); + const conclusion = new AtomicStatement(new Formula("B")); + const result = orStatementReducer2.validateReduction(literal, conclusion); + expect(result).toBeTruthy(); +}); + +// Conditional reduction rules + +test('True → P should have conclusion P', () => { + const literal = new AtomicStatement(new Formula("H")); + const conclusion = new AtomicStatement(new Formula("B")); + const result = conditionalStatementReducer1.validateReduction(literal, conclusion); + expect(result).toBeTruthy(); +}); + +test('False → P should have conclusion P', () => { + const literal = new NotStatement(new AtomicStatement(new Formula("H"))); + const conclusion = new Tautology; + const result = conditionalStatementReducer1.validateReduction(literal, conclusion); + expect(result).toBeTruthy(); +}); + +test('P → True should have conclusion P', () => { + const literal = new AtomicStatement(new Formula("H")); + const conclusion = new Tautology; + const result = conditionalStatementReducer2.validateReduction(literal, conclusion); + expect(result).toBeTruthy(); +}); + +test('P → False should have conclusion ¬P', () => { + const literal = new NotStatement(new AtomicStatement(new Formula("H"))); + const conclusion = new NotStatement(new AtomicStatement(new Formula("B"))); + const result = conditionalStatementReducer2.validateReduction(literal, conclusion); + expect(result).toBeTruthy(); +}); + +// Biconditional reduction rules + +test('True ↔ P should have conclusion P', () => { + const literal = new AtomicStatement(new Formula("H")); + const conclusion = new AtomicStatement(new Formula("B")); + const result = biconditionalStatementReducer1.validateReduction(literal, conclusion); + expect(result).toBeTruthy(); +}); + +test('False ↔ P should have conclusion P', () => { + const literal = new NotStatement(new AtomicStatement(new Formula("H"))); + const conclusion = new NotStatement(new AtomicStatement(new Formula("B")));; + const result = biconditionalStatementReducer1.validateReduction(literal, conclusion); + expect(result).toBeTruthy(); +}); + +test('P ↔ True should have conclusion P', () => { + const literal = new AtomicStatement(new Formula("H")); + const conclusion = new AtomicStatement(new Formula("B")); + const result = biconditionalStatementReducer2.validateReduction(literal, conclusion); + expect(result).toBeTruthy(); +}); + +test('P ↔ False should have conclusion ¬P', () => { + const literal = new NotStatement(new AtomicStatement(new Formula("H"))); + const conclusion = new NotStatement(new AtomicStatement(new Formula("B"))); + const result = biconditionalStatementReducer2.validateReduction(literal, conclusion); + expect(result).toBeTruthy(); +}); From 036853f32de6ba386de9ae283d37241eb22b3bf1 Mon Sep 17 00:00:00 2001 From: jssunray34 <55996087+jssunray34@users.noreply.github.com> Date: Sun, 2 Apr 2023 13:32:02 -0400 Subject: [PATCH 06/54] Handle result of validation Co-Authored-By: Jenny Gao <29582421+jeninyg@users.noreply.github.com> --- src/common/tree.ts | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/src/common/tree.ts b/src/common/tree.ts index 79b4dcc..ca5f234 100644 --- a/src/common/tree.ts +++ b/src/common/tree.ts @@ -601,16 +601,25 @@ export class TruthTreeNode { } if (this._statement) { - let statementReducer = new StatementReducer(this._statement); + // this._statement ==> conclusion + // leftNode._statement ==> literal + // rightNode._statement ==> statement to reduce let decompositionArr = Array.from(this.decomposition); if (decompositionArr.length == 2) { + let left = decompositionArr[0]; let right = decompositionArr[1]; let leftNode = this.tree.nodes[left]; let rightNode = this.tree.nodes[right]; + if (leftNode._statement && rightNode._statement) { - let res = statementReducer.validateReduction(leftNode._statement, rightNode._statement) || - statementReducer.validateReduction(rightNode._statement, leftNode._statement); + let statementReducer = new StatementReducer(rightNode._statement); + let res = statementReducer.validateReduction(leftNode._statement, this._statement) || + statementReducer.validateReduction(rightNode._statement, this._statement); + console.log(res); + if (res) { + return true; + } } } } From 4db7430a59c7bb5157c1ce17dcd71eaba2d01c17 Mon Sep 17 00:00:00 2001 From: Jenny Gao <jennyg4416@gmail.com> Date: Sun, 2 Apr 2023 14:56:59 -0400 Subject: [PATCH 07/54] add support for DP validator + reducer ToDo - add checks for when assertion gets absorbed by intermediate steps Co-Authored-By: Jody Sunray <55996087+jssunray34@users.noreply.github.com> --- src/client/component/truth-tree-branch.ts | 2 +- src/common/statement.ts | 263 +++++++++++++++++----- src/common/tree.ts | 35 ++- 3 files changed, 237 insertions(+), 63 deletions(-) diff --git a/src/client/component/truth-tree-branch.ts b/src/client/component/truth-tree-branch.ts index 9db27c6..b6d4326 100644 --- a/src/client/component/truth-tree-branch.ts +++ b/src/client/component/truth-tree-branch.ts @@ -84,7 +84,7 @@ export const TruthTreeBranchComponent = defineComponent({ if (selectedNode === null || selectedNode.id === id) { return; } - + if (selectedNode.decomposition.has(id)) { selectedNode.decomposition.delete(id); } else { diff --git a/src/common/statement.ts b/src/common/statement.ts index 9158f0d..8e6fab0 100644 --- a/src/common/statement.ts +++ b/src/common/statement.ts @@ -1,3 +1,4 @@ +import {not} from 'ajv/dist/compile/codegen'; import {Formula, REPLACEMENT_SYMBOL} from './formula'; import {AssignmentMap} from './util'; @@ -18,15 +19,15 @@ export abstract class Statement { if (this instanceof OrStatement) { const lhs = this.operands[0]; const rhs = this.operands[1]; - console.log("lhs: " + lhs); - console.log("rhs: " + rhs); + console.log('lhs: ' + lhs); + console.log('rhs: ' + rhs); if (lhs.equals(new NotStatement(rhs))) { return true; } else if (rhs.equals(new NotStatement(lhs))) { return true; } } - + return false; } @@ -600,32 +601,58 @@ class StatementEquivalenceEvaluator { } } -export class StatementReducer { - statement: Statement; +/* + * Given a statement and literal, check it reduces to conclusion + * Our davis puttnam reducer + * StatementReducer + */ +export class DPStatementReducer { + statement: Statement; // the conclustion constructor(statement: Statement) { this.statement = statement; } + /** + * check if statment is a simple statement + */ + private isSimpleStatement(statement: Statement) { + // TODO: maybe check statement can be Tautology/ Contradiction + return ( + statement instanceof AtomicStatement || + statement instanceof Tautology || + statement instanceof Contradiction + ); + } + /** * Checks if the conclusion is a valid not reduction of this statement * given the literal. * @param literal the branch taken (e.g., H or ¬H) * @param conclusion the predicted conclusion */ - private checkNotReduction(assertion: Statement, conclusion: Statement): boolean { + private reduceNotStatement(assertion: Statement): Statement | null { if (this.statement instanceof NotStatement) { - console.log("NotStatment!") + console.log('NotStatment!'); console.log(this.statement.operand); let operand = this.statement.operand; + + if (!this.isSimpleStatement(operand)) { + let new_operand = new DPStatementReducer(operand).reduceStatement( + assertion + ); + if (new_operand) { + operand = new_operand; + } + } + if (assertion.equals(operand)) { - return conclusion instanceof Contradiction; + return new Contradiction(); } else if (assertion.equals(new NotStatement(operand))) { - return conclusion instanceof Tautology; + return new Tautology(); } } - - return false; + return null; } /** @@ -634,25 +661,45 @@ export class StatementReducer { * @param literal the branch taken (e.g., H or ¬H) * @param conclusion the predicted conclusion */ - private checkAndReduction(assertion: Statement, conclusion: Statement): boolean { + private reduceAndStatement(assertion: Statement): Statement | null { if (this.statement instanceof AndStatement) { - console.log("AndStatement!"); - console.log("left: " + this.statement.operands[0]); - console.log("right: " + this.statement.operands[1]); + console.log('[hi] AndStatement!'); + console.log(this.statement.toString()); + + console.log('left: ' + this.statement.operands[0]); + console.log('right: ' + this.statement.operands[1]); let lhs = this.statement.operands[0]; let rhs = this.statement.operands[1]; + + if (!this.isSimpleStatement(lhs)) { + let new_operand = new DPStatementReducer(lhs).reduceStatement( + assertion + ); + if (new_operand) { + lhs = new_operand; + } + } + if (!this.isSimpleStatement(rhs)) { + let new_operand = new DPStatementReducer(rhs).reduceStatement( + assertion + ); + if (new_operand) { + rhs = new_operand; + } + } + console.log('And statements REDUCED', lhs.toString, rhs.toString); if (assertion.equals(lhs)) { - return conclusion.equals(rhs); + return rhs; } else if (assertion.equals(rhs)) { - return conclusion.equals(lhs); + return lhs; } else if (assertion.equals(new NotStatement(lhs))) { - return conclusion instanceof Contradiction; + return new Contradiction(); } else if (assertion.equals(new NotStatement(rhs))) { - return conclusion instanceof Contradiction; + return new Contradiction(); } } - return false; + return null; } /** @@ -661,25 +708,41 @@ export class StatementReducer { * @param literal the branch taken (e.g., H or ¬H) * @param conclusion the predicted conclusion */ - private checkOrReduction(assertion: Statement, conclusion: Statement): boolean { + private reduceOrStatement(assertion: Statement): Statement | null { if (this.statement instanceof OrStatement) { - console.log("OrStatement!"); - console.log("left: " + this.statement.operands[0]); - console.log("right: " + this.statement.operands[1]); + console.log('OrStatement!'); + console.log('left: ' + this.statement.operands[0]); + console.log('right: ' + this.statement.operands[1]); let lhs = this.statement.operands[0]; let rhs = this.statement.operands[1]; + if (!this.isSimpleStatement(lhs)) { + let new_operand = new DPStatementReducer(lhs).reduceStatement( + assertion + ); + if (new_operand) { + lhs = new_operand; + } + } + if (!this.isSimpleStatement(rhs)) { + let new_operand = new DPStatementReducer(rhs).reduceStatement( + assertion + ); + if (new_operand) { + rhs = new_operand; + } + } if (assertion.equals(lhs)) { - return conclusion instanceof Tautology; + return new Tautology(); } else if (assertion.equals(rhs)) { - return conclusion instanceof Tautology; + return new Tautology(); } else if (assertion.equals(new NotStatement(lhs))) { - return conclusion.equals(rhs); + return rhs; } else if (assertion.equals(new NotStatement(rhs))) { - return conclusion.equals(lhs); + return lhs; } } - return false; + return null; } /** @@ -688,25 +751,53 @@ export class StatementReducer { * @param literal the branch taken (e.g., H or ¬H) * @param conclusion the predicted conclusion */ - private checkConditionalReduction(assertion: Statement, conclusion: Statement): boolean { + private reduceConditionalStatement(assertion: Statement): Statement { + // can we reduce on the statement if (this.statement instanceof ConditionalStatement) { - console.log("ConditionalStatement!"); - console.log("left: " + this.statement.lhs); - console.log("right: " + this.statement.rhs); + console.log('[hi] ConditionalStatement!'); + console.log(this.statement.toString()); + + console.log('left: ' + this.statement.lhs); + console.log('right: ' + this.statement.rhs); let lhs = this.statement.lhs; let rhs = this.statement.rhs; + if (!this.isSimpleStatement(lhs)) { + let new_operand = new DPStatementReducer(lhs).reduceStatement( + assertion + ); + if (new_operand) { + lhs = new_operand; + } + } + if (!this.isSimpleStatement(rhs)) { + let new_operand = new DPStatementReducer(rhs).reduceStatement( + assertion + ); + if (new_operand) { + rhs = new_operand; + } + } + console.log( + 'Conditional statements REDUCED', + lhs.toString(), + rhs.toString() + ); + if (assertion.equals(lhs)) { - return conclusion.equals(rhs); + return rhs; } else if (assertion.equals(rhs)) { - return conclusion instanceof Tautology; + return new Tautology(); } else if (assertion.equals(new NotStatement(lhs))) { - return conclusion instanceof Tautology; + return new Tautology(); } else if (assertion.equals(new NotStatement(rhs))) { - return conclusion.equals(new NotStatement(lhs)); + return new NotStatement(lhs); + // assertions get absorbed by intermediate steps + } else if (rhs instanceof Contradiction) { + return new NotStatement(lhs); } } - return false; + return this.statement; } /** @@ -715,25 +806,92 @@ export class StatementReducer { * @param literal the branch taken (e.g., H or ¬H) * @param conclusion the predicted conclusion */ - private checkBiconditionalReduction(assertion: Statement, conclusion: Statement): boolean { + private reduceBiconditionalStatement(assertion: Statement): Statement { if (this.statement instanceof BiconditionalStatement) { - console.log("BiconditionalStatement!"); - console.log("left: " + this.statement.lhs); - console.log("right: " + this.statement.rhs); + console.log('BiconditionalStatement!'); + console.log('left: ' + this.statement.lhs); + console.log('right: ' + this.statement.rhs); let lhs = this.statement.lhs; let rhs = this.statement.rhs; + if (!this.isSimpleStatement(lhs)) { + let new_operand = new DPStatementReducer(lhs).reduceStatement( + assertion + ); + if (new_operand) { + lhs = new_operand; + } + } + if (!this.isSimpleStatement(rhs)) { + let new_operand = new DPStatementReducer(rhs).reduceStatement( + assertion + ); + if (new_operand) { + rhs = new_operand; + } + } if (assertion.equals(lhs)) { - return conclusion.equals(rhs); + return rhs; } else if (assertion.equals(rhs)) { - return conclusion.equals(lhs); + return lhs; } else if (assertion.equals(new NotStatement(lhs))) { - return conclusion.equals(new NotStatement(rhs)); + return rhs; } else if (assertion.equals(new NotStatement(rhs))) { - return conclusion.equals(new NotStatement(lhs)); + return lhs; } } - return false; + return this.statement; + } + + /** + * Verifies whether the conclusion is a valid reduction (i.e., it must satisfy + * one of the reduction rules). + * @returns true if the conclusion is valid and false otherwise + */ + reduceStatement(assertion: Statement): Statement { + const notStatement = this.reduceNotStatement(assertion); + // console.log('Not', notStatement?.toString()); + if (notStatement) { + return notStatement; + } + const andStatement = this.reduceAndStatement(assertion); + // console.log('And', andStatement?.toString()); + if (andStatement) { + return andStatement; + } + const orStatement = this.reduceOrStatement(assertion); + // console.log('Or', orStatement?.toString()); + if (orStatement) { + return orStatement; + } + const conditionalStatement = this.reduceConditionalStatement(assertion); + // console.log('Cond', conditionalStatement?.toString()); + + if (conditionalStatement) { + return conditionalStatement; + } + const biconditionalStatement = this.reduceBiconditionalStatement(assertion); + // console.log('Cond', biconditionalStatement?.toString()); + + if (biconditionalStatement) { + return biconditionalStatement; + } + return this.statement; + } +} + +export class DPStatementValidator { + statement: Statement; // statement we're attempting to reduce + assertion: Statement; + // reducer: DPStatementReducer; + validConclusion: Statement | null; + + constructor(statement: Statement, assertion: Statement) { + this.statement = statement; + this.assertion = assertion; + this.validConclusion = new DPStatementReducer(statement).reduceStatement( + this.assertion + ); } /** @@ -741,11 +899,10 @@ export class StatementReducer { * one of the reduction rules). * @returns true if the conclusion is valid and false otherwise */ - validateReduction(assertion: Statement, conclusion: Statement): boolean { - return this.checkNotReduction(assertion, conclusion) || - this.checkAndReduction(assertion, conclusion) || - this.checkOrReduction(assertion, conclusion) || - this.checkConditionalReduction(assertion, conclusion) || - this.checkBiconditionalReduction(assertion, conclusion); + validateReduction(conclusion: Statement): boolean { + if (this.validConclusion?.equals(conclusion)) { + return true; + } + return false; } } diff --git a/src/common/tree.ts b/src/common/tree.ts index 335310e..b7eb9c9 100644 --- a/src/common/tree.ts +++ b/src/common/tree.ts @@ -7,7 +7,7 @@ import { QuantifierStatement, ExistenceStatement, UniversalStatement, - StatementReducer, + DPStatementValidator, } from './statement'; import { deleteMapping, @@ -601,15 +601,32 @@ export class TruthTreeNode { } if (this._statement) { - let statementReducer = new StatementReducer(this._statement); let decompositionArr = Array.from(this.decomposition); - let left = decompositionArr[0]; - let right = decompositionArr[0]; - let leftNode = this.tree.nodes[left]; - let rightNode = this.tree.nodes[right]; - if (leftNode._statement && rightNode._statement) { - let res = statementReducer.validateReduction(leftNode._statement, rightNode._statement) || - statementReducer.validateReduction(rightNode._statement, leftNode._statement); + if (decompositionArr.length == 2) { + let left = decompositionArr[0]; + let right = decompositionArr[1]; + let leftNode = this.tree.nodes[left]; + let rightNode = this.tree.nodes[right]; + + if (leftNode._statement && rightNode._statement) { + // Validator takes in statement we wouled like to reduce along with assertion + let statementReducer = new DPStatementValidator( + leftNode._statement, + rightNode._statement + ); + let statementReducer2 = new DPStatementValidator( + rightNode._statement, + leftNode._statement + ); + + let res = + statementReducer.validateReduction(this._statement) || + statementReducer2.validateReduction(this._statement); + + if (res) { + return true; + } + } } } From d867fc205f4438a20f4b7a213f9e17ec5c22e8e7 Mon Sep 17 00:00:00 2001 From: jssunray34 <55996087+jssunray34@users.noreply.github.com> Date: Mon, 3 Apr 2023 14:37:30 -0400 Subject: [PATCH 08/54] Add absorption check Co-Authored-By: Jenny Gao <29582421+jeninyg@users.noreply.github.com> --- src/common/statement.ts | 95 ++++++++++++++++++++--------------------- src/common/tree.ts | 1 + views/index.pug | 4 +- 3 files changed, 50 insertions(+), 50 deletions(-) diff --git a/src/common/statement.ts b/src/common/statement.ts index 8e6fab0..4217083 100644 --- a/src/common/statement.ts +++ b/src/common/statement.ts @@ -16,6 +16,7 @@ export abstract class Statement { } isTautology(): boolean { + console.log("TAUTOLOGY"); if (this instanceof OrStatement) { const lhs = this.operands[0]; const rhs = this.operands[1]; @@ -633,8 +634,8 @@ export class DPStatementReducer { */ private reduceNotStatement(assertion: Statement): Statement | null { if (this.statement instanceof NotStatement) { - console.log('NotStatment!'); - console.log(this.statement.operand); + // console.log('NotStatment!'); + // console.log(this.statement.operand); let operand = this.statement.operand; if (!this.isSimpleStatement(operand)) { @@ -646,9 +647,9 @@ export class DPStatementReducer { } } - if (assertion.equals(operand)) { + if (assertion.equals(operand) || operand instanceof Tautology) { return new Contradiction(); - } else if (assertion.equals(new NotStatement(operand))) { + } else if (assertion.equals(new NotStatement(operand)) || operand instanceof Contradiction) { return new Tautology(); } } @@ -663,11 +664,11 @@ export class DPStatementReducer { */ private reduceAndStatement(assertion: Statement): Statement | null { if (this.statement instanceof AndStatement) { - console.log('[hi] AndStatement!'); - console.log(this.statement.toString()); + // console.log('[hi] AndStatement!'); + // console.log(this.statement.toString()); - console.log('left: ' + this.statement.operands[0]); - console.log('right: ' + this.statement.operands[1]); + // console.log('left: ' + this.statement.operands[0]); + // console.log('right: ' + this.statement.operands[1]); let lhs = this.statement.operands[0]; let rhs = this.statement.operands[1]; @@ -687,14 +688,14 @@ export class DPStatementReducer { rhs = new_operand; } } - console.log('And statements REDUCED', lhs.toString, rhs.toString); - if (assertion.equals(lhs)) { + // console.log('And statements REDUCED', lhs.toString, rhs.toString); + if (assertion.equals(lhs) || lhs instanceof Tautology) { return rhs; - } else if (assertion.equals(rhs)) { - return lhs; - } else if (assertion.equals(new NotStatement(lhs))) { + } else if (assertion.equals(new NotStatement(lhs)) || lhs instanceof Contradiction) { return new Contradiction(); - } else if (assertion.equals(new NotStatement(rhs))) { + } else if (assertion.equals(rhs) || rhs instanceof Tautology) { + return lhs; + } else if (assertion.equals(new NotStatement(rhs)) || rhs instanceof Contradiction) { return new Contradiction(); } } @@ -710,9 +711,9 @@ export class DPStatementReducer { */ private reduceOrStatement(assertion: Statement): Statement | null { if (this.statement instanceof OrStatement) { - console.log('OrStatement!'); - console.log('left: ' + this.statement.operands[0]); - console.log('right: ' + this.statement.operands[1]); + // console.log('OrStatement!'); + // console.log('left: ' + this.statement.operands[0]); + // console.log('right: ' + this.statement.operands[1]); let lhs = this.statement.operands[0]; let rhs = this.statement.operands[1]; if (!this.isSimpleStatement(lhs)) { @@ -731,13 +732,13 @@ export class DPStatementReducer { rhs = new_operand; } } - if (assertion.equals(lhs)) { - return new Tautology(); - } else if (assertion.equals(rhs)) { + if (assertion.equals(lhs) || lhs instanceof Tautology) { return new Tautology(); - } else if (assertion.equals(new NotStatement(lhs))) { + } else if (assertion.equals(new NotStatement(lhs)) || lhs instanceof Contradiction) { return rhs; - } else if (assertion.equals(new NotStatement(rhs))) { + } else if (assertion.equals(rhs) || rhs instanceof Tautology) { + return new Tautology(); + } else if (assertion.equals(new NotStatement(rhs) || rhs instanceof Contradiction)) { return lhs; } } @@ -754,11 +755,11 @@ export class DPStatementReducer { private reduceConditionalStatement(assertion: Statement): Statement { // can we reduce on the statement if (this.statement instanceof ConditionalStatement) { - console.log('[hi] ConditionalStatement!'); - console.log(this.statement.toString()); + // console.log('[hi] ConditionalStatement!'); + // console.log(this.statement.toString()); - console.log('left: ' + this.statement.lhs); - console.log('right: ' + this.statement.rhs); + // console.log('left: ' + this.statement.lhs); + // console.log('right: ' + this.statement.rhs); let lhs = this.statement.lhs; let rhs = this.statement.rhs; if (!this.isSimpleStatement(lhs)) { @@ -777,22 +778,20 @@ export class DPStatementReducer { rhs = new_operand; } } - console.log( - 'Conditional statements REDUCED', - lhs.toString(), - rhs.toString() - ); - - if (assertion.equals(lhs)) { + // console.log( + // 'Conditional statements REDUCED', + // lhs.toString(), + // rhs.toString() + // ); + + // second part of or is when assertions get absorbed by intermediate steps + if (assertion.equals(lhs) || lhs instanceof Tautology) { return rhs; - } else if (assertion.equals(rhs)) { + } else if (assertion.equals(new NotStatement(lhs)) || lhs instanceof Contradiction) { return new Tautology(); - } else if (assertion.equals(new NotStatement(lhs))) { + } else if (assertion.equals(rhs) || rhs instanceof Tautology) { return new Tautology(); - } else if (assertion.equals(new NotStatement(rhs))) { - return new NotStatement(lhs); - // assertions get absorbed by intermediate steps - } else if (rhs instanceof Contradiction) { + } else if (assertion.equals(new NotStatement(rhs)) || rhs instanceof Contradiction) { return new NotStatement(lhs); } } @@ -808,9 +807,9 @@ export class DPStatementReducer { */ private reduceBiconditionalStatement(assertion: Statement): Statement { if (this.statement instanceof BiconditionalStatement) { - console.log('BiconditionalStatement!'); - console.log('left: ' + this.statement.lhs); - console.log('right: ' + this.statement.rhs); + // console.log('BiconditionalStatement!'); + // console.log('left: ' + this.statement.lhs); + // console.log('right: ' + this.statement.rhs); let lhs = this.statement.lhs; let rhs = this.statement.rhs; if (!this.isSimpleStatement(lhs)) { @@ -829,14 +828,14 @@ export class DPStatementReducer { rhs = new_operand; } } - if (assertion.equals(lhs)) { + if (assertion.equals(lhs) || lhs instanceof Tautology) { return rhs; - } else if (assertion.equals(rhs)) { - return lhs; - } else if (assertion.equals(new NotStatement(lhs))) { - return rhs; - } else if (assertion.equals(new NotStatement(rhs))) { + } else if (assertion.equals(new NotStatement(lhs)) || lhs instanceof Contradiction) { + return new NotStatement(rhs); + } else if (assertion.equals(rhs) || rhs instanceof Tautology) { return lhs; + } else if (assertion.equals(new NotStatement(rhs)) || rhs instanceof Contradiction) { + return new NotStatement(lhs); } } diff --git a/src/common/tree.ts b/src/common/tree.ts index b7eb9c9..d51289e 100644 --- a/src/common/tree.ts +++ b/src/common/tree.ts @@ -242,6 +242,7 @@ export class TruthTreeNode { set statement(newStatement: Statement | null) { this._statement = newStatement; if (this._statement?.isTautology()) { + console.log("SET TO TRUE"); this.isTautology = true; } this._correctDecomposition = null; diff --git a/views/index.pug b/views/index.pug index bc62704..3d56e98 100644 --- a/views/index.pug +++ b/views/index.pug @@ -260,11 +260,11 @@ html(lang='en') tr td ⊤ td - substitution-recorder(symbol='⊤' default='T') + substitution-recorder(symbol='⊤' default='+') tr td ⊥ td - substitution-recorder(symbol='⊥' default='F') + substitution-recorder(symbol='⊥' default='-') tr td ◯ td From ac01341b49d4962a51f9a8ff3681c17ceba861fb Mon Sep 17 00:00:00 2001 From: Jenny Gao <jennyg4416@gmail.com> Date: Mon, 3 Apr 2023 17:15:27 -0400 Subject: [PATCH 09/54] return reduced statement if no base checks passes Co-Authored-By: Jody Sunray <55996087+jssunray34@users.noreply.github.com> --- src/common/statement.ts | 67 ++++++++++++++++++----------------------- src/common/tree.ts | 5 ++- 2 files changed, 31 insertions(+), 41 deletions(-) diff --git a/src/common/statement.ts b/src/common/statement.ts index 4217083..553007e 100644 --- a/src/common/statement.ts +++ b/src/common/statement.ts @@ -632,7 +632,7 @@ export class DPStatementReducer { * @param literal the branch taken (e.g., H or ¬H) * @param conclusion the predicted conclusion */ - private reduceNotStatement(assertion: Statement): Statement | null { + private reduceNotStatement(assertion: Statement): Statement { if (this.statement instanceof NotStatement) { // console.log('NotStatment!'); // console.log(this.statement.operand); @@ -652,8 +652,10 @@ export class DPStatementReducer { } else if (assertion.equals(new NotStatement(operand)) || operand instanceof Contradiction) { return new Tautology(); } + return new NotStatement(operand); + } - return null; + return this.statement; } /** @@ -662,7 +664,7 @@ export class DPStatementReducer { * @param literal the branch taken (e.g., H or ¬H) * @param conclusion the predicted conclusion */ - private reduceAndStatement(assertion: Statement): Statement | null { + private reduceAndStatement(assertion: Statement): Statement { if (this.statement instanceof AndStatement) { // console.log('[hi] AndStatement!'); // console.log(this.statement.toString()); @@ -698,9 +700,10 @@ export class DPStatementReducer { } else if (assertion.equals(new NotStatement(rhs)) || rhs instanceof Contradiction) { return new Contradiction(); } + return new AndStatement(lhs, rhs); } - return null; + return this.statement; } /** @@ -709,7 +712,7 @@ export class DPStatementReducer { * @param literal the branch taken (e.g., H or ¬H) * @param conclusion the predicted conclusion */ - private reduceOrStatement(assertion: Statement): Statement | null { + private reduceOrStatement(assertion: Statement): Statement { if (this.statement instanceof OrStatement) { // console.log('OrStatement!'); // console.log('left: ' + this.statement.operands[0]); @@ -741,9 +744,10 @@ export class DPStatementReducer { } else if (assertion.equals(new NotStatement(rhs) || rhs instanceof Contradiction)) { return lhs; } + return new OrStatement(lhs, rhs); } - return null; + return this.statement; } /** @@ -778,11 +782,11 @@ export class DPStatementReducer { rhs = new_operand; } } - // console.log( - // 'Conditional statements REDUCED', - // lhs.toString(), - // rhs.toString() - // ); + console.log( + 'Conditional statements REDUCED', + lhs.toString(), + rhs.toString() + ); // second part of or is when assertions get absorbed by intermediate steps if (assertion.equals(lhs) || lhs instanceof Tautology) { @@ -794,6 +798,7 @@ export class DPStatementReducer { } else if (assertion.equals(new NotStatement(rhs)) || rhs instanceof Contradiction) { return new NotStatement(lhs); } + return new ConditionalStatement(lhs, rhs); } return this.statement; @@ -837,6 +842,7 @@ export class DPStatementReducer { } else if (assertion.equals(new NotStatement(rhs)) || rhs instanceof Contradiction) { return new NotStatement(lhs); } + return new BiconditionalStatement(lhs, rhs); } return this.statement; @@ -848,32 +854,20 @@ export class DPStatementReducer { * @returns true if the conclusion is valid and false otherwise */ reduceStatement(assertion: Statement): Statement { - const notStatement = this.reduceNotStatement(assertion); - // console.log('Not', notStatement?.toString()); - if (notStatement) { - return notStatement; + if (this.statement instanceof NotStatement){ + return this.reduceNotStatement(assertion);; } - const andStatement = this.reduceAndStatement(assertion); - // console.log('And', andStatement?.toString()); - if (andStatement) { - return andStatement; + if (this.statement instanceof AndStatement){ + return this.reduceAndStatement(assertion); } - const orStatement = this.reduceOrStatement(assertion); - // console.log('Or', orStatement?.toString()); - if (orStatement) { - return orStatement; + if (this.statement instanceof OrStatement){ + return this.reduceOrStatement(assertion); } - const conditionalStatement = this.reduceConditionalStatement(assertion); - // console.log('Cond', conditionalStatement?.toString()); - - if (conditionalStatement) { - return conditionalStatement; + if (this.statement instanceof ConditionalStatement){ + return this.reduceConditionalStatement(assertion); } - const biconditionalStatement = this.reduceBiconditionalStatement(assertion); - // console.log('Cond', biconditionalStatement?.toString()); - - if (biconditionalStatement) { - return biconditionalStatement; + if (this.statement instanceof BiconditionalStatement){ + return this.reduceBiconditionalStatement(assertion); } return this.statement; } @@ -883,7 +877,7 @@ export class DPStatementValidator { statement: Statement; // statement we're attempting to reduce assertion: Statement; // reducer: DPStatementReducer; - validConclusion: Statement | null; + validConclusion: Statement; constructor(statement: Statement, assertion: Statement) { this.statement = statement; @@ -899,9 +893,6 @@ export class DPStatementValidator { * @returns true if the conclusion is valid and false otherwise */ validateReduction(conclusion: Statement): boolean { - if (this.validConclusion?.equals(conclusion)) { - return true; - } - return false; + return this.validConclusion.equals(conclusion); } } diff --git a/src/common/tree.ts b/src/common/tree.ts index d51289e..5207cc1 100644 --- a/src/common/tree.ts +++ b/src/common/tree.ts @@ -113,10 +113,10 @@ export class TruthTreeNode { tree: TruthTree; - parent: number | null = null; + parent: number | null = null; // physical parent children: number[] = []; - antecedent: number | null = null; + antecedent: number | null = null; // logical parent decomposition: Set<number> = new Set(); private _correctDecomposition: Set<number> | null = null; @@ -242,7 +242,6 @@ export class TruthTreeNode { set statement(newStatement: Statement | null) { this._statement = newStatement; if (this._statement?.isTautology()) { - console.log("SET TO TRUE"); this.isTautology = true; } this._correctDecomposition = null; From 498104360bfd599852c12941434cf093cbddc74f Mon Sep 17 00:00:00 2001 From: Jenny Gao <jennyg4416@gmail.com> Date: Tue, 4 Apr 2023 16:01:01 -0400 Subject: [PATCH 10/54] prettier Co-Authored-By: Jody Sunray <55996087+jssunray34@users.noreply.github.com> --- .gitignore | 7 +++++ src/common/statement.ts | 59 +++++++++++++++++++++++++++++------------ 2 files changed, 49 insertions(+), 17 deletions(-) diff --git a/.gitignore b/.gitignore index ff9733a..8487be1 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,6 @@ +# mac +.DS_Store + config.yml logs/* @@ -138,3 +141,7 @@ dist ## TypeScript ## ################## build/ + + +## +WillowFiles/ diff --git a/src/common/statement.ts b/src/common/statement.ts index 553007e..66ac202 100644 --- a/src/common/statement.ts +++ b/src/common/statement.ts @@ -16,7 +16,7 @@ export abstract class Statement { } isTautology(): boolean { - console.log("TAUTOLOGY"); + console.log('TAUTOLOGY'); if (this instanceof OrStatement) { const lhs = this.operands[0]; const rhs = this.operands[1]; @@ -649,11 +649,13 @@ export class DPStatementReducer { if (assertion.equals(operand) || operand instanceof Tautology) { return new Contradiction(); - } else if (assertion.equals(new NotStatement(operand)) || operand instanceof Contradiction) { + } else if ( + assertion.equals(new NotStatement(operand)) || + operand instanceof Contradiction + ) { return new Tautology(); } return new NotStatement(operand); - } return this.statement; } @@ -693,11 +695,17 @@ export class DPStatementReducer { // console.log('And statements REDUCED', lhs.toString, rhs.toString); if (assertion.equals(lhs) || lhs instanceof Tautology) { return rhs; - } else if (assertion.equals(new NotStatement(lhs)) || lhs instanceof Contradiction) { + } else if ( + assertion.equals(new NotStatement(lhs)) || + lhs instanceof Contradiction + ) { return new Contradiction(); } else if (assertion.equals(rhs) || rhs instanceof Tautology) { return lhs; - } else if (assertion.equals(new NotStatement(rhs)) || rhs instanceof Contradiction) { + } else if ( + assertion.equals(new NotStatement(rhs)) || + rhs instanceof Contradiction + ) { return new Contradiction(); } return new AndStatement(lhs, rhs); @@ -737,11 +745,16 @@ export class DPStatementReducer { } if (assertion.equals(lhs) || lhs instanceof Tautology) { return new Tautology(); - } else if (assertion.equals(new NotStatement(lhs)) || lhs instanceof Contradiction) { + } else if ( + assertion.equals(new NotStatement(lhs)) || + lhs instanceof Contradiction + ) { return rhs; } else if (assertion.equals(rhs) || rhs instanceof Tautology) { return new Tautology(); - } else if (assertion.equals(new NotStatement(rhs) || rhs instanceof Contradiction)) { + } else if ( + assertion.equals(new NotStatement(rhs) || rhs instanceof Contradiction) + ) { return lhs; } return new OrStatement(lhs, rhs); @@ -791,11 +804,17 @@ export class DPStatementReducer { // second part of or is when assertions get absorbed by intermediate steps if (assertion.equals(lhs) || lhs instanceof Tautology) { return rhs; - } else if (assertion.equals(new NotStatement(lhs)) || lhs instanceof Contradiction) { + } else if ( + assertion.equals(new NotStatement(lhs)) || + lhs instanceof Contradiction + ) { return new Tautology(); } else if (assertion.equals(rhs) || rhs instanceof Tautology) { return new Tautology(); - } else if (assertion.equals(new NotStatement(rhs)) || rhs instanceof Contradiction) { + } else if ( + assertion.equals(new NotStatement(rhs)) || + rhs instanceof Contradiction + ) { return new NotStatement(lhs); } return new ConditionalStatement(lhs, rhs); @@ -835,11 +854,17 @@ export class DPStatementReducer { } if (assertion.equals(lhs) || lhs instanceof Tautology) { return rhs; - } else if (assertion.equals(new NotStatement(lhs)) || lhs instanceof Contradiction) { + } else if ( + assertion.equals(new NotStatement(lhs)) || + lhs instanceof Contradiction + ) { return new NotStatement(rhs); } else if (assertion.equals(rhs) || rhs instanceof Tautology) { return lhs; - } else if (assertion.equals(new NotStatement(rhs)) || rhs instanceof Contradiction) { + } else if ( + assertion.equals(new NotStatement(rhs)) || + rhs instanceof Contradiction + ) { return new NotStatement(lhs); } return new BiconditionalStatement(lhs, rhs); @@ -854,19 +879,19 @@ export class DPStatementReducer { * @returns true if the conclusion is valid and false otherwise */ reduceStatement(assertion: Statement): Statement { - if (this.statement instanceof NotStatement){ - return this.reduceNotStatement(assertion);; + if (this.statement instanceof NotStatement) { + return this.reduceNotStatement(assertion); } - if (this.statement instanceof AndStatement){ + if (this.statement instanceof AndStatement) { return this.reduceAndStatement(assertion); } - if (this.statement instanceof OrStatement){ + if (this.statement instanceof OrStatement) { return this.reduceOrStatement(assertion); } - if (this.statement instanceof ConditionalStatement){ + if (this.statement instanceof ConditionalStatement) { return this.reduceConditionalStatement(assertion); } - if (this.statement instanceof BiconditionalStatement){ + if (this.statement instanceof BiconditionalStatement) { return this.reduceBiconditionalStatement(assertion); } return this.statement; From 91855d0c8f01992937d3dfec854cc006e3b3e122 Mon Sep 17 00:00:00 2001 From: mduboef <mduboef@gmail.com> Date: Thu, 6 Apr 2023 15:58:17 -0400 Subject: [PATCH 11/54] add Modes to nav bar --- package-lock.json | 2249 ++++++++++++++----------------------------- package.json | 6 +- src/client/index.ts | 8 + views/index.pug | 5 + 4 files changed, 731 insertions(+), 1537 deletions(-) diff --git a/package-lock.json b/package-lock.json index 08b6571..691036e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -14,13 +14,13 @@ "connect-pg-simple": "^7.0.0", "csurf": "^1.11.0", "dotenv": "^8.2.0", - "express": "^5.0.0-alpha.8", + "express": "^4.18.2", "express-session": "^1.17.2", "hotkeys-js": "^3.8.3", "http-errors": "^1.8.0", "morgan": "^1.10.0", "nodemailer": "^6.7.2", - "passport": "^0.5.0", + "passport": "^0.6.0", "passport-local": "^1.0.0", "pg": "^8.7.1", "pug": "^3.0.0", @@ -48,7 +48,7 @@ "@types/pg": "^8.6.1", "@types/pug": "^2.0.4", "@types/tmp": "^0.2.2", - "gts": "^3.1.0", + "gts": "^3.1.1", "jest": "^27.4.5", "json-schema-to-typescript": "^10.1.5", "nodemon": "^2.0.13", @@ -1177,29 +1177,56 @@ "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" } }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz", + "integrity": "sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==", + "dependencies": { + "@jridgewell/set-array": "^1.0.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.9" + }, + "engines": { + "node": ">=6.0.0" + } + }, "node_modules/@jridgewell/resolve-uri": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.0.5.tgz", - "integrity": "sha512-VPeQ7+wH0itvQxnG+lIzWgkysKIr3L9sslimFW55rHMdGu/qCQ5z5h9zq4gI8uBtqkpHhsF4Z/OwExufUCThew==", - "dev": true, + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz", + "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/set-array": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", + "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==", "engines": { "node": ">=6.0.0" } }, + "node_modules/@jridgewell/source-map": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.2.tgz", + "integrity": "sha512-m7O9o2uR8k2ObDysZYzdfhb08VuEml5oWGiosa1VdaPZ/A6QyPkAJuwN0Q1lhULOf6B7MtQmHENS743hWtCrgw==", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.0", + "@jridgewell/trace-mapping": "^0.3.9" + } + }, "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.4.11", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.11.tgz", - "integrity": "sha512-Fg32GrJo61m+VqYSdRSjRXMjQ06j8YIYfcTqndLYVAaHmroZHLJZCydsWBOTDqXS2v+mjxohBWEMfg97GXmYQg==", - "dev": true + "version": "1.4.14", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz", + "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==" }, "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.4", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.4.tgz", - "integrity": "sha512-vFv9ttIedivx0ux3QSjhgtCVjPZd5l46ZOMDSCwnH1yUO2e964gO8LZGyv2QkqcgR6TnBU1v+1IFqmeoG+0UJQ==", - "dev": true, + "version": "0.3.17", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.17.tgz", + "integrity": "sha512-MCNzAp77qzKca9+W/+I0+sEpaUnZoeasnghNeVc41VZCEKaCH73Vq3BZZ/SzWIgrqE4H4ceI+p+b6C0mHf9T4g==", "dependencies": { - "@jridgewell/resolve-uri": "^3.0.3", - "@jridgewell/sourcemap-codec": "^1.4.10" + "@jridgewell/resolve-uri": "3.1.0", + "@jridgewell/sourcemap-codec": "1.4.14" } }, "node_modules/@jsdevtools/ono": { @@ -1243,15 +1270,6 @@ "node": ">= 8" } }, - "node_modules/@sindresorhus/is": { - "version": "0.14.0", - "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-0.14.0.tgz", - "integrity": "sha512-9NET910DNaIPngYnLLPeg+Ogzqsi9uM4mSboU5y6p8S5DzMTVEsJZrawi+BoDNUVBa2DhJqQYUFvMDfgU062LQ==", - "dev": true, - "engines": { - "node": ">=6" - } - }, "node_modules/@sinonjs/commons": { "version": "1.8.3", "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.3.tgz", @@ -1270,18 +1288,6 @@ "@sinonjs/commons": "^1.7.0" } }, - "node_modules/@szmarczak/http-timer": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-1.1.2.tgz", - "integrity": "sha512-XIB2XbzHTN6ieIjfIMV9hlVcfPU26s2vafYWQcZHWXHOxiaRZYEDKEwdl129Zyg50+foYV2jCgtrqSA6qNuNSA==", - "dev": true, - "dependencies": { - "defer-to-connect": "^1.0.1" - }, - "engines": { - "node": ">=6" - } - }, "node_modules/@tootallnate/once": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz", @@ -2304,15 +2310,6 @@ } } }, - "node_modules/ansi-align": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-3.0.1.tgz", - "integrity": "sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w==", - "dev": true, - "dependencies": { - "string-width": "^4.1.0" - } - }, "node_modules/ansi-colors": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", @@ -2408,9 +2405,9 @@ } }, "node_modules/array-flatten": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-3.0.0.tgz", - "integrity": "sha512-zPMVc3ZYlGLNk4mpK1NzP2wg0ml9t7fUgDsayR5Y5rSzxQilzR9FGu/EH2jQOcKSAeAfWeylyW8juy3OkWRvNA==" + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==" }, "node_modules/array-union": { "version": "2.1.0", @@ -2603,65 +2600,68 @@ } }, "node_modules/body-parser": { - "version": "2.0.0-beta.1", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-2.0.0-beta.1.tgz", - "integrity": "sha512-I1v2bt2OdYqtmk8nEFZuEf+9Opb30DphYwTPDbgg/OorSAoJOuTpWyDrZaSWQw7FdoevbBRCP2+9z/halXSWcA==", + "version": "1.20.1", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.1.tgz", + "integrity": "sha512-jWi7abTbYwajOytWCQc37VulmWiRae5RyTpaCyDcS5/lMdtwSz5lOpDE67srw/HYe35f1z3fDQw+3txg7gNtWw==", "dependencies": { - "bytes": "3.1.1", + "bytes": "3.1.2", "content-type": "~1.0.4", "debug": "2.6.9", - "depd": "~1.1.2", - "http-errors": "1.8.1", + "depd": "2.0.0", + "destroy": "1.2.0", + "http-errors": "2.0.0", "iconv-lite": "0.4.24", - "on-finished": "~2.3.0", - "qs": "6.9.6", - "raw-body": "2.4.2", - "type-is": "~1.6.18" + "on-finished": "2.4.1", + "qs": "6.11.0", + "raw-body": "2.5.1", + "type-is": "~1.6.18", + "unpipe": "1.0.0" }, "engines": { - "node": ">= 0.10" + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" } }, - "node_modules/body-parser/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dependencies": { - "ms": "2.0.0" + "node_modules/body-parser/node_modules/depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "engines": { + "node": ">= 0.8" } }, - "node_modules/boxen": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/boxen/-/boxen-5.1.2.tgz", - "integrity": "sha512-9gYgQKXx+1nP8mP7CzFyaUARhg7D3n1dF/FnErWmu9l6JvGpNUN278h0aSb+QjoiKSWG+iZ3uHrcqk0qrY9RQQ==", - "dev": true, + "node_modules/body-parser/node_modules/http-errors": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", + "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", "dependencies": { - "ansi-align": "^3.0.0", - "camelcase": "^6.2.0", - "chalk": "^4.1.0", - "cli-boxes": "^2.2.1", - "string-width": "^4.2.2", - "type-fest": "^0.20.2", - "widest-line": "^3.1.0", - "wrap-ansi": "^7.0.0" + "depd": "2.0.0", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "toidentifier": "1.0.1" }, "engines": { - "node": ">=10" + "node": ">= 0.8" + } + }, + "node_modules/body-parser/node_modules/on-finished": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", + "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", + "dependencies": { + "ee-first": "1.1.1" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "engines": { + "node": ">= 0.8" } }, - "node_modules/boxen/node_modules/camelcase": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", - "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", - "dev": true, + "node_modules/body-parser/node_modules/statuses": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">= 0.8" } }, "node_modules/brace-expansion": { @@ -2754,55 +2754,13 @@ } }, "node_modules/bytes": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.1.tgz", - "integrity": "sha512-dWe4nWO/ruEOY7HkUJ5gFt1DCFV9zPRoJr8pV0/ASQermOZjtq8jMjOprC0Kd10GLN+l7xaUPvxzJFWtxGu8Fg==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", "engines": { "node": ">= 0.8" } }, - "node_modules/cacheable-request": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-6.1.0.tgz", - "integrity": "sha512-Oj3cAGPCqOZX7Rz64Uny2GYAZNliQSqfbePrgAQ1wKAihYmCUnraBtJtKcGR4xz7wF+LoJC+ssFZvv5BgF9Igg==", - "dev": true, - "dependencies": { - "clone-response": "^1.0.2", - "get-stream": "^5.1.0", - "http-cache-semantics": "^4.0.0", - "keyv": "^3.0.0", - "lowercase-keys": "^2.0.0", - "normalize-url": "^4.1.0", - "responselike": "^1.0.2" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/cacheable-request/node_modules/get-stream": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", - "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", - "dev": true, - "dependencies": { - "pump": "^3.0.0" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/cacheable-request/node_modules/lowercase-keys": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz", - "integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==", - "dev": true, - "engines": { - "node": ">=8" - } - }, "node_modules/call-bind": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", @@ -3003,18 +2961,6 @@ "integrity": "sha512-cOU9usZw8/dXIXKtwa8pM0OTJQuJkxMN6w30csNRUerHfeQ5R6U3kkU/FtJeIf3M202OHfY2U8ccInBG7/xogA==", "dev": true }, - "node_modules/cli-boxes": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-2.2.1.tgz", - "integrity": "sha512-y4coMcylgSCdVinjiDBuR8PCC2bLjyGTwEmPb9NHR/QaNU6EUOXcTY/s6VjGMD6ENSEaeQYHCY0GNGS5jfMwPw==", - "dev": true, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/cli-color": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/cli-color/-/cli-color-2.0.1.tgz", @@ -3077,15 +3023,6 @@ "node": ">=6" } }, - "node_modules/clone-response": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.2.tgz", - "integrity": "sha1-0dyXOSAxTfZ/vrlCI7TuNQI56Ws=", - "dev": true, - "dependencies": { - "mimic-response": "^1.0.0" - } - }, "node_modules/co": { "version": "4.6.0", "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", @@ -3195,23 +3132,6 @@ "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" }, - "node_modules/configstore": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/configstore/-/configstore-5.0.1.tgz", - "integrity": "sha512-aMKprgk5YhBNyH25hj8wGt2+D52Sw1DRRIzqBwLp2Ya9mFmY8KPvvtvmna8SxVR9JMZ4kzMD68N22vlaRpkeFA==", - "dev": true, - "dependencies": { - "dot-prop": "^5.2.0", - "graceful-fs": "^4.1.2", - "make-dir": "^3.0.0", - "unique-string": "^2.0.0", - "write-file-atomic": "^3.0.0", - "xdg-basedir": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/connect-pg-simple": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/connect-pg-simple/-/connect-pg-simple-7.0.0.tgz", @@ -3245,9 +3165,9 @@ } }, "node_modules/content-type": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", - "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==", + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", + "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", "engines": { "node": ">= 0.6" } @@ -3332,15 +3252,6 @@ "node": ">= 8" } }, - "node_modules/crypto-random-string": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-2.0.0.tgz", - "integrity": "sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA==", - "dev": true, - "engines": { - "node": ">=8" - } - }, "node_modules/csrf": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/csrf/-/csrf-3.1.0.tgz", @@ -3450,9 +3361,9 @@ } }, "node_modules/debug": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", "dependencies": { "ms": "2.0.0" } @@ -3494,33 +3405,12 @@ "integrity": "sha512-V0pfhfr8suzyPGOx3nmq4aHqabehUZn6Ch9kyFpV79TGDTWFmHqUqXdabR7QHqxzrYolF4+tVmJhUG4OURg5dQ==", "dev": true }, - "node_modules/decompress-response": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-3.3.0.tgz", - "integrity": "sha1-gKTdMjdIOEv6JICDYirt7Jgq3/M=", - "dev": true, - "dependencies": { - "mimic-response": "^1.0.0" - }, - "engines": { - "node": ">=4" - } - }, "node_modules/dedent": { "version": "0.7.0", "resolved": "https://registry.npmjs.org/dedent/-/dedent-0.7.0.tgz", "integrity": "sha1-JJXduvbrh0q7Dhvp3yLS5aVEMmw=", "dev": true }, - "node_modules/deep-extend": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", - "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", - "dev": true, - "engines": { - "node": ">=4.0.0" - } - }, "node_modules/deep-is": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", @@ -3536,12 +3426,6 @@ "node": ">=0.10.0" } }, - "node_modules/defer-to-connect": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-1.1.3.tgz", - "integrity": "sha512-0ISdNousHvZT2EiFlZeZAHBUvSxmKswVCEf8hW7KWgG4a8MVEu/3Vb6uWYozkjylyCxe0JBIiRB1jV45S70WVQ==", - "dev": true - }, "node_modules/delayed-stream": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", @@ -3560,9 +3444,13 @@ } }, "node_modules/destroy": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", - "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=" + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", + "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } }, "node_modules/detect-newline": { "version": "3.1.0", @@ -3641,18 +3529,6 @@ "node": ">=8" } }, - "node_modules/dot-prop": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-5.3.0.tgz", - "integrity": "sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q==", - "dev": true, - "dependencies": { - "is-obj": "^2.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/dotenv": { "version": "8.6.0", "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-8.6.0.tgz", @@ -3661,12 +3537,6 @@ "node": ">=10" } }, - "node_modules/duplexer3": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.4.tgz", - "integrity": "sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI=", - "dev": true - }, "node_modules/ee-first": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", @@ -3712,20 +3582,11 @@ "node_modules/encodeurl": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", - "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=", + "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", "engines": { "node": ">= 0.8" } }, - "node_modules/end-of-stream": { - "version": "1.4.4", - "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", - "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", - "dev": true, - "dependencies": { - "once": "^1.4.0" - } - }, "node_modules/enhanced-resolve": { "version": "4.5.0", "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-4.5.0.tgz", @@ -3846,19 +3707,10 @@ "node": ">=6" } }, - "node_modules/escape-goat": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/escape-goat/-/escape-goat-2.1.1.tgz", - "integrity": "sha512-8/uIhbG12Csjy2JEW7D9pHbreaVaS/OpN3ycnyvElTdwM5n6GY6W6e2IPemfvGZeUMqZ9A/3GqIZMgKnBhAw/Q==", - "dev": true, - "engines": { - "node": ">=8" - } - }, "node_modules/escape-html": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", - "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=" + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==" }, "node_modules/escape-string-regexp": { "version": "4.0.0", @@ -4358,7 +4210,7 @@ "node_modules/etag": { "version": "1.8.1", "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", - "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=", + "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", "engines": { "node": ">= 0.6" } @@ -4437,45 +4289,44 @@ } }, "node_modules/express": { - "version": "5.0.0-beta.1", - "resolved": "https://registry.npmjs.org/express/-/express-5.0.0-beta.1.tgz", - "integrity": "sha512-KPtBrlZoQu2Ps0Ce/Imqtq73AB0KBJ8Gx59yZQ3pmDJU2/LhcoZETo03oSgtTQufbcLXt/WBITk/jMjl/WMyrQ==", + "version": "4.18.2", + "resolved": "https://registry.npmjs.org/express/-/express-4.18.2.tgz", + "integrity": "sha512-5/PsL6iGPdfQ/lKM1UuielYgv3BUoJfz1aUwU9vHZ+J7gyvwdQXFEBIEIaxeGf0GIcreATNyBExtalisDbuMqQ==", "dependencies": { - "accepts": "~1.3.7", - "array-flatten": "3.0.0", - "body-parser": "2.0.0-beta.1", + "accepts": "~1.3.8", + "array-flatten": "1.1.1", + "body-parser": "1.20.1", "content-disposition": "0.5.4", "content-type": "~1.0.4", - "cookie": "0.4.1", + "cookie": "0.5.0", "cookie-signature": "1.0.6", - "debug": "3.1.0", - "depd": "~1.1.2", + "debug": "2.6.9", + "depd": "2.0.0", "encodeurl": "~1.0.2", "escape-html": "~1.0.3", "etag": "~1.8.1", - "finalhandler": "~1.1.2", + "finalhandler": "1.2.0", "fresh": "0.5.2", + "http-errors": "2.0.0", "merge-descriptors": "1.0.1", "methods": "~1.1.2", - "mime-types": "~2.1.34", - "on-finished": "~2.3.0", + "on-finished": "2.4.1", "parseurl": "~1.3.3", - "path-is-absolute": "1.0.1", + "path-to-regexp": "0.1.7", "proxy-addr": "~2.0.7", - "qs": "6.9.6", + "qs": "6.11.0", "range-parser": "~1.2.1", - "router": "2.0.0-beta.1", "safe-buffer": "5.2.1", - "send": "1.0.0-beta.1", - "serve-static": "2.0.0-beta.1", + "send": "0.18.0", + "serve-static": "1.15.0", "setprototypeof": "1.2.0", - "statuses": "~1.5.0", + "statuses": "2.0.1", "type-is": "~1.6.18", "utils-merge": "1.0.1", "vary": "~1.1.2" }, "engines": { - "node": ">= 4" + "node": ">= 0.10.0" } }, "node_modules/express-session": { @@ -4504,14 +4355,6 @@ "node": ">= 0.6" } }, - "node_modules/express-session/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dependencies": { - "ms": "2.0.0" - } - }, "node_modules/express-session/node_modules/depd": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", @@ -4521,13 +4364,55 @@ } }, "node_modules/express/node_modules/cookie": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.1.tgz", - "integrity": "sha512-ZwrFkGJxUR3EIoXtO+yVE69Eb7KlixbaeAWfBQB9vVsNn/o+Yw69gBWSSDK825hQNdN+wF8zELf3dFNl/kxkUA==", + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz", + "integrity": "sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==", "engines": { "node": ">= 0.6" } }, + "node_modules/express/node_modules/depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/express/node_modules/http-errors": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", + "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", + "dependencies": { + "depd": "2.0.0", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "toidentifier": "1.0.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/express/node_modules/on-finished": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", + "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/express/node_modules/statuses": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", + "engines": { + "node": ">= 0.8" + } + }, "node_modules/ext": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/ext/-/ext-1.6.0.tgz", @@ -4685,28 +4570,39 @@ } }, "node_modules/finalhandler": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz", - "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz", + "integrity": "sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==", "dependencies": { "debug": "2.6.9", "encodeurl": "~1.0.2", "escape-html": "~1.0.3", - "on-finished": "~2.3.0", + "on-finished": "2.4.1", "parseurl": "~1.3.3", - "statuses": "~1.5.0", + "statuses": "2.0.1", "unpipe": "~1.0.0" }, "engines": { "node": ">= 0.8" } }, - "node_modules/finalhandler/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "node_modules/finalhandler/node_modules/on-finished": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", + "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", "dependencies": { - "ms": "2.0.0" + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/finalhandler/node_modules/statuses": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", + "engines": { + "node": ">= 0.8" } }, "node_modules/find-up": { @@ -4779,7 +4675,7 @@ "node_modules/fresh": { "version": "0.5.2", "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", - "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=", + "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", "engines": { "node": ">= 0.6" } @@ -4929,21 +4825,6 @@ "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==" }, - "node_modules/global-dirs": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/global-dirs/-/global-dirs-3.0.0.tgz", - "integrity": "sha512-v8ho2DS5RiCjftj1nD9NmnfaOzTdud7RRnVd9kFNOjqZbISlx5DQ+OrTkywgd0dIt7oFCvKetZSHoHcP3sDdiA==", - "dev": true, - "dependencies": { - "ini": "2.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/globals": { "version": "13.13.0", "resolved": "https://registry.npmjs.org/globals/-/globals-13.13.0.tgz", @@ -4979,49 +4860,15 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/got": { - "version": "9.6.0", - "resolved": "https://registry.npmjs.org/got/-/got-9.6.0.tgz", - "integrity": "sha512-R7eWptXuGYxwijs0eV+v3o6+XH1IqVK8dJOEecQfTmkncw9AV4dcw/Dhxi8MdlqPthxxpZyizMzyg8RTmEsG+Q==", - "dev": true, - "dependencies": { - "@sindresorhus/is": "^0.14.0", - "@szmarczak/http-timer": "^1.1.2", - "cacheable-request": "^6.0.0", - "decompress-response": "^3.3.0", - "duplexer3": "^0.1.4", - "get-stream": "^4.1.0", - "lowercase-keys": "^1.0.1", - "mimic-response": "^1.0.1", - "p-cancelable": "^1.0.0", - "to-readable-stream": "^1.0.0", - "url-parse-lax": "^3.0.0" - }, - "engines": { - "node": ">=8.6" - } - }, - "node_modules/got/node_modules/get-stream": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", - "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", - "dev": true, - "dependencies": { - "pump": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, "node_modules/graceful-fs": { "version": "4.2.9", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.9.tgz", "integrity": "sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ==" }, "node_modules/gts": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/gts/-/gts-3.1.0.tgz", - "integrity": "sha512-Pbj3ob1VR1IRlEVEBNtKoQ1wHOa8cZz62KEojK8Fn/qeS2ClWI4gLNfhek3lD68aZSmUEg8TFb6AHXIwUMgyqQ==", + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/gts/-/gts-3.1.1.tgz", + "integrity": "sha512-Jw44aBbzMnd1vtZs7tZt3LMstKQukCBg7N4CKVGzviIQ45Cz5b9lxDJGXVKj/9ySuGv6TYEeijZJGbiiVcM27w==", "dev": true, "dependencies": { "@typescript-eslint/eslint-plugin": "^4.2.0", @@ -5038,7 +4885,6 @@ "ncp": "^2.0.0", "prettier": "^2.1.2", "rimraf": "^3.0.2", - "update-notifier": "^5.0.0", "write-file-atomic": "^3.0.3" }, "bin": { @@ -5104,15 +4950,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/has-yarn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/has-yarn/-/has-yarn-2.1.0.tgz", - "integrity": "sha512-UqBRqi4ju7T+TqGNdqAO0PaSVGsDGJUBQvk9eUWNGRY1CFGDzYhLWoM7JQEemnlvVcv/YEmc2wNW8BC24EnUsw==", - "dev": true, - "engines": { - "node": ">=8" - } - }, "node_modules/hosted-git-info": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-4.1.0.tgz", @@ -5148,12 +4985,6 @@ "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", "dev": true }, - "node_modules/http-cache-semantics": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz", - "integrity": "sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ==", - "dev": true - }, "node_modules/http-errors": { "version": "1.8.1", "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.8.1.tgz", @@ -5293,15 +5124,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/import-lazy": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/import-lazy/-/import-lazy-2.1.0.tgz", - "integrity": "sha1-BWmOPUXIjo1+nZLLBYTnfwlvPkM=", - "dev": true, - "engines": { - "node": ">=4" - } - }, "node_modules/import-local": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.1.0.tgz", @@ -5353,15 +5175,6 @@ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" }, - "node_modules/ini": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ini/-/ini-2.0.0.tgz", - "integrity": "sha512-7PnF4oN3CvZF23ADhA5wRaYEQpJ8qygSkbtTXWBeXWXmEVRXK+1ITciHWwHhsjv1TmW0MgacIv6hEi5pX5NQdA==", - "dev": true, - "engines": { - "node": ">=10" - } - }, "node_modules/inquirer": { "version": "7.3.3", "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-7.3.3.tgz", @@ -5421,24 +5234,6 @@ "node": ">=8" } }, - "node_modules/is-ci": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-2.0.0.tgz", - "integrity": "sha512-YfJT7rkpQB0updsdHLGWrvhBJfcfzNNawYDNIyQXJz0IViGf75O8EBPKSdvw2rF+LGCsX4FZ8tcr3b19LcZq4w==", - "dev": true, - "dependencies": { - "ci-info": "^2.0.0" - }, - "bin": { - "is-ci": "bin.js" - } - }, - "node_modules/is-ci/node_modules/ci-info": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz", - "integrity": "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==", - "dev": true - }, "node_modules/is-core-module": { "version": "2.8.1", "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.8.1.tgz", @@ -5498,34 +5293,6 @@ "node": ">=0.10.0" } }, - "node_modules/is-installed-globally": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/is-installed-globally/-/is-installed-globally-0.4.0.tgz", - "integrity": "sha512-iwGqO3J21aaSkC7jWnHP/difazwS7SFeIqxv6wEtLU8Y5KlzFTjyqcSIT0d8s4+dDhKytsk9PJZ2BkS5eZwQRQ==", - "dev": true, - "dependencies": { - "global-dirs": "^3.0.0", - "is-path-inside": "^3.0.2" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/is-npm": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/is-npm/-/is-npm-5.0.0.tgz", - "integrity": "sha512-WW/rQLOazUq+ST/bCAVBp/2oMERWLsR7OrKyt052dNDk4DHcDE0/7QSXITlmi+VBcV13DfIbysG3tZJm5RfdBA==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/is-number": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", @@ -5535,24 +5302,6 @@ "node": ">=0.12.0" } }, - "node_modules/is-obj": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz", - "integrity": "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/is-path-inside": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", - "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, "node_modules/is-plain-obj": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", @@ -5617,12 +5366,6 @@ "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=", "dev": true }, - "node_modules/is-yarn-global": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/is-yarn-global/-/is-yarn-global-0.3.0.tgz", - "integrity": "sha512-VjSeb/lHmkoyd8ryPVIKvOCn4D1koMqY+vqyjjUfc3xyKtP4dYOxM44sZrnqQSzSds3xyOrUTLTC9LVCVgLngw==", - "dev": true - }, "node_modules/isarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", @@ -6459,22 +6202,10 @@ "node": ">=4" } }, - "node_modules/json-buffer": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.0.tgz", - "integrity": "sha1-Wx85evx11ne96Lz8Dkfh+aPZqJg=", - "dev": true - }, - "node_modules/json-parse-better-errors": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", - "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==" - }, "node_modules/json-parse-even-better-errors": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", - "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", - "dev": true + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==" }, "node_modules/json-schema-ref-parser": { "version": "9.0.9", @@ -6535,9 +6266,9 @@ "dev": true }, "node_modules/json5": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.1.tgz", - "integrity": "sha512-1hqLFMSrGHRHxav9q9gNjJ5EXznIxGVO09xQRrwplcS8qs28pZ8s8hupZAmqDwZUmVZ2Qb2jnyPOWcDH8m8dlA==", + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", "dev": true, "bin": { "json5": "lib/cli.js" @@ -6555,15 +6286,6 @@ "promise": "^7.0.1" } }, - "node_modules/keyv": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/keyv/-/keyv-3.1.0.tgz", - "integrity": "sha512-9ykJ/46SN/9KPM/sichzQ7OvXyGDYKGTaDlKMGCAlg2UK8KRy4jb0d8sFc+0Tt0YYnThq8X2RZgCg74RPxgcVA==", - "dev": true, - "dependencies": { - "json-buffer": "3.0.0" - } - }, "node_modules/kind-of": { "version": "6.0.3", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", @@ -6587,18 +6309,6 @@ "resolved": "https://registry.npmjs.org/kuler/-/kuler-2.0.0.tgz", "integrity": "sha512-Xq9nH7KlWZmXAtodXDDRE7vs6DU1gTU8zYDHDiWLSip45Egwq3plLHzPn27NgvzL2r1LMPC1vdqh98sQxtqj4A==" }, - "node_modules/latest-version": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/latest-version/-/latest-version-5.1.0.tgz", - "integrity": "sha512-weT+r0kTkRQdCdYCNtkMwWXQTMEswKrFBkm4ckQOMVhhqhIMI1UT2hMj+1iigIhgSZm5gTmrRXBNoGUgaTY1xA==", - "dev": true, - "dependencies": { - "package-json": "^6.3.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/leven": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", @@ -6636,9 +6346,9 @@ } }, "node_modules/loader-utils": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.2.tgz", - "integrity": "sha512-TM57VeHptv569d/GKh6TAYdzKblwDNiumOdkFnejjD0XwTH87K90w3O7AiJRqdQoXygvi1VQTJTLGhJl7WqA7A==", + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.4.tgz", + "integrity": "sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==", "dev": true, "dependencies": { "big.js": "^5.2.2", @@ -6702,15 +6412,6 @@ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" }, - "node_modules/lowercase-keys": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz", - "integrity": "sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/lru-cache": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", @@ -6794,7 +6495,7 @@ "node_modules/media-typer": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", - "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=", + "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", "engines": { "node": ">= 0.6" } @@ -6888,7 +6589,7 @@ "node_modules/methods": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", - "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=", + "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", "engines": { "node": ">= 0.6" } @@ -6906,6 +6607,17 @@ "node": ">=8.6" } }, + "node_modules/mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4" + } + }, "node_modules/mime-db": { "version": "1.52.0", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", @@ -6934,15 +6646,6 @@ "node": ">=6" } }, - "node_modules/mimic-response": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz", - "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==", - "dev": true, - "engines": { - "node": ">=4" - } - }, "node_modules/min-indent": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz", @@ -7010,14 +6713,6 @@ "node": ">= 0.8.0" } }, - "node_modules/morgan/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dependencies": { - "ms": "2.0.0" - } - }, "node_modules/morgan/node_modules/depd": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", @@ -7113,22 +6808,21 @@ } }, "node_modules/nodemon": { - "version": "2.0.15", - "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-2.0.15.tgz", - "integrity": "sha512-gdHMNx47Gw7b3kWxJV64NI+Q5nfl0y5DgDbiVtShiwa7Z0IZ07Ll4RLFo6AjrhzMtoEZn5PDE3/c2AbVsiCkpA==", + "version": "2.0.22", + "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-2.0.22.tgz", + "integrity": "sha512-B8YqaKMmyuCO7BowF1Z1/mkPqLk6cs/l63Ojtd6otKjMx47Dq1utxfRxcavH1I7VSaL8n5BUaoutadnsX3AAVQ==", "dev": true, - "hasInstallScript": true, "dependencies": { "chokidar": "^3.5.2", "debug": "^3.2.7", "ignore-by-default": "^1.0.1", - "minimatch": "^3.0.4", + "minimatch": "^3.1.2", "pstree.remy": "^1.1.8", "semver": "^5.7.1", + "simple-update-notifier": "^1.0.7", "supports-color": "^5.5.0", "touch": "^3.1.0", - "undefsafe": "^2.0.5", - "update-notifier": "^5.1.0" + "undefsafe": "^2.0.5" }, "bin": { "nodemon": "bin/nodemon.js" @@ -7225,15 +6919,6 @@ "node": ">=0.10.0" } }, - "node_modules/normalize-url": { - "version": "4.5.1", - "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-4.5.1.tgz", - "integrity": "sha512-9UZCFRHQdNrfTpGg8+1INIg93B6zE0aXMVFkw1WFwvO4SlZywU6aLg5Of0Ap/PgcbSw4LNxvMWXMeugwMCX0AA==", - "dev": true, - "engines": { - "node": ">=8" - } - }, "node_modules/npm-run-path": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", @@ -7260,6 +6945,14 @@ "node": ">=0.10.0" } }, + "node_modules/object-inspect": { + "version": "1.12.3", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.3.tgz", + "integrity": "sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/on-finished": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", @@ -7336,15 +7029,6 @@ "node": ">=0.10.0" } }, - "node_modules/p-cancelable": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-1.1.0.tgz", - "integrity": "sha512-s73XxOZ4zpt1edZYZzvhqFa6uvQc1vwUa0K0BdtIZgQMAJj9IbebH+JkgKZc9h+B05PKHLOTl4ajG1BmNrVZlw==", - "dev": true, - "engines": { - "node": ">=6" - } - }, "node_modules/p-limit": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", @@ -7381,30 +7065,6 @@ "node": ">=6" } }, - "node_modules/package-json": { - "version": "6.5.0", - "resolved": "https://registry.npmjs.org/package-json/-/package-json-6.5.0.tgz", - "integrity": "sha512-k3bdm2n25tkyxcjSKzB5x8kfVxlMdgsbPr0GkZcwHsLpba6cBjqCt1KlcChKEvxHIcTB1FVMuwoijZ26xex5MQ==", - "dev": true, - "dependencies": { - "got": "^9.6.0", - "registry-auth-token": "^4.0.0", - "registry-url": "^5.0.0", - "semver": "^6.2.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/package-json/node_modules/semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true, - "bin": { - "semver": "bin/semver.js" - } - }, "node_modules/packet-reader": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/packet-reader/-/packet-reader-1.0.0.tgz", @@ -7455,12 +7115,13 @@ } }, "node_modules/passport": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/passport/-/passport-0.5.2.tgz", - "integrity": "sha512-w9n/Ot5I7orGD4y+7V3EFJCQEznE5RxHamUxcqLT2QoJY0f2JdN8GyHonYFvN0Vz+L6lUJfVhrk2aZz2LbuREw==", + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/passport/-/passport-0.6.0.tgz", + "integrity": "sha512-0fe+p3ZnrWRW74fe8+SvCyf4a3Pb2/h7gFkQ8yTJpAO50gDzlfjZUZTO1k5Eg9kUct22OxHLqDZoKUWRHOh9ug==", "dependencies": { "passport-strategy": "1.x.x", - "pause": "0.0.1" + "pause": "0.0.1", + "utils-merge": "^1.0.1" }, "engines": { "node": ">= 0.4.0" @@ -7521,9 +7182,9 @@ "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==" }, "node_modules/path-to-regexp": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-3.2.0.tgz", - "integrity": "sha512-jczvQbCUS7XmS7o+y1aEO9OBVFeZBQ1MDSEqmO7xSoPgOPoowY/SxLpZ6Vh97/8qHZOteiCKb7gkG9gA2ZUxJA==" + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", + "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==" }, "node_modules/path-type": { "version": "4.0.0", @@ -7718,15 +7379,6 @@ "node": ">= 0.8.0" } }, - "node_modules/prepend-http": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-2.0.0.tgz", - "integrity": "sha1-6SQ0v6XqjBn0HN/UAddBo8gZ2Jc=", - "dev": true, - "engines": { - "node": ">=4" - } - }, "node_modules/prettier": { "version": "2.6.0", "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.6.0.tgz", @@ -7969,16 +7621,6 @@ "resolved": "https://registry.npmjs.org/pug-walk/-/pug-walk-2.0.0.tgz", "integrity": "sha512-yYELe9Q5q9IQhuvqsZNwA5hfPkMJ8u92bQLIMcsMxf/VADjNtEYptU+inlufAFYcWdHlwNfZOEnOOQrZrcyJCQ==" }, - "node_modules/pump": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", - "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", - "dev": true, - "dependencies": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" - } - }, "node_modules/punycode": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", @@ -7987,22 +7629,13 @@ "node": ">=6" } }, - "node_modules/pupa": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/pupa/-/pupa-2.1.1.tgz", - "integrity": "sha512-l1jNAspIBSFqbT+y+5FosojNpVpF94nlI+wDUpqP9enwOTfHx9f0gh5nB96vl+6yTpsJsypeNrwfzPrKuHB41A==", - "dev": true, + "node_modules/qs": { + "version": "6.11.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", + "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==", "dependencies": { - "escape-goat": "^2.0.0" + "side-channel": "^1.0.4" }, - "engines": { - "node": ">=8" - } - }, - "node_modules/qs": { - "version": "6.9.6", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.9.6.tgz", - "integrity": "sha512-TIRk4aqYLNoJUbd+g2lEdz5kLWIuTMRagAXxl78Q0RiVjAOugHmeKNGdd3cwo/ktpf9aL9epCfFqWDEKysUlLQ==", "engines": { "node": ">=0.6" }, @@ -8064,12 +7697,12 @@ } }, "node_modules/raw-body": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.2.tgz", - "integrity": "sha512-RPMAFUJP19WIet/99ngh6Iv8fzAbqum4Li7AD6DtGaW2RpMB/11xDoalPiJMTbu6I3hkbMVkATvZrqb9EEqeeQ==", + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.1.tgz", + "integrity": "sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==", "dependencies": { - "bytes": "3.1.1", - "http-errors": "1.8.1", + "bytes": "3.1.2", + "http-errors": "2.0.0", "iconv-lite": "0.4.24", "unpipe": "1.0.0" }, @@ -8077,34 +7710,35 @@ "node": ">= 0.8" } }, - "node_modules/rc": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", - "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", - "dev": true, + "node_modules/raw-body/node_modules/depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/raw-body/node_modules/http-errors": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", + "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", "dependencies": { - "deep-extend": "^0.6.0", - "ini": "~1.3.0", - "minimist": "^1.2.0", - "strip-json-comments": "~2.0.1" + "depd": "2.0.0", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "toidentifier": "1.0.1" }, - "bin": { - "rc": "cli.js" + "engines": { + "node": ">= 0.8" } }, - "node_modules/rc/node_modules/ini": { - "version": "1.3.8", - "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", - "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", - "dev": true - }, - "node_modules/rc/node_modules/strip-json-comments": { + "node_modules/raw-body/node_modules/statuses": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", - "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", - "dev": true, + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", "engines": { - "node": ">=0.10.0" + "node": ">= 0.8" } }, "node_modules/react-is": { @@ -8260,30 +7894,6 @@ "url": "https://github.com/sponsors/mysticatea" } }, - "node_modules/registry-auth-token": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-4.2.1.tgz", - "integrity": "sha512-6gkSb4U6aWJB4SF2ZvLb76yCBjcvufXBqvvEx1HbmKPkutswjW1xNVRY0+daljIYRbogN7O0etYSlbiaEQyMyw==", - "dev": true, - "dependencies": { - "rc": "^1.2.8" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/registry-url": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/registry-url/-/registry-url-5.1.0.tgz", - "integrity": "sha512-8acYXXTI0AkQv6RAOjE3vOaIXZkT9wo4LOFbBKYQEEnnMNBpKqdUrI6S4NT0KPIo/WVvJ5tE/X5LF/TQUf0ekw==", - "dev": true, - "dependencies": { - "rc": "^1.2.8" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/require-directory": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", @@ -8356,15 +7966,6 @@ "node": ">=10" } }, - "node_modules/responselike": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/responselike/-/responselike-1.0.2.tgz", - "integrity": "sha1-kYcg7ztjHFZCvgaPFa3lpG9Loec=", - "dev": true, - "dependencies": { - "lowercase-keys": "^1.0.0" - } - }, "node_modules/restore-cursor": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", @@ -8407,22 +8008,6 @@ "resolved": "https://registry.npmjs.org/rndm/-/rndm-1.2.0.tgz", "integrity": "sha1-8z/pz7Urv9UgqhgyO8ZdsRCht2w=" }, - "node_modules/router": { - "version": "2.0.0-beta.1", - "resolved": "https://registry.npmjs.org/router/-/router-2.0.0-beta.1.tgz", - "integrity": "sha512-GLoYgkhAGAiwVda5nt6Qd4+5RAPuQ4WIYLlZ+mxfYICI+22gnIB3eCfmhgV8+uJNPS1/39DOYi/vdrrz0/ouKA==", - "dependencies": { - "array-flatten": "3.0.0", - "methods": "~1.1.2", - "parseurl": "~1.3.3", - "path-to-regexp": "3.2.0", - "setprototypeof": "1.2.0", - "utils-merge": "1.0.1" - }, - "engines": { - "node": ">= 0.10" - } - }, "node_modules/run-async": { "version": "2.4.1", "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.4.1.tgz", @@ -8571,53 +8156,75 @@ "node": ">=10" } }, - "node_modules/semver-diff": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/semver-diff/-/semver-diff-3.1.1.tgz", - "integrity": "sha512-GX0Ix/CJcHyB8c4ykpHGIAvLyOwOobtM/8d+TQkAd81/bEjgPHrfba41Vpesr7jX/t8Uh+R3EX9eAS5be+jQYg==", - "dev": true, - "dependencies": { - "semver": "^6.3.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/semver-diff/node_modules/semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true, - "bin": { - "semver": "bin/semver.js" - } - }, "node_modules/send": { - "version": "1.0.0-beta.1", - "resolved": "https://registry.npmjs.org/send/-/send-1.0.0-beta.1.tgz", - "integrity": "sha512-OKTRokcl/oo34O8+6aUpj8Jf2Bjw2D0tZzmX0/RvyfVC9ZOZW+HPAWAlhS817IsRaCnzYX1z++h2kHFr2/KNRg==", + "version": "0.18.0", + "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz", + "integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==", "dependencies": { - "debug": "3.1.0", - "destroy": "~1.0.4", + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", "encodeurl": "~1.0.2", "escape-html": "~1.0.3", "etag": "~1.8.1", "fresh": "0.5.2", - "http-errors": "1.8.1", - "mime-types": "~2.1.34", + "http-errors": "2.0.0", + "mime": "1.6.0", "ms": "2.1.3", - "on-finished": "~2.3.0", + "on-finished": "2.4.1", "range-parser": "~1.2.1", - "statuses": "~1.5.0" + "statuses": "2.0.1" }, "engines": { - "node": ">= 0.10" + "node": ">= 0.8.0" + } + }, + "node_modules/send/node_modules/depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/send/node_modules/http-errors": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", + "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", + "dependencies": { + "depd": "2.0.0", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "toidentifier": "1.0.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/send/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + }, + "node_modules/send/node_modules/on-finished": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", + "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" } }, - "node_modules/send/node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + "node_modules/send/node_modules/statuses": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", + "engines": { + "node": ">= 0.8" + } }, "node_modules/serialize-javascript": { "version": "6.0.0", @@ -8628,17 +8235,17 @@ } }, "node_modules/serve-static": { - "version": "2.0.0-beta.1", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-2.0.0-beta.1.tgz", - "integrity": "sha512-DEJ9on/tQeFO2Omj7ovT02lCp1YgP4Kb8W2lv2o/4keTFAbgc8HtH3yPd47++2wv9lvQeqiA7FHFDe5+8c4XpA==", + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz", + "integrity": "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==", "dependencies": { "encodeurl": "~1.0.2", "escape-html": "~1.0.3", "parseurl": "~1.3.3", - "send": "1.0.0-beta.1" + "send": "0.18.0" }, "engines": { - "node": ">= 0.10" + "node": ">= 0.8.0" } }, "node_modules/setprototypeof": { @@ -8679,6 +8286,19 @@ "node": ">=8" } }, + "node_modules/side-channel": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", + "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", + "dependencies": { + "call-bind": "^1.0.0", + "get-intrinsic": "^1.0.2", + "object-inspect": "^1.9.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/signal-exit": { "version": "3.0.7", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", @@ -8698,6 +8318,27 @@ "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz", "integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==" }, + "node_modules/simple-update-notifier": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/simple-update-notifier/-/simple-update-notifier-1.1.0.tgz", + "integrity": "sha512-VpsrsJSUcJEseSbMHkrsrAVSdvVS5I96Qo1QAQ4FxQ9wXFcB+pjj7FB7/us9+GcgfW4ziHtYMc1J0PLczb55mg==", + "dev": true, + "dependencies": { + "semver": "~7.0.0" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/simple-update-notifier/node_modules/semver": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.0.0.tgz", + "integrity": "sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, "node_modules/sisteransi": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", @@ -9032,13 +8673,13 @@ } }, "node_modules/terser": { - "version": "5.12.1", - "resolved": "https://registry.npmjs.org/terser/-/terser-5.12.1.tgz", - "integrity": "sha512-NXbs+7nisos5E+yXwAD+y7zrcTkMqb0dEJxIGtSKPdCBzopf7ni4odPul2aechpV7EXNvOudYOX2bb5tln1jbQ==", + "version": "5.16.8", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.16.8.tgz", + "integrity": "sha512-QI5g1E/ef7d+PsDifb+a6nnVgC4F22Bg6T0xrBrz6iloVB4PUkkunp6V8nzoOOZJIzjWVdAGqCdlKlhLq/TbIA==", "dependencies": { + "@jridgewell/source-map": "^0.3.2", "acorn": "^8.5.0", "commander": "^2.20.0", - "source-map": "~0.7.2", "source-map-support": "~0.5.20" }, "bin": { @@ -9092,14 +8733,6 @@ "node": ">=0.4.0" } }, - "node_modules/terser/node_modules/source-map": { - "version": "0.7.3", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz", - "integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==", - "engines": { - "node": ">= 8" - } - }, "node_modules/test-exclude": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", @@ -9193,15 +8826,6 @@ "node": ">=4" } }, - "node_modules/to-readable-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/to-readable-stream/-/to-readable-stream-1.0.0.tgz", - "integrity": "sha512-Iq25XBt6zD5npPhlLVXGFN3/gyR2/qODcKNNyTMd4vbm39HUaOiAM4PMq0eMVC/Tkxz+Zjdsc55g9yyz+Yq00Q==", - "dev": true, - "engines": { - "node": ">=6" - } - }, "node_modules/to-regex-range": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", @@ -9381,9 +9005,9 @@ } }, "node_modules/tsconfig-paths/node_modules/json5": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", - "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", + "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", "dev": true, "dependencies": { "minimist": "^1.2.0" @@ -9520,18 +9144,6 @@ "integrity": "sha512-WxONCrssBM8TSPRqN5EmsjVrsv4A8X12J4ArBiiayv3DyyG3ZlIg6yysuuSYdZsVz3TKcTg2fd//Ujd4CHV1iA==", "dev": true }, - "node_modules/unique-string": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-2.0.0.tgz", - "integrity": "sha512-uNaeirEPvpZWSgzwsPGtU2zVSTrn/8L5q/IexZmH0eH6SA73CmAA5U4GwORTxQAZs95TAXLNqeLoPPNO5gZfWg==", - "dev": true, - "dependencies": { - "crypto-random-string": "^2.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/universalify": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", @@ -9544,39 +9156,11 @@ "node_modules/unpipe": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", - "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=", + "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", "engines": { "node": ">= 0.8" } }, - "node_modules/update-notifier": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/update-notifier/-/update-notifier-5.1.0.tgz", - "integrity": "sha512-ItnICHbeMh9GqUy31hFPrD1kcuZ3rpxDZbf4KUDavXwS0bW5m7SLbDQpGX3UYr072cbrF5hFUs3r5tUsPwjfHw==", - "dev": true, - "dependencies": { - "boxen": "^5.0.0", - "chalk": "^4.1.0", - "configstore": "^5.0.1", - "has-yarn": "^2.1.0", - "import-lazy": "^2.1.0", - "is-ci": "^2.0.0", - "is-installed-globally": "^0.4.0", - "is-npm": "^5.0.0", - "is-yarn-global": "^0.3.0", - "latest-version": "^5.1.0", - "pupa": "^2.1.1", - "semver": "^7.3.4", - "semver-diff": "^3.1.1", - "xdg-basedir": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/yeoman/update-notifier?sponsor=1" - } - }, "node_modules/uri-js": { "version": "4.4.1", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", @@ -9585,18 +9169,6 @@ "punycode": "^2.1.0" } }, - "node_modules/url-parse-lax": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-3.0.0.tgz", - "integrity": "sha1-FrXK/Afb42dsGxmZF3gj1lA6yww=", - "dev": true, - "dependencies": { - "prepend-http": "^2.0.0" - }, - "engines": { - "node": ">=4" - } - }, "node_modules/util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", @@ -9605,7 +9177,7 @@ "node_modules/utils-merge": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", - "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=", + "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", "engines": { "node": ">= 0.4.0" } @@ -9719,9 +9291,9 @@ } }, "node_modules/watchpack": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.3.1.tgz", - "integrity": "sha512-x0t0JuydIo8qCNctdDrn1OzH/qDzk2+rdCOC3YzumZ42fiMqmQ7T3xQurykYMhYfHaPHTp4ZxAx2NfUo1K6QaA==", + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.0.tgz", + "integrity": "sha512-Lcvm7MGST/4fup+ifyKi2hjyIAwcdI4HRgtvTpIUxBRhB+RFtUh8XtDOxUfctVCnhVi+QQj49i91OyvzkJl6cg==", "dependencies": { "glob-to-regexp": "^0.4.1", "graceful-fs": "^4.1.2" @@ -9740,33 +9312,33 @@ } }, "node_modules/webpack": { - "version": "5.70.0", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.70.0.tgz", - "integrity": "sha512-ZMWWy8CeuTTjCxbeaQI21xSswseF2oNOwc70QSKNePvmxE7XW36i7vpBMYZFAUHPwQiEbNGCEYIOOlyRbdGmxw==", + "version": "5.78.0", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.78.0.tgz", + "integrity": "sha512-gT5DP72KInmE/3azEaQrISjTvLYlSM0j1Ezhht/KLVkrqtv10JoP/RXhwmX/frrutOPuSq3o5Vq0ehR/4Vmd1g==", "dependencies": { "@types/eslint-scope": "^3.7.3", "@types/estree": "^0.0.51", "@webassemblyjs/ast": "1.11.1", "@webassemblyjs/wasm-edit": "1.11.1", "@webassemblyjs/wasm-parser": "1.11.1", - "acorn": "^8.4.1", + "acorn": "^8.7.1", "acorn-import-assertions": "^1.7.6", "browserslist": "^4.14.5", "chrome-trace-event": "^1.0.2", - "enhanced-resolve": "^5.9.2", + "enhanced-resolve": "^5.10.0", "es-module-lexer": "^0.9.0", "eslint-scope": "5.1.1", "events": "^3.2.0", "glob-to-regexp": "^0.4.1", "graceful-fs": "^4.2.9", - "json-parse-better-errors": "^1.0.2", + "json-parse-even-better-errors": "^2.3.1", "loader-runner": "^4.2.0", "mime-types": "^2.1.27", "neo-async": "^2.6.2", "schema-utils": "^3.1.0", "tapable": "^2.1.1", "terser-webpack-plugin": "^5.1.3", - "watchpack": "^2.3.1", + "watchpack": "^2.4.0", "webpack-sources": "^3.2.3" }, "bin": { @@ -9859,9 +9431,9 @@ } }, "node_modules/webpack/node_modules/acorn": { - "version": "8.7.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.7.0.tgz", - "integrity": "sha512-V/LGr1APy+PXIwKebEWrkZPwoeoF+w1jiOBUmuxuiUIaOHtob8Qc9BTrYo7VuI5fR8tqsy+buA2WFooR5olqvQ==", + "version": "8.8.2", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.2.tgz", + "integrity": "sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw==", "bin": { "acorn": "bin/acorn" }, @@ -9878,9 +9450,9 @@ } }, "node_modules/webpack/node_modules/enhanced-resolve": { - "version": "5.9.2", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.9.2.tgz", - "integrity": "sha512-GIm3fQfwLJ8YZx2smuHpBKkXC1yOk+OBEmKckVyL0i/ea8mqDEykK3ld5dgH1QYPNyT/lIllxV2LULnxCHaHkA==", + "version": "5.12.0", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.12.0.tgz", + "integrity": "sha512-QHTXI/sZQmko1cbDoNAa3mJ5qhWUUNAq3vR0/YiD379fWQrcfuoX1+HW2S0MTt7XmoPLapdaDKUtelUSPic7hQ==", "dependencies": { "graceful-fs": "^4.2.4", "tapable": "^2.2.0" @@ -9941,18 +9513,6 @@ "node": ">= 8" } }, - "node_modules/widest-line": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-3.1.0.tgz", - "integrity": "sha512-NsmoXalsWVDMGupxZ5R08ka9flZjjiLvHVAWYOKtiKM8ujtZWr9cRffak+uSE48+Ob8ObalXpwyeUiyDD6QFgg==", - "dev": true, - "dependencies": { - "string-width": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/wildcard": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/wildcard/-/wildcard-2.0.0.tgz", @@ -10112,15 +9672,6 @@ } } }, - "node_modules/xdg-basedir": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/xdg-basedir/-/xdg-basedir-4.0.0.tgz", - "integrity": "sha512-PSNhEJDejZYV7h50BohL09Er9VaIefr2LMAf3OEmpCkjOi34eYyQYAXUTjEQtZJTKcF0E2UKTh+osDLsgNim9Q==", - "dev": true, - "engines": { - "node": ">=8" - } - }, "node_modules/xlsx": { "version": "0.17.5", "resolved": "https://registry.npmjs.org/xlsx/-/xlsx-0.17.5.tgz", @@ -11087,26 +10638,47 @@ "chalk": "^4.0.0" } }, + "@jridgewell/gen-mapping": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz", + "integrity": "sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==", + "requires": { + "@jridgewell/set-array": "^1.0.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.9" + } + }, "@jridgewell/resolve-uri": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.0.5.tgz", - "integrity": "sha512-VPeQ7+wH0itvQxnG+lIzWgkysKIr3L9sslimFW55rHMdGu/qCQ5z5h9zq4gI8uBtqkpHhsF4Z/OwExufUCThew==", - "dev": true + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz", + "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==" + }, + "@jridgewell/set-array": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", + "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==" + }, + "@jridgewell/source-map": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.2.tgz", + "integrity": "sha512-m7O9o2uR8k2ObDysZYzdfhb08VuEml5oWGiosa1VdaPZ/A6QyPkAJuwN0Q1lhULOf6B7MtQmHENS743hWtCrgw==", + "requires": { + "@jridgewell/gen-mapping": "^0.3.0", + "@jridgewell/trace-mapping": "^0.3.9" + } }, "@jridgewell/sourcemap-codec": { - "version": "1.4.11", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.11.tgz", - "integrity": "sha512-Fg32GrJo61m+VqYSdRSjRXMjQ06j8YIYfcTqndLYVAaHmroZHLJZCydsWBOTDqXS2v+mjxohBWEMfg97GXmYQg==", - "dev": true + "version": "1.4.14", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz", + "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==" }, "@jridgewell/trace-mapping": { - "version": "0.3.4", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.4.tgz", - "integrity": "sha512-vFv9ttIedivx0ux3QSjhgtCVjPZd5l46ZOMDSCwnH1yUO2e964gO8LZGyv2QkqcgR6TnBU1v+1IFqmeoG+0UJQ==", - "dev": true, + "version": "0.3.17", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.17.tgz", + "integrity": "sha512-MCNzAp77qzKca9+W/+I0+sEpaUnZoeasnghNeVc41VZCEKaCH73Vq3BZZ/SzWIgrqE4H4ceI+p+b6C0mHf9T4g==", "requires": { - "@jridgewell/resolve-uri": "^3.0.3", - "@jridgewell/sourcemap-codec": "^1.4.10" + "@jridgewell/resolve-uri": "3.1.0", + "@jridgewell/sourcemap-codec": "1.4.14" } }, "@jsdevtools/ono": { @@ -11141,12 +10713,6 @@ "fastq": "^1.6.0" } }, - "@sindresorhus/is": { - "version": "0.14.0", - "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-0.14.0.tgz", - "integrity": "sha512-9NET910DNaIPngYnLLPeg+Ogzqsi9uM4mSboU5y6p8S5DzMTVEsJZrawi+BoDNUVBa2DhJqQYUFvMDfgU062LQ==", - "dev": true - }, "@sinonjs/commons": { "version": "1.8.3", "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.3.tgz", @@ -11165,15 +10731,6 @@ "@sinonjs/commons": "^1.7.0" } }, - "@szmarczak/http-timer": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-1.1.2.tgz", - "integrity": "sha512-XIB2XbzHTN6ieIjfIMV9hlVcfPU26s2vafYWQcZHWXHOxiaRZYEDKEwdl129Zyg50+foYV2jCgtrqSA6qNuNSA==", - "dev": true, - "requires": { - "defer-to-connect": "^1.0.1" - } - }, "@tootallnate/once": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz", @@ -12044,15 +11601,6 @@ "ajv": "^8.0.0" } }, - "ansi-align": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-3.0.1.tgz", - "integrity": "sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w==", - "dev": true, - "requires": { - "string-width": "^4.1.0" - } - }, "ansi-colors": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", @@ -12123,9 +11671,9 @@ } }, "array-flatten": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-3.0.0.tgz", - "integrity": "sha512-zPMVc3ZYlGLNk4mpK1NzP2wg0ml9t7fUgDsayR5Y5rSzxQilzR9FGu/EH2jQOcKSAeAfWeylyW8juy3OkWRvNA==" + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==" }, "array-union": { "version": "2.1.0", @@ -12278,53 +11826,53 @@ "dev": true }, "body-parser": { - "version": "2.0.0-beta.1", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-2.0.0-beta.1.tgz", - "integrity": "sha512-I1v2bt2OdYqtmk8nEFZuEf+9Opb30DphYwTPDbgg/OorSAoJOuTpWyDrZaSWQw7FdoevbBRCP2+9z/halXSWcA==", + "version": "1.20.1", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.1.tgz", + "integrity": "sha512-jWi7abTbYwajOytWCQc37VulmWiRae5RyTpaCyDcS5/lMdtwSz5lOpDE67srw/HYe35f1z3fDQw+3txg7gNtWw==", "requires": { - "bytes": "3.1.1", + "bytes": "3.1.2", "content-type": "~1.0.4", "debug": "2.6.9", - "depd": "~1.1.2", - "http-errors": "1.8.1", + "depd": "2.0.0", + "destroy": "1.2.0", + "http-errors": "2.0.0", "iconv-lite": "0.4.24", - "on-finished": "~2.3.0", - "qs": "6.9.6", - "raw-body": "2.4.2", - "type-is": "~1.6.18" + "on-finished": "2.4.1", + "qs": "6.11.0", + "raw-body": "2.5.1", + "type-is": "~1.6.18", + "unpipe": "1.0.0" }, "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==" + }, + "http-errors": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", + "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", "requires": { - "ms": "2.0.0" + "depd": "2.0.0", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "toidentifier": "1.0.1" } - } - } - }, - "boxen": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/boxen/-/boxen-5.1.2.tgz", - "integrity": "sha512-9gYgQKXx+1nP8mP7CzFyaUARhg7D3n1dF/FnErWmu9l6JvGpNUN278h0aSb+QjoiKSWG+iZ3uHrcqk0qrY9RQQ==", - "dev": true, - "requires": { - "ansi-align": "^3.0.0", - "camelcase": "^6.2.0", - "chalk": "^4.1.0", - "cli-boxes": "^2.2.1", - "string-width": "^4.2.2", - "type-fest": "^0.20.2", - "widest-line": "^3.1.0", - "wrap-ansi": "^7.0.0" - }, - "dependencies": { - "camelcase": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", - "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", - "dev": true + }, + "on-finished": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", + "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", + "requires": { + "ee-first": "1.1.1" + } + }, + "statuses": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==" } } }, @@ -12393,41 +11941,9 @@ "integrity": "sha512-a7ZpuTZU1TRtnwyCNW3I5dc0wWNC3VR9S++Ewyk2HHZdrO3CQJqSpd+95Us590V6AL7JqUAH2IwZ/398PmNFgw==" }, "bytes": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.1.tgz", - "integrity": "sha512-dWe4nWO/ruEOY7HkUJ5gFt1DCFV9zPRoJr8pV0/ASQermOZjtq8jMjOprC0Kd10GLN+l7xaUPvxzJFWtxGu8Fg==" - }, - "cacheable-request": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-6.1.0.tgz", - "integrity": "sha512-Oj3cAGPCqOZX7Rz64Uny2GYAZNliQSqfbePrgAQ1wKAihYmCUnraBtJtKcGR4xz7wF+LoJC+ssFZvv5BgF9Igg==", - "dev": true, - "requires": { - "clone-response": "^1.0.2", - "get-stream": "^5.1.0", - "http-cache-semantics": "^4.0.0", - "keyv": "^3.0.0", - "lowercase-keys": "^2.0.0", - "normalize-url": "^4.1.0", - "responselike": "^1.0.2" - }, - "dependencies": { - "get-stream": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", - "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", - "dev": true, - "requires": { - "pump": "^3.0.0" - } - }, - "lowercase-keys": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz", - "integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==", - "dev": true - } - } + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==" }, "call-bind": { "version": "1.0.2", @@ -12567,12 +12083,6 @@ "integrity": "sha512-cOU9usZw8/dXIXKtwa8pM0OTJQuJkxMN6w30csNRUerHfeQ5R6U3kkU/FtJeIf3M202OHfY2U8ccInBG7/xogA==", "dev": true }, - "cli-boxes": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-2.2.1.tgz", - "integrity": "sha512-y4coMcylgSCdVinjiDBuR8PCC2bLjyGTwEmPb9NHR/QaNU6EUOXcTY/s6VjGMD6ENSEaeQYHCY0GNGS5jfMwPw==", - "dev": true - }, "cli-color": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/cli-color/-/cli-color-2.0.1.tgz", @@ -12623,15 +12133,6 @@ "shallow-clone": "^3.0.0" } }, - "clone-response": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.2.tgz", - "integrity": "sha1-0dyXOSAxTfZ/vrlCI7TuNQI56Ws=", - "dev": true, - "requires": { - "mimic-response": "^1.0.0" - } - }, "co": { "version": "4.6.0", "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", @@ -12730,20 +12231,6 @@ "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" }, - "configstore": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/configstore/-/configstore-5.0.1.tgz", - "integrity": "sha512-aMKprgk5YhBNyH25hj8wGt2+D52Sw1DRRIzqBwLp2Ya9mFmY8KPvvtvmna8SxVR9JMZ4kzMD68N22vlaRpkeFA==", - "dev": true, - "requires": { - "dot-prop": "^5.2.0", - "graceful-fs": "^4.1.2", - "make-dir": "^3.0.0", - "unique-string": "^2.0.0", - "write-file-atomic": "^3.0.0", - "xdg-basedir": "^4.0.0" - } - }, "connect-pg-simple": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/connect-pg-simple/-/connect-pg-simple-7.0.0.tgz", @@ -12771,9 +12258,9 @@ } }, "content-type": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", - "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==" + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", + "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==" }, "convert-source-map": { "version": "1.8.0", @@ -12841,12 +12328,6 @@ "which": "^2.0.1" } }, - "crypto-random-string": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-2.0.0.tgz", - "integrity": "sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA==", - "dev": true - }, "csrf": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/csrf/-/csrf-3.1.0.tgz", @@ -12942,9 +12423,9 @@ } }, "debug": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", "requires": { "ms": "2.0.0" } @@ -12979,27 +12460,12 @@ "integrity": "sha512-V0pfhfr8suzyPGOx3nmq4aHqabehUZn6Ch9kyFpV79TGDTWFmHqUqXdabR7QHqxzrYolF4+tVmJhUG4OURg5dQ==", "dev": true }, - "decompress-response": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-3.3.0.tgz", - "integrity": "sha1-gKTdMjdIOEv6JICDYirt7Jgq3/M=", - "dev": true, - "requires": { - "mimic-response": "^1.0.0" - } - }, "dedent": { "version": "0.7.0", "resolved": "https://registry.npmjs.org/dedent/-/dedent-0.7.0.tgz", "integrity": "sha1-JJXduvbrh0q7Dhvp3yLS5aVEMmw=", "dev": true }, - "deep-extend": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", - "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", - "dev": true - }, "deep-is": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", @@ -13012,12 +12478,6 @@ "integrity": "sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg==", "dev": true }, - "defer-to-connect": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-1.1.3.tgz", - "integrity": "sha512-0ISdNousHvZT2EiFlZeZAHBUvSxmKswVCEf8hW7KWgG4a8MVEu/3Vb6uWYozkjylyCxe0JBIiRB1jV45S70WVQ==", - "dev": true - }, "delayed-stream": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", @@ -13030,9 +12490,9 @@ "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=" }, "destroy": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", - "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=" + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", + "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==" }, "detect-newline": { "version": "3.1.0", @@ -13092,26 +12552,11 @@ } } }, - "dot-prop": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-5.3.0.tgz", - "integrity": "sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q==", - "dev": true, - "requires": { - "is-obj": "^2.0.0" - } - }, "dotenv": { "version": "8.6.0", "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-8.6.0.tgz", "integrity": "sha512-IrPdXQsk2BbzvCBGBOTmmSH5SodmqZNt4ERAZDmW4CT+tL8VtvinqywuANaFu4bOMWki16nqf0e4oC0QIaDr/g==" }, - "duplexer3": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.4.tgz", - "integrity": "sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI=", - "dev": true - }, "ee-first": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", @@ -13148,16 +12593,7 @@ "encodeurl": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", - "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=" - }, - "end-of-stream": { - "version": "1.4.4", - "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", - "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", - "dev": true, - "requires": { - "once": "^1.4.0" - } + "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==" }, "enhanced-resolve": { "version": "4.5.0", @@ -13257,16 +12693,10 @@ "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==" }, - "escape-goat": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/escape-goat/-/escape-goat-2.1.1.tgz", - "integrity": "sha512-8/uIhbG12Csjy2JEW7D9pHbreaVaS/OpN3ycnyvElTdwM5n6GY6W6e2IPemfvGZeUMqZ9A/3GqIZMgKnBhAw/Q==", - "dev": true - }, "escape-html": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", - "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=" + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==" }, "escape-string-regexp": { "version": "4.0.0", @@ -13620,7 +13050,7 @@ "etag": { "version": "1.8.1", "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", - "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=" + "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==" }, "event-emitter": { "version": "0.3.5", @@ -13678,48 +13108,77 @@ } }, "express": { - "version": "5.0.0-beta.1", - "resolved": "https://registry.npmjs.org/express/-/express-5.0.0-beta.1.tgz", - "integrity": "sha512-KPtBrlZoQu2Ps0Ce/Imqtq73AB0KBJ8Gx59yZQ3pmDJU2/LhcoZETo03oSgtTQufbcLXt/WBITk/jMjl/WMyrQ==", + "version": "4.18.2", + "resolved": "https://registry.npmjs.org/express/-/express-4.18.2.tgz", + "integrity": "sha512-5/PsL6iGPdfQ/lKM1UuielYgv3BUoJfz1aUwU9vHZ+J7gyvwdQXFEBIEIaxeGf0GIcreATNyBExtalisDbuMqQ==", "requires": { - "accepts": "~1.3.7", - "array-flatten": "3.0.0", - "body-parser": "2.0.0-beta.1", + "accepts": "~1.3.8", + "array-flatten": "1.1.1", + "body-parser": "1.20.1", "content-disposition": "0.5.4", "content-type": "~1.0.4", - "cookie": "0.4.1", + "cookie": "0.5.0", "cookie-signature": "1.0.6", - "debug": "3.1.0", - "depd": "~1.1.2", + "debug": "2.6.9", + "depd": "2.0.0", "encodeurl": "~1.0.2", "escape-html": "~1.0.3", "etag": "~1.8.1", - "finalhandler": "~1.1.2", + "finalhandler": "1.2.0", "fresh": "0.5.2", + "http-errors": "2.0.0", "merge-descriptors": "1.0.1", "methods": "~1.1.2", - "mime-types": "~2.1.34", - "on-finished": "~2.3.0", + "on-finished": "2.4.1", "parseurl": "~1.3.3", - "path-is-absolute": "1.0.1", + "path-to-regexp": "0.1.7", "proxy-addr": "~2.0.7", - "qs": "6.9.6", + "qs": "6.11.0", "range-parser": "~1.2.1", - "router": "2.0.0-beta.1", "safe-buffer": "5.2.1", - "send": "1.0.0-beta.1", - "serve-static": "2.0.0-beta.1", + "send": "0.18.0", + "serve-static": "1.15.0", "setprototypeof": "1.2.0", - "statuses": "~1.5.0", + "statuses": "2.0.1", "type-is": "~1.6.18", "utils-merge": "1.0.1", "vary": "~1.1.2" }, "dependencies": { "cookie": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.1.tgz", - "integrity": "sha512-ZwrFkGJxUR3EIoXtO+yVE69Eb7KlixbaeAWfBQB9vVsNn/o+Yw69gBWSSDK825hQNdN+wF8zELf3dFNl/kxkUA==" + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz", + "integrity": "sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==" + }, + "depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==" + }, + "http-errors": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", + "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", + "requires": { + "depd": "2.0.0", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "toidentifier": "1.0.1" + } + }, + "on-finished": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", + "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", + "requires": { + "ee-first": "1.1.1" + } + }, + "statuses": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==" } } }, @@ -13741,15 +13200,7 @@ "cookie": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.1.tgz", - "integrity": "sha512-ZwrFkGJxUR3EIoXtO+yVE69Eb7KlixbaeAWfBQB9vVsNn/o+Yw69gBWSSDK825hQNdN+wF8zELf3dFNl/kxkUA==" - }, - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "requires": { - "ms": "2.0.0" - } + "integrity": "sha512-ZwrFkGJxUR3EIoXtO+yVE69Eb7KlixbaeAWfBQB9vVsNn/o+Yw69gBWSSDK825hQNdN+wF8zELf3dFNl/kxkUA==" }, "depd": { "version": "2.0.0", @@ -13897,26 +13348,31 @@ } }, "finalhandler": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz", - "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz", + "integrity": "sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==", "requires": { "debug": "2.6.9", "encodeurl": "~1.0.2", "escape-html": "~1.0.3", - "on-finished": "~2.3.0", + "on-finished": "2.4.1", "parseurl": "~1.3.3", - "statuses": "~1.5.0", + "statuses": "2.0.1", "unpipe": "~1.0.0" }, "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "on-finished": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", + "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", "requires": { - "ms": "2.0.0" + "ee-first": "1.1.1" } + }, + "statuses": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==" } } }, @@ -13975,7 +13431,7 @@ "fresh": { "version": "0.5.2", "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", - "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=" + "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==" }, "fs.realpath": { "version": "1.0.0", @@ -14076,15 +13532,6 @@ "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==" }, - "global-dirs": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/global-dirs/-/global-dirs-3.0.0.tgz", - "integrity": "sha512-v8ho2DS5RiCjftj1nD9NmnfaOzTdud7RRnVd9kFNOjqZbISlx5DQ+OrTkywgd0dIt7oFCvKetZSHoHcP3sDdiA==", - "dev": true, - "requires": { - "ini": "2.0.0" - } - }, "globals": { "version": "13.13.0", "resolved": "https://registry.npmjs.org/globals/-/globals-13.13.0.tgz", @@ -14108,45 +13555,15 @@ "slash": "^3.0.0" } }, - "got": { - "version": "9.6.0", - "resolved": "https://registry.npmjs.org/got/-/got-9.6.0.tgz", - "integrity": "sha512-R7eWptXuGYxwijs0eV+v3o6+XH1IqVK8dJOEecQfTmkncw9AV4dcw/Dhxi8MdlqPthxxpZyizMzyg8RTmEsG+Q==", - "dev": true, - "requires": { - "@sindresorhus/is": "^0.14.0", - "@szmarczak/http-timer": "^1.1.2", - "cacheable-request": "^6.0.0", - "decompress-response": "^3.3.0", - "duplexer3": "^0.1.4", - "get-stream": "^4.1.0", - "lowercase-keys": "^1.0.1", - "mimic-response": "^1.0.1", - "p-cancelable": "^1.0.0", - "to-readable-stream": "^1.0.0", - "url-parse-lax": "^3.0.0" - }, - "dependencies": { - "get-stream": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", - "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", - "dev": true, - "requires": { - "pump": "^3.0.0" - } - } - } - }, "graceful-fs": { "version": "4.2.9", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.9.tgz", "integrity": "sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ==" }, "gts": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/gts/-/gts-3.1.0.tgz", - "integrity": "sha512-Pbj3ob1VR1IRlEVEBNtKoQ1wHOa8cZz62KEojK8Fn/qeS2ClWI4gLNfhek3lD68aZSmUEg8TFb6AHXIwUMgyqQ==", + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/gts/-/gts-3.1.1.tgz", + "integrity": "sha512-Jw44aBbzMnd1vtZs7tZt3LMstKQukCBg7N4CKVGzviIQ45Cz5b9lxDJGXVKj/9ySuGv6TYEeijZJGbiiVcM27w==", "dev": true, "requires": { "@typescript-eslint/eslint-plugin": "^4.2.0", @@ -14163,7 +13580,6 @@ "ncp": "^2.0.0", "prettier": "^2.1.2", "rimraf": "^3.0.2", - "update-notifier": "^5.0.0", "write-file-atomic": "^3.0.3" } }, @@ -14199,12 +13615,6 @@ "has-symbols": "^1.0.2" } }, - "has-yarn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/has-yarn/-/has-yarn-2.1.0.tgz", - "integrity": "sha512-UqBRqi4ju7T+TqGNdqAO0PaSVGsDGJUBQvk9eUWNGRY1CFGDzYhLWoM7JQEemnlvVcv/YEmc2wNW8BC24EnUsw==", - "dev": true - }, "hosted-git-info": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-4.1.0.tgz", @@ -14234,12 +13644,6 @@ "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", "dev": true }, - "http-cache-semantics": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz", - "integrity": "sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ==", - "dev": true - }, "http-errors": { "version": "1.8.1", "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.8.1.tgz", @@ -14343,12 +13747,6 @@ "resolve-from": "^4.0.0" } }, - "import-lazy": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/import-lazy/-/import-lazy-2.1.0.tgz", - "integrity": "sha1-BWmOPUXIjo1+nZLLBYTnfwlvPkM=", - "dev": true - }, "import-local": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.1.0.tgz", @@ -14385,12 +13783,6 @@ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" }, - "ini": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ini/-/ini-2.0.0.tgz", - "integrity": "sha512-7PnF4oN3CvZF23ADhA5wRaYEQpJ8qygSkbtTXWBeXWXmEVRXK+1ITciHWwHhsjv1TmW0MgacIv6hEi5pX5NQdA==", - "dev": true - }, "inquirer": { "version": "7.3.3", "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-7.3.3.tgz", @@ -14438,23 +13830,6 @@ "binary-extensions": "^2.0.0" } }, - "is-ci": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-2.0.0.tgz", - "integrity": "sha512-YfJT7rkpQB0updsdHLGWrvhBJfcfzNNawYDNIyQXJz0IViGf75O8EBPKSdvw2rF+LGCsX4FZ8tcr3b19LcZq4w==", - "dev": true, - "requires": { - "ci-info": "^2.0.0" - }, - "dependencies": { - "ci-info": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz", - "integrity": "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==", - "dev": true - } - } - }, "is-core-module": { "version": "2.8.1", "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.8.1.tgz", @@ -14499,40 +13874,12 @@ "is-extglob": "^2.1.1" } }, - "is-installed-globally": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/is-installed-globally/-/is-installed-globally-0.4.0.tgz", - "integrity": "sha512-iwGqO3J21aaSkC7jWnHP/difazwS7SFeIqxv6wEtLU8Y5KlzFTjyqcSIT0d8s4+dDhKytsk9PJZ2BkS5eZwQRQ==", - "dev": true, - "requires": { - "global-dirs": "^3.0.0", - "is-path-inside": "^3.0.2" - } - }, - "is-npm": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/is-npm/-/is-npm-5.0.0.tgz", - "integrity": "sha512-WW/rQLOazUq+ST/bCAVBp/2oMERWLsR7OrKyt052dNDk4DHcDE0/7QSXITlmi+VBcV13DfIbysG3tZJm5RfdBA==", - "dev": true - }, "is-number": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", "dev": true }, - "is-obj": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz", - "integrity": "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==", - "dev": true - }, - "is-path-inside": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", - "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", - "dev": true - }, "is-plain-obj": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", @@ -14579,12 +13926,6 @@ "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=", "dev": true }, - "is-yarn-global": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/is-yarn-global/-/is-yarn-global-0.3.0.tgz", - "integrity": "sha512-VjSeb/lHmkoyd8ryPVIKvOCn4D1koMqY+vqyjjUfc3xyKtP4dYOxM44sZrnqQSzSds3xyOrUTLTC9LVCVgLngw==", - "dev": true - }, "isarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", @@ -15237,22 +14578,10 @@ "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", "dev": true }, - "json-buffer": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.0.tgz", - "integrity": "sha1-Wx85evx11ne96Lz8Dkfh+aPZqJg=", - "dev": true - }, - "json-parse-better-errors": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", - "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==" - }, "json-parse-even-better-errors": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", - "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", - "dev": true + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==" }, "json-schema-ref-parser": { "version": "9.0.9", @@ -15304,9 +14633,9 @@ "dev": true }, "json5": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.1.tgz", - "integrity": "sha512-1hqLFMSrGHRHxav9q9gNjJ5EXznIxGVO09xQRrwplcS8qs28pZ8s8hupZAmqDwZUmVZ2Qb2jnyPOWcDH8m8dlA==", + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", "dev": true }, "jstransformer": { @@ -15318,15 +14647,6 @@ "promise": "^7.0.1" } }, - "keyv": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/keyv/-/keyv-3.1.0.tgz", - "integrity": "sha512-9ykJ/46SN/9KPM/sichzQ7OvXyGDYKGTaDlKMGCAlg2UK8KRy4jb0d8sFc+0Tt0YYnThq8X2RZgCg74RPxgcVA==", - "dev": true, - "requires": { - "json-buffer": "3.0.0" - } - }, "kind-of": { "version": "6.0.3", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", @@ -15344,15 +14664,6 @@ "resolved": "https://registry.npmjs.org/kuler/-/kuler-2.0.0.tgz", "integrity": "sha512-Xq9nH7KlWZmXAtodXDDRE7vs6DU1gTU8zYDHDiWLSip45Egwq3plLHzPn27NgvzL2r1LMPC1vdqh98sQxtqj4A==" }, - "latest-version": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/latest-version/-/latest-version-5.1.0.tgz", - "integrity": "sha512-weT+r0kTkRQdCdYCNtkMwWXQTMEswKrFBkm4ckQOMVhhqhIMI1UT2hMj+1iigIhgSZm5gTmrRXBNoGUgaTY1xA==", - "dev": true, - "requires": { - "package-json": "^6.3.0" - } - }, "leven": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", @@ -15381,9 +14692,9 @@ "integrity": "sha512-92+huvxMvYlMzMt0iIOukcwYBFpkYJdpl2xsZ7LrlayO7E8SOv+JJUEK17B/dJIHAOLMfh2dZZ/Y18WgmGtYNw==" }, "loader-utils": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.2.tgz", - "integrity": "sha512-TM57VeHptv569d/GKh6TAYdzKblwDNiumOdkFnejjD0XwTH87K90w3O7AiJRqdQoXygvi1VQTJTLGhJl7WqA7A==", + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.4.tgz", + "integrity": "sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==", "dev": true, "requires": { "big.js": "^5.2.2", @@ -15443,12 +14754,6 @@ } } }, - "lowercase-keys": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz", - "integrity": "sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA==", - "dev": true - }, "lru-cache": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", @@ -15516,7 +14821,7 @@ "media-typer": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", - "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=" + "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==" }, "memoizee": { "version": "0.4.15", @@ -15591,7 +14896,7 @@ "methods": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", - "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=" + "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==" }, "micromatch": { "version": "4.0.5", @@ -15603,6 +14908,11 @@ "picomatch": "^2.3.1" } }, + "mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==" + }, "mime-db": { "version": "1.52.0", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", @@ -15622,12 +14932,6 @@ "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", "dev": true }, - "mimic-response": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz", - "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==", - "dev": true - }, "min-indent": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz", @@ -15677,14 +14981,6 @@ "on-headers": "~1.0.2" }, "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "requires": { - "ms": "2.0.0" - } - }, "depd": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", @@ -15764,21 +15060,21 @@ "integrity": "sha512-KUdDsspqx89sD4UUyUKzdlUOper3hRkDVkrKh/89G+d9WKsU5ox51NWS4tB1XR5dPUdR4SP0E3molyEfOvSa3g==" }, "nodemon": { - "version": "2.0.15", - "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-2.0.15.tgz", - "integrity": "sha512-gdHMNx47Gw7b3kWxJV64NI+Q5nfl0y5DgDbiVtShiwa7Z0IZ07Ll4RLFo6AjrhzMtoEZn5PDE3/c2AbVsiCkpA==", + "version": "2.0.22", + "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-2.0.22.tgz", + "integrity": "sha512-B8YqaKMmyuCO7BowF1Z1/mkPqLk6cs/l63Ojtd6otKjMx47Dq1utxfRxcavH1I7VSaL8n5BUaoutadnsX3AAVQ==", "dev": true, "requires": { "chokidar": "^3.5.2", "debug": "^3.2.7", "ignore-by-default": "^1.0.1", - "minimatch": "^3.0.4", + "minimatch": "^3.1.2", "pstree.remy": "^1.1.8", "semver": "^5.7.1", + "simple-update-notifier": "^1.0.7", "supports-color": "^5.5.0", "touch": "^3.1.0", - "undefsafe": "^2.0.5", - "update-notifier": "^5.1.0" + "undefsafe": "^2.0.5" }, "dependencies": { "debug": { @@ -15846,12 +15142,6 @@ "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", "dev": true }, - "normalize-url": { - "version": "4.5.1", - "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-4.5.1.tgz", - "integrity": "sha512-9UZCFRHQdNrfTpGg8+1INIg93B6zE0aXMVFkw1WFwvO4SlZywU6aLg5Of0Ap/PgcbSw4LNxvMWXMeugwMCX0AA==", - "dev": true - }, "npm-run-path": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", @@ -15872,6 +15162,11 @@ "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" }, + "object-inspect": { + "version": "1.12.3", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.3.tgz", + "integrity": "sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==" + }, "on-finished": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", @@ -15930,12 +15225,6 @@ "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", "dev": true }, - "p-cancelable": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-1.1.0.tgz", - "integrity": "sha512-s73XxOZ4zpt1edZYZzvhqFa6uvQc1vwUa0K0BdtIZgQMAJj9IbebH+JkgKZc9h+B05PKHLOTl4ajG1BmNrVZlw==", - "dev": true - }, "p-limit": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", @@ -15960,26 +15249,6 @@ "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", "dev": true }, - "package-json": { - "version": "6.5.0", - "resolved": "https://registry.npmjs.org/package-json/-/package-json-6.5.0.tgz", - "integrity": "sha512-k3bdm2n25tkyxcjSKzB5x8kfVxlMdgsbPr0GkZcwHsLpba6cBjqCt1KlcChKEvxHIcTB1FVMuwoijZ26xex5MQ==", - "dev": true, - "requires": { - "got": "^9.6.0", - "registry-auth-token": "^4.0.0", - "registry-url": "^5.0.0", - "semver": "^6.2.0" - }, - "dependencies": { - "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true - } - } - }, "packet-reader": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/packet-reader/-/packet-reader-1.0.0.tgz", @@ -16018,12 +15287,13 @@ "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==" }, "passport": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/passport/-/passport-0.5.2.tgz", - "integrity": "sha512-w9n/Ot5I7orGD4y+7V3EFJCQEznE5RxHamUxcqLT2QoJY0f2JdN8GyHonYFvN0Vz+L6lUJfVhrk2aZz2LbuREw==", + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/passport/-/passport-0.6.0.tgz", + "integrity": "sha512-0fe+p3ZnrWRW74fe8+SvCyf4a3Pb2/h7gFkQ8yTJpAO50gDzlfjZUZTO1k5Eg9kUct22OxHLqDZoKUWRHOh9ug==", "requires": { "passport-strategy": "1.x.x", - "pause": "0.0.1" + "pause": "0.0.1", + "utils-merge": "^1.0.1" } }, "passport-local": { @@ -16062,9 +15332,9 @@ "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==" }, "path-to-regexp": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-3.2.0.tgz", - "integrity": "sha512-jczvQbCUS7XmS7o+y1aEO9OBVFeZBQ1MDSEqmO7xSoPgOPoowY/SxLpZ6Vh97/8qHZOteiCKb7gkG9gA2ZUxJA==" + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", + "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==" }, "path-type": { "version": "4.0.0", @@ -16197,12 +15467,6 @@ "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", "dev": true }, - "prepend-http": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-2.0.0.tgz", - "integrity": "sha1-6SQ0v6XqjBn0HN/UAddBo8gZ2Jc=", - "dev": true - }, "prettier": { "version": "2.6.0", "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.6.0.tgz", @@ -16411,35 +15675,19 @@ "resolved": "https://registry.npmjs.org/pug-walk/-/pug-walk-2.0.0.tgz", "integrity": "sha512-yYELe9Q5q9IQhuvqsZNwA5hfPkMJ8u92bQLIMcsMxf/VADjNtEYptU+inlufAFYcWdHlwNfZOEnOOQrZrcyJCQ==" }, - "pump": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", - "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", - "dev": true, - "requires": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" - } - }, "punycode": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==" }, - "pupa": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/pupa/-/pupa-2.1.1.tgz", - "integrity": "sha512-l1jNAspIBSFqbT+y+5FosojNpVpF94nlI+wDUpqP9enwOTfHx9f0gh5nB96vl+6yTpsJsypeNrwfzPrKuHB41A==", - "dev": true, + "qs": { + "version": "6.11.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", + "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==", "requires": { - "escape-goat": "^2.0.0" + "side-channel": "^1.0.4" } }, - "qs": { - "version": "6.9.6", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.9.6.tgz", - "integrity": "sha512-TIRk4aqYLNoJUbd+g2lEdz5kLWIuTMRagAXxl78Q0RiVjAOugHmeKNGdd3cwo/ktpf9aL9epCfFqWDEKysUlLQ==" - }, "queue-microtask": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", @@ -16471,39 +15719,37 @@ "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==" }, "raw-body": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.2.tgz", - "integrity": "sha512-RPMAFUJP19WIet/99ngh6Iv8fzAbqum4Li7AD6DtGaW2RpMB/11xDoalPiJMTbu6I3hkbMVkATvZrqb9EEqeeQ==", + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.1.tgz", + "integrity": "sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==", "requires": { - "bytes": "3.1.1", - "http-errors": "1.8.1", + "bytes": "3.1.2", + "http-errors": "2.0.0", "iconv-lite": "0.4.24", "unpipe": "1.0.0" - } - }, - "rc": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", - "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", - "dev": true, - "requires": { - "deep-extend": "^0.6.0", - "ini": "~1.3.0", - "minimist": "^1.2.0", - "strip-json-comments": "~2.0.1" }, "dependencies": { - "ini": { - "version": "1.3.8", - "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", - "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", - "dev": true + "depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==" + }, + "http-errors": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", + "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", + "requires": { + "depd": "2.0.0", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "toidentifier": "1.0.1" + } }, - "strip-json-comments": { + "statuses": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", - "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", - "dev": true + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==" } } }, @@ -16633,24 +15879,6 @@ "integrity": "sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==", "dev": true }, - "registry-auth-token": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-4.2.1.tgz", - "integrity": "sha512-6gkSb4U6aWJB4SF2ZvLb76yCBjcvufXBqvvEx1HbmKPkutswjW1xNVRY0+daljIYRbogN7O0etYSlbiaEQyMyw==", - "dev": true, - "requires": { - "rc": "^1.2.8" - } - }, - "registry-url": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/registry-url/-/registry-url-5.1.0.tgz", - "integrity": "sha512-8acYXXTI0AkQv6RAOjE3vOaIXZkT9wo4LOFbBKYQEEnnMNBpKqdUrI6S4NT0KPIo/WVvJ5tE/X5LF/TQUf0ekw==", - "dev": true, - "requires": { - "rc": "^1.2.8" - } - }, "require-directory": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", @@ -16701,15 +15929,6 @@ "integrity": "sha512-J1l+Zxxp4XK3LUDZ9m60LRJF/mAe4z6a4xyabPHk7pvK5t35dACV32iIjJDFeWZFfZlO29w6SZ67knR0tHzJtQ==", "dev": true }, - "responselike": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/responselike/-/responselike-1.0.2.tgz", - "integrity": "sha1-kYcg7ztjHFZCvgaPFa3lpG9Loec=", - "dev": true, - "requires": { - "lowercase-keys": "^1.0.0" - } - }, "restore-cursor": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", @@ -16739,19 +15958,6 @@ "resolved": "https://registry.npmjs.org/rndm/-/rndm-1.2.0.tgz", "integrity": "sha1-8z/pz7Urv9UgqhgyO8ZdsRCht2w=" }, - "router": { - "version": "2.0.0-beta.1", - "resolved": "https://registry.npmjs.org/router/-/router-2.0.0-beta.1.tgz", - "integrity": "sha512-GLoYgkhAGAiwVda5nt6Qd4+5RAPuQ4WIYLlZ+mxfYICI+22gnIB3eCfmhgV8+uJNPS1/39DOYi/vdrrz0/ouKA==", - "requires": { - "array-flatten": "3.0.0", - "methods": "~1.1.2", - "parseurl": "~1.3.3", - "path-to-regexp": "3.2.0", - "setprototypeof": "1.2.0", - "utils-merge": "1.0.1" - } - }, "run-async": { "version": "2.4.1", "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.4.1.tgz", @@ -16843,46 +16049,60 @@ "lru-cache": "^6.0.0" } }, - "semver-diff": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/semver-diff/-/semver-diff-3.1.1.tgz", - "integrity": "sha512-GX0Ix/CJcHyB8c4ykpHGIAvLyOwOobtM/8d+TQkAd81/bEjgPHrfba41Vpesr7jX/t8Uh+R3EX9eAS5be+jQYg==", - "dev": true, - "requires": { - "semver": "^6.3.0" - }, - "dependencies": { - "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true - } - } - }, "send": { - "version": "1.0.0-beta.1", - "resolved": "https://registry.npmjs.org/send/-/send-1.0.0-beta.1.tgz", - "integrity": "sha512-OKTRokcl/oo34O8+6aUpj8Jf2Bjw2D0tZzmX0/RvyfVC9ZOZW+HPAWAlhS817IsRaCnzYX1z++h2kHFr2/KNRg==", + "version": "0.18.0", + "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz", + "integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==", "requires": { - "debug": "3.1.0", - "destroy": "~1.0.4", + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", "encodeurl": "~1.0.2", "escape-html": "~1.0.3", "etag": "~1.8.1", "fresh": "0.5.2", - "http-errors": "1.8.1", - "mime-types": "~2.1.34", + "http-errors": "2.0.0", + "mime": "1.6.0", "ms": "2.1.3", - "on-finished": "~2.3.0", + "on-finished": "2.4.1", "range-parser": "~1.2.1", - "statuses": "~1.5.0" + "statuses": "2.0.1" }, "dependencies": { + "depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==" + }, + "http-errors": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", + "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", + "requires": { + "depd": "2.0.0", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "toidentifier": "1.0.1" + } + }, "ms": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + }, + "on-finished": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", + "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", + "requires": { + "ee-first": "1.1.1" + } + }, + "statuses": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==" } } }, @@ -16895,14 +16115,14 @@ } }, "serve-static": { - "version": "2.0.0-beta.1", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-2.0.0-beta.1.tgz", - "integrity": "sha512-DEJ9on/tQeFO2Omj7ovT02lCp1YgP4Kb8W2lv2o/4keTFAbgc8HtH3yPd47++2wv9lvQeqiA7FHFDe5+8c4XpA==", + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz", + "integrity": "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==", "requires": { "encodeurl": "~1.0.2", "escape-html": "~1.0.3", "parseurl": "~1.3.3", - "send": "1.0.0-beta.1" + "send": "0.18.0" } }, "setprototypeof": { @@ -16934,6 +16154,16 @@ "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", "dev": true }, + "side-channel": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", + "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", + "requires": { + "call-bind": "^1.0.0", + "get-intrinsic": "^1.0.2", + "object-inspect": "^1.9.0" + } + }, "signal-exit": { "version": "3.0.7", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", @@ -16955,6 +16185,23 @@ } } }, + "simple-update-notifier": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/simple-update-notifier/-/simple-update-notifier-1.1.0.tgz", + "integrity": "sha512-VpsrsJSUcJEseSbMHkrsrAVSdvVS5I96Qo1QAQ4FxQ9wXFcB+pjj7FB7/us9+GcgfW4ziHtYMc1J0PLczb55mg==", + "dev": true, + "requires": { + "semver": "~7.0.0" + }, + "dependencies": { + "semver": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.0.0.tgz", + "integrity": "sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A==", + "dev": true + } + } + }, "sisteransi": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", @@ -17212,13 +16459,13 @@ } }, "terser": { - "version": "5.12.1", - "resolved": "https://registry.npmjs.org/terser/-/terser-5.12.1.tgz", - "integrity": "sha512-NXbs+7nisos5E+yXwAD+y7zrcTkMqb0dEJxIGtSKPdCBzopf7ni4odPul2aechpV7EXNvOudYOX2bb5tln1jbQ==", + "version": "5.16.8", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.16.8.tgz", + "integrity": "sha512-QI5g1E/ef7d+PsDifb+a6nnVgC4F22Bg6T0xrBrz6iloVB4PUkkunp6V8nzoOOZJIzjWVdAGqCdlKlhLq/TbIA==", "requires": { + "@jridgewell/source-map": "^0.3.2", "acorn": "^8.5.0", "commander": "^2.20.0", - "source-map": "~0.7.2", "source-map-support": "~0.5.20" }, "dependencies": { @@ -17226,11 +16473,6 @@ "version": "8.7.0", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.7.0.tgz", "integrity": "sha512-V/LGr1APy+PXIwKebEWrkZPwoeoF+w1jiOBUmuxuiUIaOHtob8Qc9BTrYo7VuI5fR8tqsy+buA2WFooR5olqvQ==" - }, - "source-map": { - "version": "0.7.3", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz", - "integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==" } } }, @@ -17327,12 +16569,6 @@ "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=" }, - "to-readable-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/to-readable-stream/-/to-readable-stream-1.0.0.tgz", - "integrity": "sha512-Iq25XBt6zD5npPhlLVXGFN3/gyR2/qODcKNNyTMd4vbm39HUaOiAM4PMq0eMVC/Tkxz+Zjdsc55g9yyz+Yq00Q==", - "dev": true - }, "to-regex-range": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", @@ -17448,9 +16684,9 @@ }, "dependencies": { "json5": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", - "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", + "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", "dev": true, "requires": { "minimist": "^1.2.0" @@ -17549,15 +16785,6 @@ "integrity": "sha512-WxONCrssBM8TSPRqN5EmsjVrsv4A8X12J4ArBiiayv3DyyG3ZlIg6yysuuSYdZsVz3TKcTg2fd//Ujd4CHV1iA==", "dev": true }, - "unique-string": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-2.0.0.tgz", - "integrity": "sha512-uNaeirEPvpZWSgzwsPGtU2zVSTrn/8L5q/IexZmH0eH6SA73CmAA5U4GwORTxQAZs95TAXLNqeLoPPNO5gZfWg==", - "dev": true, - "requires": { - "crypto-random-string": "^2.0.0" - } - }, "universalify": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", @@ -17567,29 +16794,7 @@ "unpipe": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", - "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=" - }, - "update-notifier": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/update-notifier/-/update-notifier-5.1.0.tgz", - "integrity": "sha512-ItnICHbeMh9GqUy31hFPrD1kcuZ3rpxDZbf4KUDavXwS0bW5m7SLbDQpGX3UYr072cbrF5hFUs3r5tUsPwjfHw==", - "dev": true, - "requires": { - "boxen": "^5.0.0", - "chalk": "^4.1.0", - "configstore": "^5.0.1", - "has-yarn": "^2.1.0", - "import-lazy": "^2.1.0", - "is-ci": "^2.0.0", - "is-installed-globally": "^0.4.0", - "is-npm": "^5.0.0", - "is-yarn-global": "^0.3.0", - "latest-version": "^5.1.0", - "pupa": "^2.1.1", - "semver": "^7.3.4", - "semver-diff": "^3.1.1", - "xdg-basedir": "^4.0.0" - } + "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==" }, "uri-js": { "version": "4.4.1", @@ -17599,15 +16804,6 @@ "punycode": "^2.1.0" } }, - "url-parse-lax": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-3.0.0.tgz", - "integrity": "sha1-FrXK/Afb42dsGxmZF3gj1lA6yww=", - "dev": true, - "requires": { - "prepend-http": "^2.0.0" - } - }, "util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", @@ -17616,7 +16812,7 @@ "utils-merge": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", - "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=" + "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==" }, "v8-compile-cache": { "version": "2.3.0", @@ -17711,9 +16907,9 @@ } }, "watchpack": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.3.1.tgz", - "integrity": "sha512-x0t0JuydIo8qCNctdDrn1OzH/qDzk2+rdCOC3YzumZ42fiMqmQ7T3xQurykYMhYfHaPHTp4ZxAx2NfUo1K6QaA==", + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.0.tgz", + "integrity": "sha512-Lcvm7MGST/4fup+ifyKi2hjyIAwcdI4HRgtvTpIUxBRhB+RFtUh8XtDOxUfctVCnhVi+QQj49i91OyvzkJl6cg==", "requires": { "glob-to-regexp": "^0.4.1", "graceful-fs": "^4.1.2" @@ -17726,40 +16922,40 @@ "dev": true }, "webpack": { - "version": "5.70.0", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.70.0.tgz", - "integrity": "sha512-ZMWWy8CeuTTjCxbeaQI21xSswseF2oNOwc70QSKNePvmxE7XW36i7vpBMYZFAUHPwQiEbNGCEYIOOlyRbdGmxw==", + "version": "5.78.0", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.78.0.tgz", + "integrity": "sha512-gT5DP72KInmE/3azEaQrISjTvLYlSM0j1Ezhht/KLVkrqtv10JoP/RXhwmX/frrutOPuSq3o5Vq0ehR/4Vmd1g==", "requires": { "@types/eslint-scope": "^3.7.3", "@types/estree": "^0.0.51", "@webassemblyjs/ast": "1.11.1", "@webassemblyjs/wasm-edit": "1.11.1", "@webassemblyjs/wasm-parser": "1.11.1", - "acorn": "^8.4.1", + "acorn": "^8.7.1", "acorn-import-assertions": "^1.7.6", "browserslist": "^4.14.5", "chrome-trace-event": "^1.0.2", - "enhanced-resolve": "^5.9.2", + "enhanced-resolve": "^5.10.0", "es-module-lexer": "^0.9.0", "eslint-scope": "5.1.1", "events": "^3.2.0", "glob-to-regexp": "^0.4.1", "graceful-fs": "^4.2.9", - "json-parse-better-errors": "^1.0.2", + "json-parse-even-better-errors": "^2.3.1", "loader-runner": "^4.2.0", "mime-types": "^2.1.27", "neo-async": "^2.6.2", "schema-utils": "^3.1.0", "tapable": "^2.1.1", "terser-webpack-plugin": "^5.1.3", - "watchpack": "^2.3.1", + "watchpack": "^2.4.0", "webpack-sources": "^3.2.3" }, "dependencies": { "acorn": { - "version": "8.7.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.7.0.tgz", - "integrity": "sha512-V/LGr1APy+PXIwKebEWrkZPwoeoF+w1jiOBUmuxuiUIaOHtob8Qc9BTrYo7VuI5fR8tqsy+buA2WFooR5olqvQ==" + "version": "8.8.2", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.2.tgz", + "integrity": "sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw==" }, "acorn-import-assertions": { "version": "1.8.0", @@ -17768,9 +16964,9 @@ "requires": {} }, "enhanced-resolve": { - "version": "5.9.2", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.9.2.tgz", - "integrity": "sha512-GIm3fQfwLJ8YZx2smuHpBKkXC1yOk+OBEmKckVyL0i/ea8mqDEykK3ld5dgH1QYPNyT/lIllxV2LULnxCHaHkA==", + "version": "5.12.0", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.12.0.tgz", + "integrity": "sha512-QHTXI/sZQmko1cbDoNAa3mJ5qhWUUNAq3vR0/YiD379fWQrcfuoX1+HW2S0MTt7XmoPLapdaDKUtelUSPic7hQ==", "requires": { "graceful-fs": "^4.2.4", "tapable": "^2.2.0" @@ -17861,15 +17057,6 @@ "isexe": "^2.0.0" } }, - "widest-line": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-3.1.0.tgz", - "integrity": "sha512-NsmoXalsWVDMGupxZ5R08ka9flZjjiLvHVAWYOKtiKM8ujtZWr9cRffak+uSE48+Ob8ObalXpwyeUiyDD6QFgg==", - "dev": true, - "requires": { - "string-width": "^4.0.0" - } - }, "wildcard": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/wildcard/-/wildcard-2.0.0.tgz", @@ -17989,12 +17176,6 @@ "dev": true, "requires": {} }, - "xdg-basedir": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/xdg-basedir/-/xdg-basedir-4.0.0.tgz", - "integrity": "sha512-PSNhEJDejZYV7h50BohL09Er9VaIefr2LMAf3OEmpCkjOi34eYyQYAXUTjEQtZJTKcF0E2UKTh+osDLsgNim9Q==", - "dev": true - }, "xlsx": { "version": "0.17.5", "resolved": "https://registry.npmjs.org/xlsx/-/xlsx-0.17.5.tgz", diff --git a/package.json b/package.json index b4e3983..e72409b 100644 --- a/package.json +++ b/package.json @@ -48,7 +48,7 @@ "@types/pg": "^8.6.1", "@types/pug": "^2.0.4", "@types/tmp": "^0.2.2", - "gts": "^3.1.0", + "gts": "^3.1.1", "jest": "^27.4.5", "json-schema-to-typescript": "^10.1.5", "nodemon": "^2.0.13", @@ -65,13 +65,13 @@ "connect-pg-simple": "^7.0.0", "csurf": "^1.11.0", "dotenv": "^8.2.0", - "express": "^5.0.0-alpha.8", + "express": "^4.18.2", "express-session": "^1.17.2", "hotkeys-js": "^3.8.3", "http-errors": "^1.8.0", "morgan": "^1.10.0", "nodemailer": "^6.7.2", - "passport": "^0.5.0", + "passport": "^0.6.0", "passport-local": "^1.0.0", "pg": "^8.7.1", "pug": "^3.0.0", diff --git a/src/client/index.ts b/src/client/index.ts index 84df5f6..89e3de2 100644 --- a/src/client/index.ts +++ b/src/client/index.ts @@ -65,6 +65,7 @@ export const instance = vue assignmentName: assignment?.name ?? '', undoStack: [], redoStack: [], + DPMode: false }; }, computed: { @@ -89,6 +90,13 @@ export const instance = vue document.querySelector<HTMLInputElement>('#open-file')?.click(); } }, + // New fuctions to turn DP mode on and off + toggleDPMode() { + this.DPMode = true; + }, + toggleTTMode() { + this.DPMode = false; + }, loadFile(event: Event) { const input = event.target; if (!(input instanceof HTMLInputElement)) { diff --git a/views/index.pug b/views/index.pug index 3d56e98..4140c48 100644 --- a/views/index.pug +++ b/views/index.pug @@ -81,6 +81,11 @@ html(lang='en') .dropdown-menu button.menu-option(onclick='toolbar.showModal("shortcuts-modal")') Shortcuts button.menu-option(onclick='toolbar.showModal("substitutions-modal")') Substitutions + .dropdown + button Modes + .dropdown-menu + button.menu-option(onclick='toggleDPMode') Davis-Putnam Mode + button.menu-option(@click='toggleTTMode') Truth Tree Mode .dropdown button Help .dropdown-menu From 0615d325741243c30e7f7644f0d1f5677b466ca3 Mon Sep 17 00:00:00 2001 From: Jenny Gao <jennyg4416@gmail.com> Date: Thu, 6 Apr 2023 16:09:39 -0400 Subject: [PATCH 12/54] update .gitignore Co-Authored-By: Jody Sunray <55996087+jssunray34@users.noreply.github.com> --- .gitignore | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/.gitignore b/.gitignore index ff9733a..ca796d8 100644 --- a/.gitignore +++ b/.gitignore @@ -138,3 +138,11 @@ dist ## TypeScript ## ################## build/ + +################## +## Willow ## +################## +*.willow +WillowFiles + +.DS_Store \ No newline at end of file From 8b0884bfa38ff6fc17b8d6cd67b13f148848cec2 Mon Sep 17 00:00:00 2001 From: jssunray34 <55996087+jssunray34@users.noreply.github.com> Date: Sat, 8 Apr 2023 19:26:30 -0400 Subject: [PATCH 13/54] Add antecedents and decomposition to tree nodes ToDo: - validate (isDecomposed) - tauts will have too many things in decomposition array. ensure it stil validates Co-Authored-By: Jenny Gao <29582421+jeninyg@users.noreply.github.com> --- src/client/component/truth-tree-branch.ts | 27 ++++++++++------- src/client/component/truth-tree-node.ts | 10 ++++++- src/common/tree.ts | 36 +++++++++++++++++------ 3 files changed, 52 insertions(+), 21 deletions(-) diff --git a/src/client/component/truth-tree-branch.ts b/src/client/component/truth-tree-branch.ts index b6d4326..cd904e7 100644 --- a/src/client/component/truth-tree-branch.ts +++ b/src/client/component/truth-tree-branch.ts @@ -76,7 +76,7 @@ export const TruthTreeBranchComponent = defineComponent({ this.childBranches.push(ref); } }, - modifyDecompositionDP(id: number) { + modifyAntecedentsDP(id: number) { // TODO: Document this function more const selectedNode: TruthTreeNode | null = this.$store.getters.selectedNode; @@ -85,17 +85,22 @@ export const TruthTreeBranchComponent = defineComponent({ return; } - if (selectedNode.decomposition.has(id)) { - selectedNode.decomposition.delete(id); + const otherNode: TruthTreeNode = this.$store.state.tree.nodes[id]; // the node you right click (statement to reduce/branch) + + console.log("other node:", otherNode.id); + console.log("selected node:", selectedNode.id); + + if (selectedNode.antecedentsDP.has(id)) { // the node your cursor is on + console.log("remove"); + selectedNode.antecedentsDP.delete(id); + otherNode.decomposition.delete(selectedNode.id); } else { - selectedNode.decomposition.add(id); - } - const decomp = Array.from(selectedNode.decomposition); - for (let i = 0; i < decomp.length; i++) { - // console.log("hello"); - // console.log(decomp[i]); - console.log(this.tree.nodes[decomp[i]]); + console.log("add"); + selectedNode.antecedentsDP.add(id); + otherNode.decomposition.add(selectedNode.id); } + + console.log(selectedNode.antecedentsDP); }, /** * Adds or removes a given node from the decomposition of the selected node, @@ -240,7 +245,7 @@ export const TruthTreeBranchComponent = defineComponent({ <ul class="branch"> <template v-for="id, index in branch"> <li v-if="index === 0 || expanded" - @contextmenu.prevent="modifyDecompositionDP(id)" + @contextmenu.prevent="modifyAntecedentsDP(id)" @click="$store.commit('select', {id: id})" :class="{ selected: selected === id, diff --git a/src/client/component/truth-tree-node.ts b/src/client/component/truth-tree-node.ts index 6f536f0..410101e 100644 --- a/src/client/component/truth-tree-node.ts +++ b/src/client/component/truth-tree-node.ts @@ -96,7 +96,15 @@ export const TruthTreeNodeComponent = defineComponent({ universe: {{ JSON.stringify(node.universe.map(formula => formula.toString())) }} - </span> + </span> + <span> + id: {{ id }}, + valid: {{ node.isValid() }}, + decomposed: {{ node.isDecomposed() }}, + decomposition: {{ node.decomposition }}, + antecedents: {{ node.antecedentsDP }}, + branch: {{node.branch}} + </span> <i :class="getNodeIconClasses(node)" :title="node.getFeedback()"></i> <input :id="'node' + this.id" type="text" v-model="node.text" @focus="$store.commit('select', {id: id, focus: false})" diff --git a/src/common/tree.ts b/src/common/tree.ts index 3124cd8..a9ba4aa 100644 --- a/src/common/tree.ts +++ b/src/common/tree.ts @@ -118,6 +118,11 @@ export class TruthTreeNode { antecedent: number | null = null; // logical parent decomposition: Set<number> = new Set(); + + // For Davis Puttnam reduction + antecedentsDP: Set<number> = new Set(); + branch: Set<number> = new Set(); + private _correctDecomposition: Set<number> | null = null; /** @@ -147,7 +152,8 @@ export class TruthTreeNode { newNode.children = [...this.children]; newNode.antecedent = this.antecedent; newNode.decomposition = new Set(this.decomposition); - + newNode.antecedentsDP = new Set(this.antecedentsDP); + newNode.branch = new Set(this.branch); return newNode; } @@ -604,10 +610,10 @@ export class TruthTreeNode { // this._statement ==> conclusion // leftNode._statement ==> literal // rightNode._statement ==> statement to reduce - let decompositionArr = Array.from(this.decomposition); - if (decompositionArr.length == 2) { - let left = decompositionArr[0]; - let right = decompositionArr[1]; + let antecedentArr = Array.from(this.antecedentsDP); + if (antecedentArr.length == 2) { + let left = antecedentArr[0]; + let right = antecedentArr[1]; let leftNode = this.tree.nodes[left]; let rightNode = this.tree.nodes[right]; @@ -621,10 +627,22 @@ export class TruthTreeNode { rightNode._statement, leftNode._statement ); - let res = - statementReducer.validateReduction(this._statement) || - statementReducer2.validateReduction(this._statement); - if (res) { + let res1 = statementReducer.validateReduction(this._statement); + let res2 = statementReducer2.validateReduction(this._statement); + + if (res1) { + leftNode.branch.clear(); + // leftnode (statement to reduce) should have right node (branch) as decomp + // leftNode.decomposition.clear(); + // leftNode.decomposition.add(this.id); + leftNode.branch.add(right); + return true; + } else if (res2) { + rightNode.branch.clear(); + // opposite + // rightNode.decomposition.clear(); + // rightNode.decomposition.add(this.id); + rightNode.branch.add(left); return true; } } From f2b55555b8cb8106ff56cb614e5d6fed8288d539 Mon Sep 17 00:00:00 2001 From: Jenny Gao <jennyg4416@gmail.com> Date: Sat, 8 Apr 2023 23:51:25 -0400 Subject: [PATCH 14/54] isReduced check start - disabled calles to isDecomposed (will need to circle back) on these Co-Authored-By: Jody Sunray <55996087+jssunray34@users.noreply.github.com> --- src/client/component/truth-tree-branch.ts | 8 --- src/client/component/truth-tree-node.ts | 5 +- src/common/statement.ts | 4 -- src/common/tree.ts | 76 ++++++++++++++++++++--- 4 files changed, 71 insertions(+), 22 deletions(-) diff --git a/src/client/component/truth-tree-branch.ts b/src/client/component/truth-tree-branch.ts index cd904e7..d21f972 100644 --- a/src/client/component/truth-tree-branch.ts +++ b/src/client/component/truth-tree-branch.ts @@ -84,23 +84,15 @@ export const TruthTreeBranchComponent = defineComponent({ if (selectedNode === null || selectedNode.id === id) { return; } - const otherNode: TruthTreeNode = this.$store.state.tree.nodes[id]; // the node you right click (statement to reduce/branch) - console.log("other node:", otherNode.id); - console.log("selected node:", selectedNode.id); - if (selectedNode.antecedentsDP.has(id)) { // the node your cursor is on - console.log("remove"); selectedNode.antecedentsDP.delete(id); otherNode.decomposition.delete(selectedNode.id); } else { - console.log("add"); selectedNode.antecedentsDP.add(id); otherNode.decomposition.add(selectedNode.id); } - - console.log(selectedNode.antecedentsDP); }, /** * Adds or removes a given node from the decomposition of the selected node, diff --git a/src/client/component/truth-tree-node.ts b/src/client/component/truth-tree-node.ts index 410101e..5be7161 100644 --- a/src/client/component/truth-tree-node.ts +++ b/src/client/component/truth-tree-node.ts @@ -8,8 +8,10 @@ export function getNodeIconClasses(node: TruthTreeNode): string[] { validity.errorCode === 'not_parsable' ) { return ['fas', 'fa-exclamation-triangle', 'statement-error']; - } else if (validity === true && node.isDecomposed() === true) { + } else if (validity === true && node.isReduced() === true) { return ['fas', 'fa-check', 'statement-correct']; + // } else if (validity === true && node.isDecomposed() === true) { + // return ['fas', 'fa-check', 'statement-correct']; } else { return ['fas', 'fa-times', 'statement-incorrect']; } @@ -99,7 +101,6 @@ export const TruthTreeNodeComponent = defineComponent({ </span> <span> id: {{ id }}, - valid: {{ node.isValid() }}, decomposed: {{ node.isDecomposed() }}, decomposition: {{ node.decomposition }}, antecedents: {{ node.antecedentsDP }}, diff --git a/src/common/statement.ts b/src/common/statement.ts index 66ac202..bbe5a95 100644 --- a/src/common/statement.ts +++ b/src/common/statement.ts @@ -16,19 +16,15 @@ export abstract class Statement { } isTautology(): boolean { - console.log('TAUTOLOGY'); if (this instanceof OrStatement) { const lhs = this.operands[0]; const rhs = this.operands[1]; - console.log('lhs: ' + lhs); - console.log('rhs: ' + rhs); if (lhs.equals(new NotStatement(rhs))) { return true; } else if (rhs.equals(new NotStatement(lhs))) { return true; } } - return false; } diff --git a/src/common/tree.ts b/src/common/tree.ts index a9ba4aa..0816f66 100644 --- a/src/common/tree.ts +++ b/src/common/tree.ts @@ -4,6 +4,7 @@ import { Statement, AtomicStatement, NotStatement, + OrStatement, QuantifierStatement, ExistenceStatement, UniversalStatement, @@ -121,7 +122,7 @@ export class TruthTreeNode { // For Davis Puttnam reduction antecedentsDP: Set<number> = new Set(); - branch: Set<number> = new Set(); + branch: Set<Statement> = new Set(); private _correctDecomposition: Set<number> | null = null; @@ -635,14 +636,14 @@ export class TruthTreeNode { // leftnode (statement to reduce) should have right node (branch) as decomp // leftNode.decomposition.clear(); // leftNode.decomposition.add(this.id); - leftNode.branch.add(right); + leftNode.branch.add(rightNode._statement); return true; } else if (res2) { rightNode.branch.clear(); // opposite // rightNode.decomposition.clear(); // rightNode.decomposition.add(this.id); - rightNode.branch.add(left); + rightNode.branch.add(leftNode._statement); return true; } } @@ -731,8 +732,12 @@ export class TruthTreeNode { } // Check if each ancestor is decomposed - const ancestorDecomposed = ancestorNode.isDecomposed(); - if (ancestorDecomposed !== true) { + // const ancestorDecomposed = ancestorNode.isDecomposed(); + // if (ancestorDecomposed !== true) { + // return new CorrectnessError('open_invalid_ancestor'); + // } + const ancestorReduced = ancestorNode.isReduced(); + if (ancestorReduced !== true) { return new CorrectnessError('open_invalid_ancestor'); } } @@ -798,6 +803,57 @@ export class TruthTreeNode { return new CorrectnessError('closed_not_contradiction'); } + isReduced(): Response { + // Null statements are decomposed only if they are terminators or empty + // strings + if (this.statement === null) { + // Case 1: Empty string + if (this.text.trim().length === 0) { + return true; + } + + // Case 2: Terminator + if (this.isTerminator()) { + return true; + } + + // Otherwise, it failed to parse but is not one of the above cases + return new CorrectnessError('not_parsable'); + } + + if (this.statement instanceof OrStatement && this.statement.isTautology()) { + let lhs = this.statement.operands[0]; + let rhs = this.statement.operands[1]; + + let count = 0; + for (let key of this.decomposition){ + if (this.tree.nodes[key]._statement?.equals(lhs)){ + count +=1; + // prevents false positive from two lhs being in branch + lhs = rhs; + } else if (this.tree.nodes[key]._statement?.equals(rhs)){ + count +=1; + rhs = lhs; + // remove items from decomposition branch + } else { + this.decomposition.delete(key); + } + } + + // both lhs and rhs are in decomposition of statement + if (count === 2){ + return true; + } + return new CorrectnessError('Tautology not decomposed'); + } + + // To-do: + // 1. if statement's parent is taut (only), return true + // 2. check this+branch, this+!branch is in decomp + + return new CorrectnessError(""); + } + /** * Determines whether or not this statement is fully decomposed in every * open branch. @@ -990,9 +1046,13 @@ export class TruthTreeNode { if (validity !== true) { return validity.getErrorMessage(); } - const decomp = this.isDecomposed(); - if (decomp !== true) { - return decomp.getErrorMessage(); + // const decomp = this.isDecomposed(); + // if (decomp !== true) { + // return decomp.getErrorMessage(); + // } + const reduced = this.isReduced(); + if (reduced !== true) { + return reduced.getErrorMessage(); } if (this.premise) { From aa97ebad9e3147a4a0df629d5cd15539ed462c4e Mon Sep 17 00:00:00 2001 From: jssunray34 <55996087+jssunray34@users.noreply.github.com> Date: Sun, 9 Apr 2023 17:57:28 -0400 Subject: [PATCH 15/54] Add support for taut/con --- src/common/parser.ts | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/common/parser.ts b/src/common/parser.ts index e161b7a..4861a14 100644 --- a/src/common/parser.ts +++ b/src/common/parser.ts @@ -8,6 +8,8 @@ import { OrStatement, UniversalStatement, ExistenceStatement, + Tautology, + Contradiction, } from './statement'; import {Formula} from './formula'; @@ -314,6 +316,8 @@ export class PropositionalLogicParser extends Parser<Statement> { and: ['∧', '&', 'and'], or: ['∨', '|', 'or'], not: ['¬', '!', '~', 'not'], + taut: ['⊤'], + con: ['⊥'] }; start(): Statement { @@ -544,6 +548,8 @@ export class FirstOrderLogicParser extends PropositionalLogicParser { and: ['∧', '&', 'and'], or: ['∨', '|', 'or'], not: ['¬', '!', '~', 'not'], + taut: ['⊤'], + con: ['⊥'] }; unaryExpression(): Statement { @@ -574,6 +580,10 @@ export class FirstOrderLogicParser extends PropositionalLogicParser { this.keyword(')'); return parensStmt; + } else if (this.maybeKeyword('⊤')) { + return new Tautology(); + } else if (this.maybeKeyword('⊥')) { + return new Contradiction(); } return new AtomicStatement(this.match('predicate')); From ed84a24881f98214acdb5f1856a5f8d807eb2aa7 Mon Sep 17 00:00:00 2001 From: Jenny Gao <jennyg4416@gmail.com> Date: Sun, 9 Apr 2023 18:12:02 -0400 Subject: [PATCH 16/54] isDecomposed() Co-Authored-By: Jody Sunray <55996087+jssunray34@users.noreply.github.com> --- src/client/component/truth-tree-node.ts | 11 +- src/common/tree.ts | 458 +++++++++++------------- 2 files changed, 210 insertions(+), 259 deletions(-) diff --git a/src/client/component/truth-tree-node.ts b/src/client/component/truth-tree-node.ts index 5be7161..f6ef242 100644 --- a/src/client/component/truth-tree-node.ts +++ b/src/client/component/truth-tree-node.ts @@ -8,10 +8,8 @@ export function getNodeIconClasses(node: TruthTreeNode): string[] { validity.errorCode === 'not_parsable' ) { return ['fas', 'fa-exclamation-triangle', 'statement-error']; - } else if (validity === true && node.isReduced() === true) { + } else if (validity === true && node.isDecomposed() === true) { return ['fas', 'fa-check', 'statement-correct']; - // } else if (validity === true && node.isDecomposed() === true) { - // return ['fas', 'fa-check', 'statement-correct']; } else { return ['fas', 'fa-times', 'statement-incorrect']; } @@ -99,13 +97,6 @@ export const TruthTreeNodeComponent = defineComponent({ JSON.stringify(node.universe.map(formula => formula.toString())) }} </span> - <span> - id: {{ id }}, - decomposed: {{ node.isDecomposed() }}, - decomposition: {{ node.decomposition }}, - antecedents: {{ node.antecedentsDP }}, - branch: {{node.branch}} - </span> <i :class="getNodeIconClasses(node)" :title="node.getFeedback()"></i> <input :id="'node' + this.id" type="text" v-model="node.text" @focus="$store.commit('select', {id: id, focus: false})" diff --git a/src/common/tree.ts b/src/common/tree.ts index 0816f66..afbf8b4 100644 --- a/src/common/tree.ts +++ b/src/common/tree.ts @@ -16,6 +16,7 @@ import { createNDimensionalMapping, EvaluationResponse, } from './util'; +import { resolveUrl } from 'ajv/dist/compile/resolve'; export class CorrectnessError { errorCode: string; @@ -89,6 +90,9 @@ export class CorrectnessError { case 'universal_variables_length': { return 'Universals with multiple variables cannot be evaluated yet; please split into multiple universal statements.'; } + case 'tautology not decomposed': { + return 'Tautology is not decomposed'; + } } return 'Unknown error code. Contact a developer :)'; @@ -122,8 +126,6 @@ export class TruthTreeNode { // For Davis Puttnam reduction antecedentsDP: Set<number> = new Set(); - branch: Set<Statement> = new Set(); - private _correctDecomposition: Set<number> | null = null; /** @@ -154,7 +156,6 @@ export class TruthTreeNode { newNode.antecedent = this.antecedent; newNode.decomposition = new Set(this.decomposition); newNode.antecedentsDP = new Set(this.antecedentsDP); - newNode.branch = new Set(this.branch); return newNode; } @@ -568,6 +569,46 @@ export class TruthTreeNode { return TruthTree.CLOSED_TERMINATOR === this.text.trim(); } + isDPValid(): Response { + // For DP - check statement logically follows from antecedent + branch + // TODO: ensure this only gets checked when DP in DP mode + if (!this._statement) { + // TODO: change error + return new CorrectnessError('not_parsable'); + } + + // this._statement ==> conclusion + // leftNode._statement ==> literal + // rightNode._statement ==> statement to reduce + let antecedentArr = Array.from(this.antecedentsDP); + if (antecedentArr.length == 2) { + let left = antecedentArr[0]; + let right = antecedentArr[1]; + let leftNode = this.tree.nodes[left]; + let rightNode = this.tree.nodes[right]; + + if (leftNode._statement && rightNode._statement) { + // Validator takes in statement we would like to reduce along with assertion + let statementReducer = new DPStatementValidator( + leftNode._statement, + rightNode._statement + ); + let statementReducer2 = new DPStatementValidator( + rightNode._statement, + leftNode._statement + ); + let res1 = statementReducer.validateReduction(this._statement); + let res2 = statementReducer2.validateReduction(this._statement); + + if (res1 || res2){ + return true; + } + } + } + + // TODO: change error + return new CorrectnessError('not_logical_consequence'); + } /** * Determines whether or not this statement is valid; i.e., it is a logical * consequence of some other statement in the truth tree. @@ -607,47 +648,9 @@ export class TruthTreeNode { return true; } - if (this._statement) { - // this._statement ==> conclusion - // leftNode._statement ==> literal - // rightNode._statement ==> statement to reduce - let antecedentArr = Array.from(this.antecedentsDP); - if (antecedentArr.length == 2) { - let left = antecedentArr[0]; - let right = antecedentArr[1]; - let leftNode = this.tree.nodes[left]; - let rightNode = this.tree.nodes[right]; - - if (leftNode._statement && rightNode._statement) { - // Validator takes in statement we wouled like to reduce along with assertion - let statementReducer = new DPStatementValidator( - leftNode._statement, - rightNode._statement - ); - let statementReducer2 = new DPStatementValidator( - rightNode._statement, - leftNode._statement - ); - let res1 = statementReducer.validateReduction(this._statement); - let res2 = statementReducer2.validateReduction(this._statement); - - if (res1) { - leftNode.branch.clear(); - // leftnode (statement to reduce) should have right node (branch) as decomp - // leftNode.decomposition.clear(); - // leftNode.decomposition.add(this.id); - leftNode.branch.add(rightNode._statement); - return true; - } else if (res2) { - rightNode.branch.clear(); - // opposite - // rightNode.decomposition.clear(); - // rightNode.decomposition.add(this.id); - rightNode.branch.add(leftNode._statement); - return true; - } - } - } + // TODO: DP mode + if (this.isDPValid()){ + return true; } // Non-premises must have an antecedent for this statement to be valid @@ -732,12 +735,8 @@ export class TruthTreeNode { } // Check if each ancestor is decomposed - // const ancestorDecomposed = ancestorNode.isDecomposed(); - // if (ancestorDecomposed !== true) { - // return new CorrectnessError('open_invalid_ancestor'); - // } - const ancestorReduced = ancestorNode.isReduced(); - if (ancestorReduced !== true) { + const ancestorDecomposed = ancestorNode.isDecomposed(); + if (ancestorDecomposed !== true) { return new CorrectnessError('open_invalid_ancestor'); } } @@ -804,54 +803,18 @@ export class TruthTreeNode { } isReduced(): Response { - // Null statements are decomposed only if they are terminators or empty - // strings - if (this.statement === null) { - // Case 1: Empty string - if (this.text.trim().length === 0) { - return true; - } - - // Case 2: Terminator - if (this.isTerminator()) { - return true; - } - - // Otherwise, it failed to parse but is not one of the above cases - return new CorrectnessError('not_parsable'); + // we would like to check the two decompositions are correct + const decompArray = Array.from(this.decomposition); + if (decompArray.length != 2) { + return new CorrectnessError("invalid_decomposition"); } + const s1 = this.tree.nodes[decompArray[0]]; + const s2 = this.tree.nodes[decompArray[1]]; - if (this.statement instanceof OrStatement && this.statement.isTautology()) { - let lhs = this.statement.operands[0]; - let rhs = this.statement.operands[1]; - - let count = 0; - for (let key of this.decomposition){ - if (this.tree.nodes[key]._statement?.equals(lhs)){ - count +=1; - // prevents false positive from two lhs being in branch - lhs = rhs; - } else if (this.tree.nodes[key]._statement?.equals(rhs)){ - count +=1; - rhs = lhs; - // remove items from decomposition branch - } else { - this.decomposition.delete(key); - } - } - - // both lhs and rhs are in decomposition of statement - if (count === 2){ - return true; - } - return new CorrectnessError('Tautology not decomposed'); + if (s1.isDPValid() && s2.isDPValid()){ + return true; } - - // To-do: - // 1. if statement's parent is taut (only), return true - // 2. check this+branch, this+!branch is in decomp - - return new CorrectnessError(""); + return new CorrectnessError("invalid_decomposition"); } /** @@ -891,154 +854,156 @@ export class TruthTreeNode { } } - // This statement must be decomposed in every non-closed branch that - // contains it or exactly one open node if requireAllBranchesTerminated - // is false - let error: CorrectnessError | null = null; - for (const leafId of this.tree.leaves) { - const leafNode = this.tree.nodes[leafId]; - let leafError: CorrectnessError | null = null; - - // If this is an existence statement, we care that it is correctly - // decomposed everywhere, not just non-closed terminators - if ( - !(this.statement instanceof ExistenceStatement) && - leafNode.isClosedTerminator() - ) { - continue; - } - - // This statement must be contained in the leaf's branch - if (!(this.isAncestorOf(leafId) || this.id === leafId)) { - continue; - } - const branch = leafNode.getAncestorBranch(true); - - // Universals are unique from other statements - if (this.statement instanceof UniversalStatement) { - // For universal statements, each branch needs to instantiate - // every single constant in the leaf's universe - - // Collect the decomposed nodes in this branch - const decomposedInBranch = new Set<number>(); - for (const decomposed of this.decomposition) { - if (branch.has(decomposed)) { - decomposedInBranch.add(decomposed); - } - } - - // Each universal must instantiate at least one variable. - if (decomposedInBranch.size === 0) { - error = new CorrectnessError('universal_decompose_length'); - continue; - } - - const symbolized = this.statement.symbolized(); - - // Form every possible assignment of constants for this universal - const uninstantiated = createNDimensionalMapping( - this.statement.variables.length, - leafNode.universe! - ); - - // Remove every assignment from our mapping that appears in the branch - for (const decomposed of decomposedInBranch) { - const decomposedNode = this.tree.nodes[decomposed]; - if (decomposedNode.statement === null) { - // An empty statement cannot be a decomposition - leafError = new CorrectnessError('invalid_decomposition'); - break; - } - - const assignment = symbolized.getEqualsMap(decomposedNode.statement); - if (assignment === false) { - // Not an initialization of the antecedent - leafError = new CorrectnessError('invalid_decomposition'); - break; - } - - if ( - Object.keys(assignment).length !== this.statement.variables.length - ) { - // If the assignment does not have an assignment for every variable - // then arbitrarily assign a value from the universe. If one doesn't - // exist then arbitrarily assign the constant 'x' - - let value: Formula; - // Check universe for arbitrarily value - if (leafNode.universe!.length > 0) { - value = leafNode.universe!.values().next().value; - } else { - value = new Formula('x'); - } - - for (const variable of this.statement.variables) { - if (Object.keys(assignment).includes(variable.toString())) { - continue; - } - assignment[variable.toString()] = value; - } - } - - deleteMapping(uninstantiated, assignment, this.statement.variables); - } - - if (leafError !== null) { - error = leafError; - continue; - } - - // If there are still assignments left, then we did not instantiate every - // possible assignment of constants in this branch - if (Object.keys(uninstantiated).length !== 0) { - const mapping = getFirstUnassigned(uninstantiated)!; - leafError = new CorrectnessError( - 'universal_domain_not_decomposed', - mapping - ); - } - } else { - // Check if the correct decomposition is in this branch - let containedInBranch = false; - for (const correctlyDecomposedNode of this.correctDecomposition!) { - if (branch.has(correctlyDecomposedNode)) { - containedInBranch = true; - break; - } - } - - if (!containedInBranch) { - // This node is not decomposed in every non-closed branch - if (this.statement instanceof ExistenceStatement) { - leafError = new CorrectnessError('existence_instantiation_length'); - } else { - leafError = new CorrectnessError('invalid_decomposition'); - } - } else if (this.decomposition.size > this.correctDecomposition!.size) { - leafError = new CorrectnessError('existence_instantiation_violation'); - } - } - - if (leafError === null) { - // If we have a valid open terminator and don't require all branches to - // be terminated, then we can just return that it works! - if ( - leafNode.isOpenTerminator() && - !this.tree.options.requireAllBranchesTerminated - ) { - return true; - } - } else { - // Save the error - error = leafError; - } - } + return this.isReduced(); + + // // This statement must be decomposed in every non-closed branch that + // // contains it or exactly one open node if requireAllBranchesTerminated + // // is false + // let error: CorrectnessError | null = null; + // for (const leafId of this.tree.leaves) { + // const leafNode = this.tree.nodes[leafId]; + // let leafError: CorrectnessError | null = null; + + // // If this is an existence statement, we care that it is correctly + // // decomposed everywhere, not just non-closed terminators + // if ( + // !(this.statement instanceof ExistenceStatement) && + // leafNode.isClosedTerminator() + // ) { + // continue; + // } + + // // This statement must be contained in the leaf's branch + // if (!(this.isAncestorOf(leafId) || this.id === leafId)) { + // continue; + // } + // const branch = leafNode.getAncestorBranch(true); + + // // Universals are unique from other statements + // if (this.statement instanceof UniversalStatement) { + // // For universal statements, each branch needs to instantiate + // // every single constant in the leaf's universe + + // // Collect the decomposed nodes in this branch + // const decomposedInBranch = new Set<number>(); + // for (const decomposed of this.decomposition) { + // if (branch.has(decomposed)) { + // decomposedInBranch.add(decomposed); + // } + // } + + // // Each universal must instantiate at least one variable. + // if (decomposedInBranch.size === 0) { + // error = new CorrectnessError('universal_decompose_length'); + // continue; + // } + + // const symbolized = this.statement.symbolized(); + + // // Form every possible assignment of constants for this universal + // const uninstantiated = createNDimensionalMapping( + // this.statement.variables.length, + // leafNode.universe! + // ); + + // // Remove every assignment from our mapping that appears in the branch + // for (const decomposed of decomposedInBranch) { + // const decomposedNode = this.tree.nodes[decomposed]; + // if (decomposedNode.statement === null) { + // // An empty statement cannot be a decomposition + // leafError = new CorrectnessError('invalid_decomposition'); + // break; + // } + + // const assignment = symbolized.getEqualsMap(decomposedNode.statement); + // if (assignment === false) { + // // Not an initialization of the antecedent + // leafError = new CorrectnessError('invalid_decomposition'); + // break; + // } + + // if ( + // Object.keys(assignment).length !== this.statement.variables.length + // ) { + // // If the assignment does not have an assignment for every variable + // // then arbitrarily assign a value from the universe. If one doesn't + // // exist then arbitrarily assign the constant 'x' + + // let value: Formula; + // // Check universe for arbitrarily value + // if (leafNode.universe!.length > 0) { + // value = leafNode.universe!.values().next().value; + // } else { + // value = new Formula('x'); + // } + + // for (const variable of this.statement.variables) { + // if (Object.keys(assignment).includes(variable.toString())) { + // continue; + // } + // assignment[variable.toString()] = value; + // } + // } + + // deleteMapping(uninstantiated, assignment, this.statement.variables); + // } + + // if (leafError !== null) { + // error = leafError; + // continue; + // } + + // // If there are still assignments left, then we did not instantiate every + // // possible assignment of constants in this branch + // if (Object.keys(uninstantiated).length !== 0) { + // const mapping = getFirstUnassigned(uninstantiated)!; + // leafError = new CorrectnessError( + // 'universal_domain_not_decomposed', + // mapping + // ); + // } + // } else { + // // Check if the correct decomposition is in this branch + // let containedInBranch = false; + // for (const correctlyDecomposedNode of this.correctDecomposition!) { + // if (branch.has(correctlyDecomposedNode)) { + // containedInBranch = true; + // break; + // } + // } + + // if (!containedInBranch) { + // // This node is not decomposed in every non-closed branch + // if (this.statement instanceof ExistenceStatement) { + // leafError = new CorrectnessError('existence_instantiation_length'); + // } else { + // leafError = new CorrectnessError('invalid_decomposition'); + // } + // } else if (this.decomposition.size > this.correctDecomposition!.size) { + // leafError = new CorrectnessError('existence_instantiation_violation'); + // } + // } + + // if (leafError === null) { + // // If we have a valid open terminator and don't require all branches to + // // be terminated, then we can just return that it works! + // if ( + // leafNode.isOpenTerminator() && + // !this.tree.options.requireAllBranchesTerminated + // ) { + // return true; + // } + // } else { + // // Save the error + // error = leafError; + // } + // } - if (error !== null) { - return error; - } + // if (error !== null) { + // return error; + // } - return true; + // return true; } getFeedback(): string { @@ -1046,15 +1011,10 @@ export class TruthTreeNode { if (validity !== true) { return validity.getErrorMessage(); } - // const decomp = this.isDecomposed(); - // if (decomp !== true) { - // return decomp.getErrorMessage(); - // } - const reduced = this.isReduced(); - if (reduced !== true) { - return reduced.getErrorMessage(); + const decomp = this.isDecomposed(); + if (decomp !== true) { + return decomp.getErrorMessage(); } - if (this.premise) { return 'This statement is a premise.'; } From 35d826552b3d5ebdbe388f6f006d50f3c54107fe Mon Sep 17 00:00:00 2001 From: Jenny Gao <jennyg4416@gmail.com> Date: Sun, 9 Apr 2023 21:36:08 -0400 Subject: [PATCH 17/54] isDecomposed Co-Authored-By: Jody Sunray <55996087+jssunray34@users.noreply.github.com> --- src/client/component/truth-tree-branch.ts | 12 +++++++ src/common/tree.ts | 39 ++++++++++++++++------- 2 files changed, 40 insertions(+), 11 deletions(-) diff --git a/src/client/component/truth-tree-branch.ts b/src/client/component/truth-tree-branch.ts index d21f972..040b80e 100644 --- a/src/client/component/truth-tree-branch.ts +++ b/src/client/component/truth-tree-branch.ts @@ -93,6 +93,18 @@ export const TruthTreeBranchComponent = defineComponent({ selectedNode.antecedentsDP.add(id); otherNode.decomposition.add(selectedNode.id); } + + if (selectedNode.antecedent === id) { + selectedNode.antecedent = null; + } else { + // Remove this node from the current antecedent decomposition + if (selectedNode.antecedent !== null) { + const currentAntecedent: TruthTreeNode = + this.$store.state.tree.nodes[selectedNode.antecedent]; + } + selectedNode.antecedent = id; + } + }, /** * Adds or removes a given node from the decomposition of the selected node, diff --git a/src/common/tree.ts b/src/common/tree.ts index afbf8b4..12b6522 100644 --- a/src/common/tree.ts +++ b/src/common/tree.ts @@ -198,6 +198,18 @@ export class TruthTreeNode { } newNode.decomposition = new Set(jsonObject.decomposition); + if ( + !( + 'antecedentsDP' in jsonObject && + typeof jsonObject.antecedentsDP === 'object' && + Array.isArray(jsonObject.antecedentsDP) && + jsonObject.antecedentsDP.every(element => typeof element === 'number') + ) + ) { + throw new Error('TruthTreeNode#fromJSON: antecedentsDP not found.'); + } + newNode.antecedentsDP = new Set(jsonObject.antecedentsDP); + // Check for optional properties if ('premise' in jsonObject && typeof jsonObject.premise === 'boolean') { newNode.premise = jsonObject.premise; @@ -581,6 +593,9 @@ export class TruthTreeNode { // leftNode._statement ==> literal // rightNode._statement ==> statement to reduce let antecedentArr = Array.from(this.antecedentsDP); + + + console.log("isDPvalid arr length", this._statement.toString(), antecedentArr.length); if (antecedentArr.length == 2) { let left = antecedentArr[0]; let right = antecedentArr[1]; @@ -605,7 +620,6 @@ export class TruthTreeNode { } } } - // TODO: change error return new CorrectnessError('not_logical_consequence'); } @@ -648,26 +662,28 @@ export class TruthTreeNode { return true; } - // TODO: DP mode - if (this.isDPValid()){ + // return this.isDPValid(); + // // TODO: DP mode + if (this.isDPValid() === true){ return true; } // Non-premises must have an antecedent for this statement to be valid if (this.antecedent === null || !(this.antecedent in this.tree.nodes)) { - return new CorrectnessError('not_logical_consequence'); + + return new CorrectnessError('not_logical_consequence1'); } // The antecedent must have been successfully parsed into a statement const antecedentNode = this.tree.nodes[this.antecedent]; if (antecedentNode.statement === null) { // Cannot be a logical consequence of nothing - return new CorrectnessError('not_logical_consequence'); + return new CorrectnessError('not_logical_consequence2'); } // The antecedent must be in the ancestor branch if (!this.getAncestorBranch().has(this.antecedent)) { - return new CorrectnessError('not_logical_consequence'); + return new CorrectnessError('not_logical_consequence3'); } // If the antecedent is a quantifier, there is a different procedure: @@ -675,7 +691,7 @@ export class TruthTreeNode { if (antecedentNode.statement instanceof QuantifierStatement) { if (!antecedentNode.statement.symbolized().equals(this.statement)) { // Not a valid instantiation of the quantifier. - return new CorrectnessError('invalid_instantiation'); + return new CorrectnessError('invalid_instantiation4'); } return true; @@ -686,7 +702,7 @@ export class TruthTreeNode { return true; } - return new CorrectnessError('not_logical_consequence'); + return new CorrectnessError('not_logical_consequence5'); } /** @@ -856,9 +872,9 @@ export class TruthTreeNode { return this.isReduced(); - // // This statement must be decomposed in every non-closed branch that - // // contains it or exactly one open node if requireAllBranchesTerminated - // // is false + // This statement must be decomposed in every non-closed branch that + // contains it or exactly one open node if requireAllBranchesTerminated + // is false // let error: CorrectnessError | null = null; // for (const leafId of this.tree.leaves) { // const leafNode = this.tree.nodes[leafId]; @@ -1228,6 +1244,7 @@ export class TruthTree { text: node.text, children: node.children, decomposition: [...node.decomposition], + antecedentsDP: [...node.antecedentsDP] }; if (node.premise) { From fd766b54856592f3d2fce043eb8894af768d44df Mon Sep 17 00:00:00 2001 From: jssunray34 <55996087+jssunray34@users.noreply.github.com> Date: Sun, 9 Apr 2023 21:40:51 -0400 Subject: [PATCH 18/54] Get tautology check to work Co-Authored-By: Jenny Gao <29582421+jeninyg@users.noreply.github.com> --- src/client/component/truth-tree-branch.ts | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/client/component/truth-tree-branch.ts b/src/client/component/truth-tree-branch.ts index 040b80e..518276b 100644 --- a/src/client/component/truth-tree-branch.ts +++ b/src/client/component/truth-tree-branch.ts @@ -98,13 +98,11 @@ export const TruthTreeBranchComponent = defineComponent({ selectedNode.antecedent = null; } else { // Remove this node from the current antecedent decomposition - if (selectedNode.antecedent !== null) { - const currentAntecedent: TruthTreeNode = - this.$store.state.tree.nodes[selectedNode.antecedent]; - } selectedNode.antecedent = id; } + otherNode.correctDecomposition = null; + selectedNode.correctDecomposition = null; }, /** * Adds or removes a given node from the decomposition of the selected node, From 779d02320054f7980e68aceb33d18c5d3440d862 Mon Sep 17 00:00:00 2001 From: Jenny Gao <jennyg4416@gmail.com> Date: Sun, 9 Apr 2023 21:47:44 -0400 Subject: [PATCH 19/54] debug Co-Authored-By: Jody Sunray <55996087+jssunray34@users.noreply.github.com> --- src/client/component/truth-tree-node.ts | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/client/component/truth-tree-node.ts b/src/client/component/truth-tree-node.ts index f6ef242..e4f3424 100644 --- a/src/client/component/truth-tree-node.ts +++ b/src/client/component/truth-tree-node.ts @@ -97,6 +97,14 @@ export const TruthTreeNodeComponent = defineComponent({ JSON.stringify(node.universe.map(formula => formula.toString())) }} </span> + <span> + id: {{ id }}, + valid: {{ node.isValid() }}, + decomposed: {{ node.isDecomposed() }}, + decomposition: {{ node.decomposition }}, + antecedentsDP: {{ node.antecedentsDP }}, + antecedent: {{ node.antecedent }}, + </span> <i :class="getNodeIconClasses(node)" :title="node.getFeedback()"></i> <input :id="'node' + this.id" type="text" v-model="node.text" @focus="$store.commit('select', {id: id, focus: false})" From eef3e67c2b404a74b1dbe162d9f0e6bc0f14f06d Mon Sep 17 00:00:00 2001 From: Jenny Gao <jennyg4416@gmail.com> Date: Sun, 9 Apr 2023 21:50:28 -0400 Subject: [PATCH 20/54] prettier Co-Authored-By: Jody Sunray <55996087+jssunray34@users.noreply.github.com> --- src/client/component/truth-tree-branch.ts | 3 ++- src/client/index.ts | 2 +- src/common/parser.ts | 4 ++-- src/common/tree.ts | 26 ++++++++++++----------- 4 files changed, 19 insertions(+), 16 deletions(-) diff --git a/src/client/component/truth-tree-branch.ts b/src/client/component/truth-tree-branch.ts index 518276b..70429fd 100644 --- a/src/client/component/truth-tree-branch.ts +++ b/src/client/component/truth-tree-branch.ts @@ -86,7 +86,8 @@ export const TruthTreeBranchComponent = defineComponent({ } const otherNode: TruthTreeNode = this.$store.state.tree.nodes[id]; // the node you right click (statement to reduce/branch) - if (selectedNode.antecedentsDP.has(id)) { // the node your cursor is on + if (selectedNode.antecedentsDP.has(id)) { + // the node your cursor is on selectedNode.antecedentsDP.delete(id); otherNode.decomposition.delete(selectedNode.id); } else { diff --git a/src/client/index.ts b/src/client/index.ts index 89e3de2..c7fac54 100644 --- a/src/client/index.ts +++ b/src/client/index.ts @@ -65,7 +65,7 @@ export const instance = vue assignmentName: assignment?.name ?? '', undoStack: [], redoStack: [], - DPMode: false + DPMode: false, }; }, computed: { diff --git a/src/common/parser.ts b/src/common/parser.ts index 4861a14..00e147e 100644 --- a/src/common/parser.ts +++ b/src/common/parser.ts @@ -317,7 +317,7 @@ export class PropositionalLogicParser extends Parser<Statement> { or: ['∨', '|', 'or'], not: ['¬', '!', '~', 'not'], taut: ['⊤'], - con: ['⊥'] + con: ['⊥'], }; start(): Statement { @@ -549,7 +549,7 @@ export class FirstOrderLogicParser extends PropositionalLogicParser { or: ['∨', '|', 'or'], not: ['¬', '!', '~', 'not'], taut: ['⊤'], - con: ['⊥'] + con: ['⊥'], }; unaryExpression(): Statement { diff --git a/src/common/tree.ts b/src/common/tree.ts index 12b6522..fab43f9 100644 --- a/src/common/tree.ts +++ b/src/common/tree.ts @@ -16,7 +16,7 @@ import { createNDimensionalMapping, EvaluationResponse, } from './util'; -import { resolveUrl } from 'ajv/dist/compile/resolve'; +import {resolveUrl} from 'ajv/dist/compile/resolve'; export class CorrectnessError { errorCode: string; @@ -118,10 +118,10 @@ export class TruthTreeNode { tree: TruthTree; - parent: number | null = null; // physical parent + parent: number | null = null; // physical parent children: number[] = []; - antecedent: number | null = null; // logical parent + antecedent: number | null = null; // logical parent decomposition: Set<number> = new Set(); // For Davis Puttnam reduction @@ -594,8 +594,11 @@ export class TruthTreeNode { // rightNode._statement ==> statement to reduce let antecedentArr = Array.from(this.antecedentsDP); - - console.log("isDPvalid arr length", this._statement.toString(), antecedentArr.length); + console.log( + 'isDPvalid arr length', + this._statement.toString(), + antecedentArr.length + ); if (antecedentArr.length == 2) { let left = antecedentArr[0]; let right = antecedentArr[1]; @@ -615,7 +618,7 @@ export class TruthTreeNode { let res1 = statementReducer.validateReduction(this._statement); let res2 = statementReducer2.validateReduction(this._statement); - if (res1 || res2){ + if (res1 || res2) { return true; } } @@ -664,13 +667,12 @@ export class TruthTreeNode { // return this.isDPValid(); // // TODO: DP mode - if (this.isDPValid() === true){ + if (this.isDPValid() === true) { return true; } // Non-premises must have an antecedent for this statement to be valid if (this.antecedent === null || !(this.antecedent in this.tree.nodes)) { - return new CorrectnessError('not_logical_consequence1'); } @@ -822,15 +824,15 @@ export class TruthTreeNode { // we would like to check the two decompositions are correct const decompArray = Array.from(this.decomposition); if (decompArray.length != 2) { - return new CorrectnessError("invalid_decomposition"); + return new CorrectnessError('invalid_decomposition'); } const s1 = this.tree.nodes[decompArray[0]]; const s2 = this.tree.nodes[decompArray[1]]; - if (s1.isDPValid() && s2.isDPValid()){ + if (s1.isDPValid() && s2.isDPValid()) { return true; } - return new CorrectnessError("invalid_decomposition"); + return new CorrectnessError('invalid_decomposition'); } /** @@ -1244,7 +1246,7 @@ export class TruthTree { text: node.text, children: node.children, decomposition: [...node.decomposition], - antecedentsDP: [...node.antecedentsDP] + antecedentsDP: [...node.antecedentsDP], }; if (node.premise) { From bfa50a84841dcdf453348e786add9496eae771a8 Mon Sep 17 00:00:00 2001 From: jssunray34 <55996087+jssunray34@users.noreply.github.com> Date: Tue, 11 Apr 2023 14:36:04 -0400 Subject: [PATCH 21/54] Modify and add tree node labels Co-Authored-By: Jenny Gao <29582421+jeninyg@users.noreply.github.com> --- public/css/index.css | 20 +++++++++++++++++++- src/client/component/truth-tree-branch.ts | 15 ++++++++++++++- 2 files changed, 33 insertions(+), 2 deletions(-) diff --git a/public/css/index.css b/public/css/index.css index 6f448a3..f05e1d0 100644 --- a/public/css/index.css +++ b/public/css/index.css @@ -96,7 +96,7 @@ background-color: var(--selected); } -.antecedent { +.antecedent, .antecedents-DP-branch { background-color: var(--antecedent); } @@ -109,6 +109,24 @@ transform: translateY(-50%); } +.antecedents-DP-branch::after { + content: 'using'; + font-style: italic; + position: absolute; + top: 50%; + right: 10px; + transform: translateY(-50%); +} + +.antecedent-DP::after { + content: 'reduces from'; + font-style: italic; + position: absolute; + top: 50%; + right: 10px; + transform: translateY(-50%); +} + .decomposition { background-color: var(--decomposition); } diff --git a/src/client/component/truth-tree-branch.ts b/src/client/component/truth-tree-branch.ts index 70429fd..a3f235b 100644 --- a/src/client/component/truth-tree-branch.ts +++ b/src/client/component/truth-tree-branch.ts @@ -92,7 +92,10 @@ export const TruthTreeBranchComponent = defineComponent({ otherNode.decomposition.delete(selectedNode.id); } else { selectedNode.antecedentsDP.add(id); - otherNode.decomposition.add(selectedNode.id); + + if (!otherNode.statement?.isLiteral()) { + otherNode.decomposition.add(selectedNode.id); + } } if (selectedNode.antecedent === id) { @@ -255,6 +258,16 @@ export const TruthTreeBranchComponent = defineComponent({ antecedent: selectedNode !== null && selectedNode.antecedent === id, + 'antecedent-DP': + selectedNode != null && + selectedNode.antecedentsDP.has(id) && + $store.state.tree.nodes[id]._statement != null && + !$store.state.tree.nodes[id]._statement.isLiteral(), + 'antecedents-DP-branch': + selectedNode != null && + selectedNode.antecedentsDP.has(id) && + $store.state.tree.nodes[id]._statement != null && + $store.state.tree.nodes[id]._statement.isLiteral(), decomposition: selectedNode !== null && selectedNode.decomposition.has(id), From 57eb3fc1255c42855d42739f38df50d9381ac30b Mon Sep 17 00:00:00 2001 From: jssunray34 <55996087+jssunray34@users.noreply.github.com> Date: Tue, 11 Apr 2023 15:10:32 -0400 Subject: [PATCH 22/54] Code cleanup - remove extraneous comments - add some comments - fix correctness error codes --- src/client/component/truth-tree-branch.ts | 11 ++++------- src/client/component/truth-tree-node.ts | 8 -------- src/common/tree.ts | 10 +++++----- 3 files changed, 9 insertions(+), 20 deletions(-) diff --git a/src/client/component/truth-tree-branch.ts b/src/client/component/truth-tree-branch.ts index a3f235b..39b68db 100644 --- a/src/client/component/truth-tree-branch.ts +++ b/src/client/component/truth-tree-branch.ts @@ -79,20 +79,21 @@ export const TruthTreeBranchComponent = defineComponent({ modifyAntecedentsDP(id: number) { // TODO: Document this function more const selectedNode: TruthTreeNode | null = - this.$store.getters.selectedNode; + this.$store.getters.selectedNode; // The node your cursor is on if (selectedNode === null || selectedNode.id === id) { return; } - const otherNode: TruthTreeNode = this.$store.state.tree.nodes[id]; // the node you right click (statement to reduce/branch) + const otherNode: TruthTreeNode = this.$store.state.tree.nodes[id]; // The node you right click (statement to reduce/branch) if (selectedNode.antecedentsDP.has(id)) { - // the node your cursor is on + selectedNode.antecedentsDP.delete(id); otherNode.decomposition.delete(selectedNode.id); } else { selectedNode.antecedentsDP.add(id); + // Don't add the selected node to a literal, i.e., the branch used for reducing if (!otherNode.statement?.isLiteral()) { otherNode.decomposition.add(selectedNode.id); } @@ -135,12 +136,8 @@ export const TruthTreeBranchComponent = defineComponent({ } const decomp = Array.from(selectedNode.decomposition); for (let i = 0; i < decomp.length; i++) { - // console.log("hello"); - // console.log(decomp[i]); console.log(this.tree.nodes[decomp[i]]); } - // let first = decomp[0] - // console.log(this.tree.nodes[decomp[0]]) } else if (selectedNode.isAncestorOf(id)) { // When the selected is BEFORE, it becomes decomposition const otherNode: TruthTreeNode = this.$store.state.tree.nodes[id]; diff --git a/src/client/component/truth-tree-node.ts b/src/client/component/truth-tree-node.ts index e4f3424..f6ef242 100644 --- a/src/client/component/truth-tree-node.ts +++ b/src/client/component/truth-tree-node.ts @@ -97,14 +97,6 @@ export const TruthTreeNodeComponent = defineComponent({ JSON.stringify(node.universe.map(formula => formula.toString())) }} </span> - <span> - id: {{ id }}, - valid: {{ node.isValid() }}, - decomposed: {{ node.isDecomposed() }}, - decomposition: {{ node.decomposition }}, - antecedentsDP: {{ node.antecedentsDP }}, - antecedent: {{ node.antecedent }}, - </span> <i :class="getNodeIconClasses(node)" :title="node.getFeedback()"></i> <input :id="'node' + this.id" type="text" v-model="node.text" @focus="$store.commit('select', {id: id, focus: false})" diff --git a/src/common/tree.ts b/src/common/tree.ts index fab43f9..318aff4 100644 --- a/src/common/tree.ts +++ b/src/common/tree.ts @@ -673,19 +673,19 @@ export class TruthTreeNode { // Non-premises must have an antecedent for this statement to be valid if (this.antecedent === null || !(this.antecedent in this.tree.nodes)) { - return new CorrectnessError('not_logical_consequence1'); + return new CorrectnessError('not_logical_consequence'); } // The antecedent must have been successfully parsed into a statement const antecedentNode = this.tree.nodes[this.antecedent]; if (antecedentNode.statement === null) { // Cannot be a logical consequence of nothing - return new CorrectnessError('not_logical_consequence2'); + return new CorrectnessError('not_logical_consequence'); } // The antecedent must be in the ancestor branch if (!this.getAncestorBranch().has(this.antecedent)) { - return new CorrectnessError('not_logical_consequence3'); + return new CorrectnessError('not_logical_consequence'); } // If the antecedent is a quantifier, there is a different procedure: @@ -693,7 +693,7 @@ export class TruthTreeNode { if (antecedentNode.statement instanceof QuantifierStatement) { if (!antecedentNode.statement.symbolized().equals(this.statement)) { // Not a valid instantiation of the quantifier. - return new CorrectnessError('invalid_instantiation4'); + return new CorrectnessError('invalid_instantiation'); } return true; @@ -704,7 +704,7 @@ export class TruthTreeNode { return true; } - return new CorrectnessError('not_logical_consequence5'); + return new CorrectnessError('not_logical_consequence'); } /** From 1b508ecc95ef8dbdbf4eea875cdc67f3fd291363 Mon Sep 17 00:00:00 2001 From: jssunray34 <55996087+jssunray34@users.noreply.github.com> Date: Tue, 11 Apr 2023 15:14:46 -0400 Subject: [PATCH 23/54] prettier --- src/client/component/truth-tree-branch.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/client/component/truth-tree-branch.ts b/src/client/component/truth-tree-branch.ts index 39b68db..d60543c 100644 --- a/src/client/component/truth-tree-branch.ts +++ b/src/client/component/truth-tree-branch.ts @@ -87,7 +87,6 @@ export const TruthTreeBranchComponent = defineComponent({ const otherNode: TruthTreeNode = this.$store.state.tree.nodes[id]; // The node you right click (statement to reduce/branch) if (selectedNode.antecedentsDP.has(id)) { - selectedNode.antecedentsDP.delete(id); otherNode.decomposition.delete(selectedNode.id); } else { From 729e8bc059118a455c97611328e4a243186e63c5 Mon Sep 17 00:00:00 2001 From: jssunray34 <55996087+jssunray34@users.noreply.github.com> Date: Tue, 25 Apr 2023 12:52:13 -0400 Subject: [PATCH 24/54] Add functionality for closed terminator also fixed issue related to branch literals (when checking the correctness of the tree, we weren't storing nodes in the decomposition of any literal, which was breaking the representation check) --- public/css/index.css | 2 +- src/client/component/truth-tree-branch.ts | 39 +++++++++++++++++++---- src/client/component/truth-tree-node.ts | 8 +++++ src/common/tree.ts | 21 ++++++++++++ 4 files changed, 62 insertions(+), 8 deletions(-) diff --git a/public/css/index.css b/public/css/index.css index f05e1d0..7cad5e8 100644 --- a/public/css/index.css +++ b/public/css/index.css @@ -96,7 +96,7 @@ background-color: var(--selected); } -.antecedent, .antecedents-DP-branch { +.antecedent, .antecedent-DP, .antecedents-DP-branch { background-color: var(--antecedent); } diff --git a/src/client/component/truth-tree-branch.ts b/src/client/component/truth-tree-branch.ts index d60543c..cfaec06 100644 --- a/src/client/component/truth-tree-branch.ts +++ b/src/client/component/truth-tree-branch.ts @@ -1,3 +1,4 @@ +import {Contradiction, OrStatement} from '../../common/statement'; import {defineComponent} from 'vue'; import {TruthTree, TruthTreeNode} from '../../common/tree'; import {TruthTreeNodeComponent} from './truth-tree-node'; @@ -89,22 +90,46 @@ export const TruthTreeBranchComponent = defineComponent({ if (selectedNode.antecedentsDP.has(id)) { selectedNode.antecedentsDP.delete(id); otherNode.decomposition.delete(selectedNode.id); + + // add this maybe? + if (selectedNode.antecedent === id) { + selectedNode.antecedent = null; + } + } else { selectedNode.antecedentsDP.add(id); // Don't add the selected node to a literal, i.e., the branch used for reducing - if (!otherNode.statement?.isLiteral()) { + // if (!otherNode.statement?.isLiteral()) { + // otherNode.decomposition.add(selectedNode.id); + // } + + console.log("TYPE:", otherNode.statement?.toString()); + + if (otherNode.statement instanceof OrStatement) { + console.log("here's a branch literal:", selectedNode.statement?.toString()); + selectedNode.isBranchLiteral = true; + } + + if (!otherNode.isBranchLiteral) { + console.log("yeah don't add me to its decomposition:", otherNode.statement?.toString()); otherNode.decomposition.add(selectedNode.id); + + + selectedNode.antecedent = id; // add other node as antecedent } - } - if (selectedNode.antecedent === id) { - selectedNode.antecedent = null; - } else { - // Remove this node from the current antecedent decomposition - selectedNode.antecedent = id; + + } + // if (selectedNode.antecedent === id) { + // selectedNode.antecedent = null; + // } else { + // // Remove this node from the current antecedent decomposition + // selectedNode.antecedent = id; + // } + otherNode.correctDecomposition = null; selectedNode.correctDecomposition = null; }, diff --git a/src/client/component/truth-tree-node.ts b/src/client/component/truth-tree-node.ts index f6ef242..e4f3424 100644 --- a/src/client/component/truth-tree-node.ts +++ b/src/client/component/truth-tree-node.ts @@ -97,6 +97,14 @@ export const TruthTreeNodeComponent = defineComponent({ JSON.stringify(node.universe.map(formula => formula.toString())) }} </span> + <span> + id: {{ id }}, + valid: {{ node.isValid() }}, + decomposed: {{ node.isDecomposed() }}, + decomposition: {{ node.decomposition }}, + antecedentsDP: {{ node.antecedentsDP }}, + antecedent: {{ node.antecedent }}, + </span> <i :class="getNodeIconClasses(node)" :title="node.getFeedback()"></i> <input :id="'node' + this.id" type="text" v-model="node.text" @focus="$store.commit('select', {id: id, focus: false})" diff --git a/src/common/tree.ts b/src/common/tree.ts index 318aff4..626142e 100644 --- a/src/common/tree.ts +++ b/src/common/tree.ts @@ -9,6 +9,7 @@ import { ExistenceStatement, UniversalStatement, DPStatementValidator, + Contradiction, } from './statement'; import { deleteMapping, @@ -116,6 +117,8 @@ export class TruthTreeNode { isTautology = false; comment: string | null = null; + isBranchLiteral = false; + tree: TruthTree; parent: number | null = null; // physical parent @@ -770,6 +773,17 @@ export class TruthTreeNode { * @returns true if this closed terminator is valid, false otherwise */ private isClosedTerminatorValid(): Response { + // ***another DP mode thing*** + const antecedentsDPArray = Array.from(this.antecedentsDP); + if (antecedentsDPArray.length > 0) { + const antecedent = this.tree.nodes[antecedentsDPArray[0]]; + if (antecedent.statement instanceof Contradiction) { + return true; + } + + new CorrectnessError('closed_not_contradiction'); + } + // Closed terminators must reference exactly two statements if (this.decomposition.size !== 2) { return new CorrectnessError('closed_reference_length'); @@ -1889,6 +1903,13 @@ export class TruthTree { return false; } const decomposedNode = this.nodes[decomposedId]; + + // **potentially for DP node** + if (decomposedNode.statement instanceof Contradiction) { + console.log("herrreeee", node.id, decomposedNode.statement.toString()); + continue; + } + if (decomposedNode.antecedent !== node.id) { console.log(`${node.id} is not an antecedent of ${decomposedId}`); return false; From f0a76e5b2e9a92a85bb1d9e27e08ef3bd51b3f37 Mon Sep 17 00:00:00 2001 From: jssunray34 <55996087+jssunray34@users.noreply.github.com> Date: Tue, 25 Apr 2023 13:09:50 -0400 Subject: [PATCH 25/54] Create README files --- DP_developer_guide.md | 12 ++++++++++++ DP_userguide.md | 1 + 2 files changed, 13 insertions(+) create mode 100644 DP_developer_guide.md create mode 100644 DP_userguide.md diff --git a/DP_developer_guide.md b/DP_developer_guide.md new file mode 100644 index 0000000..5d0b6ca --- /dev/null +++ b/DP_developer_guide.md @@ -0,0 +1,12 @@ +# Davis-Putnam Developer's Guide + +## Changes to existing functionality + +When designing an implementation of Davis-Putnam (DP) supported by Willow, we wanted to utilize as much of the existing functionality as possible. Below are the major changes and additions that were made. + +1. **Implementation of the reduction rules for each type of statement:** These rules were used to reduce statements given the truth value of a literal. All of the reduction rules are as follows: + + ¬⊤ ⇒ + +2. Support for contradiction (⊥) and tautology (⊤) symbols +3. \ No newline at end of file diff --git a/DP_userguide.md b/DP_userguide.md new file mode 100644 index 0000000..006914b --- /dev/null +++ b/DP_userguide.md @@ -0,0 +1 @@ +# Davis-Putnam User's Guide \ No newline at end of file From dee25ce84db36fb7bd42aafe10be76a078e00be4 Mon Sep 17 00:00:00 2001 From: Jody Sunray <55996087+jssunray34@users.noreply.github.com> Date: Tue, 25 Apr 2023 13:53:44 -0400 Subject: [PATCH 26/54] Update DP_developer_guide.md --- DP_developer_guide.md | 24 +++++++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/DP_developer_guide.md b/DP_developer_guide.md index 5d0b6ca..41f1568 100644 --- a/DP_developer_guide.md +++ b/DP_developer_guide.md @@ -4,9 +4,27 @@ When designing an implementation of Davis-Putnam (DP) supported by Willow, we wanted to utilize as much of the existing functionality as possible. Below are the major changes and additions that were made. -1. **Implementation of the reduction rules for each type of statement:** These rules were used to reduce statements given the truth value of a literal. All of the reduction rules are as follows: +1. **Implementation of the reduction rules for each type of statement:** These rules were used to reduce statements given the truth value of a literal. The reduction rules are as follows. - ¬⊤ ⇒ + | Not | And | Or | Conditional | Biconditional | + | --------- | ----------- |------------ | ----------- | ------------- | + | ¬⊤ => ⊥ | ⊤ ∧ P => P | ⊤ ∨ P => ⊤ | ⊤ → P => P | ⊤ ↔ P => P | + | ¬⊥ => ⊤ | ⊥ ∧ P => ⊥ | ⊥ ∨ P => P | ⊥ → P => ⊤ | ⊥ ↔ P => ¬P | + | | P ∧ ⊤ => P | P ∨ ⊤ => ⊤ | P → ⊤ => ⊤ | P ↔ ⊤ => P | + | | P ∧ ⊥ => ⊥ | P ∨ ⊥ => P | P → ⊥ => ¬P | P ↔ ⊥ => ¬P | + + For example, given the statement A ∧ B and the literal B, we can reduce to the atomic statement A. Rules like this were used to verify whether the statement a user has inputted is indeed a valid inference. 2. Support for contradiction (⊥) and tautology (⊤) symbols -3. \ No newline at end of file +3. Support for basic tautological statement (A ∨ ¬A) +4. Functional frontend to that supports both DP and truth-tree methods +5. Minor language changes to tree node labels and status bar +6. Statement validation for DP +7. Statement decomposition checks for DP +8. Testing for the reduction rules + +## Tasks that still need to be completed + +The implementation of DP in Willow is completely usable in its current state. However, there are a few action items that we were not able to get to, and more thorough testing will need to be done to ensure that the feature is production-ready. + +1. Handle lingering statements that have not been fully decomposed From 46feaa9f77713884cd0c196e163f045751fd37fc Mon Sep 17 00:00:00 2001 From: jssunray34 <55996087+jssunray34@users.noreply.github.com> Date: Tue, 25 Apr 2023 22:46:31 -0400 Subject: [PATCH 27/54] Fix check for branch literal also add additional check for reducing a statement on itself --- src/client/component/truth-tree-branch.ts | 5 +++-- src/common/statement.ts | 3 +++ 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/client/component/truth-tree-branch.ts b/src/client/component/truth-tree-branch.ts index cfaec06..912f70e 100644 --- a/src/client/component/truth-tree-branch.ts +++ b/src/client/component/truth-tree-branch.ts @@ -1,4 +1,4 @@ -import {Contradiction, OrStatement} from '../../common/statement'; +import {Contradiction, NotStatement, OrStatement} from '../../common/statement'; import {defineComponent} from 'vue'; import {TruthTree, TruthTreeNode} from '../../common/tree'; import {TruthTreeNodeComponent} from './truth-tree-node'; @@ -106,9 +106,10 @@ export const TruthTreeBranchComponent = defineComponent({ console.log("TYPE:", otherNode.statement?.toString()); - if (otherNode.statement instanceof OrStatement) { + if (selectedNode.statement && otherNode.statement?.isTautology() && otherNode.statement.equals(new OrStatement(selectedNode.statement, new NotStatement(selectedNode.statement)))) { console.log("here's a branch literal:", selectedNode.statement?.toString()); selectedNode.isBranchLiteral = true; + selectedNode.decomposition.clear(); } if (!otherNode.isBranchLiteral) { diff --git a/src/common/statement.ts b/src/common/statement.ts index bbe5a95..9335f73 100644 --- a/src/common/statement.ts +++ b/src/common/statement.ts @@ -914,6 +914,9 @@ export class DPStatementValidator { * @returns true if the conclusion is valid and false otherwise */ validateReduction(conclusion: Statement): boolean { + if (this.statement.equals(this.assertion)) { + return conclusion.equals(new Tautology()); + } return this.validConclusion.equals(conclusion); } } From 0c69c2c63db3d6cddb689aaa2617ad17e9c24935 Mon Sep 17 00:00:00 2001 From: jssunray34 <55996087+jssunray34@users.noreply.github.com> Date: Tue, 25 Apr 2023 23:04:17 -0400 Subject: [PATCH 28/54] Fix test suite --- tests/reductionRules.test.ts | 66 ++++++++++++++++++++---------------- 1 file changed, 37 insertions(+), 29 deletions(-) diff --git a/tests/reductionRules.test.ts b/tests/reductionRules.test.ts index eee8be9..f2c67ea 100644 --- a/tests/reductionRules.test.ts +++ b/tests/reductionRules.test.ts @@ -1,6 +1,6 @@ import {Formula} from '../src/common/formula'; import { - StatementReducer, + DPStatementValidator, AndStatement, AtomicStatement, NotStatement, @@ -21,29 +21,21 @@ const conditionalStatementToReduce2 = new ConditionalStatement(new AtomicStateme const biconditionalStatementToReduce1 = new BiconditionalStatement(new AtomicStatement(new Formula("H")), new AtomicStatement(new Formula("B"))); const biconditionalStatementToReduce2 = new BiconditionalStatement(new AtomicStatement(new Formula("B")), new AtomicStatement(new Formula("H"))); -const notStatementReducer = new StatementReducer(notStatementToReduce); -const andStatementReducer1 = new StatementReducer(andStatementToReduce1); -const andStatementReducer2 = new StatementReducer(andStatementToReduce2); -const orStatementReducer1 = new StatementReducer(orStatementToReduce1); -const orStatementReducer2 = new StatementReducer(orStatementToReduce2); -const conditionalStatementReducer1 = new StatementReducer(conditionalStatementToReduce1); -const conditionalStatementReducer2 = new StatementReducer(conditionalStatementToReduce2); -const biconditionalStatementReducer1 = new StatementReducer(biconditionalStatementToReduce1); -const biconditionalStatementReducer2 = new StatementReducer(biconditionalStatementToReduce2); - // NOT reduction rules test('¬True should have conclusion False', () => { const literal = new AtomicStatement(new Formula("H")); + const notStatementReducer = new DPStatementValidator(notStatementToReduce, literal); const conclusion = new Contradiction; - const result = notStatementReducer.validateReduction(literal, conclusion); + const result = notStatementReducer.validateReduction(conclusion); expect(result).toBeTruthy(); }); test('¬False should have conclusion True', () => { const literal = new NotStatement(new AtomicStatement(new Formula("H"))); + const notStatementReducer = new DPStatementValidator(notStatementToReduce, literal); const conclusion = new Tautology; - const result = notStatementReducer.validateReduction(literal, conclusion); + const result = notStatementReducer.validateReduction(conclusion); expect(result).toBeTruthy(); }); @@ -51,29 +43,33 @@ test('¬False should have conclusion True', () => { test('True ∧ P should have conclusion P', () => { const literal = new AtomicStatement(new Formula("H")); + const andStatementReducer1 = new DPStatementValidator(andStatementToReduce1, literal); const conclusion = new AtomicStatement(new Formula("B")); - const result = andStatementReducer1.validateReduction(literal, conclusion); + const result = andStatementReducer1.validateReduction(conclusion); expect(result).toBeTruthy(); }); test('False ∧ P should have conclusion False', () => { const literal = new NotStatement(new AtomicStatement(new Formula("H"))); + const andStatementReducer1 = new DPStatementValidator(andStatementToReduce1, literal); const conclusion = new Contradiction; - const result = andStatementReducer1.validateReduction(literal, conclusion); + const result = andStatementReducer1.validateReduction(conclusion); expect(result).toBeTruthy(); }); test('P ∧ True should have conclusion P', () => { const literal = new AtomicStatement(new Formula("H")); + const andStatementReducer2 = new DPStatementValidator(andStatementToReduce2, literal); const conclusion = new AtomicStatement(new Formula("B")); - const result = andStatementReducer2.validateReduction(literal, conclusion); + const result = andStatementReducer2.validateReduction(conclusion); expect(result).toBeTruthy(); }); test('P ∧ False should have conclusion False', () => { const literal = new NotStatement(new AtomicStatement(new Formula("H"))); + const andStatementReducer2 = new DPStatementValidator(andStatementToReduce2, literal); const conclusion = new Contradiction; - const result = andStatementReducer2.validateReduction(literal, conclusion); + const result = andStatementReducer2.validateReduction(conclusion); expect(result).toBeTruthy(); }); @@ -81,29 +77,33 @@ test('P ∧ False should have conclusion False', () => { test('True ∨ P should have conclusion True', () => { const literal = new AtomicStatement(new Formula("H")); + const orStatementReducer1 = new DPStatementValidator(orStatementToReduce1, literal); const conclusion = new Tautology; - const result = orStatementReducer1.validateReduction(literal, conclusion); + const result = orStatementReducer1.validateReduction(conclusion); expect(result).toBeTruthy(); }); test('False ∨ P should have conclusion P', () => { const literal = new NotStatement(new AtomicStatement(new Formula("H"))); + const orStatementReducer1 = new DPStatementValidator(orStatementToReduce1, literal); const conclusion = new AtomicStatement(new Formula("B")); - const result = orStatementReducer1.validateReduction(literal, conclusion); + const result = orStatementReducer1.validateReduction(conclusion); expect(result).toBeTruthy(); }); test('P ∨ True should have conclusion P', () => { const literal = new AtomicStatement(new Formula("H")); + const orStatementReducer2 = new DPStatementValidator(orStatementToReduce2, literal); const conclusion = new Tautology; - const result = orStatementReducer2.validateReduction(literal, conclusion); + const result = orStatementReducer2.validateReduction(conclusion); expect(result).toBeTruthy(); }); test('P ∨ False should have conclusion P', () => { const literal = new NotStatement(new AtomicStatement(new Formula("H"))); + const orStatementReducer2 = new DPStatementValidator(orStatementToReduce2, literal); const conclusion = new AtomicStatement(new Formula("B")); - const result = orStatementReducer2.validateReduction(literal, conclusion); + const result = orStatementReducer2.validateReduction(conclusion); expect(result).toBeTruthy(); }); @@ -111,29 +111,33 @@ test('P ∨ False should have conclusion P', () => { test('True → P should have conclusion P', () => { const literal = new AtomicStatement(new Formula("H")); + const conditionalStatementReducer1 = new DPStatementValidator(conditionalStatementToReduce1, literal); const conclusion = new AtomicStatement(new Formula("B")); - const result = conditionalStatementReducer1.validateReduction(literal, conclusion); + const result = conditionalStatementReducer1.validateReduction(conclusion); expect(result).toBeTruthy(); }); test('False → P should have conclusion P', () => { const literal = new NotStatement(new AtomicStatement(new Formula("H"))); + const conditionalStatementReducer1 = new DPStatementValidator(conditionalStatementToReduce1, literal); const conclusion = new Tautology; - const result = conditionalStatementReducer1.validateReduction(literal, conclusion); + const result = conditionalStatementReducer1.validateReduction(conclusion); expect(result).toBeTruthy(); }); test('P → True should have conclusion P', () => { const literal = new AtomicStatement(new Formula("H")); + const conditionalStatementReducer2 = new DPStatementValidator(conditionalStatementToReduce2, literal); const conclusion = new Tautology; - const result = conditionalStatementReducer2.validateReduction(literal, conclusion); + const result = conditionalStatementReducer2.validateReduction(conclusion); expect(result).toBeTruthy(); }); test('P → False should have conclusion ¬P', () => { const literal = new NotStatement(new AtomicStatement(new Formula("H"))); + const conditionalStatementReducer2 = new DPStatementValidator(conditionalStatementToReduce2, literal); const conclusion = new NotStatement(new AtomicStatement(new Formula("B"))); - const result = conditionalStatementReducer2.validateReduction(literal, conclusion); + const result = conditionalStatementReducer2.validateReduction(conclusion); expect(result).toBeTruthy(); }); @@ -141,28 +145,32 @@ test('P → False should have conclusion ¬P', () => { test('True ↔ P should have conclusion P', () => { const literal = new AtomicStatement(new Formula("H")); + const biconditionalStatementReducer1 = new DPStatementValidator(biconditionalStatementToReduce1, literal); const conclusion = new AtomicStatement(new Formula("B")); - const result = biconditionalStatementReducer1.validateReduction(literal, conclusion); + const result = biconditionalStatementReducer1.validateReduction(conclusion); expect(result).toBeTruthy(); }); test('False ↔ P should have conclusion P', () => { const literal = new NotStatement(new AtomicStatement(new Formula("H"))); + const biconditionalStatementReducer1 = new DPStatementValidator(biconditionalStatementToReduce1, literal); const conclusion = new NotStatement(new AtomicStatement(new Formula("B")));; - const result = biconditionalStatementReducer1.validateReduction(literal, conclusion); + const result = biconditionalStatementReducer1.validateReduction(conclusion); expect(result).toBeTruthy(); }); test('P ↔ True should have conclusion P', () => { const literal = new AtomicStatement(new Formula("H")); + const biconditionalStatementReducer2 = new DPStatementValidator(biconditionalStatementToReduce2, literal); const conclusion = new AtomicStatement(new Formula("B")); - const result = biconditionalStatementReducer2.validateReduction(literal, conclusion); + const result = biconditionalStatementReducer2.validateReduction(conclusion); expect(result).toBeTruthy(); }); test('P ↔ False should have conclusion ¬P', () => { const literal = new NotStatement(new AtomicStatement(new Formula("H"))); + const biconditionalStatementReducer2 = new DPStatementValidator(biconditionalStatementToReduce2, literal); const conclusion = new NotStatement(new AtomicStatement(new Formula("B"))); - const result = biconditionalStatementReducer2.validateReduction(literal, conclusion); + const result = biconditionalStatementReducer2.validateReduction(conclusion); expect(result).toBeTruthy(); }); From d91c9eb9881c39be1739f4c2ad72d334cabdd243 Mon Sep 17 00:00:00 2001 From: jssunray34 <55996087+jssunray34@users.noreply.github.com> Date: Wed, 26 Apr 2023 00:58:49 -0400 Subject: [PATCH 29/54] Clean up code/remove extraneous comments/add comments --- src/client/component/truth-tree-branch.ts | 43 +++++----------- src/common/parser.ts | 4 +- src/common/statement.ts | 37 +++++--------- src/common/tree.ts | 60 +++++++++-------------- 4 files changed, 48 insertions(+), 96 deletions(-) diff --git a/src/client/component/truth-tree-branch.ts b/src/client/component/truth-tree-branch.ts index 912f70e..2b97c87 100644 --- a/src/client/component/truth-tree-branch.ts +++ b/src/client/component/truth-tree-branch.ts @@ -1,4 +1,4 @@ -import {Contradiction, NotStatement, OrStatement} from '../../common/statement'; +import {NotStatement, OrStatement} from '../../common/statement'; import {defineComponent} from 'vue'; import {TruthTree, TruthTreeNode} from '../../common/tree'; import {TruthTreeNodeComponent} from './truth-tree-node'; @@ -87,50 +87,37 @@ export const TruthTreeBranchComponent = defineComponent({ } const otherNode: TruthTreeNode = this.$store.state.tree.nodes[id]; // The node you right click (statement to reduce/branch) + // If the selected node already has the node that has been right + // clicked in its antecedents list, then remove it if (selectedNode.antecedentsDP.has(id)) { selectedNode.antecedentsDP.delete(id); otherNode.decomposition.delete(selectedNode.id); - // add this maybe? + // Reset the selected node's antecedent to null if (selectedNode.antecedent === id) { selectedNode.antecedent = null; } - } else { + // Otherwise add the right clicked node to the current node's antecedents list selectedNode.antecedentsDP.add(id); - // Don't add the selected node to a literal, i.e., the branch used for reducing - // if (!otherNode.statement?.isLiteral()) { - // otherNode.decomposition.add(selectedNode.id); - // } - - console.log("TYPE:", otherNode.statement?.toString()); - - if (selectedNode.statement && otherNode.statement?.isTautology() && otherNode.statement.equals(new OrStatement(selectedNode.statement, new NotStatement(selectedNode.statement)))) { - console.log("here's a branch literal:", selectedNode.statement?.toString()); + // If the selected node is a branch literal, specify it as such and clear out its decomposition + if ( + otherNode.statement?.isTautology() && + selectedNode.statement != null && + otherNode.statement.equals(new OrStatement(selectedNode.statement, new NotStatement(selectedNode.statement))) + ) { selectedNode.isBranchLiteral = true; selectedNode.decomposition.clear(); } + // Only add to the selected node's decomposition if it is not a branch literal if (!otherNode.isBranchLiteral) { - console.log("yeah don't add me to its decomposition:", otherNode.statement?.toString()); otherNode.decomposition.add(selectedNode.id); - - - selectedNode.antecedent = id; // add other node as antecedent + selectedNode.antecedent = id; // Add other node as antecedent } - - - } - // if (selectedNode.antecedent === id) { - // selectedNode.antecedent = null; - // } else { - // // Remove this node from the current antecedent decomposition - // selectedNode.antecedent = id; - // } - otherNode.correctDecomposition = null; selectedNode.correctDecomposition = null; }, @@ -159,10 +146,6 @@ export const TruthTreeBranchComponent = defineComponent({ } else { selectedNode.decomposition.add(id); } - const decomp = Array.from(selectedNode.decomposition); - for (let i = 0; i < decomp.length; i++) { - console.log(this.tree.nodes[decomp[i]]); - } } else if (selectedNode.isAncestorOf(id)) { // When the selected is BEFORE, it becomes decomposition const otherNode: TruthTreeNode = this.$store.state.tree.nodes[id]; diff --git a/src/common/parser.ts b/src/common/parser.ts index 00e147e..4861a14 100644 --- a/src/common/parser.ts +++ b/src/common/parser.ts @@ -317,7 +317,7 @@ export class PropositionalLogicParser extends Parser<Statement> { or: ['∨', '|', 'or'], not: ['¬', '!', '~', 'not'], taut: ['⊤'], - con: ['⊥'], + con: ['⊥'] }; start(): Statement { @@ -549,7 +549,7 @@ export class FirstOrderLogicParser extends PropositionalLogicParser { or: ['∨', '|', 'or'], not: ['¬', '!', '~', 'not'], taut: ['⊤'], - con: ['⊥'], + con: ['⊥'] }; unaryExpression(): Statement { diff --git a/src/common/statement.ts b/src/common/statement.ts index 9335f73..8e68ef2 100644 --- a/src/common/statement.ts +++ b/src/common/statement.ts @@ -1,4 +1,3 @@ -import {not} from 'ajv/dist/compile/codegen'; import {Formula, REPLACEMENT_SYMBOL} from './formula'; import {AssignmentMap} from './util'; @@ -15,6 +14,11 @@ export abstract class Statement { ); } + /** + * Determines whether or not this statement is a tautology, i.e., the law of + * excluded middle. + * @returns true if this statement is a tautology, false otherwise + */ isTautology(): boolean { if (this instanceof OrStatement) { const lhs = this.operands[0]; @@ -604,14 +608,16 @@ class StatementEquivalenceEvaluator { * StatementReducer */ export class DPStatementReducer { - statement: Statement; // the conclustion + statement: Statement; // The conclusion constructor(statement: Statement) { this.statement = statement; } /** - * check if statment is a simple statement + * Checks if the statement is a simple statement, i.e., it cannot be reduced. This + * could either be an atomic statement, taut symbol, or con symbol. + * @param statement the statement to be checked */ private isSimpleStatement(statement: Statement) { // TODO: maybe check statement can be Tautology/ Contradiction @@ -630,8 +636,6 @@ export class DPStatementReducer { */ private reduceNotStatement(assertion: Statement): Statement { if (this.statement instanceof NotStatement) { - // console.log('NotStatment!'); - // console.log(this.statement.operand); let operand = this.statement.operand; if (!this.isSimpleStatement(operand)) { @@ -664,11 +668,6 @@ export class DPStatementReducer { */ private reduceAndStatement(assertion: Statement): Statement { if (this.statement instanceof AndStatement) { - // console.log('[hi] AndStatement!'); - // console.log(this.statement.toString()); - - // console.log('left: ' + this.statement.operands[0]); - // console.log('right: ' + this.statement.operands[1]); let lhs = this.statement.operands[0]; let rhs = this.statement.operands[1]; @@ -688,7 +687,6 @@ export class DPStatementReducer { rhs = new_operand; } } - // console.log('And statements REDUCED', lhs.toString, rhs.toString); if (assertion.equals(lhs) || lhs instanceof Tautology) { return rhs; } else if ( @@ -718,9 +716,6 @@ export class DPStatementReducer { */ private reduceOrStatement(assertion: Statement): Statement { if (this.statement instanceof OrStatement) { - // console.log('OrStatement!'); - // console.log('left: ' + this.statement.operands[0]); - // console.log('right: ' + this.statement.operands[1]); let lhs = this.statement.operands[0]; let rhs = this.statement.operands[1]; if (!this.isSimpleStatement(lhs)) { @@ -766,13 +761,7 @@ export class DPStatementReducer { * @param conclusion the predicted conclusion */ private reduceConditionalStatement(assertion: Statement): Statement { - // can we reduce on the statement if (this.statement instanceof ConditionalStatement) { - // console.log('[hi] ConditionalStatement!'); - // console.log(this.statement.toString()); - - // console.log('left: ' + this.statement.lhs); - // console.log('right: ' + this.statement.rhs); let lhs = this.statement.lhs; let rhs = this.statement.rhs; if (!this.isSimpleStatement(lhs)) { @@ -797,7 +786,7 @@ export class DPStatementReducer { rhs.toString() ); - // second part of or is when assertions get absorbed by intermediate steps + // Second part of or is when assertions get absorbed by intermediate steps if (assertion.equals(lhs) || lhs instanceof Tautology) { return rhs; } else if ( @@ -827,9 +816,6 @@ export class DPStatementReducer { */ private reduceBiconditionalStatement(assertion: Statement): Statement { if (this.statement instanceof BiconditionalStatement) { - // console.log('BiconditionalStatement!'); - // console.log('left: ' + this.statement.lhs); - // console.log('right: ' + this.statement.rhs); let lhs = this.statement.lhs; let rhs = this.statement.rhs; if (!this.isSimpleStatement(lhs)) { @@ -895,9 +881,8 @@ export class DPStatementReducer { } export class DPStatementValidator { - statement: Statement; // statement we're attempting to reduce + statement: Statement; // Statement we're attempting to reduce assertion: Statement; - // reducer: DPStatementReducer; validConclusion: Statement; constructor(statement: Statement, assertion: Statement) { diff --git a/src/common/tree.ts b/src/common/tree.ts index 626142e..ca455b9 100644 --- a/src/common/tree.ts +++ b/src/common/tree.ts @@ -4,7 +4,6 @@ import { Statement, AtomicStatement, NotStatement, - OrStatement, QuantifierStatement, ExistenceStatement, UniversalStatement, @@ -12,12 +11,8 @@ import { Contradiction, } from './statement'; import { - deleteMapping, - getFirstUnassigned, - createNDimensionalMapping, EvaluationResponse, } from './util'; -import {resolveUrl} from 'ajv/dist/compile/resolve'; export class CorrectnessError { errorCode: string; @@ -91,9 +86,6 @@ export class CorrectnessError { case 'universal_variables_length': { return 'Universals with multiple variables cannot be evaluated yet; please split into multiple universal statements.'; } - case 'tautology not decomposed': { - return 'Tautology is not decomposed'; - } } return 'Unknown error code. Contact a developer :)'; @@ -121,14 +113,15 @@ export class TruthTreeNode { tree: TruthTree; - parent: number | null = null; // physical parent + parent: number | null = null; // Physical parent children: number[] = []; - antecedent: number | null = null; // logical parent + antecedent: number | null = null; // Logical parent decomposition: Set<number> = new Set(); - // For Davis Puttnam reduction + // For Davis Putnam reduction antecedentsDP: Set<number> = new Set(); + private _correctDecomposition: Set<number> | null = null; /** @@ -153,6 +146,7 @@ export class TruthTreeNode { newNode.text = this.text; newNode.premise = this.premise; newNode.isTautology = this.isTautology; + newNode.isBranchLiteral = this.isBranchLiteral; newNode.comment = this.comment; newNode.parent = this.parent; newNode.children = [...this.children]; @@ -585,23 +579,15 @@ export class TruthTreeNode { } isDPValid(): Response { - // For DP - check statement logically follows from antecedent + branch + // For DP: check statement logically follows from antecedent using branch // TODO: ensure this only gets checked when DP in DP mode + if (!this._statement) { // TODO: change error return new CorrectnessError('not_parsable'); } - // this._statement ==> conclusion - // leftNode._statement ==> literal - // rightNode._statement ==> statement to reduce let antecedentArr = Array.from(this.antecedentsDP); - - console.log( - 'isDPvalid arr length', - this._statement.toString(), - antecedentArr.length - ); if (antecedentArr.length == 2) { let left = antecedentArr[0]; let right = antecedentArr[1]; @@ -668,8 +654,7 @@ export class TruthTreeNode { return true; } - // return this.isDPValid(); - // // TODO: DP mode + // TODO: DP mode if (this.isDPValid() === true) { return true; } @@ -773,15 +758,9 @@ export class TruthTreeNode { * @returns true if this closed terminator is valid, false otherwise */ private isClosedTerminatorValid(): Response { - // ***another DP mode thing*** - const antecedentsDPArray = Array.from(this.antecedentsDP); - if (antecedentsDPArray.length > 0) { - const antecedent = this.tree.nodes[antecedentsDPArray[0]]; - if (antecedent.statement instanceof Contradiction) { - return true; - } - - new CorrectnessError('closed_not_contradiction'); + // TODO: DP mode + if (this.antecedent && this.tree.nodes[this.antecedent].statement instanceof Contradiction) { + return true; } // Closed terminators must reference exactly two statements @@ -834,15 +813,19 @@ export class TruthTreeNode { return new CorrectnessError('closed_not_contradiction'); } + /** + * Determines whether or not a statement has been reduced completely. This is + * done by checking to make sure every statement in its decomposition is valid. + * @returns true if this statement is fully reduced, false otherwise + */ isReduced(): Response { - // we would like to check the two decompositions are correct + // We would like to check the two decompositions are correct const decompArray = Array.from(this.decomposition); if (decompArray.length != 2) { return new CorrectnessError('invalid_decomposition'); } const s1 = this.tree.nodes[decompArray[0]]; const s2 = this.tree.nodes[decompArray[1]]; - if (s1.isDPValid() && s2.isDPValid()) { return true; } @@ -886,6 +869,7 @@ export class TruthTreeNode { } } + // TODO: for non-DP mode, uncommment the below code return this.isReduced(); // This statement must be decomposed in every non-closed branch that @@ -1050,7 +1034,6 @@ export class TruthTreeNode { if (this.premise) { return 'This statement is a premise.'; } - if (this.isTautology) { return 'This statement is a tautology.'; } @@ -1260,7 +1243,7 @@ export class TruthTree { text: node.text, children: node.children, decomposition: [...node.decomposition], - antecedentsDP: [...node.antecedentsDP], + antecedentsDP: [...node.antecedentsDP], // TODO: add other DP mode variables here }; if (node.premise) { @@ -1904,9 +1887,10 @@ export class TruthTree { } const decomposedNode = this.nodes[decomposedId]; - // **potentially for DP node** + // TODO: DP mode + // Don't worry about a contradiction's antecedents since it technically + // has more than one if (decomposedNode.statement instanceof Contradiction) { - console.log("herrreeee", node.id, decomposedNode.statement.toString()); continue; } From 242482a0757e912de7ab7dfcdd1526110d2d14c4 Mon Sep 17 00:00:00 2001 From: jssunray34 <55996087+jssunray34@users.noreply.github.com> Date: Wed, 26 Apr 2023 01:00:14 -0400 Subject: [PATCH 30/54] Remove debug prints --- src/client/component/truth-tree-node.ts | 8 -------- 1 file changed, 8 deletions(-) diff --git a/src/client/component/truth-tree-node.ts b/src/client/component/truth-tree-node.ts index e4f3424..f6ef242 100644 --- a/src/client/component/truth-tree-node.ts +++ b/src/client/component/truth-tree-node.ts @@ -97,14 +97,6 @@ export const TruthTreeNodeComponent = defineComponent({ JSON.stringify(node.universe.map(formula => formula.toString())) }} </span> - <span> - id: {{ id }}, - valid: {{ node.isValid() }}, - decomposed: {{ node.isDecomposed() }}, - decomposition: {{ node.decomposition }}, - antecedentsDP: {{ node.antecedentsDP }}, - antecedent: {{ node.antecedent }}, - </span> <i :class="getNodeIconClasses(node)" :title="node.getFeedback()"></i> <input :id="'node' + this.id" type="text" v-model="node.text" @focus="$store.commit('select', {id: id, focus: false})" From 578b224bf30d540a7d2444c8a95fd77b4a747e2f Mon Sep 17 00:00:00 2001 From: jssunray34 <55996087+jssunray34@users.noreply.github.com> Date: Wed, 26 Apr 2023 11:15:32 -0400 Subject: [PATCH 31/54] Fix branch literal check --- src/client/component/truth-tree-branch.ts | 21 ++++++++++++++++++--- src/common/tree.ts | 5 +++++ 2 files changed, 23 insertions(+), 3 deletions(-) diff --git a/src/client/component/truth-tree-branch.ts b/src/client/component/truth-tree-branch.ts index 2b97c87..b4bb1fc 100644 --- a/src/client/component/truth-tree-branch.ts +++ b/src/client/component/truth-tree-branch.ts @@ -101,11 +101,26 @@ export const TruthTreeBranchComponent = defineComponent({ // Otherwise add the right clicked node to the current node's antecedents list selectedNode.antecedentsDP.add(id); + if (selectedNode.statement) { + console.log("selected", otherNode.statement?.decompose()); + } + + let isBranch = false; + if (otherNode.statement instanceof OrStatement && selectedNode.statement) { + const lhs = otherNode.statement.operands[0]; + const rhs = otherNode.statement.operands[1]; + if (lhs.equals(selectedNode.statement)) { + isBranch = true; + } else if (rhs.equals(selectedNode.statement)) { + isBranch = true; + } + } + // If the selected node is a branch literal, specify it as such and clear out its decomposition if ( otherNode.statement?.isTautology() && selectedNode.statement != null && - otherNode.statement.equals(new OrStatement(selectedNode.statement, new NotStatement(selectedNode.statement))) + isBranch == true ) { selectedNode.isBranchLiteral = true; selectedNode.decomposition.clear(); @@ -267,12 +282,12 @@ export const TruthTreeBranchComponent = defineComponent({ selectedNode != null && selectedNode.antecedentsDP.has(id) && $store.state.tree.nodes[id]._statement != null && - !$store.state.tree.nodes[id]._statement.isLiteral(), + !$store.state.tree.nodes[id].isBranchLiteral, 'antecedents-DP-branch': selectedNode != null && selectedNode.antecedentsDP.has(id) && $store.state.tree.nodes[id]._statement != null && - $store.state.tree.nodes[id]._statement.isLiteral(), + $store.state.tree.nodes[id].isBranchLiteral, decomposition: selectedNode !== null && selectedNode.decomposition.has(id), diff --git a/src/common/tree.ts b/src/common/tree.ts index ca455b9..dbef782 100644 --- a/src/common/tree.ts +++ b/src/common/tree.ts @@ -212,6 +212,10 @@ export class TruthTreeNode { newNode.premise = jsonObject.premise; } + if ('isBranchLiteral' in jsonObject && typeof jsonObject.isBranchLiteral === 'boolean') { + newNode.isBranchLiteral = jsonObject.isBranchLiteral; + } + if ('comment' in jsonObject && typeof jsonObject.comment === 'string') { newNode.comment = jsonObject.comment; } @@ -1244,6 +1248,7 @@ export class TruthTree { children: node.children, decomposition: [...node.decomposition], antecedentsDP: [...node.antecedentsDP], // TODO: add other DP mode variables here + isBranchLiteral: node.isBranchLiteral }; if (node.premise) { From 77f64c420716f2a34e798a354f0b2f34b20164b6 Mon Sep 17 00:00:00 2001 From: jssunray34 <55996087+jssunray34@users.noreply.github.com> Date: Wed, 26 Apr 2023 11:21:05 -0400 Subject: [PATCH 32/54] Update decomposition text TODO: make this only render if in DP mode --- public/css/index.css | 9 +++++++++ src/client/component/truth-tree-branch.ts | 3 +++ 2 files changed, 12 insertions(+) diff --git a/public/css/index.css b/public/css/index.css index 7cad5e8..6ffc335 100644 --- a/public/css/index.css +++ b/public/css/index.css @@ -140,6 +140,15 @@ transform: translateY(-50%); } +.decomposition-DP::after { + content: 'reduces to'; + font-style: italic; + position: absolute; + top: 50%; + right: 10px; + transform: translateY(-50%); +} + .closing-terminator-decomposition::after { content: 'is a result of'; } diff --git a/src/client/component/truth-tree-branch.ts b/src/client/component/truth-tree-branch.ts index b4bb1fc..f5741af 100644 --- a/src/client/component/truth-tree-branch.ts +++ b/src/client/component/truth-tree-branch.ts @@ -291,6 +291,9 @@ export const TruthTreeBranchComponent = defineComponent({ decomposition: selectedNode !== null && selectedNode.decomposition.has(id), + 'decomposition-DP': + selectedNode !== null && + selectedNode.decomposition.has(id), 'closing-terminator-decomposition': selectedNode !== null && selectedNode.decomposition.has(id) && From 661d774d8c0019e1b94066cb89e66e68226a122b Mon Sep 17 00:00:00 2001 From: jssunray34 <55996087+jssunray34@users.noreply.github.com> Date: Wed, 26 Apr 2023 11:26:05 -0400 Subject: [PATCH 33/54] Code cleanup --- src/client/component/truth-tree-branch.ts | 5 +---- src/common/statement.ts | 5 ----- 2 files changed, 1 insertion(+), 9 deletions(-) diff --git a/src/client/component/truth-tree-branch.ts b/src/client/component/truth-tree-branch.ts index f5741af..3bbf4a2 100644 --- a/src/client/component/truth-tree-branch.ts +++ b/src/client/component/truth-tree-branch.ts @@ -101,10 +101,7 @@ export const TruthTreeBranchComponent = defineComponent({ // Otherwise add the right clicked node to the current node's antecedents list selectedNode.antecedentsDP.add(id); - if (selectedNode.statement) { - console.log("selected", otherNode.statement?.decompose()); - } - + // Determine whether the selected statement is a branch literal let isBranch = false; if (otherNode.statement instanceof OrStatement && selectedNode.statement) { const lhs = otherNode.statement.operands[0]; diff --git a/src/common/statement.ts b/src/common/statement.ts index 8e68ef2..9b4b2cc 100644 --- a/src/common/statement.ts +++ b/src/common/statement.ts @@ -780,11 +780,6 @@ export class DPStatementReducer { rhs = new_operand; } } - console.log( - 'Conditional statements REDUCED', - lhs.toString(), - rhs.toString() - ); // Second part of or is when assertions get absorbed by intermediate steps if (assertion.equals(lhs) || lhs instanceof Tautology) { From 9d54094d1a5da7239947c1d296b5f4d226ec05cc Mon Sep 17 00:00:00 2001 From: jssunray34 <55996087+jssunray34@users.noreply.github.com> Date: Wed, 26 Apr 2023 11:27:01 -0400 Subject: [PATCH 34/54] prettier --- src/client/component/truth-tree-branch.ts | 5 ++++- src/common/parser.ts | 4 ++-- src/common/tree.ts | 16 ++++++++++------ 3 files changed, 16 insertions(+), 9 deletions(-) diff --git a/src/client/component/truth-tree-branch.ts b/src/client/component/truth-tree-branch.ts index 3bbf4a2..9d5ca58 100644 --- a/src/client/component/truth-tree-branch.ts +++ b/src/client/component/truth-tree-branch.ts @@ -103,7 +103,10 @@ export const TruthTreeBranchComponent = defineComponent({ // Determine whether the selected statement is a branch literal let isBranch = false; - if (otherNode.statement instanceof OrStatement && selectedNode.statement) { + if ( + otherNode.statement instanceof OrStatement && + selectedNode.statement + ) { const lhs = otherNode.statement.operands[0]; const rhs = otherNode.statement.operands[1]; if (lhs.equals(selectedNode.statement)) { diff --git a/src/common/parser.ts b/src/common/parser.ts index 4861a14..00e147e 100644 --- a/src/common/parser.ts +++ b/src/common/parser.ts @@ -317,7 +317,7 @@ export class PropositionalLogicParser extends Parser<Statement> { or: ['∨', '|', 'or'], not: ['¬', '!', '~', 'not'], taut: ['⊤'], - con: ['⊥'] + con: ['⊥'], }; start(): Statement { @@ -549,7 +549,7 @@ export class FirstOrderLogicParser extends PropositionalLogicParser { or: ['∨', '|', 'or'], not: ['¬', '!', '~', 'not'], taut: ['⊤'], - con: ['⊥'] + con: ['⊥'], }; unaryExpression(): Statement { diff --git a/src/common/tree.ts b/src/common/tree.ts index dbef782..d44b172 100644 --- a/src/common/tree.ts +++ b/src/common/tree.ts @@ -10,9 +10,7 @@ import { DPStatementValidator, Contradiction, } from './statement'; -import { - EvaluationResponse, -} from './util'; +import {EvaluationResponse} from './util'; export class CorrectnessError { errorCode: string; @@ -212,7 +210,10 @@ export class TruthTreeNode { newNode.premise = jsonObject.premise; } - if ('isBranchLiteral' in jsonObject && typeof jsonObject.isBranchLiteral === 'boolean') { + if ( + 'isBranchLiteral' in jsonObject && + typeof jsonObject.isBranchLiteral === 'boolean' + ) { newNode.isBranchLiteral = jsonObject.isBranchLiteral; } @@ -763,7 +764,10 @@ export class TruthTreeNode { */ private isClosedTerminatorValid(): Response { // TODO: DP mode - if (this.antecedent && this.tree.nodes[this.antecedent].statement instanceof Contradiction) { + if ( + this.antecedent && + this.tree.nodes[this.antecedent].statement instanceof Contradiction + ) { return true; } @@ -1248,7 +1252,7 @@ export class TruthTree { children: node.children, decomposition: [...node.decomposition], antecedentsDP: [...node.antecedentsDP], // TODO: add other DP mode variables here - isBranchLiteral: node.isBranchLiteral + isBranchLiteral: node.isBranchLiteral, }; if (node.premise) { From c6b459364e66ffe021e4d1c5c44bc4ab36b55b64 Mon Sep 17 00:00:00 2001 From: Jody Sunray <55996087+jssunray34@users.noreply.github.com> Date: Wed, 26 Apr 2023 11:41:18 -0400 Subject: [PATCH 35/54] Update DP_developer_guide.md --- DP_developer_guide.md | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/DP_developer_guide.md b/DP_developer_guide.md index 41f1568..477d4a5 100644 --- a/DP_developer_guide.md +++ b/DP_developer_guide.md @@ -18,13 +18,23 @@ When designing an implementation of Davis-Putnam (DP) supported by Willow, we wa 2. Support for contradiction (⊥) and tautology (⊤) symbols 3. Support for basic tautological statement (A ∨ ¬A) 4. Functional frontend to that supports both DP and truth-tree methods -5. Minor language changes to tree node labels and status bar -6. Statement validation for DP -7. Statement decomposition checks for DP -8. Testing for the reduction rules +5. Create a new version of `modifyDecomposition` to store and update antecedents called `modifyAntecedentsDP` +6. Statement validation for DP (`isDPValid`, which calls `validateReduction`) +7. Statement decomposition checks for DP (checks that it has two statements in its decomposition, and they are both valid inferences) +8. Extensive testing of reduction rules (`tests/reductionRules.test.ts`) +9. Updated tree node highlighting and labeling: We simply applied the existing color scheme to the new DP functionality, with a couple language changes in the labels. As with Willow's truth-tree, when any statement is selected, there may be both red and green highlighting: + + 1. Statements highlighted in *green* indicate *antecedents* of the currently selected node. Non-branch literals are labeled as "reduces from," and branch literals are labeled as "using." This behavior is still not perfect, specifically when deciding when display either of these labels, as we had some difficulty marking statements as branch literals. + 2. Statements highlighted in *red* indicate those that *reduce* from the currently selected node. There may be zero, one, or two nodes in any given decomposition. Each node in the decomposition will be labeled with the text "reduces to." + +9. Updated status bar labeling +10. Support for saving and reopening files that use the DP method +11. Visual testing on simple examples and an example from class ## Tasks that still need to be completed The implementation of DP in Willow is completely usable in its current state. However, there are a few action items that we were not able to get to, and more thorough testing will need to be done to ensure that the feature is production-ready. 1. Handle lingering statements that have not been fully decomposed +2. Ensure all the labels are correct when a statement is selected +3. Perform additional testing From b580623ac5da7b747785de1f571e557e9c6638d9 Mon Sep 17 00:00:00 2001 From: Jody Sunray <55996087+jssunray34@users.noreply.github.com> Date: Wed, 26 Apr 2023 14:24:59 -0400 Subject: [PATCH 36/54] Update README --- DP_developer_guide.md | 83 ++++++++++++++++++++++++++++++++++--------- 1 file changed, 66 insertions(+), 17 deletions(-) diff --git a/DP_developer_guide.md b/DP_developer_guide.md index 477d4a5..6f00b57 100644 --- a/DP_developer_guide.md +++ b/DP_developer_guide.md @@ -1,10 +1,17 @@ # Davis-Putnam Developer's Guide +*This feature was implemented as a final project by Jenny Gao, Mason LeBouf, and Jody Sunray for Bram van Heuveln's Spring 2023 Computability and Logic course at RPI.* + ## Changes to existing functionality When designing an implementation of Davis-Putnam (DP) supported by Willow, we wanted to utilize as much of the existing functionality as possible. Below are the major changes and additions that were made. -1. **Implementation of the reduction rules for each type of statement:** These rules were used to reduce statements given the truth value of a literal. The reduction rules are as follows. +1. **By default two branches are created**: This feature was not a requirement for our project, but it made our lives easier. Plus, it was requested by Bram. :) + +https://user-images.githubusercontent.com/55996087/234662990-85eb9160-8ba4-4c81-a45a-d7121f7adbcc.mov + + +1. **Implementation of the reduction rules for each type of statement**: These rules were used to reduce statements given the truth value of a literal. The reduction rules are as follows. | Not | And | Or | Conditional | Biconditional | | --------- | ----------- |------------ | ----------- | ------------- | @@ -15,26 +22,68 @@ When designing an implementation of Davis-Putnam (DP) supported by Willow, we wa For example, given the statement A ∧ B and the literal B, we can reduce to the atomic statement A. Rules like this were used to verify whether the statement a user has inputted is indeed a valid inference. -2. Support for contradiction (⊥) and tautology (⊤) symbols -3. Support for basic tautological statement (A ∨ ¬A) -4. Functional frontend to that supports both DP and truth-tree methods -5. Create a new version of `modifyDecomposition` to store and update antecedents called `modifyAntecedentsDP` -6. Statement validation for DP (`isDPValid`, which calls `validateReduction`) -7. Statement decomposition checks for DP (checks that it has two statements in its decomposition, and they are both valid inferences) -8. Extensive testing of reduction rules (`tests/reductionRules.test.ts`) -9. Updated tree node highlighting and labeling: We simply applied the existing color scheme to the new DP functionality, with a couple language changes in the labels. As with Willow's truth-tree, when any statement is selected, there may be both red and green highlighting: - - 1. Statements highlighted in *green* indicate *antecedents* of the currently selected node. Non-branch literals are labeled as "reduces from," and branch literals are labeled as "using." This behavior is still not perfect, specifically when deciding when display either of these labels, as we had some difficulty marking statements as branch literals. - 2. Statements highlighted in *red* indicate those that *reduce* from the currently selected node. There may be zero, one, or two nodes in any given decomposition. Each node in the decomposition will be labeled with the text "reduces to." +2. **Support for contradiction (⊥) and tautology (⊤) symbols**: Since our implementation relies on the use of ⊥ and ⊤, we added support for these symbols by adding them to `parser.ts`. Thus, when a user inputs a ⊥, it is treated as a `Contradiction` statement. Similarly, when a user inputs a ⊤, it is treated as a `Tautology` statement. We also created shortcuts for these symbols; the minus sign (-) is a shortcut for ⊥, and the plus sign (+) is a shortcut for ⊤. + + <img width="944" alt="Screenshot 2023-04-26 at 12 29 47 PM" src="https://user-images.githubusercontent.com/55996087/234641790-b3f1955d-282c-48c5-9a38-cb3453b8fedc.png"> + +4. **Support for basic tautological statement (A ∨ ¬A)**: In order to be able to branch on a particular literal, we rely on the use of the basic tautological statement, which is the law of excluded middle. This statement is valid by default since all tautologies are valid, and is only marked with a green check if it has been decomposed into two branches A and ¬A. + + <img width="945" alt="Screenshot 2023-04-26 at 12 31 19 PM" src="https://user-images.githubusercontent.com/55996087/234642070-23daacd9-c597-4b24-9baf-b2a662150b88.png"> + +6. **Functional frontend to that supports both DP and truth-tree methods**: We decided that the DP method should be a separate mode on the Willow site, so that by default users interact with the original truth-tree method. To achieve this, we created a toggle in the menu bar. When clicked, the toggle sets a state variable `DPMode` to `true` or `false`. The value of this variable controls whether certain code additions will be run or not. + + <img width="947" alt="Screenshot 2023-04-26 at 12 32 01 PM" src="https://user-images.githubusercontent.com/55996087/234642243-2d97c0e4-72c4-4fb9-b5d5-90a56e414893.png"> + +8. **Create a new version of `modifyDecomposition` to store and update antecedents called `modifyAntecedentsDP`**: When a user selects a particular statement and then right clicks on another, the `modifyDecomposition` function is called to update logical relationships within the tree, specifically a statement's decomposition and antecedents. For DP mode, we modify this function (and call it `modifyAntecedentsDP`). The main additional functionality of this function is to update the selected statement's antecedents, i.e., the statement it is reducing from and the literal it is branching on. + +10. **Statement validation for DP (`isDPValid`, which calls `validateReduction`)**: A statement is considered a valid inference if it follows from one of the reduction rules listed above. Since validation for DP differs from validation for truth trees, we decided to create a separate function called `isDPValid`. This function checks whether a statement is valid given its antecedents (i.e., the statement it is reduced from and the branch literal). + + In the image below, the selected statement (highlighted in blue) is valid since it is a correct inference of H ∧ (I → F) given that we have taken the H branch (i.e., H is true). + + <img width="943" alt="Screenshot 2023-04-26 at 1 42 55 PM" src="https://user-images.githubusercontent.com/55996087/234659503-bd690ee8-9c1a-4fe1-a483-a827b6ef6990.png"> + +12. **Statement decomposition checks for DP (checks that it has two statements in its decomposition, and they are both valid inferences)**: In addition to validating a statement, we also check that it has been reduced. This is similar to the checks being done for the truth tree method, i.e., a statement is only marked with a green check if it is both valid *and* decomposed completely. To verify that a statement has been reduced, we make sure that it has exactly two statements in its decomposition, and every statement in its decomposition is valid. + + In the image below, the selected statement is not only valid but also reduced since both statements in its decomposition (⊤ and ¬I) are valid. Thus, because the selected statement is both valid and decomposed correctly, it is marked with a green check. + +<img width="945" alt="Screenshot 2023-04-26 at 1 47 13 PM" src="https://user-images.githubusercontent.com/55996087/234660442-996768f7-969a-4b37-aeca-e2a265da7980.png"> + +13. **Support for closed terminator**: We modified the `isClosedTerminatorValid()` function to validate a closed terminal when its antecedent is a contradiction. + + In the image below, the terminator is considered valid since it reduces from a contradiction (⊥). + + <img width="943" alt="Screenshot 2023-04-26 at 2 16 45 PM" src="https://user-images.githubusercontent.com/55996087/234666728-048283bb-dae8-434d-8cc4-02352c5c09f0.png"> + +14. **Extensive testing of reduction rules (`tests/reductionRules.test.ts`)**: After implementing the reduction rules listed above, we created a test suite that tests each one works as expected since these rules are crucial to the rest of the implentation of the DP method. This test suite can be run using the command `npm run test`, which runs all tests. + +16. **Updated tree node highlighting and labeling**: We simply applied the existing color scheme to the new DP functionality, with a couple language changes in the labels. As with Willow's truth tree method, when any statement is selected, there may be both red and green highlighting: + + 1. *Statements highlighted in **green** indicate **antecedents*** of the currently selected node. Non-branch literals are labeled as "reduces from," and branch literals are labeled as "using." + 2. *Statements highlighted in **red** indicate those that **reduce*** from the currently selected node. There may be zero, one, or two nodes in any given decomposition. Each node in the decomposition will be labeled with the text "reduces to." -9. Updated status bar labeling -10. Support for saving and reopening files that use the DP method -11. Visual testing on simple examples and an example from class +9. **Updated status bar labeling**: In addition to modifying the tree node labels, we also modified the language in the status bar in addition to adding new statuses. For example, a tautology has a status to indicate it as such: + +<img width="945" alt="Screenshot 2023-04-26 at 2 07 03 PM" src="https://user-images.githubusercontent.com/55996087/234664782-06325497-7f45-4849-8b61-814afb03cd20.png"> + +11. **Support for saving and reopening files that use the DP method**: When testing our implementation on larger examples, it became tedious to have to retype the example each time the application is rerun. To resolve this, we modified the `serialize()` and `fromJSON()` functions to account for any variables we added for DP mode. This allows trees that implement DP to be saved and later reopened. + +13. **Visual testing on simple examples and an example from class**: We based a lot of our preliminary tests using a small example as shown below. + + <img width="944" alt="Screenshot 2023-04-26 at 2 21 01 PM" src="https://user-images.githubusercontent.com/55996087/234667725-e87636d0-8dfb-44bd-bd7c-71b5fc8574c3.png"> + + This example has only open branches, and it's fairly simple, so we did additional tests using an example from homework 4, as shown below. + + <img width="944" alt="Screenshot 2023-04-26 at 2 23 21 PM" src="https://user-images.githubusercontent.com/55996087/234668290-0666b233-f78c-4d57-99dc-8cd0b1dca282.png"> + <img width="944" alt="Screenshot 2023-04-26 at 2 23 39 PM" src="https://user-images.githubusercontent.com/55996087/234668319-af5684a3-772c-4de7-84c2-ffd0d3b647c7.png"> + <img width="941" alt="Screenshot 2023-04-26 at 2 23 47 PM" src="https://user-images.githubusercontent.com/55996087/234668346-8bcf3eab-2089-4b64-b226-5790ee3c4e8c.png"> ## Tasks that still need to be completed The implementation of DP in Willow is completely usable in its current state. However, there are a few action items that we were not able to get to, and more thorough testing will need to be done to ensure that the feature is production-ready. 1. Handle lingering statements that have not been fully decomposed -2. Ensure all the labels are correct when a statement is selected -3. Perform additional testing + + <img width="943" alt="Screenshot 2023-04-26 at 1 34 59 PM" src="https://user-images.githubusercontent.com/55996087/234657144-c56b4be0-49cc-46c0-aef2-215da6825f84.png"> + +3. Ensure all the labels are correct when a statement is selected +4. Perform additional testing (bug hunting) From bb457a9b60c8d38a9947d08e7eaaff2d320a37f9 Mon Sep 17 00:00:00 2001 From: Jody Sunray <55996087+jssunray34@users.noreply.github.com> Date: Wed, 26 Apr 2023 14:27:17 -0400 Subject: [PATCH 37/54] Update README --- DP_developer_guide.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/DP_developer_guide.md b/DP_developer_guide.md index 6f00b57..f14e534 100644 --- a/DP_developer_guide.md +++ b/DP_developer_guide.md @@ -8,7 +8,7 @@ When designing an implementation of Davis-Putnam (DP) supported by Willow, we wa 1. **By default two branches are created**: This feature was not a requirement for our project, but it made our lives easier. Plus, it was requested by Bram. :) -https://user-images.githubusercontent.com/55996087/234662990-85eb9160-8ba4-4c81-a45a-d7121f7adbcc.mov + https://user-images.githubusercontent.com/55996087/234662990-85eb9160-8ba4-4c81-a45a-d7121f7adbcc.mov 1. **Implementation of the reduction rules for each type of statement**: These rules were used to reduce statements given the truth value of a literal. The reduction rules are as follows. @@ -46,13 +46,13 @@ https://user-images.githubusercontent.com/55996087/234662990-85eb9160-8ba4-4c81- In the image below, the selected statement is not only valid but also reduced since both statements in its decomposition (⊤ and ¬I) are valid. Thus, because the selected statement is both valid and decomposed correctly, it is marked with a green check. -<img width="945" alt="Screenshot 2023-04-26 at 1 47 13 PM" src="https://user-images.githubusercontent.com/55996087/234660442-996768f7-969a-4b37-aeca-e2a265da7980.png"> + <img width="945" alt="Screenshot 2023-04-26 at 1 47 13 PM" src="https://user-images.githubusercontent.com/55996087/234660442-996768f7-969a-4b37-aeca-e2a265da7980.png"> 13. **Support for closed terminator**: We modified the `isClosedTerminatorValid()` function to validate a closed terminal when its antecedent is a contradiction. - In the image below, the terminator is considered valid since it reduces from a contradiction (⊥). + In the image below, the terminator is considered valid since it reduces from a contradiction (⊥). - <img width="943" alt="Screenshot 2023-04-26 at 2 16 45 PM" src="https://user-images.githubusercontent.com/55996087/234666728-048283bb-dae8-434d-8cc4-02352c5c09f0.png"> + <img width="943" alt="Screenshot 2023-04-26 at 2 16 45 PM" src="https://user-images.githubusercontent.com/55996087/234666728-048283bb-dae8-434d-8cc4-02352c5c09f0.png"> 14. **Extensive testing of reduction rules (`tests/reductionRules.test.ts`)**: After implementing the reduction rules listed above, we created a test suite that tests each one works as expected since these rules are crucial to the rest of the implentation of the DP method. This test suite can be run using the command `npm run test`, which runs all tests. @@ -63,7 +63,7 @@ https://user-images.githubusercontent.com/55996087/234662990-85eb9160-8ba4-4c81- 9. **Updated status bar labeling**: In addition to modifying the tree node labels, we also modified the language in the status bar in addition to adding new statuses. For example, a tautology has a status to indicate it as such: -<img width="945" alt="Screenshot 2023-04-26 at 2 07 03 PM" src="https://user-images.githubusercontent.com/55996087/234664782-06325497-7f45-4849-8b61-814afb03cd20.png"> + <img width="945" alt="Screenshot 2023-04-26 at 2 07 03 PM" src="https://user-images.githubusercontent.com/55996087/234664782-06325497-7f45-4849-8b61-814afb03cd20.png"> 11. **Support for saving and reopening files that use the DP method**: When testing our implementation on larger examples, it became tedious to have to retype the example each time the application is rerun. To resolve this, we modified the `serialize()` and `fromJSON()` functions to account for any variables we added for DP mode. This allows trees that implement DP to be saved and later reopened. From 00312a8afd754356db7699961244017e36f5f109 Mon Sep 17 00:00:00 2001 From: Jody Sunray <55996087+jssunray34@users.noreply.github.com> Date: Wed, 26 Apr 2023 14:30:13 -0400 Subject: [PATCH 38/54] Update README --- DP_developer_guide.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/DP_developer_guide.md b/DP_developer_guide.md index f14e534..a083d6f 100644 --- a/DP_developer_guide.md +++ b/DP_developer_guide.md @@ -1,6 +1,6 @@ # Davis-Putnam Developer's Guide -*This feature was implemented as a final project by Jenny Gao, Mason LeBouf, and Jody Sunray for Bram van Heuveln's Spring 2023 Computability and Logic course at RPI.* +*This feature was implemented as a final project by Jenny Gao, Mason duBoef, and Jody Sunray for Bram van Heuveln's Spring 2023 Computability and Logic course at RPI.* ## Changes to existing functionality From 8bd4f5a0defb906dd3531fdebba10d3cc76f904c Mon Sep 17 00:00:00 2001 From: Jody Sunray <55996087+jssunray34@users.noreply.github.com> Date: Wed, 26 Apr 2023 14:35:36 -0400 Subject: [PATCH 39/54] Fix typos in developer README --- DP_developer_guide.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/DP_developer_guide.md b/DP_developer_guide.md index a083d6f..394dd33 100644 --- a/DP_developer_guide.md +++ b/DP_developer_guide.md @@ -30,13 +30,13 @@ When designing an implementation of Davis-Putnam (DP) supported by Willow, we wa <img width="945" alt="Screenshot 2023-04-26 at 12 31 19 PM" src="https://user-images.githubusercontent.com/55996087/234642070-23daacd9-c597-4b24-9baf-b2a662150b88.png"> -6. **Functional frontend to that supports both DP and truth-tree methods**: We decided that the DP method should be a separate mode on the Willow site, so that by default users interact with the original truth-tree method. To achieve this, we created a toggle in the menu bar. When clicked, the toggle sets a state variable `DPMode` to `true` or `false`. The value of this variable controls whether certain code additions will be run or not. +6. **Functional frontend that supports both DP and truth-tree methods**: We decided that the DP method should be a separate mode on the Willow site, so that by default users interact with the original truth tree method. To achieve this, we created a toggle in the menu bar. When clicked, the toggle sets a state variable `DPMode` to `true` or `false`. The value of this variable controls whether certain code additions will be run or not. <img width="947" alt="Screenshot 2023-04-26 at 12 32 01 PM" src="https://user-images.githubusercontent.com/55996087/234642243-2d97c0e4-72c4-4fb9-b5d5-90a56e414893.png"> 8. **Create a new version of `modifyDecomposition` to store and update antecedents called `modifyAntecedentsDP`**: When a user selects a particular statement and then right clicks on another, the `modifyDecomposition` function is called to update logical relationships within the tree, specifically a statement's decomposition and antecedents. For DP mode, we modify this function (and call it `modifyAntecedentsDP`). The main additional functionality of this function is to update the selected statement's antecedents, i.e., the statement it is reducing from and the literal it is branching on. -10. **Statement validation for DP (`isDPValid`, which calls `validateReduction`)**: A statement is considered a valid inference if it follows from one of the reduction rules listed above. Since validation for DP differs from validation for truth trees, we decided to create a separate function called `isDPValid`. This function checks whether a statement is valid given its antecedents (i.e., the statement it is reduced from and the branch literal). +10. **Statement validation for DP (`isDPValid`, which calls `validateReduction`)**: A statement is considered a valid inference if it follows from one of the reduction rules listed above. Since validation for DP differs from validation for truth trees, we decided to create a separate function called `isDPValid()`. This function checks whether a statement is valid given its antecedents (i.e., the statement it is reduced from and the branch literal). In the image below, the selected statement (highlighted in blue) is valid since it is a correct inference of H ∧ (I → F) given that we have taken the H branch (i.e., H is true). @@ -54,14 +54,14 @@ When designing an implementation of Davis-Putnam (DP) supported by Willow, we wa <img width="943" alt="Screenshot 2023-04-26 at 2 16 45 PM" src="https://user-images.githubusercontent.com/55996087/234666728-048283bb-dae8-434d-8cc4-02352c5c09f0.png"> -14. **Extensive testing of reduction rules (`tests/reductionRules.test.ts`)**: After implementing the reduction rules listed above, we created a test suite that tests each one works as expected since these rules are crucial to the rest of the implentation of the DP method. This test suite can be run using the command `npm run test`, which runs all tests. +14. **Extensive testing of reduction rules (`tests/reductionRules.test.ts`)**: After implementing the reduction rules listed above, we created a test suite that tests each one works as expected since these rules are crucial to the rest of the implementation of the DP method. This test suite can be run using the command `npm run test`, which runs all tests. -16. **Updated tree node highlighting and labeling**: We simply applied the existing color scheme to the new DP functionality, with a couple language changes in the labels. As with Willow's truth tree method, when any statement is selected, there may be both red and green highlighting: +16. **Updated tree node highlighting and labeling**: We simply applied the existing color scheme to the new DP functionality, with a couple language changes in the labels. As with Willow's truth tree method, when any statement is selected, there may be both green and red highlighting: 1. *Statements highlighted in **green** indicate **antecedents*** of the currently selected node. Non-branch literals are labeled as "reduces from," and branch literals are labeled as "using." 2. *Statements highlighted in **red** indicate those that **reduce*** from the currently selected node. There may be zero, one, or two nodes in any given decomposition. Each node in the decomposition will be labeled with the text "reduces to." -9. **Updated status bar labeling**: In addition to modifying the tree node labels, we also modified the language in the status bar in addition to adding new statuses. For example, a tautology has a status to indicate it as such: +9. **Updated status bar labeling**: In addition to modifying the tree node labels, we also modified the language in the status bar as well as added new statuses. For example, a tautology has a status to indicate it as such: <img width="945" alt="Screenshot 2023-04-26 at 2 07 03 PM" src="https://user-images.githubusercontent.com/55996087/234664782-06325497-7f45-4849-8b61-814afb03cd20.png"> From b106f0e2ff7bb7ea06995a8375cde81e76b953e0 Mon Sep 17 00:00:00 2001 From: mduboef <mduboef@gmail.com> Date: Thu, 27 Apr 2023 03:20:12 -0400 Subject: [PATCH 40/54] Global button --- Willow | 1 + 1 file changed, 1 insertion(+) create mode 160000 Willow diff --git a/Willow b/Willow new file mode 160000 index 0000000..1b508ec --- /dev/null +++ b/Willow @@ -0,0 +1 @@ +Subproject commit 1b508ecc95ef8dbdbf4eea875cdc67f3fd291363 From 1c6fa21de0b3e6ebf1e34a9cf6296c6eb28dd3e2 Mon Sep 17 00:00:00 2001 From: Mason duBoef <mduboef@gmail.com> Date: Thu, 27 Apr 2023 03:32:07 -0400 Subject: [PATCH 41/54] Make button global --- src/client/globals.ts | 9 + src/client/index.ts | 13 +- src/common/tree.ts | 414 ++++++++++++++++++++++++------------------ views/index.pug | 10 +- 4 files changed, 257 insertions(+), 189 deletions(-) create mode 100644 src/client/globals.ts diff --git a/src/client/globals.ts b/src/client/globals.ts new file mode 100644 index 0000000..9463395 --- /dev/null +++ b/src/client/globals.ts @@ -0,0 +1,9 @@ +let dpMode = true; + +export function setDPMode(value: boolean) { + dpMode = value; +} + +export function getDPMode() { + return dpMode; +} diff --git a/src/client/index.ts b/src/client/index.ts index 89e3de2..9484b67 100644 --- a/src/client/index.ts +++ b/src/client/index.ts @@ -7,6 +7,7 @@ import {TruthTreeBranchComponent} from './component/truth-tree-branch'; import {getNodeIconClasses} from './component/truth-tree-node'; import {Assignment} from '../types/routes/index/assignment'; import {AssignmentsByCourse} from 'types/routes/index/assignments-by-course'; +import { setDPMode, getDPMode } from './globals'; interface StoreState { shortcuts: { @@ -65,7 +66,6 @@ export const instance = vue assignmentName: assignment?.name ?? '', undoStack: [], redoStack: [], - DPMode: false }; }, computed: { @@ -78,6 +78,9 @@ export const instance = vue selectedNode() { return this.$store.getters.selectedNode; }, + getButtonLabel() { + return getDPMode() ? "Davis-Putnam Mode" : "Truth Tree Mode"; + } }, methods: { getNodeIconClasses: getNodeIconClasses, @@ -90,12 +93,10 @@ export const instance = vue document.querySelector<HTMLInputElement>('#open-file')?.click(); } }, - // New fuctions to turn DP mode on and off - toggleDPMode() { - this.DPMode = true; - }, toggleTTMode() { - this.DPMode = false; + const current = !getDPMode(); + setDPMode(current); + console.log(getDPMode()); }, loadFile(event: Event) { const input = event.target; diff --git a/src/common/tree.ts b/src/common/tree.ts index 3124cd8..f4e11eb 100644 --- a/src/common/tree.ts +++ b/src/common/tree.ts @@ -1,9 +1,11 @@ import {FirstOrderLogicParser} from './parser'; import {Formula} from './formula'; + import { Statement, AtomicStatement, NotStatement, + OrStatement, QuantifierStatement, ExistenceStatement, UniversalStatement, @@ -15,6 +17,7 @@ import { createNDimensionalMapping, EvaluationResponse, } from './util'; +import {resolveUrl} from 'ajv/dist/compile/resolve'; export class CorrectnessError { errorCode: string; @@ -88,6 +91,9 @@ export class CorrectnessError { case 'universal_variables_length': { return 'Universals with multiple variables cannot be evaluated yet; please split into multiple universal statements.'; } + case 'tautology not decomposed': { + return 'Tautology is not decomposed'; + } } return 'Unknown error code. Contact a developer :)'; @@ -113,11 +119,14 @@ export class TruthTreeNode { tree: TruthTree; - parent: number | null = null; // physical parent + parent: number | null = null; // physical parent children: number[] = []; - antecedent: number | null = null; // logical parent + antecedent: number | null = null; // logical parent decomposition: Set<number> = new Set(); + + // For Davis Puttnam reduction + antecedentsDP: Set<number> = new Set(); private _correctDecomposition: Set<number> | null = null; /** @@ -147,7 +156,7 @@ export class TruthTreeNode { newNode.children = [...this.children]; newNode.antecedent = this.antecedent; newNode.decomposition = new Set(this.decomposition); - + newNode.antecedentsDP = new Set(this.antecedentsDP); return newNode; } @@ -190,6 +199,18 @@ export class TruthTreeNode { } newNode.decomposition = new Set(jsonObject.decomposition); + if ( + !( + 'antecedentsDP' in jsonObject && + typeof jsonObject.antecedentsDP === 'object' && + Array.isArray(jsonObject.antecedentsDP) && + jsonObject.antecedentsDP.every(element => typeof element === 'number') + ) + ) { + throw new Error('TruthTreeNode#fromJSON: antecedentsDP not found.'); + } + newNode.antecedentsDP = new Set(jsonObject.antecedentsDP); + // Check for optional properties if ('premise' in jsonObject && typeof jsonObject.premise === 'boolean') { newNode.premise = jsonObject.premise; @@ -561,6 +582,51 @@ export class TruthTreeNode { return TruthTree.CLOSED_TERMINATOR === this.text.trim(); } + isDPValid(): Response { + // For DP - check statement logically follows from antecedent + branch + // TODO: ensure this only gets checked when DP in DP mode + if (!this._statement) { + // TODO: change error + return new CorrectnessError('not_parsable'); + } + + // this._statement ==> conclusion + // leftNode._statement ==> literal + // rightNode._statement ==> statement to reduce + let antecedentArr = Array.from(this.antecedentsDP); + + console.log( + 'isDPvalid arr length', + this._statement.toString(), + antecedentArr.length + ); + if (antecedentArr.length == 2) { + let left = antecedentArr[0]; + let right = antecedentArr[1]; + let leftNode = this.tree.nodes[left]; + let rightNode = this.tree.nodes[right]; + + if (leftNode._statement && rightNode._statement) { + // Validator takes in statement we would like to reduce along with assertion + let statementReducer = new DPStatementValidator( + leftNode._statement, + rightNode._statement + ); + let statementReducer2 = new DPStatementValidator( + rightNode._statement, + leftNode._statement + ); + let res1 = statementReducer.validateReduction(this._statement); + let res2 = statementReducer2.validateReduction(this._statement); + + if (res1 || res2) { + return true; + } + } + } + // TODO: change error + return new CorrectnessError('not_logical_consequence'); + } /** * Determines whether or not this statement is valid; i.e., it is a logical * consequence of some other statement in the truth tree. @@ -600,35 +666,10 @@ export class TruthTreeNode { return true; } - if (this._statement) { - // this._statement ==> conclusion - // leftNode._statement ==> literal - // rightNode._statement ==> statement to reduce - let decompositionArr = Array.from(this.decomposition); - if (decompositionArr.length == 2) { - let left = decompositionArr[0]; - let right = decompositionArr[1]; - let leftNode = this.tree.nodes[left]; - let rightNode = this.tree.nodes[right]; - - if (leftNode._statement && rightNode._statement) { - // Validator takes in statement we wouled like to reduce along with assertion - let statementReducer = new DPStatementValidator( - leftNode._statement, - rightNode._statement - ); - let statementReducer2 = new DPStatementValidator( - rightNode._statement, - leftNode._statement - ); - let res = - statementReducer.validateReduction(this._statement) || - statementReducer2.validateReduction(this._statement); - if (res) { - return true; - } - } - } + // return this.isDPValid(); + // // TODO: DP mode + if (this.isDPValid() === true) { + return true; } // Non-premises must have an antecedent for this statement to be valid @@ -780,6 +821,21 @@ export class TruthTreeNode { return new CorrectnessError('closed_not_contradiction'); } + isReduced(): Response { + // we would like to check the two decompositions are correct + const decompArray = Array.from(this.decomposition); + if (decompArray.length != 2) { + return new CorrectnessError('invalid_decomposition'); + } + const s1 = this.tree.nodes[decompArray[0]]; + const s2 = this.tree.nodes[decompArray[1]]; + + if (s1.isDPValid() && s2.isDPValid()) { + return true; + } + return new CorrectnessError('invalid_decomposition'); + } + /** * Determines whether or not this statement is fully decomposed in every * open branch. @@ -817,154 +873,156 @@ export class TruthTreeNode { } } + return this.isReduced(); + // This statement must be decomposed in every non-closed branch that // contains it or exactly one open node if requireAllBranchesTerminated // is false - let error: CorrectnessError | null = null; - for (const leafId of this.tree.leaves) { - const leafNode = this.tree.nodes[leafId]; - let leafError: CorrectnessError | null = null; - - // If this is an existence statement, we care that it is correctly - // decomposed everywhere, not just non-closed terminators - if ( - !(this.statement instanceof ExistenceStatement) && - leafNode.isClosedTerminator() - ) { - continue; - } - - // This statement must be contained in the leaf's branch - if (!(this.isAncestorOf(leafId) || this.id === leafId)) { - continue; - } - const branch = leafNode.getAncestorBranch(true); - - // Universals are unique from other statements - if (this.statement instanceof UniversalStatement) { - // For universal statements, each branch needs to instantiate - // every single constant in the leaf's universe - - // Collect the decomposed nodes in this branch - const decomposedInBranch = new Set<number>(); - for (const decomposed of this.decomposition) { - if (branch.has(decomposed)) { - decomposedInBranch.add(decomposed); - } - } - - // Each universal must instantiate at least one variable. - if (decomposedInBranch.size === 0) { - error = new CorrectnessError('universal_decompose_length'); - continue; - } - - const symbolized = this.statement.symbolized(); - - // Form every possible assignment of constants for this universal - const uninstantiated = createNDimensionalMapping( - this.statement.variables.length, - leafNode.universe! - ); - - // Remove every assignment from our mapping that appears in the branch - for (const decomposed of decomposedInBranch) { - const decomposedNode = this.tree.nodes[decomposed]; - if (decomposedNode.statement === null) { - // An empty statement cannot be a decomposition - leafError = new CorrectnessError('invalid_decomposition'); - break; - } - - const assignment = symbolized.getEqualsMap(decomposedNode.statement); - if (assignment === false) { - // Not an initialization of the antecedent - leafError = new CorrectnessError('invalid_decomposition'); - break; - } - - if ( - Object.keys(assignment).length !== this.statement.variables.length - ) { - // If the assignment does not have an assignment for every variable - // then arbitrarily assign a value from the universe. If one doesn't - // exist then arbitrarily assign the constant 'x' - - let value: Formula; - // Check universe for arbitrarily value - if (leafNode.universe!.length > 0) { - value = leafNode.universe!.values().next().value; - } else { - value = new Formula('x'); - } - - for (const variable of this.statement.variables) { - if (Object.keys(assignment).includes(variable.toString())) { - continue; - } - assignment[variable.toString()] = value; - } - } - - deleteMapping(uninstantiated, assignment, this.statement.variables); - } - - if (leafError !== null) { - error = leafError; - continue; - } - - // If there are still assignments left, then we did not instantiate every - // possible assignment of constants in this branch - if (Object.keys(uninstantiated).length !== 0) { - const mapping = getFirstUnassigned(uninstantiated)!; - leafError = new CorrectnessError( - 'universal_domain_not_decomposed', - mapping - ); - } - } else { - // Check if the correct decomposition is in this branch - let containedInBranch = false; - for (const correctlyDecomposedNode of this.correctDecomposition!) { - if (branch.has(correctlyDecomposedNode)) { - containedInBranch = true; - break; - } - } - - if (!containedInBranch) { - // This node is not decomposed in every non-closed branch - if (this.statement instanceof ExistenceStatement) { - leafError = new CorrectnessError('existence_instantiation_length'); - } else { - leafError = new CorrectnessError('invalid_decomposition'); - } - } else if (this.decomposition.size > this.correctDecomposition!.size) { - leafError = new CorrectnessError('existence_instantiation_violation'); - } - } - - if (leafError === null) { - // If we have a valid open terminator and don't require all branches to - // be terminated, then we can just return that it works! - if ( - leafNode.isOpenTerminator() && - !this.tree.options.requireAllBranchesTerminated - ) { - return true; - } - } else { - // Save the error - error = leafError; - } - } - - if (error !== null) { - return error; - } - - return true; + // let error: CorrectnessError | null = null; + // for (const leafId of this.tree.leaves) { + // const leafNode = this.tree.nodes[leafId]; + // let leafError: CorrectnessError | null = null; + + // // If this is an existence statement, we care that it is correctly + // // decomposed everywhere, not just non-closed terminators + // if ( + // !(this.statement instanceof ExistenceStatement) && + // leafNode.isClosedTerminator() + // ) { + // continue; + // } + + // // This statement must be contained in the leaf's branch + // if (!(this.isAncestorOf(leafId) || this.id === leafId)) { + // continue; + // } + // const branch = leafNode.getAncestorBranch(true); + + // // Universals are unique from other statements + // if (this.statement instanceof UniversalStatement) { + // // For universal statements, each branch needs to instantiate + // // every single constant in the leaf's universe + + // // Collect the decomposed nodes in this branch + // const decomposedInBranch = new Set<number>(); + // for (const decomposed of this.decomposition) { + // if (branch.has(decomposed)) { + // decomposedInBranch.add(decomposed); + // } + // } + + // // Each universal must instantiate at least one variable. + // if (decomposedInBranch.size === 0) { + // error = new CorrectnessError('universal_decompose_length'); + // continue; + // } + + // const symbolized = this.statement.symbolized(); + + // // Form every possible assignment of constants for this universal + // const uninstantiated = createNDimensionalMapping( + // this.statement.variables.length, + // leafNode.universe! + // ); + + // // Remove every assignment from our mapping that appears in the branch + // for (const decomposed of decomposedInBranch) { + // const decomposedNode = this.tree.nodes[decomposed]; + // if (decomposedNode.statement === null) { + // // An empty statement cannot be a decomposition + // leafError = new CorrectnessError('invalid_decomposition'); + // break; + // } + + // const assignment = symbolized.getEqualsMap(decomposedNode.statement); + // if (assignment === false) { + // // Not an initialization of the antecedent + // leafError = new CorrectnessError('invalid_decomposition'); + // break; + // } + + // if ( + // Object.keys(assignment).length !== this.statement.variables.length + // ) { + // // If the assignment does not have an assignment for every variable + // // then arbitrarily assign a value from the universe. If one doesn't + // // exist then arbitrarily assign the constant 'x' + + // let value: Formula; + // // Check universe for arbitrarily value + // if (leafNode.universe!.length > 0) { + // value = leafNode.universe!.values().next().value; + // } else { + // value = new Formula('x'); + // } + + // for (const variable of this.statement.variables) { + // if (Object.keys(assignment).includes(variable.toString())) { + // continue; + // } + // assignment[variable.toString()] = value; + // } + // } + + // deleteMapping(uninstantiated, assignment, this.statement.variables); + // } + + // if (leafError !== null) { + // error = leafError; + // continue; + // } + + // // If there are still assignments left, then we did not instantiate every + // // possible assignment of constants in this branch + // if (Object.keys(uninstantiated).length !== 0) { + // const mapping = getFirstUnassigned(uninstantiated)!; + // leafError = new CorrectnessError( + // 'universal_domain_not_decomposed', + // mapping + // ); + // } + // } else { + // // Check if the correct decomposition is in this branch + // let containedInBranch = false; + // for (const correctlyDecomposedNode of this.correctDecomposition!) { + // if (branch.has(correctlyDecomposedNode)) { + // containedInBranch = true; + // break; + // } + // } + + // if (!containedInBranch) { + // // This node is not decomposed in every non-closed branch + // if (this.statement instanceof ExistenceStatement) { + // leafError = new CorrectnessError('existence_instantiation_length'); + // } else { + // leafError = new CorrectnessError('invalid_decomposition'); + // } + // } else if (this.decomposition.size > this.correctDecomposition!.size) { + // leafError = new CorrectnessError('existence_instantiation_violation'); + // } + // } + + // if (leafError === null) { + // // If we have a valid open terminator and don't require all branches to + // // be terminated, then we can just return that it works! + // if ( + // leafNode.isOpenTerminator() && + // !this.tree.options.requireAllBranchesTerminated + // ) { + // return true; + // } + // } else { + // // Save the error + // error = leafError; + // } + // } + + // if (error !== null) { + // return error; + // } + + // return true; } getFeedback(): string { @@ -976,7 +1034,6 @@ export class TruthTreeNode { if (decomp !== true) { return decomp.getErrorMessage(); } - if (this.premise) { return 'This statement is a premise.'; } @@ -1190,6 +1247,7 @@ export class TruthTree { text: node.text, children: node.children, decomposition: [...node.decomposition], + antecedentsDP: [...node.antecedentsDP], }; if (node.premise) { diff --git a/views/index.pug b/views/index.pug index 4140c48..be27253 100644 --- a/views/index.pug +++ b/views/index.pug @@ -18,6 +18,10 @@ html(lang='en') script(type='text/javascript'). const assignmentsByCourse = !{interpolate(assignmentsByCourse)} ?? {}; const assignment = !{interpolate(assignment)} ?? undefined; + script. + function dpModeOn() { + toggleDPMode(); + } body include /global/header.pug #content @@ -81,11 +85,7 @@ html(lang='en') .dropdown-menu button.menu-option(onclick='toolbar.showModal("shortcuts-modal")') Shortcuts button.menu-option(onclick='toolbar.showModal("substitutions-modal")') Substitutions - .dropdown - button Modes - .dropdown-menu - button.menu-option(onclick='toggleDPMode') Davis-Putnam Mode - button.menu-option(@click='toggleTTMode') Truth Tree Mode + button.menu-option(@click='toggleTTMode') {{ getButtonLabel }} .dropdown button Help .dropdown-menu From 011e506eacc316e1516db97658d14dd3570404fa Mon Sep 17 00:00:00 2001 From: Jenny Gao <jennyg4416@gmail.com> Date: Thu, 27 Apr 2023 16:07:25 -0400 Subject: [PATCH 42/54] Update DP_userguide.md --- DP_userguide.md | 60 ++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 59 insertions(+), 1 deletion(-) diff --git a/DP_userguide.md b/DP_userguide.md index 006914b..bb356d0 100644 --- a/DP_userguide.md +++ b/DP_userguide.md @@ -1 +1,59 @@ -# Davis-Putnam User's Guide \ No newline at end of file +# Davis-Putnam User's Guide + +Refer to [userguide](userguide.md) for instructions on the Willow interface. +Refer to [DP_developer_guide](DP_developer_guide.md) if you are interested in extending existing functionality. + +This guide will walk through how to verify whether a set of statements is satisfiable using Davis-Putnam. + +## What is Davis-Putnam? + +[Davis Putnam](https://en.wikipedia.org/wiki/Davis%E2%80%93Putnam_algorithm), similar to truth trees, is another procedue used to determine if a set of statements is satisfiable. This is achieved by recursively selecting a literal, and creating a branch for each of the possible states. A literal can be either `True` or `False`, resulting in the creation of at most 2 states per literal. Statements are reduce with regard to some literal. This procedure halts once all states have either reached a contradiction or is deemed satisfiable. + +The following **Reduction Rules** can be used to reduce statements with respect to the truthy value of some literal. + +- `⊤` means a literal is True +- `⊥` means a literal is False. + + +| Not | And | Or | Conditional | Biconditional | +| --------- | ----------- |------------ | ----------- | ------------- | +| ¬⊤ => ⊥ | ⊤ ∧ P => P | ⊤ ∨ P => ⊤ | ⊤ → P => P | ⊤ ↔ P => P | +| ¬⊥ => ⊤ | ⊥ ∧ P => ⊥ | ⊥ ∨ P => P | ⊥ → P => ⊤ | ⊥ ↔ P => ¬P | +| | P ∧ ⊤ => P | P ∨ ⊤ => ⊤ | P → ⊤ => ⊤ | P ↔ ⊤ => P | +| | P ∧ ⊥ => ⊥ | P ∨ ⊥ => P | P → ⊥ => ¬P | P ↔ ⊥ => ¬P | + + +## Willow for Davis-Putnam + +We will walk through a simple example. Is the following clause satisfiable? + +![Clause](https://user-images.githubusercontent.com/29582421/234971620-2e1994ff-81e8-40b4-a66b-5a8e7acfef1a.jpg) + +1. **Select Mode** +Ensure your are in Davis-Putnam Mode. The two different modes have different rules that can be used to satify a set of statements. +![DP Mode](https://user-images.githubusercontent.com/29582421/234759174-d7114e69-6d88-44e7-959f-6708ab26e293.jpg) + + +2. **Adding tautologies** +Every variable can be set to the true or false. We create this tautology. +![Creating tautology](https://user-images.githubusercontent.com/29582421/234971872-905d907c-7d87-421b-a020-6c87c25b2f23.jpg) +<!-- +Tautologies are formed by disjuncting any statement $\psi$ with $\neg \psi$ + +Intention is for tautologies to be literal +(not tested with general statements) --> + +3. **Branching off tautologies** +Decompose the tautology to create the two possible states. For each of the two values, select where the statement came from. +![Decompositions](https://user-images.githubusercontent.com/29582421/234972437-47d21adc-1bd0-465e-a5da-5f13291bc17c.jpg) +![Premise](https://user-images.githubusercontent.com/29582421/234972594-4a0f52e7-dd9f-4058-86d7-090ebf0d8e0c.jpg) + +4. **Reduce Statements** +For each statement in parent branch, reduce them with respect to the literal branch. Notice that statement gets checked off when they a +![R1](https://user-images.githubusercontent.com/29582421/234977549-90c491d7-94a7-463d-ba9c-7f6fc9e18e51.jpg) +![R2](https://user-images.githubusercontent.com/29582421/234977681-ac6f0160-fe36-48ff-af3c-5cbf904dd51f.jpg) + + +5. **Validating Tree** +![Check](https://user-images.githubusercontent.com/29582421/234977819-ba52f194-1b9c-46fc-bbe3-044cf30ef490.jpg) + From b6f1a029789c79d3f9346e03b5f944a869b3b282 Mon Sep 17 00:00:00 2001 From: Mason duBoef <mduboef@gmail.com> Date: Thu, 27 Apr 2023 16:49:52 -0400 Subject: [PATCH 43/54] Button Text & tree.ts checks --- src/client/index.ts | 7 +- src/common/tree.ts | 368 +++++++++++++++++++++++--------------------- views/index.pug | 2 +- 3 files changed, 201 insertions(+), 176 deletions(-) diff --git a/src/client/index.ts b/src/client/index.ts index 9484b67..1b73e6b 100644 --- a/src/client/index.ts +++ b/src/client/index.ts @@ -66,6 +66,7 @@ export const instance = vue assignmentName: assignment?.name ?? '', undoStack: [], redoStack: [], + buttonLabel: getDPMode() ? 'Davis-Putnam Mode' : 'Truth Tree Mode' }; }, computed: { @@ -79,7 +80,7 @@ export const instance = vue return this.$store.getters.selectedNode; }, getButtonLabel() { - return getDPMode() ? "Davis-Putnam Mode" : "Truth Tree Mode"; + this.buttonLabel = getDPMode() ? 'Davis-Putnam Mode' : 'Truth Tree Mode'; } }, methods: { @@ -93,10 +94,14 @@ export const instance = vue document.querySelector<HTMLInputElement>('#open-file')?.click(); } }, + updateButtonLabel() { + this.buttonLabel = getDPMode() ? 'Davis-Putnam Mode' : 'Truth Tree Mode'; + }, toggleTTMode() { const current = !getDPMode(); setDPMode(current); console.log(getDPMode()); + this.updateButtonLabel(); }, loadFile(event: Event) { const input = event.target; diff --git a/src/common/tree.ts b/src/common/tree.ts index f4e11eb..45f7479 100644 --- a/src/common/tree.ts +++ b/src/common/tree.ts @@ -18,6 +18,8 @@ import { EvaluationResponse, } from './util'; import {resolveUrl} from 'ajv/dist/compile/resolve'; +import { getDPMode } from '../client/globals'; + export class CorrectnessError { errorCode: string; @@ -38,7 +40,11 @@ export class CorrectnessError { return 'This statement is not parsable.'; } case 'not_logical_consequence': { - return 'This statement is not a logical consequence of a statement that occurs before it.'; + if(getDPMode()==false){ + return 'This statement is not a logical consequence of a statement that occurs before it.'; + }else{ + return 'This statement is not a logical inference of a statement that occurs before it.'; + } } case 'invalid_instantiation': { return 'This statement does not instantiate the statement it references'; @@ -668,7 +674,7 @@ export class TruthTreeNode { // return this.isDPValid(); // // TODO: DP mode - if (this.isDPValid() === true) { + if (getDPMode() && this.isDPValid() === true) { return true; } @@ -844,185 +850,195 @@ export class TruthTreeNode { isDecomposed(): Response { // Null statements are decomposed only if they are terminators or empty // strings - if (this.statement === null) { - // Case 1: Empty string - if (this.text.trim().length === 0) { + if (getDPMode() == true){ + + + if (this.statement === null) { + // Case 1: Empty string + if (this.text.trim().length === 0) { + return true; + } + + // Case 2: Terminator + if (this.isTerminator()) { + return true; + } + + // Otherwise, it failed to parse but is not one of the above cases + return new CorrectnessError('not_parsable'); + } + + // A statement with no decomposition is vacuously decomposed + const expectedDecomposition = this.statement.decompose(); + if (expectedDecomposition.length === 0) { return true; } + + // Every node in the decomposition must be in a child branch of this + // node. + for (const decomposedId of this.decomposition) { + if (!this.isAncestorOf(decomposedId)) { + return new CorrectnessError('reference_not_after'); + } + } + + return this.isReduced(); - // Case 2: Terminator - if (this.isTerminator()) { - return true; + + }else{ + + + // This statement must be decomposed in every non-closed branch that + // contains it or exactly one open node if requireAllBranchesTerminated + // is false + let error: CorrectnessError | null = null; + for (const leafId of this.tree.leaves) { + const leafNode = this.tree.nodes[leafId]; + let leafError: CorrectnessError | null = null; + + // If this is an existence statement, we care that it is correctly + // decomposed everywhere, not just non-closed terminators + if ( + !(this.statement instanceof ExistenceStatement) && + leafNode.isClosedTerminator() + ) { + continue; + } + + // This statement must be contained in the leaf's branch + if (!(this.isAncestorOf(leafId) || this.id === leafId)) { + continue; + } + const branch = leafNode.getAncestorBranch(true); + + // Universals are unique from other statements + if (this.statement instanceof UniversalStatement) { + // For universal statements, each branch needs to instantiate + // every single constant in the leaf's universe + + // Collect the decomposed nodes in this branch + const decomposedInBranch = new Set<number>(); + for (const decomposed of this.decomposition) { + if (branch.has(decomposed)) { + decomposedInBranch.add(decomposed); + } + } + + // Each universal must instantiate at least one variable. + if (decomposedInBranch.size === 0) { + error = new CorrectnessError('universal_decompose_length'); + continue; + } + + const symbolized = this.statement.symbolized(); + + // Form every possible assignment of constants for this universal + const uninstantiated = createNDimensionalMapping( + this.statement.variables.length, + leafNode.universe! + ); + + // Remove every assignment from our mapping that appears in the branch + for (const decomposed of decomposedInBranch) { + const decomposedNode = this.tree.nodes[decomposed]; + if (decomposedNode.statement === null) { + // An empty statement cannot be a decomposition + leafError = new CorrectnessError('invalid_decomposition'); + break; + } + + const assignment = symbolized.getEqualsMap(decomposedNode.statement); + if (assignment === false) { + // Not an initialization of the antecedent + leafError = new CorrectnessError('invalid_decomposition'); + break; + } + + if ( + Object.keys(assignment).length !== this.statement.variables.length + ) { + // If the assignment does not have an assignment for every variable + // then arbitrarily assign a value from the universe. If one doesn't + // exist then arbitrarily assign the constant 'x' + + let value: Formula; + // Check universe for arbitrarily value + if (leafNode.universe!.length > 0) { + value = leafNode.universe!.values().next().value; + } else { + value = new Formula('x'); + } + + for (const variable of this.statement.variables) { + if (Object.keys(assignment).includes(variable.toString())) { + continue; + } + assignment[variable.toString()] = value; + } + } + + deleteMapping(uninstantiated, assignment, this.statement.variables); + } + + if (leafError !== null) { + error = leafError; + continue; + } + + // If there are still assignments left, then we did not instantiate every + // possible assignment of constants in this branch + if (Object.keys(uninstantiated).length !== 0) { + const mapping = getFirstUnassigned(uninstantiated)!; + leafError = new CorrectnessError( + 'universal_domain_not_decomposed', + mapping + ); + } + } else { + // Check if the correct decomposition is in this branch + let containedInBranch = false; + for (const correctlyDecomposedNode of this.correctDecomposition!) { + if (branch.has(correctlyDecomposedNode)) { + containedInBranch = true; + break; + } + } + + if (!containedInBranch) { + // This node is not decomposed in every non-closed branch + if (this.statement instanceof ExistenceStatement) { + leafError = new CorrectnessError('existence_instantiation_length'); + } else { + leafError = new CorrectnessError('invalid_decomposition'); + } + } else if (this.decomposition.size > this.correctDecomposition!.size) { + leafError = new CorrectnessError('existence_instantiation_violation'); + } + } + + if (leafError === null) { + // If we have a valid open terminator and don't require all branches to + // be terminated, then we can just return that it works! + if ( + leafNode.isOpenTerminator() && + !this.tree.options.requireAllBranchesTerminated + ) { + return true; + } + } else { + // Save the error + error = leafError; + } } - // Otherwise, it failed to parse but is not one of the above cases - return new CorrectnessError('not_parsable'); - } + if (error !== null) { + return error; + } - // A statement with no decomposition is vacuously decomposed - const expectedDecomposition = this.statement.decompose(); - if (expectedDecomposition.length === 0) { return true; - } - // Every node in the decomposition must be in a child branch of this - // node. - for (const decomposedId of this.decomposition) { - if (!this.isAncestorOf(decomposedId)) { - return new CorrectnessError('reference_not_after'); - } - } - - return this.isReduced(); - - // This statement must be decomposed in every non-closed branch that - // contains it or exactly one open node if requireAllBranchesTerminated - // is false - // let error: CorrectnessError | null = null; - // for (const leafId of this.tree.leaves) { - // const leafNode = this.tree.nodes[leafId]; - // let leafError: CorrectnessError | null = null; - - // // If this is an existence statement, we care that it is correctly - // // decomposed everywhere, not just non-closed terminators - // if ( - // !(this.statement instanceof ExistenceStatement) && - // leafNode.isClosedTerminator() - // ) { - // continue; - // } - - // // This statement must be contained in the leaf's branch - // if (!(this.isAncestorOf(leafId) || this.id === leafId)) { - // continue; - // } - // const branch = leafNode.getAncestorBranch(true); - - // // Universals are unique from other statements - // if (this.statement instanceof UniversalStatement) { - // // For universal statements, each branch needs to instantiate - // // every single constant in the leaf's universe - - // // Collect the decomposed nodes in this branch - // const decomposedInBranch = new Set<number>(); - // for (const decomposed of this.decomposition) { - // if (branch.has(decomposed)) { - // decomposedInBranch.add(decomposed); - // } - // } - - // // Each universal must instantiate at least one variable. - // if (decomposedInBranch.size === 0) { - // error = new CorrectnessError('universal_decompose_length'); - // continue; - // } - - // const symbolized = this.statement.symbolized(); - - // // Form every possible assignment of constants for this universal - // const uninstantiated = createNDimensionalMapping( - // this.statement.variables.length, - // leafNode.universe! - // ); - - // // Remove every assignment from our mapping that appears in the branch - // for (const decomposed of decomposedInBranch) { - // const decomposedNode = this.tree.nodes[decomposed]; - // if (decomposedNode.statement === null) { - // // An empty statement cannot be a decomposition - // leafError = new CorrectnessError('invalid_decomposition'); - // break; - // } - - // const assignment = symbolized.getEqualsMap(decomposedNode.statement); - // if (assignment === false) { - // // Not an initialization of the antecedent - // leafError = new CorrectnessError('invalid_decomposition'); - // break; - // } - - // if ( - // Object.keys(assignment).length !== this.statement.variables.length - // ) { - // // If the assignment does not have an assignment for every variable - // // then arbitrarily assign a value from the universe. If one doesn't - // // exist then arbitrarily assign the constant 'x' - - // let value: Formula; - // // Check universe for arbitrarily value - // if (leafNode.universe!.length > 0) { - // value = leafNode.universe!.values().next().value; - // } else { - // value = new Formula('x'); - // } - - // for (const variable of this.statement.variables) { - // if (Object.keys(assignment).includes(variable.toString())) { - // continue; - // } - // assignment[variable.toString()] = value; - // } - // } - - // deleteMapping(uninstantiated, assignment, this.statement.variables); - // } - - // if (leafError !== null) { - // error = leafError; - // continue; - // } - - // // If there are still assignments left, then we did not instantiate every - // // possible assignment of constants in this branch - // if (Object.keys(uninstantiated).length !== 0) { - // const mapping = getFirstUnassigned(uninstantiated)!; - // leafError = new CorrectnessError( - // 'universal_domain_not_decomposed', - // mapping - // ); - // } - // } else { - // // Check if the correct decomposition is in this branch - // let containedInBranch = false; - // for (const correctlyDecomposedNode of this.correctDecomposition!) { - // if (branch.has(correctlyDecomposedNode)) { - // containedInBranch = true; - // break; - // } - // } - - // if (!containedInBranch) { - // // This node is not decomposed in every non-closed branch - // if (this.statement instanceof ExistenceStatement) { - // leafError = new CorrectnessError('existence_instantiation_length'); - // } else { - // leafError = new CorrectnessError('invalid_decomposition'); - // } - // } else if (this.decomposition.size > this.correctDecomposition!.size) { - // leafError = new CorrectnessError('existence_instantiation_violation'); - // } - // } - - // if (leafError === null) { - // // If we have a valid open terminator and don't require all branches to - // // be terminated, then we can just return that it works! - // if ( - // leafNode.isOpenTerminator() && - // !this.tree.options.requireAllBranchesTerminated - // ) { - // return true; - // } - // } else { - // // Save the error - // error = leafError; - // } - // } - - // if (error !== null) { - // return error; - // } - - // return true; + + } } getFeedback(): string { @@ -1049,7 +1065,11 @@ export class TruthTreeNode { return 'This branch is successfully closed.'; } - return 'This statement is a logical consequence and is decomposed correctly.'; + if(getDPMode()==false){ + return 'This statement is a logical consequence and is decomposed correctly.'; + }else{ + return 'This statement is a logical inference and is reduced correctly.'; + } } /** diff --git a/views/index.pug b/views/index.pug index be27253..9233bcf 100644 --- a/views/index.pug +++ b/views/index.pug @@ -85,7 +85,7 @@ html(lang='en') .dropdown-menu button.menu-option(onclick='toolbar.showModal("shortcuts-modal")') Shortcuts button.menu-option(onclick='toolbar.showModal("substitutions-modal")') Substitutions - button.menu-option(@click='toggleTTMode') {{ getButtonLabel }} + button.menu-option(@click='toggleTTMode') {{ buttonLabel }} .dropdown button Help .dropdown-menu From 5f192e01e62a6dc495b0a3ef116510fe6d1557a6 Mon Sep 17 00:00:00 2001 From: jssunray34 <55996087+jssunray34@users.noreply.github.com> Date: Thu, 27 Apr 2023 23:28:57 -0400 Subject: [PATCH 44/54] Enable switching between modes Co-Authored-By: Jenny Gao <29582421+jeninyg@users.noreply.github.com> --- src/client/component/truth-tree-branch.ts | 10 +- src/common/tree.ts | 317 ++++++++++------------ 2 files changed, 156 insertions(+), 171 deletions(-) diff --git a/src/client/component/truth-tree-branch.ts b/src/client/component/truth-tree-branch.ts index 9d5ca58..4e8d935 100644 --- a/src/client/component/truth-tree-branch.ts +++ b/src/client/component/truth-tree-branch.ts @@ -2,6 +2,7 @@ import {NotStatement, OrStatement} from '../../common/statement'; import {defineComponent} from 'vue'; import {TruthTree, TruthTreeNode} from '../../common/tree'; import {TruthTreeNodeComponent} from './truth-tree-node'; +import { getDPMode } from '../globals'; /** * A Vue component that renders a branch of a truth tree. Note that this @@ -77,6 +78,13 @@ export const TruthTreeBranchComponent = defineComponent({ this.childBranches.push(ref); } }, + determineModifyRule(id: number) { + if (getDPMode() == true) { + this.modifyAntecedentsDP(id); + } else { + this.modifyDecomposition(id); + } + }, modifyAntecedentsDP(id: number) { // TODO: Document this function more const selectedNode: TruthTreeNode | null = @@ -271,7 +279,7 @@ export const TruthTreeBranchComponent = defineComponent({ <ul class="branch"> <template v-for="id, index in branch"> <li v-if="index === 0 || expanded" - @contextmenu.prevent="modifyAntecedentsDP(id)" + @contextmenu.prevent="determineModifyRule(id)" @click="$store.commit('select', {id: id})" :class="{ selected: selected === id, diff --git a/src/common/tree.ts b/src/common/tree.ts index d8b18c0..b6d2e49 100644 --- a/src/common/tree.ts +++ b/src/common/tree.ts @@ -5,7 +5,6 @@ import { Statement, AtomicStatement, NotStatement, - OrStatement, QuantifierStatement, ExistenceStatement, UniversalStatement, @@ -600,7 +599,6 @@ export class TruthTreeNode { isDPValid(): Response { // For DP: check statement logically follows from antecedent using branch - // TODO: ensure this only gets checked when DP in DP mode if (!this._statement) { // TODO: change error @@ -778,8 +776,8 @@ export class TruthTreeNode { * @returns true if this closed terminator is valid, false otherwise */ private isClosedTerminatorValid(): Response { - // TODO: DP mode if ( + getDPMode() && this.antecedent && this.tree.nodes[this.antecedent].statement instanceof Contradiction ) { @@ -836,21 +834,6 @@ export class TruthTreeNode { return new CorrectnessError('closed_not_contradiction'); } - isReduced(): Response { - // we would like to check the two decompositions are correct - const decompArray = Array.from(this.decomposition); - if (decompArray.length != 2) { - return new CorrectnessError('invalid_decomposition'); - } - const s1 = this.tree.nodes[decompArray[0]]; - const s2 = this.tree.nodes[decompArray[1]]; - - if (s1.isDPValid() && s2.isDPValid()) { - return true; - } - return new CorrectnessError('invalid_decomposition'); - } - /** * Determines whether or not a statement has been reduced completely. This is * done by checking to make sure every statement in its decomposition is valid. @@ -878,192 +861,187 @@ export class TruthTreeNode { isDecomposed(): Response { // Null statements are decomposed only if they are terminators or empty // strings - if (getDPMode() == true){ - + if (this.statement === null) { + // Case 1: Empty string + if (this.text.trim().length === 0) { + return true; + } - if (this.statement === null) { - // Case 1: Empty string - if (this.text.trim().length === 0) { - return true; - } - - // Case 2: Terminator - if (this.isTerminator()) { - return true; - } - - // Otherwise, it failed to parse but is not one of the above cases - return new CorrectnessError('not_parsable'); - } - - // A statement with no decomposition is vacuously decomposed - const expectedDecomposition = this.statement.decompose(); - if (expectedDecomposition.length === 0) { + // Case 2: Terminator + if (this.isTerminator()) { return true; } - - // Every node in the decomposition must be in a child branch of this - // node. - for (const decomposedId of this.decomposition) { - if (!this.isAncestorOf(decomposedId)) { - return new CorrectnessError('reference_not_after'); - } + + // Otherwise, it failed to parse but is not one of the above cases + return new CorrectnessError('not_parsable'); + } + + // A statement with no decomposition is vacuously decomposed + const expectedDecomposition = this.statement.decompose(); + if (expectedDecomposition.length === 0) { + return true; + } + + // Every node in the decomposition must be in a child branch of this + // node. + for (const decomposedId of this.decomposition) { + if (!this.isAncestorOf(decomposedId)) { + return new CorrectnessError('reference_not_after'); } - + } + + if (getDPMode() == true) { return this.isReduced(); + } - }else{ + // This statement must be decomposed in every non-closed branch that + // contains it or exactly one open node if requireAllBranchesTerminated + // is false + let error: CorrectnessError | null = null; + for (const leafId of this.tree.leaves) { + const leafNode = this.tree.nodes[leafId]; + let leafError: CorrectnessError | null = null; + // If this is an existence statement, we care that it is correctly + // decomposed everywhere, not just non-closed terminators + if ( + !(this.statement instanceof ExistenceStatement) && + leafNode.isClosedTerminator() + ) { + continue; + } - // This statement must be decomposed in every non-closed branch that - // contains it or exactly one open node if requireAllBranchesTerminated - // is false - let error: CorrectnessError | null = null; - for (const leafId of this.tree.leaves) { - const leafNode = this.tree.nodes[leafId]; - let leafError: CorrectnessError | null = null; + // This statement must be contained in the leaf's branch + if (!(this.isAncestorOf(leafId) || this.id === leafId)) { + continue; + } + const branch = leafNode.getAncestorBranch(true); - // If this is an existence statement, we care that it is correctly - // decomposed everywhere, not just non-closed terminators - if ( - !(this.statement instanceof ExistenceStatement) && - leafNode.isClosedTerminator() - ) { - continue; + // Universals are unique from other statements + if (this.statement instanceof UniversalStatement) { + // For universal statements, each branch needs to instantiate + // every single constant in the leaf's universe + + // Collect the decomposed nodes in this branch + const decomposedInBranch = new Set<number>(); + for (const decomposed of this.decomposition) { + if (branch.has(decomposed)) { + decomposedInBranch.add(decomposed); + } } - // This statement must be contained in the leaf's branch - if (!(this.isAncestorOf(leafId) || this.id === leafId)) { + // Each universal must instantiate at least one variable. + if (decomposedInBranch.size === 0) { + error = new CorrectnessError('universal_decompose_length'); continue; } - const branch = leafNode.getAncestorBranch(true); - - // Universals are unique from other statements - if (this.statement instanceof UniversalStatement) { - // For universal statements, each branch needs to instantiate - // every single constant in the leaf's universe - - // Collect the decomposed nodes in this branch - const decomposedInBranch = new Set<number>(); - for (const decomposed of this.decomposition) { - if (branch.has(decomposed)) { - decomposedInBranch.add(decomposed); - } - } - // Each universal must instantiate at least one variable. - if (decomposedInBranch.size === 0) { - error = new CorrectnessError('universal_decompose_length'); - continue; - } + const symbolized = this.statement.symbolized(); - const symbolized = this.statement.symbolized(); + // Form every possible assignment of constants for this universal + const uninstantiated = createNDimensionalMapping( + this.statement.variables.length, + leafNode.universe! + ); - // Form every possible assignment of constants for this universal - const uninstantiated = createNDimensionalMapping( - this.statement.variables.length, - leafNode.universe! - ); + // Remove every assignment from our mapping that appears in the branch + for (const decomposed of decomposedInBranch) { + const decomposedNode = this.tree.nodes[decomposed]; + if (decomposedNode.statement === null) { + // An empty statement cannot be a decomposition + leafError = new CorrectnessError('invalid_decomposition'); + break; + } - // Remove every assignment from our mapping that appears in the branch - for (const decomposed of decomposedInBranch) { - const decomposedNode = this.tree.nodes[decomposed]; - if (decomposedNode.statement === null) { - // An empty statement cannot be a decomposition - leafError = new CorrectnessError('invalid_decomposition'); - break; - } + const assignment = symbolized.getEqualsMap(decomposedNode.statement); + if (assignment === false) { + // Not an initialization of the antecedent + leafError = new CorrectnessError('invalid_decomposition'); + break; + } - const assignment = symbolized.getEqualsMap(decomposedNode.statement); - if (assignment === false) { - // Not an initialization of the antecedent - leafError = new CorrectnessError('invalid_decomposition'); - break; + if ( + Object.keys(assignment).length !== this.statement.variables.length + ) { + // If the assignment does not have an assignment for every variable + // then arbitrarily assign a value from the universe. If one doesn't + // exist then arbitrarily assign the constant 'x' + + let value: Formula; + // Check universe for arbitrarily value + if (leafNode.universe!.length > 0) { + value = leafNode.universe!.values().next().value; + } else { + value = new Formula('x'); } - if ( - Object.keys(assignment).length !== this.statement.variables.length - ) { - // If the assignment does not have an assignment for every variable - // then arbitrarily assign a value from the universe. If one doesn't - // exist then arbitrarily assign the constant 'x' - - let value: Formula; - // Check universe for arbitrarily value - if (leafNode.universe!.length > 0) { - value = leafNode.universe!.values().next().value; - } else { - value = new Formula('x'); - } - - for (const variable of this.statement.variables) { - if (Object.keys(assignment).includes(variable.toString())) { - continue; - } - assignment[variable.toString()] = value; + for (const variable of this.statement.variables) { + if (Object.keys(assignment).includes(variable.toString())) { + continue; } + assignment[variable.toString()] = value; } - - deleteMapping(uninstantiated, assignment, this.statement.variables); } - if (leafError !== null) { - error = leafError; - continue; - } + deleteMapping(uninstantiated, assignment, this.statement.variables); + } - // If there are still assignments left, then we did not instantiate every - // possible assignment of constants in this branch - if (Object.keys(uninstantiated).length !== 0) { - const mapping = getFirstUnassigned(uninstantiated)!; - leafError = new CorrectnessError( - 'universal_domain_not_decomposed', - mapping - ); - } - } else { - // Check if the correct decomposition is in this branch - let containedInBranch = false; - for (const correctlyDecomposedNode of this.correctDecomposition!) { - if (branch.has(correctlyDecomposedNode)) { - containedInBranch = true; - break; - } - } + if (leafError !== null) { + error = leafError; + continue; + } - if (!containedInBranch) { - // This node is not decomposed in every non-closed branch - if (this.statement instanceof ExistenceStatement) { - leafError = new CorrectnessError('existence_instantiation_length'); - } else { - leafError = new CorrectnessError('invalid_decomposition'); - } - } else if (this.decomposition.size > this.correctDecomposition!.size) { - leafError = new CorrectnessError('existence_instantiation_violation'); + // If there are still assignments left, then we did not instantiate every + // possible assignment of constants in this branch + if (Object.keys(uninstantiated).length !== 0) { + const mapping = getFirstUnassigned(uninstantiated)!; + leafError = new CorrectnessError( + 'universal_domain_not_decomposed', + mapping + ); + } + } else { + // Check if the correct decomposition is in this branch + let containedInBranch = false; + for (const correctlyDecomposedNode of this.correctDecomposition!) { + if (branch.has(correctlyDecomposedNode)) { + containedInBranch = true; + break; } } - if (leafError === null) { - // If we have a valid open terminator and don't require all branches to - // be terminated, then we can just return that it works! - if ( - leafNode.isOpenTerminator() && - !this.tree.options.requireAllBranchesTerminated - ) { - return true; + if (!containedInBranch) { + // This node is not decomposed in every non-closed branch + if (this.statement instanceof ExistenceStatement) { + leafError = new CorrectnessError('existence_instantiation_length'); + } else { + leafError = new CorrectnessError('invalid_decomposition'); } - } else { - // Save the error - error = leafError; + } else if (this.decomposition.size > this.correctDecomposition!.size) { + leafError = new CorrectnessError('existence_instantiation_violation'); } } - if (error !== null) { - return error; + if (leafError === null) { + // If we have a valid open terminator and don't require all branches to + // be terminated, then we can just return that it works! + if ( + leafNode.isOpenTerminator() && + !this.tree.options.requireAllBranchesTerminated + ) { + return true; + } + } else { + // Save the error + error = leafError; } + } - return true; + if (error !== null) { + return error; } + + return true; } getFeedback(): string { @@ -1936,10 +1914,9 @@ export class TruthTree { } const decomposedNode = this.nodes[decomposedId]; - // TODO: DP mode // Don't worry about a contradiction's antecedents since it technically // has more than one - if (decomposedNode.statement instanceof Contradiction) { + if (getDPMode() && decomposedNode.statement instanceof Contradiction) { continue; } From af5d03c7229e9ffd52528ed9207a1bdd97eee0d2 Mon Sep 17 00:00:00 2001 From: jssunray34 <55996087+jssunray34@users.noreply.github.com> Date: Thu, 27 Apr 2023 23:33:51 -0400 Subject: [PATCH 45/54] Add test DP trees Co-Authored-By: Jenny Gao <29582421+jeninyg@users.noreply.github.com> --- .gitignore | 6 ------ test_trees/closed_branches_DP_hw4.willow | 1 + test_trees/simple_open_branch_DP.willow | 1 + 3 files changed, 2 insertions(+), 6 deletions(-) create mode 100644 test_trees/closed_branches_DP_hw4.willow create mode 100644 test_trees/simple_open_branch_DP.willow diff --git a/.gitignore b/.gitignore index d24361e..5a6266a 100644 --- a/.gitignore +++ b/.gitignore @@ -141,9 +141,3 @@ dist ## TypeScript ## ################## build/ - -################## -## Willow ## -################## -*.willow -WillowFiles diff --git a/test_trees/closed_branches_DP_hw4.willow b/test_trees/closed_branches_DP_hw4.willow new file mode 100644 index 0000000..a6ab98f --- /dev/null +++ b/test_trees/closed_branches_DP_hw4.willow @@ -0,0 +1 @@ +{"nodes":[{"id":0,"text":"F ∨ G","children":[1],"decomposition":[8,40],"antecedentsDP":[],"isBranchLiteral":false,"premise":true},{"id":1,"text":"H ∧ (I → F)","children":[2],"decomposition":[7,41],"antecedentsDP":[],"isBranchLiteral":false,"premise":true,"parent":0},{"id":2,"text":"H → ¬F","children":[3],"decomposition":[9,42],"antecedentsDP":[],"isBranchLiteral":false,"premise":true,"parent":1},{"id":3,"text":"¬(G ∧ ¬I)","children":[4],"decomposition":[10,43],"antecedentsDP":[],"isBranchLiteral":false,"premise":true,"parent":2},{"id":4,"text":"H ∨ ¬H","children":[5,6],"decomposition":[6,5],"antecedentsDP":[],"isBranchLiteral":false,"parent":3},{"id":5,"text":"H","children":[8],"decomposition":[],"antecedentsDP":[4],"isBranchLiteral":true,"parent":4,"antecedent":4},{"id":6,"text":"¬H","children":[40],"decomposition":[],"antecedentsDP":[4],"isBranchLiteral":true,"parent":4,"antecedent":4},{"id":7,"text":"I → F","children":[9],"decomposition":[15,20],"antecedentsDP":[5,1],"isBranchLiteral":false,"parent":8,"antecedent":1},{"id":8,"text":"F ∨ G","children":[7],"decomposition":[14,19],"antecedentsDP":[5,0],"isBranchLiteral":false,"parent":5,"antecedent":0},{"id":9,"text":"¬F","children":[10],"decomposition":[16,21],"antecedentsDP":[5,2],"isBranchLiteral":false,"parent":7,"antecedent":2},{"id":10,"text":"¬(G ∧ ¬I)","children":[11],"decomposition":[17,22],"antecedentsDP":[5,3],"isBranchLiteral":false,"parent":9,"antecedent":3},{"id":11,"text":"F ∨ ¬F","children":[12,13],"decomposition":[12,13],"antecedentsDP":[],"isBranchLiteral":false,"parent":10},{"id":12,"text":"F","children":[14],"decomposition":[],"antecedentsDP":[11],"isBranchLiteral":true,"parent":11,"antecedent":11},{"id":13,"text":"¬F","children":[19],"decomposition":[],"antecedentsDP":[11],"isBranchLiteral":true,"parent":11,"antecedent":11},{"id":14,"text":"⊤","children":[15],"decomposition":[],"antecedentsDP":[12,8],"isBranchLiteral":false,"parent":12,"antecedent":8},{"id":15,"text":"⊤","children":[16],"decomposition":[],"antecedentsDP":[12,7],"isBranchLiteral":false,"parent":14,"antecedent":7},{"id":16,"text":"⊥","children":[17],"decomposition":[18],"antecedentsDP":[12,9],"isBranchLiteral":false,"parent":15,"antecedent":9},{"id":17,"text":"¬(G ∧ ¬I)","children":[18],"decomposition":[],"antecedentsDP":[12,10],"isBranchLiteral":false,"parent":16,"antecedent":10},{"id":18,"text":"×","children":[],"decomposition":[],"antecedentsDP":[16],"isBranchLiteral":false,"parent":17,"antecedent":16},{"id":19,"text":"G","children":[20],"decomposition":[],"antecedentsDP":[13,8],"isBranchLiteral":false,"parent":13,"antecedent":8},{"id":20,"text":"¬I","children":[21],"decomposition":[26,37],"antecedentsDP":[13,7],"isBranchLiteral":false,"parent":19,"antecedent":7},{"id":21,"text":"⊤","children":[22],"decomposition":[],"antecedentsDP":[13,9],"isBranchLiteral":false,"parent":20,"antecedent":9},{"id":22,"text":"¬(G ∧ ¬I)","children":[23],"decomposition":[27,38],"antecedentsDP":[13,10],"isBranchLiteral":false,"parent":21,"antecedent":10},{"id":23,"text":"G ∨ ¬G","children":[24,25],"decomposition":[24,25],"antecedentsDP":[],"isBranchLiteral":false,"parent":22},{"id":24,"text":"G","children":[26],"decomposition":[],"antecedentsDP":[23],"isBranchLiteral":true,"parent":23,"antecedent":23},{"id":25,"text":"¬G","children":[36],"decomposition":[],"antecedentsDP":[23],"isBranchLiteral":true,"parent":23,"antecedent":23},{"id":26,"text":"¬I","children":[27],"decomposition":[32],"antecedentsDP":[24,20],"isBranchLiteral":false,"parent":24,"antecedent":20},{"id":27,"text":"¬(¬I)","children":[28],"decomposition":[31,34],"antecedentsDP":[24,22],"isBranchLiteral":false,"parent":26,"antecedent":22},{"id":28,"text":"I ∨ ¬I","children":[29,30],"decomposition":[29,30],"antecedentsDP":[],"isBranchLiteral":false,"parent":27},{"id":29,"text":"I","children":[31],"decomposition":[],"antecedentsDP":[28],"isBranchLiteral":true,"parent":28,"antecedent":28},{"id":30,"text":"¬I","children":[34],"decomposition":[],"antecedentsDP":[28],"isBranchLiteral":true,"parent":28,"antecedent":28},{"id":31,"text":"I","children":[32],"decomposition":[32],"antecedentsDP":[29,27],"isBranchLiteral":false,"parent":29,"antecedent":27},{"id":32,"text":"⊥","children":[33],"decomposition":[33],"antecedentsDP":[31,26],"isBranchLiteral":false,"parent":31,"antecedent":26},{"id":33,"text":"×","children":[],"decomposition":[],"antecedentsDP":[32],"isBranchLiteral":false,"parent":32,"antecedent":32},{"id":34,"text":"⊥","children":[35],"decomposition":[35],"antecedentsDP":[30,27],"isBranchLiteral":false,"parent":30,"antecedent":27},{"id":35,"text":"×","children":[],"decomposition":[],"antecedentsDP":[34],"isBranchLiteral":false,"parent":34,"antecedent":34},{"id":36,"text":"⊥","children":[37],"decomposition":[39],"antecedentsDP":[25,19],"isBranchLiteral":false,"parent":25},{"id":37,"text":"¬I","children":[38],"decomposition":[],"antecedentsDP":[25,20],"isBranchLiteral":false,"parent":36,"antecedent":20},{"id":38,"text":"⊤","children":[39],"decomposition":[],"antecedentsDP":[25,22],"isBranchLiteral":false,"parent":37,"antecedent":22},{"id":39,"text":"×","children":[],"decomposition":[],"antecedentsDP":[36],"isBranchLiteral":false,"parent":38,"antecedent":36},{"id":40,"text":"F ∨ G","children":[41],"decomposition":[],"antecedentsDP":[6,0],"isBranchLiteral":false,"parent":6,"antecedent":0},{"id":41,"text":"⊥","children":[42],"decomposition":[44],"antecedentsDP":[6,1],"isBranchLiteral":false,"parent":40,"antecedent":1},{"id":42,"text":"⊤","children":[43],"decomposition":[],"antecedentsDP":[6,2],"isBranchLiteral":false,"parent":41,"antecedent":2},{"id":43,"text":"¬(G ∧ ¬I)","children":[44],"decomposition":[],"antecedentsDP":[6,3],"isBranchLiteral":false,"parent":42,"antecedent":3},{"id":44,"text":"×","children":[],"decomposition":[],"antecedentsDP":[41],"isBranchLiteral":false,"parent":43,"antecedent":41}],"options":{"requireAtomicContradiction":true,"requireAllBranchesTerminated":true,"lockedOptions":false}} \ No newline at end of file diff --git a/test_trees/simple_open_branch_DP.willow b/test_trees/simple_open_branch_DP.willow new file mode 100644 index 0000000..bbbe633 --- /dev/null +++ b/test_trees/simple_open_branch_DP.willow @@ -0,0 +1 @@ +{"nodes":[{"id":0,"text":"A → (¬B ∧ C)","children":[1],"decomposition":[4,5],"antecedentsDP":[],"premise":true},{"id":1,"text":"B ∨ ¬B","children":[2,3],"decomposition":[2,3],"antecedentsDP":[],"parent":0},{"id":2,"text":"B","children":[4],"decomposition":[],"antecedentsDP":[1],"parent":1,"antecedent":1},{"id":3,"text":"¬B","children":[5],"decomposition":[],"antecedentsDP":[1],"parent":1,"antecedent":1},{"id":4,"text":"¬A","children":[11],"decomposition":[],"antecedentsDP":[2,0],"parent":2,"antecedent":0},{"id":5,"text":"A → C","children":[6],"decomposition":[9,10],"antecedentsDP":[3,0],"parent":3,"antecedent":0},{"id":6,"text":"A ∨ ¬A","children":[7,8],"decomposition":[8,7],"antecedentsDP":[],"parent":5},{"id":7,"text":"A","children":[9],"decomposition":[],"antecedentsDP":[6],"parent":6,"antecedent":6},{"id":8,"text":"¬A","children":[10],"decomposition":[],"antecedentsDP":[6],"parent":6,"antecedent":6},{"id":9,"text":"C","children":[12],"decomposition":[],"antecedentsDP":[7,5],"parent":7,"antecedent":5},{"id":10,"text":"⊤","children":[13],"decomposition":[],"antecedentsDP":[8,5],"parent":8,"antecedent":5},{"id":11,"text":"◯","children":[],"decomposition":[],"antecedentsDP":[],"parent":4},{"id":12,"text":"◯","children":[],"decomposition":[],"antecedentsDP":[],"parent":9},{"id":13,"text":"◯","children":[],"decomposition":[],"antecedentsDP":[],"parent":10}],"options":{"requireAtomicContradiction":true,"requireAllBranchesTerminated":true,"lockedOptions":false}} \ No newline at end of file From 15860166ee4810083db2cd1d1f42e01e1d132961 Mon Sep 17 00:00:00 2001 From: jssunray34 <55996087+jssunray34@users.noreply.github.com> Date: Fri, 28 Apr 2023 10:11:17 -0400 Subject: [PATCH 46/54] Fix bug with closed terminator and highlight toggle button on hover edited the validate function for closed terminator to allow for selection of two antecedents, as opposed to just the contradiction symbol --- src/common/tree.ts | 16 ++++++++++++---- views/index.pug | 3 ++- 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/src/common/tree.ts b/src/common/tree.ts index b6d2e49..9f79dd5 100644 --- a/src/common/tree.ts +++ b/src/common/tree.ts @@ -785,13 +785,21 @@ export class TruthTreeNode { } // Closed terminators must reference exactly two statements - if (this.decomposition.size !== 2) { + if (!(this.decomposition.size == 2 || (getDPMode() && this.antecedentsDP.size == 2))) { return new CorrectnessError('closed_reference_length'); } - const decomposed_statements = [...this.decomposition].map( - id => this.tree.nodes[id].statement - ); + let decomposed_statements = []; + + if (getDPMode()) { + decomposed_statements = [...this.antecedentsDP].map( + id => this.tree.nodes[id].statement + ); + } else { + decomposed_statements = [...this.decomposition].map( + id => this.tree.nodes[id].statement + ); + } for (let i = 0; i < 2; ++i) { const first = decomposed_statements[i]; diff --git a/views/index.pug b/views/index.pug index 9233bcf..a347169 100644 --- a/views/index.pug +++ b/views/index.pug @@ -85,7 +85,8 @@ html(lang='en') .dropdown-menu button.menu-option(onclick='toolbar.showModal("shortcuts-modal")') Shortcuts button.menu-option(onclick='toolbar.showModal("substitutions-modal")') Substitutions - button.menu-option(@click='toggleTTMode') {{ buttonLabel }} + .dropdown + button.menu-option(@click='toggleTTMode') {{ buttonLabel }} .dropdown button Help .dropdown-menu From 3434faa0fa400d91c5274cd83f8fecf4dbcf3f42 Mon Sep 17 00:00:00 2001 From: jssunray34 <55996087+jssunray34@users.noreply.github.com> Date: Fri, 28 Apr 2023 11:51:30 -0400 Subject: [PATCH 47/54] Fix bug with deleting statements we have to clear out the antecedents array for statements in the deleted statement's decomposition --- src/common/tree.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/common/tree.ts b/src/common/tree.ts index 9f79dd5..47fb6e9 100644 --- a/src/common/tree.ts +++ b/src/common/tree.ts @@ -1637,6 +1637,10 @@ export class TruthTree { for (const childId of node.decomposition) { const childNode = this.nodes[childId]; childNode.antecedent = null; + + if (getDPMode()) { + childNode.antecedentsDP.clear(); + } } } From 811b51dffab6bc92758c82fc99ea667a5f298baf Mon Sep 17 00:00:00 2001 From: Jody Sunray <55996087+jssunray34@users.noreply.github.com> Date: Fri, 28 Apr 2023 12:09:21 -0400 Subject: [PATCH 48/54] Update README --- DP_developer_guide.md | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/DP_developer_guide.md b/DP_developer_guide.md index 394dd33..09c958c 100644 --- a/DP_developer_guide.md +++ b/DP_developer_guide.md @@ -81,9 +81,16 @@ When designing an implementation of Davis-Putnam (DP) supported by Willow, we wa The implementation of DP in Willow is completely usable in its current state. However, there are a few action items that we were not able to get to, and more thorough testing will need to be done to ensure that the feature is production-ready. -1. Handle lingering statements that have not been fully decomposed +1. **Handle unchecked statements that have not been fully decomposed**: As shown in the image below, there are a few statements that are not marked with a green check because they have not yet been decomposed. <img width="943" alt="Screenshot 2023-04-26 at 1 34 59 PM" src="https://user-images.githubusercontent.com/55996087/234657144-c56b4be0-49cc-46c0-aef2-215da6825f84.png"> + + One idea to make the red 'X' appear less alarming is by using a different symbol, such as the yellow warning icon. Another idea is to have two icons per statement: one to check the correctness of the statement, and one to check whether it has been fully decomposed. + +2. **Don't require users to reduce every statement for every branch**: Each time we branch on a literal, we require users to reduce each statement even if the branch literal is irrelevant to that statement. For example, say we have the statement F ∨ G and we are branching on the literal H; this statement does not reduce further given this branch, so it should be necessary to rewrite it (since it is a bit redundant). + +2. **Make switching between the two modes more clear**: When a user toggles from one mode to the other, their current tree is not going to be compatible with the rules of the new mode. Because of this, there should be an alert to confirm whether the user intended to switch modes, and potentially warn them that they should save their progress and then clear their tree before switching over to the other mode. + +3. **Ensure all statement labels are satisfactory**: As noted above, each statement has green and red labels which indicate their antecedents and decomposition. Additionally, the status bar on the bottom of the screen is updated accordingly. While we did perform substantial visual testing, these labels and the status bar should be double checked for different statements and scenarios to make sure they are correct. -3. Ensure all the labels are correct when a statement is selected -4. Perform additional testing (bug hunting) +5. **Perform additional testing (bug hunting)**: As with any new feature, it is important to fully test it (and try to break it). Throughout the development of the project, we encountered small bugs in our implementation that we had to fix. It is definitely possible (and very likely) that there are other bugs to be addressed. From f8479fa53ed57aa78a8520b22d7a826ca2eb2054 Mon Sep 17 00:00:00 2001 From: jssunray34 <55996087+jssunray34@users.noreply.github.com> Date: Fri, 28 Apr 2023 14:01:46 -0400 Subject: [PATCH 49/54] Make it truth tree mode by default --- src/client/globals.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/client/globals.ts b/src/client/globals.ts index 9463395..58b9937 100644 --- a/src/client/globals.ts +++ b/src/client/globals.ts @@ -1,4 +1,4 @@ -let dpMode = true; +let dpMode = false; export function setDPMode(value: boolean) { dpMode = value; From ca5e5379627ce7347d26428e49e2bfddaa423db1 Mon Sep 17 00:00:00 2001 From: Jody Sunray <55996087+jssunray34@users.noreply.github.com> Date: Fri, 28 Apr 2023 14:48:53 -0400 Subject: [PATCH 50/54] Update README --- DP_developer_guide.md | 51 ++++++++++++++++++++++--------------------- 1 file changed, 26 insertions(+), 25 deletions(-) diff --git a/DP_developer_guide.md b/DP_developer_guide.md index 09c958c..de0c07e 100644 --- a/DP_developer_guide.md +++ b/DP_developer_guide.md @@ -8,8 +8,7 @@ When designing an implementation of Davis-Putnam (DP) supported by Willow, we wa 1. **By default two branches are created**: This feature was not a requirement for our project, but it made our lives easier. Plus, it was requested by Bram. :) - https://user-images.githubusercontent.com/55996087/234662990-85eb9160-8ba4-4c81-a45a-d7121f7adbcc.mov - + https://user-images.githubusercontent.com/55996087/235219000-896ab2e9-242e-4622-b0d1-42ff31878bb8.mov 1. **Implementation of the reduction rules for each type of statement**: These rules were used to reduce statements given the truth value of a literal. The reduction rules are as follows. @@ -24,72 +23,74 @@ When designing an implementation of Davis-Putnam (DP) supported by Willow, we wa 2. **Support for contradiction (⊥) and tautology (⊤) symbols**: Since our implementation relies on the use of ⊥ and ⊤, we added support for these symbols by adding them to `parser.ts`. Thus, when a user inputs a ⊥, it is treated as a `Contradiction` statement. Similarly, when a user inputs a ⊤, it is treated as a `Tautology` statement. We also created shortcuts for these symbols; the minus sign (-) is a shortcut for ⊥, and the plus sign (+) is a shortcut for ⊤. - <img width="944" alt="Screenshot 2023-04-26 at 12 29 47 PM" src="https://user-images.githubusercontent.com/55996087/234641790-b3f1955d-282c-48c5-9a38-cb3453b8fedc.png"> + <img width="943" alt="Screenshot 2023-04-28 at 1 58 26 PM" src="https://user-images.githubusercontent.com/55996087/235220100-d52635d4-8556-4061-9900-af2952e632c9.png"> -4. **Support for basic tautological statement (A ∨ ¬A)**: In order to be able to branch on a particular literal, we rely on the use of the basic tautological statement, which is the law of excluded middle. This statement is valid by default since all tautologies are valid, and is only marked with a green check if it has been decomposed into two branches A and ¬A. +4. **Support for basic tautological statement (A ∨ ¬A)**: In order to be able to branch on a particular literal, we rely on the use of the basic tautological statement, which is the law of excluded middle. This statement is valid by default since all tautologies are valid, and is only marked with a green check if it has been decomposed into the two branches A and ¬A. - <img width="945" alt="Screenshot 2023-04-26 at 12 31 19 PM" src="https://user-images.githubusercontent.com/55996087/234642070-23daacd9-c597-4b24-9baf-b2a662150b88.png"> + <img width="945" alt="Screenshot 2023-04-28 at 2 36 32 PM" src="https://user-images.githubusercontent.com/55996087/235227067-161406d1-2b9f-4c64-8473-c640bae6bc12.png"> -6. **Functional frontend that supports both DP and truth-tree methods**: We decided that the DP method should be a separate mode on the Willow site, so that by default users interact with the original truth tree method. To achieve this, we created a toggle in the menu bar. When clicked, the toggle sets a state variable `DPMode` to `true` or `false`. The value of this variable controls whether certain code additions will be run or not. +6. **Functional frontend that supports both DP and truth-tree methods**: We decided that the DP method should be a separate mode on the Willow site, so that by default users interact with the original truth tree method. To achieve this, we created a toggle in the menu bar. When clicked, the toggle sets a state variable `dpMode` to `true` or `false`. The value of this variable controls whether certain code additions will be run or not. - <img width="947" alt="Screenshot 2023-04-26 at 12 32 01 PM" src="https://user-images.githubusercontent.com/55996087/234642243-2d97c0e4-72c4-4fb9-b5d5-90a56e414893.png"> + https://user-images.githubusercontent.com/55996087/235223254-bace0694-cef4-499a-bc56-8436e3d00aff.mov -8. **Create a new version of `modifyDecomposition` to store and update antecedents called `modifyAntecedentsDP`**: When a user selects a particular statement and then right clicks on another, the `modifyDecomposition` function is called to update logical relationships within the tree, specifically a statement's decomposition and antecedents. For DP mode, we modify this function (and call it `modifyAntecedentsDP`). The main additional functionality of this function is to update the selected statement's antecedents, i.e., the statement it is reducing from and the literal it is branching on. +8. **Create a new version of `modifyDecomposition` to store and update antecedents (called `modifyAntecedentsDP`)**: When a user selects a particular statement and then right clicks on another, the `modifyDecomposition()` function is called to update logical relationships within the tree, specifically a statement's decomposition and antecedents. For DP mode, we modify this function (and call it `modifyAntecedentsDP`). The main additional functionality of this function is to update the selected statement's antecedents, i.e., the statement it is reducing from and the literal it is branching on. -10. **Statement validation for DP (`isDPValid`, which calls `validateReduction`)**: A statement is considered a valid inference if it follows from one of the reduction rules listed above. Since validation for DP differs from validation for truth trees, we decided to create a separate function called `isDPValid()`. This function checks whether a statement is valid given its antecedents (i.e., the statement it is reduced from and the branch literal). +10. **Statement validation for DP (`isDPValid()`, which calls `validateReduction()`)**: A statement is considered a valid inference if it follows from one of the reduction rules listed above. Since validation for DP differs from validation for truth trees, we decided to create a separate function called `isDPValid()`. This function checks whether a statement is valid given its antecedents (i.e., the statement it is reduced from and the branch literal). In the image below, the selected statement (highlighted in blue) is valid since it is a correct inference of H ∧ (I → F) given that we have taken the H branch (i.e., H is true). - <img width="943" alt="Screenshot 2023-04-26 at 1 42 55 PM" src="https://user-images.githubusercontent.com/55996087/234659503-bd690ee8-9c1a-4fe1-a483-a827b6ef6990.png"> + <img width="945" alt="Screenshot 2023-04-28 at 2 19 52 PM" src="https://user-images.githubusercontent.com/55996087/235223897-cc9a0272-cab9-4054-889c-613995965b73.png"> -12. **Statement decomposition checks for DP (checks that it has two statements in its decomposition, and they are both valid inferences)**: In addition to validating a statement, we also check that it has been reduced. This is similar to the checks being done for the truth tree method, i.e., a statement is only marked with a green check if it is both valid *and* decomposed completely. To verify that a statement has been reduced, we make sure that it has exactly two statements in its decomposition, and every statement in its decomposition is valid. +12. **Statement decomposition checks for DP (checks that it has two statements in its decomposition, and they are both valid inferences)**: In addition to validating a statement, we also check that it has been reduced correctly and completely. This is similar to the checks being done for the truth tree method, i.e., a statement is only marked with a green check if it is both valid *and* decomposed completely. To verify that a statement has been reduced, we make sure that it has exactly two statements in its decomposition, and every statement in its decomposition is valid. In the image below, the selected statement is not only valid but also reduced since both statements in its decomposition (⊤ and ¬I) are valid. Thus, because the selected statement is both valid and decomposed correctly, it is marked with a green check. - <img width="945" alt="Screenshot 2023-04-26 at 1 47 13 PM" src="https://user-images.githubusercontent.com/55996087/234660442-996768f7-969a-4b37-aeca-e2a265da7980.png"> + <img width="944" alt="Screenshot 2023-04-28 at 2 23 00 PM" src="https://user-images.githubusercontent.com/55996087/235224495-d4b818bf-20bc-4e4d-a9f7-d30d06a1996d.png"> 13. **Support for closed terminator**: We modified the `isClosedTerminatorValid()` function to validate a closed terminal when its antecedent is a contradiction. In the image below, the terminator is considered valid since it reduces from a contradiction (⊥). - <img width="943" alt="Screenshot 2023-04-26 at 2 16 45 PM" src="https://user-images.githubusercontent.com/55996087/234666728-048283bb-dae8-434d-8cc4-02352c5c09f0.png"> + <img width="944" alt="Screenshot 2023-04-28 at 2 31 28 PM" src="https://user-images.githubusercontent.com/55996087/235226067-28d01aac-a8d5-42a3-aeec-05b1c5dd9509.png"> 14. **Extensive testing of reduction rules (`tests/reductionRules.test.ts`)**: After implementing the reduction rules listed above, we created a test suite that tests each one works as expected since these rules are crucial to the rest of the implementation of the DP method. This test suite can be run using the command `npm run test`, which runs all tests. 16. **Updated tree node highlighting and labeling**: We simply applied the existing color scheme to the new DP functionality, with a couple language changes in the labels. As with Willow's truth tree method, when any statement is selected, there may be both green and red highlighting: - 1. *Statements highlighted in **green** indicate **antecedents*** of the currently selected node. Non-branch literals are labeled as "reduces from," and branch literals are labeled as "using." + 1. *Statements highlighted in **green** indicate **antecedents*** of the currently selected node. Statements (including non-branch literals) are labeled as "reduces from," and branch literals are labeled as "using." 2. *Statements highlighted in **red** indicate those that **reduce*** from the currently selected node. There may be zero, one, or two nodes in any given decomposition. Each node in the decomposition will be labeled with the text "reduces to." 9. **Updated status bar labeling**: In addition to modifying the tree node labels, we also modified the language in the status bar as well as added new statuses. For example, a tautology has a status to indicate it as such: - <img width="945" alt="Screenshot 2023-04-26 at 2 07 03 PM" src="https://user-images.githubusercontent.com/55996087/234664782-06325497-7f45-4849-8b61-814afb03cd20.png"> + <img width="945" alt="Screenshot 2023-04-28 at 2 36 42 PM" src="https://user-images.githubusercontent.com/55996087/235227206-56fd394e-64fe-4f04-baa7-b1fce3e4ad2f.png"> + + If a statement is both valid and reduced, it has a status like the one shown below: + + <img width="943" alt="Screenshot 2023-04-28 at 2 38 23 PM" src="https://user-images.githubusercontent.com/55996087/235227354-39786cff-5dcf-45c7-bd48-a163029d108b.png"> 11. **Support for saving and reopening files that use the DP method**: When testing our implementation on larger examples, it became tedious to have to retype the example each time the application is rerun. To resolve this, we modified the `serialize()` and `fromJSON()` functions to account for any variables we added for DP mode. This allows trees that implement DP to be saved and later reopened. 13. **Visual testing on simple examples and an example from class**: We based a lot of our preliminary tests using a small example as shown below. - <img width="944" alt="Screenshot 2023-04-26 at 2 21 01 PM" src="https://user-images.githubusercontent.com/55996087/234667725-e87636d0-8dfb-44bd-bd7c-71b5fc8574c3.png"> + Test tree 1: [simple_open_branch_DP.willow](https://github.com/Bram-Hub/Willow/blob/tautology_dp/test_trees/simple_open_branch_DP.willow) - This example has only open branches, and it's fairly simple, so we did additional tests using an example from homework 4, as shown below. + This example has only open branches, and it's fairly simple, so we did additional tests using an example from homework 4, linked below. - <img width="944" alt="Screenshot 2023-04-26 at 2 23 21 PM" src="https://user-images.githubusercontent.com/55996087/234668290-0666b233-f78c-4d57-99dc-8cd0b1dca282.png"> - <img width="944" alt="Screenshot 2023-04-26 at 2 23 39 PM" src="https://user-images.githubusercontent.com/55996087/234668319-af5684a3-772c-4de7-84c2-ffd0d3b647c7.png"> - <img width="941" alt="Screenshot 2023-04-26 at 2 23 47 PM" src="https://user-images.githubusercontent.com/55996087/234668346-8bcf3eab-2089-4b64-b226-5790ee3c4e8c.png"> + Test tree 2: [closed_branches_DP_hw4.willow](https://github.com/Bram-Hub/Willow/blob/tautology_dp/test_trees/closed_branches_DP_hw4.willow) ## Tasks that still need to be completed The implementation of DP in Willow is completely usable in its current state. However, there are a few action items that we were not able to get to, and more thorough testing will need to be done to ensure that the feature is production-ready. -1. **Handle unchecked statements that have not been fully decomposed**: As shown in the image below, there are a few statements that are not marked with a green check because they have not yet been decomposed. +1. **Handle unchecked statements that have not been fully reduced**: As shown in the image below, it's possible for a valid tree to have statements that are not marked with a green check (since they have not yet been reduced). - <img width="943" alt="Screenshot 2023-04-26 at 1 34 59 PM" src="https://user-images.githubusercontent.com/55996087/234657144-c56b4be0-49cc-46c0-aef2-215da6825f84.png"> + <img width="944" alt="Screenshot 2023-04-28 at 2 42 47 PM" src="https://user-images.githubusercontent.com/55996087/235228119-56cbf2a5-285d-46f7-a4ac-0c85917e0b68.png"> - One idea to make the red 'X' appear less alarming is by using a different symbol, such as the yellow warning icon. Another idea is to have two icons per statement: one to check the correctness of the statement, and one to check whether it has been fully decomposed. + The tree still evaluates as valid since each branch is terminated, but we didn't think it would be appropriate to check off non-reduced statements. One idea to make the red 'X' appear less alarming is by using a different symbol, such as the yellow warning icon. Another idea is to have two icons per statement: one to check the correctness of the statement, and one to check whether it has been fully reduced. -2. **Don't require users to reduce every statement for every branch**: Each time we branch on a literal, we require users to reduce each statement even if the branch literal is irrelevant to that statement. For example, say we have the statement F ∨ G and we are branching on the literal H; this statement does not reduce further given this branch, so it should be necessary to rewrite it (since it is a bit redundant). +2. **Don't require users to reduce every statement for every branch**: Each time we branch on a literal, we require users to reduce each statement even if the branch literal is irrelevant to that statement. For example, say we have the statement F ∨ G and we are branching on the literal H; this statement does not reduce further given this branch, so it shouldn't be necessary to have to rewrite it (since it is a bit redundant). -2. **Make switching between the two modes more clear**: When a user toggles from one mode to the other, their current tree is not going to be compatible with the rules of the new mode. Because of this, there should be an alert to confirm whether the user intended to switch modes, and potentially warn them that they should save their progress and then clear their tree before switching over to the other mode. +2. **Make switching between the two modes more clear**: When a user toggles from one mode to the other, their current tree is not going to be compatible with the rules of the new mode. Because of this, there should be an alert to confirm whether the user intended to switch modes, and potentially warn them that they should save their progress. Their tree would then be cleared before switching over to the other mode. 3. **Ensure all statement labels are satisfactory**: As noted above, each statement has green and red labels which indicate their antecedents and decomposition. Additionally, the status bar on the bottom of the screen is updated accordingly. While we did perform substantial visual testing, these labels and the status bar should be double checked for different statements and scenarios to make sure they are correct. From 80c86e6d7a0adbe0a5491368f9302b3d47d3cea8 Mon Sep 17 00:00:00 2001 From: Jody Sunray <55996087+jssunray34@users.noreply.github.com> Date: Fri, 28 Apr 2023 14:58:04 -0400 Subject: [PATCH 51/54] Update user guide --- DP_userguide.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/DP_userguide.md b/DP_userguide.md index bb356d0..d71afe3 100644 --- a/DP_userguide.md +++ b/DP_userguide.md @@ -1,18 +1,18 @@ # Davis-Putnam User's Guide -Refer to [userguide](userguide.md) for instructions on the Willow interface. -Refer to [DP_developer_guide](DP_developer_guide.md) if you are interested in extending existing functionality. +- Refer to [userguide.md](userguide.md) for instructions on the Willow interface. +- Refer to [DP_developer_guide.md](DP_developer_guide.md) if you are interested in extending existing functionality for Davis-Putnam. This guide will walk through how to verify whether a set of statements is satisfiable using Davis-Putnam. ## What is Davis-Putnam? -[Davis Putnam](https://en.wikipedia.org/wiki/Davis%E2%80%93Putnam_algorithm), similar to truth trees, is another procedue used to determine if a set of statements is satisfiable. This is achieved by recursively selecting a literal, and creating a branch for each of the possible states. A literal can be either `True` or `False`, resulting in the creation of at most 2 states per literal. Statements are reduce with regard to some literal. This procedure halts once all states have either reached a contradiction or is deemed satisfiable. +[Davis Putnam](https://en.wikipedia.org/wiki/Davis%E2%80%93Putnam_algorithm), similar to truth trees, is another procedue used to determine if a set of statements is satisfiable. This is achieved by recursively selecting a literal, and creating a branch for each of the possible states. A literal can be either `true` or `false`, resulting in the creation of at most 2 states per literal. Statements are reduced with regard to some literal. This procedure halts once all states have either reached a contradiction or are deemed satisfiable. The following **Reduction Rules** can be used to reduce statements with respect to the truthy value of some literal. -- `⊤` means a literal is True -- `⊥` means a literal is False. +- `⊤` means a literal is true +- `⊥` means a literal is false. | Not | And | Or | Conditional | Biconditional | From 2e02ccf4692d1f0d98c9c57a5ae2ec1c0c73e08a Mon Sep 17 00:00:00 2001 From: Jody Sunray <55996087+jssunray34@users.noreply.github.com> Date: Fri, 28 Apr 2023 15:08:39 -0400 Subject: [PATCH 52/54] Update user guide --- DP_userguide.md | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/DP_userguide.md b/DP_userguide.md index d71afe3..284fbf7 100644 --- a/DP_userguide.md +++ b/DP_userguide.md @@ -1,9 +1,9 @@ # Davis-Putnam User's Guide - Refer to [userguide.md](userguide.md) for instructions on the Willow interface. -- Refer to [DP_developer_guide.md](DP_developer_guide.md) if you are interested in extending existing functionality for Davis-Putnam. +- Refer to [DP_developer_guide.md](DP_developer_guide.md) if you are interested in extending the existing functionality for Davis-Putnam. -This guide will walk through how to verify whether a set of statements is satisfiable using Davis-Putnam. +This guide will walk you through how to verify whether a set of statements is satisfiable using Davis-Putnam. ## What is Davis-Putnam? @@ -30,12 +30,11 @@ We will walk through a simple example. Is the following clause satisfiable? ![Clause](https://user-images.githubusercontent.com/29582421/234971620-2e1994ff-81e8-40b4-a66b-5a8e7acfef1a.jpg) 1. **Select Mode** -Ensure your are in Davis-Putnam Mode. The two different modes have different rules that can be used to satify a set of statements. -![DP Mode](https://user-images.githubusercontent.com/29582421/234759174-d7114e69-6d88-44e7-959f-6708ab26e293.jpg) +Ensure your are in Davis-Putnam Mode. The two different modes have different rules that can be used to satisfy a set of statements. +![DP Mode](https://user-images.githubusercontent.com/55996087/235231376-7ccd563f-edbd-4bc1-8eff-a47664e8c164.png) - -2. **Adding tautologies** -Every variable can be set to the true or false. We create this tautology. +2. **Adding tautologies** +We create the basic tautology (law of excluded middle). ![Creating tautology](https://user-images.githubusercontent.com/29582421/234971872-905d907c-7d87-421b-a020-6c87c25b2f23.jpg) <!-- Tautologies are formed by disjuncting any statement $\psi$ with $\neg \psi$ @@ -43,17 +42,16 @@ Tautologies are formed by disjuncting any statement $\psi$ with $\neg \psi$ Intention is for tautologies to be literal (not tested with general statements) --> -3. **Branching off tautologies** +3. **Branching off tautologies**. Decompose the tautology to create the two possible states. For each of the two values, select where the statement came from. ![Decompositions](https://user-images.githubusercontent.com/29582421/234972437-47d21adc-1bd0-465e-a5da-5f13291bc17c.jpg) ![Premise](https://user-images.githubusercontent.com/29582421/234972594-4a0f52e7-dd9f-4058-86d7-090ebf0d8e0c.jpg) -4. **Reduce Statements** -For each statement in parent branch, reduce them with respect to the literal branch. Notice that statement gets checked off when they a +4. **Reduce Statements** +For each statement in the parent branch, reduce it with respect to the literal branch. Notice that statements get checked off when they are both valid *and* reduced. ![R1](https://user-images.githubusercontent.com/29582421/234977549-90c491d7-94a7-463d-ba9c-7f6fc9e18e51.jpg) ![R2](https://user-images.githubusercontent.com/29582421/234977681-ac6f0160-fe36-48ff-af3c-5cbf904dd51f.jpg) - -5. **Validating Tree** +5. **Validating Tree** +Click the "Check tree" button in the Evaluate dropdown of the header to validate your completed tree. ![Check](https://user-images.githubusercontent.com/29582421/234977819-ba52f194-1b9c-46fc-bbe3-044cf30ef490.jpg) - From cae7cbb4d358aabd86dbd523eb61de9333ff6b34 Mon Sep 17 00:00:00 2001 From: Jody Sunray <55996087+jssunray34@users.noreply.github.com> Date: Fri, 28 Apr 2023 15:09:46 -0400 Subject: [PATCH 53/54] Update user guide --- DP_userguide.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/DP_userguide.md b/DP_userguide.md index 284fbf7..65d271b 100644 --- a/DP_userguide.md +++ b/DP_userguide.md @@ -30,7 +30,7 @@ We will walk through a simple example. Is the following clause satisfiable? ![Clause](https://user-images.githubusercontent.com/29582421/234971620-2e1994ff-81e8-40b4-a66b-5a8e7acfef1a.jpg) 1. **Select Mode** -Ensure your are in Davis-Putnam Mode. The two different modes have different rules that can be used to satisfy a set of statements. +Ensure your are in Davis-Putnam mode by toggling the mode button in the header. The two different modes have different rules that can be used to satisfy a set of statements. ![DP Mode](https://user-images.githubusercontent.com/55996087/235231376-7ccd563f-edbd-4bc1-8eff-a47664e8c164.png) 2. **Adding tautologies** From 24b2e8314a0394250b03a1333b85bf96fa4b8996 Mon Sep 17 00:00:00 2001 From: Jody Sunray <55996087+jssunray34@users.noreply.github.com> Date: Fri, 28 Apr 2023 15:42:00 -0400 Subject: [PATCH 54/54] Update developer guide --- DP_developer_guide.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/DP_developer_guide.md b/DP_developer_guide.md index de0c07e..9543a50 100644 --- a/DP_developer_guide.md +++ b/DP_developer_guide.md @@ -6,6 +6,8 @@ When designing an implementation of Davis-Putnam (DP) supported by Willow, we wanted to utilize as much of the existing functionality as possible. Below are the major changes and additions that were made. +**Note**: old `.willow` files are no longer supported. This is due to DP statements having 2 antecedents (a parent statement and literal branch), changing the structure of the tree. + 1. **By default two branches are created**: This feature was not a requirement for our project, but it made our lives easier. Plus, it was requested by Bram. :) https://user-images.githubusercontent.com/55996087/235219000-896ab2e9-242e-4622-b0d1-42ff31878bb8.mov