From 1f2880f719b12c776a80e2cee445c068ab1f50c6 Mon Sep 17 00:00:00 2001 From: Nastya Date: Tue, 22 Apr 2025 22:29:34 +0300 Subject: [PATCH] hide ai --- lib/api/quizRelase.ts | 89 +++++++++++++++---- lib/components/QuizAnswerer.tsx | 8 +- lib/components/ViewPublicationPage/Footer.tsx | 2 +- .../ViewPublicationPage.tsx | 2 +- lib/contexts/QuizDataContext.ts | 1 + lib/model/api/getQuizData.ts | 2 + lib/model/settingsData.ts | 1 + lib/utils/hooks/useQuestionFlowControl.ts | 22 ++++- 8 files changed, 103 insertions(+), 24 deletions(-) diff --git a/lib/api/quizRelase.ts b/lib/api/quizRelase.ts index e8ba0ca..de0e77e 100644 --- a/lib/api/quizRelase.ts +++ b/lib/api/quizRelase.ts @@ -71,7 +71,7 @@ export const publicationMakeRequest = ({ url, body }: PublicationMakeRequestPara method: "POST", }); }; - +let page = 0; export async function getData(quizId: string): Promise<{ data: GetQuizDataResponse | null; isRecentlyCompleted: boolean; @@ -92,16 +92,18 @@ export async function getData(quizId: string): Promise<{ }, data: { quiz_id: quizId, - limit: 100, - page: 0, - need_config: true, + limit: 1, + page, + need_config: page === 0, }, } ); + console.log(data); + if (data.items.length) page++; const sessions = JSON.parse(localStorage.getItem("sessions") || "{}"); //Тут ещё проверка на антифрод без парса конфига. Нам не интересно время если не нужно запрещать проходить чаще чем в сутки - if (typeof sessions[quizId] === "number" && data.settings.cfg.includes('antifraud":true')) { + if (!page && typeof sessions[quizId] === "number" && data.settings.cfg.includes('antifraud":true')) { // unix время. Если меньше суток прошло - выводить ошибку, иначе пустить дальше if (Date.now() - sessions[quizId] < 86400000) { return { data, isRecentlyCompleted: true }; @@ -118,27 +120,84 @@ export async function getData(quizId: string): Promise<{ } } -export async function getQuizData(quizId: string) { +export async function getQuizData(quizId: string, status?: string): Promise { + let maxRetries = 50; if (!quizId) throw new Error("No quiz id"); - const response = await getData(quizId); - const quizDataResponse = response.data; + let lastError: Error | null = null; + let responseData: any = null; - if (response.error) { - throw response.error; - } - if (!quizDataResponse) { - throw new Error("Quiz not found"); + // Первый цикл - обработка result вопросов с увеличением page + let resultRetryCount = 0; + while (resultRetryCount < maxRetries) { + try { + const response = await getData(quizId); + console.log("ф-я аналитики", response); + + if (response.error) throw response.error; + if (!response.data) throw new Error("Quiz not found"); + + const hasAiResult = response.data.items.some((item) => item.typ === "result" && status === "ai"); + + if (hasAiResult) { + page++; // Увеличиваем страницу + resultRetryCount++; + continue; + } + + // Если result вопросов нет, сохраняем данные для второго цикла + responseData = response; + break; + } catch (error) { + lastError = error as Error; + resultRetryCount++; + if (resultRetryCount >= maxRetries) break; + await new Promise((resolve) => setTimeout(resolve, 1000 * resultRetryCount)); + } } - const quizSettings = replaceSpacesToEmptyLines(parseQuizData(quizDataResponse)); + if (!responseData) { + throw lastError || new Error("Failed to get quiz data after result retries"); + } + + // Второй цикл - обработка пустого массива items (без изменения page) + let isEmpty = !responseData.data?.items.length; + let emptyRetryCount = 0; + while (isEmpty && emptyRetryCount < maxRetries) { + try { + await new Promise((resolve) => setTimeout(resolve, 1000)); + const response = await getData(quizId); + + if (response.error) throw response.error; + if (!response.data) throw new Error("Quiz not found"); + + isEmpty = !response.data.items.length; + if (!isEmpty) { + responseData = response; // Обновляем данные + } + emptyRetryCount++; + } catch (error) { + lastError = error as Error; + emptyRetryCount++; + if (emptyRetryCount >= maxRetries) break; + } + } + + if (isEmpty) { + throw new Error("Items array is empty after maximum retries"); + } + + // Финальная обработка успешного ответа + const quizSettings = replaceSpacesToEmptyLines(parseQuizData(responseData.data)); const res = JSON.parse( JSON.stringify({ data: quizSettings }) .replaceAll(/\\" \\"/g, '""') .replaceAll(/" "/g, '""') ).data as QuizSettings; - res.recentlyCompleted = response.isRecentlyCompleted; + + res.recentlyCompleted = responseData.isRecentlyCompleted; + return res; } diff --git a/lib/components/QuizAnswerer.tsx b/lib/components/QuizAnswerer.tsx index 451a1b3..c733d39 100644 --- a/lib/components/QuizAnswerer.tsx +++ b/lib/components/QuizAnswerer.tsx @@ -77,12 +77,12 @@ function QuizAnswererInner({ if (error) return ; // if (!data) return ; quizSettings ??= data; - if (!quizSettings) return ; + if (!quizSettings) return ; if (quizSettings.questions.length === 1 && quizSettings?.settings.cfg.noStartPage) - return ; - // if (quizSettings.questions.length === 1) return ; - if (!quizId) return ; + return ; + // if (quizSettings.questions.length === 1) return ; + if (!quizId) return ; const quizContainer = ( { gap: "10px", }} > - {stepNumber !== null && ( + {stepNumber !== null && settings.status !== "ai" && ( Вопрос {stepNumber} из {questionsAmount} diff --git a/lib/components/ViewPublicationPage/ViewPublicationPage.tsx b/lib/components/ViewPublicationPage/ViewPublicationPage.tsx index 6d71ce7..bfa819a 100644 --- a/lib/components/ViewPublicationPage/ViewPublicationPage.tsx +++ b/lib/components/ViewPublicationPage/ViewPublicationPage.tsx @@ -106,7 +106,7 @@ export default function ViewPublicationPage() { } nextButton={ { moveToNextQuestion(); diff --git a/lib/contexts/QuizDataContext.ts b/lib/contexts/QuizDataContext.ts index 95d39fe..a2c3261 100644 --- a/lib/contexts/QuizDataContext.ts +++ b/lib/contexts/QuizDataContext.ts @@ -1,5 +1,6 @@ import { QuizSettings } from "@model/settingsData"; import { createContext, useContext } from "react"; +import { AnyTypedQuizQuestion } from ".."; export const QuizSettingsContext = createContext< | (QuizSettings & { diff --git a/lib/model/api/getQuizData.ts b/lib/model/api/getQuizData.ts index 21f685c..384ef1b 100644 --- a/lib/model/api/getQuizData.ts +++ b/lib/model/api/getQuizData.ts @@ -12,6 +12,7 @@ export interface GetQuizDataResponse { due: number; delay: number; pausable: boolean; + status: "start" | "stop" | "ai"; }; items: { id: number; @@ -49,6 +50,7 @@ export function parseQuizData(quizDataResponse: GetQuizDataResponse): Omit { + setQuestions((prev) => [...prev, question]); + }; + //Когда квиз линейный, не ветвящийся, мы идём по вопросам по их порядковому номеру. Это их page. //За корректность page отвечает конструктор квизов. Интересный факт, если в конструкторе удалить из середины вопрос, то случится куча запросов изменения вопросов с изменением этого page const sortedQuestions = useMemo(() => { @@ -200,7 +210,12 @@ export function useQuestionFlowControl() { }, [prevQuestion]); //рычаг управления из визуала в эту функцию - const moveToNextQuestion = useCallback(() => { + const moveToNextQuestion = useCallback(async () => { + if (isgetting) return; + isgetting = true; + const data = await getQuizData(quizId, settings.status); + addQuestion(data.questions[0]); + isgetting = false; if (!nextQuestion) throw new Error("Next question not found"); // Засчитываем переход с вопроса дальше @@ -246,7 +261,8 @@ export function useQuestionFlowControl() { return { currentQuestion, - currentQuestionStepNumber: linearQuestionIndex === null ? null : linearQuestionIndex + 1, + currentQuestionStepNumber: + settings.status === "ai" ? null : linearQuestionIndex === null ? null : linearQuestionIndex + 1, nextQuestion, isNextButtonEnabled, isPreviousButtonEnabled,