Exemple #1
0
class Stat(models.Model):
    class Meta:
        verbose_name_plural = verbose_name = "统计"

    paper = models.OneToOneField(Paper,
                                 verbose_name=Paper._meta.verbose_name,
                                 related_name="stat",
                                 on_delete=models.PROTECT)
    detail = modelutils.JSONField("详情", help_text="")

    def __str__(self):
        return "统计<%s>" % self.paper

    def add_answer(self, answer):
        d = self.detail or {}
        from . import helper
        questions = d.setdefault('questions', {})
        score_level = str(answer.performance.get('stdScore', 0) / 5 * 5)
        helper.distrib_count(d.setdefault('scores', {}), score_level)
        seconds_level = str((answer.seconds / 30 + 1) * 30)
        helper.distrib_count(d.setdefault('seconds', {}),
                             seconds_level,
                             reverse=True)
        ad = answer.detail
        for a in ad:
            num = str(a.get('number'))
            questions[num] = questions.setdefault(
                num, 0) + (a.get('right') is False and 1 or 0)
        d['answer_user_count'] = self.paper.answers.values(
            'user').distinct().count()
        self.detail = d
Exemple #2
0
class Paper(models.Model):
    class Meta:
        verbose_name_plural = verbose_name = "试卷"
        ordering = (
            '-is_active',
            'order_number',
            '-create_time',
        )

    user = models.ForeignKey(User,
                             verbose_name=User._meta.verbose_name,
                             related_name="exam_papers",
                             on_delete=models.PROTECT)
    title = models.CharField("标题", max_length=255, blank=False)
    content = models.TextField(
        "内容",
        blank=True,
        null=True,
        help_text=
        "编辑指南:\n首行为标题.\n题型用中文数字加点号开头.\n题目用阿拉伯数字加点号开头.\n答案选项用英文字母加点号开头.\n正确答案用'答案:'开头"
    )
    content_object = modelutils.JSONField("内容对象",
                                          blank=True,
                                          null=True,
                                          help_text="")
    create_time = models.DateTimeField("创建时间", auto_now_add=True)
    is_active = models.BooleanField("有效", blank=False, default=True)
    questions_count = models.PositiveSmallIntegerField("题数",
                                                       blank=True,
                                                       default=0)
    is_break_through = models.BooleanField("闯关", blank=True, default=True)
    tags = models.CharField('标签', max_length=256, blank=True, default='')
    order_number = models.PositiveIntegerField('序号',
                                               default=0,
                                               blank=True,
                                               help_text='按数字从小到大排序')
    owner_type = models.ForeignKey('contenttypes.ContentType',
                                   verbose_name='归类',
                                   null=True,
                                   blank=True,
                                   on_delete=models.PROTECT)
    owner_id = models.PositiveIntegerField(verbose_name='属主编号',
                                           null=True,
                                           blank=True,
                                           db_index=True)
    owner = GenericForeignKey('owner_type', 'owner_id')

    def __str__(self):
        return self.title

    def save(self, **kwargs):
        if not self.title:
            self.title = "试卷"
        if self.is_break_through is None:
            self.is_break_through = True
        data = self.content_object
        if data:
            self.questions_count = data.get("questionCount", 0)
        return super(Paper, self).save(**kwargs)
