Skip to content

Commit

Permalink
기능 추가: YOSA find_best_case 구현 및 테스트 확인 중
Browse files Browse the repository at this point in the history
  • Loading branch information
hyunjune-lee committed Apr 22, 2021
1 parent 9a1a495 commit f3648db
Show file tree
Hide file tree
Showing 5 changed files with 201 additions and 89 deletions.
114 changes: 114 additions & 0 deletions .vscode/.ropeproject/config.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
# The default ``config.py``
# flake8: noqa


def set_prefs(prefs):
"""This function is called before opening the project"""

# Specify which files and folders to ignore in the project.
# Changes to ignored resources are not added to the history and
# VCSs. Also they are not returned in `Project.get_files()`.
# Note that ``?`` and ``*`` match all characters but slashes.
# '*.pyc': matches 'test.pyc' and 'pkg/test.pyc'
# 'mod*.pyc': matches 'test/mod1.pyc' but not 'mod/1.pyc'
# '.svn': matches 'pkg/.svn' and all of its children
# 'build/*.o': matches 'build/lib.o' but not 'build/sub/lib.o'
# 'build//*.o': matches 'build/lib.o' and 'build/sub/lib.o'
prefs['ignored_resources'] = ['*.pyc', '*~', '.ropeproject',
'.hg', '.svn', '_svn', '.git', '.tox']

# Specifies which files should be considered python files. It is
# useful when you have scripts inside your project. Only files
# ending with ``.py`` are considered to be python files by
# default.
# prefs['python_files'] = ['*.py']

# Custom source folders: By default rope searches the project
# for finding source folders (folders that should be searched
# for finding modules). You can add paths to that list. Note
# that rope guesses project source folders correctly most of the
# time; use this if you have any problems.
# The folders should be relative to project root and use '/' for
# separating folders regardless of the platform rope is running on.
# 'src/my_source_folder' for instance.
# prefs.add('source_folders', 'src')

# You can extend python path for looking up modules
# prefs.add('python_path', '~/python/')

# Should rope save object information or not.
prefs['save_objectdb'] = True
prefs['compress_objectdb'] = False

# If `True`, rope analyzes each module when it is being saved.
prefs['automatic_soa'] = True
# The depth of calls to follow in static object analysis
prefs['soa_followed_calls'] = 0

# If `False` when running modules or unit tests "dynamic object
# analysis" is turned off. This makes them much faster.
prefs['perform_doa'] = True

# Rope can check the validity of its object DB when running.
prefs['validate_objectdb'] = True

# How many undos to hold?
prefs['max_history_items'] = 32

# Shows whether to save history across sessions.
prefs['save_history'] = True
prefs['compress_history'] = False

# Set the number spaces used for indenting. According to
# :PEP:`8`, it is best to use 4 spaces. Since most of rope's
# unit-tests use 4 spaces it is more reliable, too.
prefs['indent_size'] = 4

# Builtin and c-extension modules that are allowed to be imported
# and inspected by rope.
prefs['extension_modules'] = []

# Add all standard c-extensions to extension_modules list.
prefs['import_dynload_stdmods'] = True

# If `True` modules with syntax errors are considered to be empty.
# The default value is `False`; When `False` syntax errors raise
# `rope.base.exceptions.ModuleSyntaxError` exception.
prefs['ignore_syntax_errors'] = False

# If `True`, rope ignores unresolvable imports. Otherwise, they
# appear in the importing namespace.
prefs['ignore_bad_imports'] = False

# If `True`, rope will insert new module imports as
# `from <package> import <module>` by default.
prefs['prefer_module_from_imports'] = False

# If `True`, rope will transform a comma list of imports into
# multiple separate import statements when organizing
# imports.
prefs['split_imports'] = False

# If `True`, rope will remove all top-level import statements and
# reinsert them at the top of the module when making changes.
prefs['pull_imports_to_top'] = True

# If `True`, rope will sort imports alphabetically by module name instead
# of alphabetically by import statement, with from imports after normal
# imports.
prefs['sort_imports_alphabetically'] = False

# Location of implementation of
# rope.base.oi.type_hinting.interfaces.ITypeHintingFactory In general
# case, you don't have to change this value, unless you're an rope expert.
# Change this value to inject you own implementations of interfaces
# listed in module rope.base.oi.type_hinting.providers.interfaces
# For example, you can add you own providers for Django Models, or disable
# the search type-hinting in a class hierarchy, etc.
prefs['type_hinting_factory'] = (
'rope.base.oi.type_hinting.factory.default_type_hinting_factory')


