You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
947 lines
38 KiB
947 lines
38 KiB
# -*- coding: utf-8 -*-
|
|
from django.db import models
|
|
from redactor.fields import RedactorField
|
|
|
|
from access.models import User
|
|
from courses.templates import search_in_collection, LEVELS_COLLECTION, MATERIAL_TYPE_COLLECTION, material_fabric, \
|
|
comment_fabric
|
|
from library.models import Tags
|
|
from lms.settings import DOMAIN
|
|
from lms.tools import random_string, translit
|
|
from management.models import Comment
|
|
from storage.models import Storage
|
|
|
|
MATERIALS_TYPE = (
|
|
('B', u'Базовый материал'),
|
|
('E', u'Расширеный материал'),
|
|
('P', u'Премиум материал')
|
|
)
|
|
|
|
THEME_TYPE = (
|
|
MATERIALS_TYPE[0],
|
|
MATERIALS_TYPE[1],
|
|
MATERIALS_TYPE[2],
|
|
('M', u'Предэкзаменационные материалы'),
|
|
('Ex', u'Экзаменационная тема')
|
|
)
|
|
|
|
|
|
class MaterialDirection(models.Model):
|
|
title = models.CharField(verbose_name=u'Заголовок', max_length=255)
|
|
color = models.CharField(verbose_name=u'Цвет', max_length=50)
|
|
description = RedactorField(verbose_name=u'Описание', blank=True)
|
|
mentors = models.ManyToManyField(User, verbose_name=u'Кураторы', null=True)
|
|
|
|
def __unicode__(self):
|
|
return u'%s' % self.title
|
|
|
|
def __str__(self):
|
|
return self.title
|
|
|
|
def get_face(self):
|
|
return {
|
|
'title': self.title,
|
|
'color': self.color,
|
|
'description': self.description,
|
|
'mentors': [i.get_face() for i in self.mentors.all()]
|
|
}
|
|
|
|
def get_mentors(self):
|
|
return self.mentors.all()
|
|
|
|
def html(self):
|
|
return '<span style="color: {0};font-weight: bold;">{1}</span>'.format(self.color, self.title)
|
|
|
|
def count(self):
|
|
return Course.objects.filter(direction=self).count()
|
|
|
|
class Meta:
|
|
verbose_name = u'Направление'
|
|
verbose_name_plural = u'Направления'
|
|
|
|
|
|
class Course(models.Model):
|
|
COURSE_LEVEL = (
|
|
('B', u'Базовый'),
|
|
('A', u'Продвинутый '),
|
|
('E', u'Экспертный'),
|
|
('B+A', u'Базовый + Продвинутый')
|
|
)
|
|
hidden = models.BooleanField(verbose_name=u'Видно только оплатившим', default=False)
|
|
level = models.CharField(verbose_name=u'Уровень', choices=COURSE_LEVEL, default='B', max_length=3)
|
|
slug = models.SlugField(max_length=255, editable=False, blank=True, default='', unique=True)
|
|
icon = models.ImageField(verbose_name=u'Иконка курса', blank=True, null=True, upload_to='course')
|
|
direction = models.ForeignKey(MaterialDirection, verbose_name=u'Направление', null=True)
|
|
mentors = models.ManyToManyField(User, verbose_name=u'Кураторы', null=True, blank=True, related_name='course_mentors')
|
|
public = models.BooleanField(verbose_name=u'Опубликовать', default=False)
|
|
title = models.CharField(verbose_name=u"Заголовок", max_length=255)
|
|
description = RedactorField(verbose_name=u'Описание', blank=True)
|
|
description_file = models.FileField(verbose_name='Файл писания курса', black=True, null=True, upload_to='course',
|
|
help_text=u'Файл, который будет отправляться в письме со счетом')
|
|
image = models.ImageField(verbose_name=u'Изображение', upload_to='course', blank=True)
|
|
big_image = models.ImageField(verbose_name=u'Большое изображение', upload_to='course', blank=True)
|
|
big_mobile_image = models.ImageField(verbose_name=u'Под мобилку', upload_to='course', blank=True, null=True,
|
|
help_text=u'Большая картинка для мобильной версии')
|
|
page = models.URLField(verbose_name=u'Страничка описания', blank=True, default='')
|
|
preview = models.CharField(verbose_name=u'Трэйл', blank=True, default='', max_length=255)
|
|
teachers = models.ManyToManyField(User, verbose_name=u'Преподаватели', related_name='course_teachers')
|
|
sort = models.IntegerField(verbose_name=u'Порядок сортировки', default=0)
|
|
use_fail = models.BooleanField(verbose_name=u'Использовать фейковую информацию', default=False)
|
|
basic_len = models.IntegerField(verbose_name=u'Основных модулей', default=0)
|
|
addition_len = models.IntegerField(verbose_name=u'Дополнительных модулей', default=0)
|
|
min_price = models.IntegerField(verbose_name=u'Цена от', default=0)
|
|
buy_icon = models.ImageField(verbose_name=u'Картинка покупки', upload_to='course', blank=True, null=True)
|
|
must_build = models.BooleanField(verbose_name=u'На переформировку', default=False)
|
|
keywords = models.ManyToManyField(Tags, verbose_name=u'Ключевые слова', blank=True)
|
|
recommend = models.ManyToManyField('self', verbose_name=u'Связанные курсы', blank=True,
|
|
help_text=u'Курсы, которые стоит порекомендовать вместе с этим')
|
|
|
|
|
|
def __str__(self):
|
|
return self.title
|
|
|
|
def __unicode__(self):
|
|
return u"%s" % self.title
|
|
|
|
def get_direction(self):
|
|
return self.direction if self.direction else ''
|
|
|
|
def get_mentors(self):
|
|
# Получение списка ответственных кураторов
|
|
result = set()
|
|
for mentor in self.direction.get_mentors():
|
|
result.add(mentor)
|
|
|
|
for mentor in self.mentors.all():
|
|
result.add(mentor)
|
|
|
|
return result
|
|
|
|
def get_html_direction(self):
|
|
return self.direction.html() if self.direction else ''
|
|
|
|
def get_themes(self, t=None):
|
|
# Получение списка тем в порядке кортежа THEME_TYPE
|
|
__types = list(i[0] for i in THEME_TYPE)
|
|
if t in __types:
|
|
return CourseTheme.objects.filter(course=self, _type=t).order_by('sort')
|
|
else:
|
|
result = []
|
|
for _type in __types:
|
|
for i in self.get_themes(t=_type):
|
|
result.append(i)
|
|
return result
|
|
|
|
def get_image(self):
|
|
if self.image:
|
|
return self.image.url
|
|
else:
|
|
return '/static/img/course1.jpg'
|
|
|
|
def get_big_image(self):
|
|
if self.big_image:
|
|
return self.big_image.url
|
|
else:
|
|
return '/static/img/course1.jpg'
|
|
|
|
def get_mobile_big_image(self):
|
|
if self.big_mobile_image:
|
|
return self.big_mobile_image.url
|
|
else:
|
|
return self.get_big_image()
|
|
|
|
def get_level(self):
|
|
# Получить уровень сложности
|
|
return search_in_collection(LEVELS_COLLECTION, 'flag', self.level)
|
|
|
|
def get_title(self):
|
|
# Получить заголовок курса
|
|
return self.title
|
|
|
|
def get_description(self):
|
|
# Получить описание курса
|
|
return self.description
|
|
|
|
def get_description_file(self):
|
|
return self.description_file.url or None
|
|
|
|
def get_skills(self):
|
|
# Получить скилы темы
|
|
result = []
|
|
# Обойти все размеры навыков в
|
|
for i in SkillJ.objects.filter(lesson__course=self):
|
|
if i.skill not in result:
|
|
result.append(i.skill)
|
|
return result
|
|
|
|
def get_type(self):
|
|
# Получить тип материала, как по подписке
|
|
return ''
|
|
|
|
def get_icon(self):
|
|
# Получить иконку материала, для отображения рядом с курсом
|
|
return ''
|
|
|
|
def get_materials(self):
|
|
# Получить прикрепленные файлы, для отображения на странице курса
|
|
return []
|
|
|
|
def get_comments(self):
|
|
# Получить все комментарии
|
|
return []
|
|
|
|
def lessons_length(self):
|
|
return Lesson.objects.filter(course=self).count()
|
|
|
|
def build_map(self, material=None):
|
|
# Переформирование карты
|
|
return CourseBuilder(self, material=material).main()
|
|
|
|
def to_build(self):
|
|
# Отправить на переформирование картыx
|
|
#self.must_build = True
|
|
#self.save()
|
|
self.build_map()
|
|
|
|
def get_absolute_url(self):
|
|
return '/courses/%s' % self.slug
|
|
|
|
def save(self, *args, **kwargs):
|
|
if not self.slug: self.slug = '{0}'.format(translit(self.title))
|
|
super(Course, self).save(*args, **kwargs)
|
|
|
|
class Meta:
|
|
verbose_name = u"Курс"
|
|
verbose_name_plural = u"Курсы"
|
|
ordering = ['sort']
|
|
|
|
|
|
class CourseTheme(models.Model):
|
|
on_comment = models.BooleanField(verbose_name=u'Блок комментариев', default=True)
|
|
teachers = models.ManyToManyField(User, verbose_name=u'Преподаватели', blank=True)
|
|
price_type = models.CharField(verbose_name=u'Тип подписки', choices=MATERIALS_TYPE, default='B', max_length=1)
|
|
_type = models.CharField(verbose_name=u'Тип темы', choices=THEME_TYPE, default='B', max_length=2)
|
|
icon = models.ImageField(verbose_name=u'Иконка темы', upload_to='CourseTheme', null=True, blank=True)
|
|
course = models.ForeignKey(Course, verbose_name=u'Курс', null=True)
|
|
sort = models.IntegerField(verbose_name=u'Текущая сортировка', default=1)
|
|
title = models.CharField(verbose_name=u'Заголовок', max_length=255, blank=True, default='')
|
|
description = models.TextField(verbose_name=u'Короткое описание темы', max_length=255, default='', blank=True)
|
|
empty = models.BooleanField(verbose_name=u'Ты не пройдешь!',
|
|
help_text=u'Заблокировать дальнейшее прохождение курса. Из-за того, '
|
|
u'что курс не заполнен или что-то вроде того.', default=False)
|
|
|
|
def __unicode__(self):
|
|
return u'%s:%s/%s' % (self.sort, self.course, self.title if self.title else self.get__type_display())
|
|
|
|
def __str__(self):
|
|
return u'%s:%s/%s' % (self.sort, self.course, self.title if self.title else self.get__type_display())
|
|
|
|
def get_lessons(self):
|
|
return Lesson.objects.filter(theme=self)
|
|
|
|
def get_level(self):
|
|
# Получить уровень сложности из коллекции, погрузив объект данных в фабрику
|
|
return search_in_collection(LEVELS_COLLECTION, 'flag', self.course.level)
|
|
|
|
def get_title(self):
|
|
# Получить заголовок темы
|
|
if not self.title and Lesson.objects.filter(course=self.course, theme=self).count() != 1:
|
|
return self.get__type_display()
|
|
|
|
result = u''
|
|
if self._type in ['E', 'P', 'M']:
|
|
result = u'{0}: '.format(self.get__type_display())
|
|
|
|
if self.title:
|
|
result += self.title
|
|
return result
|
|
else:
|
|
if Lesson.objects.filter(course=self.course, theme=self).count() == 1:
|
|
result += Lesson.objects.filter(theme=self).first().get_title()
|
|
return result
|
|
|
|
def get_description(self):
|
|
# Получить описание темы
|
|
result = u''
|
|
if self.description:
|
|
result += u'<p style="padding:10px;">%s</p>' % self.description
|
|
|
|
if self.lessons_length() > 1:
|
|
result += u'<ul style="padding: 0 0 0 15px;">'
|
|
for i in Lesson.objects.filter(course=self.course, theme=self).order_by('sort'):
|
|
result += i.get_description()
|
|
result += u'</ul>'
|
|
return result
|
|
|
|
if not self.description and self.lessons_length() == 1:
|
|
return Lesson.objects.get(theme=self).description
|
|
|
|
if self._type == 'Ex':
|
|
return Exam.objects.get(theme=self).get_description()
|
|
|
|
def get_skills(self):
|
|
# Получить скилы темы
|
|
result = []
|
|
# Обойти все размеры навыков в
|
|
for i in SkillJ.objects.filter(lesson__theme=self):
|
|
if i.skill not in result:
|
|
result.append(i.skill)
|
|
return result
|
|
|
|
def get_type(self):
|
|
# Получить тип материала/ Здесь идет обход по всем
|
|
__template = search_in_collection(MATERIAL_TYPE_COLLECTION, 'flag', self._type)
|
|
__template['icon'] = self.icon if self.icon else __template['icon']
|
|
return __template
|
|
|
|
def get_icon(self):
|
|
# Получить иконку материала
|
|
if self.icon:
|
|
return self.icon.url
|
|
else:
|
|
return search_in_collection(MATERIAL_TYPE_COLLECTION, 'flag', self._type, artifact='icon')
|
|
|
|
def get_materials(self):
|
|
# Получить прикрепленные файлы
|
|
return []
|
|
|
|
def get_comments(self):
|
|
# Получить все комментарии
|
|
return []
|
|
|
|
def lessons_length(self):
|
|
return Lesson.objects.filter(theme=self).count()
|
|
|
|
def homework_length(self):
|
|
return Homework.objects.filter(theme=self).count()
|
|
|
|
def save(self, *args, **kwargs):
|
|
if CourseTheme.objects.filter(course=self.course, sort=self.sort).exclude(id=self.id).exists():
|
|
# Переформировать порядок
|
|
test_in = self.sort + 1
|
|
for theme in CourseTheme.objects.filter(course=self.course, sort__gte=self.sort).exclude(id=self.id):
|
|
if theme.sort != test_in:
|
|
theme.sort = test_in
|
|
theme.save()
|
|
test_in += 1
|
|
if self.course:
|
|
self.course.to_build()
|
|
|
|
super(CourseTheme, self).save(*args, **kwargs)
|
|
|
|
class Meta:
|
|
verbose_name = u'Тема'
|
|
verbose_name_plural = u'Темы'
|
|
ordering = ['sort']
|
|
|
|
@property
|
|
def type(self):
|
|
return self._type
|
|
|
|
|
|
class Lesson(models.Model):
|
|
COMMENT_SWITCH = (
|
|
('N', 'Включены'),
|
|
('F', 'Отключены'),
|
|
('T', 'Подчиняется теме')
|
|
)
|
|
free = models.BooleanField(verbose_name=u'Бесплатное видео', default=False)
|
|
on_comment = models.CharField(verbose_name=u'Блок комментариев', default='T', choices=COMMENT_SWITCH, help_text=u'{0}/management/faq/37'.format(DOMAIN), max_length=1)
|
|
token = models.CharField(verbose_name=u'Токен доступа', default='', blank=True, max_length=100, editable=False)
|
|
title = models.TextField(verbose_name=u'Заголовок', blank=True)
|
|
sort = models.IntegerField(verbose_name=u'Текущая сортировка', default=1)
|
|
course = models.ForeignKey(Course, verbose_name=u'Курс', null=True)
|
|
theme = models.ForeignKey(CourseTheme, verbose_name=u'Тема курса', null=True)
|
|
description = RedactorField(verbose_name=u'Описание', default='', blank=True)
|
|
video = models.TextField(verbose_name=u'Код видео', default='', blank=True)
|
|
video_id = models.CharField(verbose_name=u'Видео ID', blank=True, null=True, max_length=50)
|
|
video_date = models.DateTimeField(verbose_name=u'Время генерации кода видео', blank=True, null=True)
|
|
materials = models.ManyToManyField(Storage, verbose_name=u'Материалы урока', blank=True)
|
|
comments = models.ManyToManyField(Comment, verbose_name=u'Комментарии', blank=True, editable=False)
|
|
|
|
def __str__(self):
|
|
return '%s/%s' % (self.theme, self.title)
|
|
|
|
def __unicode__(self):
|
|
return u'%s/%s' % (self.theme, self.title)
|
|
|
|
def get_title(self):
|
|
return self.title
|
|
|
|
def get_description(self):
|
|
# Просто получить описание этой темы
|
|
return self.description
|
|
|
|
def get_level(self):
|
|
# Получить уровень сложности
|
|
return search_in_collection(LEVELS_COLLECTION, 'flag', self.course.level)
|
|
|
|
def get_skills(self):
|
|
# Получить скилы темы
|
|
result = []
|
|
# Обойти все размеры навыков в
|
|
for i in SkillJ.objects.filter(lesson=self):
|
|
if i.skill not in result:
|
|
result.append(i.skill)
|
|
return result
|
|
|
|
def get_type(self):
|
|
# Получить тип материала
|
|
return self.theme.get_type()
|
|
|
|
def get_icon(self):
|
|
# Получить иконку материала
|
|
return self.theme.get_icon()
|
|
|
|
def get_materials(self):
|
|
# Получить прикрепленные файлы
|
|
return material_fabric(self.materials.all())
|
|
|
|
def get_comments(self, _user=None):
|
|
# Получить все комментарии урока
|
|
return [comment_fabric(comment, __type='L', __user=_user) for comment in self.comments.filter(parent_id=0)]
|
|
|
|
def get_all_comments(self, _user=None):
|
|
return [comment_fabric(comment, __type='L', __user=_user) for comment in self.comments.all().order_by('-date')]
|
|
|
|
def save(self, *args, **kwargs):
|
|
if not self.video and self.video_id and self.video_id != '0':
|
|
video = gen_vzaar_bb(self.video_id)
|
|
if video:
|
|
self.video = video
|
|
if Lesson.objects.filter(theme=self.theme, sort=self.sort).exclude(id=self.id).exists():
|
|
# Переформировать порядок
|
|
test_in = self.sort + 1
|
|
for lesson in Lesson.objects.filter(theme=self.theme, sort__gte=self.sort).exclude(id=self.id):
|
|
if lesson.sort != test_in:
|
|
lesson.sort = test_in
|
|
lesson.save()
|
|
test_in += 1
|
|
self.token = self.course.build_map(material=self)
|
|
super(Lesson, self).save(*args, **kwargs)
|
|
|
|
class Meta:
|
|
verbose_name = u'Урок'
|
|
verbose_name_plural = u'Уроки'
|
|
ordering = ['sort']
|
|
|
|
|
|
class Homework(models.Model):
|
|
token = models.CharField(verbose_name=u'Токен доступа', default='', blank=True, max_length=100)
|
|
course = models.ForeignKey(Course, verbose_name=u'Курс', null=True)
|
|
theme = models.ForeignKey(CourseTheme, verbose_name=u'Тема курса', null=True)
|
|
description = RedactorField(verbose_name=u'Описание')
|
|
materials = models.ManyToManyField(Storage, verbose_name=u'Материалы для домашней работы', blank=True)
|
|
sort = models.IntegerField(verbose_name=u'Текущая сортировка', default=1)
|
|
|
|
def __unicode__(self):
|
|
return u'%s ID: %s Тема: %s Порядок темы: %s' % (self.course.get_title(), self.id, self.theme.title, self.theme.sort)
|
|
|
|
def __str__(self):
|
|
return '%s ID: %s Тема: %s Порядок темы: %s' % (self.course.get_title(), self.id, self.theme.title, self.theme.sort)
|
|
|
|
def get_skills(self):
|
|
# Получить скилы темы
|
|
return []
|
|
|
|
def get_level(self):
|
|
# Получить уровень сложности
|
|
return search_in_collection(LEVELS_COLLECTION, 'flag', self.course.level)
|
|
|
|
def get_type(self):
|
|
# Получить тип материала
|
|
return self.theme.get_type()
|
|
|
|
def get_icon(self):
|
|
# Получить иконку материала
|
|
return self.theme.get_icon()
|
|
|
|
def get_description(self):
|
|
# Просто получить описание этой темы
|
|
return self.description
|
|
|
|
def get_materials(self):
|
|
# Получить прикрепленные файлы
|
|
return material_fabric(self.materials.all())
|
|
|
|
def get_comments(self):
|
|
# Получить все комментарии
|
|
return []
|
|
|
|
def get_title(self):
|
|
result = self.theme.get_title()
|
|
if Homework.objects.filter(theme=self.theme).count() > 1:
|
|
result += ' {0}'.format(self.sort)
|
|
|
|
return result
|
|
|
|
def save(self, *args, **kwargs):
|
|
if Homework.objects.filter(theme=self.theme, sort=self.sort).exclude(id=self.id).exists():
|
|
# Переформировать порядок
|
|
test_in = self.sort + 1
|
|
for homework in Homework.objects.filter(theme=self.theme, sort__gte=self.sort).exclude(id=self.id):
|
|
if homework.sort != test_in:
|
|
homework.sort = test_in
|
|
homework.save()
|
|
test_in += 1
|
|
self.token = self.course.build_map(material=self)
|
|
super(Homework, self).save(*args, **kwargs)
|
|
|
|
class Meta:
|
|
verbose_name = u'Добашнее задание'
|
|
verbose_name_plural = u'Домашние задания'
|
|
ordering = ['sort']
|
|
|
|
|
|
class Exam(models.Model):
|
|
token = models.CharField(verbose_name=u'Токен доступа', default='', blank=True, max_length=100)
|
|
sort = models.IntegerField(verbose_name=u'Порядок экзамена', default=1)
|
|
course = models.ForeignKey(Course, verbose_name=u'Курс', null=True)
|
|
theme = models.ForeignKey(CourseTheme, verbose_name=u'Тема курса', null=True)
|
|
description = RedactorField(verbose_name=u'Описание для студентов')
|
|
materials = models.ManyToManyField(Storage, verbose_name=u'Материалы экзамена', related_name='exam_materials', blank=True)
|
|
|
|
def __str__(self):
|
|
return '%s' % self.course
|
|
|
|
def __unicode__(self):
|
|
return u'%s' % self.course
|
|
|
|
def get_level(self):
|
|
# Получить уровень сложности
|
|
return search_in_collection(LEVELS_COLLECTION, 'flag', self.course.level)
|
|
|
|
def get_skills(self):
|
|
# Получить скилы темы
|
|
result = []
|
|
# Обойти все размеры навыков в
|
|
for i in SkillJ.objects.filter(lesson__theme=self):
|
|
if i.skill not in result:
|
|
result.append(i.skill)
|
|
return result
|
|
|
|
def get_type(self):
|
|
# Получить тип материала
|
|
return self.theme.get_type()
|
|
|
|
def get_icon(self):
|
|
# Получить иконку материала
|
|
return self.theme.get_icon()
|
|
|
|
def get_materials(self):
|
|
# Получить прикрепленные файлы
|
|
return material_fabric(self.materials.all())
|
|
|
|
def get_description(self):
|
|
return self.description
|
|
|
|
def get_comments(self):
|
|
# Получить все комментарии
|
|
return []
|
|
|
|
def get_title(self):
|
|
return self.theme.get_title()
|
|
|
|
def save(self, *args, **kwargs):
|
|
if Exam.objects.filter(theme=self.theme, sort=self.sort).exclude(id=self.id).exists():
|
|
# Переформировать порядок
|
|
test_in = self.sort + 1
|
|
for exam in Exam.objects.filter(theme=self.theme, sort__gte=self.sort).exclude(id=self.id):
|
|
if exam.sort != test_in:
|
|
exam.sort = test_in
|
|
exam.save()
|
|
test_in += 1
|
|
self.token = self.course.build_map(material=self)
|
|
super(Exam, self).save(*args, **kwargs)
|
|
|
|
class Meta:
|
|
verbose_name = u'Экзамен'
|
|
verbose_name_plural = u'Экзамены'
|
|
ordering = ['sort']
|
|
|
|
|
|
class Skills(models.Model):
|
|
title = models.CharField(verbose_name=u'Наименование', max_length=255)
|
|
color = models.CharField(verbose_name=u'Цвет', max_length=255)
|
|
mini_icon = models.ImageField(verbose_name=u'Маленькая картинка', upload_to='skills', null=True, help_text='15x15')
|
|
big_icon = models.ImageField(verbose_name=u'Большая картинка', upload_to='skills', null=True, help_text='65x65')
|
|
description = models.TextField(verbose_name=u'Описание', blank=True)
|
|
|
|
def __str__(self): return '%s' % self.title
|
|
|
|
def __unicode__(self): return u'%s' % self.title
|
|
|
|
class Meta:
|
|
verbose_name = u'Навык'
|
|
verbose_name_plural = u'Навыки'
|
|
|
|
|
|
class SkillJ(models.Model):
|
|
# Журнал навыков
|
|
skill = models.ForeignKey(Skills, verbose_name=u'Навык')
|
|
lesson = models.ForeignKey(Lesson, verbose_name=u'Урок')
|
|
size = models.IntegerField(verbose_name=u'Размер', default=0)
|
|
|
|
def __str__(self): return '%s %s' % (self.skill, self.size)
|
|
|
|
def __unicode__(self): return u'%s %s' % (self.skill, self.size)
|
|
|
|
class Meta:
|
|
verbose_name = u'Размер навыка'
|
|
verbose_name_plural = u'Размеры навыков'
|
|
ordering = ['id']
|
|
|
|
|
|
class Achievements(models.Model):
|
|
tech_name = models.CharField(verbose_name=u'Техническое название', max_length=20, editable=False,
|
|
help_text=u'Для системы, нигде не отображается', blank=True, default='', unique=True)
|
|
icon = models.ImageField(verbose_name=u'Иконка', upload_to='achives')
|
|
title = models.CharField(verbose_name=u'Имя', max_length=50,
|
|
help_text=u'Для нашего удобства, студентам не показывается')
|
|
image = models.ImageField(verbose_name=u'Изображение', upload_to='achives')
|
|
background = models.CharField(verbose_name=u'Цвет фона', max_length=10)
|
|
border = models.CharField(verbose_name=u'Цвет границы', max_length=10)
|
|
|
|
def __str__(self):
|
|
return u'%s' % self.title
|
|
|
|
def __unicode__(self):
|
|
return u'%s' % self.title
|
|
|
|
def save(self, *args, **kwargs):
|
|
if not self.tech_name:
|
|
self.tech_name = random_string().upper()
|
|
super(Achievements, self).save(*args, **kwargs)
|
|
|
|
class Meta:
|
|
verbose_name = u'Достижение'
|
|
verbose_name_plural = u'Достижения'
|
|
|
|
|
|
class CourseMap(models.Model):
|
|
_types = (
|
|
('L', u'Урок'),
|
|
('H', u'Домашнее задание'),
|
|
('E', u'Экзамен')
|
|
)
|
|
_type = models.CharField(verbose_name=u'Типы материалов', max_length=1, default='L', choices=_types)
|
|
course = models.ForeignKey(Course, verbose_name=u'Курс', blank=True, null=True)
|
|
lesson = models.ForeignKey(Lesson, verbose_name=u'Урок', null=True, blank=True)
|
|
homework = models.ForeignKey(Homework, verbose_name=u'Задание', null=True, blank=True)
|
|
exam = models.ForeignKey(Exam, verbose_name=u'Экзамен', null=True, blank=True)
|
|
sort = models.IntegerField(verbose_name=u'Глобальный порядок', default=0)
|
|
token = models.CharField(verbose_name=u'Быстрый ключ', null=True, editable=False, unique=True, max_length=20)
|
|
|
|
def __unicode__(self):
|
|
_tmp = None
|
|
if self._type == 'L':
|
|
_tmp = self.lesson
|
|
elif self._type == 'H':
|
|
_tmp = self.homework
|
|
elif self._type == 'E':
|
|
_tmp = self.exam
|
|
return u'%s %s %s' % (self.token, self.sort, _tmp.get_title())
|
|
|
|
def __str__(self):
|
|
_tmp = None
|
|
if self._type == 'L':
|
|
_tmp = self.lesson
|
|
elif self._type == 'H':
|
|
_tmp = self.homework
|
|
elif self._type == 'E':
|
|
_tmp = self.exam
|
|
return '%s %s %s' % (self.token, self.sort, _tmp.get_title())
|
|
|
|
def get_type(self):
|
|
_type = None
|
|
if self.lesson:
|
|
_type = 'L'
|
|
elif self.homework:
|
|
_type = 'H'
|
|
elif self.exam:
|
|
_type = 'E'
|
|
|
|
return _type
|
|
|
|
def get_next(self):
|
|
try:
|
|
_next = CourseMap.objects.get(course=self.course, sort=self.sort + 1)
|
|
except CourseMap.DoesNotExist:
|
|
_next = CourseMap.objects.get(course=self.course, sort=0)
|
|
|
|
return _next._type, _next.get_obj()
|
|
|
|
def get_before(self):
|
|
try:
|
|
_next = CourseMap.objects.get(course=self.course, sort=self.sort - 1)
|
|
except CourseMap.DoesNotExist:
|
|
_next = CourseMap.objects.get(course=self.course, sort=0)
|
|
|
|
return _next._type, _next.get_obj()
|
|
|
|
def get_obj(self):
|
|
if self._type == 'L':
|
|
return self.lesson
|
|
elif self._type == 'H':
|
|
return self.homework
|
|
elif self._type == 'E':
|
|
return self.exam
|
|
else:
|
|
return None
|
|
|
|
def get_token(self):
|
|
return '{0}#{1}'.format(self.course.id, self.sort)
|
|
|
|
def check_material(self):
|
|
result = 0
|
|
if self.lesson: result += 1
|
|
if self.homework: result += 1
|
|
if self.exam: result += 1
|
|
return result == 1
|
|
|
|
def save(self, *args, **kwargs):
|
|
if not self.course:
|
|
self.course = self.get_obj().course
|
|
_token = self.get_token()
|
|
if _token != self.token:
|
|
self.token = _token
|
|
_type = self.get_type()
|
|
if _type != self._type:
|
|
self._type = _type
|
|
|
|
super(CourseMap, self).save(*args, **kwargs)
|
|
|
|
class Meta:
|
|
verbose_name = u'Карта курса'
|
|
verbose_name_plural = u'Карты курсов'
|
|
ordering = ['sort']
|
|
|
|
|
|
class AchievementsMap(models.Model):
|
|
after = models.BooleanField(verbose_name=u'После прохождения', default=True)
|
|
point = models.ForeignKey(CourseMap, verbose_name=u'Позиция')
|
|
achiv = models.ForeignKey(Achievements, verbose_name=u'Достижение')
|
|
|
|
def __str__(self):
|
|
return u'%s %s %s' % (self.point, self.achiv, self.after)
|
|
|
|
def __unicode__(self):
|
|
return u'%s %s %s' % (self.point, self.achiv, self.after)
|
|
|
|
class Meta:
|
|
verbose_name = u'Внутреняя ачивка'
|
|
verbose_name_plural = u'Внетренние ачивки'
|
|
|
|
|
|
class Diploma(models.Model):
|
|
key = models.IntegerField(verbose_name=u'Последний ключ', max_length=255)
|
|
icon = models.ImageField(verbose_name=u'Мини картинка', upload_to='diploms', null=True)
|
|
course = models.ForeignKey(Course, verbose_name=u'Курс')
|
|
out_image = models.ImageField(verbose_name=u'Диплом без печати', upload_to='diploms')
|
|
in_image = models.ImageField(verbose_name=u'Диплом c печатью', upload_to='diploms')
|
|
#
|
|
date_place = models.CharField(verbose_name=u'Размещение даты', max_length=255,
|
|
help_text=u'Пикселей сверху:пикселей слева - 256:256', null=True)
|
|
date_color = models.CharField(verbose_name=u'Цвет даты', max_length=255, null=True,
|
|
help_text=u'RGB. Пример: 0,0,0')
|
|
date_font = models.FileField(verbose_name=u'Шрифт даты', upload_to='diploms', null=True)
|
|
date_size = models.IntegerField(verbose_name=u'Размер даты', max_length=255, null=True)
|
|
#
|
|
key_place = models.CharField(verbose_name=u'Размещение ключа', max_length=255, null=True,
|
|
help_text=u'Пикселей сверху:пикселей слева - 256:256')
|
|
key_color = models.CharField(verbose_name=u'Цвет ключа', max_length=255, null=True,
|
|
help_text=u'RGB. Пример: 0,0,0')
|
|
key_font = models.FileField(verbose_name=u'Шрифт ключа', upload_to='diploms', null=True)
|
|
key_size = models.IntegerField(verbose_name=u'Размер ключа', max_length=255, null=True)
|
|
#
|
|
name_place = models.CharField(verbose_name=u'Размещение имени', max_length=255, null=True,
|
|
help_text=u'Пикселей сверху:пикселей слева - 256:256')
|
|
name_color = models.CharField(verbose_name=u'Цвет имени', max_length=255, null=True,
|
|
help_text=u'RGB. Пример: 0,0,0')
|
|
name_font = models.FileField(verbose_name=u'Шрифт имени', upload_to='diploms', null=True)
|
|
name_size = models.IntegerField(verbose_name=u'Размер имени', max_length=255, null=True)
|
|
|
|
def __str__(self):
|
|
return '%s' % self.course
|
|
|
|
def __unicode__(self):
|
|
return u'%s' % self.course
|
|
|
|
def get_key(self):
|
|
k = self.key
|
|
self.key = k + 1
|
|
self.save()
|
|
return k
|
|
|
|
def get_color(self, _type):
|
|
if _type == 'key':
|
|
p = self.key_color
|
|
elif _type == 'name':
|
|
p = self.name_color
|
|
elif _type == 'date':
|
|
p = self.date_color
|
|
p = p.split(',')
|
|
return int(p[0]), int(p[1]), int(p[2])
|
|
|
|
def get_place(self, _type):
|
|
if _type == 'key':
|
|
p = self.key_place
|
|
elif _type == 'name':
|
|
p = self.name_place
|
|
elif _type == 'date':
|
|
p = self.date_place
|
|
p = p.split(':')
|
|
return int(p[1]), int(p[0])
|
|
|
|
class Meta:
|
|
verbose_name = u'Диплом'
|
|
verbose_name_plural = u'Дипломы'
|
|
|
|
|
|
def gen_vzaar_bb(id):
|
|
try:
|
|
int(id)
|
|
except ValueError:
|
|
return None
|
|
|
|
if id:
|
|
return '<iframe id="vzvd-{0}" name="vzvd-{0}" title="vzaar video player" class="vzaar-video-player" ' \
|
|
'type="text/html" width="768" height="432" frameborder="0" allowFullScreen allowTransparency="true" ' \
|
|
'mozallowfullscreen webkitAllowFullScreen src="//view.vzaar.com/{0}/player"></iframe>'.format(id)
|
|
else:
|
|
return None
|
|
|
|
|
|
class CourseBuilder:
|
|
def __init__(self, course, material=None):
|
|
self.course = course
|
|
self.course_public = self.course.public
|
|
self.material = material # Вернуть токен вызвавшего материала
|
|
self.ready = []
|
|
self.materials = []
|
|
self.token = ''
|
|
|
|
def append_in_price(self, map):
|
|
# Добавить карту в счета, куда включены все карты курса в типе, исключая текущий
|
|
#Price.objects.filter(included=map.get_befor)
|
|
pass
|
|
|
|
def rebuild_map(self):
|
|
sort = 0
|
|
for theme in CourseTheme.objects.filter(course=self.course):
|
|
for lesson in Lesson.objects.filter(theme=theme):
|
|
must_save = False
|
|
try:
|
|
token = '{0}#{1}'.format(self.course.id, sort)
|
|
tmp = CourseMap.objects.get(token=token)
|
|
except CourseMap.DoesNotExist:
|
|
tmp = CourseMap.objects.create(lesson=lesson, sort=sort, course=self.course)
|
|
self.append_in_price(tmp)
|
|
|
|
if tmp.homework:
|
|
tmp.homework = None
|
|
must_save = True
|
|
|
|
if tmp.exam:
|
|
tmp.exam = None
|
|
must_save = True
|
|
|
|
if tmp.lesson != lesson:
|
|
tmp.lesson = lesson
|
|
must_save = True
|
|
|
|
if lesson.token != token:
|
|
lesson.token = token
|
|
lesson.save()
|
|
|
|
if must_save: tmp.save()
|
|
|
|
if lesson == self.material:
|
|
self.token = tmp.token
|
|
self.materials.append(tmp.id)
|
|
sort += 1
|
|
|
|
for homework in Homework.objects.filter(theme=theme):
|
|
must_save = False
|
|
try:
|
|
token = '{0}#{1}'.format(self.course.id, sort)
|
|
tmp = CourseMap.objects.get(token=token)
|
|
except CourseMap.DoesNotExist:
|
|
tmp = CourseMap.objects.create(homework=homework, sort=sort, course=self.course)
|
|
self.append_in_price(tmp)
|
|
|
|
if tmp.homework != homework:
|
|
tmp.homework = homework
|
|
must_save = True
|
|
|
|
if tmp.exam:
|
|
tmp.exam = None
|
|
must_save = True
|
|
|
|
if tmp.lesson:
|
|
tmp.lesson = None
|
|
must_save = True
|
|
|
|
if homework.token != token:
|
|
homework.token = token
|
|
homework.save()
|
|
|
|
if must_save: tmp.save()
|
|
|
|
if homework == self.material:
|
|
self.token = tmp.token
|
|
|
|
self.materials.append(tmp.id)
|
|
sort += 1
|
|
|
|
for exam in Exam.objects.filter(theme=theme):
|
|
must_save = False
|
|
try:
|
|
token = '{0}#{1}'.format(self.course.id, sort)
|
|
tmp = CourseMap.objects.get(token=token)
|
|
except CourseMap.DoesNotExist:
|
|
tmp = CourseMap.objects.create(exam=exam, sort=sort, course=self.course)
|
|
self.append_in_price(tmp)
|
|
|
|
if tmp.exam != exam:
|
|
tmp.exam = exam
|
|
must_save = True
|
|
|
|
if tmp.homework:
|
|
tmp.homework = None
|
|
must_save = True
|
|
|
|
if tmp.lesson:
|
|
tmp.lesson = None
|
|
must_save = True
|
|
|
|
if exam.token != token:
|
|
exam.token = token
|
|
exam.save()
|
|
|
|
if must_save: tmp.save()
|
|
|
|
if exam == self.material:
|
|
self.token = tmp.token
|
|
self.materials.append(tmp.id)
|
|
sort += 1
|
|
|
|
if sort != CourseMap.objects.filter(course=self.course).count():
|
|
CourseMap.objects.filter(course=self.course).exclude(id__in=self.materials).delete()
|
|
|
|
def course_switcher(self):
|
|
# Блокировка курса на время обработки
|
|
if self.course_public:
|
|
if self.course.public:
|
|
self.course.public = False
|
|
else:
|
|
self.course.public = True
|
|
self.course.save()
|
|
|
|
def main(self):
|
|
self.course_switcher()
|
|
##
|
|
self.rebuild_map()
|
|
##
|
|
self.course_switcher()
|
|
return self.token if self.material else None # Вернуть токен для материала если он есть |