From f8d23465304e36c66320491cfe2435d704421bdc Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 5 Nov 2025 15:32:15 +0000 Subject: [PATCH 1/2] Add maximum digit constraint for multiplication worksheets This feature allows users to specify a maximum digit for multiplication problems, ensuring at least one operand is less than or equal to that value. This is useful for students learning multiplication tables up to a specific number (e.g., tables up to 5). Changes: - Added UI control in print config view with dropdown for max digit selection - Updated generation logic to respect max digit constraint - Added randRangeByDigitsWithMax helper function for constrained random generation - Updated multiplication worksheet generators (including visual and custom ones) - Max digit control is only shown for multiplication worksheets --- src/index.html | 11 +++++++++++ src/js/hw-gen.js | 45 ++++++++++++++++++++++++++++++++++++++------- src/js/hw-sets.js | 44 ++++++++++++++++++++++++++++++++++++-------- src/js/util.js | 15 +++++++++++++++ 4 files changed, 100 insertions(+), 15 deletions(-) diff --git a/src/index.html b/src/index.html index 4cd7f41..012c9b2 100644 --- a/src/index.html +++ b/src/index.html @@ -214,6 +214,17 @@

How many worksheets?

+
+ More Info +
+
+
+ +
+
+ +
+
+
+

Features that will blow your mind.

+
    +
  • ๐Ÿ™Š No login or registration
  • +
  • ๐Ÿ†“ No ads ๐Ÿ™ˆ
  • +
  • ๐Ÿ—๏ธ Answer key on last page
  • +
  • ๐Ÿ“ worksheets available
  • +
  • โ™พ Unlimited worksheets!
  • +
  • ๐Ÿ‘จโ€๐Ÿ’ป Open source code
  • +
+

+
+
+
+ +
+
+
+
+
+
+
๐Ÿ”„
+
+
+

Repitition and practice make perfect.

+
+ It is known by parents, teachers, cram schools, and most any profession that practicing the basics is + a sure way to grow and boost your student's confidence. +
+
+
+
+
+
+

๐Ÿ‘ Handwriting ๐Ÿ‘Ž typing / touch screens

+
+ Studies have concluded that + writing does "lead to better learning" + on paper over typing. +
+
+
+
โœ๏ธ
+
+
+
+
+

๐Ÿ“ฐ Updates

+
    +
  • + 6/17/2021 - Easier multiplication problems with space to add. +
      +
    1. ๐Ÿ”ข Multiplication Add Equations
    2. +
    +
  • +
  • + 5/31/2021 - Easier visual multiplication problems. +
      +
    1. ๐Ÿ”ข Multiplication Visual Emoji Equations
    2. +
    3. ๐Ÿ”ข Multiplication Visual Lvl 1 Equations
    4. +
    5. ๐Ÿ”ข Multiplication Visual Lvl 2 Equations
    6. +
    +
  • +
  • + 5/24/2021 - Long division. Make each number more spaced apart so they align. +
      +
    1. ๐Ÿ”ข Long Division Equations
    2. +
    3. ๐Ÿ”ข Longer Division Equations
    4. +
    5. ๐Ÿ”ข Long Division w/Remainders Equations
    6. +
    7. ๐Ÿ”ข Longer Division w/Remainders Equations
    8. +
    +
  • +
  • + 4/31/2021 - Easier visual multiplication problems. +
      +
    1. ๐Ÿ”ข Multiplication Visual Emoji Equations
    2. +
    3. ๐Ÿ”ข Multiplication Visual Lvl 1 Equations
    4. +
    5. ๐Ÿ”ข Multiplication Visual Lvl 2 Equations
    6. +
    +
  • +
+
+
+
+
+

Why not?

+ +
+
+ + + + + +
+ + + +
+
    +
  • ๐Ÿ”Ž Use Print Preview feature and set "Zoom" to "Shrink to fit" to ensure best print results.
  • +
  • ๐Ÿ“ Adjust settings such as margin size to 0.3" optimize print output.
  • +
  • ๐Ÿ“„ Adjust "Worksheets" value to get more worksheets per set of print outs.
  • +
  • ๐Ÿ—๏ธ Answer keys are on the last page.
  • +
  • ๐Ÿ”ข 1-digit equations are all possible equations not including 1.
  • +
  • ๐Ÿ˜€ Random emojis using Twemoji featured on each worksheet in case worksheets mix up.
  • +
+
+ +
+
+ + + +
+

Select a Category

+
+
+ +
+
+
+ +
+
+
+

How many worksheets?

+ +
+
+ +
+ +
+
+ +
+
+
+
+ +
+
+
+ +
+
Preview
+
+ +
+
+
+
+ + + + + +
NameDate
+
+

