From f53f5914fc882d6a3885f1191709ceb8e785837f Mon Sep 17 00:00:00 2001 From: Rokas Puzonas Date: Fri, 24 Nov 2023 23:28:36 +0200 Subject: [PATCH] add more question types --- .../MultipleChoiceAnswersController.php | 65 +++++++++++++ app/Http/Controllers/QuestionController.php | 63 ++++++++++++- .../SingleChoiceAnswerController.php | 66 ++++++++++++++ .../SingleQuestionAnswersController.php | 65 +++++++++++++ app/Http/Controllers/TestController.php | 34 ++++++- app/Models/MultipleChoiceAnswers.php | 29 ++++++ app/Models/Question.php | 2 +- app/Models/SingleChoiceAnswer.php | 25 +++++ app/Models/SingleQuestionAnswers.php | 22 +++++ ...23_10_29_172100_create_questions_table.php | 2 +- ...9_create_single_question_answers_table.php | 29 ++++++ ...657_create_single_choice_answers_table.php | 32 +++++++ ...3_create_multiple_choice_answers_table.php | 36 ++++++++ database/seeders/DatabaseSeeder.php | 53 ++++++++++- .../views/components/bool-input.blade.php | 7 ++ .../components/question-fields.blade.php | 91 +++++++++++++++++++ resources/views/layouts/app.blade.php | 1 + resources/views/questions/edit.blade.php | 30 ++++-- resources/views/tests/edit.blade.php | 18 +--- 19 files changed, 640 insertions(+), 30 deletions(-) create mode 100644 app/Http/Controllers/MultipleChoiceAnswersController.php create mode 100644 app/Http/Controllers/SingleChoiceAnswerController.php create mode 100644 app/Http/Controllers/SingleQuestionAnswersController.php create mode 100644 app/Models/MultipleChoiceAnswers.php create mode 100644 app/Models/SingleChoiceAnswer.php create mode 100644 app/Models/SingleQuestionAnswers.php create mode 100644 database/migrations/2023_11_22_201539_create_single_question_answers_table.php create mode 100644 database/migrations/2023_11_22_201657_create_single_choice_answers_table.php create mode 100644 database/migrations/2023_11_22_201903_create_multiple_choice_answers_table.php create mode 100644 resources/views/components/bool-input.blade.php create mode 100644 resources/views/components/question-fields.blade.php diff --git a/app/Http/Controllers/MultipleChoiceAnswersController.php b/app/Http/Controllers/MultipleChoiceAnswersController.php new file mode 100644 index 0000000..8d06d2a --- /dev/null +++ b/app/Http/Controllers/MultipleChoiceAnswersController.php @@ -0,0 +1,65 @@ +validate([ "question" => "required|string", - "answer" => "required|string", "points" => "required|integer|min:1", "test_id" => "required|integer", + "answer_type" => "required|string", ]); - Question::create($validated); + if ($request->answer_type == "single_answer") { + $validated_answer = $request->validate([ + "answer" => "required|string", + ]); + } else if ($request->answer_type == "single_choice") { + $validated_answer = $request->validate([ + "correct_answer" => "required|string", + "incorrect_answer1" => "required|string", + "incorrect_answer2" => "nullable|string", + "incorrect_answer3" => "nullable|string", + ]); + } else if ($request->answer_type == "multiple_choice") { + $validated_answer = $request->validate([ + "answer1" => "required|string", + "answer2" => "required|string", + "answer3" => "nullable|string", + "answer4" => "nullable|string", + "is_answer1_correct" => "nullable|boolean", + "is_answer2_correct" => "nullable|boolean", + "is_answer3_correct" => "nullable|boolean", + "is_answer4_correct" => "nullable|boolean", + ]); + } + + $question = Question::create($validated); + $validated_answer["question_id"] = $question->id; + if ($request->answer_type == "single_answer") { + SingleQuestionAnswers::create($validated_answer); + } else if ($request->answer_type == "single_choice") { + SingleChoiceAnswer::create($validated_answer); + } else if ($request->answer_type == "multiple_choice") { + MultipleChoiceAnswers::create($validated_answer); + } return redirect(route("tests.edit", [ "test" => Test::where("id", $validated["test_id"])->first() @@ -56,8 +91,30 @@ class QuestionController extends Controller */ public function edit(Question $question) { + $question_answer = $question; + if ($question->answer_type == "single_answer") { + $answer = SingleQuestionAnswers::where("question_id", $question->id)->first(); + $question_answer->answer = $answer->answer; + } else if ($question->answer_type == "single_choice") { + $answer = SingleChoiceAnswer::where("question_id", $question->id)->first(); + $question_answer->correct_answer = $answer->correct_answer; + $question_answer->incorrect_answer1 = $answer->incorrect_answer1; + $question_answer->incorrect_answer2 = $answer->incorrect_answer2; + $question_answer->incorrect_answer3 = $answer->incorrect_answer3; + } else if ($question->answer_type == "multiple_choice") { + $answer = MultipleChoiceAnswers::where("question_id", $question->id)->first(); + $question_answer->answer1 = $answer->answer1; + $question_answer->is_answer1_correct = $answer->is_answer1_correct; + $question_answer->answer2 = $answer->answer2; + $question_answer->is_answer2_correct = $answer->is_answer2_correct; + $question_answer->answer3 = $answer->answer3; + $question_answer->is_answer3_correct = $answer->is_answer3_correct; + $question_answer->answer4 = $answer->answer4; + $question_answer->is_answer4_correct = $answer->is_answer4_correct; + } + return view("questions.edit", [ - "question" => $question, + "question" => $question_answer, ]); } diff --git a/app/Http/Controllers/SingleChoiceAnswerController.php b/app/Http/Controllers/SingleChoiceAnswerController.php new file mode 100644 index 0000000..84b185f --- /dev/null +++ b/app/Http/Controllers/SingleChoiceAnswerController.php @@ -0,0 +1,66 @@ +user()->tests()->get(); return view("tests.index", [ - "tests" => $request->user()->tests()->get() + "tests" => $tests ]); } @@ -52,8 +56,36 @@ class TestController extends Controller */ public function edit(Test $test) { + $questions = $test->questions()->get(); + foreach ($questions as $question) { + if ($question->answer_type == "single_answer") { + $answer = SingleQuestionAnswers::where("question_id", $question->id)->first(); + $question->answer = $answer->answer; + } else if ($question->answer_type == "single_choice") { + $answer = SingleChoiceAnswer::where("question_id", $question->id)->first(); + $question->answer = $answer->correct_answer; + } else if ($question->answer_type == "multiple_choice") { + $answer = MultipleChoiceAnswers::where("question_id", $question->id)->first(); + $valid_answer = array(); + if ($answer->is_answer1_correct) { + array_push($valid_answer, $answer->answer1); + } + if ($answer->is_answer2_correct) { + array_push($valid_answer, $answer->answer2); + } + if ($answer->is_answer3_correct) { + array_push($valid_answer, $answer->answer3); + } + if ($answer->is_answer4_correct) { + array_push($valid_answer, $answer->answer4); + } + $question->answer = join(", ", $valid_answer); + } + } + return view("tests.edit", [ "test" => $test, + "questions" => $questions, ]); } diff --git a/app/Models/MultipleChoiceAnswers.php b/app/Models/MultipleChoiceAnswers.php new file mode 100644 index 0000000..4df4dd3 --- /dev/null +++ b/app/Models/MultipleChoiceAnswers.php @@ -0,0 +1,29 @@ +belongsTo(Question::class); + } +} diff --git a/app/Models/Question.php b/app/Models/Question.php index 4272b65..5a26dd4 100644 --- a/app/Models/Question.php +++ b/app/Models/Question.php @@ -13,7 +13,7 @@ class Question extends Model protected $fillable = [ "test_id", 'question', - 'answer', + 'answer_type', 'points', ]; diff --git a/app/Models/SingleChoiceAnswer.php b/app/Models/SingleChoiceAnswer.php new file mode 100644 index 0000000..d66dfeb --- /dev/null +++ b/app/Models/SingleChoiceAnswer.php @@ -0,0 +1,25 @@ +belongsTo(Question::class); + } +} diff --git a/app/Models/SingleQuestionAnswers.php b/app/Models/SingleQuestionAnswers.php new file mode 100644 index 0000000..1c8410e --- /dev/null +++ b/app/Models/SingleQuestionAnswers.php @@ -0,0 +1,22 @@ +belongsTo(Question::class); + } +} diff --git a/database/migrations/2023_10_29_172100_create_questions_table.php b/database/migrations/2023_10_29_172100_create_questions_table.php index 6f98c70..0ccc6af 100644 --- a/database/migrations/2023_10_29_172100_create_questions_table.php +++ b/database/migrations/2023_10_29_172100_create_questions_table.php @@ -15,7 +15,7 @@ return new class extends Migration $table->id(); $table->foreignId("test_id")->references("id")->on("tests")->constrained()->cascadeOnDelete(); $table->string("question"); - $table->string("answer"); + $table->enum("answer_type", ["single_answer", "single_choice", "multiple_choice"]); $table->unsignedInteger("points")->default(1); $table->timestamps(); }); diff --git a/database/migrations/2023_11_22_201539_create_single_question_answers_table.php b/database/migrations/2023_11_22_201539_create_single_question_answers_table.php new file mode 100644 index 0000000..904b4c2 --- /dev/null +++ b/database/migrations/2023_11_22_201539_create_single_question_answers_table.php @@ -0,0 +1,29 @@ +id(); + $table->foreignId("question_id")->references("id")->on("questions")->constrained()->cascadeOnDelete(); + $table->string("answer"); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('single_question_answers'); + } +}; diff --git a/database/migrations/2023_11_22_201657_create_single_choice_answers_table.php b/database/migrations/2023_11_22_201657_create_single_choice_answers_table.php new file mode 100644 index 0000000..5b994dc --- /dev/null +++ b/database/migrations/2023_11_22_201657_create_single_choice_answers_table.php @@ -0,0 +1,32 @@ +id(); + $table->foreignId("question_id")->references("id")->on("questions")->constrained()->cascadeOnDelete(); + $table->string("correct_answer"); + $table->string("incorrect_answer1"); + $table->string("incorrect_answer2")->nullable(); + $table->string("incorrect_answer3")->nullable(); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('single_choice_answers'); + } +}; diff --git a/database/migrations/2023_11_22_201903_create_multiple_choice_answers_table.php b/database/migrations/2023_11_22_201903_create_multiple_choice_answers_table.php new file mode 100644 index 0000000..c7902ce --- /dev/null +++ b/database/migrations/2023_11_22_201903_create_multiple_choice_answers_table.php @@ -0,0 +1,36 @@ +id(); + $table->foreignId("question_id")->references("id")->on("questions")->constrained()->cascadeOnDelete(); + $table->string("answer1"); + $table->string("answer2"); + $table->string("answer3")->nullable(); + $table->string("answer4")->nullable(); + $table->boolean("is_answer1_correct")->default(false); + $table->boolean("is_answer2_correct")->default(false); + $table->boolean("is_answer3_correct")->default(false); + $table->boolean("is_answer4_correct")->default(false); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('multiple_choice_answers'); + } +}; diff --git a/database/seeders/DatabaseSeeder.php b/database/seeders/DatabaseSeeder.php index 9b3a803..8527747 100644 --- a/database/seeders/DatabaseSeeder.php +++ b/database/seeders/DatabaseSeeder.php @@ -4,6 +4,11 @@ namespace Database\Seeders; // use Illuminate\Database\Console\Seeds\WithoutModelEvents; +use App\Models\MultipleChoiceAnswers; +use App\Models\Question; +use App\Models\SingleChoiceAnswer; +use App\Models\SingleQuestionAnswers; +use App\Models\Test; use App\Models\User; use Illuminate\Database\Seeder; use Illuminate\Support\Facades\Hash; @@ -21,7 +26,7 @@ class DatabaseSeeder extends Seeder 'password' => Hash::make("admin"), 'role' => "admin" ]); - User::create([ + $teacher = User::create([ 'name' => "Bob teacher", 'email' => "bob@teacher", 'password' => Hash::make("bob"), @@ -33,5 +38,51 @@ class DatabaseSeeder extends Seeder 'password' => Hash::make("alice"), 'role' => "student" ]); + + $test = Test::create([ + "name" => "Matematika", + "user_id" => $teacher->id + ]); + + { + $question = Question::create([ + "test_id" => $test->id, + "question" => "1+1=?", + "answer_type" => "single_answer", + ]); + SingleQuestionAnswers::create([ + "question_id" => $question->id, + "answer" => "2" + ]); + } + + { + $question = Question::create([ + "test_id" => $test->id, + "question" => "Gyvenimo prasme", + "answer_type" => "single_choice", + ]); + SingleChoiceAnswer::create([ + "question_id" => $question->id, + "correct_answer" => "42", + "incorrect_answer1" => "Kates", + "incorrect_answer3" => "Sunys", + ]); + } + + { + $question = Question::create([ + "test_id" => $test->id, + "question" => "Siandienos orai", + "answer_type" => "multiple_choice", + ]); + MultipleChoiceAnswers::create([ + "question_id" => $question->id, + "answer1" => "Sninga", "is_answer1_correct" => true, + "answer2" => "Lija", "is_answer2_correct" => true, + "answer4" => "Idk, paziurek per langa", "is_answer4_correct" => false, + ]); + } + } } diff --git a/resources/views/components/bool-input.blade.php b/resources/views/components/bool-input.blade.php new file mode 100644 index 0000000..26239e6 --- /dev/null +++ b/resources/views/components/bool-input.blade.php @@ -0,0 +1,7 @@ +@props([ + 'disabled' => false, + 'checked' => false +]) + +merge(['class' => 'border-gray-300 focus:border-indigo-500 focus:ring-indigo-500 rounded-md shadow-sm']) !!}> diff --git a/resources/views/components/question-fields.blade.php b/resources/views/components/question-fields.blade.php new file mode 100644 index 0000000..5841325 --- /dev/null +++ b/resources/views/components/question-fields.blade.php @@ -0,0 +1,91 @@ +@props([ + 'test_id' => '', + 'default_question' => '', + 'default_points' => 1, + 'default_answer_type' => 'single_answer', + + 'default_answer' => '', + + 'default_correct_answer' => '', + 'default_incorrect_answer1' => '', + 'default_incorrect_answer2' => '', + 'default_incorrect_answer3' => '', + + 'default_answer1' => '', + 'default_is_answer1_correct' => '', + 'default_answer2' => '', + 'default_is_answer2_correct' => '', + 'default_answer3' => '', + 'default_is_answer3_correct' => '', + 'default_answer4' => '', + 'default_is_answer4_correct' => '' +]) + + + +{{ __("Question") }} + + + +{{ __("Points") }} + + + +{{ __("Answer type") }} + + + + + + +
+ {{ __("Answer") }} + + +
+ +
+ {{ __("Correct answer") }} + + + + @for ($idx = 1; $idx <= 3; $idx++) + {{ __("Incorrect answer ".$idx) }} + + + @endfor +
+ +
+ @for ($idx = 1; $idx <= 4; $idx++) +
+ {{ __("Answer ".$idx) }} + + + + +
+ @endfor +
+ + diff --git a/resources/views/layouts/app.blade.php b/resources/views/layouts/app.blade.php index b59af15..d49d26d 100644 --- a/resources/views/layouts/app.blade.php +++ b/resources/views/layouts/app.blade.php @@ -12,6 +12,7 @@ + @vite(['resources/css/app.css', 'resources/js/app.js']) diff --git a/resources/views/questions/edit.blade.php b/resources/views/questions/edit.blade.php index 5723c20..7a2d4d4 100644 --- a/resources/views/questions/edit.blade.php +++ b/resources/views/questions/edit.blade.php @@ -4,17 +4,29 @@ @csrf @method("patch")
- {{ __("Question") }} - - + {{ $question->answer_type }} + {{ __("Answer") }} - - + :default_answer="$question->answer" - {{ __("Points") }} - - + :default_correct_answer="$question->correct_answer" + :default_incorrect_answer1="$question->incorrect_answer1" + :default_incorrect_answer2="$question->incorrect_answer2" + :default_incorrect_answer3="$question->incorrect_answer3" + + :default_answer1="$question->answer1" + :default_is_answer1_correct="$question->is_answer1_correct" + :default_answer2="$question->answer2" + :default_is_answer2_correct="$question->is_answer2_correct" + :default_answer3="$question->answer3" + :default_is_answer3_correct="$question->is_answer3_correct" + :default_answer4="$question->answer4" + :default_is_answer4_correct="$question->is_answer4_correct" + />
diff --git a/resources/views/tests/edit.blade.php b/resources/views/tests/edit.blade.php index 8945987..5d0c92d 100644 --- a/resources/views/tests/edit.blade.php +++ b/resources/views/tests/edit.blade.php @@ -20,19 +20,9 @@
@csrf
- - - {{ __("Question") }} - - - - {{ __("Answer") }} - - - - {{ __("Points") }} - - +
@@ -48,7 +38,7 @@ - @foreach ($test->questions()->get() as $question) + @foreach ($questions as $question) {{ $question->question }} {{ $question->answer }}