api/app/Http/Controllers/HuntStepsController.php

137 lines
4.4 KiB
PHP

<?php
namespace App\Http\Controllers;
use App\Models\HuntSteps;
use Illuminate\Http\Request;
class HuntStepsController extends Controller
{
/**
* Display a listing of the resource.
*/
public function index()
{
//
}
/**
* Show the form for creating a new resource.
*/
public function create()
{
//
}
/**
* Store a newly created resource in storage.
*/
public function store(\App\Http\Requests\StoreHuntStepRequest $request, \App\Models\Hunts $hunt)
{
if ($hunt->creator_id !== auth()->id()) {
return response()->json(['message' => 'Unauthorized'], 403);
}
$validated = $request->validated();
$step = $hunt->steps()->create($validated);
return response()->json($step, 201);
}
/**
* Validate a hunt step.
*/
public function validateStep(\Illuminate\Http\Request $request, \App\Models\Hunts $hunt, \App\Models\HuntSteps $step)
{
$request->validate([
'latitude' => 'required|numeric',
'longitude' => 'required|numeric',
]);
$user = $request->user();
// 1. Check participation
$participation = $user->participations()->where('hunt_id', $hunt->id)->first();
if (!$participation) {
return response()->json(['message' => 'Not participating in this hunt'], 403);
}
// 2. Check if this is the current step
if ($participation->pivot->current_step_number !== $step->step_number) {
return response()->json(['message' => 'This is not your current step'], 400);
}
// 3. Check proximity
// Haversine formula
$earthRadius = 6371000; // meters
$latFrom = deg2rad($request->latitude);
$lonFrom = deg2rad($request->longitude);
$latTo = deg2rad($step->latitude);
$lonTo = deg2rad($step->longitude);
$latDelta = $latTo - $latFrom;
$lonDelta = $lonTo - $lonFrom;
$angle = 2 * asin(sqrt(pow(sin($latDelta / 2), 2) +
cos($latFrom) * cos($latTo) * pow(sin($lonDelta / 2), 2)));
$distance = $angle * $earthRadius;
if ($distance > $step->radius_m) {
return response()->json([
'success' => false,
'message' => 'You are too far from the target.',
'distance' => round($distance) . 'm'
], 400);
}
// 4. Update progress
// Check if there is a next step
$nextStepNumber = $step->step_number + 1;
$nextStep = $hunt->steps()->where('step_number', $nextStepNumber)->first();
$updateData = [];
if ($nextStep) {
$updateData['current_step_number'] = $nextStepNumber;
} else {
$updateData['status'] = 'completed';
// Keep current_step_number as is (last step) or increment it to indicate "done"?
// Usually keeping it at last step or marking status completed is enough.
// Let's verify existing logic in HuntsController::show which filters based on step number.
// If we increment, show() might need adjustment to show everything if completed.
// For now, let's just mark completed and maybe keep same step number or increment.
// If we increment, $nextStep is null, so user matches nothing in filter?
// Let's increment current_step_number so that in show(), $step->step_number < $currentStepNumber becomes true for all steps.
$updateData['current_step_number'] = $nextStepNumber;
}
$hunt->participants()->updateExistingPivot($user->id, $updateData);
// 5. Return response
$response = [
'success' => true,
'message' => 'Step validated!',
];
if ($nextStep) {
$response['next_step'] = [
'step_number' => $nextStep->step_number,
'title' => $nextStep->title,
'description' => $nextStep->description,
'hint_text' => $nextStep->hint_text,
'hint_media_url' => $nextStep->hint_media_url,
// Do NOT include lat/long
];
} else {
$response['message'] = 'Hunt completed! Congratulations!';
$response['completed'] = true;
}
return response()->json($response);
}
}