Exemple #3
0
class Video(models.Model):
    class Meta:
        verbose_name_plural = verbose_name = "视频"
        ordering = ('owner_type', 'owner_id', 'name')

    user = models.ForeignKey(User,
                             verbose_name=User._meta.verbose_name,
                             related_name="media_videos",
                             on_delete=models.PROTECT)
    owner_type = models.ForeignKey('contenttypes.ContentType',
                                   verbose_name='归类',
                                   null=True,
                                   blank=True,
                                   on_delete=models.PROTECT)
    owner_id = models.PositiveIntegerField(verbose_name='属主编号',
                                           null=True,
                                           blank=True,
                                           db_index=True)
    owner = GenericForeignKey('owner_type', 'owner_id')
    name = models.CharField("名称", max_length=255)
    description = models.CharField("描述",
                                   max_length=255,
                                   null=True,
                                   blank=True,
                                   default='')
    url = models.URLField("网址")
    cover_url = models.URLField('封面', blank=True, null=True)
    duration = models.PositiveSmallIntegerField('时长',
                                                blank=True,
                                                default=0,
                                                help_text='单位: 秒.',
                                                editable=False)
    size = models.PositiveIntegerField('大小',
                                       blank=True,
                                       default=0,
                                       help_text='单位: 比特Byte',
                                       editable=False)
    context = modelutils.JSONField("详情", blank=True, default={})
    outline = models.TextField("大纲",
                               blank=True,
                               default='',
                               help_text='可在每一行最后加上时间点, 格式样例: [03:12]')
    status = models.PositiveSmallIntegerField("状态",
                                              choices=choices.STATUS,
                                              blank=True,
                                              default=choices.STATUS_PROCESS)
    is_active = models.BooleanField("有效", blank=False, default=False)
    lecturer = models.ForeignKey(Lecturer,
                                 verbose_name=Lecturer._meta.verbose_name,
                                 blank=True,
                                 null=True,
                                 related_name="videos",
                                 on_delete=models.PROTECT)
    create_time = models.DateTimeField("创建时间",
                                       auto_now_add=True,
                                       db_index=True)

    def __str__(self):
        return self.name
Exemple #4
0
class Fault(models.Model):
    class Meta:
        verbose_name_plural = verbose_name = "错题"
        unique_together = ('user', 'paper', 'question_id')
        ordering = ('-create_time', )

    user = models.ForeignKey(User,
                             verbose_name=User._meta.verbose_name,
                             related_name="exam_faults",
                             on_delete=models.PROTECT)
    paper = models.ForeignKey(Paper,
                              verbose_name=Paper._meta.verbose_name,
                              related_name="faults",
                              on_delete=models.PROTECT)
    question_id = models.CharField("题号", max_length=16)
    question_type = models.PositiveSmallIntegerField(
        "类别",
        choices=choices.CHOICES_QUESTION_TYPE,
        default=choices.QUESTION_TYPE_TEXTAREA,
        db_index=True)
    question = modelutils.JSONField("题目")
    times = models.PositiveSmallIntegerField("次数", default=1)
    detail = modelutils.JSONField("详情")
    correct_straight_times = models.PositiveSmallIntegerField("连续答对次数",
                                                              default=0)
    corrected = models.BooleanField("已订正", default=False)
    is_active = models.BooleanField("有效", blank=False, default=True)
    create_time = models.DateTimeField("创建时间",
                                       auto_now_add=True,
                                       db_index=True)
    update_time = models.DateTimeField("更新时间", auto_now=True)

    def __str__(self):
        return "%s@%s by %s" % (self.question_id, self.paper, self.user)

    def save(self, **kwargs):
        from . import helper
        self.correct_straight_times = helper.cal_correct_straight_times(
            self.detail.get('result_list', []))
        return super(Fault, self).save(**kwargs)
Exemple #5
0
class App(models.Model):
    class Meta:
        verbose_name_plural = verbose_name = "应用"
        unique_together = ('tenant', 'name')

    tenant = models.ForeignKey(Tenant, verbose_name=Tenant._meta.verbose_name, related_name="apps")
    name = models.CharField("名字", max_length=64, db_index=True, choices=choices.CHOICES_APPS)
    status = models.PositiveSmallIntegerField("状态", choices=choices.CHOICES_APP_STATUS,
                                              default=choices.APP_STATUS_INSTALL)
    settings = modelutils.JSONField('配置', default={})
    create_time = models.DateTimeField("创建时间", auto_now_add=True)
    modify_time = models.DateTimeField("修改时间", auto_now=True)

    def __unicode__(self):
        return "%s 应用 %s" % (self.tenant, self.name)
Exemple #6
0
class DailyLog(models.Model):
    class Meta:
        verbose_name_plural = verbose_name = "日志"
        unique_together = ('the_date', 'user')

    the_date = models.DateField('日期', db_index=True)
    user = models.ForeignKey(User,
                             verbose_name=User._meta.verbose_name,
                             related_name="dailylog_dailylogs",
                             on_delete=models.PROTECT)
    context = modelutils.JSONField("详情", blank=True, default={})
    create_time = models.DateTimeField("创建时间",
                                       auto_now_add=True,
                                       db_index=True)
    update_time = models.DateTimeField("创建时间", auto_now=True)

    def __unicode__(self):
        return '%s dailylog @ %s' % (self.user, self.the_date.isoformat())