def project_opened(project):
"""This function is called after opening the project"""
# Do whatever you like here!
Binary file added .vscode/.ropeproject/objectdb
Binary file not shown.
4 changes: 3 additions & 1 deletion Student.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@ class Student(CPU):
def __init__(self, student_name): # student_name는 학생 이름, class_list는 학생이 듣는 수업
super().__init__(student_name)
self.subject_list = []
self.best_grades = [0 for _ in range(25)]
self.best_solo_grades = [0 for _ in range(25)]
self.total_credits = 3 # 총 학점 21 학점같은 - 기본 운영체제 팀플 3학점을 듣기 때문에

def add_subject_list(self, subject):
self.subject_list.append(subject)
self.total_credits += subject.credit
4 changes: 2 additions & 2 deletions Subject.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@


class Subject(Process):
def __init__(self, process_id, grade, BT, color_idx, student_id):
def __init__(self, process_id, credit, BT, color_idx, student_id):
super().__init__(process_id, 0, BT, color_idx)
self.student_id = student_id
self.grade = grade
self.credit = credit
self.score_per_hour = 100 / BT
168 changes: 82 additions & 86 deletions YOSA.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from Scheduler import *
from itertools import combinations_with_replacement
from itertools import permutations
from itertools import product
from Student import *
from Subject import *

Expand All @@ -14,62 +15,75 @@
# => 그냥 내가 best_case 찾고 그에 따라서 학생들한테 값을 배정해주면 gui에서 학생들 순회하면서 값 출력
# 학생들한테 배정할 값 - 베스트 개인 공부시간/ 팀플시간, 이에 따른 각 과목 학점 및 최종 학점, 학생 전체의 평균 학점
# [Student] = CPU
# best_grades = 미리 0으로 25개 초기화

# best_solo_grades = 미리 0으로 25개 초기화

# TODO. 팀플시간 1일때 왜 전부 4.5가 안 나오는지
# TODO. 일단 개인 과목 1과목씩 받아서 하기ㅠ
class YOSA(Scheduler):
# TODO 직접 객체 리스트를 넣어줄지, 숫자(입력값)를 넣어줄지 고민
def __init__(self, subject_input_list, student_count):
super().__init__(subject_input_list, student_count)
self.students = self.create_students(student_count)
self.subjects = subject_input_list
self.allocate_subject_to_student()

def find_best_cram_case(self):
cnt = 0
def find_best_cram_case(self, total_team_play_time):
for student in self.students:
for solo_study_time in range(25):
student.best_grades[solo_study_time] = self.get_best_grade(student, solo_study_time)
print("[student.best_grades]", cnt)
cnt += 1
for b_i, b in enumerate(student.best_grades):
print(b_i, b, end="\t")
# 1,7,2,4,14
# => 학생 4명일 때
# 학생 1 - 팀플에 1시간 투자
# 학생 2 - 팀플에 7시간 투자
# 학생 3 - 팀플에 2시간 투자
# 학생 4 - 팀플에 4시간 투자
# 팀플 시간 - 학생 1,2,3,4의 총 투자시간

# 0,0,0,0
# 0,0,0,1
# 0,0,0,2
# ...
# 0,0,0,24

# 0,0,1,0

# def create_subjects(self, subject_input_list):
# subject_list = []
# for idx, s in enumerate(subject_input_list):
# new_subject = Subject(s[0], s[1], s[2], idx)
# subject_list.append(new_subject)
# return subject_list
student.best_solo_grades = self.get_best_solo_grades(student)
# print(student.best_solo_grades)

best_average_team_grade = 0
best_cram_case = []
best_cram_case_grade_list = []
best_cram_case_list = []
# team_play_time_case = ex) [0,0,0,0] or [0,4,5,7] or [24,24,24,24]
# [1, 7, 2, 4] 팀플에 학생1은 1시간, 학생2는 7시간, 학생3는 2시간, 학생4는 4시간 투자
for team_play_time_case in product(*[range(25) for each_student_case in range(len(self.students))]):
if sum(team_play_time_case) <= total_team_play_time:
final_student_grade_list = []
final_average_team_grade = 0

for student_idx, each_team_play_time in enumerate(team_play_time_case):
final_student_grade_list.append(
self.get_final_student_grade(
self.students[student_idx],
24 - each_team_play_time,
sum(team_play_time_case),
total_team_play_time,
)
)
final_average_team_grade = sum(final_student_grade_list) / len(final_student_grade_list)
# 이거 원래 > 이렇게 되어야 함
if final_average_team_grade >= best_average_team_grade:
if final_average_team_grade > best_average_team_grade:
best_average_team_grade = final_average_team_grade
best_cram_case_grade_list = []
best_cram_case_list = []
best_cram_case_grade_list.append(final_student_grade_list[:])
best_cram_case_list.append(team_play_time_case[:])

print("best_average_team_grade", best_average_team_grade)
print("best_cram_case_grade_list", best_cram_case_grade_list)
print("best_cram_case_list", best_cram_case_list)

return best_cram_case

