Overview
Assignments are the core of Wecode’s functionality, allowing instructors to create timed programming contests with multiple problems, automatic grading, and scoreboards.
Assignment Model
The Assignment model contains comprehensive configuration options:
protected $fillable = [
"name" ,
"total_submits" ,
"open" ,
"score_board" ,
"javaexceptions" ,
"start_time" ,
"finish_time" ,
"extra_time" ,
"late_rule" ,
"participants" ,
"description" ,
"user_id" ,
"language_ids" ,
];
Key Fields
Timing
start_time: When assignment becomes available
finish_time: Official deadline
extra_time: Additional time allowed (in seconds)
Configuration
open: Whether students can submit (0/1)
score_board: Enable public scoreboard (0/1)
late_rule: Formula for late penalty calculation
language_ids: Comma-separated allowed language IDs
Creating Assignments
Route: POST /assignments
Basic Creation
assignment_controller.php:154-197
public function store ( Request $request )
{
if ( ! in_array ( Auth :: user () -> role -> name , [ 'admin' , 'head_instructor' ]) )
abort ( 403 , 'You do not have permission to add assignment' );
$validated = $request -> validate ([
'name' => [ 'required' , 'max:150' ],
'pdf_file' => 'mimes:pdf' ,
]);
$input = $request -> input ();
$this -> _process_form ( $input );
$assignment = new Assignment ;
$assignment -> fill ( $input );
$assignment -> user_id = Auth :: user () -> id ;
$assignment -> save ();
// Attach problems
foreach ( $request -> problem_id as $i => $id )
{
if ( $id == - 1 ) continue ;
$assignment -> problems () -> attach ([
$id => [
'problem_name' => $request -> problem_name [ $i ],
'score' => $request -> problem_score [ $i ],
'ordering' => $i
],
]);
}
// Attach classes (lops)
if ( $request -> lop_id != NULL )
{
foreach ( $request -> lop_id as $i => $id )
{
$assignment -> lops () -> attach ( $id );
}
}
return redirect ( 'assignments' );
}
Time Processing
Adding Problems to Assignments
Problems are attached with custom names and scores:
assignment_controller.php:180-185
foreach ( $request -> problem_id as $i => $id )
{
if ( $id == - 1 ) continue ;
$assignment -> problems () -> attach ([
$id => [ 'problem_name' => $request -> problem_name [ $i ], 'score' => $request -> problem_score [ $i ], 'ordering' => $i ],
]);
}
Problem Pivot Data
public function problems ()
{
return $this -> belongsToMany ( "App\Models\Problem" )
-> withPivot ( "score" , "ordering" , "problem_name" )
-> withTimestamps ();
}
problem_name : Custom name for problem in this assignment
score : Maximum points for this problem
ordering : Display order in assignment
Opening and Closing Assignments
Route: POST /assignment/check_open
assignment_controller.php:574-591
public function check_open ( Request $request )
{
$assignment_id = $request -> assignment_id ;
$assignment = Assignment :: find ( $assignment_id );
if ( $assignment != NULL ){
if (( $t = $assignment -> cannot_edit ( Auth :: user ())) !== false ){
echo "error, " . $t ;
return ;
}
$assignment -> open =! $assignment -> open ;
$assignment -> save ();
echo "success" ;
return ;
}
else
echo "error" ;
}
Submission Rules
Assignments enforce strict submission rules:
public function can_submit ( User $user , Problem $problem = null )
{
$result = new class {};
$result -> error_message = "Unknown error" ;
$result -> can_submit = false ;
// Check if trial account expired
if (
$user -> trial_time &&
in_array ( $user -> role -> name , [ "student" ]) &&
$user -> created_at -> addHours ( $user -> trial_time ) <= Carbon :: now ()
) {
$user -> role_id = 5 ; //Convert to guest
$user -> save ();
}
if ( in_array ( $user -> role -> name , [ "guest" ])) {
$result -> error_message = "Guest can not make submissions" ;
}
elseif ( in_array ( $user -> role -> name , [ "student" ]) && $this -> open == 0 ) {
$result -> error_message = "You cannot submit, selected assignment is closed." ;
}
elseif ( ! $this -> started () && in_array ( $user -> role -> name , [ "student" ])) {
$result -> error_message = "You cannot submit, Selected assignment has not started." ;
}
elseif (
$this -> start_time < $this -> finish_time &&
Carbon :: now () > $this -> finish_time -> addSeconds ( $this -> extra_time )
) {
$result -> error_message = "You cannot submit, Selected assignment has finished." ;
}
elseif ( ! $this -> is_participant ( $user )) {
$result -> error_message = "You cannot submit, You are not registered." ;
}
else {
$result -> error_message = "none" ;
$result -> can_submit = true ;
}
return $result ;
}
Late Submission Penalties
Calculate score penalties using custom formulas:
delay = seconds after finish_time
extra_time = assignment.extra_time
submit_time = seconds after start_time
Downloading Submissions
By User or Problem
Route: GET /assignment/download_submissions/{type}/{assignment_id}
assignment_controller.php:514-555
public function download_submissions ( $type , $assignment_id )
{
if ( ! in_array ( Auth :: user () -> role -> name , [ 'admin' , 'head_instructor' , 'instructor' ]) )
abort ( 403 );
$final_subs = Submission :: get_final_submissions ( $assignment_id );
$zip = new ZipArchive ;
if ( $type === 'by_user' )
$zip_name = $assignments_root . "/assignment" . ( string ) $assignment_id . "_submissions_by_user_" . ( string ) date ( 'Y-m-d_H-i' ) . ".zip" ;
elseif ( $type === 'by_problem' )
$zip_name = $assignments_root . "/assignment" . ( string ) $assignment_id . "_submissions_by_problem_" . ( string ) date ( 'Y-m-d_H-i' ) . ".zip" ;
$zip -> open ( $zip_name , ZipArchive :: CREATE | ZipArchive :: OVERWRITE );
foreach ( $final_subs as $final_sub )
{
$file_path = Submission :: get_path ( $final_sub -> username , $assignment_id , $final_sub -> problem_id )
. "/" . ( string ) $final_sub -> file_name . "." . ( string ) Language :: find ( $final_sub -> language_id ) -> extension ;
if ( ! file_exists ( $file_path ))
continue ;
$file = file_get_contents ( $file_path );
if ( $type === 'by_user' )
$zip -> addFromString ( "{ $final_sub -> username }/problem_{ $final_sub -> problem_id }." . ( string ) Language :: find ( $final_sub -> language_id ) -> extension , $file );
elseif ( $type === 'by_problem' )
$zip -> addFromString ( "problem_{ $final_sub -> problem_id }/{ $final_sub -> username }." . ( string ) Language :: find ( $final_sub -> language_id ) -> extension , $file );
}
$zip -> close ();
return response () -> download ( $zip_name ) -> deleteFileAfterSend ();
}
All Submissions and Tests
Route: GET /assignment/download_all_submissions/{assignment_id}
assignment_controller.php:497-512
public function download_all_submissions ( $assignment_id )
{
if ( ! in_array ( Auth :: user () -> role -> name , [ 'admin' , 'head_instructor' , 'instructor' ]) )
abort ( 403 );
$ass = Assignment :: find ( $assignment_id ) ;
if ( $ass == null )
abort ( 404 );
if ( $ass -> submissions -> count () == 0 ) abort ( 404 );
$assignments_root = Setting :: get ( "assignments_root" );
$zipFile = $assignments_root . "/assignment" . ( string ) $assignment_id . "." . ( string ) date ( 'Y-m-d_H-i' ) . ".zip" ;
$pathdir = $assignments_root . '/assignment_' . $assignment_id . "/" ;
shell_exec ( "zip -r $zipFile $pathdir " );
return response () -> download ( $zipFile ) -> deleteFileAfterSend ();
}
Duplicating Assignments
Route: GET /assignment/duplicate/{assignment}
assignment_controller.php:327-341
public function duplicate ( Assignment $assignment ){
if (( $t = $assignment -> cannot_edit ( Auth :: user ())) !== false ){
abort ( 403 , $t );
}
$new = $assignment -> replicate ();
$new -> user_id = Auth :: user () -> id ;
$new -> total_submits = 0 ;
$new -> save ();
foreach ( $assignment -> problems as $p ) {
$new -> problems () -> attach ( $p -> id , [
'score' => $p -> pivot -> score ,
'problem_name' => $p -> pivot -> problem_name ,
'ordering' => $p -> pivot -> ordering
]);
}
return redirect () -> route ( 'assignments.index' );
}
Assignment Routes
Method Route Action Permission GET /assignmentsList assignments authenticated GET /assignments/createCreate form admin, head_instructor POST /assignmentsStore assignment admin, head_instructor GET /assignment/{id}/{problem}View problem participant GET /assignment/{id}/{problem}/pdfDownload PDF participant GET /assignments/{id}/editEdit form owner, admin PUT /assignments/{id}Update owner, admin DELETE /assignments/{id}Delete owner, admin POST /assignment/check_openToggle open/close owner, admin GET /assignment/duplicate/{id}Duplicate owner, admin GET /assignment/download_submissions/{type}/{id}Download finals instructor+ GET /assignment/download_all_submissions/{id}Download all instructor+ GET /assignment/reload_scoreboard/{id}Reload scores instructor+
Edit Permissions
public function cannot_edit ( User $actor )
{
if ( $actor -> role -> name == "admin" ) {
return false ;
} elseif ( $actor -> role -> name == "head_instructor" ) {
if (
$this -> user -> id != $actor -> id &&
! $actor
-> lops ()
-> with ( "assignments" )
-> get ()
-> pluck ( "assignments" )
-> collapse ()
-> pluck ( "id" )
-> contains ( $this -> id )
) {
return "You can only edit assignment you created or assignment belongs to one of your classes" ;
} else {
return false ;
}
} else {
return "You do not have permission to edit assignment" ;
}
}
Best Practices
Timing
Set start_time before finish_time
Use extra_time for grace period
Test late_rule formulas before use
Consider timezone of students
Problems
Order problems by difficulty
Set appropriate scores
Test all problems before opening
Provide clear problem names
Configuration
Limit allowed languages if needed
Enable scoreboard appropriately
Keep assignment closed until ready
Set reasonable extra_time
Management
Monitor submissions regularly
Download backups after deadline
Review scoreboard for anomalies
Communicate deadline clearly