Exemple #7
0
class User(models.Model):
    class Meta:
        verbose_name_plural = verbose_name = '用户'
        ordering = ('-subscribe_time',)

    user = models.OneToOneField(SiteUser, verbose_name="网站用户", null=True, on_delete=models.PROTECT,
                                related_name="as_wechat_user")
    openid = models.CharField("openId", max_length=64, primary_key=True)
    unionid = models.CharField("unionId", max_length=64, null=True, blank=True)
    nickname = models.CharField("昵称", max_length=64, null=True, blank=True)
    headimgurl = models.CharField("头像", max_length=255, null=True, blank=True)
    city = models.CharField("城市", max_length=128, null=True, blank=True)
    province = models.CharField("省份", max_length=128, null=True, blank=True)
    country = models.CharField("国家", max_length=128, blank=True, default="中国")
    sex = models.CharField("性别", max_length=2, null=True, blank=True, choices=choices.CHOICES_GENDER)
    longitude = models.FloatField("经度", null=True, blank=True)
    latitude = models.FloatField("纬度", null=True, blank=True)
    subscribe = models.BooleanField("订阅", blank=True, default=False)
    subscribe_time = models.DateTimeField("订阅时间", blank=True, null=True, db_index=True)
    subscribe_scene = models.CharField("关注渠道", max_length=32, blank=True, default="ADD_SCENE_QR_CODE")
    qr_scene = models.PositiveIntegerField("扫码场景", blank=True, null=True)
    qr_scene_str = models.CharField("扫码场景描述", max_length=32, blank=True, default="")
    remark = models.CharField("备注", max_length=255, blank=True, default="")
    tagid_list = modelutils.JSONField("标签ID列表", blank=True, default=[])
    groupid = models.PositiveIntegerField("分组ID", blank=True, default=0)
    language = models.CharField("语言", max_length=16, blank=True, default="zh_CN")
    create_time = models.DateTimeField("创建时间", editable=False, auto_now_add=True, db_index=True)

    def __str__(self):
        return self.nickname or self.openid

    def save(self, **kwargs):
        from xyz_util.datautils import filter_emoji
        if self.nickname:
            self.nickname = filter_emoji(self.nickname)
        if self.user is None:
            from django.utils.crypto import get_random_string
            user_name = "%s@wechat" % self.openid[-10:]
            self.user, created = SiteUser.objects.get_or_create(username=user_name,
                                                                defaults=dict(email="", first_name=self.nickname))
        return super(User, self).save(**kwargs)
Exemple #8
0
class Authority(models.Model):
    class Meta:
        verbose_name_plural = verbose_name = "权力"

    user = models.OneToOneField('auth.user',
                                related_name='xauth_authority',
                                on_delete=models.PROTECT)
    user_name = models.CharField("姓名", max_length=64, unique=True)
    roles = modelutils.JSONField("角色", blank=True, default={})
    create_time = models.DateTimeField("创建时间", auto_now_add=True)
    modify_time = models.DateTimeField("修改时间", auto_now=True)

    def __str__(self):
        return self.user_name

    @property
    def active_roles(self):
        rs = {}
        for k, v in self.roles.items():
            if v.get('is_active'):
                rs[k] = v
        return rs

    def save(self, **kwargs):
        from .helper import get_roles
        from django.contrib.contenttypes.models import ContentType
        user = self.user
        roles = {}
        for rf in get_roles():
            r = getattr(user, rf.name, None)
            if not r:
                continue
            roles[rf.name] = dict(
                id=r.pk,
                name=rf.name,
                content_type_id=ContentType.objects.get_for_model(r),
                is_active=getattr(r, 'is_active', True))
        self.roles = roles
        self.user_name = user.get_full_name()
        super(Authority, self).save(**kwargs)
