Elementary School Four Arithmetic Question Generator (JavaScript)

1. Introducción

  • Este programa es un programa generado por cuatro operaciones de un alumno con una interfaz gráfica
  • Autor: Tronco de Yu Wang Shengyuan
  • dirección de github: https://github.com/yushengyuan123/caculation
  • Marco técnico: JavaScript + electron + node.js

2. Análisis de efectividad

  • El mayor costo de rendimiento de todo el proceso debería ser la generación de respuestas. La generación de respuestas requiere la conversión de expresiones de infijo en sufijos, y luego procesar las expresiones de sufijo para obtener las respuestas. Todo el proceso requiere juicios lógicos más complicados.  

Tercero, el proceso de diseño.

  • Debido a la cooperación de dos personas, el proyecto se divide principalmente en dos divisiones de trabajo, una persona es responsable de las operaciones de archivos y la escritura de páginas html, y la otra persona es responsable de escribir la lógica de negocios relacionada con la fórmula de cálculo, incluida la generación aleatoria y la generación de resultados de la fórmula de cálculo. Encapsula todas las funciones relacionadas con las fórmulas de cálculo y bríndalas a los estudiantes responsables de los documentos y la escritura de la página para llamar. El diagrama de relación básico es el siguiente:
    img
  • Debido al uso de la interfaz gráfica, no se utilizan comandos de consola para repetir.
  • La interfaz gráfica se muestra a continuación:
    img

Cuatro, descripción del código (aquí solo se muestra el código central de la empresa)

  • Algoritmo computacional generado aleatoriamente.
const _isNumber = require('../share/utils').isNumber
const getRandom = require('../share/utils').getRandom
const getResult = require('./stack')
const print = require('../share/utils').printf
const _ = require('underscore')

const operator = ['+', '-', '*', '÷']

const _toString = Object.prototype.toString

/**
 * 随机获得一个运算符
 * @returns {string}
 */
function getOperator() {
    return operator[Math.floor(Math.random() * (3 + 1))]
}

/**
 *
 * @param qus 提交的答案
 * @param ans 正确的答案
 * @returns {*}
 */
function verifyAnswer(qus, ans) {
    let statistic
    if (_toString.call(qus) !== '[object Array]' || _toString.call(ans) !== '[object Array]') {
        throw new Error('Please dont set the poison for my code')
    }
    return statistic
}


//判断运算式子结果是否大于0
const _positive = function (expression) {
    return getResult(expression) >= 0
}

/**
 * 生成答案
 * @param qus 传入生成计算式子返回的数组
 * @returns {['1', '2', ...]}
 */
const answer = function (qus) {
    if (_toString.call(qus) !== '[object Array]') {
        throw new Error(qus + 'is not a Array')
    }
    let answer = []
    for (let i = 0; i < qus.length; i++) {
        let temp = qus[i].split('=')[0]
        temp = temp.substring(0, temp.length - 1)
        answer.push(getResult(temp))
    }
    return answer
}


/**
 * 生成计算表达式
 * @param number 传入你要生成多少条式子的数量
 * @returns {['1 + 1 =', ...]}
 */
const createExpression = function(number) {
    if(!_isNumber(number)) {
        throw new Error(`The ${number} is not a number type, please check again!`)
    }
    let result = []
    let operands = null
    let output = ''
    let index = 0
    while(index !== number) {
        operands = Math.floor(Math.random()* 3 + 1)
        switch(operands) {
            case 1: {
                output = `${getRandom()} ${getOperator()} ${getRandom()}`
                if(_positive(output)) {
                    result.push(`${output} = `)
                    index++
                }
                break
            }
            case 2: {
                output = `${getRandom()} ${getOperator()} ${getRandom()} ${getOperator()} ${getRandom()}`
                if(_positive(output)) {
                    result.push(`${output} = `)
                    index++
                }
                break
            }
            case 3: {
                output = `${getRandom()} ${getOperator()} ${getRandom()} ${getOperator()} ${getRandom()} ${getOperator()} ${getRandom()}`
                if(_positive(output)) {
                    result.push(`${output} = `)
                    index++
                }
                break
            }
            default: {
                throw new Error('operands is not in the range of 3')
            }
        }
    }
    return result
}

module.exports = {
    createExpression: createExpression,
    answer: answer
}
  • Genera al azar fracciones o números naturales
//判断是假分数还是带分数
const bandFraction = function (fraction) {
    let temp = fraction.split('/')
    let result = Number(temp[0]) / Number(temp[1])
    if (result > 1) {
        return `${Math.floor(result)}^${Number(temp[0] - Number(Math.floor(result)) * temp[1] + 1)}/${temp[1]}`
    } else if (result === 1){
        return `1`
    } else {
        return fraction
    }
}

