Commit 3c5f9db7 authored by Vladimír Štill's avatar Vladimír Štill
Browse files

evalweb: Add a bunch of type annotations & fix some types

parent 3724d735
Loading
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -5,7 +5,7 @@ from . import evalweb

# taken from tutorial on flask.palletsprojects.com/en/1.1.x/tutorial

def create_app(test_config=None):
def create_app(test_config=None) -> Flask:
    # create and configure the app
    app = Flask(__name__, instance_relative_config=True)
    app.config.from_mapping(SECRET_KEY='dev')
+8 −6
Original line number Diff line number Diff line
from flask import Blueprint, render_template, request
from flask_wtf import FlaskForm
from wtforms import RadioField
from flask_wtf import FlaskForm  # type: ignore
from wtforms import RadioField   # type: ignore
from lib.parsing.parser import ParsingError
from evalweb.web_checker import WebChecker, Language
from evalweb.examples import examples, convert_examples
@@ -49,7 +49,7 @@ class ConvertForm(FlaskForm):


@bp.route('/compare', methods=('GET', 'POST'))
def compare():
def compare() -> str:
    student_form = TaskForm(prefix='student_form')
    teacher_form = TypeForm(prefix='teacher_form')
    student_area = ""  # areas remembers user input or replace it with examples
@@ -79,6 +79,8 @@ def compare():
            missing_word_ce = checker.eq.right_counterexample
            inf = checker.eq.inf

        assert checker.teacher is not None
        assert checker.student is not None
        return render_template('result_compare.html', compare=True, ok=result,
                               inf=inf, task_solved=checker.task_solved,
                               alphabets=checker.alphabets,
@@ -108,7 +110,7 @@ def compare():

# analogical to compare, only with just one input formalism
@bp.route('/convert', methods=('GET', 'POST'))
def convert():
def convert() -> str:
    student_form = TypeForm(prefix='student_form')
    task_form = ConvertForm(prefix='task_form')
    student_area = ""
@@ -149,10 +151,10 @@ def convert():


@bp.route('/userref')
def userref():
def userref() -> str:
    return render_template('userref.html')


@bp.route('/about')
def about():
def about() -> str:
    return render_template('about.html')
+1 −1
Original line number Diff line number Diff line
@@ -11,7 +11,7 @@ teacher_dfa_total = parser.dfa_to_str(parser.str_to_dfa(teacher_dfa).total())
teacher_efa = r"(A,a)={B} (A,\e)={D} (B,b)={A} final={A,D}"
student_nfa = parser.nfa_to_str(parser.str_to_nfa(teacher_efa)
                                      .eliminate_epsilon())
student_gra = r"S -> aS' | \e\nS' -> bA | b\nA -> aS'"
student_gra = "S -> aS' | \\e\nS' -> bA | b\nA -> aS'"
student_reg = "(ab)^*"
student_efa = r"(A,a)={B} (A,\e)={D} (B,b)={C} (C,a)={B} final={C,D}"

+20 −19
Original line number Diff line number Diff line
@@ -2,7 +2,7 @@ import lib.reg as reg
from lib.parsing.parser import Parser, ParsingError
from lib.checker import transform, dfa_transform, nfa_transform, check_task, \
                        check_alphabets
from typing import List, Tuple
from typing import List, Optional
from enum import Enum
import enum

@@ -18,14 +18,7 @@ class Language: # contains information about formalism and its language
    def __init__(self, string: str, task: str = "DFA") -> None:
        self.string = string
        self.task = task
        self.dfa = None
        self.minimal = None
        self.size = None
        self.sizename = None
        self.example = None
        self.gen_lang_html()

    def gen_lang_html(self) -> None:

        parser = Parser()
        dfa = dfa_transform(self.string, self.task)
        self.minimal = parser.dfa_to_str(dfa.minimize().canonize())
@@ -53,25 +46,27 @@ class Language: # contains information about formalism and its language
    def gen_is_task(self, task: str) -> str:
        teacher = "NFA" if self.task == "EFA" else self.task
        parser = Parser()
        assert self.dfa is not None
        dfa = parser.dfa_to_str(self.dfa.canonize())
        return f"{teacher}-{task}:{dfa}"


class WebChecker:
    def __init__(self, student_string: str, task: str):
    def __init__(self, student_string: str, task: str) -> None:
        self.student_string = student_string
        self.task = task
        self.task_solved = ""
        self.alphabets = ""
        self.eq = None
        self.teacher = None
        self.student = None
        self.is_task = None
        self.img_src = None
        self.languages = [None, None, None, None]
        self.eq: Optional[reg.IsEquivalentResult] = None
        self.teacher: Optional[Language] = None
        self.student: Optional[Language] = None
        self.is_task: Optional[str] = None
        self.img_src: Optional[str] = None
        self.languages: List[Optional[Language]] = [None, None, None, None]

    # nearly equivalent to dfa_task in fja_checker (for IS ROPOTs)
    def dfa_task(self, teacher_type, teacher_string, task, student_string):
    def dfa_task(self, teacher_type: str, teacher_string: str,
                 task: str, student_string: str) -> bool:
        try:
            teacher = Language(string=teacher_string, task=teacher_type)
            student = Language(string=student_string, task=self.task)
@@ -103,6 +98,7 @@ class WebChecker:
            return False

        self.eq = reg.DFA.is_equivalent(student.dfa, teacher.dfa)
        assert self.eq is not None

        self.img_src = self.relation(self.eq.left_counterexample is None
                                     and self.eq.right_counterexample is None)
@@ -112,7 +108,7 @@ class WebChecker:
            return True
        return False

    def compare(self, teacher_string: str, teacher_type: str):
    def compare(self, teacher_string: str, teacher_type: str) -> bool:
        # signal.alarm(50)  # from fja_checker: here would kill the web
        try:
            return self.dfa_task(teacher_type=teacher_type,
@@ -124,7 +120,7 @@ class WebChecker:
            return ex.args
            # raise ParsingError(ex.args)

    def convert(self, student_type):
    def convert(self, student_type: str) -> str:
        try:
            parser = Parser()
            if self.task in {"DFA", "TOT", "MIN"}:
@@ -157,14 +153,19 @@ class WebChecker:
            print("Error inside of web checker:", ex.args)

    def relation(self, eq: bool) -> str:
        assert self.teacher is not None
        assert self.student is not None
        student = self.student.dfa
        teacher = self.teacher.dfa
        assert student is not None
        assert teacher is not None

        # language 0 on picture: complement of both
        self.languages[0] = self.language(
                              (reg.DFA.union(teacher, student)).complement())

        if not eq:
            assert self.eq is not None
            if self.eq.left_counterexample is not None:  # extra word
                if self.eq.right_counterexample is not None:  # missing word
                    intersection = reg.DFA.intersection(student, teacher)