JSFiddle - React, Tailwind, and code Playground

by Josh Pullen

HTML

<script src="//cdnjs.cloudflare.com/ajax/libs/seedrandom/3.0.5/seedrandom.min.js"></script>

JavaScript

const questions = {
	a: {
  	generate({ min, max }) {
    	const a = Math.floor(Math.random() * (max - min) + min)
      const b = Math.floor(Math.random() * (max - min) + min)
      
      return { a, b }
    },
    check({ sum }, { a, b }) {
    	return sum === a + b
    }
  },
  b: {
  	generate({ min, max }) {
    	const a = Math.floor(Math.random() * (max - min) + min)
      const b = Math.floor(Math.random() * (max - min) + min)
      
      return { a, b }
    },
    check({ difference }, { a, b }) {
    	return difference === a - b
    }
  }
}

const challenge = {
  questions: {
  	default: { type: "a", generateParams: { min: 0, max: 10 } },
    conditional: [
    	{
      	condition: { type: "progress", min: 0.5 },
        question: { type: "b", generateParams: { min: 0, max: 10 } }
      }
    ]
  }
}

function generate(questionId, parameters, seed) {
	Math.seedrandom(seed)
  
  return questions[questionId].generate(parameters)
}

Math.seedrandom("test")

class ChallengeInstance {
	constructor(userId) {
  	this.version = 1.0

		this.userId = userId
    
    this.progress = 0.0
    this.questions = []
    this.questions.push(this.generateQuestion())
  }
  
  nextSeedFromQuestions(questions) {
  	return this.userId + JSON.stringify(questions.map(question => question.answerData))
  }
  
  generateQuestion() {
    const seed = this.nextSeedFromQuestions(this.questions)
    const { type, generateParams } = challenge.questions.default
    return new Question(type, generate(type, generateParams, seed))
  }
  
  addAnswer(data, time = new Date()) {
  	const question = this.questions[this.questions.length - 1]
    question.setAnswerData(data, time)
    
    if (question.correct) {
    	this.progress = Math.min(1, this.progress + 0.2)
    } else {
      this.progress = Math.max(0, this.progress - 0.2)
    }
  }
}

class Question {
	constructor(type, questionData, createdAt = new Date()) {
  	this.type = type
  
  	this.questionData = questionData
   ...