Exemple #9
0
class Performance(models.Model):
    class Meta:
        verbose_name_plural = verbose_name = "表现"
        ordering = ('-update_time', )
        unique_together = ('owner_type', 'owner_id', 'user')

    owner_type = models.ForeignKey('contenttypes.ContentType',
                                   verbose_name='归类',
                                   null=True,
                                   blank=True,
                                   on_delete=models.PROTECT)
    owner_id = models.PositiveIntegerField(verbose_name='属主编号',
                                           null=True,
                                           blank=True,
                                           db_index=True)
    owner = GenericForeignKey('owner_type', 'owner_id')
    owner_name = models.CharField('属主名称',
                                  max_length=256,
                                  blank=True,
                                  default='')
    owner_group = models.CharField('属主分组',
                                   max_length=256,
                                   blank=True,
                                   default='')
    user = models.ForeignKey(User,
                             verbose_name=User._meta.verbose_name,
                             related_name="dailylog_performances",
                             on_delete=models.PROTECT)
    user_name = models.CharField('用户姓名',
                                 max_length=256,
                                 blank=True,
                                 default='')
    user_group = models.CharField('用户分组',
                                  max_length=256,
                                  blank=True,
                                  default='')
    detail = modelutils.JSONField('详情', default={}, blank=True)
    target = models.PositiveIntegerField("目标", default=0, blank=True)
    accomplish = models.PositiveIntegerField("完成", default=0, blank=True)
    accumulate = models.PositiveIntegerField("累计完成", default=0, blank=True)
    percent = models.PositiveSmallIntegerField('完成百分比', default=0)
    times = models.PositiveSmallIntegerField('次数', default=0)
    score = models.PositiveSmallIntegerField("得分",
                                             default=0,
                                             blank=True,
                                             null=True)
    create_time = models.DateTimeField("创建时间", auto_now_add=True)
    update_time = models.DateTimeField("更新时间", auto_now=True, db_index=True)

    def __unicode__(self):
        return "%s by %s" % (self.owner_name, self.user_name)

    def save(self, **kwargs):
        self.user_name = self.user.get_full_name()
        if hasattr(self.user, 'as_school_student'):
            student = self.user.as_school_student
            self.user_group = unicode(student.classes.first())
            self.detail['user_number'] = student.number
        self.owner_name = unicode(self.owner)
        self.owner_group = unicode(self.owner.owner) if hasattr(
            self.owner, 'owner') else ''
        d = self.detail
        self.target = d.get('target', 0)
        ps = d.get('parts', [])
        self.accomplish = len(set(ps))
        self.accumulate = len(ps)
        self.percent = int(self.accomplish * 100 /
                           self.target) if self.target else 0
        self.score = d.get('score')
        self.times = d.get('times', 0)
        return super(Performance, self).save(**kwargs)
Exemple #10
0
class Performance(models.Model):
    class Meta:
        verbose_name_plural = verbose_name = "用户成绩"
        unique_together = ('user', 'paper')
        ordering = ('-create_time', )

    user = models.ForeignKey(User,
                             verbose_name=User._meta.verbose_name,
                             related_name="exam_performances",
                             on_delete=models.PROTECT)
    paper = models.ForeignKey(Paper,
                              verbose_name=Paper._meta.verbose_name,
                              related_name="performances",
                              on_delete=models.PROTECT)
    user_name = models.CharField("用户名",
                                 max_length=255,
                                 null=False,
                                 blank=True,
                                 default='')
    paper_name = models.CharField("试卷名称",
                                  max_length=255,
                                  null=False,
                                  blank=True,
                                  default='')
    score = models.PositiveSmallIntegerField("得分",
                                             default=0,
                                             blank=True,
                                             null=True)
    detail = modelutils.JSONField("详情", blank=True, null=True, help_text="")
    create_time = models.DateTimeField("创建时间", auto_now_add=True)
    update_time = models.DateTimeField("更新时间", auto_now=True)

    def __str__(self):
        return "%s by %s" % (self.paper_name, self.user_name)

    @cached_property
    def is_passed(self):
        return self.detail.get(
            'maxScore'
        ) >= EXAM_MIN_PASS_SCORE if self.paper.is_break_through else True

    def cal_performance(self):
        answers = self.paper.answers.filter(user=self.user)
        scs = [a.performance.get('stdScore', 0) for a in answers]
        lastAnswer = answers.first()
        times = len(scs)
        return dict(maxScore=max(scs),
                    minScore=min(scs),
                    avgScore=sum(scs) / times,
                    lastScore=scs[0],
                    times=times,
                    scores=scs,
                    lastTime=lastAnswer and lastAnswer.create_time.isoformat())

    def get_user_info(self):
        u = self.user
        if hasattr(u, 'as_school_student'):
            s = u.as_school_student
            return {'number': s.number, 'group': text_type(s.classes.first())}
        return {}

    def save(self, **kwargs):
        p = self.cal_performance()
        p['userInfo'] = self.get_user_info()
        p['paperInfo'] = {'group': text_type(self.paper.owner)}
        self.paper_name = self.paper.title
        self.user_name = self.user.get_full_name()
        self.detail = p
        self.score = p.get('maxScore', 0)
        return super(Performance, self).save(**kwargs)
