Bladeren bron

feat(连续加法训练): 迁移连续加法训练

chenlianwei 7 maanden geleden
bovenliggende
commit
92c8792e86

BIN
public/static/image/game/bg-continue-addition.png


+ 1 - 1
src/api/game.ts

@@ -93,7 +93,7 @@ export interface GameResultVO {
   levelList?: ResultLevel[]
 }
 
-interface Result {
+export interface Result {
   code?: string
   name?: string
   value?: string | number

+ 0 - 8
src/components.d.ts

@@ -16,16 +16,8 @@ declare module 'vue' {
     RouterView: typeof import('vue-router')['RouterView']
     SvgIcon: typeof import('./components/SvgIcon.vue')['default']
     TabBar: typeof import('./components/TabBar.vue')['default']
-    VanButton: typeof import('vant/es')['Button']
-    VanCell: typeof import('vant/es')['Cell']
-    VanCellGroup: typeof import('vant/es')['CellGroup']
     VanConfigProvider: typeof import('vant/es')['ConfigProvider']
-    VanIcon: typeof import('vant/es')['Icon']
-    VanImage: typeof import('vant/es')['Image']
     VanNavBar: typeof import('vant/es')['NavBar']
-    VanPicker: typeof import('vant/es')['Picker']
-    VanPopup: typeof import('vant/es')['Popup']
-    VanSwitch: typeof import('vant/es')['Switch']
     VanTabbar: typeof import('vant/es')['Tabbar']
     VanTabbarItem: typeof import('vant/es')['TabbarItem']
     VoiceImp: typeof import('./components/VoiceImp/index.vue')['default']

+ 248 - 0
src/pages/cognitiveTasks/ContinueAddition/index.vue

@@ -0,0 +1,248 @@
+<script setup lang="ts">
+import { showSuccessToast } from 'vant'
+import GameAPI, { type GameResultVO, type GameVO, type Result, type ResultLevel } from '@/api/game'
+
+const router = useRouter()
+
+const subjectInfo = ref<GameVO>({})
+
+// 控制倒计时的显隐
+const showCountDown = ref(true)
+// 显示题目文本
+const showSpanText = ref('')
+// 测试总次数
+const totalCount = ref(0)
+// 当前题答案
+const currentAnswer = ref(0)
+// 正确总次数
+const rightCount = ref(0)
+// 当前轮正确次数
+const currentRoundRightCount = ref(0)
+// 连续对3次
+const rightThree = ref(0)
+// 连续错两次
+const wrongTwo = ref(0)
+// 当前轮需要计算的数字个数
+const additionNumCount = ref(2)
+// 统计每个层级答对个数
+const rightCountList: Result[] = reactive([])
+// 测试时长 100 秒
+const gameDuration = ref(10 * 1000)
+// 游戏结束时间戳
+const gameEndTime = ref(0)
+// 游戏开始时间戳
+const gameStartTime = ref(0)
+// 游戏收集的数据
+const gameData: GameResultVO = {
+  finish: '1',
+  gameId: subjectInfo.value.id,
+  gameName: subjectInfo.value.name,
+  userId: sessionStorage.getItem('userId'),
+  paramList: [],
+  levelList: [],
+}
+
+function nNumRightCount() {
+  const isIndex = rightCountList.findIndex(item => Number.parseInt(item.name) === additionNumCount.value)
+  if (isIndex !== -1) {
+    if (typeof rightCountList[isIndex].value === 'number') {
+      rightCountList[isIndex].value++
+    }
+  }
+  else {
+    rightCountList.push({
+      name: additionNumCount.value.toString(),
+      value: 1,
+    })
+  }
+}
+
+function createComputeSpanText() {
+  // 生成下一道题和答案
+  const tempSpanText: number[] = []
+  let additionResult = 0
+  for (let i = additionNumCount.value; i > 0; i--) {
+    const tempNum = Math.floor(Math.random() * 10)
+    additionResult += tempNum
+    tempSpanText.push(tempNum)
+  }
+  showSpanText.value = tempSpanText.join('+')
+  currentAnswer.value = additionResult % 10
+}
+
+function userClick(answer: number) {
+  // 如果游戏时长大于或等于 100 秒,则游戏结束
+  gameEndTime.value = performance.now()
+  const duration = gameEndTime.value - gameStartTime.value
+  if (duration >= gameDuration.value) {
+    // 游戏结束,发送数据
+    sendData()
+    return
+  }
+
+  // 用户点击动作
+  totalCount.value++
+  if (answer === currentAnswer.value) {
+    // 正确次数
+    rightCount.value++
+    // 当前数字个数计算正确数加1
+    nNumRightCount()
+    // 本轮正确次数
+    currentRoundRightCount.value++
+
+    rightThree.value++
+    wrongTwo.value = 0
+    if (rightThree.value >= 3 && wrongTwo.value === 0) {
+      additionNumCount.value++
+      rightThree.value = 0
+      wrongTwo.value = 0
+    }
+  }
+  else {
+    // 正式测试时要做降级处理
+    currentRoundRightCount.value = 0
+    rightThree.value = 0
+    wrongTwo.value++
+    if (additionNumCount.value > 2 && rightThree.value === 0 && wrongTwo.value >= 2) {
+      additionNumCount.value--
+      rightThree.value = 0
+      wrongTwo.value = 0
+    }
+  }
+
+  // 生成下一道题
+  createComputeSpanText()
+}
+
+/**
+ * 倒计时结束时的回调
+ */
+function endCountDown() {
+  // 隐藏倒计时组件
+  showCountDown.value = false
+  // 开始生成游戏的第一道题
+  createComputeSpanText()
+  // 记录游戏开始时间戳
+  gameStartTime.value = performance.now()
+  // 重置游戏结束时间戳
+  gameEndTime.value = 0
+  // 重置收集的游戏数据
+}
+
+function sendData() {
+  const totalScore = rightCountList.reduce((acc, curr) => {
+    acc += curr.value as number * 2 ** (Number.parseInt(curr.name) - 2)
+    return acc
+  }, 0)
+
+  gameData.levelList = rightCountList.map((item) => {
+    return {
+      level: item.name,
+      levelParamList: [{ item }] as Result,
+    } as ResultLevel
+  })
+
+  gameData.paramList = [
+    {
+      code: 'totalScore',
+      name: '总分',
+      value: totalScore === 0 ? 0 : Number.parseFloat(Math.log2(totalScore).toString()).toFixed(2),
+    },
+    {
+      code: 'totalCount',
+      name: '题目总数',
+      value: totalCount.value,
+    },
+    {
+      code: 'rightCount',
+      name: '总正确数',
+      value: rightCount.value,
+    },
+  ]
+
+  GameAPI.add(gameData).then(() => {
+    showSuccessToast('本次训练已结束')
+    setTimeout(() => {
+      router.go(-1)
+    }, 1300)
+  })
+}
+
+onMounted(() => {
+  const temp = sessionStorage.getItem('subjectInfo')
+  if (temp) {
+    subjectInfo.value = JSON.parse(temp)
+  }
+})
+</script>
+
+<template>
+  <section class="app-container">
+    <van-nav-bar class="self-nav-bar" :title="subjectInfo.name" left-arrow @click-left="router.go(-1)" />
+    <count-down v-if="showCountDown" :time="5" color="white" @end-count-down="endCountDown" />
+    <div v-else style="" class="w-[90%] mx-auto mt-[15px] p-[15px] border-6 border-white border-solid rounded-[8px] bg-[#425363]">
+      <div class="h-[80px] flex flex-row justify-center items-center bg-[#D2E2F1] rounded-[8px]">
+        <span class="text-[40px] text-[#222222]">{{ showSpanText }}</span>
+      </div>
+      <div class="flex flex-row justify-between mt-[24px]">
+        <div class="w-[72px] h-[72px] flex flex-row justify-center items-center bg-white rounded-[8px]" @click="userClick(1)">
+          <span class="text-[32px] text-[#222222]">1</span>
+        </div>
+        <div class="w-[72px] h-[72px] flex flex-row justify-center items-center bg-white rounded-[8px]" @click="userClick(2)">
+          <span class="text-[32px] text-[#222222]">2</span>
+        </div>
+        <div class="w-[72px] h-[72px] flex flex-row justify-center items-center bg-white rounded-[8px]" @click="userClick(3)">
+          <span class="text-[32px] text-[#222222]">3</span>
+        </div>
+      </div>
+      <div class="flex flex-row justify-between mt-[24px]">
+        <div class="w-[72px] h-[72px] flex flex-row justify-center items-center bg-white rounded-[8px]" @click="userClick(4)">
+          <span class="text-[32px] text-[#222222]">4</span>
+        </div>
+        <div class="w-[72px] h-[72px] flex flex-row justify-center items-center bg-white rounded-[8px]" @click="userClick(5)">
+          <span class="text-[32px] text-[#222222]">5</span>
+        </div>
+        <div class="w-[72px] h-[72px] flex flex-row justify-center items-center bg-white rounded-[8px]" @click="userClick(6)">
+          <span class="text-[32px] text-[#222222]">6</span>
+        </div>
+      </div>
+      <div class="flex flex-row justify-between mt-[24px]">
+        <div class="w-[72px] h-[72px] flex flex-row justify-center items-center bg-white rounded-[8px]" @click="userClick(7)">
+          <span class="text-[32px] text-[#222222]">7</span>
+        </div>
+        <div class="w-[72px] h-[72px] flex flex-row justify-center items-center bg-white rounded-[8px]" @click="userClick(8)">
+          <span class="text-[32px] text-[#222222]">8</span>
+        </div>
+        <div class="w-[72px] h-[72px] flex flex-row justify-center items-center bg-white rounded-[8px]" @click="userClick(9)">
+          <span class="text-[32px] text-[#222222]">9</span>
+        </div>
+      </div>
+      <div class="flex flex-row justify-center mt-[24px]">
+        <div class="w-[72px] h-[72px] flex flex-row justify-center items-center bg-white rounded-[8px]" @click="userClick(0)">
+          <span class="text-[32px] text-[#222222]">0</span>
+        </div>
+      </div>
+    </div>
+  </section>
+</template>
+
+<style scoped lang="less">
+.app-container {
+  background-image: url('/static/image/game/bg-continue-addition.png');
+  background-size: 100% 100%;
+  background-position: center center;
+  background-repeat: no-repeat;
+
+  :deep(.van-nav-bar) {
+    &.self-nav-bar {
+      .van-nav-bar__title {
+        color: #ffffff;
+      }
+
+      .van-icon {
+        color: #ffffff;
+      }
+    }
+  }
+}
+</style>

+ 1 - 0
src/typed-router.d.ts

@@ -23,6 +23,7 @@ declare module 'vue-router/auto-routes' {
     'charts': RouteRecordInfo<'charts', '/charts', Record<never, never>, Record<never, never>>,
     '/cognitiveTasks/BreadthTraining/': RouteRecordInfo<'/cognitiveTasks/BreadthTraining/', '/cognitiveTasks/BreadthTraining', Record<never, never>, Record<never, never>>,
     '/cognitiveTasks/BreadthTraining/BTRandomPentagram': RouteRecordInfo<'/cognitiveTasks/BreadthTraining/BTRandomPentagram', '/cognitiveTasks/BreadthTraining/BTRandomPentagram', Record<never, never>, Record<never, never>>,
+    '/cognitiveTasks/ContinueAddition/': RouteRecordInfo<'/cognitiveTasks/ContinueAddition/', '/cognitiveTasks/ContinueAddition', Record<never, never>, Record<never, never>>,
     '/cognitiveTasks/main/': RouteRecordInfo<'/cognitiveTasks/main/', '/cognitiveTasks/main', Record<never, never>, Record<never, never>>,
     '/cognitiveTasks/PicturePuzzle/': RouteRecordInfo<'/cognitiveTasks/PicturePuzzle/', '/cognitiveTasks/PicturePuzzle', Record<never, never>, Record<never, never>>,
     '/cognitiveTasks/PicturePuzzle/components/PicturePuzzleChild/': RouteRecordInfo<'/cognitiveTasks/PicturePuzzle/components/PicturePuzzleChild/', '/cognitiveTasks/PicturePuzzle/components/PicturePuzzleChild', Record<never, never>, Record<never, never>>,