From ff764048292d0b847e4fbe534231915cc28164ff Mon Sep 17 00:00:00 2001 From: OkunElya Date: Fri, 24 Apr 2026 12:16:17 +1000 Subject: [PATCH] lab 8 done --- labs/lab8/package-lock.json | 10 +++ labs/lab8/package.json | 1 + labs/lab8/src/store.tsx | 2 + .../src/testing/components/SortableItem.tsx | 5 +- labs/lab8/src/testing/features/Matching.tsx | 7 ++- labs/lab8/src/testing/features/Quiz.tsx | 63 ++++++++++++++++--- .../src/testing/features/SortableList.tsx | 3 +- labs/lab8/src/testing/features/quizSlice.tsx | 41 +++++++++++- 8 files changed, 118 insertions(+), 14 deletions(-) diff --git a/labs/lab8/package-lock.json b/labs/lab8/package-lock.json index 3a19e3b..e03cb09 100644 --- a/labs/lab8/package-lock.json +++ b/labs/lab8/package-lock.json @@ -16,6 +16,7 @@ "@mui/material": "^9.0.0", "@mui/x-charts": "^9.0.1", "@mui/x-data-grid": "^9.0.1", + "@redux-devtools/extension": "^4.0.0", "@reduxjs/toolkit": "^2.11.2", "react": "^19.2.4", "react-dom": "^19.2.4", @@ -1206,6 +1207,15 @@ "url": "https://opencollective.com/popperjs" } }, + "node_modules/@redux-devtools/extension": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@redux-devtools/extension/-/extension-4.0.0.tgz", + "integrity": "sha512-pLIzgo5MvqdDLe5D1pzHLgmr8THra/DOyRf5MvOEPZnKKDn6RhFbNSS5oXZ3Cal0cpx08kx7sR6zD8QgoXEnZA==", + "license": "MIT", + "peerDependencies": { + "redux": "^3.1.0 || ^4.0.0 || ^5.0.0" + } + }, "node_modules/@reduxjs/toolkit": { "version": "2.11.2", "resolved": "https://registry.npmjs.org/@reduxjs/toolkit/-/toolkit-2.11.2.tgz", diff --git a/labs/lab8/package.json b/labs/lab8/package.json index 6bc11d0..f45b16b 100644 --- a/labs/lab8/package.json +++ b/labs/lab8/package.json @@ -18,6 +18,7 @@ "@mui/material": "^9.0.0", "@mui/x-charts": "^9.0.1", "@mui/x-data-grid": "^9.0.1", + "@redux-devtools/extension": "^4.0.0", "@reduxjs/toolkit": "^2.11.2", "react": "^19.2.4", "react-dom": "^19.2.4", diff --git a/labs/lab8/src/store.tsx b/labs/lab8/src/store.tsx index da3d11f..2233a54 100644 --- a/labs/lab8/src/store.tsx +++ b/labs/lab8/src/store.tsx @@ -1,10 +1,12 @@ import { configureStore } from '@reduxjs/toolkit'; import listsReducer from './testing/features/quizSlice'; + const store = configureStore({ reducer: { lists: listsReducer, }, + devTools: { trace: true ,traceLimit: 25}, }); export type RootState = ReturnType; diff --git a/labs/lab8/src/testing/components/SortableItem.tsx b/labs/lab8/src/testing/components/SortableItem.tsx index 731cf2b..07a965e 100644 --- a/labs/lab8/src/testing/components/SortableItem.tsx +++ b/labs/lab8/src/testing/components/SortableItem.tsx @@ -6,9 +6,10 @@ import DragIndicatorIcon from '@mui/icons-material/DragIndicator'; interface SortableItemProps { item: string; id: string;// чтобы тайпскрипт компилятор не жаловался, добавил в инетрфейс, хотя и так компилируется нормально + isDisabled:boolean; } -export function SortableItem({ item }: SortableItemProps) { +export function SortableItem({ item ,isDisabled}: SortableItemProps) { const id = item; /* идентификатор для useSortable */ const { attributes, @@ -24,7 +25,7 @@ export function SortableItem({ item }: SortableItemProps) { }; return ( - + { + dispatch(mixUp()); + }, []); + + const answers: string[] = tasks.map((item) => item.answer); return ( diff --git a/labs/lab8/src/testing/features/Quiz.tsx b/labs/lab8/src/testing/features/Quiz.tsx index 9074270..4c322b9 100644 --- a/labs/lab8/src/testing/features/Quiz.tsx +++ b/labs/lab8/src/testing/features/Quiz.tsx @@ -1,23 +1,70 @@ import { Box, Button, Container, Typography } from '@mui/material'; import { quiz } from "../quizData"; +import { useSelector } from 'react-redux'; +import {useState } from 'react'; import Matching from './Matching'; +import type { RootState } from '../../store'; +import store from '../../store'; +import { useDispatch } from 'react-redux'; +import { mixUp, startTesting, stopTesting } from './quizSlice'; + +function QuizStats() { + + const checkTask = (index: number): string => { + useSelector((state: RootState) => state.lists.lists[index]); + let state = store.getState(); + if (state.lists.correctAnswers.length <= index) { + return ""; + } + let correctCounter = state.lists.lists[index].reduce((prev, answ, i) => prev + Number(state.lists.correctAnswers[index][i] === answ), 0) + + if (correctCounter == state.lists.lists[index].length) { + return "все ответы верные" + } + return `верно ${correctCounter}/${state.lists.lists[index].length}` + + } + return ( + +

