hide ai
All checks were successful
Deploy / CreateImage (push) Successful in 5m20s
Deploy / DeployService (push) Successful in 19s

This commit is contained in:
Nastya 2025-04-22 22:29:34 +03:00
parent 4190ae767e
commit dc3c790b63
8 changed files with 81 additions and 30 deletions

@ -71,7 +71,7 @@ export const publicationMakeRequest = ({ url, body }: PublicationMakeRequestPara
method: "POST", method: "POST",
}); });
}; };
let page = 0;
export async function getData(quizId: string): Promise<{ export async function getData(quizId: string): Promise<{
data: GetQuizDataResponse | null; data: GetQuizDataResponse | null;
isRecentlyCompleted: boolean; isRecentlyCompleted: boolean;
@ -92,12 +92,13 @@ export async function getData(quizId: string): Promise<{
}, },
data: { data: {
quiz_id: quizId, quiz_id: quizId,
limit: 100, limit: 1,
page: 0, page,
need_config: true, need_config: page === 0,
}, },
} }
); );
page++;
const sessions = JSON.parse(localStorage.getItem("sessions") || "{}"); const sessions = JSON.parse(localStorage.getItem("sessions") || "{}");
//Тут ещё проверка на антифрод без парса конфига. Нам не интересно время если не нужно запрещать проходить чаще чем в сутки //Тут ещё проверка на антифрод без парса конфига. Нам не интересно время если не нужно запрещать проходить чаще чем в сутки
@ -118,28 +119,58 @@ export async function getData(quizId: string): Promise<{
} }
} }
export async function getQuizData(quizId: string) { export async function getQuizData(quizId: string, maxRetries = 3): Promise<QuizSettings> {
if (!quizId) throw new Error("No quiz id"); if (!quizId) throw new Error("No quiz id");
const response = await getData(quizId); let retryCount = 0;
const quizDataResponse = response.data; let lastError: Error | null = null;
if (response.error) { while (retryCount < maxRetries) {
throw response.error; try {
} const response = await getData(quizId);
if (!quizDataResponse) { const quizDataResponse = response.data;
throw new Error("Quiz not found");
if (response.error) {
throw response.error;
}
if (!quizDataResponse) {
throw new Error("Quiz not found");
}
// Проверка на AI result
const hasAiResult = quizDataResponse.items.some(
(item) => item.typ === "result" && quizDataResponse.settings.status === "ai"
);
if (hasAiResult && retryCount < maxRetries - 1) {
retryCount++;
continue; // Повторяем запрос
}
const quizSettings = replaceSpacesToEmptyLines(parseQuizData(quizDataResponse));
const res = JSON.parse(
JSON.stringify({ data: quizSettings })
.replaceAll(/\\" \\"/g, '""')
.replaceAll(/" "/g, '""')
).data as QuizSettings;
res.recentlyCompleted = response.isRecentlyCompleted;
return res;
} catch (error) {
lastError = error as Error;
retryCount++;
if (retryCount >= maxRetries) {
break;
}
// Добавляем небольшую задержку перед повторным запросом
await new Promise((resolve) => setTimeout(resolve, 1000 * retryCount));
}
} }
const quizSettings = replaceSpacesToEmptyLines(parseQuizData(quizDataResponse)); throw lastError || new Error("Failed to get quiz data after retries");
const res = JSON.parse(
JSON.stringify({ data: quizSettings })
.replaceAll(/\\" \\"/g, '""')
.replaceAll(/" "/g, '""')
).data as QuizSettings;
res.recentlyCompleted = response.isRecentlyCompleted;
return res;
} }
type SendAnswerProps = { type SendAnswerProps = {

@ -77,12 +77,12 @@ function QuizAnswererInner({
if (error) return <ApologyPage error={error} />; if (error) return <ApologyPage error={error} />;
// if (!data) return <LoadingSkeleton />; // if (!data) return <LoadingSkeleton />;
quizSettings ??= data; quizSettings ??= data;
if (!quizSettings) return <ApologyPage error={new Error("Quiz data is null")} />; if (!quizSettings) return <ApologyPage error={new Error("quiz data is null")} />;
if (quizSettings.questions.length === 1 && quizSettings?.settings.cfg.noStartPage) if (quizSettings.questions.length === 1 && quizSettings?.settings.cfg.noStartPage)
return <ApologyPage error={new Error("Quiz is empty")} />; return <ApologyPage error={new Error("quiz is empty")} />;
// if (quizSettings.questions.length === 1) return <ApologyPage error={new Error("No questions found")} />; // if (quizSettings.questions.length === 1) return <ApologyPage error={new Error("no questions found")} />;
if (!quizId) return <ApologyPage error={new Error("No quiz id")} />; if (!quizId) return <ApologyPage error={new Error("no quiz id")} />;
const quizContainer = ( const quizContainer = (
<Box <Box

@ -38,7 +38,7 @@ export const Footer = ({ stepNumber, nextButton, prevButton }: FooterProps) => {
gap: "10px", gap: "10px",
}} }}
> >
{stepNumber !== null && ( {stepNumber !== null && settings.status !== "ai" && (
<Box sx={{ flexGrow: 1 }}> <Box sx={{ flexGrow: 1 }}>
<Typography sx={{ color: theme.palette.text.primary }}> <Typography sx={{ color: theme.palette.text.primary }}>
Вопрос {stepNumber} из {questionsAmount} Вопрос {stepNumber} из {questionsAmount}

@ -106,7 +106,7 @@ export default function ViewPublicationPage() {
} }
nextButton={ nextButton={
<NextButton <NextButton
isNextButtonEnabled={isNextButtonEnabled} isNextButtonEnabled={settings.status === "ai" || isNextButtonEnabled}
moveToNextQuestion={() => { moveToNextQuestion={() => {
moveToNextQuestion(); moveToNextQuestion();

@ -1,5 +1,6 @@
import { QuizSettings } from "@model/settingsData"; import { QuizSettings } from "@model/settingsData";
import { createContext, useContext } from "react"; import { createContext, useContext } from "react";
import { AnyTypedQuizQuestion } from "..";
export const QuizSettingsContext = createContext< export const QuizSettingsContext = createContext<
| (QuizSettings & { | (QuizSettings & {

@ -12,6 +12,7 @@ export interface GetQuizDataResponse {
due: number; due: number;
delay: number; delay: number;
pausable: boolean; pausable: boolean;
status: "start" | "stop" | "ai";
}; };
items: { items: {
id: number; id: number;
@ -49,6 +50,7 @@ export function parseQuizData(quizDataResponse: GetQuizDataResponse): Omit<QuizS
due: quizDataResponse.settings.due, due: quizDataResponse.settings.due,
delay: quizDataResponse.settings.delay, delay: quizDataResponse.settings.delay,
pausable: quizDataResponse.settings.pausable, pausable: quizDataResponse.settings.pausable,
status: quizDataResponse.settings.status,
}; };
return { cnt: quizDataResponse.cnt, settings, questions: items, show_badge: quizDataResponse.show_badge }; return { cnt: quizDataResponse.cnt, settings, questions: items, show_badge: quizDataResponse.show_badge };

@ -51,6 +51,7 @@ export type QuizSettingsConfig = {
delay: number; delay: number;
pausable: boolean; pausable: boolean;
cfg: QuizConfig; cfg: QuizConfig;
status: "start" | "stop" | "ai";
}; };
export type QuizSettings = { export type QuizSettings = {

@ -9,10 +9,20 @@ import { useQuizViewStore } from "@stores/quizView";
import { useVkMetricsGoals } from "@/utils/hooks/metrics/useVkMetricsGoals"; import { useVkMetricsGoals } from "@/utils/hooks/metrics/useVkMetricsGoals";
import { useYandexMetricsGoals } from "@/utils/hooks/metrics/useYandexMetricsGoals"; import { useYandexMetricsGoals } from "@/utils/hooks/metrics/useYandexMetricsGoals";
import { AnyTypedQuizQuestion } from "@/index";
import { getQuizData } from "@/api/quizRelase";
let isgetting = false;
export function useQuestionFlowControl() { export function useQuestionFlowControl() {
//Получаем инфо о квизе и список вопросов. //Получаем инфо о квизе и список вопросов.
const { settings, questions } = useQuizSettings(); const { settings, questions: initialQuestions, quizId } = useQuizSettings();
const [questions, setQuestions] = useState(initialQuestions);
const addQuestion = (question: AnyTypedQuizQuestion) => {
setQuestions((prev) => [...prev, question]);
};
//Когда квиз линейный, не ветвящийся, мы идём по вопросам по их порядковому номеру. Это их page. //Когда квиз линейный, не ветвящийся, мы идём по вопросам по их порядковому номеру. Это их page.
//За корректность page отвечает конструктор квизов. Интересный факт, если в конструкторе удалить из середины вопрос, то случится куча запросов изменения вопросов с изменением этого page //За корректность page отвечает конструктор квизов. Интересный факт, если в конструкторе удалить из середины вопрос, то случится куча запросов изменения вопросов с изменением этого page
const sortedQuestions = useMemo(() => { const sortedQuestions = useMemo(() => {
@ -200,7 +210,12 @@ export function useQuestionFlowControl() {
}, [prevQuestion]); }, [prevQuestion]);
//рычаг управления из визуала в эту функцию //рычаг управления из визуала в эту функцию
const moveToNextQuestion = useCallback(() => { const moveToNextQuestion = useCallback(async () => {
if (isgetting) return;
isgetting = true;
const data = await getQuizData(quizId);
addQuestion(data.questions[0]);
isgetting = false;
if (!nextQuestion) throw new Error("Next question not found"); if (!nextQuestion) throw new Error("Next question not found");
// Засчитываем переход с вопроса дальше // Засчитываем переход с вопроса дальше
@ -246,7 +261,8 @@ export function useQuestionFlowControl() {
return { return {
currentQuestion, currentQuestion,
currentQuestionStepNumber: linearQuestionIndex === null ? null : linearQuestionIndex + 1, currentQuestionStepNumber:
settings.status === "ai" ? null : linearQuestionIndex === null ? null : linearQuestionIndex + 1,
nextQuestion, nextQuestion,
isNextButtonEnabled, isNextButtonEnabled,
isPreviousButtonEnabled, isPreviousButtonEnabled,