|
|
from django.db import models
|
|
|
|
|
|
# Create your models here.
|
|
|
|
|
|
from django.db import models
|
|
|
from django.db.models import Model, Max, Min
|
|
|
import random
|
|
|
from django.db.models import F
|
|
|
|
|
|
class Student(models.Model):
|
|
|
name = models.CharField(max_length=32)
|
|
|
sid = models.CharField(max_length=20)
|
|
|
credit = models.FloatField()
|
|
|
class_name = models.CharField(max_length=32)
|
|
|
probability = models.FloatField()
|
|
|
max = models.FloatField()
|
|
|
min = models.FloatField()
|
|
|
|
|
|
|
|
|
def prob(self,class_name,credit): #由积分求概率
|
|
|
stu = Student.objects.filter(class_name=class_name)
|
|
|
credits = [student.credit for student in stu]
|
|
|
max_credit = max(credits)
|
|
|
min_credit = max(credits)
|
|
|
if max_credit == min_credit:
|
|
|
return 1
|
|
|
else:
|
|
|
return (credit - min_credit)/(max_credit - min_credit)
|
|
|
|
|
|
def callstu(self,class_name,num,mode): #点名的函数,输入要点的人数,返回这些人的学号姓名,不重复,(基础模式)
|
|
|
sts = Student.objects.filter(class_name=class_name)
|
|
|
probabilities = []
|
|
|
if mode == 1 or mode == 2: #基础模式和得分加倍的筛选概率不变
|
|
|
probabilities = [student.probability for student in sts]
|
|
|
elif mode == 3 : #三五成群
|
|
|
for s1 in sts:
|
|
|
if (int(s1.credit) % 3 == 0 or int(s1.credit) % 5 == 0) and s1.credit != 0:
|
|
|
probabilities.append(2*s1.probability)
|
|
|
else:
|
|
|
probabilities.append(s1.probability)
|
|
|
else: #六六大顺
|
|
|
for s1 in sts:
|
|
|
if int(s1.credit) % 6 == 0 and s1.credit != 0:
|
|
|
probabilities.append(2*s1.probability)
|
|
|
else:
|
|
|
probabilities.append(s1.probability)
|
|
|
if probabilities:
|
|
|
max_probability = max(probabilities)
|
|
|
min_probability = min(probabilities)
|
|
|
else:
|
|
|
max_probability = -1
|
|
|
min_probability = -1
|
|
|
if num > sts.count():
|
|
|
data = {'message':0}
|
|
|
return data
|
|
|
else:
|
|
|
result = {}
|
|
|
if mode == 1 or mode == 2:
|
|
|
time = 0 #筛选出一个学生需要生成的随机数的次数 (刚开始比较稀疏,要避免一直不能完成抽取条件的情况)设置上限为10
|
|
|
while len(result) < num: #基础模式和得分加倍模式
|
|
|
if time == 10: #当为了筛选一个人而生成了10次随机数后,由于太浪费时间,直接筛选剩下的人
|
|
|
flag = 0
|
|
|
while flag == 0:
|
|
|
s = sts.order_by('?').first()
|
|
|
if s.sid not in result:
|
|
|
result[s.name] = s.sid
|
|
|
time = 0
|
|
|
flag += 1
|
|
|
else:
|
|
|
random_probability = random.uniform(min_probability, max_probability)
|
|
|
time += 1
|
|
|
s = sts.filter(probability__gte = random_probability).order_by('?').first()
|
|
|
if s.sid not in result:
|
|
|
result[s.name] = s.sid
|
|
|
time = 0 #当筛选出一个的时候,为下一次的筛选置为0
|
|
|
elif mode == 3: #三五成群
|
|
|
time = 0 # 筛选出一个学生需要生成的随机数的次数 (刚开始比较稀疏,要避免一直不能完成抽取条件的情况)设置上限为10
|
|
|
while len(result) < num: #一个随机数就选出一个学生
|
|
|
if time == 10:
|
|
|
flag = 0
|
|
|
while flag == 0:
|
|
|
s = sts.order_by('?').first()
|
|
|
if s.sid not in result:
|
|
|
result[s.name] = s.sid
|
|
|
time = 0
|
|
|
flag += 1
|
|
|
else:
|
|
|
random_probability = random.uniform(min_probability, max_probability)
|
|
|
# print(random_probability)
|
|
|
ss1 = [student for student in sts if ( int(student.credit) % 5 == 0
|
|
|
or int(student.credit) % 3 == 0 )and student.probability > random_probability/2]
|
|
|
ss2 =[student for student in sts if student.credit > random_probability]
|
|
|
ss = list(set(ss1+ss2))
|
|
|
random_student = random.choice(ss)
|
|
|
if random_student.id not in result:
|
|
|
result[random_student.name] = random_student.sid
|
|
|
time = 0
|
|
|
print(result)
|
|
|
elif mode == 4: #六六大顺
|
|
|
time = 0 # 筛选出一个学生需要生成的随机数的次数 (刚开始比较稀疏,要避免一直不能完成抽取条件的情况)设置上限为10
|
|
|
while len(result) < num: #一个随机数就选出一个学生
|
|
|
if time == 10:
|
|
|
flag = 0
|
|
|
while flag == 0:
|
|
|
s = sts.order_by('?').first()
|
|
|
if s.sid not in result:
|
|
|
result[s.name] = s.sid
|
|
|
time = 0
|
|
|
flag += 1
|
|
|
else:
|
|
|
random_probability = random.uniform(min_probability, max_probability)
|
|
|
ss1 = [student for student in sts if int(student.credit) % 6 == 0 and student.probability > random_probability/2]
|
|
|
ss2 = [student for student in sts if student.credit > random_probability]
|
|
|
ss = list(set(ss1+ss2))
|
|
|
random_student = random.choice(ss)
|
|
|
if random_student.id not in result:
|
|
|
result[random_student.name] = random_student.sid
|
|
|
time = 0
|
|
|
data = {'message':1,
|
|
|
'result':result}
|
|
|
return data
|
|
|
|
|
|
def updateinfor (self,point,class_name,sid,style): #更新积分和概率
|
|
|
if style == 1 :
|
|
|
point = point
|
|
|
if style == 2 :
|
|
|
point = point * 2
|
|
|
#先改变该学生的积分值
|
|
|
current_s = Student.objects.filter(class_name=class_name, sid=sid).first()
|
|
|
current_credit = current_s.credit
|
|
|
current_s.credit = current_credit + point
|
|
|
current_s.save()
|
|
|
#查找最新的最大或最小值,与原来写在表中的上次更新的最大值和最小值做对比
|
|
|
max_credit = Student.objects.filter(class_name=class_name).aggregate(max_credit=Max('credit'))['max_credit']
|
|
|
min_credit = Student.objects.filter(class_name=class_name).aggregate(min_credit=Min('credit'))['min_credit']
|
|
|
s = Student.objects.filter(class_name=class_name).first() #找未更新的值
|
|
|
max_credit0 = s.max
|
|
|
min_credit0 = s.min
|
|
|
fm = max_credit - min_credit #最新的分母
|
|
|
#如果不影响2个最值,仅改变单个学生的概率
|
|
|
if max_credit == max_credit0 and min_credit == min_credit0:
|
|
|
if fm == 0:
|
|
|
prob = 1.0
|
|
|
else:
|
|
|
prob = 1 - (current_s.credit - min_credit)/fm
|
|
|
current_s.probability = prob # 直接设置字段的值
|
|
|
current_s.save() # 调用 save 方法保存更改
|
|
|
|
|
|
#影响积分最大值和最小值其中的一个时,所有学生的概率都需要改变,先将最新的最大值和最小值写入数据库
|
|
|
else:
|
|
|
#将最新的最大值和最小值写入数据库
|
|
|
sts = Student.objects.filter(class_name=class_name)
|
|
|
sts.update(min = min_credit, max = max_credit)
|
|
|
#更新所有学生的概率
|
|
|
if fm == 0 :
|
|
|
sts.update(probability = 1.0)
|
|
|
else:
|
|
|
sts.update(probability = (1 - (F('credit') - min_credit)/fm))
|
|
|
|
|
|
#耗时最大,性能改进前的代码
|
|
|
# def updateinfor (self,point,class_name,sid,style): #更新积分和概率
|
|
|
# if style == 1 :
|
|
|
# point = point
|
|
|
# if style == 2 :
|
|
|
# point = point * 2
|
|
|
# #先改变该学生的积分值
|
|
|
# current_s = Student.objects.filter(class_name=class_name, sid=sid).first()
|
|
|
# current_credit = current_s.credit
|
|
|
# current_s.credit = current_credit + point
|
|
|
# current_s.save()
|
|
|
# #查找最新的最大或最小值,与原来写在表中的上次更新的最大值和最小值做对比
|
|
|
# max_credit = Student.objects.filter(class_name=class_name).aggregate(max_credit=Max('credit'))['max_credit']
|
|
|
# min_credit = Student.objects.filter(class_name=class_name).aggregate(min_credit=Min('credit'))['min_credit']
|
|
|
# fm = max_credit - min_credit #最新的分母
|
|
|
# sts = Student.objects.filter(class_name=class_name)
|
|
|
# sts.update(min=min_credit, max=max_credit)
|
|
|
# # 更新所有学生的概率
|
|
|
# if fm == 0:
|
|
|
# sts.update(probability=1.0)
|
|
|
# else:
|
|
|
# sts.update(probability=(1 - (F('credit') - min_credit) / fm)) |