def get_final_student_grade(self, student, each_solo_study_time, team_play_time, total_team_play_time):
team_play_score = 100 * (team_play_time / total_team_play_time)
team_play_grade = self.convert_score_to_grade(team_play_score) * 3 # 운영체제는 3학점임
# print("team_play_grade", team_play_grade)
solo_study_grade = student.best_solo_grades[each_solo_study_time] * (student.total_credits - 3)

return (team_play_grade + solo_study_grade) / student.total_credits

def create_students(self, student_count):
student_list = []
for i in range(student_count):
student_list.append(Student(i))
return student_list
return [Student(idx) for idx in range(student_count)]

def run(self):
self.find_best_cram_case()
# for s in self.students[0].subject_list:
# print(s.process_id)
# # print(self.students[0].subject_list)
# for i in range(0, 20):
# print("[study_time -", i, "]")
# print("best_grade", self.get_best_grade(self.students[0], i))
for i in range(1, 73):
print("[{0}]==========================".format(i))
print(self.find_best_cram_case(i))
# print(self.find_best_cram_case(55))

def allocate_subject_to_student(self):
# 과목 리스트를 돌면서
Expand All @@ -80,38 +94,33 @@ def allocate_subject_to_student(self):
student.add_subject_list(subject)
break

# A 학생, 10시간들어오면
def get_best_grade(self, student, study_time): # study_time: 학생 1명에게 할당된 개인 공부 시간
# 모든 과목 공부시간(BT)을 다 합쳐도 study_time이 남을 때
if self.is_enough_time_to_study(student, study_time):
def get_best_solo_grades(self, student):
all_study_cases = self.get_all_study_cases(student.subject_list)
best_solo_grades = [0 for _ in range(25)]
for study_time in range(25):
best_solo_grades[study_time] = self.get_best_grade(student, study_time, all_study_cases)
# test
# for study_time, best_solo_grade in enumerate(best_solo_grades):
# print("best_solo_grades", study_time, best_solo_grade)
return best_solo_grades

def get_best_grade(self, student, study_time, all_study_cases): # study_time: 학생 1명에게 할당된 개인 공부 시간
# 모든 과목 공부시간(BT)을 다 합쳐도 시간이 남아서 현재 study_time에 대한 경우가 없을 때
if study_time not in all_study_cases:
return 4.5

best_grade = 0
all_study_cases = self.get_all_study_cases(student.subject_list, study_time)
for study_case in all_study_cases:
# print("study_case", study_case)
for study_case in all_study_cases[study_time]:
grade_sum = 0 # 받은 학점들의 합
all_grade = 0 # 1학점, 2학점의 grade
for subject_idx, subject_study_hour in enumerate(study_case):
score = subject_study_hour * student.subject_list[subject_idx].score_per_hour
grade = self.convert_score_to_grade(score) * student.subject_list[subject_idx].grade
grade = self.convert_score_to_grade(score) * student.subject_list[subject_idx].credit
grade_sum += grade
all_grade += student.subject_list[subject_idx].grade
average_grade = grade_sum / all_grade
average_grade = grade_sum / (student.total_credits - 3)
best_grade = max(best_grade, average_grade)

# grade 비교, 누가 더 작은지
return best_grade

def is_enough_time_to_study(self, student, study_time):
# 모든 과목 공부시간(BT)을 다 합쳐도 study_time이 남을 때
study_time_sum = 0
for subject in student.subject_list:
study_time_sum += subject.BT
if study_time_sum <= study_time:
return True
return False

# ======================================================
def convert_score_to_grade(self, score):
if score >= 95:
Expand All @@ -133,25 +142,12 @@ def convert_score_to_grade(self, score):
else:
return 0

def get_all_study_cases(self, subject_list, study_time):
max_bt_subject = max(subject_list, key=lambda x: x.BT)
# print("max_bt_subject", max_bt_subject.BT)
num_list = [x for x in range(0, max_bt_subject.BT + 1)]
result = []
for arr in combinations_with_replacement(num_list, len(subject_list)): # (0, 0, 0, 24)
if sum(arr) == study_time:
for each_case in permutations(arr, len(subject_list)): # (24, 0, 0, 0), (0, 24, 0, 0), (0, 0, 24, 0)...
if each_case not in result:
can_append = True
for subject_idx, subject in enumerate(subject_list):
if each_case[subject_idx] > subject.BT:
can_append = False
break
if can_append:
result.append(each_case)
return result


# 결과
# for each_case in result:
# print(each_case)
def get_all_study_cases(self, subject_list):
all_study_cases = defaultdict(list)

for study_subject_time_case in product(*[range(subject.BT + 1) for subject in subject_list]):
study_time = sum(study_subject_time_case)
if study_time <= 24:
all_study_cases[study_time].append(study_subject_time_case)
# print("all_study_cases", all_study_cases)
return all_study_cases

0 comments on commit f3648db

Please sign in to comment.