kik/laravel-quiz

提供问答功能

dev-main 2023-04-29 18:21 UTC

This package is auto-updated.

Last update: 2024-09-29 21:21:44 UTC


README

Laravel Quiz

Laravel Quiz

Latest Version on Packagist Total Downloads GitHub Actions

使用此包,您可以将问答功能轻松集成到您的Laravel项目中。

特性

  • 将主题添加到问题、问答以及其他主题中
  • 支持的题目类型:多项选择、单选题和填空题
  • 添加您自己的题目类型并定义处理它们的自定义方法
  • 灵活的扣分设置
  • 灵活的问答设置,包含大多数有用的设置(例如:总分、及格分、扣分、时长、有效日期、描述等)
  • 您应用程序的任何类型的用户都可以成为问答的参与者
  • 您应用程序的任何类型的用户,以及任何数量的用户都可以成为问答的作者(不同角色)
  • 生成随机问答(进行中)

安装

您可以通过composer安装此包

composer require harishdurga/laravel-quiz
  • Laravel版本:9.X
  • PHP版本:8.X

使用

类图

LaravelQuiz

发布供应商文件(config,mingrations,seeder)

php artisan vendor:publish --provider="Harishdurga\LaravelQuiz\LaravelQuizServiceProvider"

如果您正在更新包,您可能需要运行上述命令来发布供应商文件。但请备份配置文件。同时运行迁移命令以向现有表添加新列。

创建主题

$computer_science = Topic::create([
    'name' => 'Computer Science',
    'slug' => 'computer-science',
]);

创建子主题

$algorithms = Topic::create([
    'name' => 'Algorithms',
    'slug' => 'algorithms'
]);
$computer_science->children()->save($algorithms);

题目类型

一个名为 QuestionTypeSeeder 的seeder类将被发布到 database/seeders 文件夹中。运行以下命令来播种题目类型。

php artisan db:seed --class=\\Harishdurga\\LaravelQuiz\\Database\\Seeders\\QuestionTypeSeeder

目前此包仅配置为处理以下类型的题目

  • multiple_choice_single_answer
  • multiple_choice_multiple_answer
  • fill_the_blank

创建一个题目类型

QuestionType::create(['name'=>'select_all']);

为每种题目类型定义用户自定义方法来评估答案

尽管此包提供了三种题目类型,但您可以轻松更改评估答案所使用的方法。您可以通过更新配置文件中的 get_score_for_question_type 属性来实现这一点。

'get_score_for_question_type' => [
    1 => '\Harishdurga\LaravelQuiz\Models\QuizAttempt::get_score_for_type_1_question',
    2 => '\Harishdurga\LaravelQuiz\Models\QuizAttempt::get_score_for_type_2_question',
    3 => '\Harishdurga\LaravelQuiz\Models\QuizAttempt::get_score_for_type_3_question',
    4 => 'Your custom method'
]

但您的方法需要具有以下签名

/**
 * @param QuizAttemptAnswer[] $quizQuestionAnswers All the answers of the quiz question
 */
public static function get_score_for_type_3_question(QuizAttempt $quizAttempt, QuizQuestion $quizQuestion, array $quizQuestionAnswers, $data = null): float
{
    // Your logic here
}

如果您需要将数据传递给您的函数,则可以将数据作为最后一个 $data 参数传递。当您调用 calculate_score() 方法时,您可以作为参数传递数据。

创建题目

$question_one = Question::create([
    'name' => 'What is an algorithm?',
    'question_type_id' => 1,
    'is_active' => true,
    'media_url'=>'url',
    'media_type'=>'image'
]);

获取某种类型的题目

$question_type->questions

仅获取带有选项的题目(有效题目)

Question::hasOptions()->get()

将主题附加到题目

$question->topics()->attach([$computer_science->id, $algorithms->id]);

题目选项

$question_two_option_one = QuestionOption::create([
            'question_id' => $question_two->id,
            'name' => 'array',
            'is_correct' => true,
            'media_type'=>'image',
            'media_url'=>'media url'
        ]);

获取题目的选项

$question->options

创建问答

$quiz = Quiz::create([
    'name' => 'Computer Science Quiz',
    'description' => 'Test your knowledge of computer science',
    'slug' => 'computer-science-quiz',
    'time_between_attempts' => 0, //Time in seconds between each attempt
    'total_marks' => 10,
    'pass_marks' => 6,
    'max_attempts' => 1,
    'is_published' => 1,
    'valid_from' => now(),
    'valid_upto' => now()->addDay(5),
    'media_url'=>'',
    'media_type'=>'',
    'negative_marking_settings'=>[
        'enable_negative_marks' => true,
        'negative_marking_type' => 'fixed',
        'negative_mark_value' => 0,
    ]
]);

将主题附加到问答

$quiz->topics()->attach([$topic_one->id, $topic_two->id]);

可主题化

主题可以附加到问答或题目。题目可以在问答之外存在。例如,您可以创建一个问题库,如果附加了主题,则可以根据主题进行筛选。

扣分设置