Результаты теста

+ Задание 1: {checkTask(0)} + Задание 2: {checkTask(1)} +
+ ) +} + function Quiz() { - + const dispatch = useDispatch(); + const [displayingResults, setDisplayingResults] = useState(false); + const resetQuiz = () => { + setDisplayingResults(false); + dispatch(mixUp()); + dispatch(startTesting()); + } + const checkQuiz = () => { + setDisplayingResults(true); + dispatch(stopTesting()); + } + + return ( {quiz.map((item, index) => ( - + - {index + 1}. { item.title } + {index + 1}. {item.title} - + - ))} - - - + ))} + + + + + {displayingResults && } + ); } diff --git a/labs/lab8/src/testing/features/SortableList.tsx b/labs/lab8/src/testing/features/SortableList.tsx index 7f418c0..300d822 100644 --- a/labs/lab8/src/testing/features/SortableList.tsx +++ b/labs/lab8/src/testing/features/SortableList.tsx @@ -15,6 +15,7 @@ function SortableList({ index}: ComponentProps) { const dispatch = useDispatch(); const arr = useSelector((state: RootState) => state.lists.lists[index]) + const isDisabled = useSelector((state: RootState) => state.lists.isTestingDone) const draggedItems = arr || []; const handleDragEnd = (event: any) => { @@ -33,7 +34,7 @@ function SortableList({ index}: ComponentProps) { strategy={verticalListSortingStrategy}> {draggedItems.map((item) => ( - + ))} diff --git a/labs/lab8/src/testing/features/quizSlice.tsx b/labs/lab8/src/testing/features/quizSlice.tsx index a0d9aa8..aa7d350 100644 --- a/labs/lab8/src/testing/features/quizSlice.tsx +++ b/labs/lab8/src/testing/features/quizSlice.tsx @@ -1,11 +1,33 @@ import { createSlice } from '@reduxjs/toolkit'; import type {PayloadAction} from '@reduxjs/toolkit'; + +function shuffle(array:Array):Array { + let currentIndex = array.length; + + // While there remain elements to shuffle... + while (currentIndex != 0) { + + // Pick a remaining element... + let randomIndex = Math.floor(Math.random() * currentIndex); + currentIndex--; + + // And swap it with the current element. + [array[currentIndex], array[randomIndex]] = [ + array[randomIndex], array[currentIndex]]; + } + return array; +} + interface ListsState { lists: string[][]; // хранит перемещаемые элементы каждого списка ответов + correctAnswers:string[][]; + isTestingDone:boolean } const initialState: ListsState = { lists: [], + correctAnswers:[], + isTestingDone:false }; const listsSlice = createSlice({ @@ -14,7 +36,9 @@ const listsSlice = createSlice({ reducers: { addList: (state, action: PayloadAction<{index: number; items: string[]}>)=>{ const { index, items } = action.payload; - state.lists.splice(index, 0, items); + state.lists.splice(index, 1, items); + state.correctAnswers.splice(index, 1, items); + }, setDraggedItems: (state, action: PayloadAction<{ index: number; items: string[] }>) => { const { index, items } = action.payload; @@ -22,9 +46,22 @@ const listsSlice = createSlice({ state.lists[index] = items; // обновляем конкретный список } }, + mixUp: (state) => { + state.lists=state.lists.map((list)=> + { + return shuffle(list); + }) + }, + stopTesting:(state)=>{ + state.isTestingDone=true; + }, + startTesting:(state)=>{ + state.isTestingDone=false; + } }, }); // Экспортируем действия и редьюсер -export const { addList, setDraggedItems } = listsSlice.actions; +export const { addList, setDraggedItems,mixUp,startTesting,stopTesting } = listsSlice.actions; +export type {ListsState} export default listsSlice.reducer; \ No newline at end of file