Skip to content

Commit

Permalink
[#4] Add answer tracking
Browse files Browse the repository at this point in the history
Migration needed
  • Loading branch information
danmichaelo committed May 24, 2018
1 parent 3f70ccd commit a63ea43
Show file tree
Hide file tree
Showing 9 changed files with 184 additions and 5 deletions.
42 changes: 42 additions & 0 deletions app/AnalyticsEvent.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
<?php

namespace App;

use App\Events\AnalyticsEventCreating;
use Illuminate\Database\Eloquent\Model;

class AnalyticsEvent extends Model
{
/**
* The attributes that are mass assignable.
*
* @var array
*/
protected $fillable = ['event_type', 'timestamp', 'session_id', 'data'];

/**
* The attributes that should be mutated to dates.
*
* @var array
*/
protected $dates = [
'timestamp',
];

/**
* The attributes that should be cast to native types.
*
* @var array
*/
protected $casts = [
'data' => 'object',
];

/**
* Disable the default created_at and updated_at, since an event never changes.
* We will use a single timestamp column instead.
*
* @var bool
*/
public $timestamps = false;
}
9 changes: 9 additions & 0 deletions app/Course.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ class Course extends Model
'modules' => 'object',
'github_hook' => 'object',
'last_event' => 'object',
'options' => 'object',
];

protected $fillable = ['name', 'modules', 'header', 'headertext', 'footer', 'repo'];
Expand All @@ -45,4 +46,12 @@ public function exercises()
{
return $this->hasMany(Exercise::class);
}

/**
* Get a course option value.
*/
public function option($key, $default = null)
{
return isset($this->options->$key) ? $this->options->$key : $default ;
}
}
28 changes: 24 additions & 4 deletions app/CourseLoader.php
Original file line number Diff line number Diff line change
Expand Up @@ -90,16 +90,22 @@ public function importFromFolder($dirname)
* @param $obj
* @param $data
* @param $props
* @param $optionalProps
* @throws ImportError
*/
protected function setData($obj, $data, $props)
protected function setData($obj, $data, $props, $optionalProps = [])
{
foreach ($props as $prop) {
if (!isset($data->{$prop})) {
throw new ImportError("No '$prop' field found in {$obj->name}");
}
$obj->{$prop} = $data->{$prop};
}
foreach ($optionalProps as $prop) {
if (isset($data->{$prop})) {
$obj->{$prop} = $data->{$prop};
}
}
}

/**
Expand All @@ -112,10 +118,20 @@ protected function setData($obj, $data, $props)
*/
public function courseFromJson($courseName, $data)
{
$props = ['header', 'headertext', 'footer', 'modules', 'repo'];
$props = [
'header',
'headertext',
'footer',
'modules',
'repo',
];

$optionalProps = [
'options',
];

$course = Course::firstOrNew(['name' => $courseName]);
$this->setData($course, $data, $props);
$this->setData($course, $data, $props, $optionalProps);

return $course;
}
Expand All @@ -131,7 +147,11 @@ public function courseFromJson($courseName, $data)
*/
public function exerciseFromJson(Course $course, $exerciseName, $data)
{
$props = ['type', 'content', 'answer'];
$props = [
'type',
'content',
'answer',
];

$exercise = Exercise::firstOrNew([
'course_id' => $course->id,
Expand Down
12 changes: 11 additions & 1 deletion app/Http/Controllers/ExerciseController.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,12 @@

namespace App\Http\Controllers;

use App\AnalyticsEvent;
use App\Course;
use App\Exercise;
use Carbon\Carbon;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use App\Exercise;

class ExerciseController extends Controller
{
Expand Down Expand Up @@ -63,6 +65,14 @@ public function checkAnswers(Request $request)
'answer' => $answer,
'isCorrect' => $isCorrect[$exercise->id],
]);
AnalyticsEvent::create([
'event_type' => 'answer',
'data' => [
'name' => $exercise->name,
'answer' => $answer,
'isCorrect' => $isCorrect[$exercise->id],
],
]);
}
return response()->json($isCorrect);
}
Expand Down
16 changes: 16 additions & 0 deletions app/Observers/AnalyticsEventObserver.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<?php

namespace App\Observers;

use App\AnalyticsEvent;
use Carbon\Carbon;

class AnalyticsEventObserver
{
public function creating(AnalyticsEvent $evt)
{
// Append timestamp and session id
$evt->timestamp = Carbon::now();
$evt->session_id = sha1(\Request::session()->getId());
}
}
3 changes: 3 additions & 0 deletions app/Providers/EventServiceProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@

namespace App\Providers;

use App\Observers\AnalyticsEventObserver;
use App\Observers\UserObserver;
use App\AnalyticsEvent;
use App\User;
use Illuminate\Foundation\Support\Providers\EventServiceProvider as ServiceProvider;

Expand Down Expand Up @@ -34,5 +36,6 @@ public function boot()
parent::boot();

User::observe($this->app->make(UserObserver::class));
AnalyticsEvent::observe($this->app->make(AnalyticsEventObserver::class));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
<?php

use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;

// phpcs:disable PSR1.Classes.ClassDeclaration.MissingNamespace
class CreateAnalyticsEventsTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('analytics_events', function (Blueprint $table) {
$table->increments('id');
$table->dateTime('timestamp');
$table->text('event_type');
$table->text('session_id');
$table->json('data');
});
}

/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('analytics_events');
}
}
33 changes: 33 additions & 0 deletions database/migrations/2018_05_24_172405_add_course_options.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
<?php

use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;

// phpcs:disable PSR1.Classes.ClassDeclaration.MissingNamespace
class AddCourseOptions extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::table('courses', function (Blueprint $table) {
$table->json('options')->default('{}');
});
}

/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::table('courses', function (Blueprint $table) {
$table->dropColumn('options');
});
}
}
11 changes: 11 additions & 0 deletions resources/views/courses/show.blade.php
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,17 @@
</div>
</div>

<div class="container-fluid">
@if ($course->option('show_privacy_statement'))
<p class="text-small text-muted">
Personvern: Dette er et anonymt nettkurs.
Vi lagrer svar på oppgaver for statistikkformål og for å kunne forbedre kurset,
men knytter de ikke til brukerkonto, IP-adresse eller noe annet
som kan identifisere deg.<!-- For mer informasjon, se <a href="/personvern">personvern</a>.-->
</p>
@endif
</div>

@foreach ($course->modules as $id => $module)
<course-module class="module" course-id="{{ $course->id }}" module-id="{{ $id }}" image="resources/{{ $module->image }}" :image-aspect-ratio="{{ isset($module->imageaspectratio) ? $module->imageaspectratio : 4 }}" name="{{ $module->name }}">
{!! $module->html !!}
Expand Down

0 comments on commit a63ea43

Please sign in to comment.