gaku_core 0.3.0.pre.0 → 0.3.0.pre.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (34) hide show
  1. checksums.yaml +4 -4
  2. data/app/assets/javascripts/gaku/courses.js.coffee +20 -0
  3. data/app/assets/javascripts/gaku/exams.js.coffee +23 -0
  4. data/app/assets/stylesheets/gaku/bootstrap_and_theme.css.scss +574 -0
  5. data/app/controllers/gaku/courses/exams/exam_portion_scores_controller.rb +23 -0
  6. data/app/controllers/gaku/courses/exams_controller.rb +291 -0
  7. data/app/controllers/gaku/exams_controller.rb +170 -0
  8. data/app/helpers/gaku/gaku_helper.rb +155 -0
  9. data/app/models/gaku/enrollment.rb +1 -1
  10. data/app/models/gaku/exam_portion.rb +9 -0
  11. data/app/models/gaku/semester_connector.rb +1 -1
  12. data/app/models/gaku/student.rb +4 -0
  13. data/app/views/gaku/admin/grading_methods/_form_fields.html.slim +7 -0
  14. data/app/views/gaku/courses/_form_fields.html.slim +5 -0
  15. data/app/views/gaku/courses/exams/exam_portion_scores/update.js.erb +5 -0
  16. data/app/views/gaku/courses/exams/grading/_calculations.html.slim +16 -0
  17. data/app/views/gaku/courses/exams/grading/_exam_portion_score_form.htmls.lim +0 -0
  18. data/app/views/gaku/courses/exams/grading/_exam_scores.html.slim +78 -0
  19. data/app/views/gaku/courses/exams/grading/_students.html.slim +12 -0
  20. data/app/views/gaku/courses/exams/grading.html.slim +38 -0
  21. data/app/views/gaku/layouts/gaku.html.slim +25 -0
  22. data/app/views/gaku/shared/menu/_global.html.erb +1 -1
  23. data/config/locales/bg.yml +421 -413
  24. data/config/locales/en.yml +53 -110
  25. data/config/locales/ja.yml +891 -883
  26. data/config/locales/pt-BR.yml +11 -3
  27. data/config/locales/zh-CN.yml +9 -1
  28. data/config/routes.rb +120 -5
  29. data/db/migrate/20160209100945_add_score_types_to_exam_portions.rb +6 -0
  30. data/db/migrate/20160209104713_add_fields_to_exam_portion_score.rb +6 -0
  31. data/lib/gaku/grading/single/percentage.rb +3 -3
  32. data/lib/gaku/grading/single/score.rb +3 -3
  33. data/lib/gaku/testing/factories/exam_portion_factory.rb +1 -1
  34. metadata +20 -2