默认情况下,由于向后兼容性,已启用扣分。您可以通过将 enable_negative_marks 设置为 false 来禁用它。支持两种类型的扣分( negative_marking_type): fixedpercentage。在题目级别定义的扣分值将优先于在问答级别定义的值。如果您想在问答级别设置扣分值,请将 negative_mark_value 设置为您想要的值。如果您想在题目级别设置扣分值,请将 QuizQuestionnegative_marks 设置为您想要的值。无需给出负数,负分或百分比应以正数给出。

向问答添加作者(s)

$admin = Author::create(
            ['name' => "John Doe"]
        );
$quiz = Quiz::factory()->make()->create([
            'name' => 'Sample Quiz',
            'slug' => 'sample-quiz'
        ]);
QuizAuthor::create([
            'quiz_id' => $quiz->id,
            'author_id' => $admin->id,
            'author_type' => get_class($admin),
            'author_role' => 'admin',
        ]);
$quiz->quizAuthors->first()->author; //Original User

CanAuthorQuiz 特性添加到您的模型中,您可以通过调用 quizzes 关系来获取所有关联的测验。您可以赋予任何您想要的作者角色,并根据您的用例实现 ACL。

将问题添加到测验中

$quiz_question =  QuizQuestion::create([
    'quiz_id' => $quiz->id,
    'question_id' => $question->id,
    'marks' => 3,
    'order' => 1,
    'negative_marks'=>1,
    'is_optional'=>false
]);

获取测验问题

$quiz->questions

尝试测验

$quiz_attempt = QuizAttempt::create([
    'quiz_id' => $quiz->id,
    'participant_id' => $participant->id,
    'participant_type' => get_class($participant)
]);

获取测验尝试参与者

MorphTo 关系。

$quiz_attempt->participant

回答测验尝试

QuizAttemptAnswer::create(
    [
        'quiz_attempt_id' => $quiz_attempt->id,
        'quiz_question_id' => $quiz_question->id,
        'question_option_id' => $question_option->id,
    ]
);

QuizAttemptAnswer 属于 QuizAttemptQuizQuestionQuestionOption

获取测验尝试分数

$quiz_attempt->calculate_score()

如果没有找到非必答题的答案,则会应用负分数。

获取问题的正确选项

$question->correct_options

返回 QuestionOption 集合。

public function correct_options(): Collection
{
    return $this->options()->where('is_correct', 1)->get();
}

请参阅单元和功能测试以了解更多信息。

验证测验问题

您可以使用 QuizAttempt 模型的 validate() 方法来代替获取测验尝试的总分。此方法将返回一个数组,其中 QuizQuestion 模型的 id 作为关联数组中的键。 示例:

$quizAttempt->validate($quizQuestion->id); //For a particular question
$quizAttempt->validate(); //For all the questions in the quiz attempt
$quizAttempt->validate($quizQuestion->id,$data); //$data can any type
[
  1 => [
    'score' => 10,
    'is_correct' => true,
    'correct_answer' => ['One','Five','Seven'],
    'user_answer' => ['Five','One','Seven']
  ],
  2 => [
    'score' => 0,
    'is_correct' => false,
    'correct_answer' => 'Hello There',
    'user_answer' => 'Hello World'
  ]
]

为了能够渲染不同类型的问题(除了包支持的 3 种类型)的用户答案和正确答案,已添加了新的配置选项。

'render_answers_responses'    => [
        1  => '\Harishdurga\LaravelQuiz\Models\QuizAttempt::renderQuestionType1Answers',
        2  => '\Harishdurga\LaravelQuiz\Models\QuizAttempt::renderQuestionType2Answers',
        3  => '\Harishdurga\LaravelQuiz\Models\QuizAttempt::renderQuestionType3Answers',
    ]

通过将问题类型 ID 作为键,您可以将处理该问题类型的自定义函数的路径放入其中。此自定义方法将在 validate() 方法内部通过传递 QuizQuestion 对象作为参数来调用。 示例:

public static function renderQuestionType1Answers(QuizQuestion $quizQuestion,QuizAttempt $quizAttempt,mixed $data=null)
    {
        /**
         * @var Question $actualQuestion
         */
        $actualQuestion = $quizQuestion->question;
        $answers = $quizQuestion->answers->where('quiz_attempt_id', $quizAttempt->id);
        $questionOptions = $actualQuestion->options;
        $correctAnswer = $actualQuestion->correct_options()->first()?->option;
        $givenAnswer = $answers->first()?->question_option_id;
        foreach ($questionOptions as $questionOption) {
            if ($questionOption->id == $givenAnswer) {
                $givenAnswer = $questionOption->option;
                break;
            }
        }
        return [$correctAnswer, $givenAnswer];
    }

如示例所示,您自定义的方法应返回一个包含两个元素的数组,第一个元素是问题的正确答案,第二个元素是用户的答案。无论您将什么 $data 发送到 validate(),它都将发送到这些自定义方法,以便您可以发送额外的数据以渲染答案。

测试

composer test

变更日志

请参阅 CHANGELOG 了解最近更改的更多信息。

贡献

请参阅 CONTRIBUTING 了解详细信息。

安全性

如果您发现任何与安全相关的问题,请通过电子邮件 durgaharish5@gmail.com 而不是使用问题跟踪器。

鸣谢

许可证

MIT 许可证 (MIT)。请参阅 许可证文件 了解更多信息。

Laravel 包模板

此包是使用 Laravel 包模板 生成的。