diff --git a/.gitignore b/.gitignore
index b5b62e4..fdb5652 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,3 +1,38 @@
.DS_Store
./QuizzyTemplate
-./QuizzyTemplate/*
+/.QuizzyTemplate
+
+# Android/Gradle
+/.gradle/
+/build/
+/app/build/
+/**/build/
+
+# Gradle wrapper
+/gradle/wrapper/gradle-wrapper.jar
+
+# Local configuration
+/local.properties
+
+# Keystore
+*.jks
+
+# Generated APKs/outputs
+**/outputs/
+**/apk/**
+*.apk
+*.ap_
+
+# IntelliJ / Android Studio
+.idea/
+*.iml
+
+# macOS
+.DS_Store
+
+# NPM / Node
+node_modules/
+
+# Misc
+*.log
+
diff --git a/.gradle/8.5/checksums/checksums.lock b/.gradle/8.5/checksums/checksums.lock
index 0881312..ad42142 100644
Binary files a/.gradle/8.5/checksums/checksums.lock and b/.gradle/8.5/checksums/checksums.lock differ
diff --git a/.gradle/8.5/checksums/md5-checksums.bin b/.gradle/8.5/checksums/md5-checksums.bin
index 3ab0385..2119158 100644
Binary files a/.gradle/8.5/checksums/md5-checksums.bin and b/.gradle/8.5/checksums/md5-checksums.bin differ
diff --git a/.gradle/8.5/checksums/sha1-checksums.bin b/.gradle/8.5/checksums/sha1-checksums.bin
index a197b7f..930219c 100644
Binary files a/.gradle/8.5/checksums/sha1-checksums.bin and b/.gradle/8.5/checksums/sha1-checksums.bin differ
diff --git a/.idea/workspace.xml b/.idea/workspace.xml
index aa9ec5e..ccd0453 100644
--- a/.idea/workspace.xml
+++ b/.idea/workspace.xml
@@ -13,6 +13,18 @@
+
+
+
+
+
+
+
+
+
+
+
+
@@ -25,20 +37,21 @@
- {
- "keyToString": {
- "ModuleVcsDetector.initialDetectionPerformed": "true",
- "RunOnceActivity.ShowReadmeOnStart": "true",
- "RunOnceActivity.cidr.known.project.marker": "true",
- "RunOnceActivity.git.unshallow": "true",
- "RunOnceActivity.readMode.enableVisualFormatting": "true",
- "cf.first.check.clang-format": "false",
- "cidr.known.project.marker": "true",
- "git-widget-placeholder": "master",
- "kotlin-language-version-configured": "true",
- "last_opened_file_path": "/Users/aln/Work/Matma"
+
+}]]>
diff --git a/app/src/main/assets/js/app.js b/app/src/main/assets/js/app.js
index d1bfe0a..8d40d9f 100644
--- a/app/src/main/assets/js/app.js
+++ b/app/src/main/assets/js/app.js
@@ -9,6 +9,7 @@ const state = {
timeLeft: 60,
sessionSolved: 0,
sessionTarget: 20,
+ history: [],
settings: {
timedSeconds: 60,
maxResult: 40,
@@ -137,6 +138,7 @@ function startPlay(){
menuScreen.classList.add('hidden')
playScreen.classList.remove('hidden')
state.score = 0
+ state.history = []
scoreEl.textContent = state.score
state.answerBuffer = ''
answerEl.textContent = ''
@@ -160,53 +162,74 @@ function startPlay(){
function generateProblem(){
const ops = Array.from(state.ops)
- const op = ops[Math.floor(Math.random()*ops.length)]
const maxOp = Math.max(1, state.settings.maxOperand)
const maxRes = Math.max(1, state.settings.maxResult)
- let a = 0, b = 0
- for (let i=0;i<200;i++){
+ let a = 0, b = 0, op = '';
+
+ const maxAttempts = 200;
+ for (let i = 0; i < maxAttempts; i++) {
+ op = ops[Math.floor(Math.random()*ops.length)]
+ let candidate = null;
+
if (op === 'div'){
b = randInt(1, maxOp)
if (!state.settings.allowFraction){
const maxQByOp = Math.floor(maxOp / b)
const maxQ = Math.min(maxRes, maxQByOp)
- if (maxQ < 0) continue
- const q = randInt(0, maxQ)
- a = q * b
- if (state.settings.allowNegative && Math.random() < 0.2) a = -a
- return {a,b,op}
+ if (maxQ >= 0) {
+ const q = randInt(0, maxQ)
+ a = q * b
+ if (state.settings.allowNegative && Math.random() < 0.2) a = -a
+ candidate = {a,b,op}
+ }
} else {
const maxResultNByOp = Math.floor((10 * maxOp) / b)
const maxResultN = Math.min(maxRes * 10, maxResultNByOp)
- if (maxResultN < 0) continue
- const result_n = randInt(0, maxResultN)
- if ((result_n * b) % 10 !== 0) continue
- a = (result_n * b) / 10
- if (state.settings.allowNegative && Math.random() < 0.2) a = -a
- return {a,b,op}
+ if (maxResultN >= 0) {
+ const result_n = randInt(0, maxResultN)
+ if ((result_n * b) % 10 === 0) {
+ a = (result_n * b) / 10
+ if (state.settings.allowNegative && Math.random() < 0.2) a = -a
+ candidate = {a,b,op}
+ }
+ }
}
} else if (op === 'mul'){
a = randInt(0, maxOp)
b = randInt(0, maxOp)
- if (a * b <= maxRes) return {a,b,op}
+ if (a * b <= maxRes) candidate = {a,b,op}
} else if (op === 'add'){
a = randInt(0, maxOp)
b = randInt(0, maxOp)
- if (a + b <= maxRes) return {a,b,op}
+ if (a + b <= maxRes) candidate = {a,b,op}
} else if (op === 'sub'){
a = randInt(0, maxOp)
b = randInt(0, maxOp)
if (!state.settings.allowNegative){
if (a < b) [a,b] = [b,a]
- if (a - b <= maxRes) return {a,b,op}
+ if (a - b <= maxRes) candidate = {a,b,op}
} else {
- if (Math.abs(a - b) <= maxRes) return {a,b,op}
+ if (Math.abs(a - b) <= maxRes) candidate = {a,b,op}
}
}
+
+ if (candidate) {
+ // Generujemy klucz dla historii. Dla dodawania i mnożenia 2+3 to to samo co 3+2.
+ const key = (op === 'add' || op === 'mul')
+ ? `${op}:${[candidate.a, candidate.b].sort().join(',')}`
+ : `${op}:${candidate.a},${candidate.b}`;
+
+ if (!state.history.includes(key) || i === maxAttempts - 1) {
+ state.history.push(key);
+ if (state.history.length > 20) state.history.shift();
+ return candidate;
+ }
+ }
}
+
a = Math.min(maxOp, Math.floor(maxRes/2))
b = Math.min(maxOp, 1)
- return {a,b,op}
+ return {a,b,op: ops[0] || 'add'}
}
function randInt(min,max){
diff --git a/app/src/main/assets/js/dzielenie.js b/app/src/main/assets/js/dzielenie.js
index 16a288c..1420d55 100644
--- a/app/src/main/assets/js/dzielenie.js
+++ b/app/src/main/assets/js/dzielenie.js
@@ -1,6 +1,6 @@
// Nauka Dzielenia
;(function () {
- const st = { divisor: null, total: 20, solved: 0, score: 0, current: null, buf: '' }
+ const st = { divisor: null, total: 20, solved: 0, score: 0, current: null, buf: '', history: [] }
const selectScreen = document.getElementById('select-screen')
const playScreen = document.getElementById('play-screen')
@@ -26,13 +26,14 @@
st.total = Math.max(5, Math.min(100, parseInt(totalInput.value, 10) || 20))
st.solved = 0
st.score = 0
+ st.history = []
show(playScreen)
nextProblem()
})
document.getElementById('back-btn').addEventListener('click', () => show(selectScreen))
document.getElementById('again-btn').addEventListener('click', () => {
- st.solved = 0; st.score = 0; show(playScreen); nextProblem()
+ st.solved = 0; st.score = 0; st.history = []; show(playScreen); nextProblem()
})
document.getElementById('change-btn').addEventListener('click', () => show(selectScreen))
@@ -60,9 +61,28 @@
function randInt(min, max) { return Math.floor(Math.random() * (max - min + 1)) + min }
function nextProblem() {
- const b = st.divisor || randInt(1, 10) // divisor
- const answer = randInt(1, 10) // quotient (always integer)
- const a = b * answer // dividend
+ let a, b, answer, key;
+ const maxAttempts = 50;
+
+ for (let i = 0; i < maxAttempts; i++) {
+ b = st.divisor || randInt(1, 10) // divisor
+ answer = randInt(1, 10) // quotient
+ a = b * answer // dividend
+
+ // Jeśli wybrano konkretny dzielnik, kluczem jest iloraz (wynik).
+ // W przeciwnym razie kluczem jest całe działanie.
+ key = st.divisor ? answer : `${a}:${b}`;
+
+ if (!st.history.includes(key) || i === maxAttempts - 1) {
+ st.history.push(key);
+ break;
+ }
+ }
+
+ if (st.history.length > (st.divisor ? 6 : 15)) {
+ st.history.shift();
+ }
+
st.current = { a, b, answer }
problemEl.textContent = `${a} ÷ ${b}`
feedbackEl.textContent = ''
diff --git a/app/src/main/assets/js/mnozenie.js b/app/src/main/assets/js/mnozenie.js
index 5be3efc..64ed945 100644
--- a/app/src/main/assets/js/mnozenie.js
+++ b/app/src/main/assets/js/mnozenie.js
@@ -1,6 +1,6 @@
// Nauka Mnożenia
;(function () {
- const st = { table: null, total: 20, solved: 0, score: 0, current: null, buf: '' }
+ const st = { table: null, total: 20, solved: 0, score: 0, current: null, buf: '', history: [] }
const selectScreen = document.getElementById('select-screen')
const playScreen = document.getElementById('play-screen')
@@ -27,13 +27,14 @@
st.total = Math.max(5, Math.min(100, parseInt(totalInput.value, 10) || 20))
st.solved = 0
st.score = 0
+ st.history = []
show(playScreen)
nextProblem()
})
document.getElementById('back-btn').addEventListener('click', () => show(selectScreen))
document.getElementById('again-btn').addEventListener('click', () => {
- st.solved = 0; st.score = 0; show(playScreen); nextProblem()
+ st.solved = 0; st.score = 0; st.history = []; show(playScreen); nextProblem()
})
document.getElementById('change-btn').addEventListener('click', () => show(selectScreen))
@@ -61,8 +62,26 @@
function randInt(min, max) { return Math.floor(Math.random() * (max - min + 1)) + min }
function nextProblem() {
- const a = st.table || randInt(1, 10)
- const b = randInt(1, 10)
+ let a, b, key;
+ const maxAttempts = 50;
+
+ for (let i = 0; i < maxAttempts; i++) {
+ a = st.table || randInt(1, 10)
+ b = randInt(1, 10)
+ // Jeśli wybrano konkretną tabelkę, kluczem jest tylko drugi składnik.
+ // Jeśli "wszystkie", kluczem jest posortowana para (żeby 2x3 i 3x2 były traktowane tak samo).
+ key = st.table ? b : [a, b].sort().join('x');
+
+ if (!st.history.includes(key) || i === maxAttempts - 1) {
+ st.history.push(key);
+ break;
+ }
+ }
+
+ if (st.history.length > (st.table ? 6 : 15)) {
+ st.history.shift();
+ }
+
st.current = { a, b, answer: a * b }
problemEl.textContent = `${a} × ${b}`
feedbackEl.textContent = ''