removed some constraints on quiz (uniqueness of puzzles, number of bits etc), added animation when the answer is wrong
This commit is contained in:
71
TODO.md
71
TODO.md
@@ -1,35 +1,56 @@
|
|||||||
- add progression
|
# Content
|
||||||
- add explanation/tutorial
|
- explanation/tutorial
|
||||||
- timed
|
- 'about'/contact
|
||||||
- add column labels
|
|
||||||
- add spacing beyond X places
|
## Curriculum
|
||||||
- add color and font
|
- how to negate a signed binary integer?
|
||||||
- optional super mario tyype sounds
|
- how to convert decimal to binary?
|
||||||
- gamification via character upgrades
|
- how to convert hex to binary?
|
||||||
|
- how to convert binary to hex?
|
||||||
|
- how many unsigned integers can be represented in ____? (a byte, nibble, word)
|
||||||
|
- how many _signed_ integers can be represented in ____? (a byte, nibble, word)
|
||||||
|
- how to determine if a binary int is even/odd?
|
||||||
|
- what can be said of a binary integer who ____ bits are 0?
|
||||||
|
- if all positions in a binary integer are 0 except position ____, what number does it represent?
|
||||||
|
- if all positions in a binary integer are 1 except position ____, what number does it represent?
|
||||||
|
- memorize powers of 2 up to 16 (speed round)
|
||||||
|
- what happens to the represented integer after shifting to the left?
|
||||||
|
- what happens to the represented integer after shifting to the right?
|
||||||
|
- what is the binary for the value 2^n - 1?
|
||||||
|
- what is sign extension? how do you do it?
|
||||||
|
- what is contraction?
|
||||||
|
- what is zero extension?
|
||||||
|
|
||||||
|
# Design
|
||||||
|
- color and font
|
||||||
|
- toggleable column labels
|
||||||
|
- animations
|
||||||
|
- [x] 'nuh-uh' shake for wrong answers
|
||||||
|
- [ ] nice reward animations for right answers
|
||||||
|
- [ ] make the placeholders become real text for a split second before starting
|
||||||
- processor graphic/animation
|
- processor graphic/animation
|
||||||
- diff processors for different bits
|
- diff processors for different bits
|
||||||
- mobile
|
|
||||||
|
## mobile
|
||||||
- make autofocus work on quiz
|
- make autofocus work on quiz
|
||||||
- remove "[enter]" from start button
|
- remove "[enter]" from start button
|
||||||
|
- on-screen keyboard, like wordle
|
||||||
- make it all on one line
|
- make it all on one line
|
||||||
- make the font smaller or the div wider
|
- make the font smaller or the div wider
|
||||||
- put a 'submit' button in
|
- put a 'submit' button in (or auto-submit?)
|
||||||
- add a range slider for easier input?
|
- add a range slider for easier input?
|
||||||
- make text inputs big enough for MAX_DIGITS_PROBLEMS and MAX_DIGITS_BITS
|
|
||||||
- show a message on submit
|
# Features
|
||||||
|
- keyboard shortcuts
|
||||||
|
- ctrl-c to go back to menu
|
||||||
|
- specify what you already know, then prove it (modular learning)
|
||||||
|
- save progress
|
||||||
|
- local storage
|
||||||
|
- login
|
||||||
|
- timed
|
||||||
|
- keyboard shortcuts with help overlay
|
||||||
|
- leaderboard
|
||||||
- show warning when specifying invalid number of bits or problems
|
- show warning when specifying invalid number of bits or problems
|
||||||
- add contact info
|
|
||||||
- add 'about'
|
|
||||||
- add mailing list
|
|
||||||
- prompt at the end of a quiz to sign up for it
|
|
||||||
- uncomment PDF part
|
- uncomment PDF part
|
||||||
- add PDF export in pure front end
|
- add PDF export in pure front end
|
||||||
- add animations
|
- cheat/human detection
|
||||||
- 'nuh-uh' shake for wrong answers
|
|
||||||
- nice reward animations for right answers
|
|
||||||
- make the placeholders become real text for a split second before starting
|
|
||||||
- super mario land [pixellation animation](http://blog.swishscripts.com/2019/06/19/snes-mosaic-effect/) ("mosaic")
|
|
||||||
- add user accounts using Userbase
|
|
||||||
- required for higher numbers
|
|
||||||
- required for PDF output?
|
|
||||||
- required after X uses?
|
|
||||||
|
|||||||
2226
package-lock.json
generated
2226
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -14,12 +14,15 @@
|
|||||||
"@rollup/plugin-node-resolve": "^8.0.0",
|
"@rollup/plugin-node-resolve": "^8.0.0",
|
||||||
"rollup": "^2.3.4",
|
"rollup": "^2.3.4",
|
||||||
"rollup-plugin-livereload": "^1.0.0",
|
"rollup-plugin-livereload": "^1.0.0",
|
||||||
"rollup-plugin-svelte": "^5.0.3",
|
"rollup-plugin-svelte": "^6.1.1",
|
||||||
"rollup-plugin-terser": "^5.1.2",
|
"rollup-plugin-terser": "^5.1.2",
|
||||||
"svelte": "^3.0.0"
|
"svelte": "^3.53.0"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"axios": "^0.19.2",
|
"axios": "^0.19.2",
|
||||||
"sirv-cli": "^0.4.4"
|
"coc-svelte": "^0.4.2",
|
||||||
|
"g": "^2.0.1",
|
||||||
|
"sirv-cli": "^0.4.4",
|
||||||
|
"tree-sitter-svelte": "^0.10.1"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -101,3 +101,27 @@ input[type=number] {
|
|||||||
.problem input[type=number] {
|
.problem input[type=number] {
|
||||||
border: none;
|
border: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* borrowed from https://stackoverflow.com/a/15991184/4386191 */
|
||||||
|
.nuhuh {
|
||||||
|
animation: shake .5s linear;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes shake {
|
||||||
|
8%, 41% {
|
||||||
|
transform: translateX(-10px);
|
||||||
|
}
|
||||||
|
25%, 58% {
|
||||||
|
transform: translateX(10px);
|
||||||
|
}
|
||||||
|
75% {
|
||||||
|
transform: translateX(-5px);
|
||||||
|
}
|
||||||
|
92% {
|
||||||
|
transform: translateX(5px);
|
||||||
|
}
|
||||||
|
0%, 100% {
|
||||||
|
transform: translateX(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<script>
|
<script>
|
||||||
import Inputs from "./components/Inputs.svelte";
|
import Inputs from "./components/Inputs.svelte";
|
||||||
import Quiz from "./components/Quiz.svelte";
|
import Quiz from "./components/Quiz.svelte";
|
||||||
import {activeQuiz} from './stores'
|
import { activeQuiz } from './stores'
|
||||||
</script>
|
</script>
|
||||||
<main style="margin: 2em;">
|
<main style="margin: 2em;">
|
||||||
<h1>Binary Quiz!</h1>
|
<h1>Binary Quiz!</h1>
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
<script>
|
<script>
|
||||||
import download from '../download'
|
import download from '../download.js'
|
||||||
import {
|
import {
|
||||||
MIN_BITS, MAX_BITS, MIN_PROBLEMS, MAX_PROBLEMS, DEFAULT_BITS, DEFAULT_NUM_PROBLEMS,
|
MIN_BITS, MAX_BITS, MIN_PROBLEMS, MAX_PROBLEMS, DEFAULT_BITS, DEFAULT_NUM_PROBLEMS,
|
||||||
MAX_DIGITS_BITS, MAX_DIGITS_PROBLEMS
|
MAX_DIGITS_BITS, MAX_DIGITS_PROBLEMS
|
||||||
} from '../config'
|
} from '../config.js'
|
||||||
import { bits, num_problems, valid, activeQuiz, problems } from '../stores'
|
import { bits, num_problems, valid, activeQuiz, problems } from '../stores.js'
|
||||||
import {generateProblems} from "../problems";
|
import { generateProblems } from "../problems.js";
|
||||||
|
|
||||||
const downloadAndClear = () => {
|
const downloadAndClear = () => {
|
||||||
download($bits || DEFAULT_BITS, $num_problems || DEFAULT_NUM_PROBLEMS)
|
download($bits || DEFAULT_BITS, $num_problems || DEFAULT_NUM_PROBLEMS)
|
||||||
@@ -54,7 +54,7 @@
|
|||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
<input class="primary-button" disabled={!$valid} type=submit value="Start Quiz [enter]" >
|
<input class="primary-button" disabled={!$valid} type=submit value="Start Quiz [enter]" >
|
||||||
<!-- <input class="button" disabled={!$valid} type=button on:click={downloadAndClear} value="Download PDFs">-->
|
<!-- <input class="button" disabled={!$valid} type=button on:click={downloadAndClear} value="Download PDFs">-->
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
|
|||||||
@@ -1,30 +1,47 @@
|
|||||||
<script>
|
<script>
|
||||||
import {checkAnswer} from "../problems";
|
import {checkAnswer} from "../problems";
|
||||||
import {problems, bits, activeProblemIndex, tally, num_problems, activeQuiz} from '../stores'
|
import { problems, bits, activeProblemIndex, tally, num_problems, activeQuiz } from '../stores';
|
||||||
import Tally from "./Tally.svelte";
|
import Tally from "./Tally.svelte";
|
||||||
|
|
||||||
$: problem = $problems[$activeProblemIndex]
|
$: problem = $problems[$activeProblemIndex];
|
||||||
let displaySummary = false
|
let displaySummary = false;
|
||||||
let solution
|
let solution;
|
||||||
|
let userInput;
|
||||||
|
let form;
|
||||||
|
let visible = true;
|
||||||
|
|
||||||
const check = () => {
|
function shakeAndClear() {
|
||||||
|
userInput.style.color = 'red';
|
||||||
|
userInput.classList.add('nuhuh');
|
||||||
|
setTimeout(function() {
|
||||||
|
userInput.classList.remove('nuhuh');
|
||||||
|
userInput.value = '';
|
||||||
|
userInput.style.color = '#333';
|
||||||
|
}, 550)
|
||||||
|
}
|
||||||
|
|
||||||
|
function check() {
|
||||||
if (!checkAnswer(solution, problem)) {
|
if (!checkAnswer(solution, problem)) {
|
||||||
class_ = "incorrect"
|
shakeAndClear();
|
||||||
} else {
|
} else {
|
||||||
tally.update(() => $tally + 1)
|
tally.update(() => $tally + 1);
|
||||||
if ($num_problems === $activeProblemIndex + 1) {
|
if ($num_problems === $activeProblemIndex + 1) {
|
||||||
displaySummary = true
|
displaySummary = true;
|
||||||
} else {
|
} else {
|
||||||
activeProblemIndex.update(() => $activeProblemIndex + 1)
|
visible = false;
|
||||||
|
setTimeout(function() {
|
||||||
|
activeProblemIndex.update(() => $activeProblemIndex + 1);
|
||||||
|
solution = null;
|
||||||
|
visible = true;
|
||||||
|
}, 550)
|
||||||
}
|
}
|
||||||
solution = null
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const reset = () => {
|
const reset = () => {
|
||||||
|
activeQuiz.update(() => false)
|
||||||
activeProblemIndex.update(() => 0)
|
activeProblemIndex.update(() => 0)
|
||||||
tally.update(() => 0)
|
tally.update(() => 0)
|
||||||
activeQuiz.update(() => false)
|
|
||||||
bits.update(() => null)
|
bits.update(() => null)
|
||||||
num_problems.update(() => null)
|
num_problems.update(() => null)
|
||||||
displaySummary = false
|
displaySummary = false
|
||||||
@@ -43,12 +60,13 @@
|
|||||||
</div>
|
</div>
|
||||||
{:else}
|
{:else}
|
||||||
<Tally />
|
<Tally />
|
||||||
<form on:submit|preventDefault={check} class="problem">
|
{#if visible}
|
||||||
<label>
|
<form bind:this={form} on:submit|preventDefault={check} class="problem">
|
||||||
{problem} =
|
<label>
|
||||||
<input autofocus type=number bind:value={solution}>
|
{problem} =
|
||||||
</label>
|
<input bind:this={userInput} autofocus type=number bind:value={solution} id="problem">
|
||||||
<input type=submit style="visibility: hidden">
|
</label>
|
||||||
</form>
|
<input type=submit style="visibility: hidden">
|
||||||
|
</form>
|
||||||
|
{/if}
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
|
|||||||
@@ -1,13 +1,9 @@
|
|||||||
export const MIN_BITS = 3
|
export const MIN_BITS = 2
|
||||||
export const MAX_BITS = 16
|
export const MAX_BITS = 16
|
||||||
export const MIN_PROBLEMS = 2
|
export const MIN_PROBLEMS = 1
|
||||||
export const MAX_PROBLEMS = 99
|
export const MAX_PROBLEMS = 99
|
||||||
export const MAX_DIGITS_PROBLEMS = MAX_PROBLEMS.toString().length
|
export const MAX_DIGITS_PROBLEMS = MAX_PROBLEMS.toString().length
|
||||||
export const MAX_DIGITS_BITS = MAX_BITS.toString().length
|
export const MAX_DIGITS_BITS = MAX_BITS.toString().length
|
||||||
export const DEFAULT_BITS = 4
|
export const DEFAULT_BITS = 4
|
||||||
export const DEFAULT_NUM_PROBLEMS = 10
|
export const DEFAULT_NUM_PROBLEMS = 10
|
||||||
|
|
||||||
export const getMaxPermutations = (bits) => {
|
|
||||||
return Math.pow(2, bits)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,23 +1,20 @@
|
|||||||
import {DEFAULT_BITS, DEFAULT_NUM_PROBLEMS} from "./config";
|
|
||||||
|
|
||||||
export const generateProblems = (bits, num_problems) => {
|
export function generateProblems(bits, num_problems) {
|
||||||
let probs = []
|
return new Array(num_problems)
|
||||||
let counter = 0
|
.fill(null)
|
||||||
|
.map(function() {
|
||||||
while (counter < (num_problems || DEFAULT_NUM_PROBLEMS)) {
|
return generateProblem(bits)
|
||||||
let problem = generateProblem(bits || DEFAULT_BITS)
|
})
|
||||||
if (!probs.includes(problem)) {
|
|
||||||
probs.push(problem)
|
|
||||||
counter++
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return probs
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export const generateProblem = bits => Array.from(Array(bits)).map((_, i) => Math.random() >= .5 ? '1' : '0').join('')
|
export function generateProblem(bits) {
|
||||||
|
return Array.from(Array(bits)).map((_, i) => Math.random() >= .5 ? '1' : '0').join('');
|
||||||
|
}
|
||||||
|
|
||||||
export const solveProblem = problem => parseInt(problem, 2)
|
export function solveProblem(problem) {
|
||||||
|
return parseInt(problem, 2);
|
||||||
export const checkAnswer = (answer, problem) => solveProblem(problem) === answer
|
}
|
||||||
|
|
||||||
|
export function checkAnswer(answer, problem) {
|
||||||
|
return solveProblem(problem) === answer
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
import {derived, writable} from 'svelte/store'
|
import { derived, writable } from 'svelte/store'
|
||||||
import {generateProblem} from "./problems"
|
import { MIN_BITS, MAX_BITS, MIN_PROBLEMS, MAX_PROBLEMS, DEFAULT_BITS, DEFAULT_NUM_PROBLEMS } from "./config"
|
||||||
import {getMaxPermutations, MIN_BITS, MAX_BITS, MIN_PROBLEMS, MAX_PROBLEMS, DEFAULT_BITS, DEFAULT_NUM_PROBLEMS} from "./config"
|
|
||||||
|
|
||||||
export const bits = writable()
|
export const bits = writable()
|
||||||
export const num_problems = writable()
|
export const num_problems = writable()
|
||||||
@@ -14,6 +13,5 @@ export const valid = derived([bits, num_problems], ([$bits, $num_problems]) => (
|
|||||||
&& ($bits || DEFAULT_BITS) >= MIN_BITS
|
&& ($bits || DEFAULT_BITS) >= MIN_BITS
|
||||||
&& ($num_problems || DEFAULT_NUM_PROBLEMS) >= MIN_PROBLEMS
|
&& ($num_problems || DEFAULT_NUM_PROBLEMS) >= MIN_PROBLEMS
|
||||||
&& ($num_problems || DEFAULT_NUM_PROBLEMS) <= MAX_PROBLEMS
|
&& ($num_problems || DEFAULT_NUM_PROBLEMS) <= MAX_PROBLEMS
|
||||||
&& ($num_problems || DEFAULT_NUM_PROBLEMS) <= getMaxPermutations($bits || DEFAULT_BITS)
|
|
||||||
))
|
))
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user