예제 #1
0
class Tuxie(form.Form):
    """Tuxie says"""

    text = fields.Markdown("Text")
    width = fields.Expression("Tuxie width", default="400")
    image = fields.Select("Image",
                          options=["tuxie", "jigglypuff", "pikachu"],
                          default="tuxie")
    position = fields.Select("Bubble position",
                             options=["left", "right"],
                             default="right")

    template = """
예제 #2
0
class Survey(form.Form):
    """Marked question"""

    name = fields.Field("Survey name")
    answer = fields.Expression("Your answer", nosave=True, editable=True)
    correct_answer = fields.Expression("Correct Answer", required=True)
    max_error = fields.Expression("Maximal error", default=0)
    before = fields.Markdown("Before field text", default="Your answer:")
    after = fields.Markdown("After field text")
    question = fields.Markdown("Question")
    marking_type = fields.Select(
        "Marking type",
        options=["Default", "Numerical", "Fraction"],
        default="Default",
    )

    template = """
        <p v-if="config.edit || payload.question">`question`</p>
        <widget-settings v-if="config.edit">
            <config-option name="Correct Answer">`correct_answer`</config-option>
            <config-option name="Tolerated error">`max_error`</config-option>
            <config-option name="Marking type">`marking_type`</config-option>
        </widget-settings>
        <survey
            :config="config"
            :name="payload.name"
            :showStats="config.authState.loggedIn"
            :correct="computed.correct"
            :value="payload.answer">
            <span v-if="config.edit || payload.before">`before`</span>
            `answer`
            <span v-if="config.edit || payload.after">`after`</span>
        </survey>
    """

    _total_marks = 1

    @property
    def _marks(self):
        return 1 if self.correct else 0

    @fields.computed("Correct", field=fields.Boolean)
    def correct(self):
        if self.answer is None:
            return False
        elif self.marking_type == "Numerical":
            numbers = sympy.core.numbers
            if not self.answer.func in [numbers.Float, numbers.Integer]:
                return False
        elif self.marking_type == "Fraction":
            if not re.search(r"^[0-9\s/]*$", self._answer):
                return False
        return (sympy.Abs(sympy.nsimplify(self.answer - self.correct_answer))
                <= self.max_error)

    def validate(self):
        if not self.name:
            self.name = str(uuid.uuid1())
예제 #3
0
class Foo(form.Form):
    field = fields.Field("Field", desc="description")
    equation = fields.Equation("Equation")
    real = fields.Expression("Real number")
    markdown = fields.Markdown("Markdown")
    matrix = fields.Matrix("Matrix")
    email = fields.Email("Email")
    password = fields.Password("Email")
    protected = fields.Field("Protected", default="Protected", protected=True)
    select = fields.Select("Select", options=["Hi", "Hello"])

    @fields.constraint("Contraint", default=True)
    def constraint(self):
        return self.real > 0

    @fields.computed("Computed")
    def computed_field(self):
        return self.field
class FractionOperations(form.Form):
    """Fractions"""

    template = "Calculate `fraction_1` `operation` `fraction_2` `solution`"

    fraction_1 = fields.Expression("fraction 1", required=True)
    fraction_2 = fields.Expression("fraction 2", required=True)
    operation = fields.Select("operation",
                              options=["+", "-", "×", "÷"],
                              default="+")

    @fields.computed("Solution")
    def solution(self):
        operations = {
            "+": sympy.Add,
            "-": lambda a, b: a - b,
            "×": sympy.Mul,
            "÷": lambda a, b: a / b,
        }
        if self.operation:
            return sympy.simplify(operations[self.operation](self.fraction_1,
                                                             self.fraction_2))

    a = fields.RandomNumber("a")
    b = fields.RandomNumber("b")
    c = fields.RandomNumber("c")
    d = fields.RandomNumber("d")
    op = fields.RandomNumber("op", default=["+", "-", "×", "÷"])

    def generator(self):
        self.fraction_1 = self.a / self.b
        self.fraction_2 = self.c / self.d
        self.operation = self.op

    @fields.range_constraint("non-zero numbers",
                             default=True,
                             hidden=True,
                             protected=True)
    def non_zero_numbers(self):
        self.a -= {0}
        self.b -= {0}
        self.c -= {0}
        self.d -= {0}
예제 #5
0
class Image(form.Form):
    """Image"""

    src = fields.Field("Image URL", required=True)
    height = fields.Expression("Original height", default=0)
    width = fields.Expression("Original width", default=0)
    zoom = fields.Expression("Zoom", default=1)
    position = fields.Select("Position",
                             options=["left", "right", "center"],
                             default="center")

    template = """
        <widget-settings v-if="config.edit">
            <config-option name="Zoom">`zoom`</config-option>
            <config-option name="Position">`position`</config-option>
        </widget-settings>
        `image`
    """

    @fields.computed("Image", field=fields.Html, nohide=True)
    def image(self):
        style = f"float:{self.position}" if self.position != "center" else ""
        return f"""
            <img src="{self.src}"
                width="{self.zoom * self.width}"
                style="{style}"
                height="{self.zoom * self.height}"/>"""

    def validate(self):
        if "," in self.src:
            data = self.src.split(",")
            image_hash = hashlib.sha1(data[1].encode("utf-8")).hexdigest()
            ext = mimetypes.guess_extension(data[0][5:data[0].find(";")])
            folder = os.environ.get("STORAGE", "./storage/")
            filename = image_hash + ext
            with open(folder + filename, "wb") as f:
                image = base64.b64decode(data[1])
                f.write(image)
            self.src = "/storage/" + filename
        if not self.width:
            path = os.environ.get("STORAGE", "./storage/") + self.src[9:]
            self.width, self.height = PIL.Image.open(path).size
            self.zoom = 1
예제 #6
0
class CircleEquation(form.Form):
    """Circle radius and center"""

    template = "Find the `info` of the circle `equation` `solution`"

    equation = fields.Equation("Equation", required=True)
    info = fields.Select("Info", options=["radius", "center"])

    @fields.computed("Radius/Center")
    def solution(self):
        (a, h, k, x, y), r = (
            sympy.symbols("a h k x y"),
            sympy.symbols("r", positive=True),
        )
        formula = a * ((x - h) ** 2 + (y - k) ** 2 - r ** 2)
        equation = sympy.expand(self.equation.args[0] - self.equation.args[1] - formula)
        system = [equation.coeff(*t) for t in [(x, 2), (y, 2), (x, 1), (y, 1), (x, 0)]]
        values = sympy.solve(system, (a, r, h, k), dict=True)
        if not values:
            raise ValueError(f"{repr(self.equation)} is not an equation for a circle")
        values = values[0]
        return values[r] if self.info == "radius" else (values[h], values[k])
예제 #7
0
class MultipleChoice(form.Form):
    """Multiple Choice"""

    name = fields.Field("Survey name")
    answer = fields.Select("Your answer",
                           nosave=True,
                           options=["", "A", "B", "C", "D", "E"])
    correct_answer = fields.Select("Correct Answer",
                                   options=["A", "B", "C", "D", "E"],
                                   default="A")
    question = fields.Markdown("Question")

    option_a = fields.Markdown("Option A")
    option_b = fields.Markdown("Option B")
    option_c = fields.Markdown("Option C")
    option_d = fields.Markdown("Option D")
    option_e = fields.Markdown("Option E")

    @property
    def template(self):
        buttons = []
        for ltr in ["a", "b", "c", "d", "e"]:
            buttons.append(f"""
                <span v-if="!config.edit">
                    <span v-if="payload.option_{ltr}">
                        <b-button @click="$set(payload, 'answer', '{ltr.upper()}')"
                            type="is-primary"
                            v-if="'{ltr.upper()}' === payload.answer">
                            `option_{ltr}`
                        </b-button>
                        <b-button @click="$set(payload, 'answer', '{ltr.upper()}')" v-else>
                            `option_{ltr}`
                        </b-button>
                    </span>
                </span>
                <span v-else>
                    <b-button>`option_{ltr}`</b-button>
                </span>
            """)
        return f"""
            <p v-if="config.edit || payload.question">`question`</p>
            <widget-settings v-if="config.edit">
                <config-option name="Correct Answer">`correct_answer`</config-option>
            </widget-settings>
            <survey
                :config="config"
                :name="payload.name"
                :showStats="config.authState.loggedIn"
                :correct="computed.correct"
                :max-attempts="1"
                :value="payload.answer">
                <span class="buttons are-large">
                    {"".join(buttons)}
                </span>
            </survey>
    """

    @property
    def _marks(self):
        return 1 if self.correct else 0

    @fields.computed("Correct", field=fields.Boolean)
    def correct(self):
        return self.answer == self.correct_answer

    def validate(self):
        if not self.name:
            self.name = str(uuid.uuid1())