@@ -0,0 +1,291 @@
1
+ module Gaku
2
+ class Courses::ExamsController < GakuController
3
+
4
+ respond_to :html
5
+
6
+
7
+ def grading
8
+
9
+ def init_variables
10
+ @course = Course.find(params[:course_id])
11
+ @exam = Exam.find(params[:id])
12
+ @students = @course.students
13
+ if params[:id] != nil
14
+ @exams = Exam.find_all_by_id(params[:id])
15
+ else
16
+ @exams = @course.syllabus.exams.all
17
+ end
18
+
19
+ # 試験の平均点を入れるハッシュ
20
+ @exams_average = Hash.new{|h,k| h[k]=Hash.new(&h.default_proc)}
21
+
22
+ # 試験の合計点を入れるハッシュ
23
+ @student_exams_total_score = Hash.new{|h,k| h[k]=Hash.new(&h.default_proc)}
24
+
25
+ # 偏差値を入れるハッシュ
26
+ @student_exams_deviation = Hash.new{|h,k| h[k]=Hash.new(&h.default_proc)}
27
+
28
+ # for grade and rank--------
29
+ # 10段階用の設定
30
+ # @student_exams_grade: 生徒の10段階を入れるHash。
31
+ @student_exams_grade = Hash.new{|h,k| h[k]=Hash.new(&h.default_proc)}
32
+
33
+ # 5段階用の設定
34
+ # @student_exams_rank: 生徒の5段階を入れるHash。
35
+ @student_exams_rank = Hash.new{|h,k| h[k]=Hash.new(&h.default_proc)}
36
+ end
37
+
38
+ def set_student_exams_total_scores_and_set_exams_average
39
+ @exams.each do |exam|
40
+ @students.each do |student|
41
+
42
+ # 素点用と得点用変数の初期化 --------
43
+ @student_exams_total_score[:raw][exam.id][student.id] = 0.0
44
+ @student_exams_total_score[exam.id][student.id] = 0.0
45
+
46
+ @exams_average[:raw][exam.id] = 0.0
47
+ @exams_average[exam.id] = 0.0
48
+
49
+ exam.exam_portions.each do |portion|
50
+ seps = student.exam_portion_scores.where(exam_portion_id: portion.id).first.score.to_f
51
+
52
+ @student_exams_total_score[:raw][exam.id][student.id] += seps
53
+ if exam.use_weighting
54
+ @student_exams_total_score[exam.id][student.id] += (portion.weight.to_f / 100) * seps
55
+ else
56
+ @student_exams_total_score[exam.id][student.id] += seps
57
+ end
58
+ end
59
+
60
+ # calc for average --------
61
+ @exams_average[:raw][exam.id] += @student_exams_total_score[:raw][exam.id][student.id]
62
+ @exams_average[exam.id] += @student_exams_total_score[exam.id][student.id]
63
+ end
64
+
65
+ # set Exams Average --------
66
+ if exam === @exams.last
67
+ @exams_average[:raw][exam.id] = fix_digit @exams_average[:raw][exam.id] / @students.length, 4
68
+ @exams_average[exam.id] = fix_digit @exams_average[exam.id] / @students.length, 4
69
+ end
70
+ end
71
+ end
72
+
73
+ def set_student_exams_deviaton
74
+
75
+ def get_standard_deviation exam
76
+ scratch_standard_deviation = 0.0
77
+ @students.each do |student|
78
+ scratch_standard_deviation += (@student_exams_total_score[exam.id][student.id] - @exams_average[exam.id]) ** 2
79
+ end
80
+ return Math.sqrt scratch_standard_deviation / @students.length
81
+ end
82
+
83
+ def get_deviation standard_deviation, exam, student
84
+ scratch_deviation = (@student_exams_total_score[exam.id][student.id] - @exams_average[exam.id]) / standard_deviation
85
+ if scratch_deviation.nan?
86
+ return 50
87
+ else
88
+ return fix_digit @student_exams_deviation[exam.id][student.id] * 10 + 50, 4
89
+ end
90
+ end
91
+
92
+ # start main --------
93
+ @exams.each do |exam|
94
+ standard_deviation = get_standard_deviation(exam)
95
+
96
+ # set deviations --------
97
+ @students.each do |student|
98
+ @student_exams_deviation[exam.id][student.id] = get_deviation(standard_deviation, exam, student)
99
+ end
100
+ end
101
+ end
102
+
103
+ def set_student_exams_grade_and_rank
104
+
105
+ # def method_ratio(grading_method)
106
+ def method_ratio
107
+ default_grade_level_deviation = [100, 66, 62, 58, 55, 50, 45, 37, 0]
108
+ @rank_level = [15, 20]
109
+
110
+ # default_grade_level_percent = [5, 5, 10, 10, 30, 10, 100]
111
+
112
+ default = {
113
+ # for grade ----
114
+ g10: 100,
115
+ g9: 66,
116
+ g8: 62,
117
+
118
+ # for rank----
119
+ r10: 5,
120
+ r9: 5,
121
+ r8: 10
122
+ }
123
+
124
+ default = {
125
+ grade:{
126
+ g10: 100,
127
+ g9: 66,
128
+ g8: 62
129
+ },
130
+ rank: {
131
+ r10: 5,
132
+ r9: 5,
133
+ r8: 10
134
+ }
135
+ }
136
+
137
+ # @grade_level_deviation:
138
+ # 10段階の全体評価で判定する時に使う変数。
139
+ # 決められた偏差値を基に、生徒の偏差値と比べ、その多寡で評価を行う。
140
+ # @grade_level_percent:
141
+ # 10段階の相対評価で判定する時に使う変数。
142
+ # 決められたパーセンテージを元に、生徒がクラス内で上位何%以内かを調べ、評価を行う。
143
+
144
+ @ = JSON.parse grading_method.method.arguments, symbolize_names: true
145
+
146
+ @grade_level_deviation = [100, 66, 62, 58, 55, 50, 45, 37, 0]
147
+ @grade_level_percent = [5, 5, 10, 10, 30, 10, 100]
148
+
149
+ # @rank_level: 5段階を付ける時に使うパーセンテージ配列の変数。
150
+ @rank_level = [15, 20]
151
+
152
+
153
+
154
+ # Grade and Rank Calculation (ここは別途光ヶ丘の生徒評価表を参照して下さい)-------- {
155
+ # set grade and rank --------
156
+ @exams.each do |exam|
157
+
158
+ # 生徒の順位用配列を作成
159
+ exam_student_scores = Hash.new{|h,k| h[k]=Hash.new(&h.default_proc)} # 生徒の順位を出す為の変数。
160
+
161
+ # 試験毎の合計点数と生徒IDをexam_student_scoresに格納する。
162
+ @students.each do |student|
163
+ exam_student_scores[student.id] = @student_exams_total_score[exam.id][student.id]
164
+ end
165
+ # 試験のスコアを降順に並び替える
166
+ exam_student_scores = exam_student_scores.sort_by {|key,val| -val}
167
+
168
+ # 採点方式を選択、その採点方式でGradeを決定。
169
+ grading_method = 1
170
+ grade_point = 10
171
+
172
+ case grading_method
173
+
174
+ # calc for 全体評価
175
+ when 1
176
+ @grade_level_deviation.each_with_index do |glevel, i|
177
+ @students.each do |student|
178
+ if @grade_level_deviation[i] > @student_exams_deviation[exam.id][student.id] && @grade_level_deviation[i+1] <= @student_exams_deviation[exam.id][student.id]
179
+ @student_exams_grade[exam.id][student.id] = grade_point
180
+ end
181
+ end
182
+ grade_point -= 1
183
+ end
184
+
185
+ # calc for 相対評価
186
+ when 2
187
+ scratch_exam_student_scores = exam_student_scores.clone
188
+ grade_limit_nums = []
189
+ @grade_level_percent.each do |glevel|
190
+ grade_limit_nums.push((@students.length * (glevel.to_f / 100)).ceil)
191
+ end
192
+ grade_limit_nums.each do |gnum|
193
+ i = 0
194
+ while i < gnum && scratch_exam_student_scores.length != 0
195
+ @student_exams_grade[exam.id][scratch_exam_student_scores.shift[0]] = grade_point
196
+ i += 1
197
+ end
198
+ grade_point -= 1
199
+ end
200
+
201
+ end
202
+
203
+ # Rank Calculation --------
204
+ # rankPoint = 5
205
+ # @students.each do |student|
206
+ # @student_exams_rank[exam.id][student.id] = 3
207
+ # end
208
+ # rankNums = []
209
+ # @rank_level.each do |rlevel|
210
+ # rankNums.push((@students.length * (rlevel.to_f / 100)).ceil)
211
+ # end
212
+ # rankNums.each do |rnum|
213
+ # i = 0
214
+ # while i < rnum && exam_student_scores.length != 0
215
+ # scoreMem = exam_student_scores.shift()
216
+ # @student_exams_rank[exam.id][scoreMem[1]] = rankPoint
217
+ # if exam_student_scores.length != 0 and scoreMem[0] == exam_student_scores[0][0]
218
+ # rnum += 1
219
+ # end
220
+ # i += 1
221
+ # end
222
+ # rankPoint -= 1
223
+ # end
224
+ # exam_student_scores.each do |score|
225
+ # if @student_exams_grade[exam.id][socre[1]] == 3
226
+ # @student_exams_rank[exam.id][score[1]] = 2
227
+ # elsif @student_exams_grade[exam.id][socre[1]] < 3
228
+ # @student_exams_rank[exam.id][score[1]] = 1
229
+ # end
230
+ # end
231
+ end
232
+ end
233
+
234
+ # start main --------
235
+ # p '@exam.grading_method.method -------'
236
+ # p @exam.grading_method
237
+
238
+ # case @exam.grading_method.method
239
+ case "ratio"
240
+
241
+ when "ratio"
242
+ # method_ratio(@exam.grading_method)
243
+ # method_ratio()
244
+ method = Grading::Ratio.new (arguments)
245
+
246
+ exam.student_score.each do |student|
247
+ results << method.grade (student, exam)
248
+ end
249
+
250
+ return results
251
+
252
+
253
+ end
254
+
255
+ end
256
+
257
+ def fix_digit num, digit_num
258
+ for_fix = 10 ** digit_num
259
+ num = num * for_fix
260
+ if num.nan?
261
+ num = 0
262
+ else
263
+ num = num.truncate.to_f / for_fix.to_f
264
+ end
265
+ return num
266
+ end
267
+
268
+ # start main --------
269
+ init_variables()
270
+ init_portion_scores()
271
+ set_student_exams_total_scores_and_set_exams_average()
272
+ set_student_exams_deviaton()
273
+ set_student_exams_grade_and_rank()
274
+
275
+ respond_with @exam
276
+ end
277
+
278
+ private
279
+
280
+ def init_portion_scores
281
+ @students.each do |student|
282
+ @exam.exam_portions.each do |portion|
283
+ unless portion.exam_portion_scores.pluck(:student_id).include?(student.id)
284
+ ExamPortionScore.create!(exam_portion: portion, student: student)
285
+ end
286
+ end
287
+ end
288
+ end
289
+
290
+ end
291
+ end
@@ -0,0 +1,170 @@
1
+ module Gaku
2
+ class ExamsController < GakuController
3
+
4
+ respond_to :html, :js, :json
5
+ respond_to :xls, only: :export
6
+
7
+ include Gaku::Grading::Calculations
8
+
9
+ before_action :set_exam, only: %i( show edit update soft_delete )
10
+ before_action :set_unscoped_exam, only: %i( destroy recovery )
11
+ before_action :load_data, only: %i( new edit )
12
+
13
+ def index
14
+ if params[:course_id]
15
+ @exams = Course.find(params[:course_id]).syllabus.exams
16
+ else
17
+ @exams = Exam.all
18
+ @exam = Exam.new
19
+ end
20
+
21
+ @exam.exam_portions.build
22
+ set_count
23
+ respond_to do |format|
24
+ format.html
25
+ format.json { render json: @exams.as_json(include: {exam_portions: {include: :exam_portion_scores}})}
26
+ end
27
+ end
28
+
29
+ def show
30
+ respond_with @exam
31
+ end
32
+
33
+ def new
34
+ @exam = Exam.new
35
+ @master_portion = @exam.exam_portions.new
36
+ respond_with @exam
37
+ end
38
+
39
+ def create
40
+ @exam = Exam.create(exam_params)
41
+ @exam.save
42
+ set_count
43
+ respond_with @exam
44
+ end
45
+
46
+ def edit
47
+ respond_with @exam
48
+ end
49
+
50
+ def update
51
+ @exam.update(exam_params)
52
+ respond_with @exam, location: [:edit, @exam]
53
+ end
54
+
55
+ def destroy
56
+ @exam.destroy
57
+ set_count
58
+ respond_with @exam
59
+ end
60
+
61
+ def recovery
62
+ @exam.recover
63
+ respond_with @exam
64
+ end
65
+
66
+ def soft_delete
67
+ @exam.soft_delete
68
+ respond_with @exam, location: exams_path
69
+ end
70
+
71
+ def export
72
+ @course = Course.find(params[:course_id])
73
+ end
74
+
75
+
76
+ # def grading
77
+ # @course = Course.find(params[:course_id])
78
+ # @exam = Exam.find(params[:id])
79
+ # @students = @course.students
80
+
81
+ # respond_with @exam
82
+ # find_exams
83
+
84
+ # calculate_totals
85
+ # calculate_exam_averages
86
+ # calculate_deviation
87
+ # calculate_rank_and_grade
88
+
89
+ # @path_to_exam = course_path(id: params[:course_id])
90
+
91
+ # #exam_portions need reload to properly include exam_portion_score in as_json
92
+ # @exams.each { |exam| exam.exam_portions.reload }
93
+
94
+ # respond_to do |format|
95
+ # format.json do render json: {
96
+ # student_total_scores: @student_total_scores.as_json,
97
+ # exams: @exams.as_json(include: {exam_portions: {include: :exam_portion_scores }},root: false),
98
+ # course: @course.as_json(root: false),
99
+ # exam_averages: @exam_averages.as_json(root: false),
100
+ # deviation: @deviation.as_json(root: false),
101
+ # students: @students.to_json(root: false),
102
+ # grades: @grades.as_json(root: false),
103
+ # ranks: @ranks.as_json(root: false),
104
+ # attendances: @student_portion_attendance.as_json(root: true, include: :attendance_type),
105
+ # path_to_exam: @path_to_exam.to_json,
106
+ # completion: @completion
107
+ # }end
108
+ # format.html { render 'gaku/exams/grading' }
109
+ # end
110
+ # end
111
+
112
+ def completed
113
+ @exam = Exam.find(params[:id])
114
+ @course = Course.find(params[:course_id])
115
+ @students = @course.students
116
+
117
+
118
+ respond_with @exam.completed_by_students(@students)
119
+ end
120
+
121
+ protected
122
+
123
+ def exam_params
124
+ params.require(:exam).permit(attributes)
125
+ end
126
+
127
+ private
128
+
129
+ def load_data
130
+ @departments = Department.all
131
+ end
132
+
133
+ def t_resource
134
+ t(:'exam.singular')
135
+ end
136
+
137
+ def attributes
138
+ [:name, :department_id, :weight, :description, :adjustments, :use_weighting,
139
+ exam_portions_attributes: [:id, :name, :weight, :problem_count, :max_score, :description, :adjustments]
140
+ ]
141
+ end
142
+
143
+ def set_exam
144
+ @exam = Exam.find(params[:id])
145
+ set_notable
146
+ end
147
+
148
+ def set_unscoped_exam
149
+ @exam = Exam.unscoped.find(params[:id])
150
+ set_notable
151
+ end
152
+
153
+ def set_notable
154
+ @notable = @exam
155
+ @notable_resource = @notable.class.to_s.underscore.split('/')[1].gsub('_','-')
156
+ end
157
+
158
+ def set_count
159
+ @count = Exam.count
160
+ end
161
+
162
+ def find_exams
163
+ if params[:id] != nil
164
+ @exams = Exam.where(id: params[:id])
165
+ else
166
+ @exams = @course.syllabus.exams
167
+ end
168
+ end
169
+ end
170
+ end
@@ -0,0 +1,155 @@
1
+ module Gaku
2
+ module GakuHelper
3
+
4
+ include SortHelper
5
+ include TranslationsHelper
6
+ include FlashHelper
7
+
8
+ def broadcast(channel, &block)
9
+ message = {:channel => channel, :data => capture(&block)}
10
+ uri = URI.parse("http://localhost:9292/faye")
11
+ Net::HTTP.post_form(uri, :message => message.to_json)
12
+ end
13
+
14
+
15
+ def tr_for(resource, &block)
16
+ content_tag :tr, id: "#{resource.class.to_s.demodulize.underscore.dasherize}-#{resource.id}" do
17
+ block.call
18
+ end
19
+ end
20
+
21
+ def current_parent_controller
22
+ controller.controller_path.split('/').second
23
+ end
24
+
25
+ def current_controller_action
26
+ controller.action_name
27
+ end
28
+
29
+ def drag_field
30
+ content_tag :td, class: 'sort-handler' do
31
+ content_tag :i, nil, class: 'icon-move'
32
+ end
33
+ end
34
+
35
+ def can_edit?
36
+ if controller.action_name.include?('edit')
37
+ true
38
+ else
39
+ false
40
+ end
41
+ end
42
+
43
+ def cannot_edit?
44
+ ! can_edit?
45
+ end
46
+
47
+ def genders
48
+ { t(:'gender.female') => false, t(:'gender.male') => true }
49
+ end
50
+
51
+ def style_semester(date)
52
+ date.strftime('')
53
+ end
54
+
55
+ def required_field
56
+ content_tag :span, t(:required), class: 'label label-important pull-right'
57
+ end
58
+
59
+ def render_js_partial(partial, locals = {})
60
+ unless locals == {}
61
+ escape_javascript(render partial: partial, formats: [:html], handlers: [:erb, :slim], locals: locals)
62
+ else
63
+ escape_javascript(render partial: partial, formats: [:html], handlers: [:erb, :slim])
64
+ end
65
+ end
66
+
67
+ def title(text)
68
+ content_for(:title) do
69
+ text
70
+ end
71
+ end
72
+
73
+ def color_code(color)
74
+ content_tag :div, nil, style: "width:100px;height:20px;background-color:#{color}"
75
+ end
76
+
77
+
78
+
79
+ def comma_separated_list(objects, &block)
80
+ if objects.any?
81
+ objects.map do |object|
82
+ block_given? ? block.call(object) : object
83
+ end.join(', ').html_safe
84
+ else
85
+ t(:empty)
86
+ end
87
+ end
88
+
89
+ def prepare_target(nested_resource, address)
90
+ return nil if nested_resource.blank?
91
+ [nested_resource, address].flatten
92
+ end
93
+
94
+ def prepare_resource_name(nested_resources, resource)
95
+ @resource_name = [nested_resources.map {|r| r.is_a?(Symbol) ? r.to_s : get_class(r) }, resource.to_s].flatten.join '-'
96
+ end
97
+
98
+ def exam_completion_info(exam)
99
+ @course_students ||= @course.students
100
+ ungraded = exam.ungraded(@course_students)
101
+ total = exam.total_records(@course_students)
102
+
103
+ percentage = number_to_percentage exam.completion(@course_students), precision: 2
104
+
105
+ "#{t(:'exam.completion')}:#{percentage} #{t(:'exam.graded')}:#{total - ungraded} #{t(:'exam.ungraded')}:#{ungraded} #{t(:'exam.total')}:#{total}"
106
+ end
107
+
108
+ def datepicker_date_format(date)
109
+ date ? date.strftime('%Y-%m-%d') : Time.now.strftime('%Y-%m-%d')
110
+ end
111
+
112
+ def extract_grouped(grouped, resource)
113
+ grouped.map(&resource.to_sym)
114
+ end
115
+
116
+ def nested_header(text)
117
+ content_tag :h4, text
118
+ end
119
+
120
+ def state_load(object)
121
+ object.country.nil? ? Gaku::State.none : object.country.states
122
+ end
123
+
124
+ def disabled?(object)
125
+ object.new_record? || object.country.states.blank?
126
+ end
127
+
128
+ def link_to_download(resource, options = {})
129
+ name = content_tag(:span, nil, class: 'glyphicon glyphicon-download')
130
+ attributes = {
131
+ class: "btn btn-xs btn-success download-link"
132
+ }.merge(options)
133
+ link_to name, resource, attributes
134
+ end
135
+
136
+ def ajax_link_to_recovery(resource, options = {})
137
+ name = content_tag(:span, nil, class: 'glyphicon glyphicon-repeat')
138
+ attributes = {
139
+ remote: true,
140
+ class: "btn btn-xs btn-success recovery-link"
141
+ }.merge(options)
142
+ link_to name, resource, attributes
143
+ end
144
+
145
+ def icon(name)
146
+ content_tag(:span, nil, class: "#{name}")
147
+ end
148
+
149
+ def icon_label(icon_name, label)
150
+ raw %{ #{icon(icon_name)} #{label} }
151
+ end
152
+
153
+ end
154
+ end
155
+
@@ -8,7 +8,7 @@ module Gaku
8
8
 
9
9
  validates :student_id,
10
10
  uniqueness: {
11
- scope: %w( enrollable_type enrollable_id ),
11
+ scope: %i( enrollable_type enrollable_id ),
12
12
  message: I18n.t(:'student.already_enrolled')
13
13
  }
14
14
 
@@ -26,6 +26,9 @@ module Gaku
26
26
  after_destroy :refresh_positions
27
27
 
28
28
  before_update :weight_calculate
29
+ before_save :sanitize_score_selection_options
30
+
31
+ enum score_type: %i( score score_selection score_text )
29
32
 
30
33
  def to_s
31
34
  name
@@ -68,6 +71,12 @@ module Gaku
68
71
 
69
72
  private
70
73
 
74
+ def sanitize_score_selection_options
75
+ if self.score_selection_options
76
+ self.score_selection_options = self.score_selection_options.reject(&:blank?)
77
+ end
78
+ end
79
+
71
80
  def proper_position
72
81
  self.position = exam.exam_portions.count
73
82
  end
@@ -7,7 +7,7 @@ module Gaku
7
7
  validates :semester_id, :semesterable_type, :semesterable_id, presence: true
8
8
 
9
9
  validates :semester_id,
10
- uniqueness: { scope: %w( semesterable_type semesterable_id ), message: I18n.t(:'semester.already') }
10
+ uniqueness: { scope: %i( semesterable_id semesterable_type ), message: I18n.t(:'semester.already') }
11
11
 
12
12
  validates :semesterable_type,
13
13
  inclusion: { in: %w( Gaku::ClassGroup Gaku::Course ), message: '%{value} is not a valid' }
@@ -62,6 +62,10 @@ module Gaku
62
62
  where(enrollment_status_code: EnrollmentStatus.active.pluck(:code))
63
63
  end
64
64
 
65
+ def full_name
66
+ "#{name} #{surname}"
67
+ end
68
+
65
69
  def make_enrolled
66
70
  enrollment_status = EnrollmentStatus.where(
67
71
  code: 'enrolled',
@@ -0,0 +1,7 @@
1
+ = f.text_field :name, label: t(:'grading_method.name')
2
+ = f.text_field :description, label: t(:'grading_method.description')
3
+
4
+ /= f.text_field :method, label: t(:'grading_method.method')
5
+ = f.select :method, {"Score" => "score", "Percentage" => "percentage", "Ordinal" => "ordinal", "Interval" => "interval", "Ratio" => "ratio", "Pass/Fail" => "pass_fail"}, {prompt: "メソッドを選択してください"} , class: "form-control"
6
+
7
+ = render 'arguments_form_fields', f: f
@@ -0,0 +1,5 @@
1
+ .row
2
+ .col-md-6
3
+ = f.select :syllabus_id, options_from_collection_for_select(@syllabuses, :id, :name), {}, label: t(:'syllabus.singular'), class: 'form-control'
4
+ .col-md-6
5
+ = f.text_field :code, placeholder: t(:'course.code_sample'), label: t(:'course.code')
@@ -0,0 +1,5 @@
1
+ var jsonObject = '<%= @exam_portion_score.to_json.html_safe.to_s %>'
2
+ <% broadcast "/messages/new" do %>
3
+ $('#edit_exam_portion_score_<%= @exam_portion_score.id %>').children('input').val('<%= @exam_portion_score.score %>')
4
+ <% end %>
5
+