From 73b4d63024736f67337c36eee78bada1c68fe3d8 Mon Sep 17 00:00:00 2001 From: Shadow Date: Wed, 2 Apr 2025 12:30:55 +0300 Subject: [PATCH 1/2] =?UTF-8?q?=D0=94=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB=D0=B5?= =?UTF-8?q?=D0=BD=D0=BE=20=D0=9C=D0=92=D0=9F=202-=20=D0=B3=D0=BE=20=D0=BE?= =?UTF-8?q?=D0=BF=D1=80=D0=BE=D1=81=D0=BD=D0=B8=D0=BA=D0=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/Questionnaire2.py | 126 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 126 insertions(+) create mode 100644 app/Questionnaire2.py diff --git a/app/Questionnaire2.py b/app/Questionnaire2.py new file mode 100644 index 0000000..d997b21 --- /dev/null +++ b/app/Questionnaire2.py @@ -0,0 +1,126 @@ +import tkinter as tk +from tkinter import messagebox +import tkinter.font as tkFont + +def get_screen_size(): + root.update_idletasks() + screen_width = root.winfo_screenwidth() + screen_height = root.winfo_screenheight() + return screen_width, screen_height + +class Questionnaire: + def __init__(self, master): + self.master = master + master.title("Опрос о зависимости от гаджетов") + + screen_width, screen_height = get_screen_size() + window_width = int(screen_width * 0.75) + window_height = int(screen_height * 0.30) + master.geometry(f"{window_width}x{window_height}") + + + self.questions = [ + "1. Думаешь ли ты в школе о том, что придешь домой и будешь сидеть в социальных сетях (Тикток, Лайк и другие)?", + "2. Легко ли тебе отложить телефон по первой просьбе родителей/ прожить день без социальных сетей?", + "3. Чувствуешь ли ты себя злым, грустным или одиноким, когда не можешь пользоваться телефоном?", + "4. Бывает ли, что у тебя болит голова, глаза, спина или трудности с засыпанием после времени, проведенного за смартфоном?", + "5. Отвлекаешься ли ты на телефон во время учебы?", + "6. Случается ли, что ты играешь в телефон или компьютер дольше, чем планировал?", + "7. Часто ли из-за игр на телефоне (компьютере, планшете) ты забываешь сделать домашнее задание или выполнить обязанности по дому?", + "8. Приходилось ли тебе скрывать от родителей, сколько времени ты провел за игрой в телефон, планшет или компьютер?", + "9. Бывает, что из-за игр в телефоне, планшете или компьютере ты ссоришься с друзьями или родителями?", + "10. Как ты относишься к людям, которые всё своё время проводят за компьютерными играми?" + ] + + self.answers = [None] * len(self.questions) # сохранение ответов + self.scores = [ + {"А": 3, "Б": 2, "В": 1, "Г": 0}, # Баллы (экранная зависимость) + {"А": 3, "Б": 2, "В": 1, "Г": 0}, # Баллы (игровая зависимость) + ] + + self.current_question = 0 + self.create_widgets() + + def create_widgets(self): + self.question_label = tk.Label(self.master, text="", wraplength=550, font=("Arial", 14)) + self.question_label.pack(pady=10) + + self.radio_var = tk.StringVar() # Для хранения выбранного ответа + self.radio_buttons = [] + options = ["А", "Б", "В", "Г"] + for i, option in enumerate(options): + radio_button = tk.Radiobutton(self.master, text=option, variable=self.radio_var, value=option, font=("Arial", 12)) + radio_button.pack(anchor=tk.W, padx=20) + self.radio_buttons.append(radio_button) + + + self.next_button = tk.Button(self.master, text="Следующий вопрос", command=self.next_question, font=("Arial", 12)) + self.next_button.pack(pady=20) + + self.show_question() + + def show_question(self): + if self.current_question < len(self.questions): + self.question_label.config(text=self.questions[self.current_question]) + self.radio_var.set(None) # <--- Очистка значения radio_var + else: + self.calculate_results() + + def next_question(self): + if self.current_question < len(self.questions): # проверка на окончание вопросов + answer = self.radio_var.get() + if not answer: + messagebox.showinfo("Внимание", "Пожалуйста, выберите ответ.") + return + + self.answers[self.current_question] = answer + self.current_question += 1 + self.show_question() + else: + self.calculate_results() + + def calculate_results(self): + screen_score = 0 + game_score = 0 + + # Расчет баллов для вопросов 2-6 (экранная зависимость) + for i in range(2, 7): + answer = self.answers[i-2] + if answer: + screen_score += self.scores[0][answer] + + # Расчет баллов для вопросов 7-11 + for i in range(7, 11): + answer = self.answers[i-2] + if answer: + game_score += self.scores[1][answer] + + # Определение результата + screen_result = self.get_result_text(screen_score, "экранной") + game_result = self.get_result_text(game_score, "игровой") + + messagebox.showinfo("Результаты опроса", + f"Результаты по экранной зависимости: {screen_score} баллов ({screen_result})\n" + f"Результаты по игровой зависимости: {game_score} баллов ({game_result})") + + def get_result_text(self, score, dependency_type): + """Получает текстовое описание результата в зависимости от набранных баллов.""" + if dependency_type == "экранной": + if score >= 9: + return "Высокая зависимость" + elif score >= 5: + return "Средняя зависимость" + else: + return "Низкая зависимость" + elif dependency_type == "игровой": + if score >= 9: + return "Высокая зависимость" + elif score >= 5: + return "Средняя зависимость" + else: + return "Низкая зависимость" + return "Невозможно определить" # на всякий случай + +root = tk.Tk() +questionnaire = Questionnaire(root) +root.mainloop() \ No newline at end of file From af9b769343e3f1b09985e4b494931f0d59c65618 Mon Sep 17 00:00:00 2001 From: Shadow Date: Sun, 13 Apr 2025 22:15:42 +0300 Subject: [PATCH 2/2] =?UTF-8?q?=D0=9E=D0=BF=D1=80=D0=BE=D1=81=D0=BD=D0=B8?= =?UTF-8?q?=D0=BA=202?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 1 + app/Questionnaire2.py | 126 ----------------------------------------- app/crud/survey2.py | 106 ++++++++++++++++++++++++++++++++++ app/main.py | 3 +- app/models/survey2.py | 47 +++++++++++++++ app/router/survey2.py | 46 +++++++++++++++ app/schemas/survey2.py | 71 +++++++++++++++++++++++ 7 files changed, 273 insertions(+), 127 deletions(-) delete mode 100644 app/Questionnaire2.py create mode 100644 app/crud/survey2.py create mode 100644 app/models/survey2.py create mode 100644 app/router/survey2.py create mode 100644 app/schemas/survey2.py diff --git a/.gitignore b/.gitignore index 31af5a6..60ec3ca 100644 --- a/.gitignore +++ b/.gitignore @@ -135,6 +135,7 @@ venv/ ENV/ env.bak/ venv.bak/ +SG/ # Spyder project settings .spyderproject diff --git a/app/Questionnaire2.py b/app/Questionnaire2.py deleted file mode 100644 index d997b21..0000000 --- a/app/Questionnaire2.py +++ /dev/null @@ -1,126 +0,0 @@ -import tkinter as tk -from tkinter import messagebox -import tkinter.font as tkFont - -def get_screen_size(): - root.update_idletasks() - screen_width = root.winfo_screenwidth() - screen_height = root.winfo_screenheight() - return screen_width, screen_height - -class Questionnaire: - def __init__(self, master): - self.master = master - master.title("Опрос о зависимости от гаджетов") - - screen_width, screen_height = get_screen_size() - window_width = int(screen_width * 0.75) - window_height = int(screen_height * 0.30) - master.geometry(f"{window_width}x{window_height}") - - - self.questions = [ - "1. Думаешь ли ты в школе о том, что придешь домой и будешь сидеть в социальных сетях (Тикток, Лайк и другие)?", - "2. Легко ли тебе отложить телефон по первой просьбе родителей/ прожить день без социальных сетей?", - "3. Чувствуешь ли ты себя злым, грустным или одиноким, когда не можешь пользоваться телефоном?", - "4. Бывает ли, что у тебя болит голова, глаза, спина или трудности с засыпанием после времени, проведенного за смартфоном?", - "5. Отвлекаешься ли ты на телефон во время учебы?", - "6. Случается ли, что ты играешь в телефон или компьютер дольше, чем планировал?", - "7. Часто ли из-за игр на телефоне (компьютере, планшете) ты забываешь сделать домашнее задание или выполнить обязанности по дому?", - "8. Приходилось ли тебе скрывать от родителей, сколько времени ты провел за игрой в телефон, планшет или компьютер?", - "9. Бывает, что из-за игр в телефоне, планшете или компьютере ты ссоришься с друзьями или родителями?", - "10. Как ты относишься к людям, которые всё своё время проводят за компьютерными играми?" - ] - - self.answers = [None] * len(self.questions) # сохранение ответов - self.scores = [ - {"А": 3, "Б": 2, "В": 1, "Г": 0}, # Баллы (экранная зависимость) - {"А": 3, "Б": 2, "В": 1, "Г": 0}, # Баллы (игровая зависимость) - ] - - self.current_question = 0 - self.create_widgets() - - def create_widgets(self): - self.question_label = tk.Label(self.master, text="", wraplength=550, font=("Arial", 14)) - self.question_label.pack(pady=10) - - self.radio_var = tk.StringVar() # Для хранения выбранного ответа - self.radio_buttons = [] - options = ["А", "Б", "В", "Г"] - for i, option in enumerate(options): - radio_button = tk.Radiobutton(self.master, text=option, variable=self.radio_var, value=option, font=("Arial", 12)) - radio_button.pack(anchor=tk.W, padx=20) - self.radio_buttons.append(radio_button) - - - self.next_button = tk.Button(self.master, text="Следующий вопрос", command=self.next_question, font=("Arial", 12)) - self.next_button.pack(pady=20) - - self.show_question() - - def show_question(self): - if self.current_question < len(self.questions): - self.question_label.config(text=self.questions[self.current_question]) - self.radio_var.set(None) # <--- Очистка значения radio_var - else: - self.calculate_results() - - def next_question(self): - if self.current_question < len(self.questions): # проверка на окончание вопросов - answer = self.radio_var.get() - if not answer: - messagebox.showinfo("Внимание", "Пожалуйста, выберите ответ.") - return - - self.answers[self.current_question] = answer - self.current_question += 1 - self.show_question() - else: - self.calculate_results() - - def calculate_results(self): - screen_score = 0 - game_score = 0 - - # Расчет баллов для вопросов 2-6 (экранная зависимость) - for i in range(2, 7): - answer = self.answers[i-2] - if answer: - screen_score += self.scores[0][answer] - - # Расчет баллов для вопросов 7-11 - for i in range(7, 11): - answer = self.answers[i-2] - if answer: - game_score += self.scores[1][answer] - - # Определение результата - screen_result = self.get_result_text(screen_score, "экранной") - game_result = self.get_result_text(game_score, "игровой") - - messagebox.showinfo("Результаты опроса", - f"Результаты по экранной зависимости: {screen_score} баллов ({screen_result})\n" - f"Результаты по игровой зависимости: {game_score} баллов ({game_result})") - - def get_result_text(self, score, dependency_type): - """Получает текстовое описание результата в зависимости от набранных баллов.""" - if dependency_type == "экранной": - if score >= 9: - return "Высокая зависимость" - elif score >= 5: - return "Средняя зависимость" - else: - return "Низкая зависимость" - elif dependency_type == "игровой": - if score >= 9: - return "Высокая зависимость" - elif score >= 5: - return "Средняя зависимость" - else: - return "Низкая зависимость" - return "Невозможно определить" # на всякий случай - -root = tk.Tk() -questionnaire = Questionnaire(root) -root.mainloop() \ No newline at end of file diff --git a/app/crud/survey2.py b/app/crud/survey2.py new file mode 100644 index 0000000..ab80c69 --- /dev/null +++ b/app/crud/survey2.py @@ -0,0 +1,106 @@ +from sqlalchemy.orm import Session +from app.models.survey2 import Survey, Question, Option, UserResponse + +def get_survey(db: Session, survey_id: int): + return db.query(Survey).filter(Survey.id == survey_id).first() + +def get_active_survey(db: Session): + return db.query(Survey).filter(Survey.is_active == True).first() + +def create_survey(db: Session, survey_data): + db_survey = Survey( + title=survey_data.title, + description=survey_data.description, + is_active=survey_data.is_active + ) + db.add(db_survey) + db.commit() + db.refresh(db_survey) + + for question_data in survey_data.questions: + db_question = Question( + text=question_data.text, + question_type=question_data.question_type, + survey_id=db_survey.id + ) + db.add(db_question) + db.commit() + db.refresh(db_question) + + for option_data in question_data.options: + db_option = Option( + text=option_data.text, + score=option_data.score, + question_id=db_question.id + ) + db.add(db_option) + + db.commit() + db.refresh(db_survey) + return db_survey + +def save_response(db: Session, response_data): + db_response = UserResponse(**response_data.dict()) + db.add(db_response) + db.commit() + db.refresh(db_response) + return db_response + +def calculate_results(db: Session, user_id: str, survey_id: int): + responses = db.query(UserResponse).filter( + UserResponse.user_id == user_id, + UserResponse.survey_id == survey_id + ).all() + + if not responses: + return None + + # Вопросы для экранной зависимости (2-6) + screen_questions = {2, 3, 4, 5, 6} + # Вопросы для игровой зависимости (7-11) + game_questions = {7, 8, 9, 10, 11} + + screen_score = 0 + game_score = 0 + + for response in responses: + option = db.query(Option).filter(Option.id == response.option_id).first() + if response.question_id in screen_questions: + screen_score += option.score + elif response.question_id in game_questions: + game_score += option.score + + # Определение уровней зависимости + def get_dependency_level(score, dependency_type): + if score >= 11: + level = "высокий уровень риска" + if dependency_type == "screen": + desc = "Ребенок зависим от гаджета, возможны нарушения сна и успеваемости" + else: + desc = "Ребенок зависим от игр, возможны проблемы с учебой и общением" + elif 6 <= score <= 10: + level = "средний уровень риска" + if dependency_type == "screen": + desc = "Регулярное, но не чрезмерное использование устройств" + else: + desc = "Чрезмерное увлечение играми с небольшим влиянием на учебу" + else: + level = "низкий уровень риска" + if dependency_type == "screen": + desc = "Умеренное использование гаджетов без нарушений" + else: + desc = "Контролируемое использование игр, хороший баланс" + + return level, desc + + screen_level, screen_desc = get_dependency_level(screen_score, "screen") + game_level, game_desc = get_dependency_level(game_score, "game") + + return { + "screen_dependency_score": screen_score, + "game_dependency_score": game_score, + "screen_dependency_level": screen_level, + "game_dependency_level": game_level, + "screen_dependency_description": screen_desc, + "game_dependency_description": game_desc + } \ No newline at end of file diff --git a/app/main.py b/app/main.py index 238b98b..3804410 100644 --- a/app/main.py +++ b/app/main.py @@ -1,7 +1,7 @@ from fastapi import FastAPI from app.config import get_settings -from app.router import geo, session +from app.router import geo, session, survey2 from app.database import Base, engine settings = get_settings() @@ -10,6 +10,7 @@ app.include_router(geo.router, prefix="/geo", tags=["Geo"]) app.include_router(session.router, prefix="/session", tags=["Session"]) +app.include_router(survey2.router) @app.get("/") async def root(): diff --git a/app/models/survey2.py b/app/models/survey2.py new file mode 100644 index 0000000..19a56b6 --- /dev/null +++ b/app/models/survey2.py @@ -0,0 +1,47 @@ +from sqlalchemy import Column, Integer, String, ForeignKey, Boolean, DateTime +from sqlalchemy.orm import relationship +from datetime import datetime +from app.database import Base + +class Survey(Base): #Опрос + __tablename__ = "surve2" + + id = Column(Integer, primary_key=True, index=True) + title = Column(String, nullable=False) + description = Column(String) + is_active = Column(Boolean, default=True) + created_at = Column(DateTime, default=datetime.utcnow) + + questions = relationship("Question", back_populates="survey", cascade="all, delete-orphan") + +class Question(Base):#Вопрос + __tablename__ = "questions" + + id = Column(Integer, primary_key=True, index=True) + text = Column(String, nullable=False) + survey_id = Column(Integer, ForeignKey("surve2.id")) + + survey = relationship("Survey", back_populates="questions") + options = relationship("Option", back_populates="question", cascade="all, delete-orphan") + +class Option(Base): # Ответ + __tablename__ = "options" + + id = Column(Integer, primary_key=True, index=True) + text = Column(String, nullable=False) + score = Column(Integer, nullable=False) # Баллы за вариант ответа + question_id = Column(Integer, ForeignKey("questions.id")) + + question = relationship("Question", back_populates="options") + +class UserResponse(Base):# Результаты + __tablename__ = "user_responses" + + id = Column(Integer, primary_key=True, index=True) + question_id = Column(Integer, ForeignKey("questions.id")) + option_id = Column(Integer, ForeignKey("options.id")) + survey_id = Column(Integer, ForeignKey("surve2.id")) + + question = relationship("Question") + option = relationship("Option") + survey = relationship("Survey") \ No newline at end of file diff --git a/app/router/survey2.py b/app/router/survey2.py new file mode 100644 index 0000000..3ef89c2 --- /dev/null +++ b/app/router/survey2.py @@ -0,0 +1,46 @@ +from fastapi import APIRouter, Depends, HTTPException +from sqlalchemy.orm import Session +from typing import List +from app.logger import get_logger + +from app.database import get_db +from app.schemas.survey2 import ( + Survey, SurveyCreate, SurveyResult, + Response, ResponseCreate +) +from app.crud.survey2 import ( + get_survey, get_active_survey, + create_survey, save_response, + calculate_results +) + +router = APIRouter(prefix="/surveys", tags=["Surveys"]) +logger = get_logger() + +@router.get("/active", response_model=Survey) +def get_active_survey_endpoint(db: Session = Depends(get_db)): + survey = get_active_survey(db) + if not survey: + raise HTTPException(status_code=404, detail="No active survey found") + return survey + +@router.post("/responses", response_model=Response) +def create_response( + response: ResponseCreate, + db: Session = Depends(get_db) +): + return save_response(db, response) + +@router.get("/results/{user_id}", response_model=SurveyResult) +def get_survey_results( + user_id: str, + db: Session = Depends(get_db) +): + survey = get_active_survey(db) + if not survey: + raise HTTPException(status_code=404, detail="No active survey found") + + results = calculate_results(db, user_id=user_id, survey_id=survey.id) + if not results: + raise HTTPException(status_code=404, detail="Responses not found") + return results \ No newline at end of file diff --git a/app/schemas/survey2.py b/app/schemas/survey2.py new file mode 100644 index 0000000..a6613bb --- /dev/null +++ b/app/schemas/survey2.py @@ -0,0 +1,71 @@ +from pydantic import BaseModel +from typing import List, Optional +from datetime import datetime + +class OptionBase(BaseModel): + text: str + score: int + +class OptionCreate(OptionBase): + pass + +class Option(OptionBase): + id: int + question_id: int + + class Config: + from_attributes = True + +class QuestionBase(BaseModel): + text: str + +class QuestionCreate(QuestionBase): + options: List[OptionCreate] = [] + +class Question(QuestionBase): + id: int + survey_id: int + options: List[Option] = [] + + class Config: + from_attributes = True + +class SurveyBase(BaseModel): + title: str + description: Optional[str] = None + is_active: Optional[bool] = True + +class SurveyCreate(SurveyBase): + questions: List[QuestionCreate] = [] + +class Survey(SurveyBase): + id: int + created_at: datetime + questions: List[Question] = [] + + class Config: + from_attributes = True + +class ResponseBase(BaseModel): + user_id: str + question_id: int + option_id: int + survey_id: int + +class ResponseCreate(ResponseBase): + pass + +class Response(ResponseBase): + id: int + created_at: datetime + + class Config: + from_attributes = True + +class SurveyResult(BaseModel): + screen_dependency_score: int + game_dependency_score: int + screen_dependency_level: str + game_dependency_level: str + screen_dependency_description: str + game_dependency_description: str \ No newline at end of file