Finish basic API implementation

This commit is contained in:
2025-08-27 15:01:06 +09:00
parent fff9bce9e7
commit cc9edb9932
19 changed files with 3844 additions and 5 deletions

192
rog/location_interaction.py Normal file
View File

@ -0,0 +1,192 @@
"""
Location evaluation_value に基づく処理ロジック
evaluation_value の値に応じた処理を定義:
- 0: 通常ポイント (通常のチェックイン)
- 1: 写真撮影 + 買い物ポイント
- 2: QRコードスキャン + クイズ回答
"""
from django.utils.translation import gettext_lazy as _
class LocationInteractionType:
"""ロケーションインタラクションタイプの定数"""
NORMAL_CHECKIN = "0"
PHOTO_SHOPPING = "1"
QR_QUIZ = "2"
CHOICES = [
(NORMAL_CHECKIN, _("通常ポイント")),
(PHOTO_SHOPPING, _("写真撮影 + 買い物ポイント")),
(QR_QUIZ, _("QRコードスキャン + クイズ回答")),
]
def get_interaction_type(location):
"""
Locationオブジェクトから適切なインタラクションタイプを取得
Args:
location: Locationモデルのインスタンス
Returns:
dict: インタラクション情報
"""
evaluation_value = location.evaluation_value or "0"
interaction_info = {
'type': evaluation_value,
'requires_photo': False,
'requires_qr_code': False,
'point_type': 'checkin',
'description': '',
'instructions': '',
}
if evaluation_value == LocationInteractionType.NORMAL_CHECKIN:
interaction_info.update({
'point_type': 'checkin',
'description': '通常のチェックイン',
'instructions': 'この場所でチェックインしてポイントを獲得してください',
})
elif evaluation_value == LocationInteractionType.PHOTO_SHOPPING:
interaction_info.update({
'requires_photo': True,
'point_type': 'buy',
'description': '写真撮影 + 買い物ポイント',
'instructions': '商品の写真を撮影してください。買い物をすることでポイントを獲得できます',
})
elif evaluation_value == LocationInteractionType.QR_QUIZ:
interaction_info.update({
'requires_qr_code': True,
'point_type': 'quiz',
'description': 'QRコードスキャン + クイズ回答',
'instructions': 'QRコードをスキャンしてクイズに答えてください',
})
else:
# 未知の値の場合はデフォルト処理
interaction_info.update({
'point_type': 'checkin',
'description': '通常のチェックイン',
'instructions': 'この場所でチェックインしてポイントを獲得してください',
})
return interaction_info
def should_use_qr_code(location):
"""
ロケーションでQRコードを使用すべきかを判定
Args:
location: Locationモデルのインスタンス
Returns:
bool: QRコード使用フラグ
"""
# use_qr_codeフラグが設定されている場合、またはevaluation_value=2の場合
return (getattr(location, 'use_qr_code', False) or
location.evaluation_value == LocationInteractionType.QR_QUIZ)
def get_point_calculation(location, interaction_result=None):
"""
ロケーションでのポイント計算
Args:
location: Locationモデルのインスタンス
interaction_result: インタラクション結果 (写真、クイズ回答など)
Returns:
dict: ポイント情報
"""
evaluation_value = location.evaluation_value or "0"
base_checkin_point = location.checkin_point or 10
buy_point = location.buy_point or 0
point_info = {
'points_awarded': 0,
'point_type': 'checkin',
'bonus_applied': False,
'message': '',
}
if evaluation_value == LocationInteractionType.NORMAL_CHECKIN:
# 通常ポイント
point_info.update({
'points_awarded': base_checkin_point,
'point_type': 'checkin',
'message': f'チェックインポイント {base_checkin_point}pt を獲得しました!',
})
elif evaluation_value == LocationInteractionType.PHOTO_SHOPPING:
# 写真撮影 + 買い物ポイント
total_points = base_checkin_point + buy_point
point_info.update({
'points_awarded': total_points,
'point_type': 'buy',
'bonus_applied': True,
'message': f'写真撮影ボーナス込みで {total_points}pt を獲得しました! (基本: {base_checkin_point}pt + ボーナス: {buy_point}pt)',
})
elif evaluation_value == LocationInteractionType.QR_QUIZ:
# QRクイズの場合、正答によってポイントが変わる
if interaction_result and interaction_result.get('quiz_correct', False):
bonus_points = 20 # クイズ正答ボーナス
total_points = base_checkin_point + bonus_points
point_info.update({
'points_awarded': total_points,
'point_type': 'quiz',
'bonus_applied': True,
'message': f'クイズ正答ボーナス込みで {total_points}pt を獲得しました! (基本: {base_checkin_point}pt + ボーナス: {bonus_points}pt)',
})
else:
# 不正解またはクイズ未実施
point_info.update({
'points_awarded': base_checkin_point,
'point_type': 'checkin',
'message': f'基本ポイント {base_checkin_point}pt を獲得しました',
})
return point_info
def validate_interaction_requirements(location, request_data):
"""
インタラクション要件の検証
Args:
location: Locationモデルのインスタンス
request_data: リクエストデータ
Returns:
dict: 検証結果
"""
evaluation_value = location.evaluation_value or "0"
validation_result = {
'valid': True,
'errors': [],
'warnings': [],
}
if evaluation_value == LocationInteractionType.PHOTO_SHOPPING:
# 写真が必要
if not request_data.get('photo'):
validation_result['valid'] = False
validation_result['errors'].append('写真の撮影が必要です')
elif evaluation_value == LocationInteractionType.QR_QUIZ:
# QRコードスキャンとクイズ回答が必要
if not request_data.get('qr_code_data'):
validation_result['valid'] = False
validation_result['errors'].append('QRコードのスキャンが必要です')
if not request_data.get('quiz_answer'):
validation_result['valid'] = False
validation_result['errors'].append('クイズの回答が必要です')
return validation_result