Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
42 commits
Select commit Hold shift + click to select a range
ded552f
setup development environment with Docker Compose
biplala Dec 2, 2024
e0d2c45
refactor/display-Set
Yukkurisiteikitai Dec 3, 2024
c295a6b
set GameMenu&GameKind
Yukkurisiteikitai Dec 3, 2024
d7a5977
setREADME-template
Yukkurisiteikitai Dec 4, 2024
df2a316
perf/mockup-quiz
Yukkurisiteikitai Dec 4, 2024
0864746
peft/game-selectSystem
Yukkurisiteikitai Dec 4, 2024
eea20c8
peft/quiz-question-easy
Yukkurisiteikitai Dec 4, 2024
10f8f0f
perf/setQuiz-Question
Yukkurisiteikitai Dec 4, 2024
7e47750
I Don't know What do division
Yukkurisiteikitai Dec 5, 2024
c0aa97f
implement base of backend application
biplala Dec 5, 2024
0683e3d
setDifferentPoint
Yukkurisiteikitai Dec 5, 2024
e042088
Add intro quiz files (index.html, script.js,style.css)
nozo120 Dec 5, 2024
ec159e0
Add intro quiz frontend
nozo120 Dec 5, 2024
78ce24d
Add intro quiz files (index.html)
nozo120 Dec 5, 2024
18268a3
future/set collision
Yukkurisiteikitai Dec 6, 2024
47f4f20
fix/changeName-FindDifference.js
Yukkurisiteikitai Dec 6, 2024
9b36bf4
bug/canvas-don'tLoadImageFile
Yukkurisiteikitai Dec 6, 2024
17fd7ef
Merge remote-tracking branch 'origin/feature/intro-quiz' into future/…
biplala Dec 6, 2024
bcf46ed
フロントエンドの変更を加えました
nozo120 Dec 7, 2024
b63f04c
define create_quiz
Dec 7, 2024
d13ac05
revise create_quiz
Dec 7, 2024
c5171c8
Load-Division
Yukkurisiteikitai Dec 7, 2024
e5690cb
create_intro
Dec 7, 2024
856a180
フロントエンドの変更を加えました
nozo120 Dec 7, 2024
886691d
set/quiz
Yukkurisiteikitai Dec 7, 2024
f408c9a
set/print-Quiz
Yukkurisiteikitai Dec 7, 2024
90984cb
create_quiz
Dec 7, 2024
cb2dfd0
Merge pull request #1 from tetsushi33/division/gameSystemFile
Yukkurisiteikitai Dec 7, 2024
547dc38
DynamoDBとの繋ぎこみを実装
biplala Dec 7, 2024
dd61c71
フロントエンドの変更を加えました
nozo120 Dec 7, 2024
526b2b7
Merge branch 'develop' into test
Dec 7, 2024
d2f6efe
Merge pull request #2 from tetsushi33/test
biplala Dec 7, 2024
289b2c5
Merge pull request #4 from tetsushi33/feature/intro-quiz
nozo120 Dec 7, 2024
1574875
Merge remote-tracking branch 'origin/develop' into feature/connection…
biplala Dec 7, 2024
29fa499
Merge remote-tracking branch 'origin/develop' into feature/connection…
biplala Dec 7, 2024
824ceeb
Merge pull request #3 from tetsushi33/feature/connection-with-aws-ser…
biplala Dec 7, 2024
066eae5
create_quize() define get_last_id
Dec 7, 2024
2c87794
Merge pull request #5 from tetsushi33/backend
tetsushi33 Dec 7, 2024
9fc3caa
don't set ;
Yukkurisiteikitai Dec 7, 2024
ce2fcb7
フロントエンドの表示デグレを解消
nozo120 Dec 7, 2024
6868981
Merge branch 'develop' of https://github.com/tetsushi33/Mini-Run into…
nozo120 Dec 7, 2024
5960876
フロントエンドの変更を加えました
nozo120 Dec 7, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# log files
*.log.*
*.log

# environment informations and credentials
*.env
*.pyc
./frontend/thinks
*.DS_Store
19 changes: 17 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,17 @@
# Mini-Run
aa
# **「暇つぶし革命!遊びながら学び、作って解く新感覚ミニゲーム体験!」**
URL:https://test.croud

## 実行方法
```
docker compose build
docker compose up
```
URL("localhost:5000")に接続

## 使用技術
|kind |version |
|:--|:--:|
|node.js |node:18 |
|Flask |2.2.5 |
|boto3 |1.26.145 |
|gunicorn |20.1.0 |
10 changes: 10 additions & 0 deletions backend/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
FROM python:3.10

WORKDIR /app

COPY requirements.txt ./
RUN pip install --no-cache-dir -r requirements.txt

COPY . .

CMD ["flask", "run", "--host=0.0.0.0"]
26 changes: 26 additions & 0 deletions backend/app.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
from flask import Flask
from flask_cors import CORS
import router
from config import config

def create_app():
app = Flask(__name__)

app.config.from_object(config.Config)

app.register_blueprint(router.router)