//随机返回分数或者是整数
//Math.floor(Math.random()*(m-n+1)+n)
const getRandom = function() {
    //随机决定是生成整数还是分数1表示整数,0表示分数
    let isZ = Math.round(Math.random())
    if(isZ) {
        return Math.floor(Math.random() * 9 + 1)
    } else {
        let Molecule = Math.ceil(Math.random() * 9 + 1)
        let Denominator = Math.ceil(Math.random() * (Molecule * 10  - 1 + 1) + 1)
        return bandFraction(`${Denominator}/${Molecule}`)
    }
}

La idea de generar ideas: la función getRandom decide si generar aleatoriamente una fracción o un número natural, y utiliza una variable que genera aleatoriamente 0 y 1 para decidir cuál generar, 0 genera una fracción y 1 genera un número natural. Al generar una expresión de cálculo, una variable aleatoria que genera 1-3 también se usa para determinar la longitud de la fórmula de cálculo.1 significa dos operandos y un símbolo de cálculo, 2 significa tres operandos y dos operadores, y 3 Por analogía Cada operando que genera una expresión de cálculo llama a getRandom una vez para generar un operando aleatorio. Esta es la idea general.

  • Código de representación del resultado del cálculo
/**
 * 符号优先级比较
 * @param operator_one
 * @param operator_two
 * @returns {boolean}
 */
const operatorRank = function (operator_one, operator_two) {
    if(operator_one === void 0) {
        throw new Error('you not have a expression')
    }
    if (operator_two === undefined) {
        return true
    }
    if (operator_one === '/' || operator_one === '*') {
        return !(operator_two === '/' || operator_two === '*');
    } else if (operator_one === '+' || operator_one === '-'){
        return operator_two === ')' || operator_two === '(';
    } else if (operator_two === ')' || operator_two === '(') {
        return false
    }
}

const changeFormat = function (array) {
    let freeback = array.slice(0)
    for (let i = 0; i < array.length; i++) {
        if (array[i] === '÷') {
            freeback[i] = '/'
        }
        if (array[i].length > 1 && array[i].indexOf('/') !== -1) {
            if (array[i].indexOf('^') !== -1) {
                let temp = freeback[i].split('/')
                let one = temp[0].split('^')
                freeback[i] = Number(one[0]) + Number(one[1] / temp[1])
            } else {
                let temp = freeback[i].split('/')
                freeback[i] = temp[0] / temp[1]
            }
        }
    }
    return freeback
}

/**
 * 计算器
 * @param expressionArray
 * @returns {[]}
 */
const counter = function (expressionArray) {
    expressionArray = changeFormat(expressionArray.split(' '))
    let outStack = []
    let operatorStack = []
    for (let i = 0; i < expressionArray.length; i++) {
        if (typeof Number(expressionArray[i]) == "number"
            && !isNaN(Number(expressionArray[i]))) {
            outStack.push(expressionArray[i])
        } else if (expressionArray[i] === '(') {
            operatorStack.push(expressionArray[i])
        } else if (expressionArray[i] === '+'
            || expressionArray[i] === '-'
            || expressionArray[i] === '*'
            || expressionArray[i] === '/') {
            if (operatorRank(expressionArray[i], operatorStack[operatorStack.length-1])) {
                operatorStack.push(expressionArray[i])
            } else {
                outStack.push(operatorStack.pop())
                while (!operatorRank(expressionArray[i], operatorStack[operatorStack.length-1])) {
                    outStack.push(operatorStack.pop())
                }
                operatorStack.push(expressionArray[i])
            }
        } else if (expressionArray[i] === ')') {
            while (operatorStack[operatorStack.length-1] !== '(') {
                outStack.push(operatorStack.pop())
            }
            if (operatorStack[operatorStack.length-1] === '(') {
                operatorStack.pop()
            }
        }
        if (i === expressionArray.length - 1) {
            while (operatorStack.length !== 0) {
                outStack.push(operatorStack.pop())
            }
        }
    }
    return outStack
}

/**
 * 答案产生器
 * @param suffix
 * @returns {[]}
 */