Exemple #11
0
class Answer(models.Model):
    class Meta:
        verbose_name_plural = verbose_name = "用户答卷"
        ordering = ('-create_time', )

    user = models.ForeignKey(User,
                             verbose_name=User._meta.verbose_name,
                             related_name="exam_answers",
                             on_delete=models.PROTECT)
    paper = models.ForeignKey(Paper,
                              verbose_name=Paper._meta.verbose_name,
                              related_name="answers",
                              on_delete=models.PROTECT)
    detail = modelutils.JSONField("详情", help_text="")
    grade_detail = modelutils.JSONField("批卷", blank=True, help_text="")
    pictures = modelutils.JSONField("图片", blank=True, default={})
    seconds = models.PositiveSmallIntegerField("用时",
                                               default=0,
                                               blank=True,
                                               null=True,
                                               help_text="单位(秒)")
    std_score = models.PositiveSmallIntegerField("分数",
                                                 default=0,
                                                 blank=True,
                                                 null=True)
    performance = modelutils.JSONField("成绩表现",
                                       blank=True,
                                       null=True,
                                       help_text="")
    create_time = models.DateTimeField("创建时间",
                                       auto_now_add=True,
                                       db_index=True)

    def __str__(self):
        return "%s by %s" % (self.paper, self.user.get_full_name())

    def save(self, **kwargs):
        if not self.grade_detail:
            self.grade_detail = {}
        self.performance = self.cal_performance()
        self.std_score = self.performance.get('stdScore')
        return super(Answer, self).save(**kwargs)

    def get_question_subjective_map(self):
        p = self.paper.content_object
        m = {}
        for g in p['groups']:
            is_subjective = False
            for q in g['questions']:
                if q.get('type') in ['textarea', 'sentence']:
                    is_subjective = True
                    break
            for q in g['questions']:
                m[q['number']] = is_subjective
        return m

    def cal_performance(self):
        wc = 0
        rc = 0
        score = 0
        score_subjective = 0
        score_objective = 0
        fsc = 0

        sm = self.get_question_subjective_map()

        for a in self.detail:
            if a['right'] is True:
                rc += 1
            else:
                wc += 1
            is_subjective = sm.get(a['number'])
            sc = a['userScore']
            if is_subjective:
                score_subjective += sc
            else:
                score_objective += sc
            score += sc
            fsc += a['score']
        stdScore = score * 100 / fsc if fsc > 0 else 0

        ms = self.cal_merge_score()
        format = lambda a: int(round(a))  # float('%.1f' % a)
        return dict(wrongCount=wc,
                    rightCount=rc,
                    fullScore=fsc,
                    score=format(score),
                    stdScore=format(stdScore),
                    scoreSubjective=format(score_subjective),
                    scoreObjective=format(score_objective),
                    isPassed=stdScore >= EXAM_MIN_PASS_SCORE,
                    scoreMerge=format(ms),
                    stdScoreMerge=format(ms * 100 / fsc if fsc > 0 else 0))

    def cal_group_score(self):
        p = self.paper.content_object
        m = {}
        d = self.detail
        if not d:
            return m
        ld = len(d)
        for g in p['groups']:
            gs = 0
            for q in g['questions']:
                n = q['number']
                if n > ld:
                    continue
                gs += d[n - 1]['userScore']
            m[g['id']] = gs
        return m

    def merge_group_score(self):
        m = self.cal_group_score()
        gm = deepcopy(self.grade_detail)
        for k, v in m.items():
            if k in gm:
                continue
            gm[k] = dict(score=m[k])
        return gm

    def cal_merge_score(self):
        gm = self.merge_group_score()
        return sum([v['score'] for k, v in gm.items()])