Spaces:
Runtime error
Runtime error
Commit ·
db7ff15
1
Parent(s): d877823
Deploy files from GitHub repository
Browse files- controllers/event_controller.go +2 -2
- models/entity/entity.go +130 -130
- repositories/exam_event_answer_repository.go +9 -9
- repositories/exam_event_assign_repository.go +2 -2
- repositories/exam_event_attempt_repository.go +11 -12
- repositories/exam_event_repository.go +5 -5
- repositories/problem_set_exam_assign_repository.go +2 -2
- repositories/problem_set_repository.go +3 -3
- repositories/question_repository.go +5 -5
- repositories/result_repository.go +18 -11
- router/event_router.go +1 -1
- router/exam_event_router.go +6 -5
- services/exam_event_service.go +66 -42
- utils/util.go +1 -1
controllers/event_controller.go
CHANGED
|
@@ -38,10 +38,10 @@ func (c *eventController) List(ctx *gin.Context) {
|
|
| 38 |
}
|
| 39 |
|
| 40 |
func (c *eventController) DetailBySlug(ctx *gin.Context) {
|
| 41 |
-
slug := ctx.Param("
|
| 42 |
accountId := ParseAccountId(ctx)
|
| 43 |
res, err := c.eventService.DetailBySlug(ctx.Request.Context(), slug, accountId)
|
| 44 |
-
ResponseJSON(ctx, gin.H{"
|
| 45 |
}
|
| 46 |
|
| 47 |
func (c *eventController) Join(ctx *gin.Context) {
|
|
|
|
| 38 |
}
|
| 39 |
|
| 40 |
func (c *eventController) DetailBySlug(ctx *gin.Context) {
|
| 41 |
+
slug := ctx.Param("event_slug")
|
| 42 |
accountId := ParseAccountId(ctx)
|
| 43 |
res, err := c.eventService.DetailBySlug(ctx.Request.Context(), slug, accountId)
|
| 44 |
+
ResponseJSON(ctx, gin.H{"event_slug": slug, "id_account": accountId}, res, err)
|
| 45 |
}
|
| 46 |
|
| 47 |
func (c *eventController) Join(ctx *gin.Context) {
|
models/entity/entity.go
CHANGED
|
@@ -4,205 +4,206 @@ import (
|
|
| 4 |
"time"
|
| 5 |
|
| 6 |
"github.com/google/uuid"
|
|
|
|
| 7 |
)
|
| 8 |
|
| 9 |
type Account struct {
|
| 10 |
Id uuid.UUID `gorm:"type:uuid;primary_key;default:uuid_generate_v4()" json:"id"`
|
| 11 |
-
Username string `gorm:"uniqueIndex" json:"username"`
|
| 12 |
-
Email string `gorm:"uniqueIndex" json:"email"`
|
| 13 |
-
Role string `json:"role"`
|
| 14 |
Password string `json:"-"`
|
| 15 |
-
IsEmailVerified bool `json:"is_email_verified"`
|
| 16 |
-
IsDetailCompleted bool `json:"is_detail_completed"`
|
| 17 |
-
CreatedAt time.Time `json:"created_at"`
|
| 18 |
-
DeletedAt *time.Time `json:"deleted_at" gorm:"default:null"`
|
| 19 |
}
|
| 20 |
|
| 21 |
func (Account) TableName() string { return "account" }
|
| 22 |
|
| 23 |
type AccountDetail struct {
|
| 24 |
Id uuid.UUID `gorm:"type:uuid;primary_key;default:uuid_generate_v4()" json:"id"`
|
| 25 |
-
AccountId uuid.UUID `json:"account_id"`
|
| 26 |
-
FullName *string `json:"full_name"`
|
| 27 |
-
SchoolName *string `json:"school_name"`
|
| 28 |
-
Province *string `json:"province"`
|
| 29 |
-
City *string `json:"city"`
|
| 30 |
-
Avatar *string `json:"avatar"`
|
| 31 |
-
PhoneNumber *string `json:"phone_number"`
|
| 32 |
-
Account *Account `gorm:"foreignKey:AccountId"`
|
| 33 |
}
|
| 34 |
|
| 35 |
func (AccountDetail) TableName() string { return "account_details" }
|
| 36 |
|
| 37 |
type EmailVerification struct {
|
| 38 |
Id uuid.UUID `gorm:"type:uuid;primary_key;default:uuid_generate_v4()" json:"id"`
|
| 39 |
-
Token uint `json:"token"`
|
| 40 |
-
AccountId uuid.UUID `json:"account_id"`
|
| 41 |
-
IsExpired bool `json:"is_expired"`
|
| 42 |
-
CreatedAt time.Time `json:"created_at"`
|
| 43 |
-
ExpiredAt time.Time `json:"expired_at"`
|
| 44 |
-
Account *Account `gorm:"foreignKey:AccountId"`
|
| 45 |
}
|
| 46 |
|
| 47 |
func (EmailVerification) TableName() string { return "email_verification" }
|
| 48 |
|
| 49 |
type ExternalAuth struct {
|
| 50 |
Id uuid.UUID `gorm:"type:uuid;primary_key;default:uuid_generate_v4()" json:"id"`
|
| 51 |
-
OauthID string `json:"oauth_id"`
|
| 52 |
-
AccountId uuid.UUID `json:"account_id"`
|
| 53 |
-
OauthProvider string `json:"oauth_provider"`
|
| 54 |
}
|
| 55 |
|
| 56 |
func (ExternalAuth) TableName() string { return "external_auth" }
|
| 57 |
|
| 58 |
type FCM struct {
|
| 59 |
Id uuid.UUID `gorm:"type:uuid;primary_key;default:uuid_generate_v4()" json:"id"`
|
| 60 |
-
AccountId uuid.UUID `json:"account_id"`
|
| 61 |
-
FCMToken string `json:"fcm_token"`
|
| 62 |
}
|
| 63 |
|
| 64 |
func (FCM) TableName() string { return "fcm" }
|
| 65 |
|
| 66 |
type ForgotPassword struct {
|
| 67 |
Id uuid.UUID `gorm:"type:uuid;primary_key;default:uuid_generate_v4()" json:"id"`
|
| 68 |
-
Token uint `json:"token"`
|
| 69 |
-
AccountId uuid.UUID `json:"account_id"`
|
| 70 |
-
IsExpired bool `json:"is_expired"`
|
| 71 |
-
CreatedAt time.Time `json:"created_at"`
|
| 72 |
-
ExpiredAt time.Time `json:"expired_at"`
|
| 73 |
}
|
| 74 |
|
| 75 |
func (ForgotPassword) TableName() string { return "forgot_password" }
|
| 76 |
|
| 77 |
type Events struct {
|
| 78 |
Id uuid.UUID `gorm:"type:uuid;primary_key;default:uuid_generate_v4()" json:"id_event"`
|
| 79 |
-
Title string `json:"title"`
|
| 80 |
-
Slug string `json:"slug"`
|
| 81 |
-
StartEvent time.Time `json:"start_event"`
|
| 82 |
-
EndEvent time.Time `json:"end_event"`
|
| 83 |
-
Overview string `json:"overview"`
|
| 84 |
-
EventCode string `json:"event_code"`
|
| 85 |
-
IsPublic bool `json:"is_public"`
|
| 86 |
}
|
| 87 |
|
| 88 |
func (Events) TableName() string { return "events" }
|
| 89 |
|
| 90 |
type Announcement struct {
|
| 91 |
Id uuid.UUID `gorm:"type:uuid;primary_key;default:uuid_generate_v4()" json:"id_announcement"`
|
| 92 |
-
Title string `json:"title"`
|
| 93 |
-
CreatedAt time.Time `json:"created_at"`
|
| 94 |
-
Message string `json:"message"`
|
| 95 |
-
Publisher string `json:"publisher"`
|
| 96 |
-
EventId uuid.UUID `json:"id_event"`
|
| 97 |
}
|
| 98 |
|
| 99 |
func (Announcement) TableName() string { return "announcement" }
|
| 100 |
|
| 101 |
type ProblemSet struct {
|
| 102 |
Id uuid.UUID `gorm:"type:uuid;primary_key;default:uuid_generate_v4()" json:"id_problem_set"`
|
| 103 |
-
Title string `json:"title"`
|
| 104 |
-
Description string `json:"description"`
|
| 105 |
}
|
| 106 |
|
| 107 |
func (ProblemSet) TableName() string { return "problem_set" }
|
| 108 |
|
| 109 |
type Exam struct {
|
| 110 |
Id uuid.UUID `gorm:"type:uuid;primary_key;default:uuid_generate_v4()" json:"id_exam"`
|
| 111 |
-
Slug string `json:"slug"`
|
| 112 |
-
Title string `json:"title"`
|
| 113 |
-
Description string `json:"description"`
|
| 114 |
-
Duration time.Duration `json:"duration"`
|
| 115 |
-
Randomize uint `json:"randomize"`
|
| 116 |
}
|
| 117 |
|
| 118 |
func (Exam) TableName() string { return "exam" }
|
| 119 |
|
| 120 |
type OptionCategory struct {
|
| 121 |
Id uint `gorm:"primaryKey" json:"id"`
|
| 122 |
-
OptionName string `json:"option_name"`
|
| 123 |
-
OptionSlug string `json:"option_slug"`
|
| 124 |
}
|
| 125 |
|
| 126 |
func (OptionCategory) TableName() string { return "option_category" }
|
| 127 |
|
| 128 |
type OptionValues struct {
|
| 129 |
Id uint `gorm:"primaryKey" json:"id"`
|
| 130 |
-
OptionCategoryId uint `json:"option_category_id"`
|
| 131 |
-
OptionValue string `json:"option_value"`
|
| 132 |
}
|
| 133 |
|
| 134 |
func (OptionValues) TableName() string { return "option_values" }
|
| 135 |
|
| 136 |
type RegionProvince struct {
|
| 137 |
Id uint `json:"id"`
|
| 138 |
-
Name string `json:"name"`
|
| 139 |
-
Code string `json:"code"`
|
| 140 |
}
|
| 141 |
|
| 142 |
func (RegionProvince) TableName() string { return "region_provinces" }
|
| 143 |
|
| 144 |
type RegionCity struct {
|
| 145 |
Id uint `json:"id"`
|
| 146 |
-
Type string `json:"type"`
|
| 147 |
-
Name string `json:"name"`
|
| 148 |
-
Code string `json:"code"`
|
| 149 |
-
FullCode string `json:"full_code"`
|
| 150 |
-
ProvinceId uint `json:"province_id"`
|
| 151 |
}
|
| 152 |
|
| 153 |
func (RegionCity) TableName() string { return "region_cities" }
|
| 154 |
|
| 155 |
type Options struct {
|
| 156 |
-
OptionCategory OptionCategory `json:"option_category"`
|
| 157 |
-
OptionValues []OptionValues `json:"option_values"`
|
| 158 |
}
|
| 159 |
|
| 160 |
func (Options) TableName() string { return "options" }
|
| 161 |
|
| 162 |
type EventAssign struct {
|
| 163 |
Id uuid.UUID `gorm:"type:uuid;primary_key;default:uuid_generate_v4()" json:"id_assign"`
|
| 164 |
-
AccountId uuid.UUID `json:"id_account"`
|
| 165 |
-
EventId uuid.UUID `json:"id_event"`
|
| 166 |
-
AssignedAt time.Time `json:"assigned_at"`
|
| 167 |
|
| 168 |
-
Account *Account `gorm:"foreignKey:AccountId"`
|
| 169 |
-
Event *Events `gorm:"foreignKey:EventId"`
|
| 170 |
}
|
| 171 |
|
| 172 |
func (EventAssign) TableName() string { return "event_assign" }
|
| 173 |
|
| 174 |
type Questions struct {
|
| 175 |
-
Id uuid.UUID
|
| 176 |
-
Type string
|
| 177 |
-
Question string
|
| 178 |
-
Options
|
| 179 |
-
AnsKey
|
| 180 |
-
CorrMark float64
|
| 181 |
-
IncorrMark float64
|
| 182 |
-
NullMark float64
|
| 183 |
-
ProblemSetId uuid.UUID
|
| 184 |
-
|
| 185 |
-
ProblemSet *ProblemSet `gorm:"foreignKey:ProblemSetId"`
|
| 186 |
}
|
| 187 |
|
| 188 |
func (Questions) TableName() string { return "questions" }
|
| 189 |
|
| 190 |
type ProblemSetExamAssign struct {
|
| 191 |
Id uuid.UUID `gorm:"type:uuid;primary_key;default:uuid_generate_v4()" json:"id_problem_set_exam_assign"`
|
| 192 |
-
ExamId uuid.UUID `json:"id_exam"`
|
| 193 |
-
ProblemSetId uuid.UUID `json:"id_problem_set"`
|
| 194 |
-
Exam *Exam `gorm:"foreignKey:ExamId"`
|
| 195 |
-
ProblemSet *ProblemSet `gorm:"foreignKey:ProblemSetId"`
|
| 196 |
}
|
| 197 |
|
| 198 |
func (ProblemSetExamAssign) TableName() string { return "problem_set_exam_assign" }
|
| 199 |
|
| 200 |
type ExamEventAssign struct {
|
| 201 |
Id uuid.UUID `gorm:"type:uuid;primary_key;default:uuid_generate_v4()" json:"id_exam_event_assign"`
|
| 202 |
-
EventId uuid.UUID `json:"id_event"`
|
| 203 |
-
ExamId uuid.UUID `json:"id_exam"`
|
| 204 |
-
Exam *Exam `gorm:"foreignKey:ExamId"`
|
| 205 |
-
Event *Events `gorm:"foreignKey:EventId"`
|
| 206 |
}
|
| 207 |
|
| 208 |
func (ExamEventAssign) TableName() string { return "exam_event_assign" }
|
|
@@ -210,94 +211,93 @@ func (ExamEventAssign) TableName() string { return "exam_event_assign" }
|
|
| 210 |
type CPQuestionVerdict struct {
|
| 211 |
TimeExecution float32 `json:"time_exec"`
|
| 212 |
MemoryUsage float32 `json:"memory"`
|
| 213 |
-
Verdict string `json:"verdict"`
|
| 214 |
Score float32 `json:"score"`
|
| 215 |
}
|
|
|
|
| 216 |
type ExamEventAnswer struct {
|
| 217 |
Id uuid.UUID `gorm:"type:uuid;primary_key;default:uuid_generate_v4()" json:"id"`
|
| 218 |
-
AttemptId uuid.UUID `json:"id_attempt" gorm:"index"`
|
| 219 |
-
QuestionId uuid.UUID `json:"id_question" gorm:"index"`
|
| 220 |
-
Answers
|
| 221 |
Score float32 `json:"score"`
|
| 222 |
-
ExamEventAttempt *ExamEventAttempt `gorm:"foreignKey:AttemptId" json:"
|
| 223 |
-
CreatedAt time.Time `json:"created_at"`
|
| 224 |
-
UpdatedAt time.Time `json:"updated_at"`
|
| 225 |
}
|
| 226 |
|
| 227 |
func (ExamEventAnswer) TableName() string { return "exam_event_answer" }
|
| 228 |
|
| 229 |
type ExamEventAttempt struct {
|
| 230 |
-
Id uuid.UUID
|
| 231 |
-
AccountId uuid.UUID
|
| 232 |
-
EventId uuid.UUID
|
| 233 |
-
ExamId uuid.UUID
|
| 234 |
-
Questions
|
| 235 |
-
Answers
|
| 236 |
-
Account *Account
|
| 237 |
-
Event *Events
|
| 238 |
-
Exam *Exam
|
| 239 |
-
RemTime int
|
| 240 |
-
Mark float32
|
| 241 |
-
CreatedAt time.Time
|
| 242 |
-
DueAt time.Time
|
| 243 |
-
Submitted bool
|
| 244 |
}
|
| 245 |
|
| 246 |
func (ExamEventAttempt) TableName() string { return "exam_event_attempt" }
|
| 247 |
|
| 248 |
type Result struct {
|
| 249 |
-
Id
|
| 250 |
-
|
| 251 |
-
FinalScore
|
| 252 |
-
ExamEventAttempt
|
| 253 |
}
|
| 254 |
|
| 255 |
func (Result) TableName() string { return "result" }
|
| 256 |
|
| 257 |
type Academy struct {
|
| 258 |
Id uuid.UUID `gorm:"primaryKey" json:"id"`
|
| 259 |
-
Title string `json:"title"`
|
| 260 |
-
Slug string `json:"slug"`
|
| 261 |
-
Description string `json:"description"`
|
| 262 |
}
|
| 263 |
|
| 264 |
func (Academy) TableName() string { return "academy" }
|
| 265 |
|
| 266 |
type AcademyMaterial struct {
|
| 267 |
Id uuid.UUID `gorm:"primaryKey" json:"id"`
|
| 268 |
-
AcademyId uuid.UUID `json:"academy_id"`
|
| 269 |
-
Title string `json:"title"`
|
| 270 |
-
Slug string `json:"slug"`
|
| 271 |
-
Description string `json:"description"`
|
| 272 |
}
|
| 273 |
|
| 274 |
func (AcademyMaterial) TableName() string { return "academy_materials" }
|
| 275 |
|
| 276 |
type AcademyContent struct {
|
| 277 |
Id uuid.UUID `gorm:"primaryKey" json:"id"`
|
| 278 |
-
Title string `json:"title"`
|
| 279 |
-
Order uint `json:"order"`
|
| 280 |
-
AcademyMaterialId uuid.UUID `json:"academy_material_id"`
|
| 281 |
-
Contents string `json:"contents"`
|
| 282 |
}
|
| 283 |
|
| 284 |
func (AcademyContent) TableName() string { return "academy_contents" }
|
| 285 |
|
| 286 |
type AcademyMaterialProgress struct {
|
| 287 |
Id uuid.UUID `gorm:"primaryKey" json:"id"`
|
| 288 |
-
AccountId uint `json:"account_id"`
|
| 289 |
-
AcademyMaterialId uuid.UUID `json:"academy_material_id"`
|
| 290 |
-
Progress uint `json:"progress"`
|
| 291 |
}
|
| 292 |
|
| 293 |
func (AcademyMaterialProgress) TableName() string { return "academy_materials_progress" }
|
| 294 |
|
| 295 |
type AcademyContentProgress struct {
|
| 296 |
Id uuid.UUID `gorm:"primaryKey" json:"id"`
|
| 297 |
-
AccountId uuid.UUID `json:"account_id"`
|
| 298 |
-
AcademyId uuid.UUID `json:"academy_id"`
|
| 299 |
}
|
| 300 |
|
| 301 |
func (AcademyContentProgress) TableName() string { return "academy_contents_progress" }
|
| 302 |
-
|
| 303 |
-
// Gorm table name settings
|
|
|
|
| 4 |
"time"
|
| 5 |
|
| 6 |
"github.com/google/uuid"
|
| 7 |
+
"github.com/lib/pq"
|
| 8 |
)
|
| 9 |
|
| 10 |
type Account struct {
|
| 11 |
Id uuid.UUID `gorm:"type:uuid;primary_key;default:uuid_generate_v4()" json:"id"`
|
| 12 |
+
Username string `gorm:"uniqueIndex" json:"username,omitempty"`
|
| 13 |
+
Email string `gorm:"uniqueIndex" json:"email,omitempty"`
|
| 14 |
+
Role string `json:"role,omitempty"`
|
| 15 |
Password string `json:"-"`
|
| 16 |
+
IsEmailVerified bool `json:"is_email_verified,omitempty"`
|
| 17 |
+
IsDetailCompleted bool `json:"is_detail_completed,omitempty"`
|
| 18 |
+
CreatedAt time.Time `json:"created_at,omitempty"`
|
| 19 |
+
DeletedAt *time.Time `json:"deleted_at,omitempty" gorm:"default:null"`
|
| 20 |
}
|
| 21 |
|
| 22 |
func (Account) TableName() string { return "account" }
|
| 23 |
|
| 24 |
type AccountDetail struct {
|
| 25 |
Id uuid.UUID `gorm:"type:uuid;primary_key;default:uuid_generate_v4()" json:"id"`
|
| 26 |
+
AccountId uuid.UUID `json:"account_id,omitempty"`
|
| 27 |
+
FullName *string `json:"full_name,omitempty"`
|
| 28 |
+
SchoolName *string `json:"school_name,omitempty"`
|
| 29 |
+
Province *string `json:"province,omitempty"`
|
| 30 |
+
City *string `json:"city,omitempty"`
|
| 31 |
+
Avatar *string `json:"avatar,omitempty"`
|
| 32 |
+
PhoneNumber *string `json:"phone_number,omitempty"`
|
| 33 |
+
Account *Account `gorm:"foreignKey:AccountId" json:"account,omitempty"`
|
| 34 |
}
|
| 35 |
|
| 36 |
func (AccountDetail) TableName() string { return "account_details" }
|
| 37 |
|
| 38 |
type EmailVerification struct {
|
| 39 |
Id uuid.UUID `gorm:"type:uuid;primary_key;default:uuid_generate_v4()" json:"id"`
|
| 40 |
+
Token uint `json:"token,omitempty"`
|
| 41 |
+
AccountId uuid.UUID `json:"account_id,omitempty"`
|
| 42 |
+
IsExpired bool `json:"is_expired,omitempty"`
|
| 43 |
+
CreatedAt time.Time `json:"created_at,omitempty"`
|
| 44 |
+
ExpiredAt time.Time `json:"expired_at,omitempty"`
|
| 45 |
+
Account *Account `gorm:"foreignKey:AccountId" json:"account,omitempty"`
|
| 46 |
}
|
| 47 |
|
| 48 |
func (EmailVerification) TableName() string { return "email_verification" }
|
| 49 |
|
| 50 |
type ExternalAuth struct {
|
| 51 |
Id uuid.UUID `gorm:"type:uuid;primary_key;default:uuid_generate_v4()" json:"id"`
|
| 52 |
+
OauthID string `json:"oauth_id,omitempty"`
|
| 53 |
+
AccountId uuid.UUID `json:"account_id,omitempty"`
|
| 54 |
+
OauthProvider string `json:"oauth_provider,omitempty"`
|
| 55 |
}
|
| 56 |
|
| 57 |
func (ExternalAuth) TableName() string { return "external_auth" }
|
| 58 |
|
| 59 |
type FCM struct {
|
| 60 |
Id uuid.UUID `gorm:"type:uuid;primary_key;default:uuid_generate_v4()" json:"id"`
|
| 61 |
+
AccountId uuid.UUID `json:"account_id,omitempty"`
|
| 62 |
+
FCMToken string `json:"fcm_token,omitempty"`
|
| 63 |
}
|
| 64 |
|
| 65 |
func (FCM) TableName() string { return "fcm" }
|
| 66 |
|
| 67 |
type ForgotPassword struct {
|
| 68 |
Id uuid.UUID `gorm:"type:uuid;primary_key;default:uuid_generate_v4()" json:"id"`
|
| 69 |
+
Token uint `json:"token,omitempty"`
|
| 70 |
+
AccountId uuid.UUID `json:"account_id,omitempty"`
|
| 71 |
+
IsExpired bool `json:"is_expired,omitempty"`
|
| 72 |
+
CreatedAt time.Time `json:"created_at,omitempty"`
|
| 73 |
+
ExpiredAt time.Time `json:"expired_at,omitempty"`
|
| 74 |
}
|
| 75 |
|
| 76 |
func (ForgotPassword) TableName() string { return "forgot_password" }
|
| 77 |
|
| 78 |
type Events struct {
|
| 79 |
Id uuid.UUID `gorm:"type:uuid;primary_key;default:uuid_generate_v4()" json:"id_event"`
|
| 80 |
+
Title string `json:"title,omitempty"`
|
| 81 |
+
Slug string `json:"slug,omitempty"`
|
| 82 |
+
StartEvent time.Time `json:"start_event,omitempty"`
|
| 83 |
+
EndEvent time.Time `json:"end_event,omitempty"`
|
| 84 |
+
Overview string `json:"overview,omitempty"`
|
| 85 |
+
EventCode string `json:"event_code,omitempty"`
|
| 86 |
+
IsPublic bool `json:"is_public,omitempty"`
|
| 87 |
}
|
| 88 |
|
| 89 |
func (Events) TableName() string { return "events" }
|
| 90 |
|
| 91 |
type Announcement struct {
|
| 92 |
Id uuid.UUID `gorm:"type:uuid;primary_key;default:uuid_generate_v4()" json:"id_announcement"`
|
| 93 |
+
Title string `json:"title,omitempty"`
|
| 94 |
+
CreatedAt time.Time `json:"created_at,omitempty"`
|
| 95 |
+
Message string `json:"message,omitempty"`
|
| 96 |
+
Publisher string `json:"publisher,omitempty"`
|
| 97 |
+
EventId uuid.UUID `json:"id_event,omitempty"`
|
| 98 |
}
|
| 99 |
|
| 100 |
func (Announcement) TableName() string { return "announcement" }
|
| 101 |
|
| 102 |
type ProblemSet struct {
|
| 103 |
Id uuid.UUID `gorm:"type:uuid;primary_key;default:uuid_generate_v4()" json:"id_problem_set"`
|
| 104 |
+
Title string `json:"title,omitempty"`
|
| 105 |
+
Description string `json:"description,omitempty"`
|
| 106 |
}
|
| 107 |
|
| 108 |
func (ProblemSet) TableName() string { return "problem_set" }
|
| 109 |
|
| 110 |
type Exam struct {
|
| 111 |
Id uuid.UUID `gorm:"type:uuid;primary_key;default:uuid_generate_v4()" json:"id_exam"`
|
| 112 |
+
Slug string `json:"slug,omitempty"`
|
| 113 |
+
Title string `json:"title,omitempty"`
|
| 114 |
+
Description string `json:"description,omitempty"`
|
| 115 |
+
Duration time.Duration `json:"duration,omitempty"`
|
| 116 |
+
Randomize uint `json:"randomize,omitempty"`
|
| 117 |
}
|
| 118 |
|
| 119 |
func (Exam) TableName() string { return "exam" }
|
| 120 |
|
| 121 |
type OptionCategory struct {
|
| 122 |
Id uint `gorm:"primaryKey" json:"id"`
|
| 123 |
+
OptionName string `json:"option_name,omitempty"`
|
| 124 |
+
OptionSlug string `json:"option_slug,omitempty"`
|
| 125 |
}
|
| 126 |
|
| 127 |
func (OptionCategory) TableName() string { return "option_category" }
|
| 128 |
|
| 129 |
type OptionValues struct {
|
| 130 |
Id uint `gorm:"primaryKey" json:"id"`
|
| 131 |
+
OptionCategoryId uint `json:"option_category_id,omitempty"`
|
| 132 |
+
OptionValue string `json:"option_value,omitempty"`
|
| 133 |
}
|
| 134 |
|
| 135 |
func (OptionValues) TableName() string { return "option_values" }
|
| 136 |
|
| 137 |
type RegionProvince struct {
|
| 138 |
Id uint `json:"id"`
|
| 139 |
+
Name string `json:"name,omitempty"`
|
| 140 |
+
Code string `json:"code,omitempty"`
|
| 141 |
}
|
| 142 |
|
| 143 |
func (RegionProvince) TableName() string { return "region_provinces" }
|
| 144 |
|
| 145 |
type RegionCity struct {
|
| 146 |
Id uint `json:"id"`
|
| 147 |
+
Type string `json:"type,omitempty"`
|
| 148 |
+
Name string `json:"name,omitempty"`
|
| 149 |
+
Code string `json:"code,omitempty"`
|
| 150 |
+
FullCode string `json:"full_code,omitempty"`
|
| 151 |
+
ProvinceId uint `json:"province_id,omitempty"`
|
| 152 |
}
|
| 153 |
|
| 154 |
func (RegionCity) TableName() string { return "region_cities" }
|
| 155 |
|
| 156 |
type Options struct {
|
| 157 |
+
OptionCategory OptionCategory `json:"option_category,omitempty"`
|
| 158 |
+
OptionValues []OptionValues `json:"option_values,omitempty"`
|
| 159 |
}
|
| 160 |
|
| 161 |
func (Options) TableName() string { return "options" }
|
| 162 |
|
| 163 |
type EventAssign struct {
|
| 164 |
Id uuid.UUID `gorm:"type:uuid;primary_key;default:uuid_generate_v4()" json:"id_assign"`
|
| 165 |
+
AccountId uuid.UUID `json:"id_account,omitempty"`
|
| 166 |
+
EventId uuid.UUID `json:"id_event,omitempty"`
|
| 167 |
+
AssignedAt time.Time `json:"assigned_at,omitempty"`
|
| 168 |
|
| 169 |
+
Account *Account `gorm:"foreignKey:AccountId" json:"account,omitempty"`
|
| 170 |
+
Event *Events `gorm:"foreignKey:EventId" json:"event,omitempty"`
|
| 171 |
}
|
| 172 |
|
| 173 |
func (EventAssign) TableName() string { return "event_assign" }
|
| 174 |
|
| 175 |
type Questions struct {
|
| 176 |
+
Id uuid.UUID `gorm:"type:uuid;primary_key;default:uuid_generate_v4()" json:"id_question"`
|
| 177 |
+
Type string `json:"type,omitempty"`
|
| 178 |
+
Question string `json:"question,omitempty"`
|
| 179 |
+
Options pq.StringArray `gorm:"type:text[]" json:"options,omitempty"`
|
| 180 |
+
AnsKey pq.StringArray `gorm:"type:text[]" json:"ans_key,omitempty"`
|
| 181 |
+
CorrMark float64 `json:"corr_mark,omitempty"`
|
| 182 |
+
IncorrMark float64 `json:"incorr_mark,omitempty"`
|
| 183 |
+
NullMark float64 `json:"null_mark,omitempty"`
|
| 184 |
+
ProblemSetId uuid.UUID `json:"id_problem_set,omitempty"`
|
| 185 |
+
|
| 186 |
+
ProblemSet *ProblemSet `gorm:"foreignKey:ProblemSetId" json:"problem_set,omitempty"`
|
| 187 |
}
|
| 188 |
|
| 189 |
func (Questions) TableName() string { return "questions" }
|
| 190 |
|
| 191 |
type ProblemSetExamAssign struct {
|
| 192 |
Id uuid.UUID `gorm:"type:uuid;primary_key;default:uuid_generate_v4()" json:"id_problem_set_exam_assign"`
|
| 193 |
+
ExamId uuid.UUID `json:"id_exam,omitempty"`
|
| 194 |
+
ProblemSetId uuid.UUID `json:"id_problem_set,omitempty"`
|
| 195 |
+
Exam *Exam `gorm:"foreignKey:ExamId" json:"exam,omitempty"`
|
| 196 |
+
ProblemSet *ProblemSet `gorm:"foreignKey:ProblemSetId" json:"problem_set,omitempty"`
|
| 197 |
}
|
| 198 |
|
| 199 |
func (ProblemSetExamAssign) TableName() string { return "problem_set_exam_assign" }
|
| 200 |
|
| 201 |
type ExamEventAssign struct {
|
| 202 |
Id uuid.UUID `gorm:"type:uuid;primary_key;default:uuid_generate_v4()" json:"id_exam_event_assign"`
|
| 203 |
+
EventId uuid.UUID `json:"id_event,omitempty"`
|
| 204 |
+
ExamId uuid.UUID `json:"id_exam,omitempty"`
|
| 205 |
+
Exam *Exam `gorm:"foreignKey:ExamId" json:"exam,omitempty"`
|
| 206 |
+
Event *Events `gorm:"foreignKey:EventId" json:"event,omitempty"`
|
| 207 |
}
|
| 208 |
|
| 209 |
func (ExamEventAssign) TableName() string { return "exam_event_assign" }
|
|
|
|
| 211 |
type CPQuestionVerdict struct {
|
| 212 |
TimeExecution float32 `json:"time_exec"`
|
| 213 |
MemoryUsage float32 `json:"memory"`
|
| 214 |
+
Verdict string `json:"verdict"`
|
| 215 |
Score float32 `json:"score"`
|
| 216 |
}
|
| 217 |
+
|
| 218 |
type ExamEventAnswer struct {
|
| 219 |
Id uuid.UUID `gorm:"type:uuid;primary_key;default:uuid_generate_v4()" json:"id"`
|
| 220 |
+
AttemptId uuid.UUID `json:"id_attempt,omitempty" gorm:"index"`
|
| 221 |
+
QuestionId uuid.UUID `json:"id_question,omitempty" gorm:"index"`
|
| 222 |
+
Answers pq.StringArray `gorm:"type:text[]" json:"answer,omitempty"`
|
| 223 |
Score float32 `json:"score"`
|
| 224 |
+
ExamEventAttempt *ExamEventAttempt `gorm:"foreignKey:AttemptId" json:"exam_attempt,omitempty"`
|
| 225 |
+
CreatedAt time.Time `json:"created_at,omitempty"`
|
| 226 |
+
UpdatedAt time.Time `json:"updated_at,omitempty"`
|
| 227 |
}
|
| 228 |
|
| 229 |
func (ExamEventAnswer) TableName() string { return "exam_event_answer" }
|
| 230 |
|
| 231 |
type ExamEventAttempt struct {
|
| 232 |
+
Id uuid.UUID `gorm:"type:uuid;primary_key;default:uuid_generate_v4()" json:"id_attempt"`
|
| 233 |
+
AccountId uuid.UUID `json:"id_account,omitempty"`
|
| 234 |
+
EventId uuid.UUID `json:"id_event,omitempty"`
|
| 235 |
+
ExamId uuid.UUID `json:"id_exam,omitempty"`
|
| 236 |
+
Questions []Questions `gorm:"-" json:"questions,omitempty"`
|
| 237 |
+
Answers []ExamEventAnswer `gorm:"foreignKey:AttemptId;references:Id" json:"answers,omitempty"`
|
| 238 |
+
Account *Account `gorm:"foreignKey:AccountId" json:"account,omitempty"`
|
| 239 |
+
Event *Events `gorm:"foreignKey:EventId" json:"event,omitempty"`
|
| 240 |
+
Exam *Exam `gorm:"foreignKey:ExamId" json:"exam,omitempty"`
|
| 241 |
+
RemTime int `json:"remaining_time,omitempty"`
|
| 242 |
+
Mark float32 `json:"mark,omitempty"`
|
| 243 |
+
CreatedAt time.Time `json:"created_at,omitempty"`
|
| 244 |
+
DueAt time.Time `json:"due_at,omitempty"`
|
| 245 |
+
Submitted bool `json:"submitted,omitempty"`
|
| 246 |
}
|
| 247 |
|
| 248 |
func (ExamEventAttempt) TableName() string { return "exam_event_attempt" }
|
| 249 |
|
| 250 |
type Result struct {
|
| 251 |
+
Id uuid.UUID `gorm:"type:uuid;primary_key;default:uuid_generate_v4()" json:"id_result"`
|
| 252 |
+
AttemptId uuid.UUID `json:"id_attempt,omitempty"`
|
| 253 |
+
FinalScore float32 `json:"final_score"`
|
| 254 |
+
ExamEventAttempt *ExamEventAttempt `gorm:"foreignKey:AttemptId" json:"exam_attempt,omitempty"`
|
| 255 |
}
|
| 256 |
|
| 257 |
func (Result) TableName() string { return "result" }
|
| 258 |
|
| 259 |
type Academy struct {
|
| 260 |
Id uuid.UUID `gorm:"primaryKey" json:"id"`
|
| 261 |
+
Title string `json:"title,omitempty"`
|
| 262 |
+
Slug string `json:"slug,omitempty"`
|
| 263 |
+
Description string `json:"description,omitempty"`
|
| 264 |
}
|
| 265 |
|
| 266 |
func (Academy) TableName() string { return "academy" }
|
| 267 |
|
| 268 |
type AcademyMaterial struct {
|
| 269 |
Id uuid.UUID `gorm:"primaryKey" json:"id"`
|
| 270 |
+
AcademyId uuid.UUID `json:"academy_id,omitempty"`
|
| 271 |
+
Title string `json:"title,omitempty"`
|
| 272 |
+
Slug string `json:"slug,omitempty"`
|
| 273 |
+
Description string `json:"description,omitempty"`
|
| 274 |
}
|
| 275 |
|
| 276 |
func (AcademyMaterial) TableName() string { return "academy_materials" }
|
| 277 |
|
| 278 |
type AcademyContent struct {
|
| 279 |
Id uuid.UUID `gorm:"primaryKey" json:"id"`
|
| 280 |
+
Title string `json:"title,omitempty"`
|
| 281 |
+
Order uint `json:"order,omitempty"`
|
| 282 |
+
AcademyMaterialId uuid.UUID `json:"academy_material_id,omitempty"`
|
| 283 |
+
Contents string `json:"contents,omitempty"`
|
| 284 |
}
|
| 285 |
|
| 286 |
func (AcademyContent) TableName() string { return "academy_contents" }
|
| 287 |
|
| 288 |
type AcademyMaterialProgress struct {
|
| 289 |
Id uuid.UUID `gorm:"primaryKey" json:"id"`
|
| 290 |
+
AccountId uint `json:"account_id,omitempty"`
|
| 291 |
+
AcademyMaterialId uuid.UUID `json:"academy_material_id,omitempty"`
|
| 292 |
+
Progress uint `json:"progress,omitempty"`
|
| 293 |
}
|
| 294 |
|
| 295 |
func (AcademyMaterialProgress) TableName() string { return "academy_materials_progress" }
|
| 296 |
|
| 297 |
type AcademyContentProgress struct {
|
| 298 |
Id uuid.UUID `gorm:"primaryKey" json:"id"`
|
| 299 |
+
AccountId uuid.UUID `json:"account_id,omitempty"`
|
| 300 |
+
AcademyId uuid.UUID `json:"academy_id,omitempty"`
|
| 301 |
}
|
| 302 |
|
| 303 |
func (AcademyContentProgress) TableName() string { return "academy_contents_progress" }
|
|
|
|
|
|
repositories/exam_event_answer_repository.go
CHANGED
|
@@ -9,8 +9,8 @@ import (
|
|
| 9 |
)
|
| 10 |
|
| 11 |
type ExamEventAnswerRepository interface {
|
| 12 |
-
Create(ctx context.Context, ans entity.ExamEventAnswer) error
|
| 13 |
-
Update(ctx context.Context, ans entity.ExamEventAnswer) error
|
| 14 |
GetByAttemptAndQuestion(ctx context.Context, attemptId uuid.UUID, questionId uuid.UUID) (entity.ExamEventAnswer, error)
|
| 15 |
ListByAttempt(ctx context.Context, attemptId uuid.UUID) ([]entity.ExamEventAnswer, error)
|
| 16 |
DeleteByAttempt(ctx context.Context, attemptId uuid.UUID) error
|
|
@@ -26,20 +26,20 @@ func NewExamEventAnswerRepository(db *gorm.DB) ExamEventAnswerRepository {
|
|
| 26 |
return &examEventAnswerRepository{db: db}
|
| 27 |
}
|
| 28 |
|
| 29 |
-
func (r *examEventAnswerRepository) Create(ctx context.Context, ans entity.ExamEventAnswer) error {
|
| 30 |
-
return r.db.WithContext(ctx).Create(
|
| 31 |
}
|
| 32 |
|
| 33 |
-
func (r *examEventAnswerRepository) Update(ctx context.Context, ans entity.ExamEventAnswer) error {
|
| 34 |
return r.db.WithContext(ctx).
|
| 35 |
-
Where("
|
| 36 |
Updates(ans).Error
|
| 37 |
}
|
| 38 |
|
| 39 |
func (r *examEventAnswerRepository) GetByAttemptAndQuestion(ctx context.Context, attemptId uuid.UUID, questionId uuid.UUID) (entity.ExamEventAnswer, error) {
|
| 40 |
var ans entity.ExamEventAnswer
|
| 41 |
err := r.db.WithContext(ctx).
|
| 42 |
-
Where("
|
| 43 |
First(&ans).Error
|
| 44 |
return ans, err
|
| 45 |
}
|
|
@@ -47,13 +47,13 @@ func (r *examEventAnswerRepository) GetByAttemptAndQuestion(ctx context.Context,
|
|
| 47 |
func (r *examEventAnswerRepository) ListByAttempt(ctx context.Context, attemptId uuid.UUID) ([]entity.ExamEventAnswer, error) {
|
| 48 |
var answers []entity.ExamEventAnswer
|
| 49 |
err := r.db.WithContext(ctx).
|
| 50 |
-
Where("
|
| 51 |
Find(&answers).Error
|
| 52 |
return answers, err
|
| 53 |
}
|
| 54 |
|
| 55 |
func (r *examEventAnswerRepository) DeleteByAttempt(ctx context.Context, attemptId uuid.UUID) error {
|
| 56 |
return r.db.WithContext(ctx).
|
| 57 |
-
Where("
|
| 58 |
Delete(&entity.ExamEventAnswer{}).Error
|
| 59 |
}
|
|
|
|
| 9 |
)
|
| 10 |
|
| 11 |
type ExamEventAnswerRepository interface {
|
| 12 |
+
Create(ctx context.Context, ans *entity.ExamEventAnswer) error
|
| 13 |
+
Update(ctx context.Context, ans *entity.ExamEventAnswer) error
|
| 14 |
GetByAttemptAndQuestion(ctx context.Context, attemptId uuid.UUID, questionId uuid.UUID) (entity.ExamEventAnswer, error)
|
| 15 |
ListByAttempt(ctx context.Context, attemptId uuid.UUID) ([]entity.ExamEventAnswer, error)
|
| 16 |
DeleteByAttempt(ctx context.Context, attemptId uuid.UUID) error
|
|
|
|
| 26 |
return &examEventAnswerRepository{db: db}
|
| 27 |
}
|
| 28 |
|
| 29 |
+
func (r *examEventAnswerRepository) Create(ctx context.Context, ans *entity.ExamEventAnswer) error {
|
| 30 |
+
return r.db.WithContext(ctx).Create(ans).Error
|
| 31 |
}
|
| 32 |
|
| 33 |
+
func (r *examEventAnswerRepository) Update(ctx context.Context, ans *entity.ExamEventAnswer) error {
|
| 34 |
return r.db.WithContext(ctx).
|
| 35 |
+
Where("attempt_id = ? AND question_id = ?", ans.AttemptId, ans.QuestionId).
|
| 36 |
Updates(ans).Error
|
| 37 |
}
|
| 38 |
|
| 39 |
func (r *examEventAnswerRepository) GetByAttemptAndQuestion(ctx context.Context, attemptId uuid.UUID, questionId uuid.UUID) (entity.ExamEventAnswer, error) {
|
| 40 |
var ans entity.ExamEventAnswer
|
| 41 |
err := r.db.WithContext(ctx).
|
| 42 |
+
Where("attempt_id = ? AND question_id = ?", attemptId, questionId).
|
| 43 |
First(&ans).Error
|
| 44 |
return ans, err
|
| 45 |
}
|
|
|
|
| 47 |
func (r *examEventAnswerRepository) ListByAttempt(ctx context.Context, attemptId uuid.UUID) ([]entity.ExamEventAnswer, error) {
|
| 48 |
var answers []entity.ExamEventAnswer
|
| 49 |
err := r.db.WithContext(ctx).
|
| 50 |
+
Where("attempt_id = ?", attemptId).
|
| 51 |
Find(&answers).Error
|
| 52 |
return answers, err
|
| 53 |
}
|
| 54 |
|
| 55 |
func (r *examEventAnswerRepository) DeleteByAttempt(ctx context.Context, attemptId uuid.UUID) error {
|
| 56 |
return r.db.WithContext(ctx).
|
| 57 |
+
Where("attempt_id = ?", attemptId).
|
| 58 |
Delete(&entity.ExamEventAnswer{}).Error
|
| 59 |
}
|
repositories/exam_event_assign_repository.go
CHANGED
|
@@ -27,7 +27,7 @@ func (r *examEventAssignRepository) Create(ctx context.Context, m entity.ExamEve
|
|
| 27 |
func (r *examEventAssignRepository) ListByEvent(ctx context.Context, eventId uuid.UUID) ([]entity.ExamEventAssign, error) {
|
| 28 |
var items []entity.ExamEventAssign
|
| 29 |
err := r.db.WithContext(ctx).
|
| 30 |
-
Where("
|
| 31 |
Preload("Exam").
|
| 32 |
Find(&items).Error
|
| 33 |
return items, err
|
|
@@ -35,6 +35,6 @@ func (r *examEventAssignRepository) ListByEvent(ctx context.Context, eventId uui
|
|
| 35 |
|
| 36 |
func (r *examEventAssignRepository) Delete(ctx context.Context, id uuid.UUID) error {
|
| 37 |
return r.db.WithContext(ctx).
|
| 38 |
-
Where("
|
| 39 |
Delete(&entity.ExamEventAssign{}).Error
|
| 40 |
}
|
|
|
|
| 27 |
func (r *examEventAssignRepository) ListByEvent(ctx context.Context, eventId uuid.UUID) ([]entity.ExamEventAssign, error) {
|
| 28 |
var items []entity.ExamEventAssign
|
| 29 |
err := r.db.WithContext(ctx).
|
| 30 |
+
Where("event_id = ?", eventId).
|
| 31 |
Preload("Exam").
|
| 32 |
Find(&items).Error
|
| 33 |
return items, err
|
|
|
|
| 35 |
|
| 36 |
func (r *examEventAssignRepository) Delete(ctx context.Context, id uuid.UUID) error {
|
| 37 |
return r.db.WithContext(ctx).
|
| 38 |
+
Where("id = ?", id).
|
| 39 |
Delete(&entity.ExamEventAssign{}).Error
|
| 40 |
}
|
repositories/exam_event_attempt_repository.go
CHANGED
|
@@ -9,10 +9,10 @@ import (
|
|
| 9 |
)
|
| 10 |
|
| 11 |
type ExamEventAttemptRepository interface {
|
| 12 |
-
Create(ctx context.Context, a entity.ExamEventAttempt) error
|
| 13 |
GetById(ctx context.Context, attemptId uuid.UUID) (entity.ExamEventAttempt, error)
|
| 14 |
GetByExamEvent(ctx context.Context, eventId uuid.UUID, examId uuid.UUID, accountId uuid.UUID) (entity.ExamEventAttempt, error)
|
| 15 |
-
Update(ctx context.Context, a entity.ExamEventAttempt) error
|
| 16 |
}
|
| 17 |
|
| 18 |
type examEventAttemptRepository struct{ db *gorm.DB }
|
|
@@ -21,15 +21,15 @@ func NewExamEventAttemptRepository(db *gorm.DB) ExamEventAttemptRepository {
|
|
| 21 |
return &examEventAttemptRepository{db}
|
| 22 |
}
|
| 23 |
|
| 24 |
-
func (r *examEventAttemptRepository) Create(ctx context.Context, a entity.ExamEventAttempt) error {
|
| 25 |
-
return r.db.WithContext(ctx).Create(
|
| 26 |
}
|
| 27 |
|
| 28 |
func (r *examEventAttemptRepository) GetById(ctx context.Context, attemptId uuid.UUID) (entity.ExamEventAttempt, error) {
|
| 29 |
var a entity.ExamEventAttempt
|
| 30 |
err := r.db.WithContext(ctx).
|
| 31 |
-
Preload("
|
| 32 |
-
First(&a, "
|
| 33 |
return a, err
|
| 34 |
}
|
| 35 |
|
|
@@ -38,19 +38,18 @@ func (r *examEventAttemptRepository) GetByExamEvent(ctx context.Context, eventId
|
|
| 38 |
var attempt entity.ExamEventAttempt
|
| 39 |
|
| 40 |
err := r.db.WithContext(ctx).
|
| 41 |
-
Preload("Questions").
|
| 42 |
Preload("Answers").
|
| 43 |
-
Where("
|
| 44 |
-
Where("
|
| 45 |
-
Where("
|
| 46 |
First(&attempt).Error
|
| 47 |
|
| 48 |
return attempt, err
|
| 49 |
}
|
| 50 |
|
| 51 |
-
func (r *examEventAttemptRepository) Update(ctx context.Context, a entity.ExamEventAttempt) error {
|
| 52 |
return r.db.WithContext(ctx).
|
| 53 |
Model(&entity.ExamEventAttempt{}).
|
| 54 |
-
Where("
|
| 55 |
Updates(a).Error
|
| 56 |
}
|
|
|
|
| 9 |
)
|
| 10 |
|
| 11 |
type ExamEventAttemptRepository interface {
|
| 12 |
+
Create(ctx context.Context, a *entity.ExamEventAttempt) error
|
| 13 |
GetById(ctx context.Context, attemptId uuid.UUID) (entity.ExamEventAttempt, error)
|
| 14 |
GetByExamEvent(ctx context.Context, eventId uuid.UUID, examId uuid.UUID, accountId uuid.UUID) (entity.ExamEventAttempt, error)
|
| 15 |
+
Update(ctx context.Context, a *entity.ExamEventAttempt) error
|
| 16 |
}
|
| 17 |
|
| 18 |
type examEventAttemptRepository struct{ db *gorm.DB }
|
|
|
|
| 21 |
return &examEventAttemptRepository{db}
|
| 22 |
}
|
| 23 |
|
| 24 |
+
func (r *examEventAttemptRepository) Create(ctx context.Context, a *entity.ExamEventAttempt) error {
|
| 25 |
+
return r.db.WithContext(ctx).Create(a).Error
|
| 26 |
}
|
| 27 |
|
| 28 |
func (r *examEventAttemptRepository) GetById(ctx context.Context, attemptId uuid.UUID) (entity.ExamEventAttempt, error) {
|
| 29 |
var a entity.ExamEventAttempt
|
| 30 |
err := r.db.WithContext(ctx).
|
| 31 |
+
Preload("Answers").
|
| 32 |
+
First(&a, "id = ?", attemptId).Error
|
| 33 |
return a, err
|
| 34 |
}
|
| 35 |
|
|
|
|
| 38 |
var attempt entity.ExamEventAttempt
|
| 39 |
|
| 40 |
err := r.db.WithContext(ctx).
|
|
|
|
| 41 |
Preload("Answers").
|
| 42 |
+
Where("event_id = ?", eventId).
|
| 43 |
+
Where("exam_id = ?", examId).
|
| 44 |
+
Where("account_id = ?", accountId).
|
| 45 |
First(&attempt).Error
|
| 46 |
|
| 47 |
return attempt, err
|
| 48 |
}
|
| 49 |
|
| 50 |
+
func (r *examEventAttemptRepository) Update(ctx context.Context, a *entity.ExamEventAttempt) error {
|
| 51 |
return r.db.WithContext(ctx).
|
| 52 |
Model(&entity.ExamEventAttempt{}).
|
| 53 |
+
Where("id = ?", a.Id).
|
| 54 |
Updates(a).Error
|
| 55 |
}
|
repositories/exam_event_repository.go
CHANGED
|
@@ -37,7 +37,7 @@ func (r *examRepository) Create(ctx context.Context, e entity.Exam) error {
|
|
| 37 |
func (r *examRepository) Get(ctx context.Context, id uuid.UUID) (entity.Exam, error) {
|
| 38 |
var e entity.Exam
|
| 39 |
err := r.db.WithContext(ctx).
|
| 40 |
-
First(&e, "
|
| 41 |
return e, err
|
| 42 |
}
|
| 43 |
|
|
@@ -52,13 +52,13 @@ func (r *examRepository) GetBySlug(ctx context.Context, slug string) (entity.Exa
|
|
| 52 |
func (r *examRepository) Update(ctx context.Context, e entity.Exam) error {
|
| 53 |
return r.db.WithContext(ctx).
|
| 54 |
Model(&entity.Exam{}).
|
| 55 |
-
Where("
|
| 56 |
Updates(e).Error
|
| 57 |
}
|
| 58 |
|
| 59 |
func (r *examRepository) Delete(ctx context.Context, id uuid.UUID) error {
|
| 60 |
return r.db.WithContext(ctx).
|
| 61 |
-
Where("
|
| 62 |
Delete(&entity.Exam{}).Error
|
| 63 |
}
|
| 64 |
|
|
@@ -77,8 +77,8 @@ func (r *examRepository) ListByEvent(ctx context.Context, eventId uuid.UUID) ([]
|
|
| 77 |
|
| 78 |
err := r.db.WithContext(ctx).
|
| 79 |
Table("exam").
|
| 80 |
-
Joins(`JOIN exam_event_assign ON exam_event_assign.
|
| 81 |
-
Where("exam_event_assign.
|
| 82 |
Find(&exams).Error
|
| 83 |
|
| 84 |
return exams, err
|
|
|
|
| 37 |
func (r *examRepository) Get(ctx context.Context, id uuid.UUID) (entity.Exam, error) {
|
| 38 |
var e entity.Exam
|
| 39 |
err := r.db.WithContext(ctx).
|
| 40 |
+
First(&e, "exam_id = ?", id).Error
|
| 41 |
return e, err
|
| 42 |
}
|
| 43 |
|
|
|
|
| 52 |
func (r *examRepository) Update(ctx context.Context, e entity.Exam) error {
|
| 53 |
return r.db.WithContext(ctx).
|
| 54 |
Model(&entity.Exam{}).
|
| 55 |
+
Where("exam_id = ?", e.Id).
|
| 56 |
Updates(e).Error
|
| 57 |
}
|
| 58 |
|
| 59 |
func (r *examRepository) Delete(ctx context.Context, id uuid.UUID) error {
|
| 60 |
return r.db.WithContext(ctx).
|
| 61 |
+
Where("exam_id = ?", id).
|
| 62 |
Delete(&entity.Exam{}).Error
|
| 63 |
}
|
| 64 |
|
|
|
|
| 77 |
|
| 78 |
err := r.db.WithContext(ctx).
|
| 79 |
Table("exam").
|
| 80 |
+
Joins(`JOIN exam_event_assign ON exam_event_assign.exam_id = exam.exam_id`).
|
| 81 |
+
Where("exam_event_assign.event_id = ?", eventId).
|
| 82 |
Find(&exams).Error
|
| 83 |
|
| 84 |
return exams, err
|
repositories/problem_set_exam_assign_repository.go
CHANGED
|
@@ -27,7 +27,7 @@ func (r *problemSetExamAssignRepository) Create(ctx context.Context, m entity.Pr
|
|
| 27 |
func (r *problemSetExamAssignRepository) GetByExam(ctx context.Context, examId uuid.UUID) (entity.ProblemSetExamAssign, error) {
|
| 28 |
var items entity.ProblemSetExamAssign
|
| 29 |
err := r.db.WithContext(ctx).
|
| 30 |
-
Where("
|
| 31 |
Preload("ProblemSet").
|
| 32 |
First(&items).Error
|
| 33 |
return items, err
|
|
@@ -35,6 +35,6 @@ func (r *problemSetExamAssignRepository) GetByExam(ctx context.Context, examId u
|
|
| 35 |
|
| 36 |
func (r *problemSetExamAssignRepository) Delete(ctx context.Context, id uuid.UUID) error {
|
| 37 |
return r.db.WithContext(ctx).
|
| 38 |
-
Where("
|
| 39 |
Delete(&entity.ProblemSetExamAssign{}).Error
|
| 40 |
}
|
|
|
|
| 27 |
func (r *problemSetExamAssignRepository) GetByExam(ctx context.Context, examId uuid.UUID) (entity.ProblemSetExamAssign, error) {
|
| 28 |
var items entity.ProblemSetExamAssign
|
| 29 |
err := r.db.WithContext(ctx).
|
| 30 |
+
Where("exam_id = ?", examId).
|
| 31 |
Preload("ProblemSet").
|
| 32 |
First(&items).Error
|
| 33 |
return items, err
|
|
|
|
| 35 |
|
| 36 |
func (r *problemSetExamAssignRepository) Delete(ctx context.Context, id uuid.UUID) error {
|
| 37 |
return r.db.WithContext(ctx).
|
| 38 |
+
Where("id = ?", id).
|
| 39 |
Delete(&entity.ProblemSetExamAssign{}).Error
|
| 40 |
}
|
repositories/problem_set_repository.go
CHANGED
|
@@ -31,7 +31,7 @@ func (r *problemSetRepository) Create(ctx context.Context, ps entity.ProblemSet)
|
|
| 31 |
func (r *problemSetRepository) Get(ctx context.Context, id uuid.UUID) (entity.ProblemSet, error) {
|
| 32 |
var ps entity.ProblemSet
|
| 33 |
err := r.db.WithContext(ctx).
|
| 34 |
-
First(&ps, "
|
| 35 |
return ps, err
|
| 36 |
}
|
| 37 |
|
|
@@ -46,12 +46,12 @@ func (r *problemSetRepository) List(ctx context.Context) ([]entity.ProblemSet, e
|
|
| 46 |
func (r *problemSetRepository) Update(ctx context.Context, ps entity.ProblemSet) error {
|
| 47 |
return r.db.WithContext(ctx).
|
| 48 |
Model(&entity.ProblemSet{}).
|
| 49 |
-
Where("
|
| 50 |
Updates(ps).Error
|
| 51 |
}
|
| 52 |
|
| 53 |
func (r *problemSetRepository) Delete(ctx context.Context, id uuid.UUID) error {
|
| 54 |
return r.db.WithContext(ctx).
|
| 55 |
-
Where("
|
| 56 |
Delete(&entity.ProblemSet{}).Error
|
| 57 |
}
|
|
|
|
| 31 |
func (r *problemSetRepository) Get(ctx context.Context, id uuid.UUID) (entity.ProblemSet, error) {
|
| 32 |
var ps entity.ProblemSet
|
| 33 |
err := r.db.WithContext(ctx).
|
| 34 |
+
First(&ps, "id = ?", id).Error
|
| 35 |
return ps, err
|
| 36 |
}
|
| 37 |
|
|
|
|
| 46 |
func (r *problemSetRepository) Update(ctx context.Context, ps entity.ProblemSet) error {
|
| 47 |
return r.db.WithContext(ctx).
|
| 48 |
Model(&entity.ProblemSet{}).
|
| 49 |
+
Where("id = ?", ps.Id).
|
| 50 |
Updates(ps).Error
|
| 51 |
}
|
| 52 |
|
| 53 |
func (r *problemSetRepository) Delete(ctx context.Context, id uuid.UUID) error {
|
| 54 |
return r.db.WithContext(ctx).
|
| 55 |
+
Where("id = ?", id).
|
| 56 |
Delete(&entity.ProblemSet{}).Error
|
| 57 |
}
|
repositories/question_repository.go
CHANGED
|
@@ -28,28 +28,28 @@ func (r *questionsRepository) Create(ctx context.Context, q entity.Questions) er
|
|
| 28 |
|
| 29 |
func (r *questionsRepository) Get(ctx context.Context, id uuid.UUID) (entity.Questions, error) {
|
| 30 |
var q entity.Questions
|
| 31 |
-
err := r.db.WithContext(ctx).First(&q, "
|
| 32 |
return q, err
|
| 33 |
}
|
| 34 |
|
| 35 |
func (r *questionsRepository) Update(ctx context.Context, q entity.Questions) error {
|
| 36 |
return r.db.WithContext(ctx).
|
| 37 |
Model(&entity.Questions{}).
|
| 38 |
-
Where("
|
| 39 |
Updates(q).Error
|
| 40 |
}
|
| 41 |
|
| 42 |
func (r *questionsRepository) Delete(ctx context.Context, id uuid.UUID) error {
|
| 43 |
return r.db.WithContext(ctx).
|
| 44 |
-
Where("
|
| 45 |
Delete(&entity.Questions{}).Error
|
| 46 |
}
|
| 47 |
|
| 48 |
func (r *questionsRepository) ListByProblemSet(ctx context.Context, problemSetId uuid.UUID) ([]entity.Questions, error) {
|
| 49 |
var q []entity.Questions
|
| 50 |
err := r.db.WithContext(ctx).
|
| 51 |
-
Where("
|
| 52 |
-
Order("
|
| 53 |
Find(&q).Error
|
| 54 |
return q, err
|
| 55 |
}
|
|
|
|
| 28 |
|
| 29 |
func (r *questionsRepository) Get(ctx context.Context, id uuid.UUID) (entity.Questions, error) {
|
| 30 |
var q entity.Questions
|
| 31 |
+
err := r.db.WithContext(ctx).First(&q, "id = ?", id).Error
|
| 32 |
return q, err
|
| 33 |
}
|
| 34 |
|
| 35 |
func (r *questionsRepository) Update(ctx context.Context, q entity.Questions) error {
|
| 36 |
return r.db.WithContext(ctx).
|
| 37 |
Model(&entity.Questions{}).
|
| 38 |
+
Where("id = ?", q.Id).
|
| 39 |
Updates(q).Error
|
| 40 |
}
|
| 41 |
|
| 42 |
func (r *questionsRepository) Delete(ctx context.Context, id uuid.UUID) error {
|
| 43 |
return r.db.WithContext(ctx).
|
| 44 |
+
Where("id = ?", id).
|
| 45 |
Delete(&entity.Questions{}).Error
|
| 46 |
}
|
| 47 |
|
| 48 |
func (r *questionsRepository) ListByProblemSet(ctx context.Context, problemSetId uuid.UUID) ([]entity.Questions, error) {
|
| 49 |
var q []entity.Questions
|
| 50 |
err := r.db.WithContext(ctx).
|
| 51 |
+
Where("problem_set_id = ?", problemSetId).
|
| 52 |
+
Order("id").
|
| 53 |
Find(&q).Error
|
| 54 |
return q, err
|
| 55 |
}
|
repositories/result_repository.go
CHANGED
|
@@ -9,10 +9,11 @@ import (
|
|
| 9 |
)
|
| 10 |
|
| 11 |
type ResultRepository interface {
|
| 12 |
-
Create(ctx context.Context, r entity.Result) error
|
| 13 |
-
|
| 14 |
-
Update(ctx context.Context, r entity.Result) error
|
| 15 |
ListByEvent(ctx context.Context, eventId uuid.UUID) ([]entity.Result, error)
|
|
|
|
| 16 |
}
|
| 17 |
|
| 18 |
type resultRepository struct{ db *gorm.DB }
|
|
@@ -21,32 +22,38 @@ func NewResultRepository(db *gorm.DB) ResultRepository {
|
|
| 21 |
return &resultRepository{db}
|
| 22 |
}
|
| 23 |
|
| 24 |
-
func (r *resultRepository) Create(ctx context.Context, rs entity.Result) error {
|
| 25 |
-
return r.db.WithContext(ctx).Create(
|
| 26 |
}
|
| 27 |
-
|
| 28 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 29 |
var rs entity.Result
|
| 30 |
err := r.db.WithContext(ctx).
|
| 31 |
Preload("Account").
|
| 32 |
Preload("Event").
|
| 33 |
Preload("ProblemSet").
|
| 34 |
Preload("ExamEventAttempt").
|
| 35 |
-
First(&rs, "
|
| 36 |
return rs, err
|
| 37 |
}
|
| 38 |
|
| 39 |
-
func (r *resultRepository) Update(ctx context.Context, rs entity.Result) error {
|
| 40 |
return r.db.WithContext(ctx).
|
| 41 |
Model(&entity.Result{}).
|
| 42 |
-
Where("
|
| 43 |
Updates(rs).Error
|
| 44 |
}
|
| 45 |
|
| 46 |
func (r *resultRepository) ListByEvent(ctx context.Context, eventId uuid.UUID) ([]entity.Result, error) {
|
| 47 |
var list []entity.Result
|
| 48 |
err := r.db.WithContext(ctx).
|
| 49 |
-
Where("
|
| 50 |
Preload("Account").
|
| 51 |
Find(&list).Error
|
| 52 |
return list, err
|
|
|
|
| 9 |
)
|
| 10 |
|
| 11 |
type ResultRepository interface {
|
| 12 |
+
Create(ctx context.Context, r *entity.Result) error
|
| 13 |
+
GetById(ctx context.Context, id uuid.UUID) (entity.Result, error)
|
| 14 |
+
Update(ctx context.Context, r *entity.Result) error
|
| 15 |
ListByEvent(ctx context.Context, eventId uuid.UUID) ([]entity.Result, error)
|
| 16 |
+
GetByAttemptId(ctx context.Context, attemptId uuid.UUID) (entity.Result, error)
|
| 17 |
}
|
| 18 |
|
| 19 |
type resultRepository struct{ db *gorm.DB }
|
|
|
|
| 22 |
return &resultRepository{db}
|
| 23 |
}
|
| 24 |
|
| 25 |
+
func (r *resultRepository) Create(ctx context.Context, rs *entity.Result) error {
|
| 26 |
+
return r.db.WithContext(ctx).Create(rs).Error
|
| 27 |
}
|
| 28 |
+
func (r *resultRepository) GetByAttemptId(ctx context.Context, attemptId uuid.UUID) (entity.Result, error) {
|
| 29 |
+
var rs entity.Result
|
| 30 |
+
err := r.db.WithContext(ctx).
|
| 31 |
+
Preload("ExamEventAttempt").
|
| 32 |
+
First(&rs, "attempt_id = ?", attemptId).Error
|
| 33 |
+
return rs, err
|
| 34 |
+
}
|
| 35 |
+
func (r *resultRepository) GetById(ctx context.Context, id uuid.UUID) (entity.Result, error) {
|
| 36 |
var rs entity.Result
|
| 37 |
err := r.db.WithContext(ctx).
|
| 38 |
Preload("Account").
|
| 39 |
Preload("Event").
|
| 40 |
Preload("ProblemSet").
|
| 41 |
Preload("ExamEventAttempt").
|
| 42 |
+
First(&rs, "id = ?", id).Error
|
| 43 |
return rs, err
|
| 44 |
}
|
| 45 |
|
| 46 |
+
func (r *resultRepository) Update(ctx context.Context, rs *entity.Result) error {
|
| 47 |
return r.db.WithContext(ctx).
|
| 48 |
Model(&entity.Result{}).
|
| 49 |
+
Where("id = ?", rs.Id).
|
| 50 |
Updates(rs).Error
|
| 51 |
}
|
| 52 |
|
| 53 |
func (r *resultRepository) ListByEvent(ctx context.Context, eventId uuid.UUID) ([]entity.Result, error) {
|
| 54 |
var list []entity.Result
|
| 55 |
err := r.db.WithContext(ctx).
|
| 56 |
+
Where("event_id = ?", eventId).
|
| 57 |
Preload("Account").
|
| 58 |
Find(&list).Error
|
| 59 |
return list, err
|
router/event_router.go
CHANGED
|
@@ -11,7 +11,7 @@ func EventRouter(router *gin.Engine, middleware provider.MiddlewareProvider, con
|
|
| 11 |
routerGroup := router.Group("api/v1/events")
|
| 12 |
{
|
| 13 |
routerGroup.GET("/", authenticationMiddleware.VerifyAccount, eventController.List)
|
| 14 |
-
routerGroup.GET("/:
|
| 15 |
routerGroup.POST("/register-event", authenticationMiddleware.VerifyAccount, eventController.Join)
|
| 16 |
}
|
| 17 |
}
|
|
|
|
| 11 |
routerGroup := router.Group("api/v1/events")
|
| 12 |
{
|
| 13 |
routerGroup.GET("/", authenticationMiddleware.VerifyAccount, eventController.List)
|
| 14 |
+
routerGroup.GET("/:event_slug", authenticationMiddleware.VerifyAccount, eventController.DetailBySlug)
|
| 15 |
routerGroup.POST("/register-event", authenticationMiddleware.VerifyAccount, eventController.Join)
|
| 16 |
}
|
| 17 |
}
|
router/exam_event_router.go
CHANGED
|
@@ -8,18 +8,19 @@ import (
|
|
| 8 |
func ExamEventRouter(router *gin.Engine, middleware provider.MiddlewareProvider, controller provider.ControllerProvider) {
|
| 9 |
examController := controller.ProvideExamController()
|
| 10 |
auth := middleware.ProvideAuthenticationMiddleware()
|
| 11 |
-
|
| 12 |
-
routerGroup := router.Group("api/v1/exam")
|
| 13 |
{
|
| 14 |
-
routerGroup.GET("/:event_slug/:exam_slug/attempt",
|
| 15 |
auth.VerifyAccount,
|
| 16 |
examController.Attempt,
|
| 17 |
)
|
| 18 |
-
|
|
|
|
| 19 |
auth.VerifyAccount,
|
| 20 |
examController.Answer,
|
| 21 |
)
|
| 22 |
-
|
|
|
|
| 23 |
auth.VerifyAccount,
|
| 24 |
examController.Submit,
|
| 25 |
)
|
|
|
|
| 8 |
func ExamEventRouter(router *gin.Engine, middleware provider.MiddlewareProvider, controller provider.ControllerProvider) {
|
| 9 |
examController := controller.ProvideExamController()
|
| 10 |
auth := middleware.ProvideAuthenticationMiddleware()
|
| 11 |
+
routerGroup := router.Group("api/v1/events")
|
|
|
|
| 12 |
{
|
| 13 |
+
routerGroup.GET("/:event_slug/exam/:exam_slug/attempt",
|
| 14 |
auth.VerifyAccount,
|
| 15 |
examController.Attempt,
|
| 16 |
)
|
| 17 |
+
|
| 18 |
+
routerGroup.POST("/:event_slug/exam/:attempt_id/answer_question/",
|
| 19 |
auth.VerifyAccount,
|
| 20 |
examController.Answer,
|
| 21 |
)
|
| 22 |
+
|
| 23 |
+
routerGroup.POST("/:event_slug/exam/:attempt_id/submit/",
|
| 24 |
auth.VerifyAccount,
|
| 25 |
examController.Submit,
|
| 26 |
)
|
services/exam_event_service.go
CHANGED
|
@@ -3,6 +3,7 @@ package services
|
|
| 3 |
import (
|
| 4 |
"context"
|
| 5 |
"errors"
|
|
|
|
| 6 |
"time"
|
| 7 |
|
| 8 |
"abdanhafidz.com/go-boilerplate/models/dto"
|
|
@@ -52,7 +53,7 @@ func NewExamService(eventService EventService, problemSetService ProblemSetServi
|
|
| 52 |
func ProtectExamEventAttempt(attempt entity.ExamEventAttempt) entity.ExamEventAttempt {
|
| 53 |
|
| 54 |
var cleanQuestions []entity.Questions
|
| 55 |
-
for _, q := range
|
| 56 |
qCopy := q
|
| 57 |
qCopy.AnsKey = nil // hide answer key
|
| 58 |
qCopy.CorrMark = 0
|
|
@@ -61,19 +62,19 @@ func ProtectExamEventAttempt(attempt entity.ExamEventAttempt) entity.ExamEventAt
|
|
| 61 |
|
| 62 |
cleanQuestions = append(cleanQuestions, qCopy)
|
| 63 |
}
|
| 64 |
-
attempt.Questions =
|
| 65 |
|
| 66 |
// protect answers verdict info
|
| 67 |
var cleanAnswers []entity.ExamEventAnswer
|
| 68 |
|
| 69 |
-
for _, a := range
|
| 70 |
aCopy := a
|
| 71 |
aCopy.Score = 0 // hide score
|
| 72 |
|
| 73 |
cleanAnswers = append(cleanAnswers, aCopy)
|
| 74 |
}
|
| 75 |
|
| 76 |
-
attempt.Answers =
|
| 77 |
|
| 78 |
return attempt
|
| 79 |
}
|
|
@@ -99,7 +100,7 @@ func (s *examService) GetEventExamExisting(ctx context.Context, eventSlug string
|
|
| 99 |
return ev, exam, err
|
| 100 |
}
|
| 101 |
|
| 102 |
-
if exam, err = s.examRepo.GetBySlug(ctx,
|
| 103 |
return ev, exam, err
|
| 104 |
}
|
| 105 |
|
|
@@ -115,7 +116,7 @@ func (s *examService) GetExamEventAttempt(ctx context.Context, eventSlug string,
|
|
| 115 |
}
|
| 116 |
|
| 117 |
examEventAttempt, err := s.examEventAttemptRepo.GetByExamEvent(ctx, ev.Data.Id, exam.Id, accountId)
|
| 118 |
-
|
| 119 |
if err != nil && !errors.Is(err, gorm.ErrRecordNotFound) {
|
| 120 |
return dto.UserExamStatus{}, entity.ExamEventAttempt{}, err
|
| 121 |
}
|
|
@@ -126,21 +127,16 @@ func (s *examService) GetExamEventAttempt(ctx context.Context, eventSlug string,
|
|
| 126 |
attemptStatus.IsSubmitted = examEventAttempt.Submitted
|
| 127 |
attemptStatus.IsOnAttempt = !attemptStatus.IsNotAttempt && !attemptStatus.IsTimeOut && !attemptStatus.IsSubmitted
|
| 128 |
|
| 129 |
-
return attemptStatus, examEventAttempt,
|
| 130 |
}
|
| 131 |
func (s *examService) SetupQuestions(ctx context.Context, eventSlug string, examId uuid.UUID, accountId uuid.UUID) ([]entity.Questions, error) {
|
| 132 |
examAssign, err := s.problemSetExamAssignRepo.GetByExam(ctx, examId)
|
| 133 |
|
| 134 |
-
if err != nil {
|
| 135 |
-
return []entity.Questions{}, err
|
| 136 |
-
}
|
| 137 |
-
problemSet, err := s.problemSetService.GetProblemSet(ctx, examAssign.ProblemSetId)
|
| 138 |
-
|
| 139 |
if err != nil {
|
| 140 |
return []entity.Questions{}, err
|
| 141 |
}
|
| 142 |
|
| 143 |
-
questions, err := s.problemSetService.ListQuestions(ctx,
|
| 144 |
|
| 145 |
if err != nil {
|
| 146 |
return []entity.Questions{}, err
|
|
@@ -158,7 +154,7 @@ func (s *examService) SetupAnswer(ctx context.Context, questions []entity.Questi
|
|
| 158 |
QuestionId: q.Id,
|
| 159 |
}
|
| 160 |
|
| 161 |
-
err := s.examEventAnswerRepo.Create(ctx, blank_ans)
|
| 162 |
if err != nil {
|
| 163 |
return []entity.ExamEventAnswer{}, err
|
| 164 |
}
|
|
@@ -170,31 +166,43 @@ func (s *examService) SetupAnswer(ctx context.Context, questions []entity.Questi
|
|
| 170 |
|
| 171 |
func (s *examService) SetupExamTimer(ctx context.Context, exam entity.Exam) (time.Time, time.Time) {
|
| 172 |
startTime := time.Now()
|
| 173 |
-
dueTime := startTime.Add(exam.Duration)
|
| 174 |
return startTime, dueTime
|
| 175 |
}
|
| 176 |
|
| 177 |
func (s *examService) SubmitExamEvent(ctx context.Context, attemptId uuid.UUID) (result entity.Result, err error) {
|
| 178 |
attempt, err := s.examEventAttemptRepo.GetById(ctx, attemptId)
|
| 179 |
-
|
| 180 |
if err != nil {
|
| 181 |
return entity.Result{}, err
|
| 182 |
}
|
| 183 |
|
| 184 |
-
for _, ans := range
|
| 185 |
-
|
| 186 |
}
|
| 187 |
|
| 188 |
-
result.ExamEventAttemptId = attempt.Id
|
| 189 |
-
result.ExamEventAttempt = &attempt
|
| 190 |
-
|
| 191 |
if !attempt.Submitted {
|
| 192 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 193 |
if err != nil {
|
| 194 |
return entity.Result{}, err
|
| 195 |
}
|
| 196 |
} else {
|
| 197 |
-
err
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 198 |
if err != nil {
|
| 199 |
return entity.Result{}, err
|
| 200 |
}
|
|
@@ -214,36 +222,40 @@ func (s *examService) AttemptExamEvent(ctx context.Context, eventSlug string, ex
|
|
| 214 |
if err != nil {
|
| 215 |
return entity.ExamEventAttempt{}, err
|
| 216 |
}
|
|
|
|
|
|
|
|
|
|
| 217 |
|
|
|
|
|
|
|
|
|
|
| 218 |
if attemptStatus.IsNotAttempt {
|
| 219 |
-
questions, err := s.SetupQuestions(ctx, eventSlug, exam.Id, accountId)
|
| 220 |
-
|
| 221 |
-
if err != nil {
|
| 222 |
-
return entity.ExamEventAttempt{}, err
|
| 223 |
-
}
|
| 224 |
-
|
| 225 |
-
answers, err := s.SetupAnswer(ctx, questions, examEventAttempt.Id)
|
| 226 |
-
|
| 227 |
-
if err != nil {
|
| 228 |
-
return entity.ExamEventAttempt{}, err
|
| 229 |
-
}
|
| 230 |
|
| 231 |
startTime, dueTime := s.SetupExamTimer(ctx, exam)
|
|
|
|
|
|
|
|
|
|
| 232 |
examEventAttempt = entity.ExamEventAttempt{
|
| 233 |
AccountId: accountId,
|
| 234 |
EventId: ev.Data.Id,
|
| 235 |
ExamId: exam.Id,
|
| 236 |
-
Questions: &questions,
|
| 237 |
-
Answers: &answers,
|
| 238 |
CreatedAt: startTime,
|
| 239 |
DueAt: dueTime,
|
| 240 |
Submitted: false,
|
|
|
|
| 241 |
}
|
| 242 |
|
| 243 |
-
if err := s.examEventAttemptRepo.Create(ctx, examEventAttempt); err != nil {
|
| 244 |
return entity.ExamEventAttempt{}, err
|
| 245 |
}
|
| 246 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 247 |
return ProtectExamEventAttempt(examEventAttempt), err
|
| 248 |
|
| 249 |
} else if attemptStatus.IsOnAttempt {
|
|
@@ -251,10 +263,12 @@ func (s *examService) AttemptExamEvent(ctx context.Context, eventSlug string, ex
|
|
| 251 |
remTime := utils.CalculateRemainingTime(examEventAttempt.CreatedAt, examEventAttempt.DueAt)
|
| 252 |
examEventAttempt.RemTime = remTime
|
| 253 |
|
| 254 |
-
if err := s.examEventAttemptRepo.Update(ctx, examEventAttempt); err != nil {
|
| 255 |
return entity.ExamEventAttempt{}, err
|
| 256 |
}
|
| 257 |
|
|
|
|
|
|
|
| 258 |
return ProtectExamEventAttempt(examEventAttempt), err
|
| 259 |
|
| 260 |
} else if attemptStatus.IsTimeOut {
|
|
@@ -265,7 +279,7 @@ func (s *examService) AttemptExamEvent(ctx context.Context, eventSlug string, ex
|
|
| 265 |
|
| 266 |
s.SubmitExamEvent(ctx, examEventAttempt.Id)
|
| 267 |
examEventAttempt.Submitted = true
|
| 268 |
-
if err := s.examEventAttemptRepo.Update(ctx, examEventAttempt); err != nil {
|
| 269 |
return entity.ExamEventAttempt{}, err
|
| 270 |
}
|
| 271 |
|
|
@@ -279,15 +293,25 @@ func (s *examService) EvaluateAnswer(ctx context.Context, question entity.Questi
|
|
| 279 |
|
| 280 |
nonCPEvaluator := func(answer []string) (float32, entity.CPQuestionVerdict) {
|
| 281 |
score := float32(0)
|
|
|
|
| 282 |
for i, ans := range answer {
|
|
|
|
|
|
|
| 283 |
if ans != question.AnsKey[i] && ans != "" {
|
| 284 |
score += float32(question.IncorrMark)
|
|
|
|
|
|
|
| 285 |
} else if ans == "" {
|
| 286 |
score += float32(question.NullMark)
|
| 287 |
-
|
| 288 |
-
|
| 289 |
}
|
| 290 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 291 |
return score, entity.CPQuestionVerdict{}
|
| 292 |
}
|
| 293 |
|
|
@@ -321,7 +345,7 @@ func (s *examService) AnswerExamEvent(ctx context.Context, attemptId uuid.UUID,
|
|
| 321 |
|
| 322 |
score, CPQuestionVerdict := s.EvaluateAnswer(ctx, question)(answer)
|
| 323 |
|
| 324 |
-
err = s.examEventAnswerRepo.Update(ctx, entity.ExamEventAnswer{
|
| 325 |
AttemptId: attemptId,
|
| 326 |
QuestionId: questionId,
|
| 327 |
Answers: answer,
|
|
|
|
| 3 |
import (
|
| 4 |
"context"
|
| 5 |
"errors"
|
| 6 |
+
"fmt"
|
| 7 |
"time"
|
| 8 |
|
| 9 |
"abdanhafidz.com/go-boilerplate/models/dto"
|
|
|
|
| 53 |
func ProtectExamEventAttempt(attempt entity.ExamEventAttempt) entity.ExamEventAttempt {
|
| 54 |
|
| 55 |
var cleanQuestions []entity.Questions
|
| 56 |
+
for _, q := range attempt.Questions {
|
| 57 |
qCopy := q
|
| 58 |
qCopy.AnsKey = nil // hide answer key
|
| 59 |
qCopy.CorrMark = 0
|
|
|
|
| 62 |
|
| 63 |
cleanQuestions = append(cleanQuestions, qCopy)
|
| 64 |
}
|
| 65 |
+
attempt.Questions = cleanQuestions
|
| 66 |
|
| 67 |
// protect answers verdict info
|
| 68 |
var cleanAnswers []entity.ExamEventAnswer
|
| 69 |
|
| 70 |
+
for _, a := range attempt.Answers {
|
| 71 |
aCopy := a
|
| 72 |
aCopy.Score = 0 // hide score
|
| 73 |
|
| 74 |
cleanAnswers = append(cleanAnswers, aCopy)
|
| 75 |
}
|
| 76 |
|
| 77 |
+
attempt.Answers = cleanAnswers
|
| 78 |
|
| 79 |
return attempt
|
| 80 |
}
|
|
|
|
| 100 |
return ev, exam, err
|
| 101 |
}
|
| 102 |
|
| 103 |
+
if exam, err = s.examRepo.GetBySlug(ctx, examSlug); err != nil {
|
| 104 |
return ev, exam, err
|
| 105 |
}
|
| 106 |
|
|
|
|
| 116 |
}
|
| 117 |
|
| 118 |
examEventAttempt, err := s.examEventAttemptRepo.GetByExamEvent(ctx, ev.Data.Id, exam.Id, accountId)
|
| 119 |
+
fmt.Println("Error Exam Event Attempt", errors.Is(err, gorm.ErrRecordNotFound))
|
| 120 |
if err != nil && !errors.Is(err, gorm.ErrRecordNotFound) {
|
| 121 |
return dto.UserExamStatus{}, entity.ExamEventAttempt{}, err
|
| 122 |
}
|
|
|
|
| 127 |
attemptStatus.IsSubmitted = examEventAttempt.Submitted
|
| 128 |
attemptStatus.IsOnAttempt = !attemptStatus.IsNotAttempt && !attemptStatus.IsTimeOut && !attemptStatus.IsSubmitted
|
| 129 |
|
| 130 |
+
return attemptStatus, examEventAttempt, nil
|
| 131 |
}
|
| 132 |
func (s *examService) SetupQuestions(ctx context.Context, eventSlug string, examId uuid.UUID, accountId uuid.UUID) ([]entity.Questions, error) {
|
| 133 |
examAssign, err := s.problemSetExamAssignRepo.GetByExam(ctx, examId)
|
| 134 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 135 |
if err != nil {
|
| 136 |
return []entity.Questions{}, err
|
| 137 |
}
|
| 138 |
|
| 139 |
+
questions, err := s.problemSetService.ListQuestions(ctx, examAssign.ProblemSetId)
|
| 140 |
|
| 141 |
if err != nil {
|
| 142 |
return []entity.Questions{}, err
|
|
|
|
| 154 |
QuestionId: q.Id,
|
| 155 |
}
|
| 156 |
|
| 157 |
+
err := s.examEventAnswerRepo.Create(ctx, &blank_ans)
|
| 158 |
if err != nil {
|
| 159 |
return []entity.ExamEventAnswer{}, err
|
| 160 |
}
|
|
|
|
| 166 |
|
| 167 |
func (s *examService) SetupExamTimer(ctx context.Context, exam entity.Exam) (time.Time, time.Time) {
|
| 168 |
startTime := time.Now()
|
| 169 |
+
dueTime := startTime.Add(exam.Duration * time.Minute)
|
| 170 |
return startTime, dueTime
|
| 171 |
}
|
| 172 |
|
| 173 |
func (s *examService) SubmitExamEvent(ctx context.Context, attemptId uuid.UUID) (result entity.Result, err error) {
|
| 174 |
attempt, err := s.examEventAttemptRepo.GetById(ctx, attemptId)
|
| 175 |
+
finalScore := float32(0)
|
| 176 |
if err != nil {
|
| 177 |
return entity.Result{}, err
|
| 178 |
}
|
| 179 |
|
| 180 |
+
for _, ans := range attempt.Answers {
|
| 181 |
+
finalScore += ans.Score
|
| 182 |
}
|
| 183 |
|
|
|
|
|
|
|
|
|
|
| 184 |
if !attempt.Submitted {
|
| 185 |
+
|
| 186 |
+
attempt.Submitted = true
|
| 187 |
+
result.AttemptId = attempt.Id
|
| 188 |
+
result.ExamEventAttempt = &attempt
|
| 189 |
+
result.FinalScore = float32(finalScore)
|
| 190 |
+
|
| 191 |
+
s.examEventAttemptRepo.Update(ctx, &attempt)
|
| 192 |
+
err := s.resultRepo.Create(ctx, &result)
|
| 193 |
+
|
| 194 |
if err != nil {
|
| 195 |
return entity.Result{}, err
|
| 196 |
}
|
| 197 |
} else {
|
| 198 |
+
result, err = s.resultRepo.GetByAttemptId(ctx, attempt.Id)
|
| 199 |
+
|
| 200 |
+
if err != nil {
|
| 201 |
+
return entity.Result{}, err
|
| 202 |
+
}
|
| 203 |
+
|
| 204 |
+
result.FinalScore = float32(finalScore)
|
| 205 |
+
err := s.resultRepo.Update(ctx, &result)
|
| 206 |
if err != nil {
|
| 207 |
return entity.Result{}, err
|
| 208 |
}
|
|
|
|
| 222 |
if err != nil {
|
| 223 |
return entity.ExamEventAttempt{}, err
|
| 224 |
}
|
| 225 |
+
questions, err := s.SetupQuestions(ctx, eventSlug, exam.Id, accountId)
|
| 226 |
+
examEventAttempt.Questions = questions
|
| 227 |
+
fmt.Println("Question = ", questions)
|
| 228 |
|
| 229 |
+
if err != nil {
|
| 230 |
+
return entity.ExamEventAttempt{}, err
|
| 231 |
+
}
|
| 232 |
if attemptStatus.IsNotAttempt {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 233 |
|
| 234 |
startTime, dueTime := s.SetupExamTimer(ctx, exam)
|
| 235 |
+
remTime := utils.CalculateRemainingTime(startTime, dueTime)
|
| 236 |
+
|
| 237 |
+
fmt.Println("Rem Time = ", remTime)
|
| 238 |
examEventAttempt = entity.ExamEventAttempt{
|
| 239 |
AccountId: accountId,
|
| 240 |
EventId: ev.Data.Id,
|
| 241 |
ExamId: exam.Id,
|
|
|
|
|
|
|
| 242 |
CreatedAt: startTime,
|
| 243 |
DueAt: dueTime,
|
| 244 |
Submitted: false,
|
| 245 |
+
RemTime: remTime,
|
| 246 |
}
|
| 247 |
|
| 248 |
+
if err := s.examEventAttemptRepo.Create(ctx, &examEventAttempt); err != nil {
|
| 249 |
return entity.ExamEventAttempt{}, err
|
| 250 |
}
|
| 251 |
|
| 252 |
+
answers, err := s.SetupAnswer(ctx, questions, examEventAttempt.Id)
|
| 253 |
+
fmt.Println("Answer = ", answers)
|
| 254 |
+
if err != nil {
|
| 255 |
+
return entity.ExamEventAttempt{}, err
|
| 256 |
+
}
|
| 257 |
+
|
| 258 |
+
examEventAttempt.Answers = answers
|
| 259 |
return ProtectExamEventAttempt(examEventAttempt), err
|
| 260 |
|
| 261 |
} else if attemptStatus.IsOnAttempt {
|
|
|
|
| 263 |
remTime := utils.CalculateRemainingTime(examEventAttempt.CreatedAt, examEventAttempt.DueAt)
|
| 264 |
examEventAttempt.RemTime = remTime
|
| 265 |
|
| 266 |
+
if err := s.examEventAttemptRepo.Update(ctx, &examEventAttempt); err != nil {
|
| 267 |
return entity.ExamEventAttempt{}, err
|
| 268 |
}
|
| 269 |
|
| 270 |
+
examEventAttempt.Questions = questions
|
| 271 |
+
|
| 272 |
return ProtectExamEventAttempt(examEventAttempt), err
|
| 273 |
|
| 274 |
} else if attemptStatus.IsTimeOut {
|
|
|
|
| 279 |
|
| 280 |
s.SubmitExamEvent(ctx, examEventAttempt.Id)
|
| 281 |
examEventAttempt.Submitted = true
|
| 282 |
+
if err := s.examEventAttemptRepo.Update(ctx, &examEventAttempt); err != nil {
|
| 283 |
return entity.ExamEventAttempt{}, err
|
| 284 |
}
|
| 285 |
|
|
|
|
| 293 |
|
| 294 |
nonCPEvaluator := func(answer []string) (float32, entity.CPQuestionVerdict) {
|
| 295 |
score := float32(0)
|
| 296 |
+
isCorrect := true
|
| 297 |
for i, ans := range answer {
|
| 298 |
+
fmt.Println("User Answer :", ans)
|
| 299 |
+
fmt.Println("Answer Key :", question.AnsKey[i])
|
| 300 |
if ans != question.AnsKey[i] && ans != "" {
|
| 301 |
score += float32(question.IncorrMark)
|
| 302 |
+
isCorrect = false
|
| 303 |
+
break
|
| 304 |
} else if ans == "" {
|
| 305 |
score += float32(question.NullMark)
|
| 306 |
+
isCorrect = false
|
| 307 |
+
break
|
| 308 |
}
|
| 309 |
}
|
| 310 |
+
|
| 311 |
+
if isCorrect {
|
| 312 |
+
score += float32(question.CorrMark)
|
| 313 |
+
}
|
| 314 |
+
|
| 315 |
return score, entity.CPQuestionVerdict{}
|
| 316 |
}
|
| 317 |
|
|
|
|
| 345 |
|
| 346 |
score, CPQuestionVerdict := s.EvaluateAnswer(ctx, question)(answer)
|
| 347 |
|
| 348 |
+
err = s.examEventAnswerRepo.Update(ctx, &entity.ExamEventAnswer{
|
| 349 |
AttemptId: attemptId,
|
| 350 |
QuestionId: questionId,
|
| 351 |
Answers: answer,
|
utils/util.go
CHANGED
|
@@ -33,5 +33,5 @@ func CalculateRemainingTime(startTime, dueTime time.Time) int {
|
|
| 33 |
if remaining < 0 {
|
| 34 |
return 0
|
| 35 |
}
|
| 36 |
-
return remaining
|
| 37 |
}
|
|
|
|
| 33 |
if remaining < 0 {
|
| 34 |
return 0
|
| 35 |
}
|
| 36 |
+
return remaining / 60
|
| 37 |
}
|