const getResult = function (suffix) {
    suffix = counter(suffix)
    let resultStack = []
    for (let i = 0; i < suffix.length; i++) {
        if (typeof Number(suffix[i]) == "number"
            && !isNaN(Number(suffix[i]))) {
            resultStack.push(Number(suffix[i]))
        } else {
            switch (suffix[i]) {
                case '+': {
                    resultStack.push(Number(resultStack.pop()) + Number(resultStack.pop()))
                    break
                }
                case '-': {
                    let reduce = Number(resultStack.pop())
                    let beReduce = Number(resultStack.pop())
                    resultStack.push(beReduce - reduce)
                    break
                }
                case '*': {
                    resultStack.push(Number(resultStack.pop()) * Number(resultStack.pop()))
                    break
                }
                case '/': {
                    let reduce = Number(resultStack.pop())
                    let beReduce = Number(resultStack.pop())
                    resultStack.push(beReduce / reduce)
                    break
                }
                default: {
                    throw new Error('illegal symbol ')
                }
            }
        }
    }
    return resultStack[0]
}

module.exports = getResult
  • La respuesta genera las siguientes ideas:
    • Al principio, el método eval () se adoptó por conveniencia. Puede analizar una fórmula de cálculo en el resultado de un libro de cálculo, pero tiene varios defectos. El primero es que puede usarse para la inyección de código, lo cual es muy peligroso. En segundo lugar, si la fórmula de cálculo tiene una fracción, porque la fracción es esencialmente una fórmula de división con prioridad, directamente usando eval, no puede reconocer si usted es una fracción o una división simple. Tercero, es demasiado tonto y parece ser menos técnico.
    • Teniendo en cuenta estos factores, decidí dejar el uso de este método, aunque es muy conveniente, pero hay muchos inconvenientes. Finalmente, escribí una calculadora yo mismo, que es convertir una expresión de infijo en una expresión de sufijo, y usar la expresión de sufijo para calcular. Finalmente, se obtiene el resultado. El código anterior es convertir la expresión de infijo en una expresión de sufijo y finalmente procesar el resultado del cálculo de la expresión de sufijo. El proceso de conversión de infijo a sufijo no se introduce aquí.

Cinco, operación de prueba

  • Los resultados de la prueba de 10 preguntas generadas aleatoriamente se muestran en la figura:
    img

El ^ en el título representa el puntaje mixto. Hice 10 preguntas manualmente, y tres de ellas escribieron una respuesta para ver si el sistema puede verificar automáticamente. Encontró que los resultados de la prueba son correctos.

  • Al enviar una pregunta, se generará un archivo de preguntas y respuestas y la salida de los resultados estadísticos de forma correspondiente, como se muestra en la siguiente captura de pantalla:
    img
  • Las capturas de pantalla de los tres archivos son las siguientes:
    • img
    • img
    • img

Los resultados estadísticos finales son consistentes con la finalización de las preguntas de la interfaz.7 preguntas son correctas y 3 preguntas son incorrectas.

6. registro de formulario PSP

PSP2.1 Etapas del proceso de software personal Tiempo estimado (minutos) Tiempo real (minutos)
Planificación Plan 1440 1500
· Estimación · Estime cuánto tiempo llevará esta tarea 1440 1500
Desarrollo Desarrollo 1000 1100
· Análisis · Análisis de necesidades (incluido el aprendizaje de nuevas tecnologías) 60 60 40
· Especificaciones de diseño · Generar documentos de diseño. 0 0 0 0
· Revisión de diseño · Revisión de diseño (revisión de documentos de diseño con colegas) 60 60 80
· Estándar de codificación · Especificaciones de código (haciendo especificaciones apropiadas para el desarrollo actual) 60 60 60 60
· Diseño · Diseño específico 60 60 60 60
· Codificación · Codificación específica 1000 1100
· Revisión de código · Revisión de código 200 250
· Prueba · Prueba (autocomprobación, modificar código, enviar cambios) 200 250
Informes Informe 0 0 0 0
· Informe de prueba · Informe de prueba 0 0 0 0
· Medida del tamaño · Calcular la carga de trabajo 1400 1200
· Plan de mejora de procesos y autopsias · Resumen luego, y proponer un plan de mejora de procesos 60 60 60 60
Total 1400 1500

7. Resumen del proyecto

  • Yu Shengyuan: Este proyecto, una vez más, está familiarizado con el uso del empaquetado de la estructura electrónica. La parte más desafiante de todo el proyecto es la escritura del algoritmo de la expresión infijada a la expresión sufija. La implementación js es más simple que la implementación c.
  • Wang Shugan: Probablemente porque tenemos más cooperación, este proyecto comenzó rápidamente, y después de un tiempo, la división del trabajo y las interfaces funcionales se determinaron rápidamente. Después de determinar el marco general, no necesitamos mucha comunicación más tarde. Todos comenzamos a desarrollar nuestras propias partes de forma independiente, y finalmente las integramos directamente para la prueba del programa y algunas modificaciones menores.

Supongo que te gusta

Origin www.cnblogs.com/wsg1111/p/12675194.html
Recomendado
Clasificación