123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271 |
- from django.contrib import auth
- from rest_framework.views import APIView
- from rest_framework.response import Response
- from rest_framework import status
- from rest_framework.authtoken.models import Token
- from rest_framework.authentication import BasicAuthentication, TokenAuthentication
- from .serializers import UserRegisterSerializer
- from django.middleware.csrf import get_token
- from django.contrib.auth import login
- from api.utils import *
- from api.models import Result, Graph, GraphToken, Plan
- from random import randint
- import json, csv
- class ViewGraphByToken(APIView):
- # 通过验证码看图——供VR使用
- authentication_classes = []
- permission_classes = []
- def get(self, request):
- print(request.GET)
- requestToken = request.GET.get('token')
- print(requestToken)
- try:
- token = GraphToken.objects.get(token=str(requestToken))
- except GraphToken.DoesNotExist:
- return failed(message="Token不存在")
- if token.checkExpire():
- return failed(message="Token已过期")
- graph = token.graph
- return success(data={
- 'nodes': graph.nodes,
- 'edges': graph.edges,
- })
- class GenerateGraph(APIView):
- # 生成图数据
- def get(self, request):
- user = request.user
- method = request.GET.get('method') # 以何种视图查看
- planId = request.GET.get('plan')
- try:
- plan = Plan.objects.get(id=planId)
- except Plan.DoesNotExist:
- print("获取结果的Plan失败")
- return failed(message="无法找到该结果对应规划")
- result = plan.own_result
- # 图表显示不生成图,仅做统计计算
- if method == 'chart':
- nodeJson = result.nodeFile.toJson()
- edgeJson = result.edgeFile.toJson()
- def isOriginEdge(edge):
- for meta in edge['meta']:
- if meta.get('optimize') == 'new' or meta.get('predict') == 'new':
- return False
- return True
- # 需要完善图表视图统计数据,根据具体图表类型决定
- # 通用图数据统计,包括SDI节点数量、边数量,各类型节点度数分布
- # 平均链长度,聚类系数即D节点间连接紧密程度
- # 分别统计SDI节点的数量和度数:sNodes,dNodes,iNodes
- sDegree = dDegree = iDegree = [0 for i in range(11)] # 度的取值范围0~10,共11个元素
- sNodes = [node for node in nodeJson if node['type'] == 'S']
- for s in sNodes:
- degree = len([edge for edge in edgeJson if edge['from'] == s['id'] or edge['to'] == s['id']])
- if degree <= 10:
- sDegree[degree] += 1
- else:
- sDegree[10] += 1
- dNodes = [node for node in nodeJson if node['type'] == 'D']
- for d in dNodes:
- degree = len([edge for edge in edgeJson if edge['from'] == d['id'] or edge['to'] == d['id']])
- if degree <= 10:
- dDegree[degree] += 1
- else:
- dDegree[10] += 1
- iNodes = [node for node in nodeJson if node['type'] == 'I']
- for i in iNodes:
- degree = len([edge for edge in edgeJson if edge['from'] == i['id'] or edge['to'] == i['id']])
- if degree <= 10:
- iDegree[degree] += 1
- else:
- iDegree[10] += 1
- # 查找所有OODA链路:chains
- chains = []
- for s in sNodes:
- stack = [(s, [s])] # (当前节点, 路径, 已访问节点)
- while stack:
- current, path = stack.pop()
- # 必须限制链路长度,否则无法结束,除限制长度外还可尝试将不同顺序节点的链路视为同一条,从而减少链路数量
- if len(path) > 5:
- continue
- # 终止条件:到达I节点
- if current['type'] == 'I':
- chains.append(path)
- continue
-
- # 遍历邻居,注意通用计算只统计原始图
- neighbors = [edge['to'] for edge in edgeJson if (isOriginEdge(edge) and edge['from'] == current['id'])] + [edge['from'] for edge in edgeJson if (isOriginEdge(edge) and edge['to'] == current['id'])]
- for neighborId in neighbors:
- neighbor = [node for node in nodeJson if node.get('id') == neighborId]
- if len(neighbor) != 1:
- return failed(message="查找OODA链路时出错:不存在的邻居节点")
- neighbor = neighbor[0]
- if neighbor in path: continue # 避免环路
- # 不能连线的几种情况
- if current['type'] == 'S' and neighbor['type'] == 'I':
- continue
- if current['type'] == 'D' and neighbor['type'] == 'S':
- continue
- stack.append((neighbor, path + [neighbor]))
- chainsNum = len(chains)
- chainsNumByLength = [0 for i in range(5)]
- for chain in chains:
- length = len(chain)
- if length >= 5:
- length = 5
- chainsNumByLength[length-1] += 1
- averageChainsLength = round(sum([len(chain) for chain in chains]) / chainsNum, 2)
- data = {
- 'sNodesNum': len(sNodes),
- 'dNodesNum': len(dNodes),
- 'iNodesNum': len(iNodes),
- 'sDegree': sDegree,
- 'dDegree': dDegree,
- 'iDegree': iDegree,
- 'chains': {
- 'num': chainsNum,
- 'averageLength': averageChainsLength,
- 'numByLength': chainsNumByLength,
- },
- }
- # 根据计算类型的不同分别计算特殊数据
- if result.plan.algorithm.type in ['optimize', 'predict'] :
- # 拓扑优化算法应该统计原有图的数据与优化后图的数据,优化应该仅优化边
- newChains = []
- for s in sNodes:
- stack = [(s, [s])] # (当前节点, 路径, 已访问节点)
- while stack:
- current, path = stack.pop()
-
- # 终止条件:到达I节点
- if current['type'] == 'I':
- newChains.append(path)
- continue
-
- # 遍历邻居,注意优化计算只统计新图
- neighbors = [edge['to'] for edge in edgeJson if (not isOriginEdge(edge) and edge['from'] == current['id'])] + [edge['from'] for edge in edgeJson if (not isOriginEdge(edge) and edge['to'] == current['id'])]
- for neighborId in neighbors:
- neighbor = [node for node in nodeJson if node.get('id') == neighborId]
- if len(neighbor) != 1:
- return failed(message="查找OODA链路时出错:不存在的邻居节点")
- neighbor = neighbor[0]
- if neighbor in path: continue # 避免环路
- # 不能连线的几种情况
- if current['type'] == 'S' and neighbor['type'] == 'I':
- continue
- if current['type'] == 'D' and neighbor['type'] == 'S':
- continue
- stack.append((neighbor, path + [neighbor]))
- newChainsNum = len(newChains)
- newAverageChainsLength = 0
- if newChainsNum != 0:
- newAverageChainsLength = round(sum([len(chain) for chain in newChains]) / newChainsNum, 2)
- data['newChains'] = {
- 'num': newChainsNum,
- 'averageLength': newAverageChainsLength,
- }
- return success(data=data)
- # 如果已经生成过图数据,则直接生成新的验证码
- if result.own_graphs.exists():
- graph = result.own_graphs.first()
- if method == 'web' or method == '3D' or method == '3d':
- return success(data={
- 'nodes': graph.nodes,
- 'edges': graph.edges,
- })
- elif method == 'VR':
- token = graph.generateToken()
- return success(data={
- 'token': token,
- })
- else:
- nodeJson = result.nodeFile.toJson()
- edgeJson = result.edgeFile.toJson()
- ######测试用,添加几个标签
- for node in nodeJson:
- node['meta'].append({'optimize': 'new'})
- node['meta'].append({'group': randint(1,5)})
- node['meta'].append({'predict': 'new'})
- for edge in edgeJson:
- edge['meta'].append({'optimize': 'new'})
- edge['meta'].append({'predict': 'new'})
- ########################
- # 两种3D视图的数据结构应该是一样的
- if result.plan.algorithm.type == 'optimize':
- # 拓扑优化算法生成的结果,只有网络结构数据
- # 检查合法性
- for node in nodeJson:
- if not 'id' in node or not 'type' in node:
- return failed(message="拓扑优化结果的节点文件存在问题")
- for edge in edgeJson:
- if not 'from' in edge or not 'to' in edge:
- return failed(message="边文件存在问题")
- # 对于优化算法,边的属性中应该有新旧的区分
- missingLabel = True
- for meta in edge['meta']:
- if 'optimize' in meta and meta['optimize'] in ['new', 'old']:
- missingLabel = False
- if missingLabel:
- return failed(message="无拓扑优化标签")
- elif result.plan.algorithm.type == 'group':
- # 功能体探测算法生成的结果
- # 检查合法性
- for node in nodeJson:
- if not 'id' in node or not 'type' in node:
- return failed(message="节点文件存在问题")
- # 对于功能体探测算法,节点的属性中应有功能体的编号
- missingLabel = True
- for meta in node['meta']:
- if 'group' in meta and type(meta['group']) == int:
- missingLabel = False
- if missingLabel:
- return failed(message="无功能体标签")
- for edge in edgeJson:
- if not 'from' in edge or not 'to' in edge:
- return failed(message="边文件存在问题")
- elif result.plan.algorithm.type == 'predict':
- # 链路演化预测算法生成的结果
- # 检查合法性
- for node in nodeJson:
- if not 'id' in node or not 'type' in node:
- return failed(message="节点文件存在问题")
- # 对于演化预测算法,节点的属性中应有新旧区分
- missingLabel = True
- for meta in node['meta']:
- if 'predict' in meta and meta['predict'] in ['new', 'old']:
- missingLabel = False
- if missingLabel:
- return failed(message="无演化预测标签")
- for edge in edgeJson:
- if not 'from' in edge or not 'to' in edge:
- return failed(message="边文件存在问题")
- # 对于演化预测算法,边的属性中应有新旧区分
- missingLabel = True
- for meta in edge['meta']:
- if 'predict' in meta and meta['predict'] in ['new', 'old']:
- missingLabel = False
- if missingLabel:
- return failed(message="无演化预测标签")
- graph = Graph.objects.createFromResult(result)
- graph.save()
- if method == 'web':
- return success(data={
- 'nodes': graph.nodes,
- 'edges': graph.edges,
- })
- if method == 'VR':
- token = graph.generateToken()
- return success(data={
- 'token': token,
- })
|