+
+
+
+
+
+
+
+ + + + + + + + + + + + diff --git a/docs/js/hw-gen.js b/docs/js/hw-gen.js new file mode 100644 index 0000000..3ed64e2 --- /dev/null +++ b/docs/js/hw-gen.js @@ -0,0 +1,295 @@ +const HwGen = (() => { + const MODE = { INTRO: 1, CATEGORIES: 2, WORKSHEET_SELECT: 3, PRINT_CONFIG: 4, PREVIEW: 5, PREVIEW: 6 }; + const myNavbar = document.getElementById("myNavbar"); + const introView = document.getElementById("introView"); + const breadcrumbView = document.getElementById("breadcrumbView"); + const breadcrumb = document.getElementById("breadcrumb"); + const screenshotRotation = document.getElementById("screenshotRotation"); + const tipsView = document.getElementById("tipsView"); + const tipScroller = document.querySelector(".tip-scroller"); + const tipElemList = tipScroller.querySelectorAll("li"); + const categoriesView = document.getElementById("categoriesView"); + const worksheetSelectView = document.getElementById("worksheetSelectView"); + const worksheetCountSelect = document.getElementById("worksheetCount"); + const answerKeyChkbx = document.getElementById("answerKeyChkbx"); + const maxDigitSelect = document.getElementById("maxDigitSelect"); + const maxDigitContainer = document.getElementById("maxDigitContainer"); + const printConfigView = document.getElementById("printConfigView"); + const worksheetView = document.getElementById("worksheetView"); + const categorySelectView = document.getElementById("categorySelectView"); + const footer = document.getElementById("footer"); + const hwMap = {}; + const data = { + "mode": MODE.INTRO, + "selectedCat": "", + "selectedSet": "", + "selectedCount": 6, + "showAnswerKey": true, + "maxDigit": 9, + }; + let screenshotInterval = null; + let screenshotNum = 2; + let tipScrollInterval = null; + let tipNum = 0; + const genEquation = (xSize, ySize, mathSymbol, maxDigit) => { + let x, y; + if (mathSymbol === "*" && maxDigit && maxDigit < 9) { + // For multiplication with max digit constraint + // Ensure at least one operand is <= maxDigit + const useMaxForFirst = Math.random() < 0.5; + if (useMaxForFirst) { + x = randRangeByDigitsWithMax(xSize, maxDigit); + y = randRangeByDigits(ySize); + } else { + x = randRangeByDigits(xSize); + y = randRangeByDigitsWithMax(ySize, maxDigit); + } + } else { + x = randRangeByDigits(xSize); + y = randRangeByDigits(ySize); + } + const z = solution(x, y, mathSymbol); + return { x, y, z }; + }; + const generate = (xSize, ySize, mathSymbol, count, useAllPossible1Digit, myGenEq, maxDigit) => { + let arr = []; + if (useAllPossible1Digit) { + SINGLE_DIGITS.map(x => SINGLE_DIGITS.map(y => arr.push({ x, y, z: solution(x, y, mathSymbol) }))); + arr.sort(() => Math.random() - 0.5); //shuffle + arr.sort(() => Math.random() - 0.5); //shuffle + if (count < arr.length) arr = arr.slice(0, count); + // Filter based on maxDigit for multiplication + if (mathSymbol === "*" && maxDigit && maxDigit < 9) { + arr = arr.filter(eq => eq.x <= maxDigit || eq.y <= maxDigit); + } + } + else { + for (let i = 0; i < count; i++) { + arr.push(myGenEq ? myGenEq(maxDigit) : genEquation(xSize, ySize, mathSymbol, maxDigit)); + } + } + return arr; + }; + const selectCat = cat => { + if (cat !== data["selectedCat"]) data["selectedSet"] = ""; + data["selectedCat"] = cat; + data['mode'] = MODE.WORKSHEET_SELECT; + render(); + }; + const renderIntro = () => { + const wsCount = document.getElementById("wsCount"); + let sum = 0; + Object.keys(hwMap).forEach(a => sum += hwMap[a].length); + if (wsCount) wsCount.innerHTML = sum; + //go through all screenshots + if (screenshotInterval) clearInterval(screenshotInterval); + screenshotInterval = setInterval(() => { + screenshotRotation.innerHTML = ``; + screenshotNum++; + if (screenshotNum > 5) screenshotNum = 1; + }, 2000); + }; + const addBreadcrumb = (arr, action, label, selected) => + arr.push(``); + const renderBreadcrumb = () => { + const arr = []; + addBreadcrumb(arr, "HwGen.intro();", "๐Ÿ  Home", data['mode'] === MODE.INTRO); + addBreadcrumb(arr, "HwGen.start();", "โš– Categories", data['mode'] === MODE.CATEGORIES); + if (data['mode'] !== MODE.CATEGORIES) + addBreadcrumb(arr, `HwGen.selectCat('${data['selectedCat']}');`, `๐Ÿ”ข ${data['selectedCat']}`, data['mode'] === MODE.WORKSHEET_SELECT); + if ((data['mode'] !== MODE.CATEGORIES && data['mode'] !== MODE.WORKSHEET_SELECT) && data['selectedSet']) + addBreadcrumb(arr, `HwGen.printConfig();`, "๐Ÿ–จ Print Config", data['mode'] === MODE.PRINT_CONFIG); + if ((data['mode'] !== MODE.CATEGORIES && data['mode'] !== MODE.WORKSHEET_SELECT) && data['selectedSet']) + addBreadcrumb(arr, `HwGen.preview();`, `๐Ÿ“„ ${hwSets[data['selectedSet']].title}`, data['mode'] === MODE.PREVIEW); + breadcrumb.innerHTML = arr.join(""); + }; + const getIcon = cat => { + switch(cat) { + case 'Addition': return 'โž•'; + case 'Subtraction': return 'โž–'; + case 'Multiplication': return 'โœ–'; + case 'Division': return 'โž—'; + case 'Japanese': return '๐Ÿ‡ฏ๐Ÿ‡ต'; + } + return '๐Ÿ”ข'; + }; + const renderCategories = () => { + const categories = Object.keys(hwMap); + if (!data["selectedCat"]) data["selectedCat"] = categories.length > 0 ? categories[0] : ""; + categorySelectView.innerHTML = categories.map(cat => { + return ` +
+
+
+

${getIcon(cat)} ${cat}

+
+
+ ${hwMap[cat].length} worksheets + +
+
+
`}).join(""); + }; + const renderWorksheetList = () => { + const worksheetList = document.getElementById("worksheetList"); + const answerKey = true; + if (!data["selectedCat"]) { + worksheetList.innerHTML = `
No selected tab
`; + return; + } + worksheetList.innerHTML = `

Select ${data["selectedCat"]} Worksheet

` + + hwMap[data["selectedCat"]].map((hwSet, i) => { + const {title, xSize, ySize, mathSymbol, outputFunc, count, name, long, useAllPossible1Digit, myGenEq, myGenEqList} = hwSet; + const eq = myGenEq ? myGenEq(data['maxDigit']) : myGenEqList ? myGenEqList()[0] : genEquation(xSize, ySize, mathSymbol, data['maxDigit']); + const eqStr = outputFunc(eq, -1, 0, long); + return `${i === 0 ? '' : '
'}
+
+ ${i + 1}. +
+
+ ${title} +
${(useAllPossible1Digit ? 64 : myGenEqList ? myGenEqList().length : count || 0)} Problems
+ ${answerKey ? '
w/answer key
' : ''} +
+
e.g.
+
+ ${eqStr}
+
+
`; + }).join(""); + document.title = `Math Homework Generator | ${data["selectedCat"]}`; + }; + const renderPreview = () => { + const worksheetsDiv = document.querySelector(".worksheets") + , answerKeyDiv = document.querySelector(".answerKey") + , hwSetInfoDiv = document.querySelector(".hw-set-info") + , worksheetOrig = document.querySelector(".worksheet").cloneNode(true) + , hwSet = hwSets[data['selectedSet']] + , allAnswerKeys = [] + ; + if (!hwSet) { + alert(`Worksheet set doesn't exist ${data['selectedSet']} `); + return; + } + const { title, count, columns, xSize, ySize, mathSymbol, myGenEqList, outputFunc, answerKey, long, answerSpace, useAllPossible1Digit, myGenEq } = hwSet; + worksheetsDiv.innerHTML = ""; + for (let i = 0; i < data['selectedCount']; i++) { + const worksheet = worksheetOrig.cloneNode(true) + , output = worksheet.querySelector(".output") + , eqList = myGenEqList ? myGenEqList() : generate(xSize, ySize, mathSymbol, count, useAllPossible1Digit, myGenEq, data['maxDigit']) + , titleDiv = worksheet.querySelector(".title") + , outputStr = eqList.map((eq, i) => outputFunc(eq, i, columns, long, answerSpace)).join("") + , emoji = randArr(emojis) + ; + allAnswerKeys.push(`
+
${emoji} ${title} #${i + 1}
+
${eqList.map(answerKey || function(eq) {return eq.z}).map((a, i) => + `
${i + 1}.) ${a}
`).join("")}
`); + titleDiv.innerHTML = `${emoji} ${title} #${i + 1}`; + output.innerHTML = `${outputStr}`; + worksheetsDiv.appendChild(worksheet); + } + hwSetInfoDiv.innerHTML = `${data['selectedCount']} worksheets. ${data['showAnswerKey'] ? '' : 'No '}Answer Key on last page.`; + answerKeyDiv.innerHTML = data['showAnswerKey'] ? allAnswerKeys.join("") : ''; + document.title = title; + }; + const render = () => { + window.scrollTo(); + if (!data['mode']) data['mode'] = MODE.INTRO; + if (screenshotInterval) clearInterval(screenshotInterval); + const displayNavView = [MODE.CATEGORIES, MODE.WORKSHEET_SELECT, MODE.PRINT_CONFIG].includes(data['mode']) ? "" : "none"; + const displayFooter = [MODE.CATEGORIES, MODE.WORKSHEET_SELECT, MODE.PRINT_CONFIG, MODE.INTRO].includes(data['mode']) ? "" : "none"; + breadcrumbView.style.display = myNavbar.style.display = tipsView.style.display = displayNavView; + footer.style.display = displayFooter; + introView.style.display = data['mode'] === MODE.INTRO ? "" : "none"; + categoriesView.style.display = data['mode'] === MODE.CATEGORIES ? "" : "none"; + worksheetSelectView.style.display = data['mode'] === MODE.WORKSHEET_SELECT ? "" : "none"; + printConfigView.style.display = data['mode'] === MODE.PRINT_CONFIG ? "" : "none"; + worksheetView.style.display = data['mode'] === MODE.PREVIEW ? "" : "none"; + handleParams(); + switch (data['mode']) { + case MODE.INTRO: renderIntro(); break; + case MODE.CATEGORIES: renderCategories(); break; + case MODE.WORKSHEET_SELECT: renderWorksheetList(); break; + case MODE.PREVIEW: renderPreview(); break; + default: + } + renderBreadcrumb(); + window.scrollTo(0, 0); + twemoji && twemoji.parse(document.body); + }; + const handleParams = () => { + if (data['selectedSet'] && hwSets[data['selectedSet']]) { + setUrlParam(`set=${data['selectedSet']}`); + } + else { + setUrlParam(""); + } + data['selectedCount'] = worksheetCountSelect ? parseInt(worksheetCountSelect.value) : 1; + data['showAnswerKey'] = answerKeyChkbx.checked ? true : false; + data['maxDigit'] = maxDigitSelect ? parseInt(maxDigitSelect.value) : 9; + + // Show/hide maxDigit control only for Multiplication category + if (maxDigitContainer) { + const showMaxDigit = data['selectedCat'] === 'Multiplication' && + data['selectedSet'] && + hwSets[data['selectedSet']] && + hwSets[data['selectedSet']].mathSymbol === '*'; + maxDigitContainer.style.display = showMaxDigit ? '' : 'none'; + } + }; + const init = () => { + const hwSetName = getUrlParam("set"); + if (hwSetName && hwSets[hwSetName]) { + data['selectedSet'] = hwSetName; + data['selectedCat'] = hwSets[hwSetName].category; + data['mode'] = MODE.PRINT_CONFIG; + } + worksheetCountSelect.innerHTML = new Array(29).fill().map((_, i) => ``).join(""); + //map sets by Category. + Object.keys(hwSets).map(a => { + const hwSet = hwSets[a]; + if (!hwSet.category) alert(`"${a}" does not have a category!`); + hwSet.name = a; + if (!hwMap[hwSet.category]) { + hwMap[hwSet.category] = []; + } + hwMap[hwSet.category].push(hwSet); + }); + initTipScroller(); + HwGen.render(); + }; + const initTipScroller = () => {showTip(); tipScrollInterval = setInterval(() => showTip(), 10000);}; + const nextTip = () => { + clearInterval(tipScrollInterval); + initTipScroller(); + } + const showTip = () => { + tipElemList.forEach((a, i) => { + a.style.display = tipNum === i ? '' : 'none'; + a.className = "fade-in"; + }); + tipNum++; + if (tipNum >= tipElemList.length) tipNum = 0; + }; + window.onload = init; + const setWs = hwSetName => { + data['selectedSet'] = hwSetName; + data['mode'] = MODE.PRINT_CONFIG + HwGen.render(); + return false; + }; + const intro = () => { data['mode'] = MODE.INTRO; HwGen.render(); }; + const start = () => { data['mode'] = MODE.CATEGORIES; HwGen.render(); }; + const printConfig = () => { data['mode'] = MODE.PRINT_CONFIG; HwGen.render(); }; + const preview = () => { data['mode'] = MODE.PREVIEW; HwGen.render(); }; + return { + intro, + start, + printConfig, + preview, + render, + selectCat, nextTip, + setWs + }; +})(); \ No newline at end of file diff --git a/docs/js/hw-sets-jp.js b/docs/js/hw-sets-jp.js new file mode 100644 index 0000000..d51c465 --- /dev/null +++ b/docs/js/hw-sets-jp.js @@ -0,0 +1,67 @@ +const jpOutput = ({x, y}, i, columns) => ` +${i + 1}.) + +
${x}
+
+ +
+ +${((i + 1) % columns) === 0 ? '' : ''}`; + +const ro2ja = jpSet => jpSet.map(({ ja, ro }) => ({ x: ro, z: ja })); +const ja2ro = jpSet => jpSet.map(({ ja, ro }) => ({ x: ja, z: ro })); + +const shuffleEqSetRo2Ja = jpSet => shuffle(ro2ja(jpSet)); +const shuffleEqSetJa2Ro = jpSet => shuffle(ja2ro(jpSet)); + + +// Japanese Homework sets +hwSets["hiragana-ro2ja-a-na"] = { + title: "Hiragana Romanized to Kana (A to NA)", category: "Japanese", columns: 5, + myGenEqList: () => shuffleEqSetRo2Ja(hiraganaSets["A-NA"]), outputFunc: jpOutput, +}; +hwSets["hiragana-ro2ja-ha-wa"] = { + title: "Hiragana Romanized to Kana (HA to WA)", category: "Japanese", columns: 5, + myGenEqList: () => shuffleEqSetRo2Ja(hiraganaSets["HA-WA"]), outputFunc: jpOutput, +}; +hwSets["hiragana-ro2ja-digraphs"] = { + title: "Hiragana Digraphs Romanized to Kana", category: "Japanese", columns: 5, + myGenEqList: () => shuffleEqSetRo2Ja(hiraganaSets["Digraphs"]), outputFunc: jpOutput, +}; +hwSets["hiragana-ja2ro-a-na"] = { + title: "Hiragana Kana to Romanized (A to NA)", category: "Japanese", columns: 5, + myGenEqList: () => shuffleEqSetJa2Ro(hiraganaSets["A-NA"]), outputFunc: jpOutput, +}; +hwSets["hiragana-ja2ro-ha-wa"] = { + title: "Hiragana Kana to Romanized (HA to WA)", category: "Japanese", columns: 5, + myGenEqList: () => shuffleEqSetJa2Ro(hiraganaSets["HA-WA"]), outputFunc: jpOutput, +}; +hwSets["hiragana-ja2ro-digraphs"] = { + title: "Hiragana Digraphs Kana to Romanized", category: "Japanese", columns: 5, + myGenEqList: () => shuffleEqSetJa2Ro(hiraganaSets["Digraphs"]), outputFunc: jpOutput, +}; + +hwSets["katakana-ro2ja-a-na"] = { + title: "Katakana Romanized to Kana (A to NA)", category: "Japanese", columns: 5, + myGenEqList: () => shuffleEqSetRo2Ja(katakanaSets["A-NA"]), outputFunc: jpOutput, +}; +hwSets["katakana-ro2ja-ha-wa"] = { + title: "Katakana Romanized to Kana (HA to WA)", category: "Japanese", columns: 5, + myGenEqList: () => shuffleEqSetRo2Ja(katakanaSets["HA-WA"]), outputFunc: jpOutput, +}; +hwSets["katakana-ro2ja-digraphs"] = { + title: "Katakana Digraphs Romanized to Kana", category: "Japanese", columns: 5, + myGenEqList: () => shuffleEqSetRo2Ja(katakanaSets["Digraphs"]), outputFunc: jpOutput, +}; +hwSets["katakana-ja2ro-a-na"] = { + title: "Katakana Kana to Romanized(A to NA)", category: "Japanese", columns: 5, + myGenEqList: () => shuffleEqSetJa2Ro(katakanaSets["A-NA"]), outputFunc: jpOutput, +}; +hwSets["katakana-ja2ro-ha-wa"] = { + title: "Katakana Kana to Romanized (HA to WA)", category: "Japanese", columns: 5, + myGenEqList: () => shuffleEqSetJa2Ro(katakanaSets["HA-WA"]), outputFunc: jpOutput, +}; +hwSets["katakana-ja2ro-digraphs"] = { + title: "Katakana Digraphs Kana to Romanizeda", category: "Japanese", columns: 5, + myGenEqList: () => shuffleEqSetJa2Ro(katakanaSets["Digraphs"]), outputFunc: jpOutput, +}; \ No newline at end of file diff --git a/docs/js/hw-sets.js b/docs/js/hw-sets.js new file mode 100644 index 0000000..2fbba31 --- /dev/null +++ b/docs/js/hw-sets.js @@ -0,0 +1,439 @@ +const verticalEq = (eq, i, columns, mathSym, long, answerSpace) => ` + ${i + 1}.) + +
${eq.x}
+
${mathSym} ${eq.y}
+
+ + ${((i + 1) % columns) === 0 ? `` : ''}` + /** + * Solve: + * z + * mathSym x + * ___ + */ + , verticalEqZX_ = (eq, i, columns, mathSym, long) => ` + ${i + 1}.) + +
${eq.z}
+
${mathSym} ${eq.x}
+
+ + ${((i + 1) % columns) === 0 ? `` : ''}` + , horizontalEq = (eq, i, columns, mathSym) => ` + + ${i + 1}.)${eq.x} ${mathSym} ${eq.y} = + + + ${((i + 1) % columns) === 0 ? '' : ''}` + , longDivEq = (eq, i, columns, longer) => ` + ${i + 1}.) + +
+
+
+
${eq.x}
+
${eq.z}
+
+ + ${((i + 1) % columns) === 0 ? '' : ''}` + , visualMultiEq = (eq, i, columns, size = 6) => ` + ${i + 1}.) + + ${repeat(`${repeat(``, size)}`, size)}
+
+ ${eq.x} × ${eq.y} = +
+ + ${((i + 1) % columns) === 0 ? '' : ''}` + , visualEmojiMultiEq = (eq, i, columns) => ` + ${i + 1}.) + +
+ ${repeat(`
${repeat(randArr(emojis), eq.y)}
`, eq.x)} +
+
+ ${eq.x} × ${eq.y} = +
+ + ${((i + 1) % columns) === 0 ? '' : ''}` + , multiAddEq = (eq, i, columns) => ` + ${i + 1}.) + +
+ ${repeat(`+ `, eq.y).substr(2)} +
+
+
+ ${eq.x} × ${eq.y} = +
+ + ${((i + 1) % columns) === 0 ? '' : ''}` + , multiAddEq2 = (eq, i, columns) => ` + ${i + 1}.) + +
+ ${repeat(`+ `, eq.y).substr(2)} +
+
+
+ ${eq.x} × ${eq.y} = +
+ + ${((i + 1) % columns) === 0 ? '' : ''}` + , visualAddition = (eq, i, columns, mathSym, emoji) => ` +
${i + 1}.)
+ ${strXTimes(`${emoji}`, eq.x)} + + + ${strXTimes(`${emoji}`, eq.y)} + = + + + + + ${((i + 1) % 5) === 0 ? `
` : ''}` + /** + * Solve: + * x mathSym ___ = y + */ + , horizontalEqX_Y = (eq, i, columns, mathSym) => ` + + + + ${((i + 1) % columns) === 0 ? '' : ''}` + /** + * Solve: + * z mathSym x = ___ + */ + , horizontalEqZX_ = (eq, i, columns, mathSym) => ` + + + + ${((i + 1) % columns) === 0 ? '' : ''}` +; +const hwSets = { + "addition": { + title: "Addition 1-digit Equations", category: "Addition", + columns: 4, + useAllPossible1Digit: true, + xSize: 1, ySize: 1, //number of digits in x & y. + mathSymbol: "+", + outputFunc: (eq, i, columns) => horizontalEq(eq, i, columns, "+"), + }, + "addition-visual-1": { + title: "Addition Visual Equations Level 1 (1-6)", category: "Addition", + count: 10, columns: 1, + xSize: .6, ySize: .6, + mathSymbol: "+", + outputFunc: (eq, i) => visualAddition(eq, i, 0, "+", randArr(countable)), + }, + "addition-visual-2": { + title: "Addition Visual Equations Level 2", category: "Addition", + count: 10, columns: 1, + xSize: 1, ySize: 1, + mathSymbol: "+", + outputFunc: (eq, i) => visualAddition(eq, i, 0, "+", randArr(countable)), + }, + "addition-find-addends": { + title: "Addition Find Addend Equations", category: "Addition", + count: 20, columns: 3, + useAllPossible1Digit: true, + xSize: 1, ySize: 1, mathSymbol: "+", + outputFunc: (eq, i, columns) => horizontalEqX_Y(eq, i, columns, "+"), + }, + "addition-2-1": { + title: "Addition 2-1-digit Equations", category: "Addition", + count: 44, columns: 4, + xSize: 2, ySize: 1, mathSymbol: "+", + outputFunc: (eq, i, columns) => verticalEq(eq, i, columns, "+"), + }, + "addition-2-2": { + title: "Addition 2-digit Equations", category: "Addition", + count: 44, columns: 4, + xSize: 2, ySize: 2, mathSymbol: "+", + outputFunc: (eq, i, columns) => verticalEq(eq, i, columns, "+"), + }, + "addition-3-3": { + title: "Addition 3-digit Equations", category: "Addition", + count: 44, columns: 4, long: true, + xSize: 3, ySize: 3, mathSymbol: "+", + outputFunc: (eq, i, columns, long) => verticalEq(eq, i, columns, "+", long), + }, + "addition-4-4": { + title: "Addition 4-digit Equations", category: "Addition", + count: 44, columns: 4, long: true, + xSize: 4, ySize: 4, mathSymbol: "+", + outputFunc: (eq, i, columns, long) => verticalEq(eq, i, columns, "+", long), + }, + "addition-5-5": { + title: "Addition 5-digit Equations", category: "Addition", + count: 44, columns: 4, long: true, + xSize: 5, ySize: 5, mathSymbol: "+", + outputFunc: (eq, i, columns, long) => verticalEq(eq, i, columns, "+", long), + }, + "subtraction": { + title: "Subtraction 1-digit Equations", category: "Subtraction", + count: 64, columns: 4, + xSize: 1, ySize: 1, + useAllPossible1Digit: 1, + mathSymbol: "+", + outputFunc: (eq, i, columns) => horizontalEqZX_(eq, i, columns, "-"), + answerKey: eq => eq.y, + }, + "subtraction-2-1": { + title: "Subtraction 2-1-digit Equations", category: "Subtraction", + count: 44, columns: 4, + xSize: 1, ySize: 2, mathSymbol: "+", + outputFunc: (eq, i, columns) => verticalEqZX_(eq, i, columns, "-"), + answerKey: eq => eq.y, + }, + "subtraction-2-2": { + title: "Subtraction 2-digit Equations", category: "Subtraction", + count: 44, columns: 4, + xSize: 2, ySize: 2, mathSymbol: "+", + outputFunc: (eq, i, columns) => verticalEqZX_(eq, i, columns, "-"), + answerKey: eq => eq.y, + }, + "subtraction-3-3": { + title: "Subtraction 3-digit Equations", category: "Subtraction", + count: 44, columns: 4, long: true, + xSize: 3, ySize: 3, mathSymbol: "+", + outputFunc: (eq, i, columns, long) => verticalEqZX_(eq, i, columns, "-", long), + answerKey: eq => eq.y, + }, + "subtraction-4-4": { + title: "Subtraction 4-digit Equations", category: "Subtraction", + count: 44, columns: 4, long: true, + xSize: 4, ySize: 4, mathSymbol: "+", + outputFunc: (eq, i, columns, long) => verticalEqZX_(eq, i, columns, "-", long), + answerKey: eq => eq.y, + }, + "subtraction-5-5": { + title: "Subtraction 5-digit Equations", category: "Subtraction", + count: 44, columns: 4, long: true, + xSize: 5, ySize: 5, mathSymbol: "+", + outputFunc: (eq, i, columns, long) => verticalEqZX_(eq, i, columns, "-", long), + answerKey: eq => eq.y, + }, + "multiplication-vis-emoji": { + title: "Muliplication Visual Emoji Equations", category: "Multiplication", + count: 16, columns: 2, + xSize: 1, ySize: 1, + myGenEq: (maxDigit) => { + const xOptions = [2,3,4].filter(n => !maxDigit || maxDigit >= 9 || n <= maxDigit); + const yOptions = [1,2,3,4,5].filter(n => !maxDigit || maxDigit >= 9 || n <= maxDigit); + const x = xOptions.length > 0 ? randArr(xOptions) : randArr([2,3,4]); + const y = yOptions.length > 0 ? randArr(yOptions) : randArr([1,2,3,4,5]); + const z = x * y; + return { x, y, z }; + }, + outputFunc: (eq, i, columns) => visualEmojiMultiEq(eq, i, columns), + }, + "multiplication-vis-1": { + title: "Muliplication Visual Lvl 1 Equations", category: "Multiplication", + count: 16, columns: 2, + xSize: 1, ySize: 1, + myGenEq: (maxDigit) => { + const options = [2,3,4,5,6]; + let x, y; + if (maxDigit && maxDigit < 9) { + // Ensure at least one operand is <= maxDigit + const constrainedOptions = options.filter(n => n <= maxDigit); + if (constrainedOptions.length > 0) { + if (Math.random() < 0.5) { + x = randArr(constrainedOptions); + y = randArr(options); + } else { + x = randArr(options); + y = randArr(constrainedOptions); + } + } else { + x = randArr(options); + y = randArr(options); + } + } else { + x = randArr(options); + y = randArr(options); + } + const z = x * y; + return { x, y, z }; + }, + outputFunc: (eq, i, columns) => visualMultiEq(eq, i, columns, 6), + }, + "multiplication-vis-2": { + title: "Muliplication Visual Lvl 2 Equations", category: "Multiplication", + count: 16, columns: 2, + xSize: 1, ySize: 1, + outputFunc: (eq, i, columns) => visualMultiEq(eq, i, columns, 9), + }, + "multiplication-add-1": { + title: "Muliplication Add Equations 1", category: "Multiplication", + count: 16, columns: 2, + myGenEqList: () => { + const xList = [6,7,8,9]; + const yList = [2,3,4,5]; + const eqList = []; + xList.forEach(x => yList.forEach(y => eqList.push({x, y, z: x * y}))); + eqList.sort(() => Math.random() - 0.5); //shuffle + eqList.sort(() => Math.random() - 0.5); //shuffle + return eqList; + }, + outputFunc: (eq, i, columns) => multiAddEq(eq, i, columns), + }, + "multiplication-add-2": { + title: "Muliplication Add Equations 2", category: "Multiplication", + count: 16, columns: 2, + myGenEqList: () => { + const xList = [6,7,8,9]; + const yList = [6,7,8,9]; + const eqList = []; + xList.forEach(x => yList.forEach(y => eqList.push({x, y, z: x * y}))); + eqList.sort(() => Math.random() - 0.5); //shuffle + eqList.sort(() => Math.random() - 0.5); //shuffle + return eqList; + }, + outputFunc: (eq, i, columns) => multiAddEq2(eq, i, columns), + }, + "multiplication": { + title: "Multiplication 1-digit Equations", category: "Multiplication", + count: 64, columns: 4, + xSize: 1, ySize: 1, + useAllPossible1Digit: 1, + mathSymbol: "*", + outputFunc: (eq, i, columns) => horizontalEq(eq, i, columns, "×"), + }, + "multiplication-find-multiple": { + title: "Multiplication Find Multiple Equations", category: "Multiplication", + count: 20, columns: 3, + xSize: 1, ySize: 1, + useAllPossible1Digit: 1, + mathSymbol: "*", + outputFunc: (eq, i, columns) => horizontalEqX_Y(eq, i, columns, "×"), + }, + "multiplication-11-13": { + title: "Multiplication with 11 to 13 Equations", category: "Multiplication", + count: 64, columns: 3, + mathSymbol: "*", + myGenEq: (maxDigit) => { + const x = randRange(11, 14); + let y; + if (maxDigit && maxDigit < 9) { + // For this special case with 11-13, constrain y to be <= maxDigit + const validDigits = SINGLE_DIGITS.filter(d => d <= maxDigit); + y = validDigits.length > 0 ? randArr(validDigits) : randNoOnes(); + } else { + y = randNoOnes(); + } + const z = x * y; + return { x, y, z }; + }, + outputFunc: (eq, i, columns) => horizontalEq(eq, i, columns, "×"), + }, + "multiplication-2-1": { + title: "Muliplication 2 to 1-digit Equations", category: "Multiplication", + count: 44, columns: 4, + xSize: 2, ySize: 1, + mathSymbol: "*", + outputFunc: (eq, i, columns) => verticalEq(eq, i, columns, "×"), + }, + "multiplication-2-2": { + title: "Muliplication 2-digit Equations", category: "Multiplication", + count: 28, columns: 4, long: true, answerSpace: 6, + xSize: 2, ySize: 2, + mathSymbol: "*", + outputFunc: (eq, i, columns, long, answerSpace) => verticalEq(eq, i, columns, "×", long, answerSpace), + }, + "multiplication-3": { + title: "Muliplication 3-digit Equations", category: "Multiplication", + count: 24, columns: 4, long: true, answerSpace: 10, + xSize: 3, ySize: 3, + mathSymbol: "*", + outputFunc: (eq, i, columns, long, answerSpace) => verticalEq(eq, i, columns, "×", long, answerSpace), + }, + "division": { + title: "Division 1-digit Equations", category: "Division", + count: 64, columns: 4, + xSize: 1, ySize: 1, + useAllPossible1Digit: 1, + mathSymbol: "*", + outputFunc: (eq, i, columns) => horizontalEqZX_(eq, i, columns, "÷"), + answerKey: eq => eq.y, + }, + "division-box": { + title: "Division Box Format Equations", category: "Division", + count: 36, columns: 4, + xSize: 1, ySize: 1, + useAllPossible1Digit: 1, + mathSymbol: "*", + outputFunc: (eq, i, columns) => longDivEq(eq, i, columns), + answerKey: eq => eq.y, + }, + "division-box-remainders": { + title: "Division Box Format w/Remainders Equations", category: "Division", + count: 27, columns: 3, + myGenEq: () => { + const x = randNoOnes(); + const y = randNoOnes(); + const remainder = rand(x - 1) + 1; + const z = (x * y) + remainder; + return { x, y, z, remainder}; + }, + outputFunc: (eq, i, columns) => longDivEq(eq, i, columns), + answerKey: eq => `${eq.y} r. ${eq.remainder}`, + }, + "division-long": { + title: "Long Division Equations", category: "Division", + count: 27, columns: 3, + myGenEq: () => { + const x = randNoOnes(); + const y = randRangeByDigits(2); + const z = x * y; + return { x, y, z }; + }, + outputFunc: (eq, i, columns) => longDivEq(eq, i, columns), + answerKey: eq => eq.y, + }, + "division-longer": { + title: "Longer Division Equations", category: "Division", + count: 24, columns: 3, + myGenEq: () => { + const x = randNoOnes(); + const y = randRangeByDigits(3); + const z = x * y; + return { x, y, z }; + }, + outputFunc: (eq, i, columns) => longDivEq(eq, i, columns, true), + answerKey: eq => eq.y, + }, + "division-long-remainders": { + title: "Long Division w/Remainders Equations", category: "Division", + count: 27, columns: 3, + myGenEq: () => { + const x = randNoOnes(); + const y = randRangeByDigits(2); + const remainder = rand(x - 1) + 1; + const z = (x * y) + remainder; + return { x, y, z, remainder}; + }, + outputFunc: (eq, i, columns) => longDivEq(eq, i, columns), + answerKey: eq => `${eq.y} r. ${eq.remainder}`, + }, + "division-longer-remainders": { + title: "Longer Division w/Remainders Equations", category: "Division", + count: 24, columns: 3, + mathSymbol: "*", + myGenEq: () => { + const x = randNoOnes(); + const y = randRangeByDigits(3); + const remainder = rand(x - 1) + 1; + const z = (x * y) + remainder; + return { x, y, z, remainder}; + }, + outputFunc: (eq, i, columns) => longDivEq(eq, i, columns, true), + answerKey: eq => `${eq.y} r. ${eq.remainder}`, + }, +}; diff --git a/docs/js/jp-data.js b/docs/js/jp-data.js new file mode 100644 index 0000000..9fc7e6b --- /dev/null +++ b/docs/js/jp-data.js @@ -0,0 +1,52 @@ +const hiraganaCsv = "ใ‚,a,ใ„,i,ใ†,u,ใˆ,e,ใŠ,o,ใ‹,ka,ใ,ki,ใ,ku,ใ‘,ke,ใ“,ko,ใ•,sa,ใ—,shi,ใ™,su,ใ›,se,ใ,so,ใŸ,ta,ใก,chi,ใค,tsu,ใฆ,te,ใจ,to,ใช,na,ใซ,ni,ใฌ,nu,ใญ,ne,ใฎ,no,ใฏ,ha,ใฒ,hi,ใต,hu,ใธ,he,ใป,ho,ใพ,ma,ใฟ,mi,ใ‚€,mu,ใ‚,me,ใ‚‚,mo,ใ‚„,ya,ใ‚†,yu,ใ‚ˆ,yo,ใ‚‰,ra,ใ‚Š,ri,ใ‚‹,ru,ใ‚Œ,re,ใ‚,ro,ใ‚,wa,ใ‚’,wo,ใ‚“,n,ใŒ,ga,ใŽ,gi,ใ,gu,ใ’,ge,ใ”,go,ใ–,za,ใ˜,ji,ใš,zu,ใœ,ze,ใž,zo,ใ ,da,ใข,ji,ใฅ,zu,ใง,de,ใฉ,do,ใฐ,ba,ใณ,bi,ใถ,bu,ใน,be,ใผ,bo,ใฑ,pa,ใด,pi,ใท,pu,ใบ,pe,ใฝ,po,ใใ‚ƒ,kya,ใใ‚…,kyu,ใใ‚‡,kyo,ใ—ใ‚ƒ,sha,ใ—ใ‚…,shu,ใ—ใ‚‡,sho,ใกใ‚ƒ,cha,ใกใ‚…,chu,ใกใ‚‡,cho,ใซใ‚ƒ,nya,ใซใ‚…,nyu,ใซใ‚‡,nyo,ใฒใ‚ƒ,hya,ใฒใ‚…,hyu,ใฒใ‚‡,hyo,ใฟใ‚ƒ,mya,ใฟใ‚…,myu,ใฟใ‚‡,myo,ใ‚Šใ‚ƒ,rya,ใ‚Šใ‚…,ryu,ใ‚Šใ‚‡,ryo,ใŽใ‚ƒ,gya,ใŽใ‚…,gyu,ใŽใ‚‡,gyo,ใ˜ใ‚ƒ,ja,ใ˜ใ‚…,ju,ใ˜ใ‚‡,jo,ใณใ‚ƒ,bya,ใณใ‚…,byu,ใณใ‚‡,byo,ใดใ‚ƒ,pya,ใดใ‚…,pyu,ใดใ‚‡,pyo"; +const katakanaCsv = "ใ‚ข,a,ใ‚ค,i,ใ‚ฆ,u,ใ‚จ,e,ใ‚ช,o,ใ‚ซ,ka,ใ‚ญ,ki,ใ‚ฏ,ku,ใ‚ฑ,ke,ใ‚ณ,ko,ใ‚ต,sa,ใ‚ท,shi,ใ‚น,su,ใ‚ป,se,ใ‚ฝ,so,ใ‚ฟ,ta,ใƒ,chi,ใƒ„,tsu,ใƒ†,te,ใƒˆ,to,ใƒŠ,na,ใƒ‹,ni,ใƒŒ,nu,ใƒ,ne,ใƒŽ,no,ใƒ,ha,ใƒ’,hi,ใƒ•,hu,ใƒ˜,he,ใƒ›,ho,ใƒž,ma,ใƒŸ,mi,ใƒ ,mu,ใƒก,me,ใƒข,mo,ใƒค,ya,ใƒฆ,yu,ใƒจ,yo,ใƒฉ,ra,ใƒช,ri,ใƒซ,ru,ใƒฌ,re,ใƒญ,ro,ใƒฏ,wa,ใƒฒ,wo,ใƒณ,n,ใ‚ฌ,ga,ใ‚ฎ,gi,ใ‚ฐ,gu,ใ‚ฒ,ge,ใ‚ด,go,ใ‚ถ,za,ใ‚ธ,ji,ใ‚บ,zu,ใ‚ผ,ze,ใ‚พ,zo,ใƒ€,da,ใƒ‚,ji,ใƒ…,zu,ใƒ‡,de,ใƒ‰,do,ใƒ,ba,ใƒ“,bi,ใƒ–,bu,ใƒ™,be,ใƒœ,bo,ใƒ‘,pa,ใƒ”,pi,ใƒ—,pu,ใƒš,pe,ใƒ,po,ใ‚ญใƒฃ,kya,ใ‚ญใƒฅ,kyu,ใ‚ญใƒง,kyo,ใ‚ทใƒฃ,sha,ใ‚ทใƒฅ,shu,ใ‚ทใƒง,sho,ใƒใƒฃ,cha,ใƒใƒฅ,chu,ใƒใƒง,cho,ใƒ‹ใƒฃ,nya,ใƒ‹ใƒฅ,nyu,ใƒ‹ใƒง,nyo,ใƒ’ใƒฃ,hya,ใƒ’ใƒฅ,hyu,ใƒ’ใƒง,hyo,ใƒŸใƒฃ,mya,ใƒŸใƒฅ,myu,ใƒŸใƒง,myo,ใƒชใƒฃ,rya,ใƒชใƒฅ,ryu,ใƒชใƒง,ryo,ใ‚ฎใƒฃ,gya,ใ‚ฎใƒฅ,gyu,ใ‚ฎใƒง,gyo,ใ‚ธใƒฃ,ja,ใ‚ธใƒฅ,ju,ใ‚ธใƒง,jo,ใƒ“ใƒฃ,bya,ใƒ“ใƒฅ,byu,ใƒ“ใƒง,byo,ใƒ”ใƒฃ,pya,ใƒ”ใƒฅ,pyu,ใƒ”ใƒง,pyo,ใ‚คใ‚ฃ,yi,ใ‚คใ‚ง,ye,ใƒดใ‚ก,va,ใƒดใ‚ฃ,vi,ใƒด,vu,ใƒดใ‚ง,ve,ใƒดใ‚ฉ,vo,ใƒดใƒฃ,vya,ใƒดใƒฅ,vyu,ใƒดใƒง,vyo,ใ‚ทใ‚ง,she,ใ‚ธใ‚ง,je,ใƒใ‚ง,che,ใ‚นใ‚ก,swa,ใ‚นใ‚ฃ,swi,ใ‚นใ‚ฅ,swu,ใ‚นใ‚ง,swe,ใ‚นใ‚ฉ,swo,ใ‚นใƒฃ,sya,ใ‚นใƒฅ,syu,ใ‚นใƒง,syo,ใ‚ปใ‚ฃ,si,ใ‚บใ‚ก,zwa,ใ‚บใ‚ฃ,zwi,ใ‚บใ‚ฅ,zwu,ใ‚บใ‚ง,zwe,ใ‚บใ‚ฉ,zwo,ใ‚บใƒฃ,zya,ใ‚บใƒฅ,zyu,ใ‚บใƒง,zyo,ใ‚ผใ‚ฃ,zi,ใƒ„ใ‚ก,tsa,ใƒ„ใ‚ฃ,tsi,ใƒ„ใ‚ง,tse,ใƒ„ใ‚ฉ,tso,ใƒ†ใ‚ก,tha,ใƒ†ใ‚ฃ,ti,ใƒ†ใ‚ฅ,thu,ใƒ†ใ‚ง,tye,ใƒ†ใ‚ฉ,tho,ใƒ†ใƒฃ,tya,ใƒ†ใƒฅ,tyu,ใƒ†ใƒง,tyo,ใƒ‡ใ‚ก,dha,ใƒ‡ใ‚ฃ,di,ใƒ‡ใ‚ฅ,dhu,ใƒ‡ใ‚ง,dye,ใƒ‡ใ‚ฉ,dho,ใƒ‡ใƒฃ,dya,ใƒ‡ใƒฅ,dyu,ใƒ‡ใƒง,dyo,ใƒˆใ‚ก,twa,ใƒˆใ‚ฃ,twi,ใƒˆใ‚ฅ,tu,ใƒˆใ‚ง,twe,ใƒˆใ‚ฉ,two,ใƒ‰ใ‚ก,dwa,ใƒ‰ใ‚ฃ,dwi,ใƒ‰ใ‚ฅ,du,ใƒ‰ใ‚ง,dwe,ใƒ‰ใ‚ฉ,dwo,ใƒ•ใ‚ก,fa,ใƒ•ใ‚ฃ,fi,ใƒ›ใ‚ฅ,hu,ใƒ•ใ‚ง,fe,ใƒ•ใ‚ฉ,fo,ใƒ•ใƒฃ,fya,ใƒ•ใƒฅ,fyu,ใƒ•ใƒง,fyo,ใƒชใ‚ฃ,ryi,ใƒชใ‚ง,rye,ใ‚ฆใ‚ก,(wa),ใ‚ฆใ‚ฃ,wi,ใ‚ฆใ‚ฅ,(wu),ใ‚ฆใ‚ง,we,ใ‚ฆใ‚ฉ,wo,ใ‚ฆใƒฃ,wya,ใ‚ฆใƒฅ,wyu,ใ‚ฆใƒง,wyo,ใ‚ฏใ‚ก,kwa,ใ‚ฏใ‚ฃ,kwi,ใ‚ฏใ‚ฅ,kwu,ใ‚ฏใ‚ง,kwe,ใ‚ฏใ‚ฉ,kwo,ใ‚ฐใ‚ก,gwa,ใ‚ฐใ‚ฃ,gwi,ใ‚ฐใ‚ฅ,gwu,ใ‚ฐใ‚ง,gwe,ใ‚ฐใ‚ฉ,gwo,ใƒ ใ‚ก,mwa,ใƒ ใ‚ฃ,mwi,ใƒ ใ‚ฅ,mwu,ใƒ ใ‚ง,mwe,ใƒ ใ‚ฉ,mwo"; + +const csvToJaRo = csvStr => { + const arr = csvStr.split`,`; + return arr.reduce((prev, curr, i) => { + if (i % 2) prev.push({ja: arr[i - 1], ro: curr}); + return prev; + }, []); +}; + +const hiragana = csvToJaRo(hiraganaCsv); +const katakana = csvToJaRo(katakanaCsv); + +const hiraganaSets = { + "A-NA": hiragana.filter(({ro}) => ro === "chi" || ( + "aiueokstn".includes(ro[0]) && ro[1] !== "y" + && !"sha,shu,sho,n".split`,`.includes(ro) + )), + "HA-WA": hiragana.filter(({ro}) => "hmyrw".includes(ro[0]) && ro[1] !== "y" || ro === "n"), + //"Non-Digraphs": hiragana.filter(({ro}) => ro[1] !== "y"), + "Digraphs": hiragana.filter(({ro}) => ro[1] === "y"), +}; + +const katakanaSets = { + "A-NA": katakana.filter(({ro, ja}) => ro === "chi" || ( + "aiueokstnc".includes(ro[0]) + && !"yw".includes(ro[1]) + && !(ro.length === 2 && ja[0] === "ใ‚ฆ") + && !"n,she,si,tsa,tsi,tse,tso,tha,ti,thu,tho,tu,sha,shu,sho,cha,chu,cho,che".split`,`.includes(ro) + )), + "HA-WA": katakana.filter(({ro}) => ro === "n" || ("hmyrw".includes(ro[0]) && ro[1] !== "y" + && !"yi,ye,hu,wi,we,mwa,mwi,mwu,mwe,mwo".split`,`.includes(ro))), + //"Non-Digraphs": katakana.filter(({ro}) => ro[1] !== "y"), + "Digraphs": katakana.filter(({ro}) => ro[1] === "y"), +}; + +console.log(hiragana); + + +const printAllSets = set => { + printSet(set, "A-NA") + printSet(set, "HA-WA") + printSet(set, "Digraphs") +}; +const printSet = (set, name) => { + console.log("===================", name) + console.log(set[name].length, set[name]) + console.log(set[name].map(a => a.ro).join(",")) +}; +printAllSets(hiraganaSets); +printAllSets(katakanaSets); diff --git a/docs/js/util.js b/docs/js/util.js new file mode 100644 index 0000000..8bdb6cf --- /dev/null +++ b/docs/js/util.js @@ -0,0 +1,66 @@ +const emojis = "โšฝ๏ธ ๐Ÿ€ ๐Ÿˆ โšพ๏ธ ๐ŸฅŽ ๐ŸŽพ ๐Ÿ ๐Ÿ‰ ๐Ÿฅ ๐ŸŽฑ ๐Ÿช€ ๐Ÿ“ ๐Ÿธ ๐Ÿ’ ๐Ÿ‘ ๐Ÿฅ ๐Ÿ ๐Ÿฅ… โ›ณ๏ธ ๐Ÿš— ๐Ÿš• ๐Ÿš™ ๐ŸšŒ ๐ŸšŽ ๐ŸŽ ๐Ÿš“ ๐Ÿš‘ ๐Ÿš’ ๐Ÿš ๐Ÿšš ๐Ÿš› ๐Ÿšœ ๐Ÿšฒ ๐Ÿ›ต ๐Ÿ ๐Ÿ›บ ๐Ÿšจ ๐Ÿš” ๐Ÿš ๐Ÿš˜ ๐Ÿš– ๐Ÿšก ๐Ÿš  ๐ŸšŸ ๐Ÿšƒ ๐Ÿš‹ ๐Ÿšž ๐Ÿš ๐Ÿš„ ๐Ÿš… ๐Ÿšˆ ๐Ÿš‚ ๐Ÿš† ๐Ÿš‡ ๐ŸšŠ ๐Ÿš‰ โœˆ๏ธ ๐Ÿ›ซ ๐Ÿ›ฌ ๐Ÿ›ฉ ๐Ÿ›ฐ ๐Ÿš€ ๐Ÿ›ธ ๐Ÿš ๐Ÿ›ถ โ›ต๏ธ ๐Ÿšค ๐Ÿ›ฅ ๐Ÿ›ณ โ›ด ๐Ÿšข โš“๏ธ โ›ฝ๏ธ ๐Ÿšง ๐Ÿšฆ ๐Ÿšฅ ๐Ÿ—บ ๐Ÿ—ฟ ๐Ÿ—ฝ ๐Ÿ—ผ ๐Ÿฐ ๐Ÿฏ ๐ŸŸ ๐ŸŽก ๐ŸŽข ๐ŸŽ  โ›ฒ๏ธ โ›ฑ ๐Ÿ– ๐Ÿ ๐Ÿœ ๐ŸŒ‹ โ›ฐ ๐Ÿ” ๐Ÿ—ป ๐Ÿ• โ›บ๏ธ ๐Ÿ  ๐Ÿก ๐Ÿ˜ ๐Ÿš ๐Ÿ— ๐Ÿญ ๐Ÿข ๐Ÿฌ ๐Ÿฃ ๐Ÿค ๐Ÿฅ ๐Ÿฆ ๐Ÿจ ๐Ÿช ๐Ÿซ ๐Ÿฉ ๐Ÿ’’ ๐Ÿ› โ›ช๏ธ ๐Ÿ•Œ ๐Ÿ• ๐Ÿ›• ๐Ÿ•‹ โ›ฉ ๐Ÿ›ค ๐Ÿ›ฃ ๐Ÿ—พ ๐ŸŽ‘ ๐Ÿž ๐ŸŒ… ๐ŸŒ„ ๐ŸŒ  ๐ŸŽ‡ ๐ŸŽ† ๐ŸŒ‡ ๐ŸŒ† ๐Ÿ™ ๐ŸŒƒ ๐ŸŒŒ ๐ŸŒ‰ ๐ŸŒ ๐ŸŽช ๐Ÿฅ ๐ŸŽฎ ๐Ÿงฉ ๐Ÿ ๐ŸŽ ๐Ÿ ๐ŸŠ ๐Ÿ‹ ๐ŸŒ ๐Ÿ‰ ๐Ÿ‡ ๐Ÿ“ ๐Ÿˆ ๐Ÿ’ ๐Ÿ‘ ๐Ÿฅญ ๐Ÿ ๐Ÿฅฅ ๐Ÿฅ ๐Ÿ… ๐Ÿ† ๐Ÿฅ‘ ๐Ÿฅฆ ๐Ÿฅฌ ๐Ÿฅ’ ๐ŸŒถ ๐ŸŒฝ ๐Ÿฅ• ๐Ÿง„ ๐Ÿง… ๐Ÿฅ” ๐Ÿ  ๐Ÿฅ ๐Ÿฅฏ ๐Ÿž ๐Ÿฅ– ๐Ÿฅจ ๐Ÿง€ ๐Ÿฅš ๐Ÿณ ๐Ÿงˆ ๐Ÿฅž ๐Ÿง‡ ๐Ÿฅ“ ๐Ÿฅฉ ๐Ÿ— ๐Ÿ– ๐Ÿฆด ๐ŸŒญ ๐Ÿ” ๐ŸŸ ๐Ÿ• ๐Ÿฅช ๐Ÿฅ™ ๐Ÿง† ๐ŸŒฎ ๐ŸŒฏ ๐Ÿฅ— ๐Ÿฅ˜ ๐Ÿ ๐Ÿœ ๐Ÿฒ ๐Ÿ› ๐Ÿฃ ๐Ÿฑ ๐ŸฅŸ ๐Ÿฆช ๐Ÿค ๐Ÿ™ ๐Ÿš ๐Ÿ˜ ๐Ÿฅ ๐Ÿฅ  ๐Ÿฅฎ ๐Ÿข ๐Ÿก ๐Ÿง ๐Ÿจ ๐Ÿฆ ๐Ÿฅง ๐Ÿง ๐Ÿฐ ๐ŸŽ‚ ๐Ÿฎ ๐Ÿญ ๐Ÿฌ ๐Ÿซ ๐Ÿฟ ๐Ÿฉ ๐Ÿช ๐ŸŒฐ ๐Ÿฅœ ๐Ÿฏ ๐Ÿฅ› ๐Ÿงƒ ๐Ÿฅค ๐Ÿ•น ๐Ÿ”จ โš’ ๐Ÿ›  ๐Ÿงธ ๐ŸŽ ๐ŸŽˆ ๐Ÿ““ ๐Ÿ“” ๐Ÿ“’ ๐Ÿ“• ๐Ÿ“— ๐Ÿ“˜ ๐Ÿ“™ ๐Ÿ“š ๐Ÿ“– ๐Ÿ–‹ ๐Ÿ–Œ ๐Ÿ– โœ๏ธ ๐Ÿ”Ž โค๏ธ ๐Ÿงก ๐Ÿ’› ๐Ÿ’š ๐Ÿ’™ ๐Ÿ’œ ๐Ÿง‘โ€๐ŸŽ„ ๐Ÿˆโ€โฌ› ๐Ÿ˜บ ๐Ÿถ ๐Ÿฑ ๐Ÿญ ๐Ÿน ๐Ÿฐ ๐ŸฆŠ ๐Ÿป ๐Ÿผ ๐Ÿจ ๐Ÿฏ ๐Ÿฆ ๐Ÿฎ ๐Ÿท ๐Ÿฝ ๐Ÿธ ๐Ÿต ๐Ÿ™ˆ ๐Ÿ™‰ ๐Ÿ™Š ๐Ÿ’ ๐Ÿ” ๐Ÿง ๐Ÿฆ ๐Ÿค ๐Ÿฃ ๐Ÿฅ ๐Ÿฆ† ๐Ÿฆ… ๐Ÿฆ‰ ๐Ÿฆ‡ ๐Ÿบ ๐Ÿ— ๐Ÿด ๐Ÿฆ„ ๐Ÿ ๐Ÿ› ๐Ÿฆ‹ ๐ŸŒ ๐Ÿž ๐Ÿœ ๐ŸฆŸ ๐Ÿฆ— ๐Ÿ•ท ๐Ÿ•ธ ๐Ÿฆ‚ ๐Ÿข ๐Ÿ ๐ŸฆŽ ๐Ÿฆ– ๐Ÿฆ• ๐Ÿ™ ๐Ÿฆ‘ ๐Ÿฆ ๐Ÿฆž ๐Ÿฆ€ ๐Ÿก ๐Ÿ  ๐ŸŸ ๐Ÿฌ ๐Ÿณ ๐Ÿ‹ ๐Ÿฆˆ ๐ŸŠ ๐Ÿ… ๐Ÿ† ๐Ÿฆ“ ๐Ÿฆ ๐Ÿฆง ๐Ÿ˜ ๐Ÿฆ› ๐Ÿฆ ๐Ÿช ๐Ÿซ ๐Ÿฆ’ ๐Ÿฆ˜ ๐Ÿƒ ๐Ÿ‚ ๐Ÿ„ ๐ŸŽ ๐Ÿ– ๐Ÿ ๐Ÿ‘ ๐Ÿฆ™ ๐Ÿ ๐ŸฆŒ ๐Ÿ• ๐Ÿฉ ๐Ÿฆฎ ๐Ÿ•โ€๐Ÿฆบ ๐Ÿˆ ๐Ÿ“ ๐Ÿฆƒ ๐Ÿฆš ๐Ÿฆœ ๐Ÿฆข ๐Ÿฆฉ ๐Ÿ•Š ๐Ÿ‡ ๐Ÿฆ ๐Ÿฆจ ๐Ÿฆก ๐Ÿฆฆ ๐Ÿฆฅ ๐Ÿ ๐Ÿ€ ๐Ÿฟ ๐Ÿฆ” ๐Ÿพ ๐Ÿ‰ ๐Ÿฒ ๐ŸŒต ๐ŸŽ„ ๐ŸŒฒ ๐ŸŒณ ๐ŸŒด ๐ŸŒฑ ๐ŸŒฟ โ˜˜๏ธ ๐Ÿ€ ๐ŸŽ ๐ŸŽ‹ ๐Ÿƒ ๐Ÿ‚ ๐Ÿ ๐Ÿ„ ๐Ÿš ๐ŸŒพ ๐Ÿ’ ๐ŸŒท ๐ŸŒน ๐ŸŒบ ๐ŸŒธ ๐ŸŒผ ๐ŸŒป ๐ŸŒž ๐ŸŒ ๐ŸŒ› ๐ŸŒš ๐ŸŒ™ ๐ŸŒŽ ๐ŸŒ ๐ŸŒ ๐Ÿช ๐Ÿ’ซ โญ๏ธ ๐ŸŒŸ โœจ โšก๏ธ โ˜„๏ธ ๐Ÿ’ฅ ๐Ÿ”ฅ ๐ŸŒช ๐ŸŒˆ โ˜€๏ธ ๐ŸŒค โ„๏ธ โ˜ƒ๏ธ โ›„๏ธ".split(" "); +const countable = "โšฝ๏ธ ๐Ÿ€ ๐Ÿˆ โšพ๏ธ ๐ŸฅŽ ๐ŸŽพ ๐Ÿ ๐Ÿš— ๐Ÿš• ๐Ÿš™ ๐ŸšŒ ๐ŸšŽ ๐ŸŽ ๐Ÿš“ ๐Ÿš‘ ๐Ÿš’ ๐Ÿš ๐Ÿšš ๐Ÿš› ๐Ÿšœ ๐Ÿšฒ ๐Ÿ›ต ๐Ÿ ๐Ÿ›บ ๐Ÿš” ๐Ÿš ๐Ÿš˜ ๐Ÿš– ๐Ÿšก ๐Ÿš  ๐ŸšŸ ๐Ÿšƒ ๐Ÿš‹ ๐Ÿšž ๐Ÿš ๐Ÿš„ ๐Ÿš… ๐Ÿšˆ ๐Ÿš‚ ๐Ÿš† ๐Ÿš‡ ๐ŸšŠ โœˆ๏ธ ๐Ÿ›ฉ ๐Ÿ›ฐ ๐Ÿš€ ๐Ÿ›ธ ๐Ÿš ๐Ÿ›ถ โ›ต๏ธ ๐Ÿšค โ›ด ๐Ÿšข โš“๏ธ โ›ฝ๏ธ ๐Ÿšง ๐Ÿšฆ ๐Ÿ—ฟ ๐Ÿ—ฝ ๐Ÿ—ผ ๐Ÿฐ ๐Ÿฏ ๐ŸŽก ๐ŸŽข ๐ŸŽ  โ›ฒ๏ธ โ›ฑ ๐Ÿ– ๐Ÿ ๐Ÿœ ๐ŸŒ‹ โ›ฐ ๐Ÿ” ๐Ÿ—ป ๐Ÿ• โ›บ๏ธ ๐Ÿ  ๐Ÿก ๐Ÿ— ๐Ÿญ ๐Ÿข ๐Ÿฌ ๐Ÿฃ ๐Ÿฅ ๐Ÿฆ ๐Ÿจ ๐Ÿช ๐Ÿซ ๐Ÿ’’ ๐Ÿ› โ›ช๏ธ ๐Ÿ•Œ ๐Ÿ• ๐Ÿ›• ๐Ÿ•‹ โ›ฉ ๐ŸŒ… ๐ŸŒ„ ๐ŸŒ  ๐ŸŽ† ๐ŸŒ‰ ๐ŸŒ ๐ŸŽช ๐Ÿฅ ๐ŸŽฎ ๐Ÿงฉ ๐Ÿ ๐ŸŽ ๐Ÿ ๐ŸŠ ๐Ÿ‹ ๐ŸŒ ๐Ÿ‰ ๐Ÿ‡ ๐Ÿ“ ๐Ÿˆ ๐Ÿ’ ๐Ÿ‘ ๐Ÿฅญ ๐Ÿ ๐Ÿฅฅ ๐Ÿฅ ๐Ÿ… ๐Ÿ† ๐Ÿฅ‘ ๐Ÿฅฆ ๐Ÿฅฌ ๐Ÿฅ’ ๐ŸŒถ ๐ŸŒฝ ๐Ÿฅ• ๐Ÿง„ ๐Ÿง… ๐Ÿฅ” ๐Ÿ  ๐Ÿฅ ๐Ÿฅฏ ๐Ÿž ๐Ÿฅ– ๐Ÿฅจ ๐Ÿง€ ๐Ÿฅš ๐Ÿณ ๐Ÿงˆ ๐Ÿฅž ๐Ÿง‡ ๐Ÿฅ“ ๐Ÿฅฉ ๐Ÿ— ๐Ÿ– ๐Ÿฆด ๐ŸŒญ ๐Ÿ” ๐ŸŸ ๐Ÿ• ๐Ÿฅช ๐Ÿฅ™ ๐Ÿง† ๐ŸŒฎ ๐ŸŒฏ ๐Ÿฅ— ๐Ÿฅ˜ ๐Ÿ ๐Ÿœ ๐Ÿฒ ๐Ÿ› ๐Ÿฃ ๐Ÿฑ ๐ŸฅŸ ๐Ÿฆช ๐Ÿค ๐Ÿ™ ๐Ÿš ๐Ÿ˜ ๐Ÿฅ  ๐Ÿฅฎ ๐Ÿข ๐Ÿก ๐Ÿง ๐Ÿจ ๐Ÿฆ ๐Ÿฅง ๐Ÿง ๐Ÿฐ ๐ŸŽ‚ ๐Ÿฎ ๐Ÿญ ๐Ÿฌ ๐Ÿซ ๐Ÿฟ ๐Ÿฉ ๐Ÿช ๐ŸŒฐ ๐Ÿฅœ ๐Ÿฏ ๐Ÿฅ› ๐Ÿงƒ ๐Ÿฅค ๐Ÿ•น ๐Ÿ”จ โš’ ๐Ÿ›  ๐Ÿงธ ๐ŸŽ ๐ŸŽˆ ๐Ÿ““ ๐Ÿ“” ๐Ÿ“’ ๐Ÿ“• ๐Ÿ“— ๐Ÿ“˜ ๐Ÿ“™ ๐Ÿ“š ๐Ÿ“– ๐Ÿ–‹ ๐Ÿ–Œ ๐Ÿ– โœ๏ธ ๐Ÿ”Ž โค๏ธ ๐Ÿงก ๐Ÿ’› ๐Ÿ’š ๐Ÿ’™ ๐Ÿ’œ ๐Ÿง‘โ€๐ŸŽ„ ๐Ÿˆโ€โฌ› ๐Ÿ˜บ ๐Ÿถ ๐Ÿฑ ๐Ÿญ ๐Ÿน ๐Ÿฐ ๐ŸฆŠ ๐Ÿป ๐Ÿผ ๐Ÿจ ๐Ÿฏ ๐Ÿฆ ๐Ÿฎ ๐Ÿท ๐Ÿฝ ๐Ÿธ ๐Ÿต ๐Ÿ™ˆ ๐Ÿ™‰ ๐Ÿ™Š ๐Ÿ’ ๐Ÿ” ๐Ÿง ๐Ÿฆ ๐Ÿค ๐Ÿฃ ๐Ÿฅ ๐Ÿฆ† ๐Ÿฆ… ๐Ÿฆ‰ ๐Ÿฆ‡ ๐Ÿบ ๐Ÿ— ๐Ÿด ๐Ÿฆ„ ๐Ÿ ๐Ÿ› ๐Ÿฆ‹ ๐ŸŒ ๐Ÿž ๐Ÿœ ๐ŸฆŸ ๐Ÿฆ— ๐Ÿ•ท ๐Ÿ•ธ ๐Ÿฆ‚ ๐Ÿข ๐Ÿ ๐ŸฆŽ ๐Ÿฆ– ๐Ÿฆ• ๐Ÿ™ ๐Ÿฆ‘ ๐Ÿฆ ๐Ÿฆž ๐Ÿฆ€ ๐Ÿก ๐Ÿ  ๐ŸŸ ๐Ÿฌ ๐Ÿณ ๐Ÿ‹ ๐Ÿฆˆ ๐ŸŠ ๐Ÿ… ๐Ÿ† ๐Ÿฆ“ ๐Ÿฆ ๐Ÿฆง ๐Ÿ˜ ๐Ÿฆ› ๐Ÿฆ ๐Ÿช ๐Ÿซ ๐Ÿฆ’ ๐Ÿฆ˜ ๐Ÿƒ ๐Ÿ‚ ๐Ÿ„ ๐ŸŽ ๐Ÿ– ๐Ÿ ๐Ÿ‘ ๐Ÿฆ™ ๐Ÿ ๐ŸฆŒ ๐Ÿ• ๐Ÿฉ ๐Ÿฆฎ ๐Ÿ•โ€๐Ÿฆบ ๐Ÿˆ ๐Ÿ“ ๐Ÿฆƒ ๐Ÿฆš ๐Ÿฆœ ๐Ÿฆข ๐Ÿฆฉ ๐Ÿ‡ ๐Ÿฆ ๐Ÿฆจ ๐Ÿฆก ๐Ÿฆฆ ๐Ÿฆฅ ๐Ÿ ๐Ÿ€ ๐Ÿฆ” ๐Ÿ‰ ๐Ÿฒ ๐ŸŒต ๐ŸŽ„ ๐ŸŒฒ ๐ŸŒณ ๐ŸŒด ๐ŸŒฑ ๐ŸŒฟ โ˜˜๏ธ ๐Ÿ€ ๐ŸŽ ๐ŸŽ‹ ๐Ÿƒ ๐Ÿ ๐Ÿ„ ๐Ÿš ๐ŸŒพ ๐Ÿ’ ๐ŸŒท ๐ŸŒน ๐ŸŒบ ๐ŸŒธ ๐ŸŒผ ๐ŸŒป ๐ŸŒž ๐ŸŒ ๐ŸŒ› ๐ŸŒš ๐ŸŒ™ ๐ŸŒŽ ๐ŸŒ ๐ŸŒ ๐Ÿช ๐Ÿ’ซ โญ๏ธ ๐ŸŒŸ โœจ โšก๏ธ โ˜„๏ธ ๐Ÿ’ฅ ๐Ÿ”ฅ ๐ŸŒช ๐ŸŒˆ โ˜€๏ธ โ„๏ธ โ˜ƒ๏ธ โ›„๏ธ".split(" "); +const rand = max => Math.floor(Math.random() * max); +const randRange = (min, max) => rand(max - min) + min; +const randArr = arr => arr[rand(arr.length)]; +const shuffle = arr => arr.map(val => ({ val, sort: Math.random() })) + .sort((a, b) => a.sort - b.sort) + .map(({val}) => val) +; +const SINGLE_DIGITS = [2,3,4,5,6,7,8,9]; +const randNoOnes = () => randArr(SINGLE_DIGITS); +const randRangeByDigits = digits => { + if (digits === 1) return randNoOnes(); + if (digits < 1) return randRange(1, digits * 10); + const start = Math.pow(10, digits - 1); + const end = Math.pow(10, digits) - 1; + return randRange(start, end); +}; +const randRangeByDigitsWithMax = (digits, maxDigit) => { + if (digits === 1) { + // For single digit, return a number from 2 to maxDigit + const validDigits = SINGLE_DIGITS.filter(d => d <= maxDigit); + return validDigits.length > 0 ? randArr(validDigits) : randNoOnes(); + } + if (digits < 1) { + const max = Math.min(digits * 10, maxDigit); + return randRange(1, max); + } + // For multi-digit numbers, constrain the first digit + const start = Math.pow(10, digits - 1); + const end = Math.min(Math.pow(10, digits) - 1, maxDigit * Math.pow(10, digits - 1) + Math.pow(10, digits - 1) - 1); + return randRange(start, end + 1); +}; +const solution = (x, y, mathSymbol) => { + switch (mathSymbol) { + case "*": return x * y; + case "/": return x / y; + case "-": return x - y; + default: return x + y; + } +}; +const getUrlParam = param => { + const paramMap = {}; + const urlArr = document.location.href.split("?"); + const queryParam = urlArr.length > 1 ? urlArr[1] : false; + if (queryParam) { + var paramArr = queryParam.split("&"); + paramArr.map(paramSet => { + if (paramSet.indexOf(param + "=") === 0) { + paramMap[param] = paramSet.split("=")[1].replace(/%20/g, " "); + } + }); + } + return paramMap[param] || false; +}; +const setUrlParam = param => { + const url = document.location.href.split("?")[0]; + window.history.pushState({ param: param }, param, url + (param ? "?" + param : "")); + return false; +}; +const strXTimes = (str, x) => { + return new Array(x).fill().map((a, i) => str + (i > 0 && i % 4 === 0 ? '
' : '')).join(""); +}; +const repeat = (str, x) => { + return new Array(x).fill().map(() => str).join(""); +}; diff --git a/docs/style.css b/docs/style.css new file mode 100644 index 0000000..8533054 --- /dev/null +++ b/docs/style.css @@ -0,0 +1,189 @@ +.grid-tbl > tbody > tr > td { + width: .5rem; + height: .5rem; + border: 2px solid gray; +} +tr.example > td.multi-vis-emoji > div { width: 100% !important } +.tip-scroller { padding-left: 0; } +.tip-scroller > li { list-style: none; } +.breadcrumb-list > li { list-style: none; } +html { scroll-behavior: smooth; } +.my-img { width: 90%; box-shadow: 0px 0px 15px 5px #888; } +.icon-shadow { + width: 50px; + margin-top: 1rem; + box-shadow: 0px 0px 15px 5px #888; + animation: grow 3s ease-in-out infinite; +} +@keyframes grow { + 0% { + width: 50px; + box-shadow: 0px 0px 8px 5px #888; + } + 50% { width: 80px; + box-shadow: 0px 0px 15px 5px #888; + } + 100% { width: 50px; + box-shadow: 0px 0px 8px 5px #888; + } +} +.page-break { page-break-after: always; } +/* body { margin: 1.5rem; } */ +.worksheets { font-size: 2rem; } +.number { + font-size: 1.5rem; + width: 2rem; + text-align: right; + margin-right: 1rem; +} +img.emoji { + width: 1.2em; + height: 1.2em; + margin: 0 .05rem 0.25rem .1rem; +} +#answerKeyCbx { width: .7rem; height: .7rem; } +.my-table > tbody > tr > td { border-top: 0; } +.table > tbody > tr:last-child { + border-bottom: 1px solid #dee2e6; +} +.my-table.table > tbody > tr:last-child { + border-bottom: 0; +} + +.equation { + width: 6rem; + letter-spacing: 1rem; + text-align: right; + white-space: nowrap; +} +.vert-equation { + letter-spacing: 1rem; + text-align: right; + white-space: nowrap; +} +.long-div { padding-bottom: 8rem; } +.long-div.er > div > .answer-input { width: 10rem; } +.long-div > div > .answer-input { + border-top: 0; + border-bottom: 3px solid black; + text-align: right; + margin-left: -1.7rem; + width: 8rem; +} +.long-div.er { padding-bottom: 10rem; } +.long-div.er > div > .answer-input { + width: 10rem; +} +.long-div-divisor { + border-right: 3px solid black; + border-radius: 1rem; + text-align: right; +} +.long-div-numerator { + letter-spacing: 1rem; + white-space: nowrap; + text-align: left; +} +.example > td > .long-div { padding-bottom: 0; } +.example .number { display: none; } +.example .emoji { font-size: 1rem; border-top: 0; } +.example > td.answer { text-align: left; padding-left:0; } +tr.example > td { padding:.75rem; text-align: right; border-top: 0 !important; } +.example > td { border: 0; text-align: right; } +.example > td .equation { width: 4rem !important; } +.example > td.pb-5 { padding-bottom: 0 !important; padding-top: 0; } +.example .answer-input.down, .example .answer-input { width: 2rem; } +.example .vert-equation > .answer-input { width: 10rem; } +.example .vert-equation.md > .answer-input { width: 5rem; } +.answer { width: 5rem; } +.text-input { border: 0px; border-bottom: 3px solid black; } +tr.example.long > td > div.equation > .answer-input { width: 3.5rem; } +tr.example.long > td > div.vert-equation > .answer-input { width: 8rem; } +tr.long > td > div.equation { width: 8rem; } +tr.long > td > div.equation > .answer-input { width: 8rem; } +tr.long > td > div.vert-equation > .answer-input { width: 10rem; } +.answer-input { + border: 0px; + border-top: 3px solid black; + letter-spacing: 1rem; + width: 6rem; + text-align: right; +} +.answer-input.down { + border-top: 0; + border-bottom: 3px solid black; + text-align: center; +} +.answer-input.box { + border: 3px solid black; + text-align: center; + width: 10rem; + height: 10rem; + margin: 0 auto; + display: block; +} +.answer-key-table { font-size: 16px; border: 1px solid gray; } +.answer-key { width: 5rem; display: inline-block; } +/* .worksheets-view-panel { margin-top: -1rem; } */ +@media print { + .no-print { display: none; } + body { margin: 0; font-size: 4px; } + .multi-vis > tbody > tr > td { + width: 1rem; + height: 1rem; + border: 1px solid black !important; + } +} +@media (max-width: 500px) { + body { margin: .3rem; } + .worksheets-view-panel { margin-top: 0; } +} + +.my-jumbo-header { + font-size: 5.5rem; + font-weight: 300; + line-height: 1.2; +} +.text-lg { font-size: 1.75rem; } +@media (min-width: 0) { + .my-jumbo-header { font-size: 2rem; } + .text-lg { font-size: 1.3rem; } +} +@media (min-width: 500px) { + .my-jumbo-header { font-size: 2rem; } + .text-lg { font-size: 1.5rem; } +} +@media (min-width: 800px) { + .my-jumbo-header { font-size: 4rem; } +} +@media (min-width: 1200px) { + .my-jumbo-header { font-size: 5.5rem; } +} +.fade-in { + animation: fadeIn ease 1s; + -webkit-animation: fadeIn ease 1s; + -moz-animation: fadeIn ease 1s; + -o-animation: fadeIn ease 1s; + -ms-animation: fadeIn ease 1s; +} +@keyframes fadeIn { 0% {opacity:0;} 100% {opacity:1;} } +@-moz-keyframes fadeIn { 0% {opacity:0;} 100% {opacity:1;} } +@-webkit-keyframes fadeIn { 0% {opacity:0;} 100% {opacity:1;} } +@-o-keyframes fadeIn { 0% {opacity:0;} 100% {opacity:1;} } +@-ms-keyframes fadeIn { 0% {opacity:0;} 100% {opacity:1;} } + +@-webkit-keyframes float { + 0% { transform: translatey(0px); } + 50% { transform: translatey(-20px); } + 100% { transform: translatey(0px); } +} +@keyframes float { + 0% { transform: translatey(0px); } + 50% { transform: translatey(-20px); } + 100% { transform: translatey(0px); } +} + +.landing-logo { + transform: translatey(0px); + animation: float 3s ease-in-out infinite; +} \ No newline at end of file
${i + 1}.) + ${eq.x} ${mathSym} = + ${eq.z}
${i + 1}.) + ${eq.z} ${mathSym} ${eq.x} = +