From ded552f69820697c8a68b7eba3a9b30763511a87 Mon Sep 17 00:00:00 2001 From: Fuchs0101 Date: Mon, 2 Dec 2024 21:14:09 +0900 Subject: [PATCH 01/51] setup development environment with Docker Compose --- backend/Dockerfile | 9 ++++++++ backend/requirements.txt | 3 +++ compose.yml | 45 ++++++++++++++++++++++++++++++++++++++++ frontend/Dockerfile | 8 +++++++ frontend/package.json | 3 +++ 5 files changed, 68 insertions(+) create mode 100644 backend/Dockerfile create mode 100644 backend/requirements.txt create mode 100644 compose.yml create mode 100644 frontend/Dockerfile create mode 100644 frontend/package.json diff --git a/backend/Dockerfile b/backend/Dockerfile new file mode 100644 index 0000000..fb25ab0 --- /dev/null +++ b/backend/Dockerfile @@ -0,0 +1,9 @@ +FROM python:3.10 + +WORKDIR /app + +COPY requirements.txt ./ +RUN pip install --no-cache-dir -r requirements.txt + +COPY . . + diff --git a/backend/requirements.txt b/backend/requirements.txt new file mode 100644 index 0000000..a23a866 --- /dev/null +++ b/backend/requirements.txt @@ -0,0 +1,3 @@ +Flask==2.2.5 +boto3==1.26.145 +gunicorn==20.1.0 \ No newline at end of file diff --git a/compose.yml b/compose.yml new file mode 100644 index 0000000..17fdc1b --- /dev/null +++ b/compose.yml @@ -0,0 +1,45 @@ +services: + frontend: + build: ./frontend + container_name: frontend + ports: + - "3000:3000" + volumes: + - ./frontend:/app + environment: + - NODE_ENV=development + + backend: + build: ./backend + container_name: backend + ports: + - "5000:5000" + volumes: + - ./backend:/app + environment: + - FLASK_ENV=development + + dynamodb: + image: amazon/dynamodb-local + container_name: dynamodb + ports: + - "8000:8000" + volumes: + - dynamodb_data:/home/dynamodblocal/data + + minio: + image: minio/minio + container_name: minio + ports: + - "9000:9000" + - "9001:9001" + environment: + - MINIO_ROOT_USER=miniominio + - MINIO_ROOT_PASSWORD=miniominio + command: server --console-address ":9001" /data + volumes: + - minio_data:/data + +volumes: + dynamodb_data: + minio_data: \ No newline at end of file diff --git a/frontend/Dockerfile b/frontend/Dockerfile new file mode 100644 index 0000000..223797c --- /dev/null +++ b/frontend/Dockerfile @@ -0,0 +1,8 @@ +FROM node:18 + +WORKDIR /app + +COPY package*.json ./ +RUN npm install + +COPY . . diff --git a/frontend/package.json b/frontend/package.json new file mode 100644 index 0000000..544b7b4 --- /dev/null +++ b/frontend/package.json @@ -0,0 +1,3 @@ +{ + +} \ No newline at end of file From e0d2c4541f2eca5eff0257f811de004acd6ff2a2 Mon Sep 17 00:00:00 2001 From: Sairon <138011409+Yukkurisiteikitai@users.noreply.github.com> Date: Tue, 3 Dec 2024 15:26:39 +0900 Subject: [PATCH 02/51] refactor/display-Set --- frontend/game.js | 188 ++++++++++++++++++++++++++++++++++++++++++++ frontend/index.html | 51 ++++++++++++ frontend/style.css | 60 ++++++++++++++ 3 files changed, 299 insertions(+) create mode 100644 frontend/game.js create mode 100644 frontend/index.html create mode 100644 frontend/style.css diff --git a/frontend/game.js b/frontend/game.js new file mode 100644 index 0000000..2801f3b --- /dev/null +++ b/frontend/game.js @@ -0,0 +1,188 @@ +document.addEventListener("DOMContentLoaded", () => { + const homeScreen = document.getElementById("home"); + const quizScreen = document.getElementById("quiz"); + const resultScreen = document.getElementById("result"); + const menuScreen = document.getElementById("menu"); + + const startButton = document.getElementById("start-button"); + const createButton = document.getElementById("create-button"); + const playButton = document.getElementById("play-button"); + + const options = document.querySelectorAll(".selects"); + const nextButton = document.querySelector(".next-button"); + const quitButton = document.querySelector(".quit-button"); + + + + const statusText = document.querySelector(".status"); + const answerText = document.querySelector(".answer"); + + // クイズデータ + + + questions = [ + { + "question": "halejfalwjfwfioa", + "options": [ + "hewaj;foewifj;w", + "jfoiea;jfiwfo", + "hoieajf;fjwf", + "hioefj;aefiofe" + ], + "answer": "hfeafjaweo;fiw" + }, + { + "question": "別の質問例", + "options": ["選択肢1", "選択肢2", "選択肢3", "選択肢4"], + "answer": "正解" + } + ] + + function reqListener(){ + console.log(this.responseText); + } + + function LoadRequest(){ + console.log("hello"); + + const req = new XMLHttpRequest(); + // req.addEventListener("load",reqListener); + req.open("GET","http://127.0.0.1:2342/info/2") + // req.send(); + req.responseType = "json"; + req.onload = () => { + if(req.readyState == 4 && req.status == 200){ + const date = req.response; + console.log(date); + return date; + }else{ + console.log(`Error: ${req.status}`); + } + }; + return "Not Found"; + } + + + question = {} + + fetch('http://127.0.0.1:2342/info/2') + .then(res => res.json()) + .then(data => { + console.log(data[0]); + const question = data[0]; + const d = document.createElement('h1'); + d.innerText=question["questiondate"]; + document.body.appendChild(d) + }) + + +displayLoadRequest + //display + function displayLoadRequest(display) + { + /** + * That option discplayis + * @param display (string)第1引数のコメント + * [home],["quiz"],["menu"],["result"] + */ + quizScreen.classList.add("d-none"); + resultScreen.classList.add("d-none"); + menuScreen.classList.add("d-none"); + homeScreen.classList.add("d-none"); + if (display == "home") + { + homeScreen.classList.remove("d-none"); + } + else if (display == "quiz") + { + quizScreen.classList.remove("d-none"); + } + else if (display == "menu") + { + menuScreen.classList.remove("d-none"); + } + else if (display == "result") + { + resultScreen.classList.remove("d-none"); + } + } + + // 正解データ + const correctAnswer = "スイッチ"; + + // クイズ開始 + startButton.addEventListener("click", () => { + /* + homeScreen.classList.add("d-none"); + quizScreen.classList.remove("d-none"); + */ + displayLoadRequest("menu"); + }); + + + + // 回答選択 + options.forEach(option => { + option.addEventListener("click", (event) => { + const selectedAnswer = event.target.textContent; + + // 判定処理 + if (selectedAnswer === correctAnswer) + { + statusText.textContent = "正解"; + statusText.style.color = "#28a745"; + } + else + { + statusText.textContent = "不正解"; + statusText.style.color = "#dc3545"; + } + + answerText.textContent = correctAnswer; // 正解を表示 + + // 結果画面へ移動 + quizScreen.classList.add("d-none"); + resultScreen.classList.remove("d-none"); + }); + }); + + + function ScreenSet(switch_screen,screen) + { + console.log(screen,switch_screen); + if(switch_screen == true) + { + + screen.classList.remove("d-none"); + } + else if(switch_screen == false) + { + screen.classList.add("d-none"); + } + else + { + console.error("ScreenDon't set switch_screen"); + } + console.log(screen,switch_screen); + + } + + // 次の問題へ(ここでは単純にホーム画面に戻る処理) + nextButton.addEventListener("click", () => { + // resultScreen.classList.add("d-none"); + // menuScreen.classList.add("d-none"); + // homeScreen.classList.remove("d-none"); + ScreenSet(false,resultScreen); + ScreenSet(false,menuScreen); + ScreenSet(true,homeScreen); + }); + + // やめる(ホーム画面に戻る) + quitButton.addEventListener("click", () => { + resultScreen.classList.add("d-none"); + homeScreen.classList.remove("d-none"); + }); + + + }); + diff --git a/frontend/index.html b/frontend/index.html new file mode 100644 index 0000000..afdbfae --- /dev/null +++ b/frontend/index.html @@ -0,0 +1,51 @@ + + + + + + クイズアプリ + + + + + +
+

ミニラン

+ +
+ + + + + +
+

クイズ

+

任天堂・・

+
+ + + + +
+
+ + +
+

正解

+

スイッチ

+
+ + +
+
+ + + + diff --git a/frontend/style.css b/frontend/style.css new file mode 100644 index 0000000..2c90a81 --- /dev/null +++ b/frontend/style.css @@ -0,0 +1,60 @@ +body { + font-family: 'Arial', sans-serif; + background-color: #f8f9fa; + margin: 0; + padding: 0; + display: flex; + justify-content: center; + align-items: center; + height: 100vh; + } + + .container { + max-width: 500px; + } + + .logo { + font-size: 2.5rem; + font-weight: bold; + margin-bottom: 20px; + } + + .title { + font-size: 1.8rem; + margin-bottom: 10px; + } + + .question { + font-size: 1.5rem; + margin: 20px 0; + } + + .question.h2{ + color: black; + } + + .options .btn { + width: 100%; + margin: 5px 0; + } + + .status { + font-size: 1.2rem; + color: #28a745; + } + + .answer { + font-size: 2rem; + font-weight: bold; + margin: 20px 0; + } + + .actions .btn { + width: 100%; + margin: 5px 0; + } + + .d-none { + display: none; + } + \ No newline at end of file From c295a6b98389a81928eecdc521495389e0232271 Mon Sep 17 00:00:00 2001 From: Sairon <138011409+Yukkurisiteikitai@users.noreply.github.com> Date: Tue, 3 Dec 2024 16:15:12 +0900 Subject: [PATCH 03/51] set GameMenu&GameKind --- frontend/game.js | 122 ++++++++++++++++++++++++-------------------- frontend/index.html | 14 +++-- 2 files changed, 78 insertions(+), 58 deletions(-) diff --git a/frontend/game.js b/frontend/game.js index 2801f3b..1389ae4 100644 --- a/frontend/game.js +++ b/frontend/game.js @@ -2,23 +2,29 @@ document.addEventListener("DOMContentLoaded", () => { const homeScreen = document.getElementById("home"); const quizScreen = document.getElementById("quiz"); const resultScreen = document.getElementById("result"); - const menuScreen = document.getElementById("menu"); + const gameModeScreen = document.getElementById("game-mode"); + const selectGameScreen = document.getElementById("SelctGameKind"); + const startButton = document.getElementById("start-button"); const createButton = document.getElementById("create-button"); const playButton = document.getElementById("play-button"); + + const options = document.querySelectorAll(".selects"); const nextButton = document.querySelector(".next-button"); const quitButton = document.querySelector(".quit-button"); + const gameKindOptions = document.querySelector(".gamekind-option"); + // const gameModeOptions = document.querySelector(".gamemodes-option"); const statusText = document.querySelector(".status"); const answerText = document.querySelector(".answer"); - // クイズデータ - + // ゲームデータ + let gameMode = "play"; questions = [ { @@ -38,56 +44,22 @@ document.addEventListener("DOMContentLoaded", () => { } ] - function reqListener(){ - console.log(this.responseText); - } - - function LoadRequest(){ - console.log("hello"); - - const req = new XMLHttpRequest(); - // req.addEventListener("load",reqListener); - req.open("GET","http://127.0.0.1:2342/info/2") - // req.send(); - req.responseType = "json"; - req.onload = () => { - if(req.readyState == 4 && req.status == 200){ - const date = req.response; - console.log(date); - return date; - }else{ - console.log(`Error: ${req.status}`); - } - }; - return "Not Found"; - } - - question = {} - - fetch('http://127.0.0.1:2342/info/2') - .then(res => res.json()) - .then(data => { - console.log(data[0]); - const question = data[0]; - const d = document.createElement('h1'); - d.innerText=question["questiondate"]; - document.body.appendChild(d) - }) - + -displayLoadRequest - //display + /** + * That option discplayis + * @param display (string)この引数にhome,quiz,result,game_select,game_modeなどをstringで入れると、 + * その名前のdisplayを表示する + */ function displayLoadRequest(display) { - /** - * That option discplayis - * @param display (string)第1引数のコメント - * [home],["quiz"],["menu"],["result"] - */ + + gameModeScreen.classList.add("d-none"); + selectGameScreen.classList.add("d-none"); quizScreen.classList.add("d-none"); resultScreen.classList.add("d-none"); - menuScreen.classList.add("d-none"); + // menuScreen.classList.add("d-none"); homeScreen.classList.add("d-none"); if (display == "home") { @@ -97,9 +69,13 @@ displayLoadRequest { quizScreen.classList.remove("d-none"); } - else if (display == "menu") + else if (display == "game_select") { - menuScreen.classList.remove("d-none"); + selectGameScreen.classList.remove("d-none"); + } + else if (display == "game_mode") + { + gameModeScreen.classList.remove("d-none"); } else if (display == "result") { @@ -107,18 +83,53 @@ displayLoadRequest } } + displayLoadRequest("home"); // 正解データ const correctAnswer = "スイッチ"; - - // クイズ開始 + + // ゲームモードへ行く startButton.addEventListener("click", () => { /* homeScreen.classList.add("d-none"); quizScreen.classList.remove("d-none"); */ - displayLoadRequest("menu"); + console.log("start"); + displayLoadRequest("game_mode"); + }); + + playButton.addEventListener("click",()=>{ + displayLoadRequest("game_select"); }); + //gameMode + options.forEach(option => { + option.addEventListener("click", (event) => { + const selectedAnswer = event.target.textContent; + + // 判定処理 + if (selectedAnswer === correctAnswer) + { + statusText.textContent = "正解"; + statusText.style.color = "#28a745"; + } + else + { + statusText.textContent = "不正解"; + statusText.style.color = "#dc3545"; + } + + answerText.textContent = correctAnswer; // 正解を表示 + + // 結果画面へ移動 + /* + quizScreen.classList.add("d-none"); + resultScreen.classList.remove("d-none"); + */ + displayLoadRequest("result"); + }); + }); + + // 回答選択 @@ -141,8 +152,11 @@ displayLoadRequest answerText.textContent = correctAnswer; // 正解を表示 // 結果画面へ移動 + /* quizScreen.classList.add("d-none"); resultScreen.classList.remove("d-none"); + */ + displayLoadRequest("result"); }); }); @@ -172,9 +186,7 @@ displayLoadRequest // resultScreen.classList.add("d-none"); // menuScreen.classList.add("d-none"); // homeScreen.classList.remove("d-none"); - ScreenSet(false,resultScreen); - ScreenSet(false,menuScreen); - ScreenSet(true,homeScreen); + displayLoadRequest("home"); }); // やめる(ホーム画面に戻る) diff --git a/frontend/index.html b/frontend/index.html index afdbfae..af266c7 100644 --- a/frontend/index.html +++ b/frontend/index.html @@ -14,9 +14,17 @@

ミニラン

- - - -
-

クイズ

-

任天堂・・

-
- - - - + + + +
+ + +
+

間違い探し

+
+

05/??

+ + + + +
+ + +
+

クイズ

+

任天堂・・

+
+ + + + +
+
+ + +
+

制限時間は10秒!5回まで答えられるよ!

+
+

残り時間: 10

+

解答回数: 0/5

+ +
+ + +
+ + + + +
+
+ + + +
+
+ + +
+
+ + +
+ +
+ +
+ +
+
+

間違い探し

+
+ 画像1を選択 + 画像2を選択 +
+
+ +
+

クイズ

+
+ +
- -
-

正解

-

スイッチ

-
- -
- + + + + + + + diff --git a/make.css b/make.css new file mode 100644 index 0000000..5ca278a --- /dev/null +++ b/make.css @@ -0,0 +1,98 @@ +/* 画面全体の中央揃え */ +body { + font-family: Arial, sans-serif; + display: flex; + justify-content: center; + align-items: center; + height: 100vh; + margin: 0; + background-color: #f0f0f0; +} + +#quiz-container { + text-align: center; + color: #333; + width: 100%; + max-width: 500px; /* 適切な幅を指定 */ +} + +#info-text { + font-size: 18px; + font-weight: bold; + margin-bottom: 20px; + color: #ff4081; +} + +button { + padding: 10px 20px; + margin: 10px 0; /* 垂直方向の間隔を調整 */ + font-size: 16px; + cursor: pointer; + border-radius: 5px; + border: none; + transition: background-color 0.3s ease; +} + +#start-button { + background-color: #ff4081; + color: white; +} + +.answer-button { + background-color: #4caf50; + color: white; +} + +button.disabled { + background-color: #ccc; + cursor: not-allowed; +} + +#answer-input { + padding: 10px; + font-size: 16px; + border-radius: 5px; + border: 1px solid #ddd; + margin-top: 10px; + width: calc(100% - 40px); /* 入力フィールドの幅調整 */ + box-sizing: border-box; + display: none; +} + +#submit-answer-button { + background-color: #00bcd4; /* 水色 */ + color: white; + padding: 10px 20px; + font-size: 16px; + border-radius: 5px; + border: none; + cursor: pointer; + margin-top: 10px; +} + +button.disabled, +#answer-input.disabled { + background-color: #ccc; /* 灰色 */ + cursor: not-allowed; + color: #666; +} + +#next-button { + background-color: #ff9800; /* オレンジ */ + color: white; + margin-top: 20px; +} + +#result-message { + font-size: 100px; + font-weight: bold; + margin: 20px; +} + +.correct { + color: blue; +} + +.incorrect { + color: red; +} \ No newline at end of file diff --git a/play.css b/play.css new file mode 100644 index 0000000..e69de29 diff --git a/stylesheet.css b/stylesheet.css new file mode 100644 index 0000000..e69de29 From e5690cb9e5261c33932fc238026f796476c95170 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=AB=98=E8=A5=BF=E5=93=B2=E5=8F=B8?= Date: Sat, 7 Dec 2024 13:54:20 +0900 Subject: [PATCH 22/51] create_intro --- backend/controller/game_controller.py | 29 +++++++++++++++++++++++---- backend/engine/dynamo_client.py | 12 ++++++++--- backend/router.py | 10 +++++++++ compose.yml | 2 +- 4 files changed, 45 insertions(+), 8 deletions(-) diff --git a/backend/controller/game_controller.py b/backend/controller/game_controller.py index a5d2730..59e85d2 100644 --- a/backend/controller/game_controller.py +++ b/backend/controller/game_controller.py @@ -12,12 +12,17 @@ def get_game_random(self): 'game': response })) + def create_quiz(self): + # 必要な処理をここに記述 + return {"message": "Intro created successfully"} + def create_quiz(self): # リクエストデータを取得 data = request.get_json() question = data['questions'] selects = data['selects'] - answer = data['answer'] + answer = data['answer_idx'] + id = data['id'] # データベースを見て次のidを取得する # バリデーションを実装 if not data or 'quiz_name' not in data or 'questions' not in data: @@ -42,9 +47,20 @@ def create_quiz(self): def create_intro(self): data = request.get_json() - if not data or 'intro_name' not in data or 'intro_text' not in data: - return make_response(jsonify({'code': 400, 'message': 'Invalid data'}), 400) - + music_title_answer = data['music_title_answer'] + music_data = data['music_data']#musicのデータ本体 + id = data['id'] # データベースを見て次のidを取得する + + # バリデーションを実装 + #if not data or 'intro_name' not in data or 'intro_text' not in data: + # return make_response(jsonify({'code': 400, 'message': 'Invalid data'}), 400) + + if not isinstance(music_title_answer, str) or not music_title_answer.strip(): + return make_response(jsonify({'code': 400, 'message': 'Invalid music_title_answer'}), 400) + if not music_data: + return make_response(jsonify({'code': 400, 'message': 'Invalid music_data'}), 400) + + # DBに保存 try: if self.db_client.create_intro(data): return make_response(jsonify({'code': 200, 'message': 'Intro created successfully'}), 200) @@ -52,3 +68,8 @@ def create_intro(self): return make_response(jsonify({'code': 500, 'message': 'Failed to create intro'}), 500) except Exception as e: return make_response(jsonify({'code': 500, 'message': str(e)}), 500) + + def create_diffshot(self): + data = request.get_json() + music_title_answer = data['music_title_answer'] + music_data = data['music_data'] \ No newline at end of file diff --git a/backend/engine/dynamo_client.py b/backend/engine/dynamo_client.py index b4544a4..271aad0 100644 --- a/backend/engine/dynamo_client.py +++ b/backend/engine/dynamo_client.py @@ -28,9 +28,15 @@ def create_quiz(self, data: dict) -> None: ''' client = boto3.client('dynamodb') # ここで良いかは不明 response = client.put_item(TableName=self.table_name, Item={ - 'quiz_name': {'S': data['quiz_name']}, # quiz_nameではなくidか 'questions': {'S': data['questions']}, 'selects': {'L': [{'S': s} for s in data['selects']]}, - 'answer': {'N': str(data['answer'])} + 'answer_idx': {'N': str(data['answer'])}, + 'likes': {'N': '0'} }) - return True if response['ResponseMetadata']['HTTPStatusCode'] == 200 else False \ No newline at end of file + return True if response['ResponseMetadata']['HTTPStatusCode'] == 200 else False + + def create_intro(self, data: dict) -> None: + '''対象のテーブルにイントロデータを登録するメソッド + ''' + client = boto3.client('dynamodb') + \ No newline at end of file diff --git a/backend/router.py b/backend/router.py index 679179c..ba9b227 100644 --- a/backend/router.py +++ b/backend/router.py @@ -26,6 +26,16 @@ def api_play_random(): def api_create_quiz(): return game_controller.create_quiz() +@router.route("/api/create/intro", methods=['POST']) +@logger.http_request_logging +def api_create_intro(): + return game_controller.create_intro() + +@router.route("/api/create/diffshot", methods=['POST']) +@logger.http_request_logging +def api_create_diffshot(): + return game_controller.create_diffshot() + @router.after_request def after_request(response): # response.headers.add('Access-Control-Allow-Origin', '*') diff --git a/compose.yml b/compose.yml index 3cae6f6..5d99fb4 100644 --- a/compose.yml +++ b/compose.yml @@ -15,7 +15,7 @@ services: build: ./backend container_name: backend ports: - - "5001:5001" + - "5001:5000" volumes: - ./backend:/app env_file: From 856a18055ec3cf2611241921d8404e2e08e2824b Mon Sep 17 00:00:00 2001 From: nozo120 Date: Sat, 7 Dec 2024 14:24:56 +0900 Subject: [PATCH 23/51] =?UTF-8?q?=E3=83=95=E3=83=AD=E3=83=B3=E3=83=88?= =?UTF-8?q?=E3=82=A8=E3=83=B3=E3=83=89=E3=81=AE=E5=A4=89=E6=9B=B4=E3=82=92?= =?UTF-8?q?=E5=8A=A0=E3=81=88=E3=81=BE=E3=81=97=E3=81=9F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- index.html | 2 +- index2.html | 9 +- merged_index.html | 51 ++++------- merged_script.js | 224 ++++++++++++++++++++++++++++++++++++++++++++++ merged_style.css | 118 ++++++++++++++++++++++++ style2.css | 1 + 6 files changed, 367 insertions(+), 38 deletions(-) create mode 100644 merged_script.js create mode 100644 merged_style.css diff --git a/index.html b/index.html index 63cb66c..a4af0a7 100644 --- a/index.html +++ b/index.html @@ -8,7 +8,7 @@ -
+

制限時間は10秒!5回まで答えられるよ!

残り時間: 10

diff --git a/index2.html b/index2.html index 44a0389..46e7271 100644 --- a/index2.html +++ b/index2.html @@ -5,7 +5,10 @@ イントロドン作成 - + + + +
@@ -30,8 +33,10 @@

イントロドン作成

- + + + diff --git a/merged_index.html b/merged_index.html index aec47ae..c43f825 100644 --- a/merged_index.html +++ b/merged_index.html @@ -4,20 +4,18 @@ イントロドン - - イントロドン作成 - + -
@@ -111,15 +109,26 @@

間違い探し

クイズ

- +
+

質問

+ + +

選択肢

+ + + + + +

回答

+ +
-
- +
diff --git a/frontend/style.css b/frontend/style.css index 2c90a81..4f32952 100644 --- a/frontend/style.css +++ b/frontend/style.css @@ -57,4 +57,104 @@ body { .d-none { display: none; } - \ No newline at end of file + + + body { + font-family: Arial, sans-serif; + display: flex; + justify-content: center; + align-items: center; + height: 100vh; + margin: 0; + background-color: #f0f0f0; +} + +#quiz-container { + text-align: center; + color: #333; + width: 100%; + max-width: 500px; /* 適切な幅を指定 */ +} + +#info-text { + font-size: 18px; + font-weight: bold; + margin-bottom: 20px; + color: #ff4081; +} + +button { + width: 120px; + height: 45px; + padding: 10px 20px; + margin: 10px 0; /* 垂直方向の間隔を調整 */ + font-size: 16px; + cursor: pointer; + border-radius: 5px; + border: none; + transition: background-color 0.3s ease; +} + +#start-button { + background-color: #ff4081; + color: white; +} + +.answer-button { + background-color: #4caf50; + color: white; +} + +button.disabled { + background-color: #ccc; + cursor: not-allowed; +} + +#answer-input { + padding: 10px; + font-size: 16px; + border-radius: 5px; + border: 1px solid #ddd; + margin-top: 10px; + width: calc(100% - 40px); /* 入力フィールドの幅調整 */ + box-sizing: border-box; + display: none; +} + +#submit-answer-button { + background-color: #00bcd4; /* 水色 */ + color: white; + padding: 10px 20px; + font-size: 16px; + border-radius: 5px; + border: none; + cursor: pointer; + margin-top: 10px; +} + +button.disabled, +#answer-input.disabled { + background-color: #ccc; /* 灰色 */ + cursor: not-allowed; + color: #666; +} + +#next-button { + background-color: #ff9800; /* オレンジ */ + color: white; + margin-top: 20px; +} + +#result-message { + font-size: 100px; + font-weight: bold; + margin: 20px; +} + +.correct { + color: blue; +} + +.incorrect { + color: red; +} From 90984cb756e3d93203df3e2ff5ddf9e1f0c34e70 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=AB=98=E8=A5=BF=E5=93=B2=E5=8F=B8?= Date: Sat, 7 Dec 2024 16:13:25 +0900 Subject: [PATCH 26/51] create_quiz --- backend/controller/game_controller.py | 72 ++++++++++++++++++++------- backend/engine/dynamo_client.py | 18 ++++++- backend/router.py | 22 ++++++-- 3 files changed, 89 insertions(+), 23 deletions(-) diff --git a/backend/controller/game_controller.py b/backend/controller/game_controller.py index 59e85d2..3474ae4 100644 --- a/backend/controller/game_controller.py +++ b/backend/controller/game_controller.py @@ -1,5 +1,10 @@ from flask import make_response, jsonify, request from engine.dynamo_client import DynamoClient +import hashlib +#from werkzeug.utils import secure_filename +#from dynamo_client import save_file_metadata +#from s3_client import upload_to_s3 +#from dotenv import load_dotenv class GameController: def __init__(self): @@ -12,22 +17,16 @@ def get_game_random(self): 'game': response })) - def create_quiz(self): - # 必要な処理をここに記述 - return {"message": "Intro created successfully"} - def create_quiz(self): # リクエストデータを取得 data = request.get_json() - question = data['questions'] + question = data['question'] selects = data['selects'] - answer = data['answer_idx'] - id = data['id'] # データベースを見て次のidを取得する + answer = data['answer'] + id = 1 # データベースを見て次のidを取得する + data['id'] = id # バリデーションを実装 - if not data or 'quiz_name' not in data or 'questions' not in data: - return make_response(jsonify({'code': 400, 'message': 'Invalid data'}), 400) - if not isinstance(question, str) or not question.strip(): return make_response(jsonify({'code': 400, 'message': 'Invalid question'}), 400) if not isinstance(selects, list) or len(selects) != 4: @@ -48,13 +47,32 @@ def create_quiz(self): def create_intro(self): data = request.get_json() music_title_answer = data['music_title_answer'] - music_data = data['music_data']#musicのデータ本体 - id = data['id'] # データベースを見て次のidを取得する + #music_data = data['music_data'] # musicのデータ本体 + id = 1 # データベースを見て次のidを取得する + data['id'] = id + + if 'file' not in request.files: + return jsonify({"error": "No file part"}), 400 + + file = request.files['file'] + if file.filename == '': + return jsonify({"error": "No selected file"}), 400 + # ファイル名を安全にする + filename = secure_filename(file.filename) + # ファイル名のハッシュを生成 + file_hash = hashlib.sha256(filename.encode('utf-8')).hexdigest() + + try: + # S3にファイルをアップロード + upload_to_s3(file, file_hash, file.content_type) + # DynamoDBにメタデータを保存 + save_file_metadata(file_hash, filename) + return jsonify({"message": "File uploaded successfully", "file_hash": file_hash}), 200 + except Exception as e: + return jsonify({"error": str(e)}), 500 - # バリデーションを実装 - #if not data or 'intro_name' not in data or 'intro_text' not in data: - # return make_response(jsonify({'code': 400, 'message': 'Invalid data'}), 400) + # バリデーションを実装 if not isinstance(music_title_answer, str) or not music_title_answer.strip(): return make_response(jsonify({'code': 400, 'message': 'Invalid music_title_answer'}), 400) if not music_data: @@ -71,5 +89,25 @@ def create_intro(self): def create_diffshot(self): data = request.get_json() - music_title_answer = data['music_title_answer'] - music_data = data['music_data'] \ No newline at end of file + picture_data = data['picture_data'] + picture_data_answer = data['picture_data_answer'] + answer_points = data['answer_points'] + id = 1 # データベースを見て次のidを取得する + data['id'] = id + + # バリデーションを実装 + if not isinstance(picture_data, str) or not music_title_answer.strip(): + return make_response(jsonify({'code': 400, 'message': 'Invalid music_title_answer'}), 400) + if not music_data: + return make_response(jsonify({'code': 400, 'message': 'Invalid music_data'}), 400) + + + # DBに保存 + try: + if self.db_client.create_diffshot(data): + return make_response(jsonify({'code': 200, 'message': 'Diffshot created successfully'}), 200) + else: + return make_response(jsonify({'code': 500, 'message': 'Failed to create diffshot'}), 500) + except Exception as e: + return make_response(jsonify({'code': 500, 'message': str(e)}), 500) + \ No newline at end of file diff --git a/backend/engine/dynamo_client.py b/backend/engine/dynamo_client.py index 271aad0..aab9846 100644 --- a/backend/engine/dynamo_client.py +++ b/backend/engine/dynamo_client.py @@ -6,6 +6,9 @@ class DynamoClient: def __init__(self, table_name: str) -> None: self.db = boto3.client('dynamodb', endpoint_url=os.getenv("DYNAMO_ENDPOINT")) self.table_name = table_name + #self.db = boto3.resource('dynamodb', region_name=REGION_NAME) + #self.table_name = table_name or DYNAMODB_TABLE + #self.table = self.db.Table(self.table_name) def get_all(self) -> list: '''対象のテーブルからレコード全件を取得するメソッド @@ -28,7 +31,8 @@ def create_quiz(self, data: dict) -> None: ''' client = boto3.client('dynamodb') # ここで良いかは不明 response = client.put_item(TableName=self.table_name, Item={ - 'questions': {'S': data['questions']}, + 'id': {'N': str(data['id'])}, + 'question': {'S': data['question']}, 'selects': {'L': [{'S': s} for s in data['selects']]}, 'answer_idx': {'N': str(data['answer'])}, 'likes': {'N': '0'} @@ -39,4 +43,16 @@ def create_intro(self, data: dict) -> None: '''対象のテーブルにイントロデータを登録するメソッド ''' client = boto3.client('dynamodb') + response = client.put_item(TableName=self.table_name, Item={ + 'id': {'N': str(data['id'])}, + 'music_title_answer': {'S': data['music_title_answer']}, + 'music_data': {'B': data['music_data']}, + 'likes': {'N': '0'} + }) + + def create_diffshot(self, data: dict) -> None: + '''対象のテーブルにディフショットデータを登録するメソッド + ''' + client = boto3.client('dynamodb') + \ No newline at end of file diff --git a/backend/router.py b/backend/router.py index ba9b227..88abe63 100644 --- a/backend/router.py +++ b/backend/router.py @@ -1,11 +1,23 @@ from flask import Blueprint -from controller import game_controller +from controller.game_controller import GameController from logging import config from json import load import logger +import boto3 + +## クライアントの初期化 +#s3_client = boto3.client( +# "s3", +# aws_access_key_id=S3_ACCESS_KEY, +# aws_secret_access_key=S3_SECRET_KEY, +# endpoint_url=S3_ENDPOINT, # MinIOの場合 +#) +#dynamodb = boto3.resource("dynamodb", region_name=REGION_NAME) +#dynamodb_table = dynamodb.Table(DYNAMODB_TABLE) # Generate Router Instance router = Blueprint('router', __name__) +controller = GameController() # Read Logging Configuration with open("./config/logging.json", "r", encoding="utf-8") as f: @@ -19,22 +31,22 @@ def hello_world(): @router.route("/api/play/random", methods=['GET']) @logger.http_request_logging def api_play_random(): - return game_controller.get_game_random() + return controller.get_game_random() @router.route("/api/create/quiz", methods=['POST']) @logger.http_request_logging def api_create_quiz(): - return game_controller.create_quiz() + return controller.create_quiz() @router.route("/api/create/intro", methods=['POST']) @logger.http_request_logging def api_create_intro(): - return game_controller.create_intro() + return controller.create_intro() @router.route("/api/create/diffshot", methods=['POST']) @logger.http_request_logging def api_create_diffshot(): - return game_controller.create_diffshot() + return controller.create_diffshot() @router.after_request def after_request(response): From 547dc385597e73934a62ee33ef4360163b2c7d0a Mon Sep 17 00:00:00 2001 From: Fuchs0101 Date: Sat, 7 Dec 2024 16:17:30 +0900 Subject: [PATCH 27/51] =?UTF-8?q?DynamoDB=E3=81=A8=E3=81=AE=E7=B9=8B?= =?UTF-8?q?=E3=81=8E=E3=81=93=E3=81=BF=E3=82=92=E5=AE=9F=E8=A3=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 3 ++- backend/controller/game_controller.py | 2 +- backend/engine/dynamo_client.py | 8 ++++---- backend/router.py | 7 ++++--- compose.yml | 4 +--- frontend/Dockerfile | 10 ++-------- 6 files changed, 14 insertions(+), 20 deletions(-) diff --git a/.gitignore b/.gitignore index 0b6b20a..cb52990 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,6 @@ # log files -backend/logs +*.log.* +*.log # environment informations and credentials *.env diff --git a/backend/controller/game_controller.py b/backend/controller/game_controller.py index 00db5ef..24ecda9 100644 --- a/backend/controller/game_controller.py +++ b/backend/controller/game_controller.py @@ -3,7 +3,7 @@ class GameController: def __init__(self): - self.db_client = DynamoClient(table_name="game_table") + self.db_client = DynamoClient(table_name="minirun_game_table") def get_game_random(self): response = self.db_client.get_random() diff --git a/backend/engine/dynamo_client.py b/backend/engine/dynamo_client.py index 624e13f..2b7a0b8 100644 --- a/backend/engine/dynamo_client.py +++ b/backend/engine/dynamo_client.py @@ -4,7 +4,7 @@ class DynamoClient: def __init__(self, table_name: str) -> None: - self.db = boto3.client('dynamodb', endpoint_url=os.getenv("DYNAMO_ENDPOINT")) + self.db = boto3.client('dynamodb') self.table_name = table_name def get_all(self) -> list: @@ -18,7 +18,7 @@ def get_random(self) -> None: '''対象のテーブルからランダムに1件レコードを取得するメソッド ''' response_all = self.db.scan(TableName=self.table_name) - response_len = response_all['Count'] - random_key = random.randrange(response_len) + valid_keys = [item['id']['N'] for item in response_all['Items']] + random_key = random.choice(valid_keys) response = self.db.get_item(TableName=self.table_name, Key={"id": {"N": str(random_key)}}) - return response.get('Item', []) + return response.get('Item') diff --git a/backend/router.py b/backend/router.py index 679179c..9a4aaab 100644 --- a/backend/router.py +++ b/backend/router.py @@ -1,11 +1,12 @@ from flask import Blueprint -from controller import game_controller +from controller.game_controller import GameController from logging import config from json import load import logger # Generate Router Instance router = Blueprint('router', __name__) +controller = GameController() # Read Logging Configuration with open("./config/logging.json", "r", encoding="utf-8") as f: @@ -19,12 +20,12 @@ def hello_world(): @router.route("/api/play/random", methods=['GET']) @logger.http_request_logging def api_play_random(): - return game_controller.get_game_random() + return controller.get_game_random() @router.route("/api/create/quiz", methods=['POST']) @logger.http_request_logging def api_create_quiz(): - return game_controller.create_quiz() + return controller.create_quiz() @router.after_request def after_request(response): diff --git a/compose.yml b/compose.yml index b6a7552..22f3440 100644 --- a/compose.yml +++ b/compose.yml @@ -3,11 +3,9 @@ services: build: ./frontend container_name: frontend ports: - - "3000:3000" + - "8080:80" volumes: - ./frontend:/app - environment: - - NODE_ENV=development depends_on: - backend diff --git a/frontend/Dockerfile b/frontend/Dockerfile index 223797c..6e8acef 100644 --- a/frontend/Dockerfile +++ b/frontend/Dockerfile @@ -1,8 +1,2 @@ -FROM node:18 - -WORKDIR /app - -COPY package*.json ./ -RUN npm install - -COPY . . +FROM nginx:alpine +COPY . /usr/share/nginx/html From dd61c715de570523ca37a3acea0293dee1c07265 Mon Sep 17 00:00:00 2001 From: nozo120 Date: Sat, 7 Dec 2024 16:18:51 +0900 Subject: [PATCH 28/51] =?UTF-8?q?=E3=83=95=E3=83=AD=E3=83=B3=E3=83=88?= =?UTF-8?q?=E3=82=A8=E3=83=B3=E3=83=89=E3=81=AE=E5=A4=89=E6=9B=B4=E3=82=92?= =?UTF-8?q?=E5=8A=A0=E3=81=88=E3=81=BE=E3=81=97=E3=81=9F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- index2.html | 2 +- index3.html | 32 ++++++++++++++++++++++++++++++++ merged_index.html | 9 +++++++++ merged_script.js | 38 ++++++++++++++++++++++++++++++++++---- script3.js | 22 ++++++++++++++++++++++ style3.css | 37 +++++++++++++++++++++++++++++++++++++ 6 files changed, 135 insertions(+), 5 deletions(-) create mode 100644 index3.html create mode 100644 script3.js create mode 100644 style3.css diff --git a/index2.html b/index2.html index 46e7271..1a9188c 100644 --- a/index2.html +++ b/index2.html @@ -8,7 +8,7 @@ - +
diff --git a/index3.html b/index3.html new file mode 100644 index 0000000..5c57f6b --- /dev/null +++ b/index3.html @@ -0,0 +1,32 @@ + + + + + + ボタンで画面遷移 + + + +
+

ボタンで画面遷移

+
+ + + +
+
+ + + +
+
+ + + + diff --git a/merged_index.html b/merged_index.html index c43f825..604a7ef 100644 --- a/merged_index.html +++ b/merged_index.html @@ -11,6 +11,15 @@ + +
+ -
- - -
- - - - -
-
- - - - diff --git a/index2.html b/index2.html deleted file mode 100644 index 1a9188c..0000000 --- a/index2.html +++ /dev/null @@ -1,42 +0,0 @@ - - - - - - - イントロドン作成 - - - - - - -
-

イントロドン作成

- - - - - -

- - - - - -

- - - - - - -
- - - - - - - - diff --git a/script.js b/script.js deleted file mode 100644 index d0dec9c..0000000 --- a/script.js +++ /dev/null @@ -1,147 +0,0 @@ - -document.addEventListener('DOMContentLoaded', function () { - const startButton = document.getElementById('start-button'); - const submitButton = document.getElementById('submit-answer-button'); - const resultMessage = document.getElementById('result-message'); - const nextButton = document.getElementById('next-button'); - const answerInput = document.getElementById('answer-input'); - const timeLeftElement = document.getElementById('time-left'); - const answerCountElement = document.getElementById('answer-count'); - const maxAnswerCountElement = document.getElementById('max-answer-count'); - const infoText = document.getElementById('info-text'); - const button1 = document.getElementById('button1'); - const button2 = document.getElementById('button2'); - - const audio = new Audio('your-music-file.mp3'); - let timer; - let timeRemaining = 10; - let answerCount = 0; - const maxAnswerCount = 5; - let correctAnswer = "曲名"; - let quizFinished = false; - let answerEnabled = false; - - // 初期設定 - maxAnswerCountElement.textContent = maxAnswerCount; - answerInput.style.display = 'none'; - submitButton.style.display = 'none'; - submitButton.disabled = true; - - - startButton.addEventListener('click', function () { - audio.play(); - startButton.disabled = true; - startTimer(); - }); - - function startTimer() { - timer = setInterval(function () { - timeRemaining--; - timeLeftElement.textContent = timeRemaining; - - if (timeRemaining <= 0) { - clearInterval(timer); - endQuiz(false); - } - }, 1000); - } - - function resetButtons() { - button1.disabled = false; - button2.disabled = false; - button1.classList.remove('disabled'); - button2.classList.remove('disabled'); - button1.style.backgroundColor = '#4caf50'; - button2.style.backgroundColor = '#4caf50'; - } - - button1.addEventListener('click', function () { - enableAnswer(); - button1.disabled = true; - button2.classList.add('disabled'); - button2.style.backgroundColor = '#ccc'; - }); - - button2.addEventListener('click', function () { - enableAnswer(); - button2.disabled = true; - button1.classList.add('disabled'); - button1.style.backgroundColor = '#ccc'; - }); - - function enableAnswer() { - answerEnabled = true; - answerInput.style.display = 'block'; - submitButton.style.display = 'block'; - submitButton.disabled = false; - } - - submitButton.addEventListener('click', function () { - if (quizFinished || !answerEnabled) return; - - const userAnswer = answerInput.value.trim(); - answerCount++; - answerCountElement.textContent = answerCount; - - if (userAnswer.toLowerCase() === correctAnswer.toLowerCase()) { - endQuiz(true); - } else if (answerCount >= maxAnswerCount) { - endQuiz(false); - } else { - resultMessage.style.display = 'block'; - resultMessage.textContent = "×"; - resultMessage.className = 'incorrect'; - resetButtons(); // ボタンの状態をリセット - } - }); - - nextButton.addEventListener('click', function () { - window.location.href = 'next-page.html'; - }); - - function endQuiz(isCorrect) { - clearInterval(timer); - quizFinished = true; - - resultMessage.style.display = 'block'; - nextButton.style.display = 'block'; - - if (isCorrect) { - resultMessage.textContent = "〇"; - resultMessage.className = 'correct'; - } else { - resultMessage.textContent = "×"; - resultMessage.className = 'incorrect'; - } - - disableAllInputs(); - - // 解答入力と解答完了ボタンを無効化 - answerInput.disabled = true; - submitButton.disabled = true; - submitButton.classList.add('disabled'); - } - -function disableAllInputs() { - document.querySelectorAll('.answer-button').forEach(button => { - button.disabled = true; - button.classList.add('disabled'); - }); - - // 解答入力フィールドと解答完了ボタンを無効化 - answerInput.disabled = true; - submitButton.disabled = true; - submitButton.classList.add('disabled'); -} - -function enableAllInputs() { - document.querySelectorAll('.answer-button').forEach(button => { - button.disabled = false; - button.classList.remove('disabled'); - }); - // 解答完了ボタンも有効化 - submitButton.disabled = false; - submitButton.classList.remove('disabled'); - answerInput.disabled = false; -} -}) \ No newline at end of file diff --git a/script2.js b/script2.js deleted file mode 100644 index 0cfa32d..0000000 --- a/script2.js +++ /dev/null @@ -1,61 +0,0 @@ -document.getElementById("create-button").addEventListener("click", function () { - const audioFile = document.getElementById("audio-upload").files[0]; - const answer = document.getElementById("answer-input").value; - - // 音声ファイルがない場合 - if (!audioFile) { - alert("音声ファイルを入力してください!"); - return; - } - - // 答えがない場合 - if (!answer) { - alert("答えを入力してください!"); - return; - } - - - // フォームデータの作成 - const formData = new FormData(); - formData.append("audio", audioFile); - formData.append("answer", answer); - - // データをバックエンドに送信 - fetch("YOUR_BACKEND_URL", { - method: "POST", - body: formData - }) - - - .then((response) => { - if (response.ok) { - document.getElementById("status-message").style.display = "block"; - } else { - alert("エラーが発生しました。再試行してください。"); - } - }) - .catch((error) => { - console.error("通信エラー:", error); - alert("通信エラーが発生しました。"); - }); -document.getElementById("audio-upload").addEventListener("change", toggleCreateButton); -document.getElementById("answer-input").addEventListener("input", toggleCreateButton); - -function toggleCreateButton() { - const audioFile = document.getElementById("audio-upload").files[0]; - const answer = document.getElementById("answer-input").value; - - const createButton = document.getElementById("create-button"); - - // 音声ファイルと答えが両方入力されている場合はボタンを有効化 - if (audioFile && answer) { - createButton.disabled = false; - } else { - createButton.disabled = true; - } -} - -// 初期状態でボタンを無効化しておく -toggleCreateButton(); - -}); From ce2fcb781e214961fd337d057ba6cf7515f84ade Mon Sep 17 00:00:00 2001 From: nozo120 Date: Sat, 7 Dec 2024 17:40:47 +0900 Subject: [PATCH 31/51] =?UTF-8?q?=E3=83=95=E3=83=AD=E3=83=B3=E3=83=88?= =?UTF-8?q?=E3=82=A8=E3=83=B3=E3=83=89=E3=81=AE=E8=A1=A8=E7=A4=BA=E3=83=87?= =?UTF-8?q?=E3=82=B0=E3=83=AC=E3=82=92=E8=A7=A3=E6=B6=88?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- merged_index.html | 6 +----- merged_script.js | 33 ++++++--------------------------- 2 files changed, 7 insertions(+), 32 deletions(-) diff --git a/merged_index.html b/merged_index.html index 604a7ef..63b5dda 100644 --- a/merged_index.html +++ b/merged_index.html @@ -12,11 +12,7 @@ -
-
- + From 199cb4c4e008a5db6a68bb2879fed368df0f3593 Mon Sep 17 00:00:00 2001 From: tetsushi33 Date: Sat, 7 Dec 2024 18:33:45 +0900 Subject: [PATCH 35/51] define play_intro, play_diffshot temp --- backend/controller/game_controller.py | 49 +++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) diff --git a/backend/controller/game_controller.py b/backend/controller/game_controller.py index c70714a..7791008 100644 --- a/backend/controller/game_controller.py +++ b/backend/controller/game_controller.py @@ -145,3 +145,52 @@ def play_quiz(self): 'code': 500, 'message': str(e) }), 500) + + def play_intro(self): + try: + # データベースからランダムに問題を取得 + response = self.db_client.get_random() + if response: + intro_data = { + "music_title_answer": response.get('music_title_answer', {}).get('S', ''), + "music_data": response.get('music_data', {}).get('B', '') + } + return make_response(jsonify({ + 'code': 200, + 'game_content': intro_data + }), 200) + else: + return make_response(jsonify({ + 'code': 404, + 'message': 'No intro found' + }), 404) + except Exception as e: + return make_response(jsonify({ + 'code': 500, + 'message': str(e) + }), 500) + + def play_diffshot(self): + try: + # データベースからランダムに問題を取得 + response = self.db_client.get_random() + if response: + diffshot_data = { + "picture_data": response.get('picture_data', {}).get('S', ''), + "picture_data_answer": response.get('picture_data_answer', {}).get('S', ''), + "answer_points": response.get('answer_points', {}).get('L', []) + } + return make_response(jsonify({ + 'code': 200, + 'game_content': diffshot_data + }), 200) + else: + return make_response(jsonify({ + 'code': 404, + 'message': 'No diffshot found' + }), 404) + except Exception as e: + return make_response(jsonify({ + 'code': 500, + 'message': str(e) + }), 500) \ No newline at end of file From 7feb8433519666c474d6af9b5d794fce200a2e37 Mon Sep 17 00:00:00 2001 From: tetsushi33 Date: Sat, 7 Dec 2024 19:34:11 +0900 Subject: [PATCH 36/51] define play_intro --- backend/controller/game_controller.py | 15 +++++----- backend/engine/dynamo_client.py | 25 ++++++++++++++++ backend/engine/s3_client.py | 42 +++++++++++++++++++++++++++ 3 files changed, 75 insertions(+), 7 deletions(-) diff --git a/backend/controller/game_controller.py b/backend/controller/game_controller.py index 7791008..c9b2548 100644 --- a/backend/controller/game_controller.py +++ b/backend/controller/game_controller.py @@ -3,7 +3,7 @@ import hashlib #from werkzeug.utils import secure_filename #from dynamo_client import save_file_metadata -#from s3_client import upload_to_s3 +from s3_client import upload_to_s3 #from dotenv import load_dotenv @@ -58,8 +58,8 @@ def create_intro(self): data = request.get_json() music_title_answer = data['music_title_answer'] #music_data = data['music_data'] # musicのデータ本体 - id = 1 # データベースを見て次のidを取得する - data['id'] = id + last_id = self.get_last_id() + data['id'] = last_id + 1 if 'file' not in request.files: return jsonify({"error": "No file part"}), 400 @@ -68,7 +68,8 @@ def create_intro(self): if file.filename == '': return jsonify({"error": "No selected file"}), 400 # ファイル名を安全にする - filename = secure_filename(file.filename) + #filename = secure_filename(file.filename) + filename = file.filename # ファイル名のハッシュを生成 file_hash = hashlib.sha256(filename.encode('utf-8')).hexdigest() @@ -76,7 +77,7 @@ def create_intro(self): # S3にファイルをアップロード upload_to_s3(file, file_hash, file.content_type) # DynamoDBにメタデータを保存 - save_file_metadata(file_hash, filename) + self.db_client.save_file_metadata(data, file_hash, filename) return jsonify({"message": "File uploaded successfully", "file_hash": file_hash}), 200 except Exception as e: return jsonify({"error": str(e)}), 500 @@ -102,8 +103,8 @@ def create_diffshot(self): picture_data = data['picture_data'] picture_data_answer = data['picture_data_answer'] answer_points = data['answer_points'] - id = 1 # データベースを見て次のidを取得する - data['id'] = id + last_id = self.get_last_id() + data['id'] = last_id + 1 # バリデーションを実装 if not isinstance(picture_data, str) or not music_title_answer.strip(): diff --git a/backend/engine/dynamo_client.py b/backend/engine/dynamo_client.py index 133b758..e9586ae 100644 --- a/backend/engine/dynamo_client.py +++ b/backend/engine/dynamo_client.py @@ -53,6 +53,31 @@ def create_intro(self, data: dict) -> None: 'likes': {'N': '0'} }) + def save_file_metadata(self, data: dict, file_hash: str, original_name: str) -> bool: + """ + DynamoDBにファイルのメタデータを保存する関数 + + Args: + file_hash (str): ファイルのハッシュ値 + original_name (str): 元のファイル名 + + Returns: + bool: 成功した場合はTrue、失敗した場合はFalse + """ + try: + client = boto3.client('dynamodb') + # DynamoDBにデータを登録 + response = client.put_item(Item={ + 'id': {'N': str(data['id'])}, + 'file_hash': file_hash, + 'original_name': original_name + }) + return response.get('ResponseMetadata', {}).get('HTTPStatusCode') == 200 + except Exception as e: + print(f"Error saving file metadata to DynamoDB: {e}") + return False + + def create_diffshot(self, data: dict) -> None: '''対象のテーブルにディフショットデータを登録するメソッド ''' diff --git a/backend/engine/s3_client.py b/backend/engine/s3_client.py index e69de29..745019a 100644 --- a/backend/engine/s3_client.py +++ b/backend/engine/s3_client.py @@ -0,0 +1,42 @@ +import boto3 +import os +from dotenv import load_dotenv + +# .envファイルを読み込む +load_dotenv() + +# boto3クライアントの初期化 +s3_client = boto3.client( + "s3", + aws_access_key_id=os.getenv("S3_ACCESS_KEY"), + aws_secret_access_key=os.getenv("S3_SECRET_KEY"), + endpoint_url=os.getenv("S3_ENDPOINT") # MinIOを使用する場合に必要 +) + +def upload_to_s3(file, file_hash, content_type): + """ + S3にファイルをアップロードする関数 + + Args: + file: アップロードするファイルオブジェクト + file_hash: S3に保存するオブジェクトのキー(ユニークな名前) + content_type: ファイルのContent-Type + + Raises: + Exception: アップロードが失敗した場合 + """ + try: + # 環境変数からS3バケットを取得 + s3_bucket = os.getenv("S3_BUCKET") + + # S3にファイルをアップロード + s3_client.upload_fileobj( + file, + s3_bucket, + file_hash, # ファイル名の代わりにハッシュを使用 + ExtraArgs={"ContentType": content_type} + ) + print(f"File uploaded successfully to S3 with key: {file_hash}") + except Exception as e: + print(f"Error uploading file to S3: {e}") + raise e \ No newline at end of file From 3df4d1b885eb2619daf122c68f402c2d527311ef Mon Sep 17 00:00:00 2001 From: tetsushi33 Date: Sat, 7 Dec 2024 19:44:40 +0900 Subject: [PATCH 37/51] define play_intro --- backend/router.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/backend/router.py b/backend/router.py index 9395a97..68f6e80 100644 --- a/backend/router.py +++ b/backend/router.py @@ -53,6 +53,11 @@ def api_create_diffshot(): def api_play_quiz(): return controller.play_quiz() +@router.route("/api/play/intro", methods=['GET']) +@logger.http_request_logging +def api_play_intro(): + return controller.play_intro() + @router.after_request def after_request(response): From fbdc62c58e887b34fd97dc0bbb40cfca746ff0a3 Mon Sep 17 00:00:00 2001 From: Sairon <138011409+Yukkurisiteikitai@users.noreply.github.com> Date: Sat, 7 Dec 2024 20:38:48 +0900 Subject: [PATCH 38/51] add/XMLhttpRequest-GET-quiz-do --- backend/app.py | 4 +- frontend/game.js | 140 ++++++-- test.txt | 903 ++--------------------------------------------- 3 files changed, 150 insertions(+), 897 deletions(-) diff --git a/backend/app.py b/backend/app.py index b5f6b16..9178668 100644 --- a/backend/app.py +++ b/backend/app.py @@ -15,7 +15,7 @@ def create_app(): CORS( app, resources = { - r"/api/*": {"origins": ["http://localhost", "http://localhost:3000"]} + r"/api/*": {"origins": ["http://localhost", "http://localhost:3000","http://localhost:8032"]} } ) @@ -23,4 +23,4 @@ def create_app(): if __name__ == "__main__": app = create_app() - app.run(host='0.0.0.0', debug=True, port=5000, threaded=True, use_reloader=False) \ No newline at end of file + app.run(host='0.0.0.0', debug=True, port=5001, threaded=True, use_reloader=False) \ No newline at end of file diff --git a/frontend/game.js b/frontend/game.js index cab4084..bf75089 100644 --- a/frontend/game.js +++ b/frontend/game.js @@ -54,7 +54,7 @@ document.addEventListener("DOMContentLoaded", () => { //クイズデータ let question_date = [ { - "question": "次のうち、太陽系に存在する惑星はどれですか?", + "question": "次のうち、太陽fejfioewajf;owjfo;eiwajfoi;する惑星はどれですか?", "selects": [ "シリウス", "地球", @@ -74,6 +74,10 @@ document.addEventListener("DOMContentLoaded", () => { console.log(question_date); + function rd(max){ + return Math.floor(Math.random() * max) + } + console.log(rd(2)); /** * That option discplayis * @param display (string)この引数にhome,quiz,result,game_select,game_modeなどをstringで入れると、 @@ -205,28 +209,88 @@ document.addEventListener("DOMContentLoaded", () => { * "アンドロメダ", * "アルタイル" * ], - * "answer":2 + * "answer":2 * } */ - function load_QuizQuestion(){ - - } - function quiz_set(question_text,selects,answer_number){ - let date = { - "question": "次のうち、太陽系に存在する惑星はどれですか?", - "selects": [ - "シリウス", - "地球", - "アンドロメダ", - "アルタイル" - ], - "answer":2 + // async function load_QuizQuestion(url) { + // const get_url = url + "/api/play/random"; + // try { + // const request = await fetch(get_url, { + // method: "GET", + // headers: { + // "Content-Type": "application/json", + // }, + // }) + // .then(quizDate){ + // console.log() + // } + + // // ステータスコードのチェック + // if (!request.ok) { + // throw new Error(`レスポンスエラー: ステータス ${request.status}`); + // } + + // // JSON データを取得 + // const json_data = await request.json(); + // console.log("取得したクイズデータ:", json_data); + // return json_data; // データを返す + // } catch (error) { + // console.error("エラーが発生しました:", error); + // throw error; // 必要に応じてエラーを再スロー + // } + // } + + function load_QuizQuestion(url, callback) { + const get_url = url + "/api/play/random"; + const xhr = new XMLHttpRequest(); + + xhr.open("GET", get_url, true); + xhr.setRequestHeader("Content-Type", "application/json"); + + xhr.onreadystatechange = function () { + if (xhr.readyState === 4) { // 完了 + if (xhr.status >= 200 && xhr.status < 300) { + try { + const data = JSON.parse(xhr.responseText); + callback(null, data); // データをコールバックで返す + } catch (error) { + callback(error, null); + } + } else { + callback(new Error(`ステータスエラー: ${xhr.status}`), null); + } + } + }; + + xhr.onerror = function () { + callback(new Error("ネットワークエラー"), null); }; - // fetch("api/play/quiz",method("GET")){ + + xhr.send(); + } + + - // } - console.log(date); - } + + console.log("helloWorldejfo;iejfejf;oaewjgo;ifewjgo;wjgo;jeawgo;eajwgojeg;je\n"); + // console.log(load_QuizQuestion("http://172.23.0.5:5001")) + // function quiz_set(question_text,selects,answer_number){ + + // let date = { + // "question": "次のうち、太陽系に存在する惑星はどれですか?", + // "selects": [ + // "シリウス", + // "地球", + // "アンドロメダ", + // "アルタイル" + // ], + // "answer":2 + // }; + // fetch("api/play/quiz",method("GET")){ + + // } + // console.log(date); + // } /** * 質問を書き込む @@ -247,10 +311,36 @@ document.addEventListener("DOMContentLoaded", () => { correctAnswer = selects[answer_number]; } - quiz_set(question_date[0]["question"], + + function get_quiz_set(question_text,selects,answer_number) + { + console.log(`dateLoading-:-${typeof(question_text)}, \n ${selects}, \n ${answer_number}`); + quiz_qustion.textContent = question_text; + const quiz_contents = quiz_select_options.item(0).children; + for(var i = 0; i < 4;i++) + { + quiz_contents[i].textContent = selects[i]["S"]; + } + correctAnswer = selects[answer_number]; + } + + // 使用例 + load_QuizQuestion("http://localhost:5001", (error, data) => { + if (error) { + console.error("エラー:", error); + } else { + console.log("取得したクイズデータ:", data); + + get_quiz_set(data["game"]["question"]["S"],data["game"]["selects"]["L"],data["game"]["answer_idx"]["N"]); + } + }); + /*quiz_set(question_date[0]["question"], question_date[0]["selects"], - question_date[0]["answer"]); + question_date[0]["answer"]);*/ + // let get_question = load_QuizQuestion("http://localhost:5001"); + // console.log(get_question); + // get_quiz_set(get_question["game"]["question"],get_question["game"]["selects"]["L"],get_question["game"]["answer_idx"]["N"]); //================================================================================================================================================================ @@ -622,10 +712,10 @@ document.addEventListener("DOMContentLoaded", () => { }); - //テスト用のプログラムを組み込んでいる - quiz_set(question_date[0]["question"], - question_date[0]["selects"], - question_date[0]["answer"]); + // //テスト用のプログラムを組み込んでいる + // quiz_set(question_date[0]["question"], + // question_date[0]["selects"], + // question_date[0]["answer"]); let quiz_number diff --git a/test.txt b/test.txt index 4ddce9c..0da8f53 100644 --- a/test.txt +++ b/test.txt @@ -1,870 +1,33 @@ -. -.. -.git -.gitignore -.mypy_cache -README.md -backend -compose.yml -frontend -temp.py -test.txt - -./.git: -. -.. -COMMIT_EDITMSG -FETCH_HEAD -HEAD -ORIG_HEAD -config -description -hooks -index -info -logs -objects -packed-refs -refs - -./.git/hooks: -. -.. -applypatch-msg.sample -commit-msg.sample -fsmonitor-watchman.sample -post-update.sample -pre-applypatch.sample -pre-commit.sample -pre-merge-commit.sample -pre-push.sample -pre-rebase.sample -pre-receive.sample -prepare-commit-msg.sample -push-to-checkout.sample -update.sample - -./.git/info: -. -.. -exclude - -./.git/logs: -. -.. -HEAD -refs - -./.git/logs/refs: -. -.. -heads -remotes - -./.git/logs/refs/heads: -. -.. -develop -division -future - -./.git/logs/refs/heads/division: -. -.. -gameSystemFile - -./.git/logs/refs/heads/future: -. -.. -setQuiz - -./.git/logs/refs/remotes: -. -.. -origin - -./.git/logs/refs/remotes/origin: -. -.. -HEAD -future - -./.git/logs/refs/remotes/origin/future: -. -.. -backend-base -setQuiz - -./.git/objects: -. -.. -00 -02 -05 -06 -08 -0b -10 -13 -18 -19 -1a -24 -26 -28 -2c -2e -30 -31 -37 -47 -4a -4f -52 -55 -57 -62 -64 -65 -67 -6b -6e -76 -78 -79 -7e -7f -81 -82 -83 -85 -89 -8a -8b -8d -90 -91 -93 -94 -97 -9a -a1 -a5 -a7 -a9 -ab -ac -af -b0 -b1 -b3 -b4 -b5 -b6 -b7 -ba -be -c0 -c1 -c2 -cb -cc -d4 -d7 -d8 -dc -de -df -e0 -ed -ee -f5 -fa -fd -ff -info -pack - -./.git/objects/00: -. -.. -1f25886b7af0d774051063edd08552ba96f9a9 -db5ef7b04fa7ba165dd34e977dc7915b66c1cf - -./.git/objects/02: -. -.. -f0ced09a96aba23f5b2ebc95924cf20cbc9b19 - -./.git/objects/05: -. -.. -2548b67e50198cb21dab2f63368cb659a58b0c -5ccbcc0ac85139ac9e49c0d5acb2f9e8f80ddf - -./.git/objects/06: -. -.. -83e3db4e0d5038d882679d2252ff19a68c6044 -b46d77bb72af1b38bfd00d797cde2616dfd32c - -./.git/objects/08: -. -.. -64746f85208bf228c5289debf0414d21108e1a - -./.git/objects/0b: -. -.. -27c19be1c0365fe152023548be2158f3127e8f -6b20a802b8cdc9e2962bf86f16f798376fe5bc - -./.git/objects/10: -. -.. -ba08e7359a566e810767b8335dc1835629d2b6 -f8f0faa5c26d31e7363904c3342d83b4c1f6b0 - -./.git/objects/13: -. -.. -89ae49f67a7f26ab5469b624b073754b56063b - -./.git/objects/18: -. -.. -268a387711559a646e0ebac27df4ce29e98369 - -./.git/objects/19: -. -.. -e8fa45302f089bc63579c393dacc6c6288b630 - -./.git/objects/1a: -. -.. -22ca6f8c39aef0366c91e1b7d3a63d6bc5480d -3b6ea59a40d4c26b79bf380523e78b8b3a0ecc - -./.git/objects/24: -. -.. -ecc328359d2d3b899c05106211e55317a4c7b0 - -./.git/objects/26: -. -.. -4c0c9b47e5be176f5b38049ff39e1163236518 - -./.git/objects/28: -. -.. -01f3be1d9494c6273534e54d7a4996c1ef4c53 - -./.git/objects/2c: -. -.. -90a81c6e4a26ebf8d203fc052392ce9c5562b1 - -./.git/objects/2e: -. -.. -66282e63c7b89013e6b5d36c11d84567a4e9b7 - -./.git/objects/30: -. -.. -860087c133dbec3f2e6b658bbec088dbc3a4f4 - -./.git/objects/31: -. -.. -5b0b8dfb93e73b6a6df18b529d9a4409801bc5 - -./.git/objects/37: -. -.. -ae094ef2bce72a4f983c77598468f7b9408ed5 -dd079d19cd06da209ad7dcae7240df63943ec9 - -./.git/objects/47: -. -.. -f4f2087cc6861b86be1938b5e3c99f23f04f05 - -./.git/objects/4a: -. -.. -6e00805b14ccd3e3852d5f26a9466edd81b6ae - -./.git/objects/4f: -. -.. -bde366e026d43a6fd44c2d8ab4ad9e24177050 - -./.git/objects/52: -. -.. -a96ee10001be474a05e45c98239d03d800ffcc - -./.git/objects/55: -. -.. -577401cd5d6e8331261c929e5bdbd941d9916f - -./.git/objects/57: -. -.. -e7aabb436ea6f61e7310f559dc491c448d9a9d - -./.git/objects/62: -. -.. -4e13f9262883ae822e2392c2188c7a70a2fc80 - -./.git/objects/64: -. -.. -5efc7a9f1244d4be93a4911363dd8659dbf2b0 - -./.git/objects/65: -. -.. -bfbbf240d68514568edbe85d7601abff920a39 - -./.git/objects/67: -. -.. -9179cc18ae13e76a3fc1be51fc32c026d4e563 - -./.git/objects/6b: -. -.. -bca84f7373d5fe9ef415132ae1ebc1c60f3293 - -./.git/objects/6e: -. -.. -1f230124b559b4ee039dfd6210aa30ec6444a6 -b42e1b66fc2c9c94faabe30796ec0002dd5be9 - -./.git/objects/76: -. -.. -0afd6da38dd3bbfeb9ebbfd3a9ef8480c11a4e - -./.git/objects/78: -. -.. -f8bb2d7ddcafe86160e33a56f5288d8455515e - -./.git/objects/79: -. -.. -a2c535a99eb6bed715787de623f56024713d7a - -./.git/objects/7e: -. -.. -47750bde9cc5fa90b5a190718b012557be6ac2 -f7401d14d3f474d48a58405a4a4946988cb06a - -./.git/objects/7f: -. -.. -1dc67509b4ace2d565b51fd451bdce2b971dda - -./.git/objects/81: -. -.. -325793127d44c5d34064b6a37a78cce50d117e - -./.git/objects/82: -. -.. -5e8007423c2e811493718e9ac3ae6ded0ce30d - -./.git/objects/83: -. -.. -88d9fc76d3ab9f8c75ec4f986c369b659d92c4 - -./.git/objects/85: -. -.. -44ff1841d9f559cda3b1a9b940fdb5ad399ede - -./.git/objects/89: -. -.. -2304da97df8c35d3a78d91ab4607d978ec3c57 - -./.git/objects/8a: -. -.. -4c9080e373a3ab4f7bbfe0dcbcaecef7ca9124 - -./.git/objects/8b: -. -.. -e5987bf0735cfc513a5b75e03e017198edbb80 - -./.git/objects/8d: -. -.. -72f4e95140e228f3eb2e4b3cfe1a339ff44b1f - -./.git/objects/90: -. -.. -dcedceba970395bbc09127357c98b2d058c43f - -./.git/objects/91: -. -.. -b3a2d77f3af5c222c4d7b2c5aeee36f3dad7a0 - -./.git/objects/93: -. -.. -7d92cc65c860a341596f0cfcdb52720d5982c0 - -./.git/objects/94: -. -.. -1892cd8119bc1f691db7316bf359fba036b1c7 - -./.git/objects/97: -. -.. -29fc4f3958b6d1da84fa21963162e41b727281 - -./.git/objects/9a: -. -.. -9c3f3292463a6245c5fb5be5ddeeaef46f45ed -b65aae942f8d969483b78fc890f0067d1efb60 - -./.git/objects/a1: -. -.. -3d65c67e24b0237a20f267d44dfdbc0418c90b - -./.git/objects/a5: -. -.. -0387feaf3dfe02d5ada4f06730b1401a46bba8 -8d0f4b9d2efaca2022057d029c75becca75406 - -./.git/objects/a7: -. -.. -d4d59eefcfbbb2528647ed64412be16adab167 - -./.git/objects/a9: -. -.. -48aa5e3fdccd314a37b837807c2323be86e3aa -c76281e6c0a75bbae08253ed0ba5cf86272810 - -./.git/objects/ab: -. -.. -5423543ef14f0b8147f7dc4545575bf995c631 - -./.git/objects/ac: -. -.. -87f7828ab32829572af3a4932fc3a77a95a7a6 - -./.git/objects/af: -. -.. -266c791ab5ceef5de2efda84ef74d637157514 -dbfae32df1382bcce0286094fef694ed304831 - -./.git/objects/b0: -. -.. -511f416a79d9979efc9f3eb76f7fac8891e248 - -./.git/objects/b1: -. -.. -6ec5c5577c37507ca3b69ab76253b26a6f63fb -83c68799d3cdeb2609995967d6ece08fa780fb - -./.git/objects/b3: -. -.. -176a4c3491263a52408ace68ae826a4ac7b695 - -./.git/objects/b4: -. -.. -3f168ad98a2b708e06f38e6f051fbb82c30f7a - -./.git/objects/b5: -. -.. -f6b169c9f7dd1680b556e5d09d469490b772c3 - -./.git/objects/b6: -. -.. -a75520a1e20b2cf69ca7289ad8f6467be3695c - -./.git/objects/b7: -. -.. -77b1fb2fb1fa2204a3231a9a681f69938b7c8e - -./.git/objects/ba: -. -.. -4d74bc65435685baf0888970d3011eccba9d9d - -./.git/objects/be: -. -.. -004386b9d13f8bdb966fd4f3df882da50a872f - -./.git/objects/c0: -. -.. -19c932ec5aab91680e488f3327aec272696c52 -aa97fe6d290a98b778b99f9e2bf53a424fa1ad - -./.git/objects/c1: -. -.. -2b6885f6e1fca076b7f77e78cbd5b0f8adc33b - -./.git/objects/c2: -. -.. -36ea10cd9a624ea0abc71995f38f8234f10cef -95a6b98389a81928eecdc521495389e0232271 - -./.git/objects/cb: -. -.. -03014fbf5470dac584f3ebb7b4de6aec9d31b0 - -./.git/objects/cc: -. -.. -c75e93a8dba45a1ba42d857f64b2cce649b42f - -./.git/objects/d4: -. -.. -fa0a98e5aae2cab9abae86ac611e7954067683 - -./.git/objects/d7: -. -.. -125ba82e2c53e511979909e4f1cbac92572cbc -a597736555e4b74b9f4acb2bba2ff1a03b6601 - -./.git/objects/d8: -. -.. -5e4eae37214f72db4bb745a83b2a3d73b67df4 - -./.git/objects/dc: -. -.. -64d31e35c2a2dbd7b9afb9e7e7749effcf56fa - -./.git/objects/de: -. -.. -1eac0da7a1bda0617744b9815abcf71740a896 - -./.git/objects/df: -. -.. -2a3167f5a0634ceb101fd966843c9d6ba7adef - -./.git/objects/e0: -. -.. -d2c4541f2eca5eff0257f811de004acd6ff2a2 - -./.git/objects/ed: -. -.. -377205b05bda4c5521a7ac1a160795cab16d14 - -./.git/objects/ee: -. -.. -a20c8b730bed89e705e5ed5dcba19bac72ca8d - -./.git/objects/f5: -. -.. -66e264d4a37fc2cb31613777846ef9d2c1ff66 - -./.git/objects/fa: -. -.. -c74855e4e0fddc9525a8d9842d5e7968c9ba4b - -./.git/objects/fd: -. -.. -42a08cc817e573c65e0e7f8a23366f517e16af - -./.git/objects/ff: -. -.. -c2432e5ed02544800e896fb88636a3982dc101 - -./.git/objects/info: -. -.. - -./.git/objects/pack: -. -.. -pack-a7f1da3635a81f4a305b6eca309a2248b62cab20.idx -pack-a7f1da3635a81f4a305b6eca309a2248b62cab20.pack - -./.git/refs: -. -.. -heads -remotes -tags - -./.git/refs/heads: -. -.. -develop -division -future - -./.git/refs/heads/division: -. -.. -gameSystemFile - -./.git/refs/heads/future: -. -.. -setQuiz - -./.git/refs/remotes: -. -.. -origin - -./.git/refs/remotes/origin: -. -.. -HEAD -future - -./.git/refs/remotes/origin/future: -. -.. -backend-base -setQuiz - -./.git/refs/tags: -. -.. - -./.mypy_cache: -. -.. -.gitignore -3.11 -CACHEDIR.TAG - -./.mypy_cache/3.11: -. -.. -@plugins_snapshot.json -_ast.data.json -_ast.meta.json -_codecs.data.json -_codecs.meta.json -_collections_abc.data.json -_collections_abc.meta.json -_typeshed -abc.data.json -abc.meta.json -builtins.data.json -builtins.meta.json -codecs.data.json -codecs.meta.json -collections -contextlib.data.json -contextlib.meta.json -dataclasses.data.json -dataclasses.meta.json -email -enum.data.json -enum.meta.json -genericpath.data.json -genericpath.meta.json -importlib -io.data.json -io.meta.json -os -pathlib.data.json -pathlib.meta.json -posixpath.data.json -posixpath.meta.json -re.data.json -re.meta.json -resource.data.json -resource.meta.json -sre_compile.data.json -sre_compile.meta.json -sre_constants.data.json -sre_constants.meta.json -sre_parse.data.json -sre_parse.meta.json -subprocess.data.json -subprocess.meta.json -sys -temp.data.json -temp.meta.json -types.data.json -types.meta.json -typing.data.json -typing.meta.json -typing_extensions.data.json -typing_extensions.meta.json -zipfile - -./.mypy_cache/3.11/_typeshed: -. -.. -__init__.data.json -__init__.meta.json -importlib.data.json -importlib.meta.json - -./.mypy_cache/3.11/collections: -. -.. -__init__.data.json -__init__.meta.json -abc.data.json -abc.meta.json - -./.mypy_cache/3.11/email: -. -.. -__init__.data.json -__init__.meta.json -_policybase.data.json -_policybase.meta.json -charset.data.json -charset.meta.json -contentmanager.data.json -contentmanager.meta.json -errors.data.json -errors.meta.json -header.data.json -header.meta.json -message.data.json -message.meta.json -policy.data.json -policy.meta.json - -./.mypy_cache/3.11/importlib: -. -.. -__init__.data.json -__init__.meta.json -_abc.data.json -_abc.meta.json -abc.data.json -abc.meta.json -machinery.data.json -machinery.meta.json -metadata -readers.data.json -readers.meta.json -resources - -./.mypy_cache/3.11/importlib/metadata: -. -.. -__init__.data.json -__init__.meta.json -_meta.data.json -_meta.meta.json - -./.mypy_cache/3.11/importlib/resources: -. -.. -__init__.data.json -__init__.meta.json -abc.data.json -abc.meta.json - -./.mypy_cache/3.11/os: -. -.. -__init__.data.json -__init__.meta.json -path.data.json -path.meta.json - -./.mypy_cache/3.11/sys: -. -.. -__init__.data.json -__init__.meta.json - -./.mypy_cache/3.11/zipfile: -. -.. -__init__.data.json -__init__.meta.json - -./backend: -. -.. -Dockerfile -requirements.txt - -./frontend: -. -.. -.DS_Store -Dockerfile -differentPoint.html -game.js -game.jsREADME.md -games -image -index.html -package.json -style.css -thinks - -./frontend/games: -. -.. -FindDifference.js -quiz.js - -./frontend/image: -. -.. -ban-1.png -ban-2.png -fabicon.ico - -./frontend/thinks: -. -.. -differentpoint.md +{ + "code": 200, + "game": { + "question": { + "S": "次のうち、太陽系に存在する惑星はどれですか?" + }, + "likes": { + "N": "0" + }, + "answer_idx": { + "N": "2" + }, + "id": { + "N": "3" + }, + "selects": { + "L": [ + { + "S": "シリウス" + }, + { + "S": "地球" + }, + { + "S": "アンドロメダ" + }, + { + "S": "アルタイル" + } + ] + } + } +} From 4e37ed821231d1807e7ea75042bfaf877a0390bb Mon Sep 17 00:00:00 2001 From: tetsushi33 Date: Sat, 7 Dec 2024 20:58:10 +0900 Subject: [PATCH 39/51] define play_quiz --- backend/controller/game_controller.py | 9 +++-- backend/engine/dynamo_client.py | 47 +++++++++++++++++++++++++++ backend/engine/s3_client.py | 23 ++++++++++++- backend/router.py | 4 +-- 4 files changed, 78 insertions(+), 5 deletions(-) diff --git a/backend/controller/game_controller.py b/backend/controller/game_controller.py index c9b2548..266b1ae 100644 --- a/backend/controller/game_controller.py +++ b/backend/controller/game_controller.py @@ -122,10 +122,14 @@ def create_diffshot(self): except Exception as e: return make_response(jsonify({'code': 500, 'message': str(e)}), 500) + + def play_quiz(self): try: + data = request.get_json() # データベースからランダムに問題を取得 - response = self.db_client.get_random() + #response = self.db_client.get_random() + response = self.db_client.get_random_2(genre="quiz") if response: quiz_data = { "question": response.get('question', {}).get('S', ''), @@ -151,10 +155,11 @@ def play_intro(self): try: # データベースからランダムに問題を取得 response = self.db_client.get_random() + #response = self.db_client.get_random_2() if response: intro_data = { "music_title_answer": response.get('music_title_answer', {}).get('S', ''), - "music_data": response.get('music_data', {}).get('B', '') + #"music_data": response.get('music_data', {}).get('B', '') } return make_response(jsonify({ 'code': 200, diff --git a/backend/engine/dynamo_client.py b/backend/engine/dynamo_client.py index e9586ae..664668b 100644 --- a/backend/engine/dynamo_client.py +++ b/backend/engine/dynamo_client.py @@ -25,6 +25,53 @@ def get_random(self) -> None: random_key = random.choice(valid_keys) response = self.db.get_item(TableName=self.table_name, Key={"id": {"N": str(random_key)}}) return response.get('Item') + + def get_random_2(self, genre: str) -> None: + '''指定されたジャンルの中からランダムに1件レコードを取得するメソッド''' + # 指定されたジャンルのアイテムをスキャン + response_all = self.db.scan( + TableName=self.table_name, + FilterExpression="genre = :genre", + ExpressionAttributeValues={":genre": {"S": genre}} + ) + items = response_all.get('Items', []) + if not items: + return None + + if genre == "quiz": + # 有効なキーを取得 + valid_keys = [item['id']['N'] for item in items] + random_key = random.choice(valid_keys) + # 選択肢をシャッフル + selects = selected_item['selects']['L'] + random.shuffle(selects) + # ランダムに選ばれたキーのアイテムを取得 + response = self.db.get_item(TableName=self.table_name, Key={"id": {"N": str(random_key)}}) + return response.get('Item') + if genre == "introdon": + # "introdon" 用の特別な処理 + selected_item = random.choice(items) + + # 音声データのハッシュ値と元の名前を取得 + file_hash = selected_item['file_hash']['S'] + original_name = selected_item['original_name']['S'] + + # 必要に応じて他の処理を追加可能 + return { + "file_hash": file_hash, + "original_name": original_name, + } + + + + # 有効なキーを取得 + valid_keys = [item['id']['N'] for item in items] + random_key = random.choice(valid_keys) + + # ランダムに選ばれたキーのアイテムを取得 + response = self.db.get_item(TableName=self.table_name, Key={"id": {"N": str(random_key)}}) + return response.get('Item') + def scan(self, **kwargs): return self.db.scan(**kwargs) diff --git a/backend/engine/s3_client.py b/backend/engine/s3_client.py index 745019a..01c17ae 100644 --- a/backend/engine/s3_client.py +++ b/backend/engine/s3_client.py @@ -39,4 +39,25 @@ def upload_to_s3(file, file_hash, content_type): print(f"File uploaded successfully to S3 with key: {file_hash}") except Exception as e: print(f"Error uploading file to S3: {e}") - raise e \ No newline at end of file + raise e + +def get_s3_file_url(file_key: str) -> str: + """ + S3のファイルにアクセスするための署名付きURLを生成する関数 + + Args: + file_key (str): S3に格納されているオブジェクトのキー + + Returns: + str: 署名付きURL + """ + try: + url = s3_client.generate_presigned_url( + 'get_object', + Params={'Bucket': os.getenv("S3_BUCKET"), 'Key': file_key}, + ExpiresIn=3600 # URLの有効期限(秒単位) + ) + return url + except Exception as e: + print(f"Error generating S3 presigned URL: {e}") + return "" \ No newline at end of file diff --git a/backend/router.py b/backend/router.py index 68f6e80..3391bec 100644 --- a/backend/router.py +++ b/backend/router.py @@ -30,8 +30,8 @@ def hello_world(): @router.route("/api/play/random", methods=['GET']) @logger.http_request_logging -def api_play_random(): - return controller.get_game_random() +def api_play_random_quiz(): + return controller.get_quiz_random() @router.route("/api/create/quiz", methods=['POST']) @logger.http_request_logging From faa6ea87404d257fa72f82555841bbfd4cd56d70 Mon Sep 17 00:00:00 2001 From: Sairon <138011409+Yukkurisiteikitai@users.noreply.github.com> Date: Sat, 7 Dec 2024 21:07:50 +0900 Subject: [PATCH 40/51] changeCreateD-none --- frontend/game.js | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/frontend/game.js b/frontend/game.js index bf75089..372b8d0 100644 --- a/frontend/game.js +++ b/frontend/game.js @@ -2,6 +2,8 @@ const homeScreen = document.getElementById("home"); const quiz_Screen = document.getElementById("quiz-container"); const differentPoint_Screen = document.getElementById("differentPoint-container"); const introdon_Screen = document.getElementById("introDon-container"); +const createModeScreen = document.getElementById(""); +const playModeScreen = document.getElementById(""); const resultScreen = document.getElementById("result"); const gameModeScreen = document.getElementById("game-mode"); @@ -30,6 +32,9 @@ document.addEventListener("DOMContentLoaded", () => { // ゲームデータ let gameMode = "play"; + + createButton.addEventListener("click") + //ゲーム選択画面でそのままLoadingKeyに入れるようにするための対策 const gamekind = { "クイズ":"quiz", @@ -37,6 +42,7 @@ document.addEventListener("DOMContentLoaded", () => { "イントロドン":"introdon" } + //bug const gameSetting = { "create":{ "クイズ":"quiz", @@ -482,7 +488,7 @@ document.addEventListener("DOMContentLoaded", () => { }); }); - + /** * 正解の場所かどうかを判定する処理 * @param touchPos 要素数2の1次元の配列 From 731e36df87a8024ec385dfd0ef7ff1d870400839 Mon Sep 17 00:00:00 2001 From: tetsushi33 Date: Sat, 7 Dec 2024 21:16:03 +0900 Subject: [PATCH 41/51] define play_quiz --- backend/controller/game_controller.py | 4 ++-- backend/engine/dynamo_client.py | 15 +++++---------- backend/router.py | 2 +- 3 files changed, 8 insertions(+), 13 deletions(-) diff --git a/backend/controller/game_controller.py b/backend/controller/game_controller.py index 266b1ae..6943dfc 100644 --- a/backend/controller/game_controller.py +++ b/backend/controller/game_controller.py @@ -154,8 +154,8 @@ def play_quiz(self): def play_intro(self): try: # データベースからランダムに問題を取得 - response = self.db_client.get_random() - #response = self.db_client.get_random_2() + #response = self.db_client.get_random() + response = self.db_client.get_random_2(genre="introdon") if response: intro_data = { "music_title_answer": response.get('music_title_answer', {}).get('S', ''), diff --git a/backend/engine/dynamo_client.py b/backend/engine/dynamo_client.py index 664668b..9b5a400 100644 --- a/backend/engine/dynamo_client.py +++ b/backend/engine/dynamo_client.py @@ -34,22 +34,17 @@ def get_random_2(self, genre: str) -> None: FilterExpression="genre = :genre", ExpressionAttributeValues={":genre": {"S": genre}} ) - items = response_all.get('Items', []) - if not items: - return None - + if genre == "quiz": # 有効なキーを取得 - valid_keys = [item['id']['N'] for item in items] + valid_keys = [item['id']['N'] for item in response_all['Items']] random_key = random.choice(valid_keys) - # 選択肢をシャッフル - selects = selected_item['selects']['L'] - random.shuffle(selects) - # ランダムに選ばれたキーのアイテムを取得 response = self.db.get_item(TableName=self.table_name, Key={"id": {"N": str(random_key)}}) return response.get('Item') if genre == "introdon": - # "introdon" 用の特別な処理 + # 有効なキーを取得 + valid_keys = [item['id']['N'] for item in items] + random_key = random.choice(valid_keys) selected_item = random.choice(items) # 音声データのハッシュ値と元の名前を取得 diff --git a/backend/router.py b/backend/router.py index 3391bec..23ff225 100644 --- a/backend/router.py +++ b/backend/router.py @@ -31,7 +31,7 @@ def hello_world(): @router.route("/api/play/random", methods=['GET']) @logger.http_request_logging def api_play_random_quiz(): - return controller.get_quiz_random() + return controller.get_game_random() @router.route("/api/create/quiz", methods=['POST']) @logger.http_request_logging From 5960876fb078f99633a123d3f462fb76a0e69e3e Mon Sep 17 00:00:00 2001 From: nozo120 Date: Sat, 7 Dec 2024 21:37:52 +0900 Subject: [PATCH 42/51] =?UTF-8?q?=E3=83=95=E3=83=AD=E3=83=B3=E3=83=88?= =?UTF-8?q?=E3=82=A8=E3=83=B3=E3=83=89=E3=81=AE=E5=A4=89=E6=9B=B4=E3=82=92?= =?UTF-8?q?=E5=8A=A0=E3=81=88=E3=81=BE=E3=81=97=E3=81=9F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/router.py | 2 +- frontend/game.js | 78 ++++++++++++++++++++++++++++++++++++++++++++- frontend/index.html | 40 ++++++++++++----------- index.html | 30 +++++++++++++++++ 4 files changed, 130 insertions(+), 20 deletions(-) create mode 100644 index.html diff --git a/backend/router.py b/backend/router.py index 71dcb0a..33dd937 100644 --- a/backend/router.py +++ b/backend/router.py @@ -51,7 +51,7 @@ def api_create_diffshot(): @router.after_request def after_request(response): - # response.headers.add('Access-Control-Allow-Origin', '*') + response.headers.add('Access-Control-Allow-Origin', '*') response.headers.add('Access-Control-Allow-Headers', 'Content-Type,Authorization') response.headers.add('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE,OPTIONS') return response diff --git a/frontend/game.js b/frontend/game.js index d9f7f7e..ea4969f 100644 --- a/frontend/game.js +++ b/frontend/game.js @@ -2,19 +2,23 @@ const homeScreen = document.getElementById("home"); const quiz_Screen = document.getElementById("quiz-container"); const differentPoint_Screen = document.getElementById("differentPoint-container"); const introdon_Screen = document.getElementById("introDon-container"); +const createScreen = document.getElementById("create-mode"); const resultScreen = document.getElementById("result"); const gameModeScreen = document.getElementById("game-mode"); const selectGameScreen = document.getElementById("SelctGameKind"); +const createQuizScreen = document.getElementById("create_quizScreen"); document.addEventListener("DOMContentLoaded", () => { const startButton = document.getElementById("start-button"); + const createButton = document.getElementById("create-button"); const playButton = document.getElementById("play-button"); const nextButton = document.querySelector(".next-button"); const quitButton = document.querySelector(".quit-button"); + const gameKindOptions = document.querySelectorAll(".gamekind-option"); @@ -30,6 +34,10 @@ document.addEventListener("DOMContentLoaded", () => { // ゲームデータ let gameMode = "play"; + + createButton.addEventListener("click",()=>{ + gameMode="create"; + }) //ゲーム選択画面でそのままLoadingKeyに入れるようにするための対策 const gamekind = { "クイズ":"quiz", @@ -81,6 +89,10 @@ document.addEventListener("DOMContentLoaded", () => { */ function displayLoadRequest(display) { + if(gameMode == "create"){ + createScreen.classList.remove("d-none"); + } + gameModeScreen.classList.add("d-none"); selectGameScreen.classList.add("d-none"); @@ -90,6 +102,8 @@ document.addEventListener("DOMContentLoaded", () => { resultScreen.classList.add("d-none"); homeScreen.classList.add("d-none"); + create_quizScreen.classList.add("d-none"); + console.log(`display:${display}`); @@ -115,6 +129,9 @@ document.addEventListener("DOMContentLoaded", () => { //gameCreate else if (display == "create_quiz") { + + createQuizScreen.classList.remove("d-none"); + } @@ -136,6 +153,7 @@ document.addEventListener("DOMContentLoaded", () => { else if (display == "game_select") { selectGameScreen.classList.remove("d-none"); + displayLoadRequest("create_quiz") } else if (display == "game_mode") @@ -148,6 +166,7 @@ document.addEventListener("DOMContentLoaded", () => { resultScreen.classList.remove("d-none"); } } + displayLoadRequest("home"); @@ -161,6 +180,10 @@ document.addEventListener("DOMContentLoaded", () => { displayLoadRequest("game_select"); }); + createButton.addEventListener('click', function () { + displayLoadRequest("create_quiz"); + }); + //gameMode @@ -627,4 +650,57 @@ document.addEventListener("DOMContentLoaded", () => { displayLoadRequest("home"); }); - }); \ No newline at end of file + + document.getElementById("submit_quiz").addEventListener("click", async function () { + // フォームからデータを取得 + const question = document.getElementById("quiz_question").value; + const options = [ + document.getElementById("option_1").value, + document.getElementById("option_2").value, + document.getElementById("option_3").value, + document.getElementById("option_4").value, + ]; + const answer = parseInt(document.getElementById("quiz_answer").value, 10); + + // 入力チェック + if (!question || options.some(option => !option) || isNaN(answer) || answer < 1 || answer > 4) { + alert("すべてのフィールドを正しく入力してください。"); + return; + } + + // クイズデータを表示(または送信) + const quizData = { + question: question, + selects: options, + answer_idx: answer, + }; + + // クイズデータをサーバーに送信 + try { + const response = await fetch('http://localhost:5001/api/create/quiz', { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify(quizData), + }); + + if (!response.ok) { + throw new Error('Failed to fetch'); + } + + console.log(await response.json()); + } catch (error) { + console.error(error); + }; + + + console.log("クイズデータ:", quizData); + alert("クイズが作成されました!"); + + }); + + }); + + + \ No newline at end of file diff --git a/frontend/index.html b/frontend/index.html index 81079cc..5c801b2 100644 --- a/frontend/index.html +++ b/frontend/index.html @@ -106,24 +106,28 @@

間違い探し

-
-

クイズ

-
-
-

質問

- - -

選択肢

- - - - - -

回答

- -
-
+
+

クイズ作成

+
+
+ + +
+
+ + + + + +
+
+ + +
+ +
+ @@ -132,7 +136,7 @@

クイズ

- + diff --git a/index.html b/index.html new file mode 100644 index 0000000..a4af0a7 --- /dev/null +++ b/index.html @@ -0,0 +1,30 @@ + + + + + + + イントロドン + + + +
+

制限時間は10秒!5回まで答えられるよ!

+
+

残り時間: 10

+

解答回数: 0/5

+ +
+ + +
+ + + + +
+
+ + + + From 9411b92b86108877d24223a911f0110eebee29f0 Mon Sep 17 00:00:00 2001 From: tetsushi33 Date: Sat, 7 Dec 2024 21:45:55 +0900 Subject: [PATCH 43/51] define play_quiz --- backend/controller/game_controller.py | 2 +- backend/engine/dynamo_client.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/backend/controller/game_controller.py b/backend/controller/game_controller.py index 6943dfc..e242d52 100644 --- a/backend/controller/game_controller.py +++ b/backend/controller/game_controller.py @@ -3,7 +3,7 @@ import hashlib #from werkzeug.utils import secure_filename #from dynamo_client import save_file_metadata -from s3_client import upload_to_s3 +from engine.s3_client import upload_to_s3 #from dotenv import load_dotenv diff --git a/backend/engine/dynamo_client.py b/backend/engine/dynamo_client.py index 9b5a400..bcc611e 100644 --- a/backend/engine/dynamo_client.py +++ b/backend/engine/dynamo_client.py @@ -43,7 +43,7 @@ def get_random_2(self, genre: str) -> None: return response.get('Item') if genre == "introdon": # 有効なキーを取得 - valid_keys = [item['id']['N'] for item in items] + valid_keys = [item['id']['N'] for item in response_all['Items']] random_key = random.choice(valid_keys) selected_item = random.choice(items) From 2a4c6e79aba7c3102d8890cf88dcc78d03e0ed25 Mon Sep 17 00:00:00 2001 From: Fuchs0101 Date: Sat, 7 Dec 2024 22:56:55 +0900 Subject: [PATCH 44/51] =?UTF-8?q?=E3=83=95=E3=83=AD=E3=83=B3=E3=83=88?= =?UTF-8?q?=E3=81=8B=E3=82=89=E3=81=AE=E3=82=AF=E3=82=A4=E3=82=BA=E5=8F=96?= =?UTF-8?q?=E5=BE=97=E5=87=A6=E7=90=86=E3=82=92=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/controller/game_controller.py | 1 - backend/requirements.txt | 3 +- backend/router.py | 2 +- frontend/game.js | 159 ++++++++++++++++++++++++-- frontend/index.html | 2 +- 5 files changed, 155 insertions(+), 12 deletions(-) diff --git a/backend/controller/game_controller.py b/backend/controller/game_controller.py index e242d52..e6e6bae 100644 --- a/backend/controller/game_controller.py +++ b/backend/controller/game_controller.py @@ -126,7 +126,6 @@ def create_diffshot(self): def play_quiz(self): try: - data = request.get_json() # データベースからランダムに問題を取得 #response = self.db_client.get_random() response = self.db_client.get_random_2(genre="quiz") diff --git a/backend/requirements.txt b/backend/requirements.txt index 65bfbbf..f4589fa 100644 --- a/backend/requirements.txt +++ b/backend/requirements.txt @@ -1,4 +1,5 @@ Flask==2.2.5 boto3==1.26.145 gunicorn==20.1.0 -flask_cors \ No newline at end of file +flask_cors +python-dotenv \ No newline at end of file diff --git a/backend/router.py b/backend/router.py index 23ff225..e35f9a2 100644 --- a/backend/router.py +++ b/backend/router.py @@ -61,7 +61,7 @@ def api_play_intro(): @router.after_request def after_request(response): - # response.headers.add('Access-Control-Allow-Origin', '*') + response.headers.add('Access-Control-Allow-Origin', '*') response.headers.add('Access-Control-Allow-Headers', 'Content-Type,Authorization') response.headers.add('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE,OPTIONS') return response diff --git a/frontend/game.js b/frontend/game.js index 94c34cc..ceaf7cd 100644 --- a/frontend/game.js +++ b/frontend/game.js @@ -2,6 +2,8 @@ const homeScreen = document.getElementById("home"); const quiz_Screen = document.getElementById("quiz-container"); const differentPoint_Screen = document.getElementById("differentPoint-container"); const introdon_Screen = document.getElementById("introDon-container"); +const createModeScreen = document.getElementById("create_quiz"); +const playModeScreen = document.getElementById("play-mode"); const resultScreen = document.getElementById("result"); const gameModeScreen = document.getElementById("game-mode"); @@ -30,6 +32,14 @@ document.addEventListener("DOMContentLoaded", () => { // ゲームデータ let gameMode = "play"; + + createButton.addEventListener("click",()=>{ + gameMode = "create"; + }); + playButton.addEventListener("click",()=>{ + gameMode = "play"; + }); + //ゲーム選択画面でそのままLoadingKeyに入れるようにするための対策 const gamekind = { "クイズ":"quiz", @@ -37,6 +47,7 @@ document.addEventListener("DOMContentLoaded", () => { "イントロドン":"introdon" } + //bug const gameSetting = { "create":{ "クイズ":"quiz", @@ -54,7 +65,7 @@ document.addEventListener("DOMContentLoaded", () => { //クイズデータ let question_date = [ { - "question": "次のうち、太陽系に存在する惑星はどれですか?", + "question": "次のうち、太陽fejfioewajf;owjfo;eiwajfoi;する惑星はどれですか?", "selects": [ "シリウス", "地球", @@ -74,6 +85,10 @@ document.addEventListener("DOMContentLoaded", () => { console.log(question_date); + function rd(max){ + return Math.floor(Math.random() * max) + } + console.log(rd(2)); /** * That option discplayis * @param display (string)この引数にhome,quiz,result,game_select,game_modeなどをstringで入れると、 @@ -81,6 +96,15 @@ document.addEventListener("DOMContentLoaded", () => { */ function displayLoadRequest(display) { + + createModeScreen.classList.add("d-none"); + playModeScreen.classList.add("d-none"); + if(gameMode == "create"){ + createModeScreen.classList.remove("d-none"); + }else if (gameMode == "play"){ + playModeScreen.classList.remove("d-none"); + } + gameModeScreen.classList.add("d-none"); selectGameScreen.classList.add("d-none"); @@ -195,6 +219,99 @@ document.addEventListener("DOMContentLoaded", () => { }); }); + /** + * 返り値 + * { + * "question": "次のうち、太陽系に存在する惑星はどれですか?", + * "selects": [ + * "シリウス", + * "地球", + * "アンドロメダ", + * "アルタイル" + * ], + * "answer":2 + * } + */ + // async function load_QuizQuestion(url) { + // const get_url = url + "/api/play/random"; + // try { + // const request = await fetch(get_url, { + // method: "GET", + // headers: { + // "Content-Type": "application/json", + // }, + // }) + // .then(quizDate){ + // console.log() + // } + + // // ステータスコードのチェック + // if (!request.ok) { + // throw new Error(`レスポンスエラー: ステータス ${request.status}`); + // } + + // // JSON データを取得 + // const json_data = await request.json(); + // console.log("取得したクイズデータ:", json_data); + // return json_data; // データを返す + // } catch (error) { + // console.error("エラーが発生しました:", error); + // throw error; // 必要に応じてエラーを再スロー + // } + // } + + function load_QuizQuestion(url, callback) { + const get_url = url + "/api/play/quiz"; + const xhr = new XMLHttpRequest(); + + xhr.open("GET", get_url, true); + xhr.setRequestHeader("Content-Type", "application/json"); + + xhr.onreadystatechange = function () { + if (xhr.readyState === 4) { // 完了 + if (xhr.status >= 200 && xhr.status < 300) { + try { + const data = JSON.parse(xhr.responseText); + callback(null, data); // データをコールバックで返す + } catch (error) { + callback(error, null); + } + } else { + callback(new Error(`ステータスエラー: ${xhr.status}`), null); + } + } + }; + + xhr.onerror = function () { + callback(new Error("ネットワークエラー"), null); + }; + + xhr.send(); + } + + + + + console.log("helloWorldejfo;iejfejf;oaewjgo;ifewjgo;wjgo;jeawgo;eajwgojeg;je\n"); + // console.log(load_QuizQuestion("http://172.23.0.5:5001")) + // function quiz_set(question_text,selects,answer_number){ + + // let date = { + // "question": "次のうち、太陽系に存在する惑星はどれですか?", + // "selects": [ + // "シリウス", + // "地球", + // "アンドロメダ", + // "アルタイル" + // ], + // "answer":2 + // }; + // fetch("api/play/quiz",method("GET")){ + + // } + // console.log(date); + // } + /** * 質問を書き込む * @param question_text { string } 質問文 @@ -214,10 +331,36 @@ document.addEventListener("DOMContentLoaded", () => { correctAnswer = selects[answer_number]; } - quiz_set(question_date[0]["question"], + + function get_quiz_set(question_text,selects,answer_number) + { + console.log(`dateLoading-:-${typeof(question_text)}, \n ${selects}, \n ${answer_number}`); + quiz_qustion.textContent = question_text; + const quiz_contents = quiz_select_options.item(0).children; + for(var i = 0; i < 4;i++) + { + quiz_contents[i].textContent = selects[i]["S"]; + } + correctAnswer = selects[answer_number]; + } + + // 使用例 + load_QuizQuestion("http://localhost:5001", (error, data) => { + if (error) { + console.error("エラー:", error); + } else { + console.log("取得したクイズデータ:", data); + + get_quiz_set(data["game"]["question"]["S"],data["game"]["selects"]["L"],data["game"]["answer_idx"]["N"]); + } + }); + /*quiz_set(question_date[0]["question"], question_date[0]["selects"], - question_date[0]["answer"]); + question_date[0]["answer"]);*/ + // let get_question = load_QuizQuestion("http://localhost:5001"); + // console.log(get_question); + // get_quiz_set(get_question["game"]["question"],get_question["game"]["selects"]["L"],get_question["game"]["answer_idx"]["N"]); //================================================================================================================================================================ @@ -359,7 +502,7 @@ document.addEventListener("DOMContentLoaded", () => { }); }); - + /** * 正解の場所かどうかを判定する処理 * @param touchPos 要素数2の1次元の配列 @@ -589,10 +732,10 @@ document.addEventListener("DOMContentLoaded", () => { }); - //テスト用のプログラムを組み込んでいる - quiz_set(question_date[0]["question"], - question_date[0]["selects"], - question_date[0]["answer"]); + // //テスト用のプログラムを組み込んでいる + // quiz_set(question_date[0]["question"], + // question_date[0]["selects"], + // question_date[0]["answer"]); let quiz_number diff --git a/frontend/index.html b/frontend/index.html index 81079cc..02242e3 100644 --- a/frontend/index.html +++ b/frontend/index.html @@ -132,7 +132,7 @@

クイズ

- + From 0cacacb6ae3e3920d9be583910b2a3d01db1c2fc Mon Sep 17 00:00:00 2001 From: tetsushi33 Date: Sun, 8 Dec 2024 02:18:50 +0900 Subject: [PATCH 45/51] define play_search_diff, create_search_diff --- backend/controller/game_controller.py | 97 ++++++++++++---- backend/engine/dynamo_client.py | 88 ++++++++++----- backend/engine/s3_client.py | 156 +++++++++++++++++--------- backend/router.py | 11 +- 4 files changed, 248 insertions(+), 104 deletions(-) diff --git a/backend/controller/game_controller.py b/backend/controller/game_controller.py index e6e6bae..5a7aed2 100644 --- a/backend/controller/game_controller.py +++ b/backend/controller/game_controller.py @@ -1,16 +1,15 @@ from flask import make_response, jsonify, request from engine.dynamo_client import DynamoClient import hashlib +from engine.s3_client import S3Client #from werkzeug.utils import secure_filename -#from dynamo_client import save_file_metadata -from engine.s3_client import upload_to_s3 -#from dotenv import load_dotenv class GameController: def __init__(self): self.table_name = "minirun_game_table" self.db_client = DynamoClient(table_name="minirun_game_table") + self.s3_client = S3Client() # S3専用クラスを利用 def get_game_random(self): response = self.db_client.get_random() @@ -98,30 +97,45 @@ def create_intro(self): except Exception as e: return make_response(jsonify({'code': 500, 'message': str(e)}), 500) - def create_diffshot(self): - data = request.get_json() - picture_data = data['picture_data'] - picture_data_answer = data['picture_data_answer'] - answer_points = data['answer_points'] - last_id = self.get_last_id() - data['id'] = last_id + 1 + def create_search_diff(self): + try: + # フォームデータとファイルを取得 + images = request.files.getlist('images') # 画像ファイルのリスト + answer_idx = request.form.get('answer_idx') # 正解の番号(request.filesを操作した後にrequest.get_json()を使用するとエラーが発生する可能性があるらしい) - # バリデーションを実装 - if not isinstance(picture_data, str) or not music_title_answer.strip(): - return make_response(jsonify({'code': 400, 'message': 'Invalid music_title_answer'}), 400) - if not music_data: - return make_response(jsonify({'code': 400, 'message': 'Invalid music_data'}), 400) + # バリデーションチェック + if not images or len(images) != 9: + return make_response(jsonify({'code': 400, 'message': 'Invalid images list'}), 400) + if answer_idx is None or not answer_idx.isdigit() or not (0 <= int(answer_idx) < 9): + return make_response(jsonify({'code': 400, 'message': 'Invalid correct index'}), 400) + answer_idx = int(answer_idx) - # DBに保存 - try: - if self.db_client.create_diffshot(data): - return make_response(jsonify({'code': 200, 'message': 'Diffshot created successfully'}), 200) + # 画像ファイルをS3に保存 + image_hashes = [] + for image in images: + #filename = secure_filename(image.filename) + filename = image.filename + file_hash = hashlib.sha256(filename.encode('utf-8')).hexdigest() + # S3にアップロード + self.s3_client.upload_fileobj(image, file_hash) + image_hashes.append(file_hash) + + # DynamoDBに保存するデータを作成 + data_to_save = { + 'id': self.get_last_id() + 1, # 新しいID + 'genre': 'search_diff', # ジャンルを指定 + 'image_hashes': image_hashes, # 画像ハッシュリスト + 'answer_idx': answer_idx # 正解のインデックス + } + + # データベースに保存 + if self.db_client.create_search_diff(data_to_save): + return make_response(jsonify({'code': 200, 'message': 'Search diff created successfully'}), 200) else: - return make_response(jsonify({'code': 500, 'message': 'Failed to create diffshot'}), 500) + return make_response(jsonify({'code': 500, 'message': 'Failed to create search diff'}), 500) except Exception as e: return make_response(jsonify({'code': 500, 'message': str(e)}), 500) - def play_quiz(self): @@ -175,6 +189,47 @@ def play_intro(self): 'message': str(e) }), 500) + def play_search_diff(self): + try: + # データベースからランダムに問題を取得 + response = self.db_client.get_random_2(genre="search_diff") + if response: + # ハッシュ値リストを取得 + image_hashes = response.get("image_hashes", []) + answer_idx = response.get("answer_idx", -1) + # ハッシュ値を元にS3から画像データを取得 + image_data_list = [] + for image_hash in image_hashes: + try: + image_data = self.s3_client.get_s3_file_data(image_hash) + image_data_list.append(image_data) + except Exception as s3_error: + print(f"Error getting image data from S3: {e}") + return make_response(jsonify({ + 'code': 500, + 'message': f"Failed to retrieve image for hash: {image_hash}" + }), 500) + + search_diff_data = { + "images": image_data_list, # 画像データリスト + "answer_idx": answer_idx + } + return make_response(jsonify({ + 'code': 200, + 'game_content': search_diff_data + }), 200) + else: + return make_response(jsonify({ + 'code': 404, + 'message': 'No search_diff found' + }), 404) + except Exception as e: + return make_response(jsonify({ + 'code': 500, + 'message': str(e) + }), 500) + + def play_diffshot(self): try: # データベースからランダムに問題を取得 diff --git a/backend/engine/dynamo_client.py b/backend/engine/dynamo_client.py index bcc611e..8881be3 100644 --- a/backend/engine/dynamo_client.py +++ b/backend/engine/dynamo_client.py @@ -20,11 +20,16 @@ def get_all(self) -> list: def get_random(self) -> None: '''対象のテーブルからランダムに1件レコードを取得するメソッド ''' - response_all = self.db.scan(TableName=self.table_name) - valid_keys = [item['id']['N'] for item in response_all['Items']] - random_key = random.choice(valid_keys) - response = self.db.get_item(TableName=self.table_name, Key={"id": {"N": str(random_key)}}) - return response.get('Item') + try: + response_all = self.db.scan(TableName=self.table_name) + items = response_all.get('Items', []) + if not items: + return None + random_item = random.choice(items) + return random_item + except Exception as e: + print(f"Error retrieving random item: {e}") + return None def get_random_2(self, genre: str) -> None: '''指定されたジャンルの中からランダムに1件レコードを取得するメソッド''' @@ -34,7 +39,9 @@ def get_random_2(self, genre: str) -> None: FilterExpression="genre = :genre", ExpressionAttributeValues={":genre": {"S": genre}} ) - + items = response_all.get('Items', []) + if not items: + return None if genre == "quiz": # 有効なキーを取得 valid_keys = [item['id']['N'] for item in response_all['Items']] @@ -56,16 +63,19 @@ def get_random_2(self, genre: str) -> None: "file_hash": file_hash, "original_name": original_name, } + if genre == "search_diff": + selected_item = random.choice(items) + # 画像データのハッシュリストと正解インデックスを取得 + image_hashes = [hash_item["S"] for hash_item in selected_item['image_hashes']['L']] + answer_idx = int(selected_item['answer_idx']['N']) - - - # 有効なキーを取得 - valid_keys = [item['id']['N'] for item in items] - random_key = random.choice(valid_keys) - - # ランダムに選ばれたキーのアイテムを取得 - response = self.db.get_item(TableName=self.table_name, Key={"id": {"N": str(random_key)}}) - return response.get('Item') + # 必要なデータを返す + return { + "image_hashes": image_hashes, + "answer_idx": answer_idx + } + else: + return None def scan(self, **kwargs): @@ -74,15 +84,18 @@ def scan(self, **kwargs): def create_quiz(self, data: dict) -> None: '''対象のテーブルにクイズデータを登録するメソッド ''' - client = boto3.client('dynamodb') # ここで良いかは不明 - response = client.put_item(TableName=self.table_name, Item={ - 'id': {'N': str(data['id'])}, - 'question': {'S': data['question']}, - 'selects': {'L': [{'S': s} for s in data['selects']]}, - 'answer_idx': {'N': str(data['answer_idx'])}, - 'likes': {'N': '0'} - }) - return True if response['ResponseMetadata']['HTTPStatusCode'] == 200 else False + try: + response = self.db.put_item(TableName=self.table_name, Item={ + 'id': {'N': str(data['id'])}, + 'question': {'S': data['question']}, + 'selects': {'L': [{'S': s} for s in data['selects']]}, + 'answer_idx': {'N': str(data['answer_idx'])}, + 'likes': {'N': '0'} + }) + return True if response['ResponseMetadata']['HTTPStatusCode'] == 200 else False + except Exception as e: + print(f"Error saving data to DynamoDB: {e}") + return False def create_intro(self, data: dict) -> None: '''対象のテーブルにイントロデータを登録するメソッド @@ -120,11 +133,28 @@ def save_file_metadata(self, data: dict, file_hash: str, original_name: str) -> return False - def create_diffshot(self, data: dict) -> None: - '''対象のテーブルにディフショットデータを登録するメソッド - ''' - client = boto3.client('dynamodb') - ## 未 + def create_search_diff(self, data: dict) -> bool: + """ + DynamoDBに間違い画像選択ゲームのデータを保存する + """ + try: + item = { + 'id': {'N': str(data['id'])}, + 'genre': {'S': data['genre']}, + 'image_hashes': {'L': [{'S': hash} for hash in data['image_hashes']]}, + 'answer_idx': {'N': str(data['answer_idx'])}, + 'likes': {'N': '0'} # 初期値として0を設定 + } + response = self.db.put_item( + TableName=self.table_name, + #Item=data + Item=item + ) + # ステータスコードが200であれば成功 + return response['ResponseMetadata']['HTTPStatusCode'] == 200 + except Exception as e: + print(f"Error saving data to DynamoDB: {e}") + return False diff --git a/backend/engine/s3_client.py b/backend/engine/s3_client.py index 01c17ae..5ea2e81 100644 --- a/backend/engine/s3_client.py +++ b/backend/engine/s3_client.py @@ -5,59 +5,113 @@ # .envファイルを読み込む load_dotenv() -# boto3クライアントの初期化 -s3_client = boto3.client( - "s3", - aws_access_key_id=os.getenv("S3_ACCESS_KEY"), - aws_secret_access_key=os.getenv("S3_SECRET_KEY"), - endpoint_url=os.getenv("S3_ENDPOINT") # MinIOを使用する場合に必要 -) -def upload_to_s3(file, file_hash, content_type): - """ - S3にファイルをアップロードする関数 - - Args: - file: アップロードするファイルオブジェクト - file_hash: S3に保存するオブジェクトのキー(ユニークな名前) - content_type: ファイルのContent-Type +class S3Client: + def __init__(self): + """ + S3クライアントを初期化し、バケット名を設定 + """ + self.s3_client = boto3.client( + "s3", + #aws_access_key_id=os.getenv("S3_ACCESS_KEY"), + #aws_secret_access_key=os.getenv("S3_SECRET_KEY"), + #endpoint_url=os.getenv("S3_ENDPOINT") # 必要に応じて指定(MinIOやローカルS3の場合) + ) + self.bucket_name = os.getenv("S3_BUCKET") # 環境変数からバケット名を取得 - Raises: - Exception: アップロードが失敗した場合 - """ - try: - # 環境変数からS3バケットを取得 - s3_bucket = os.getenv("S3_BUCKET") + def upload_fileobj(self, file, file_key): + """ + S3にファイルをアップロードするメソッド - # S3にファイルをアップロード - s3_client.upload_fileobj( - file, - s3_bucket, - file_hash, # ファイル名の代わりにハッシュを使用 - ExtraArgs={"ContentType": content_type} - ) - print(f"File uploaded successfully to S3 with key: {file_hash}") - except Exception as e: - print(f"Error uploading file to S3: {e}") - raise e - -def get_s3_file_url(file_key: str) -> str: - """ - S3のファイルにアクセスするための署名付きURLを生成する関数 + Args: + file: アップロードするファイルオブジェクト + file_key: S3に保存するオブジェクトのキー - Args: - file_key (str): S3に格納されているオブジェクトのキー + Raises: + Exception: アップロード失敗時に例外を発生 + """ + try: + self.s3_client.upload_fileobj( + file, + self.bucket_name, # バケット名は内部で指定 + file_key, + ExtraArgs={'ContentType': file.content_type} # MIMEタイプを指定 + ) + print(f"Uploaded {file_key} to {self.bucket_name}") + except Exception as e: + print(f"Failed to upload file: {e}") + raise e - Returns: - str: 署名付きURL - """ - try: - url = s3_client.generate_presigned_url( - 'get_object', - Params={'Bucket': os.getenv("S3_BUCKET"), 'Key': file_key}, - ExpiresIn=3600 # URLの有効期限(秒単位) - ) - return url - except Exception as e: - print(f"Error generating S3 presigned URL: {e}") - return "" \ No newline at end of file +## boto3クライアントの初期化 +#s3_client = boto3.client( +# "s3", +# #aws_access_key_id=os.getenv("S3_ACCESS_KEY"), +# #aws_secret_access_key=os.getenv("S3_SECRET_KEY"), +# #endpoint_url=os.getenv("S3_ENDPOINT") # ローカル時のみ +#) +# +#def upload_to_s3(file, file_hash, content_type): +# """ +# S3にファイルをアップロードする関数 +# +# Args: +# file: アップロードするファイルオブジェクト +# file_hash: S3に保存するオブジェクトのキー(ユニークな名前) +# content_type: ファイルのContent-Type +# +# Raises: +# Exception: アップロードが失敗した場合 +# """ +# try: +# # 環境変数からS3バケットを取得 +# s3_bucket = os.getenv("S3_BUCKET") +# +# # S3にファイルをアップロード +# s3_client.upload_fileobj( +# file, +# s3_bucket, +# file_hash, # ファイル名の代わりにハッシュを使用 +# ExtraArgs={"ContentType": content_type} +# ) +# print(f"File uploaded successfully to S3 with key: {file_hash}") +# except Exception as e: +# print(f"Error uploading file to S3: {e}") +# raise e +# +#def get_s3_file_url(file_key: str) -> str: +# """ +# S3のファイルにアクセスするための署名付きURLを生成する関数 +# +# Args: +# file_key (str): S3に格納されているオブジェクトのキー +# +# Returns: +# str: 署名付きURL +# """ +# try: +# url = s3_client.generate_presigned_url( +# 'get_object', +# Params={'Bucket': os.getenv("S3_BUCKET"), 'Key': file_key}, +# ExpiresIn=3600 # URLの有効期限(秒単位) +# ) +# return url +# except Exception as e: +# print(f"Error generating S3 presigned URL: {e}") +# return "" +# +#def upload_fileobj(self, file, bucket_name, file_hash): +# """ +# S3にファイルをアップロードする +# """ +# try: +# self.s3_client.upload_fileobj( +# file, +# bucket_name, +# file_hash, +# ExtraArgs={'ContentType': file.content_type} +# ) +# print(f"Uploaded {file_hash} to {bucket_name}") +# except Exception as e: +# print(f"Failed to upload file: {e}") +# raise e +# \ No newline at end of file diff --git a/backend/router.py b/backend/router.py index e35f9a2..4b696ee 100644 --- a/backend/router.py +++ b/backend/router.py @@ -43,10 +43,10 @@ def api_create_quiz(): def api_create_intro(): return controller.create_intro() -@router.route("/api/create/diffshot", methods=['POST']) +@router.route("/api/create/searchdiff", methods=['POST']) @logger.http_request_logging -def api_create_diffshot(): - return controller.create_diffshot() +def api_create_search_diff(): + return controller.create_search_diff() @router.route("/api/play/quiz", methods=['GET']) @logger.http_request_logging @@ -58,6 +58,11 @@ def api_play_quiz(): def api_play_intro(): return controller.play_intro() +@router.route("/api/play/searchdiff", methods=['GET']) +@logger.http_request_logging +def api_play_search_diff(): + return controller.play_search_diff() + @router.after_request def after_request(response): From c63b6603ff1f17156c422a7cdf02e3b2274842ab Mon Sep 17 00:00:00 2001 From: Fuchs0101 Date: Sun, 8 Dec 2024 03:16:47 +0900 Subject: [PATCH 46/51] =?UTF-8?q?=E3=82=AF=E3=82=A4=E3=82=BA=E3=83=97?= =?UTF-8?q?=E3=83=AC=E3=82=A4=E7=94=BB=E9=9D=A2=E3=81=8C=E5=8B=95=E4=BD=9C?= =?UTF-8?q?=E3=81=99=E3=82=8B=E3=82=88=E3=81=86=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/game.js | 235 +++++++++++--------------------------------- frontend/index.html | 11 ++- 2 files changed, 66 insertions(+), 180 deletions(-) diff --git a/frontend/game.js b/frontend/game.js index ceaf7cd..bc967b9 100644 --- a/frontend/game.js +++ b/frontend/game.js @@ -20,9 +20,10 @@ document.addEventListener("DOMContentLoaded", () => { const gameKindOptions = document.querySelectorAll(".gamekind-option"); - //game + //quiz const quiz_select_options = document.querySelectorAll(".quiz_selects"); const quiz_qustion = document.getElementById("question_text"); + const quiz_result = document.getElementById("quiz-judge"); const statusText = document.querySelector(".status"); const answerText = document.querySelector(".answer"); @@ -61,28 +62,48 @@ document.addEventListener("DOMContentLoaded", () => { } } - - //クイズデータ - let question_date = [ - { - "question": "次のうち、太陽fejfioewajf;owjfo;eiwajfoi;する惑星はどれですか?", - "selects": [ - "シリウス", - "地球", - "アンドロメダ", - "アルタイル" - ], - "answer": 2 - }, - { - "question": "別の質問例", - "selects": ["選択肢1", "選択肢2", "選択肢3", "選択肢4"], - "answer": 1 - }, - ] - let correctAnswer = "nullHello"; - console.log(question_date); + + function loadQuizQuestion(url, callback) { + const getUrl = url + "/api/play/quiz"; + + fetch(getUrl, { + method: "GET", + }) + .then(response => { + if (!response.ok) { + throw new Error(`ステータスエラー: ${response.status}`); + } + return response.json(); // JSONを解析 + }) + .then(data => { + callback(null, data); // データをコールバックで返す + }) + .catch(error => { + callback(error, null); // エラーをコールバックで返す + }); + } + + + + /** + * 質問を書き込む + * @param question_text { string } 質問文 + * @param selects (list-string)選択肢で表示するもの + * @param answer_number (int)selectsでの連番-何番目の選択肢を正解にするか、 + * その名前のdisplayを表示する + */ + + function set_quiz(question_text,selects,answer_number) + { + quiz_qustion.textContent = question_text; + const quiz_contents = quiz_select_options.item(0).children; + for(var i = 0; i < 4;i++) + { + quiz_contents[i].textContent = selects[i]; + } + correctAnswer = selects[answer_number]; + } function rd(max){ @@ -125,7 +146,18 @@ document.addEventListener("DOMContentLoaded", () => { //game-play else if (display == "quiz") { + loadQuizQuestion("http://localhost:5001", (error, data) => { + if (error) { + console.error("エラー:", error); + } else { + console.log("取得したクイズデータ:", data); + + set_quiz(data["game_content"]["question"],data["game_content"]["selects"],data["game_content"]["answer_idx"]); + } + }); quiz_Screen.classList.remove("d-none"); + + } else if (display == "differentPoint") { @@ -192,7 +224,6 @@ document.addEventListener("DOMContentLoaded", () => { //============================================================================================================================================ quiz_select_options.forEach(option => { - let faild = false; console.log(option[0]); option.addEventListener("click", (event) => { const selectedAnswer = event.target.textContent; @@ -200,15 +231,17 @@ document.addEventListener("DOMContentLoaded", () => { // 判定処理 if (selectedAnswer === correctAnswer) { - event.target.style.color = "#28a745"; + console.log("正解"); + quiz_result.textContent = "正解!" + quiz_result.style.color = "#28a745"; } else { console.log("不正解"); - event.target.style.color = "#dc3545"; - faild = true; + quiz_result.textContent = "残念、不正解…" + quiz_result.style.color = "#dc3545"; } @@ -218,150 +251,6 @@ document.addEventListener("DOMContentLoaded", () => { displayLoadRequest("result"); }); }); - - /** - * 返り値 - * { - * "question": "次のうち、太陽系に存在する惑星はどれですか?", - * "selects": [ - * "シリウス", - * "地球", - * "アンドロメダ", - * "アルタイル" - * ], - * "answer":2 - * } - */ - // async function load_QuizQuestion(url) { - // const get_url = url + "/api/play/random"; - // try { - // const request = await fetch(get_url, { - // method: "GET", - // headers: { - // "Content-Type": "application/json", - // }, - // }) - // .then(quizDate){ - // console.log() - // } - - // // ステータスコードのチェック - // if (!request.ok) { - // throw new Error(`レスポンスエラー: ステータス ${request.status}`); - // } - - // // JSON データを取得 - // const json_data = await request.json(); - // console.log("取得したクイズデータ:", json_data); - // return json_data; // データを返す - // } catch (error) { - // console.error("エラーが発生しました:", error); - // throw error; // 必要に応じてエラーを再スロー - // } - // } - - function load_QuizQuestion(url, callback) { - const get_url = url + "/api/play/quiz"; - const xhr = new XMLHttpRequest(); - - xhr.open("GET", get_url, true); - xhr.setRequestHeader("Content-Type", "application/json"); - - xhr.onreadystatechange = function () { - if (xhr.readyState === 4) { // 完了 - if (xhr.status >= 200 && xhr.status < 300) { - try { - const data = JSON.parse(xhr.responseText); - callback(null, data); // データをコールバックで返す - } catch (error) { - callback(error, null); - } - } else { - callback(new Error(`ステータスエラー: ${xhr.status}`), null); - } - } - }; - - xhr.onerror = function () { - callback(new Error("ネットワークエラー"), null); - }; - - xhr.send(); - } - - - - - console.log("helloWorldejfo;iejfejf;oaewjgo;ifewjgo;wjgo;jeawgo;eajwgojeg;je\n"); - // console.log(load_QuizQuestion("http://172.23.0.5:5001")) - // function quiz_set(question_text,selects,answer_number){ - - // let date = { - // "question": "次のうち、太陽系に存在する惑星はどれですか?", - // "selects": [ - // "シリウス", - // "地球", - // "アンドロメダ", - // "アルタイル" - // ], - // "answer":2 - // }; - // fetch("api/play/quiz",method("GET")){ - - // } - // console.log(date); - // } - - /** - * 質問を書き込む - * @param question_text { string } 質問文 - * @param selects (list-string)選択肢で表示するもの - * @param answer_number (int)selectsでの連番-何番目の選択肢を正解にするか、 - * その名前のdisplayを表示する - */ - function quiz_set(question_text,selects,answer_number) - { - console.log(`dateLoading-:-${typeof(question_text)}, \n ${selects}, \n ${answer_number}`); - quiz_qustion.textContent = question_text; - const quiz_contents = quiz_select_options.item(0).children; - for(var i = 0; i < 4;i++) - { - quiz_contents[i].textContent = selects[i]; - } - correctAnswer = selects[answer_number]; - } - - - function get_quiz_set(question_text,selects,answer_number) - { - console.log(`dateLoading-:-${typeof(question_text)}, \n ${selects}, \n ${answer_number}`); - quiz_qustion.textContent = question_text; - const quiz_contents = quiz_select_options.item(0).children; - for(var i = 0; i < 4;i++) - { - quiz_contents[i].textContent = selects[i]["S"]; - } - correctAnswer = selects[answer_number]; - } - - // 使用例 - load_QuizQuestion("http://localhost:5001", (error, data) => { - if (error) { - console.error("エラー:", error); - } else { - console.log("取得したクイズデータ:", data); - - get_quiz_set(data["game"]["question"]["S"],data["game"]["selects"]["L"],data["game"]["answer_idx"]["N"]); - } - }); - /*quiz_set(question_date[0]["question"], - question_date[0]["selects"], - question_date[0]["answer"]);*/ - - // let get_question = load_QuizQuestion("http://localhost:5001"); - // console.log(get_question); - // get_quiz_set(get_question["game"]["question"],get_question["game"]["selects"]["L"],get_question["game"]["answer_idx"]["N"]); - //================================================================================================================================================================ //============================================================================================================================================ @@ -741,11 +630,7 @@ document.addEventListener("DOMContentLoaded", () => { let quiz_number // 次の問題へ(ここでは単純にホーム画面に戻る処理) nextButton.addEventListener("click", () => { - displayLoadRequest("home"); - - quiz_set(question_date[0]["question"], - question_date[0]["selects"], - question_date[0]["answer"]); + displayLoadRequest("quiz"); }); // やめる(ホーム画面に戻る) diff --git a/frontend/index.html b/frontend/index.html index 02242e3..8c950bf 100644 --- a/frontend/index.html +++ b/frontend/index.html @@ -50,12 +50,12 @@

間違い探し

クイズ

-

任天堂・・

+

- - - - + + + +
@@ -79,6 +79,7 @@

クイズ

+

From af25618d8b2342735bb1f127dfa867b933903ab8 Mon Sep 17 00:00:00 2001 From: tetsushi33 Date: Sun, 8 Dec 2024 03:18:33 +0900 Subject: [PATCH 47/51] define create_search_diff, play_search_diff, others --- backend/controller/game_controller.py | 14 ++++---- backend/engine/dynamo_client.py | 49 +++++++++++++-------------- 2 files changed, 31 insertions(+), 32 deletions(-) diff --git a/backend/controller/game_controller.py b/backend/controller/game_controller.py index 5a7aed2..55c415d 100644 --- a/backend/controller/game_controller.py +++ b/backend/controller/game_controller.py @@ -31,9 +31,11 @@ def create_quiz(self): data = request.get_json() question = data['question'] selects = data['selects'] - answer_idx = data['answer_idx'] + answer_idx = data['answer_idx'] - 1 + data['answer_idx'] = answer_idx - 1 last_id = self.get_last_id() data['id'] = last_id + 1 + data['genre'] = 'quiz' # バリデーションを実装 if not isinstance(question, str) or not question.strip(): @@ -106,10 +108,10 @@ def create_search_diff(self): # バリデーションチェック if not images or len(images) != 9: return make_response(jsonify({'code': 400, 'message': 'Invalid images list'}), 400) - if answer_idx is None or not answer_idx.isdigit() or not (0 <= int(answer_idx) < 9): + if answer_idx is None or not answer_idx.isdigit() or not (0 <= int(answer_idx) - 1 < 9): return make_response(jsonify({'code': 400, 'message': 'Invalid correct index'}), 400) - answer_idx = int(answer_idx) + answer_idx = int(answer_idx) - 1 # 画像ファイルをS3に保存 image_hashes = [] @@ -145,9 +147,9 @@ def play_quiz(self): response = self.db_client.get_random_2(genre="quiz") if response: quiz_data = { - "question": response.get('question', {}).get('S', ''), - "selects": [select.get('S', '') for select in response.get('selects', {}).get('L', [])], - "answer_idx": int(response.get('answer_idx', {}).get('N', -1)) + "question": response.get('question', {}).get('S', ''), + "selects": [select.get('S', '') for select in response.get('selects', {}).get('L', [])], + "answer_idx": int(response.get('answer_idx', {}).get('N', -1)) } return make_response(jsonify({ 'code': 200, diff --git a/backend/engine/dynamo_client.py b/backend/engine/dynamo_client.py index 8881be3..61d3801 100644 --- a/backend/engine/dynamo_client.py +++ b/backend/engine/dynamo_client.py @@ -108,31 +108,6 @@ def create_intro(self, data: dict) -> None: 'likes': {'N': '0'} }) - def save_file_metadata(self, data: dict, file_hash: str, original_name: str) -> bool: - """ - DynamoDBにファイルのメタデータを保存する関数 - - Args: - file_hash (str): ファイルのハッシュ値 - original_name (str): 元のファイル名 - - Returns: - bool: 成功した場合はTrue、失敗した場合はFalse - """ - try: - client = boto3.client('dynamodb') - # DynamoDBにデータを登録 - response = client.put_item(Item={ - 'id': {'N': str(data['id'])}, - 'file_hash': file_hash, - 'original_name': original_name - }) - return response.get('ResponseMetadata', {}).get('HTTPStatusCode') == 200 - except Exception as e: - print(f"Error saving file metadata to DynamoDB: {e}") - return False - - def create_search_diff(self, data: dict) -> bool: """ DynamoDBに間違い画像選択ゲームのデータを保存する @@ -156,6 +131,28 @@ def create_search_diff(self, data: dict) -> bool: print(f"Error saving data to DynamoDB: {e}") return False - + def save_file_metadata(self, data: dict, file_hash: str, original_name: str) -> bool: + """ + DynamoDBにファイルのメタデータを保存する関数 + + Args: + file_hash (str): ファイルのハッシュ値 + original_name (str): 元のファイル名 + + Returns: + bool: 成功した場合はTrue、失敗した場合はFalse + """ + try: + client = boto3.client('dynamodb') + # DynamoDBにデータを登録 + response = client.put_item(Item={ + 'id': {'N': str(data['id'])}, + 'file_hash': file_hash, + 'original_name': original_name + }) + return response.get('ResponseMetadata', {}).get('HTTPStatusCode') == 200 + except Exception as e: + print(f"Error saving file metadata to DynamoDB: {e}") + return False From 67df3b4c3214f52b73ba18e2b46c06875edba9bb Mon Sep 17 00:00:00 2001 From: Fuchs0101 Date: Sun, 8 Dec 2024 03:39:46 +0900 Subject: [PATCH 48/51] =?UTF-8?q?=E3=83=90=E3=82=B0=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/game.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/game.js b/frontend/game.js index 140412b..5a78840 100644 --- a/frontend/game.js +++ b/frontend/game.js @@ -121,7 +121,7 @@ document.addEventListener("DOMContentLoaded", () => { function displayLoadRequest(display) { - createModeScreen.classList.add("d-none"); + createScreen.classList.add("d-none"); playScreen.classList.add("d-none"); if(gameMode == "create"){ createScreen.classList.remove("d-none"); From d1795115a6efda831f1e1b7b53937819a49bdf53 Mon Sep 17 00:00:00 2001 From: tetsushi33 Date: Sun, 8 Dec 2024 04:09:32 +0900 Subject: [PATCH 49/51] =?UTF-8?q?create=5Fquiz=E3=81=AB'genre':=20{'S':=20?= =?UTF-8?q?'quiz'}?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/controller/game_controller.py | 3 ++- backend/engine/dynamo_client.py | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/backend/controller/game_controller.py b/backend/controller/game_controller.py index e6e6bae..c90824c 100644 --- a/backend/controller/game_controller.py +++ b/backend/controller/game_controller.py @@ -32,7 +32,8 @@ def create_quiz(self): data = request.get_json() question = data['question'] selects = data['selects'] - answer_idx = data['answer_idx'] + answer_idx = data['answer_idx'] - 1 + data['answer_idx'] = answer_idx - 1 last_id = self.get_last_id() data['id'] = last_id + 1 diff --git a/backend/engine/dynamo_client.py b/backend/engine/dynamo_client.py index bcc611e..120d68e 100644 --- a/backend/engine/dynamo_client.py +++ b/backend/engine/dynamo_client.py @@ -80,7 +80,8 @@ def create_quiz(self, data: dict) -> None: 'question': {'S': data['question']}, 'selects': {'L': [{'S': s} for s in data['selects']]}, 'answer_idx': {'N': str(data['answer_idx'])}, - 'likes': {'N': '0'} + 'likes': {'N': '0'}, + 'genre': {'S': 'quiz'} }) return True if response['ResponseMetadata']['HTTPStatusCode'] == 200 else False From 381b99ecd429ec38ba20e45af2a97837dcc3b377 Mon Sep 17 00:00:00 2001 From: tetsushi33 Date: Sun, 8 Dec 2024 04:13:11 +0900 Subject: [PATCH 50/51] =?UTF-8?q?answer=5Fidx=E3=82=92-1=E3=80=81'genre':?= =?UTF-8?q?=20{'S':=20'quiz'}=E3=82=92=E8=BF=BD=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/controller/game_controller.py | 1 - backend/engine/dynamo_client.py | 3 ++- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/backend/controller/game_controller.py b/backend/controller/game_controller.py index 55c415d..454f980 100644 --- a/backend/controller/game_controller.py +++ b/backend/controller/game_controller.py @@ -35,7 +35,6 @@ def create_quiz(self): data['answer_idx'] = answer_idx - 1 last_id = self.get_last_id() data['id'] = last_id + 1 - data['genre'] = 'quiz' # バリデーションを実装 if not isinstance(question, str) or not question.strip(): diff --git a/backend/engine/dynamo_client.py b/backend/engine/dynamo_client.py index 61d3801..bff642f 100644 --- a/backend/engine/dynamo_client.py +++ b/backend/engine/dynamo_client.py @@ -90,7 +90,8 @@ def create_quiz(self, data: dict) -> None: 'question': {'S': data['question']}, 'selects': {'L': [{'S': s} for s in data['selects']]}, 'answer_idx': {'N': str(data['answer_idx'])}, - 'likes': {'N': '0'} + 'likes': {'N': '0'}, + 'genre': {'S': 'quiz'} }) return True if response['ResponseMetadata']['HTTPStatusCode'] == 200 else False except Exception as e: From c6def86ad3f37d52d4a4a569fbcc62c5537e72c1 Mon Sep 17 00:00:00 2001 From: Fuchs0101 Date: Sun, 8 Dec 2024 12:07:22 +0900 Subject: [PATCH 51/51] =?UTF-8?q?=E3=83=87=E3=82=B0=E3=83=AC=E4=BF=AE?= =?UTF-8?q?=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/game.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/frontend/game.js b/frontend/game.js index 5a78840..82c11fc 100644 --- a/frontend/game.js +++ b/frontend/game.js @@ -151,6 +151,7 @@ document.addEventListener("DOMContentLoaded", () => { //game-play else if (display == "quiz") { + loadQuizQuestion("http://localhost:5001", (error, data) => { if (error) { console.error("エラー:", error); @@ -200,7 +201,6 @@ document.addEventListener("DOMContentLoaded", () => { else if (display == "game_select") { selectGameScreen.classList.remove("d-none"); - displayLoadRequest("create_quiz") } else if (display == "game_mode") @@ -224,10 +224,12 @@ document.addEventListener("DOMContentLoaded", () => { }); playButton.addEventListener("click",()=>{ + console.log("呼ばれてる1") displayLoadRequest("game_select"); }); - createButton.addEventListener('click', function () { + createButton.addEventListener('click',()=>{ + console.log("呼ばれてる2") displayLoadRequest("create_quiz"); });