app.config['JSON_AS_ASCII'] = False #日本語文字化け対策
app.config["JSON_SORT_KEYS"] = False #ソートをそのまま
CORS(
app,
resources = {
r"/api/*": {"origins": ["http://localhost", "http://localhost:3000"]}
}
)

return app

if __name__ == "__main__":
app = create_app()
app.run(host='0.0.0.0', debug=True, port=5000, threaded=True, use_reloader=False)
7 changes: 7 additions & 0 deletions backend/config/config.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import os
from dataclasses import dataclass

@dataclass
class Config:
DEBUG = os.getenv("DEBUG")
DATABASE_URI= ""
38 changes: 38 additions & 0 deletions backend/config/logging.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
{
"version": 1,
"formatters": {
"default": {
"format": "[%(asctime)s] [%(levelname)s] : %(message)s"
}
},
"loggers": {
"file": {
"handlers": ["file"],
"level": "WARN",
"qualname": "file",
"propagate": "no"
},
"wsgi": {
"handlers": ["wsgi"],
"level": "WARN",
"qualname": "wsgi",
"propagate": "no"
}
},
"handlers": {
"file": {
"class": "logging.handlers.TimedRotatingFileHandler",
"formatter": "default",
"filename": "./logs/application.log"
},
"wsgi": {
"class": "logging.StreamHandler",
"stream": "ext://flask.logging.wsgi_errors_stream",
"formatter": "default"
}
},
"root": {
"level": "WARN",
"handlers": ["file", "wsgi"]
}
}
124 changes: 124 additions & 0 deletions backend/controller/game_controller.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
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):
self.table_name = "minirun_game_table"
self.db_client = DynamoClient(table_name="minirun_game_table")

def get_game_random(self):
response = self.db_client.get_random()
return make_response(jsonify({
'code': 200,
'game': response
}))

def get_last_id(self) -> int:
response = self.db_client.scan(TableName=self.table_name, ProjectionExpression="id")
items = response.get('Items', [])
if not items:
return 0
ids = [int(item['id']['N']) for item in items]
return max(ids)

def create_quiz(self):
# リクエストデータを取得
data = request.get_json()
question = data['question']
selects = data['selects']
answer_idx = data['answer_idx']
last_id = self.get_last_id()
data['id'] = last_id + 1

# バリデーションを実装
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:
return make_response(jsonify({'code': 400, 'message': 'Invalid selects'}), 400)
if not isinstance(answer_idx, int) or not (0 <= answer_idx <= 3):
return make_response(jsonify({'code': 400, 'message': 'Invalid answer_idx'}), 400)

# DBに保存
try:
if self.db_client.create_quiz(data):
return make_response(jsonify({'code': 200, 'message': 'Quiz created successfully'}), 200)
else:
return make_response(jsonify({'code': 500, 'message': 'Failed to create quiz'}), 500)
except Exception as e:
# エラーハンドリングを実装
return make_response(jsonify({'code': 500, 'message': str(e)}), 500)

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

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 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)
else:
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()
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)


61 changes: 61 additions & 0 deletions backend/engine/dynamo_client.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import os
import boto3
import random

class DynamoClient:
def __init__(self, table_name: str) -> None:
self.db = boto3.client('dynamodb')
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:
'''対象のテーブルからレコード全件を取得するメソッド
'''
response = self.db.scan(TableName=self.table_name)
items = response.get('Items', [])
return items

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')

def scan(self, **kwargs):
return self.db.scan(**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

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')


Empty file added backend/engine/s3_client.py
Empty file.
21 changes: 21 additions & 0 deletions backend/initialize_db.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import os
import boto3

dynamodb = boto3.client('dynamodb', endpoint_url=os.getenv("DYNAMO_ENDPOINT"))

table_name = "game_table"

def main():
dynamodb.create_table(
TableName=table_name,
KeySchema=[
{"AttributeName": "id", "KeyType": "HASH",},
],
AttributeDefinitions=[
{"AttributeName": "id", "AttributeType": "N"},
],
BillingMode="PAY_PER_REQUEST",
)

if __name__ == "__main__":
main()
14 changes: 14 additions & 0 deletions backend/logger.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
from flask import request, current_app
from functools import wraps

def http_request_logging(f):
@wraps(f)
def decorated_function(*args, **kwargs):
logger = current_app.logger
try:
logger.info('%s - %s - %s - %s', request.remote_addr, request.method, request.url, request.query_string)
except Exception as e:
logger.exception(e)
pass
return f(*args, **kwargs)
return decorated_function
17 changes: 17 additions & 0 deletions backend/model/games.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
class Quiz:
def __init__(self, id: int, question: str, selects: list, answer_idx: int, likes: int=0) -> None:
self.id = id
self.question = question
self.selects = selects
self.answer_idx = answer_idx
self.likes = likes

# TODO: __repr__(self)をつくる

class IntroDon:
def __init__(self, game_id: int, question: str, selects: list, answer: str, likes: int=0) -> None:
self.game_id = game_id
self.question = question
self.selects = selects
self.answer = answer
self.likes = likes
4 changes: 4 additions & 0 deletions backend/requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
Flask==2.2.5
boto3==1.26.145
gunicorn==20.1.0
flask_cors
Loading