From b4f4e664e330650b7dcb7e15daf3826e07df20fd Mon Sep 17 00:00:00 2001 From: Jim Hill Date: Mon, 27 Apr 2020 17:50:39 -0500 Subject: [PATCH 01/31] Uploading is now on by default --- frontend/src/client/src/layouts/MyLayout.vue | 2 +- frontend/src/client/src/store/common/state.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/frontend/src/client/src/layouts/MyLayout.vue b/frontend/src/client/src/layouts/MyLayout.vue index 2d70181..a9c48a1 100644 --- a/frontend/src/client/src/layouts/MyLayout.vue +++ b/frontend/src/client/src/layouts/MyLayout.vue @@ -104,7 +104,7 @@ export default { rightDrawerOpen: false, sequenceId: 'Standard', student: '', - upload: false + upload: true } }, methods: { diff --git a/frontend/src/client/src/store/common/state.js b/frontend/src/client/src/store/common/state.js index 4c03c8a..16b3cc0 100644 --- a/frontend/src/client/src/store/common/state.js +++ b/frontend/src/client/src/store/common/state.js @@ -10,7 +10,7 @@ export default { sequence: {}, user: { sequenceId: 'Standard', - uploading: false, + uploading: true, name: '' }, retryLimit: 3, From 2dd4bc4da479e61c03fcb1d8c3b5a6a1b00f7653 Mon Sep 17 00:00:00 2001 From: Jim Hill Date: Mon, 27 Apr 2020 17:51:08 -0500 Subject: [PATCH 02/31] Updated version --- frontend/src/client/src/store/common/state.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/src/client/src/store/common/state.js b/frontend/src/client/src/store/common/state.js index 16b3cc0..278c4b0 100644 --- a/frontend/src/client/src/store/common/state.js +++ b/frontend/src/client/src/store/common/state.js @@ -1,5 +1,5 @@ export default { - version: '1.0.2.0', + version: '1.1.0.1', patternsLoading: true, patterns: {}, history: {}, From aa1c1d916c3c2f39854a89dffd4b5d70005ae446 Mon Sep 17 00:00:00 2001 From: Jim Hill Date: Mon, 27 Apr 2020 19:19:59 -0500 Subject: [PATCH 03/31] Fixed save settings and updated color scheme --- .../src/client/src/components/EelCanvas.vue | 23 ++++----- .../src/client/src/components/EelPractice.vue | 8 ++-- frontend/src/client/src/css/app.sass | 1 + .../src/client/src/css/quasar.variables.sass | 17 +++---- frontend/src/client/src/layouts/MyLayout.vue | 48 +++++++++++++------ frontend/src/client/src/pages/Index.vue | 2 +- .../src/client/src/store/common/actions.js | 2 +- frontend/src/client/src/store/common/state.js | 2 +- 8 files changed, 61 insertions(+), 42 deletions(-) diff --git a/frontend/src/client/src/components/EelCanvas.vue b/frontend/src/client/src/components/EelCanvas.vue index 6f3a7c9..c8477cb 100644 --- a/frontend/src/client/src/components/EelCanvas.vue +++ b/frontend/src/client/src/components/EelCanvas.vue @@ -57,8 +57,7 @@ export default { this.middleLineY = this.upperLineY + canvasTopWritingAreaRatio * this.canvas.height this.lowerLineY = this.middleLineY + canvasWritingAreaRatio * this.canvas.height this.lowestLineY = this.lowerLineY + canvasBottomWritingAreaRatio * this.canvas.height - this.canvas.style.background = 'linear-gradient(180deg, #f7feff, #FFFFFF, #f7feff)' - this.canvas.style.border = '1px solid #E0F7FA' + this.canvas.style.background = '#F9F7F0' }, configureCanvas () { this.canvas.addEventListener('mousedown', (e) => this.handleMouseDown(e), false) @@ -136,31 +135,29 @@ export default { }, setStrokeStyle (style) { this.context.lineCap = 'round' + this.context.strokeStyle = '#072A40' this.context.setLineDash([]) if (style === 'START_CIRCLE') { - this.context.strokeStyle = '#003300' - this.context.fillStyle = 'green' + this.context.strokeStyle = 'white' + this.context.fillStyle = '#5A8100' this.context.lineWidth = 2 } else if (style === 'END_CIRCLE') { - this.context.strokeStyle = '#900000' - this.context.fillStyle = 'red' + this.context.strokeStyle = 'white' + this.context.fillStyle = '#B74803' this.context.lineWidth = 2 } else if (style === 'USER') { - this.context.strokeStyle = '#006064' + this.context.strokeStyle = '#178CA4' this.context.lineWidth = 15 } else if (style === 'EEL') { - this.context.strokeStyle = '#FFD54F' - this.context.lineWidth = 8 + this.context.strokeStyle = '#18B7BE' + this.context.lineWidth = 7 } else if (style === 'PRIMARY_GUIDE') { - this.context.strokeStyle = '#3D4849' this.context.lineWidth = 6 } else if (style === 'DOTTED_GUIDE') { - this.context.strokeStyle = '#3D4849' this.context.lineWidth = 3 this.context.setLineDash([this.canvas.width * 0.04, this.canvas.width * 0.02875]) } else if (style === 'MINIMAL_GUIDE') { - this.context.strokeStyle = '#667b7d' - this.context.lineWidth = 4 + this.context.lineWidth = 3 } }, paintLine (from, to) { diff --git a/frontend/src/client/src/components/EelPractice.vue b/frontend/src/client/src/components/EelPractice.vue index cf0ceb9..e9bbc5c 100644 --- a/frontend/src/client/src/components/EelPractice.vue +++ b/frontend/src/client/src/components/EelPractice.vue @@ -3,7 +3,7 @@
- +
Welcome! Draw: {{letter}} @@ -17,9 +17,9 @@ - Start - - Go + Start + + Go diff --git a/frontend/src/client/src/css/app.sass b/frontend/src/client/src/css/app.sass index 329abd3..56b9db1 100644 --- a/frontend/src/client/src/css/app.sass +++ b/frontend/src/client/src/css/app.sass @@ -2,5 +2,6 @@ a { color: $primary; text-decoration: none; } body { font-family: 'Niramit', sans-serif; } +body { background-color: $background} @import url('https://fonts.googleapis.com/css?family=Niramit&display=swap'); \ No newline at end of file diff --git a/frontend/src/client/src/css/quasar.variables.sass b/frontend/src/client/src/css/quasar.variables.sass index 47576c4..d2e973d 100644 --- a/frontend/src/client/src/css/quasar.variables.sass +++ b/frontend/src/client/src/css/quasar.variables.sass @@ -12,13 +12,14 @@ // to match your app's branding. // Tip: Use the "Theme Builder" on Quasar's documentation website. -$primary : #4DD0E1 -$secondary : #CE93D8 -$accent : #006064 +$primary : #178CA4 +$secondary : #18B7BE +$accent : #072A40 -$dark : #1D1D1D +$background: #F9F7F0 +$dark : #072A40 -$positive : #21BA45 -$negative : #C10015 -$info : #31CCEC -$warning : #F2C037 +$positive : #5A8100 +$negative : #B74803 +$info : #18B7BE +$warning : #B74803 diff --git a/frontend/src/client/src/layouts/MyLayout.vue b/frontend/src/client/src/layouts/MyLayout.vue index a9c48a1..d08e40a 100644 --- a/frontend/src/client/src/layouts/MyLayout.vue +++ b/frontend/src/client/src/layouts/MyLayout.vue @@ -9,7 +9,8 @@ Blue Eel - + + @@ -17,7 +18,8 @@ v-model="leftDrawerOpen" show-if-above bordered - content-class="bg-grey-2" + elevated + :content-style="{ backgroundColor: '#f9f7f0' }" > @@ -58,16 +60,25 @@
-
v{{$store.state.common.version}}     © 2020
+ + +
v{{$store.state.common.version}}
+
© 2020
+
+
+ + + + @@ -79,15 +90,15 @@ + + + - - - @@ -95,19 +106,28 @@ export default { name: 'MyLayout', mounted: function () { - this.sequenceId = this.$router.currentRoute.query.seq || 'Standard' + this.setSettings() this.saveSequence() }, data () { return { leftDrawerOpen: false, rightDrawerOpen: false, - sequenceId: 'Standard', + sequenceId: '', student: '', - upload: true + upload: false } }, methods: { + save () { + this.saveSequence() + this.rightDrawerOpen = false + }, + setSettings (user) { + this.student = this.$router.currentRoute.query.student || this.$store.state.common.user.name + this.sequenceId = this.$router.currentRoute.query.seq || this.$store.state.common.user.sequenceId + this.upload = this.$store.state.common.user.uploading + }, saveSequence () { let user = { name: this.student, @@ -119,8 +139,8 @@ export default { }, watch: { rightDrawerOpen: function (updated, previous) { - if (updated === false) { - this.saveSequence() + if (updated === true) { + this.setSettings(this.$store.state.common.user) } } } diff --git a/frontend/src/client/src/pages/Index.vue b/frontend/src/client/src/pages/Index.vue index 79a4663..2024c38 100644 --- a/frontend/src/client/src/pages/Index.vue +++ b/frontend/src/client/src/pages/Index.vue @@ -10,7 +10,7 @@

Writing made simple!

- +
diff --git a/frontend/src/client/src/store/common/actions.js b/frontend/src/client/src/store/common/actions.js index e5182ec..ecca954 100644 --- a/frontend/src/client/src/store/common/actions.js +++ b/frontend/src/client/src/store/common/actions.js @@ -61,7 +61,7 @@ export function fetchSequence (ctx) { export function uploadPractice (ctx, update) { let sequenceId = ctx.state.user.sequenceId if (sequenceId == null || sequenceId === '') { - sequenceId = 'Standard' + return } let data = { diff --git a/frontend/src/client/src/store/common/state.js b/frontend/src/client/src/store/common/state.js index 278c4b0..a49dcdf 100644 --- a/frontend/src/client/src/store/common/state.js +++ b/frontend/src/client/src/store/common/state.js @@ -9,7 +9,7 @@ export default { pendingQueue: [], sequence: {}, user: { - sequenceId: 'Standard', + sequenceId: '', uploading: true, name: '' }, From 7de31334eadc587eb1235ff5aee9e3e148b2fea2 Mon Sep 17 00:00:00 2001 From: Jim Hill Date: Mon, 27 Apr 2020 20:06:14 -0500 Subject: [PATCH 04/31] Smoother transition when saving settings --- frontend/src/client/src/store/common/actions.js | 5 +++-- frontend/src/client/src/store/common/mutations.js | 1 + frontend/src/client/src/store/common/state.js | 3 ++- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/frontend/src/client/src/store/common/actions.js b/frontend/src/client/src/store/common/actions.js index ecca954..2e8fe37 100644 --- a/frontend/src/client/src/store/common/actions.js +++ b/frontend/src/client/src/store/common/actions.js @@ -41,8 +41,8 @@ export function fetchSequence (ctx) { if (ctx.state.user != null && ctx.state.user.sequenceId != null && ctx.state.user.sequenceId === 'jim') { sequence = { letters: [ - ['a', 'b'], - ['c', 'd'] + ['j', 'i', 'm'], + ['f'] ], words: [ ['jim', 'rocks'] @@ -53,6 +53,7 @@ export function fetchSequence (ctx) { ctx.commit('setReintroduceCount', 1) } ctx.commit('setSequence', sequence) + ctx.commit('resetState', ctx.state.level) } // ////////////////// diff --git a/frontend/src/client/src/store/common/mutations.js b/frontend/src/client/src/store/common/mutations.js index d61a1fe..a792aaf 100644 --- a/frontend/src/client/src/store/common/mutations.js +++ b/frontend/src/client/src/store/common/mutations.js @@ -88,6 +88,7 @@ export function resetState (state, level) { state.letter = '' state.activeQueue = [] state.stableQueue = [] + state.level = level if (level === 'word') { state.pendingQueue = Array.from(state.sequence.words, block => Array.from(block, word => word)) } else { diff --git a/frontend/src/client/src/store/common/state.js b/frontend/src/client/src/store/common/state.js index a49dcdf..36b49d1 100644 --- a/frontend/src/client/src/store/common/state.js +++ b/frontend/src/client/src/store/common/state.js @@ -1,5 +1,5 @@ export default { - version: '1.1.0.1', + version: '1.1.0.2', patternsLoading: true, patterns: {}, history: {}, @@ -7,6 +7,7 @@ export default { activeQueue: [], stableQueue: [], pendingQueue: [], + level: '', sequence: {}, user: { sequenceId: '', From 83966250549eab101efe9a5487e91fb70791f114 Mon Sep 17 00:00:00 2001 From: Jim Hill Date: Tue, 28 Apr 2020 17:54:53 -0500 Subject: [PATCH 05/31] Added endpoint checks to ensure directionality is met --- frontend/src/client/src/logic/path.js | 2 +- frontend/src/client/src/logic/validate.js | 27 +++++++++++++++++++++++ 2 files changed, 28 insertions(+), 1 deletion(-) diff --git a/frontend/src/client/src/logic/path.js b/frontend/src/client/src/logic/path.js index c04f9fd..9c4eee9 100644 --- a/frontend/src/client/src/logic/path.js +++ b/frontend/src/client/src/logic/path.js @@ -9,7 +9,7 @@ export function size (path) { return { x: Math.max(max.x, p.x), y: Math.max(max.y, p.y) } }) - return Math.max([maxs.x - mins.x, maxs.y - mins.y]) + return Math.max(maxs.x - mins.x, maxs.y - mins.y) } export function simplify (originalPath, desiredPoints) { diff --git a/frontend/src/client/src/logic/validate.js b/frontend/src/client/src/logic/validate.js index 4060e8c..aecf4c8 100644 --- a/frontend/src/client/src/logic/validate.js +++ b/frontend/src/client/src/logic/validate.js @@ -1,6 +1,13 @@ import * as path from './path.js' +import * as vector from './vector.js' export function compare (a, b) { + return comparePathLength(a, b) && + comparePoints(a, b, 'start') && + comparePoints(a, b, 'end') +} + +function comparePathLength (a, b) { const countA = a.length || 0 const countB = b.length || 0 if (countA < 10 || countB < 10) { @@ -19,3 +26,23 @@ export function compare (a, b) { } return false } + +function comparePoints (a, b, typeFilter) { + let filteredA = a.filter(point => point.type === typeFilter) + let filteredB = b.filter(point => point.type === typeFilter) + + let size = path.size(a) + for (let i = 0; i < filteredA.length; i++) { + let minDist = size + for (let j = 0; j < filteredB.length; j++) { + let lineAB = vector.substract(filteredA[i], filteredB[j]) + let dist = vector.magnitude(lineAB) + minDist = Math.min(minDist, dist) + } + let error = minDist / size + if (error > 0.1) { + return false + } + } + return true +} From c2f3ffbb3c1dc68fd9269b61aeb2a7752179048b Mon Sep 17 00:00:00 2001 From: Jim Hill Date: Tue, 28 Apr 2020 18:08:00 -0500 Subject: [PATCH 06/31] Increased render speed for just start/end points --- frontend/src/client/src/components/EelCanvas.vue | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/frontend/src/client/src/components/EelCanvas.vue b/frontend/src/client/src/components/EelCanvas.vue index c8477cb..9960451 100644 --- a/frontend/src/client/src/components/EelCanvas.vue +++ b/frontend/src/client/src/components/EelCanvas.vue @@ -189,9 +189,15 @@ export default { } this.animationSegment = 0 this.animationPoints = points - this.animationPaintPath = includePath + let drawTime = 3000 // milliseconds this.timePerPoint = drawTime / this.animationPoints.length + + if (includePath === false) { + this.animationPoints = points.filter(point => point.type === 'start' || point.type === 'end') + this.timePerPoint = 400 // milliseconds + } + this.then = Date.now() this.now = Date.now() this.isAnimating = true @@ -215,7 +221,7 @@ export default { } else if (this.animationPoints[this.animationSegment].type === 'end') { this.setStrokeStyle('END_CIRCLE') this.paintCircle(this.animationPoints[this.animationSegment], 13) - } else if (this.animationPaintPath) { + } else { this.setStrokeStyle('EEL') let endPoint = this.animationPoints[this.animationSegment + 1] || this.animationPoints[this.animationSegment] this.paintLine(this.animationPoints[this.animationSegment], endPoint) From b68909f4485b2f61ebe853dbdae4c8b8bf855092 Mon Sep 17 00:00:00 2001 From: Jim Hill Date: Tue, 28 Apr 2020 18:55:34 -0500 Subject: [PATCH 07/31] Added quicker stabilization of strong letters. --- frontend/src/client/src/store/common/mutations.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/frontend/src/client/src/store/common/mutations.js b/frontend/src/client/src/store/common/mutations.js index a792aaf..b4903d5 100644 --- a/frontend/src/client/src/store/common/mutations.js +++ b/frontend/src/client/src/store/common/mutations.js @@ -47,6 +47,10 @@ export function recordSuccess (state, letter) { if (letterHistory.attempts === 1) { letterHistory.singleAttemptSuccesses = letterHistory.singleAttemptSuccesses + 1 || 1 letterHistory.totalSingleAttemptSuccesses = letterHistory.totalSingleAttemptSuccesses + 1 || 1 + if (letterHistory.totalAttempts === 1) { // Bonus for getting it right on your very first try + letterHistory.singleAttemptSuccesses = letterHistory.singleAttemptSuccesses + 1 + letterHistory.totalSingleAttemptSuccesses = letterHistory.totalSingleAttemptSuccesses + 1 + } } Vue.set(state.history, letter, letterHistory) } From f03b27d3b92cb43b17d67b5f3fbf70e16c8ad662 Mon Sep 17 00:00:00 2001 From: Jim Hill Date: Tue, 28 Apr 2020 18:56:20 -0500 Subject: [PATCH 08/31] Forcing new bunches in before reintroduced and preloading of patterns --- .../src/client/src/components/EelPractice.vue | 5 +-- .../src/client/src/store/common/actions.js | 43 +++++++++++++------ 2 files changed, 30 insertions(+), 18 deletions(-) diff --git a/frontend/src/client/src/components/EelPractice.vue b/frontend/src/client/src/components/EelPractice.vue index e9bbc5c..86bfa3e 100644 --- a/frontend/src/client/src/components/EelPractice.vue +++ b/frontend/src/client/src/components/EelPractice.vue @@ -67,10 +67,7 @@ export default { start () { this.atStart = false this.$store.dispatch('common/startPractice', this.level) - setTimeout(() => { - // TODO: Need to wait to fetch first letter... fix this - this.refresh() - }, 1000) + this.refresh() }, done () { let recording = this.$refs.whiteboard.getRecording() diff --git a/frontend/src/client/src/store/common/actions.js b/frontend/src/client/src/store/common/actions.js index 2e8fe37..226bec3 100644 --- a/frontend/src/client/src/store/common/actions.js +++ b/frontend/src/client/src/store/common/actions.js @@ -52,6 +52,21 @@ export function fetchSequence (ctx) { ctx.commit('setStabilizeCount', 1) ctx.commit('setReintroduceCount', 1) } + for (let i = 0; i < sequence.letters.length; i++) { + let bunch = sequence.letters[i] + for (let j = 0; j < bunch.length; j++) { + ctx.dispatch('fetchLetter', bunch[j]) + } + } + for (let i = 0; i < sequence.words.length; i++) { + let bunch = sequence.words[i] + for (let j = 0; j < bunch.length; j++) { + let word = bunch[j] + for (let z = 0; z < word.length; z++) { + ctx.dispatch('fetchLetter', word[j]) + } + } + } ctx.commit('setSequence', sequence) ctx.commit('resetState', ctx.state.level) } @@ -114,12 +129,10 @@ export function practiceAttempted (ctx, update) { } export function nextLetter (ctx) { - if (ctx.state.activeQueue.length < 2 && ctx.state.pendingQueue.length > 0) { + if (ctx.state.activeQueue.length < 1) { ctx.dispatch('activateLetters') - ctx.dispatch('nextLetter') - } else { - ctx.commit('nextLetter') } + ctx.commit('nextLetter') } export function resetLetter (ctx, letter) { @@ -131,19 +144,21 @@ export function stabilizeLetter (ctx, letter) { } export function activateLetters (ctx) { - let countToAdd = Math.min(ctx.state.reintroduceCount, ctx.state.stableQueue.length) - for (let i = 0; i < countToAdd; i++) { + let countToReintroduce = 0 + + if (ctx.state.pendingQueue.length > 0) { + ctx.state.isFinalReview = false + ctx.commit('activateNextBunch') + countToReintroduce = Math.min(ctx.state.reintroduceCount, ctx.state.stableQueue.length) + } else if (!ctx.state.isFinalReview) { + ctx.state.isFinalReview = true + countToReintroduce = ctx.state.stableQueue.length + } + + for (let i = 0; i < countToReintroduce; i++) { const newLetter = ctx.state.stableQueue[0] - ctx.dispatch('fetchLetter', newLetter) ctx.commit('reintroduceLetter', newLetter) } - for (let i = 0; i < ctx.state.pendingQueue[0].length; i++) { - const newLetter = ctx.state.pendingQueue[0][i] - for (let j = 0; j < newLetter.length; j++) { - ctx.dispatch('fetchLetter', newLetter[j]) - } - } - ctx.commit('activateNextBunch') } export function lowActive (ctx, level) { From 99881f3a4a94817f19651a8d1e56d115d455b4d6 Mon Sep 17 00:00:00 2001 From: Jim Hill Date: Wed, 29 Apr 2020 18:43:40 -0500 Subject: [PATCH 09/31] Added stale fail functionality --- .../src/client/src/store/common/actions.js | 27 ++++++++++++++----- .../src/client/src/store/common/mutations.js | 20 +++++++++++--- frontend/src/client/src/store/common/state.js | 2 ++ 3 files changed, 40 insertions(+), 9 deletions(-) diff --git a/frontend/src/client/src/store/common/actions.js b/frontend/src/client/src/store/common/actions.js index 226bec3..61c3a8a 100644 --- a/frontend/src/client/src/store/common/actions.js +++ b/frontend/src/client/src/store/common/actions.js @@ -1,5 +1,7 @@ import { axios } from 'boot/axios' +const STALE_REINTRODUCE_COUNT = 2 + // ////////////////// // FETCH FROM CLOUD // ////////////////// @@ -117,9 +119,14 @@ export function practiceAttempted (ctx, update) { } if (update.success) { ctx.commit('recordSuccess', update.letter) + ctx.commit('resetFail') ctx.dispatch('nextLetter') ctx.dispatch('resetLetter', update.letter) } else if (ctx.state.history[update.letter].attempts >= ctx.state.retryLimit) { + ctx.commit('incrementFail') + if (ctx.state.consecutiveFails >= ctx.state.activeQueue.length) { + ctx.dispatch('staleFail') + } ctx.dispatch('nextLetter') ctx.dispatch('resetLetter', update.letter) } @@ -161,10 +168,18 @@ export function activateLetters (ctx) { } } -export function lowActive (ctx, level) { - -} - -export function staleFail (ctx, level) { - +export function staleFail (ctx) { + if (ctx.state.staleFails > (ctx.state.stableQueue.length / STALE_REINTRODUCE_COUNT)) { + ctx.dispatch('activateLetters') + ctx.commit('resetStaleFail') + } else if (ctx.state.stableQueue.length >= STALE_REINTRODUCE_COUNT) { + for (let i = 0; i < STALE_REINTRODUCE_COUNT; i++) { + const newLetter = ctx.state.stableQueue[0] + ctx.commit('reintroduceLetter', newLetter) + } + } else { + ctx.dispatch('activateLetters') + } + ctx.commit('recordStaleFail') + ctx.commit('resetFail') } diff --git a/frontend/src/client/src/store/common/mutations.js b/frontend/src/client/src/store/common/mutations.js index b4903d5..47b599d 100644 --- a/frontend/src/client/src/store/common/mutations.js +++ b/frontend/src/client/src/store/common/mutations.js @@ -41,6 +41,22 @@ export function incrementAttempts (state, letter) { Vue.set(state.history, letter, letterHistory) } +export function incrementFail (state) { + state.consecutiveFails = state.consecutiveFails + 1 || 1 +} + +export function resetFail (state) { + state.consecutiveFails = 0 +} + +export function recordStaleFail (state) { + state.staleFails = state.staleFails + 1 || 1 +} + +export function resetStaleFail (state) { + state.staleFails = 0 +} + export function recordSuccess (state, letter) { let letterHistory = state.history[letter] || {} letterHistory.success = true @@ -57,10 +73,8 @@ export function recordSuccess (state, letter) { export function nextLetter (state) { let next = state.activeQueue.shift() - if (state.letter != null && state.letter !== '') { - state.activeQueue.push(state.letter) - } state.letter = next + state.activeQueue.push(next) } export function stabilizeLetter (state, letter) { diff --git a/frontend/src/client/src/store/common/state.js b/frontend/src/client/src/store/common/state.js index 36b49d1..ed0e0f2 100644 --- a/frontend/src/client/src/store/common/state.js +++ b/frontend/src/client/src/store/common/state.js @@ -4,6 +4,8 @@ export default { patterns: {}, history: {}, letter: '', + consecutiveFails: 0, + staleFails: 0, activeQueue: [], stableQueue: [], pendingQueue: [], From 7fc381d082201a9249a3af93e9801a9e8956ab40 Mon Sep 17 00:00:00 2001 From: Jim Hill Date: Wed, 29 Apr 2020 18:53:00 -0500 Subject: [PATCH 10/31] Fixed bug around repeat letters showing up at final round --- .../src/client/src/store/common/actions.js | 19 ++++++------------- 1 file changed, 6 insertions(+), 13 deletions(-) diff --git a/frontend/src/client/src/store/common/actions.js b/frontend/src/client/src/store/common/actions.js index 61c3a8a..329d132 100644 --- a/frontend/src/client/src/store/common/actions.js +++ b/frontend/src/client/src/store/common/actions.js @@ -120,36 +120,29 @@ export function practiceAttempted (ctx, update) { if (update.success) { ctx.commit('recordSuccess', update.letter) ctx.commit('resetFail') + if (ctx.state.history[update.letter].singleAttemptSuccesses >= ctx.state.stabilizeCount) { + ctx.commit('stabilizeLetter', update.letter) + } ctx.dispatch('nextLetter') - ctx.dispatch('resetLetter', update.letter) + ctx.commit('resetLetter', update.letter) } else if (ctx.state.history[update.letter].attempts >= ctx.state.retryLimit) { ctx.commit('incrementFail') if (ctx.state.consecutiveFails >= ctx.state.activeQueue.length) { ctx.dispatch('staleFail') } ctx.dispatch('nextLetter') - ctx.dispatch('resetLetter', update.letter) - } - if (ctx.state.history[update.letter].singleAttemptSuccesses >= ctx.state.stabilizeCount) { - ctx.dispatch('stabilizeLetter', update.letter) + ctx.commit('resetLetter', update.letter) } } export function nextLetter (ctx) { + console.log(ctx.state) if (ctx.state.activeQueue.length < 1) { ctx.dispatch('activateLetters') } ctx.commit('nextLetter') } -export function resetLetter (ctx, letter) { - ctx.commit('resetLetter', letter) -} - -export function stabilizeLetter (ctx, letter) { - ctx.commit('stabilizeLetter', letter) -} - export function activateLetters (ctx) { let countToReintroduce = 0 From a1d06f3c0b081854d90ba69de2a085a827325835 Mon Sep 17 00:00:00 2001 From: Jim Hill Date: Wed, 29 Apr 2020 18:54:07 -0500 Subject: [PATCH 11/31] Removed dead logging --- frontend/src/client/src/store/common/actions.js | 1 - 1 file changed, 1 deletion(-) diff --git a/frontend/src/client/src/store/common/actions.js b/frontend/src/client/src/store/common/actions.js index 329d132..45f93f1 100644 --- a/frontend/src/client/src/store/common/actions.js +++ b/frontend/src/client/src/store/common/actions.js @@ -136,7 +136,6 @@ export function practiceAttempted (ctx, update) { } export function nextLetter (ctx) { - console.log(ctx.state) if (ctx.state.activeQueue.length < 1) { ctx.dispatch('activateLetters') } From 7b3c50ead9fece8f1f5c163b6d2bd1de1439fe58 Mon Sep 17 00:00:00 2001 From: Jim Hill Date: Wed, 29 Apr 2020 20:44:47 -0500 Subject: [PATCH 12/31] Added custom sequence for Brendan --- frontend/src/client/src/store/common/actions.js | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/frontend/src/client/src/store/common/actions.js b/frontend/src/client/src/store/common/actions.js index 45f93f1..fb446ac 100644 --- a/frontend/src/client/src/store/common/actions.js +++ b/frontend/src/client/src/store/common/actions.js @@ -40,6 +40,17 @@ export function fetchSequence (ctx) { ] } } + if (ctx.state.user != null && ctx.state.user.sequenceId != null && ctx.state.user.sequenceId === 'QnJlbmRh') { + sequence = { + letters: [ + ['n', 'b', 's', 'r', 'k', 'e', 'p'] + ], + words: [ + ['trains', 'are', 'cool'], + ['planes', 'fly', 'high'] + ] + } + } if (ctx.state.user != null && ctx.state.user.sequenceId != null && ctx.state.user.sequenceId === 'jim') { sequence = { letters: [ From 4777f15bd50195d82970e10c53404d18bda7ffe1 Mon Sep 17 00:00:00 2001 From: Jim Hill Date: Wed, 29 Apr 2020 21:10:22 -0500 Subject: [PATCH 13/31] Changed eel thickness back to 8 --- frontend/src/client/src/components/EelCanvas.vue | 2 +- frontend/src/client/src/store/common/state.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/frontend/src/client/src/components/EelCanvas.vue b/frontend/src/client/src/components/EelCanvas.vue index 9960451..66db1b8 100644 --- a/frontend/src/client/src/components/EelCanvas.vue +++ b/frontend/src/client/src/components/EelCanvas.vue @@ -150,7 +150,7 @@ export default { this.context.lineWidth = 15 } else if (style === 'EEL') { this.context.strokeStyle = '#18B7BE' - this.context.lineWidth = 7 + this.context.lineWidth = 8 } else if (style === 'PRIMARY_GUIDE') { this.context.lineWidth = 6 } else if (style === 'DOTTED_GUIDE') { diff --git a/frontend/src/client/src/store/common/state.js b/frontend/src/client/src/store/common/state.js index ed0e0f2..59d2aed 100644 --- a/frontend/src/client/src/store/common/state.js +++ b/frontend/src/client/src/store/common/state.js @@ -1,5 +1,5 @@ export default { - version: '1.1.0.2', + version: '1.1.0.4', patternsLoading: true, patterns: {}, history: {}, From 9c40eb5ec66507ed25d0032ba1158f08c289273d Mon Sep 17 00:00:00 2001 From: Jim Hill Date: Thu, 30 Apr 2020 18:45:09 -0500 Subject: [PATCH 14/31] Refactored layout to move technique into settings rather than be seperate views --- .../src/client/src/components/EelPractice.vue | 10 +---- frontend/src/client/src/layouts/MyLayout.vue | 45 +++++++------------ frontend/src/client/src/pages/Freeform.vue | 16 ------- frontend/src/client/src/pages/Index.vue | 2 +- frontend/src/client/src/pages/Letter.vue | 21 +++++++++ frontend/src/client/src/pages/Pattern.vue | 16 ------- frontend/src/client/src/pages/Tracing.vue | 16 ------- frontend/src/client/src/router/routes.js | 4 +- .../src/client/src/store/common/actions.js | 24 +++++++--- .../src/client/src/store/common/mutations.js | 4 ++ frontend/src/client/src/store/common/state.js | 5 ++- 11 files changed, 66 insertions(+), 97 deletions(-) delete mode 100644 frontend/src/client/src/pages/Freeform.vue create mode 100644 frontend/src/client/src/pages/Letter.vue delete mode 100644 frontend/src/client/src/pages/Pattern.vue delete mode 100644 frontend/src/client/src/pages/Tracing.vue diff --git a/frontend/src/client/src/components/EelPractice.vue b/frontend/src/client/src/components/EelPractice.vue index 86bfa3e..9ea6ec3 100644 --- a/frontend/src/client/src/components/EelPractice.vue +++ b/frontend/src/client/src/components/EelPractice.vue @@ -122,15 +122,7 @@ export default { this.isCanvasActive = true }, go () { - if (this.level === 'tracing') { - this.$router.push({ name: 'pattern' }) - } else if (this.level === 'pattern') { - this.$router.push({ name: 'freeform' }) - } else if (this.level === 'freeform') { - this.$router.push({ name: 'word' }) - } else { - this.$router.push({ name: 'congratulations' }) - } + this.$store.dispatch('common/completedTechnique') } } } diff --git a/frontend/src/client/src/layouts/MyLayout.vue b/frontend/src/client/src/layouts/MyLayout.vue index d08e40a..3a30e8c 100644 --- a/frontend/src/client/src/layouts/MyLayout.vue +++ b/frontend/src/client/src/layouts/MyLayout.vue @@ -22,31 +22,13 @@ :content-style="{ backgroundColor: '#f9f7f0' }" > - + - + - Tracing Practice - Practice tracing letters to learn the patterns - - - - - - - - Pattern Practice - Practice writing letters given a start and finish point - - - - - - - - Freeform Practice - Practice writing letters + Letter Practice + Practice writing individual letters with assistance or freeform @@ -55,7 +37,7 @@ Word Practice - Practice combining letters to make words + Practice combining letters to form complete words @@ -82,10 +64,13 @@ > - + - + + + + - - - - - - diff --git a/frontend/src/client/src/pages/Index.vue b/frontend/src/client/src/pages/Index.vue index 2024c38..ef762a1 100644 --- a/frontend/src/client/src/pages/Index.vue +++ b/frontend/src/client/src/pages/Index.vue @@ -10,7 +10,7 @@

Writing made simple!

- +
diff --git a/frontend/src/client/src/pages/Letter.vue b/frontend/src/client/src/pages/Letter.vue new file mode 100644 index 0000000..89d2d4f --- /dev/null +++ b/frontend/src/client/src/pages/Letter.vue @@ -0,0 +1,21 @@ + + + diff --git a/frontend/src/client/src/pages/Pattern.vue b/frontend/src/client/src/pages/Pattern.vue deleted file mode 100644 index eb8bb67..0000000 --- a/frontend/src/client/src/pages/Pattern.vue +++ /dev/null @@ -1,16 +0,0 @@ - - - diff --git a/frontend/src/client/src/pages/Tracing.vue b/frontend/src/client/src/pages/Tracing.vue deleted file mode 100644 index 0881fa7..0000000 --- a/frontend/src/client/src/pages/Tracing.vue +++ /dev/null @@ -1,16 +0,0 @@ - - - diff --git a/frontend/src/client/src/router/routes.js b/frontend/src/client/src/router/routes.js index 2aa3ab6..0daaabb 100644 --- a/frontend/src/client/src/router/routes.js +++ b/frontend/src/client/src/router/routes.js @@ -4,9 +4,7 @@ const routes = [ component: () => import('layouts/MyLayout.vue'), children: [ { name: 'home', path: '', component: () => import('pages/Index.vue') }, - { name: 'tracing', path: 'tracing', component: () => import('pages/Tracing.vue') }, - { name: 'pattern', path: 'pattern', component: () => import('pages/Pattern.vue') }, - { name: 'freeform', path: 'freeform', component: () => import('pages/Freeform.vue') }, + { name: 'letter', path: 'letter', component: () => import('pages/Letter.vue') }, { name: 'word', path: 'word', component: () => import('pages/Word.vue') }, { name: 'congratulations', path: 'congratulations', component: () => import('pages/Congratulations.vue') } ] diff --git a/frontend/src/client/src/store/common/actions.js b/frontend/src/client/src/store/common/actions.js index fb446ac..5f85420 100644 --- a/frontend/src/client/src/store/common/actions.js +++ b/frontend/src/client/src/store/common/actions.js @@ -28,7 +28,7 @@ export function fetchSequence (ctx) { ['feature', 'coming', 'soon'] ] } - if (ctx.state.user != null && ctx.state.user.sequenceId != null && ctx.state.user.sequenceId === 'Tm9haCBH') { + if (ctx.state.user != null && ctx.state.user.sequence != null && ctx.state.user.sequence === 'Tm9haCBH') { sequence = { letters: [ ['n', 't', 'm', 'f'], @@ -40,7 +40,7 @@ export function fetchSequence (ctx) { ] } } - if (ctx.state.user != null && ctx.state.user.sequenceId != null && ctx.state.user.sequenceId === 'QnJlbmRh') { + if (ctx.state.user != null && ctx.state.user.sequence != null && ctx.state.user.sequence === 'QnJlbmRh') { sequence = { letters: [ ['n', 'b', 's', 'r', 'k', 'e', 'p'] @@ -51,7 +51,7 @@ export function fetchSequence (ctx) { ] } } - if (ctx.state.user != null && ctx.state.user.sequenceId != null && ctx.state.user.sequenceId === 'jim') { + if (ctx.state.user != null && ctx.state.user.sequence != null && ctx.state.user.sequence === 'jim') { sequence = { letters: [ ['j', 'i', 'm'], @@ -88,8 +88,8 @@ export function fetchSequence (ctx) { // UPLOAD TO CLOUD // ////////////////// export function uploadPractice (ctx, update) { - let sequenceId = ctx.state.user.sequenceId - if (sequenceId == null || sequenceId === '') { + let sequence = ctx.state.user.sequence + if (sequence == null || sequence === '') { return } @@ -107,7 +107,7 @@ export function uploadPractice (ctx, update) { } } let filename = `${timestamp}.json` - axios.put(`https://eel3-data.s3.us-east-2.amazonaws.com/practice/${sequenceId}/${filename}`, data, config) + axios.put(`https://eel3-data.s3.us-east-2.amazonaws.com/practice/${sequence}/${filename}`, data, config) } // ////////////////// @@ -186,3 +186,15 @@ export function staleFail (ctx) { ctx.commit('recordStaleFail') ctx.commit('resetFail') } + +export function completedTechnique (ctx) { + if (ctx.state.user.technique === 'Tracing') { + ctx.commit('setTechnique', 'Pattern') + } else if (this.level === 'pattern') { + ctx.commit('setTechnique', 'Freeform') + } else { + ctx.commit('setTechnique', 'Tracing') + this.$router.push({ name: 'congratulations' }) + } + ctx.dispatch('startPractice') +} diff --git a/frontend/src/client/src/store/common/mutations.js b/frontend/src/client/src/store/common/mutations.js index 47b599d..386a96d 100644 --- a/frontend/src/client/src/store/common/mutations.js +++ b/frontend/src/client/src/store/common/mutations.js @@ -8,6 +8,10 @@ export function setSequence (state, sequence) { state.sequence = sequence } +export function setTechnique (state, technique) { + Vue.set(state.user, 'technique', technique) +} + export function setRetryLimit (state, limit) { state.retryLimit = limit } diff --git a/frontend/src/client/src/store/common/state.js b/frontend/src/client/src/store/common/state.js index 59d2aed..ecc19c2 100644 --- a/frontend/src/client/src/store/common/state.js +++ b/frontend/src/client/src/store/common/state.js @@ -12,9 +12,10 @@ export default { level: '', sequence: {}, user: { - sequenceId: '', + sequence: '', uploading: true, - name: '' + name: '', + technique: 'Tracing' }, retryLimit: 3, stabilizeCount: 3, From 780df7638fba0a1251fca03305b0f19f84964e3e Mon Sep 17 00:00:00 2001 From: Jim Hill Date: Thu, 30 Apr 2020 19:07:08 -0500 Subject: [PATCH 15/31] Finished refactor of words. Now technique is decoupled. --- frontend/src/client/src/components/EelPractice.vue | 10 +++------- frontend/src/client/src/pages/Letter.vue | 8 +++----- frontend/src/client/src/pages/Word.vue | 5 ++++- frontend/src/client/src/store/common/actions.js | 10 ++++++++-- frontend/src/client/src/store/common/mutations.js | 10 +++++++--- 5 files changed, 25 insertions(+), 18 deletions(-) diff --git a/frontend/src/client/src/components/EelPractice.vue b/frontend/src/client/src/components/EelPractice.vue index 9ea6ec3..13452bd 100644 --- a/frontend/src/client/src/components/EelPractice.vue +++ b/frontend/src/client/src/components/EelPractice.vue @@ -41,9 +41,6 @@ export default { components: { EelCanvas }, - props: { - level: String - }, data () { return { isCanvasActive: false, @@ -66,7 +63,7 @@ export default { methods: { start () { this.atStart = false - this.$store.dispatch('common/startPractice', this.level) + this.$store.dispatch('common/startPractice') this.refresh() }, done () { @@ -74,7 +71,6 @@ export default { let update = { success: this.validateSuccess(), letter: this.letter, - level: this.level, pattern: { letter: this.letter, dimensions: recording.dimensions, @@ -105,9 +101,9 @@ export default { }, demonstrateLetter () { if (this.$store.state.common.patterns[this.letter]) { - if (this.level === 'tracing') { + if (this.$store.state.common.user.technique === 'Tracing') { this.$refs.whiteboard.draw(this.$store.state.common.patterns[this.letter].path, true) - } else if (this.level === 'pattern') { + } else if (this.$store.state.common.user.technique === 'Pattern') { this.$refs.whiteboard.draw(this.$store.state.common.patterns[this.letter].path, false) } else { setTimeout(() => { diff --git a/frontend/src/client/src/pages/Letter.vue b/frontend/src/client/src/pages/Letter.vue index 89d2d4f..79df1a7 100644 --- a/frontend/src/client/src/pages/Letter.vue +++ b/frontend/src/client/src/pages/Letter.vue @@ -1,6 +1,6 @@ @@ -12,10 +12,8 @@ export default { components: { EelPractice }, - computed: { - technique: function () { - return this.$store.state.common.user.technique.toLowerCase() - } + created: function () { + this.$store.dispatch('common/changeLevel', 'letter') } } diff --git a/frontend/src/client/src/pages/Word.vue b/frontend/src/client/src/pages/Word.vue index 2e688c1..358f0b4 100644 --- a/frontend/src/client/src/pages/Word.vue +++ b/frontend/src/client/src/pages/Word.vue @@ -1,6 +1,6 @@ @@ -11,6 +11,9 @@ export default { name: 'PageWord', components: { EelPractice + }, + created: function () { + this.$store.dispatch('common/changeLevel', 'word') } } diff --git a/frontend/src/client/src/store/common/actions.js b/frontend/src/client/src/store/common/actions.js index 5f85420..e6dca26 100644 --- a/frontend/src/client/src/store/common/actions.js +++ b/frontend/src/client/src/store/common/actions.js @@ -118,14 +118,20 @@ export function loginUser (ctx, user) { ctx.dispatch('fetchSequence') } -export function startPractice (ctx, level) { - ctx.commit('resetState', level) +export function changeLevel (ctx, level) { + ctx.commit('setLevel', level) +} + +export function startPractice (ctx) { + ctx.commit('resetState') ctx.dispatch('nextLetter') } export function practiceAttempted (ctx, update) { ctx.commit('incrementAttempts', update.letter) if (ctx.state.user.uploading) { + update.technique = ctx.state.user.technique + update.level = ctx.state.level ctx.dispatch('uploadPractice', update) } if (update.success) { diff --git a/frontend/src/client/src/store/common/mutations.js b/frontend/src/client/src/store/common/mutations.js index 386a96d..9f21f20 100644 --- a/frontend/src/client/src/store/common/mutations.js +++ b/frontend/src/client/src/store/common/mutations.js @@ -8,6 +8,11 @@ export function setSequence (state, sequence) { state.sequence = sequence } +export function setLevel (state, level) { + console.log(level) + state.level = level +} + export function setTechnique (state, technique) { Vue.set(state.user, 'technique', technique) } @@ -105,13 +110,12 @@ export function reintroduceLetter (state, letter) { state.activeQueue.push(letter) } -export function resetState (state, level) { +export function resetState (state) { state.history = {} state.letter = '' state.activeQueue = [] state.stableQueue = [] - state.level = level - if (level === 'word') { + if (state.level === 'word') { state.pendingQueue = Array.from(state.sequence.words, block => Array.from(block, word => word)) } else { state.pendingQueue = Array.from(state.sequence.letters, block => Array.from(block, letter => letter)) From 0255cd62acef15a431e30388a3dee2484dace1a3 Mon Sep 17 00:00:00 2001 From: Jim Hill Date: Fri, 1 May 2020 00:18:15 -0500 Subject: [PATCH 16/31] Got resizing working. Just need to make canvas refresh/redraw on a resize. --- frontend/src/client/quasar.conf.js | 5 +- .../src/client/src/components/EelCanvas.vue | 14 +++-- .../src/client/src/components/EelPractice.vue | 52 ++++++++----------- frontend/src/client/src/pages/Letter.vue | 2 +- frontend/src/client/src/pages/Word.vue | 2 +- frontend/src/client/src/store/common/state.js | 2 +- 6 files changed, 36 insertions(+), 41 deletions(-) diff --git a/frontend/src/client/quasar.conf.js b/frontend/src/client/quasar.conf.js index 3f4b482..9f78536 100644 --- a/frontend/src/client/quasar.conf.js +++ b/frontend/src/client/quasar.conf.js @@ -102,9 +102,8 @@ module.exports = function (ctx) { short_name: 'Blue Eel', description: 'Learn to read', display: 'standalone', - orientation: 'portrait', - background_color: '#81d4fa', - theme_color: '#b3e5fc', + background_color: '#178CA4', + theme_color: '#178CA4', icons: [ { 'src': 'statics/icons/icon-128x128.png', diff --git a/frontend/src/client/src/components/EelCanvas.vue b/frontend/src/client/src/components/EelCanvas.vue index 66db1b8..2f73bcf 100644 --- a/frontend/src/client/src/components/EelCanvas.vue +++ b/frontend/src/client/src/components/EelCanvas.vue @@ -1,9 +1,13 @@