--- a/OSSEval/analysis/models.py
+++ b/OSSEval/analysis/models.py
@@ -1,3 +1,4 @@
+import importlib
from django.db import models
from datetime import datetime
from random import randrange
@@ -41,7 +42,7 @@
class HasPages(models.Model):
bar_chart = models.TextField(blank=True)
radar_chart = models.TextField(blank=True)
- def create_graphs(self, instances):
+ def create_graphs(self, instances, include_max = True):
# I draw the graphs for the report
#styles = [NeonStyle, DarkSolarizedStyle, LightSolarizedStyle, LightStyle, CleanStyle, RedBlueStyle, DarkColorizedStyle, LightColorizedStyle, TurquoiseStyle, LightGreenStyle, DarkGreenStyle, DarkGreenBlueStyle, BlueStyle]
#style=styles[randrange(len(styles))]
@@ -56,6 +57,9 @@
instance_scores = {}
for instance in instances:
instance_scores[instance.id] = []
+ if include_max:
+ # I use 0 as an id for the max score
+ instance_scores[0] = []
for page in self.page_set.all():
radar_chart.x_labels.append(page.name)
for instance in instances:
@@ -64,9 +68,15 @@
instance_scores[instance.id].append(ps.score)
except:
instance_scores[instance.id].append(0)
+ if include_max:
+ instance_scores[0].append(5)
+ print str(page.id) + " - " + str(page.max_score)
for instance in instances:
radar_chart.add(instance.name, instance_scores[instance.id])
bar_chart.add(instance.name, sum(instance_scores[instance.id]))
+ if include_max:
+ radar_chart.add("MAX", instance_scores[0])
+ bar_chart.add("MAX", sum(instance_scores[0]))
self.radar_chart = radar_chart.render()
self.bar_chart = bar_chart.render()
self.save()
@@ -128,6 +138,7 @@
order = models.IntegerField(null=False,blank=False)
parent = models.ForeignKey('self',null=True,blank=True)
methodology_version = models.ForeignKey(MethodologyVersion,null=True,blank=True)
+ max_score = 0
def questions(self):
q = list(self.question_set.all())
for p in self.page_set.all():
@@ -180,6 +191,7 @@
return '<Page Id="' + str(self.id) + '" Name="' + self.name + '" Order="' + str(self.order) + '">' + str_xml + "</Page>"
def calculate_scores(self, instance, weight_scenario, instances):
+ self.max_score = 5
# Let's reset the score to 0
try:
ps = PageScore.objects.get(page=self, instance=instance)
@@ -321,6 +333,12 @@
class Meta:
ordering = ['order']
+class Weight():
+ '''
+ used by WeightScenario so I need to define it first
+ '''
+ pass
+
class WeightScenario(models.Model):
name = models.CharField(max_length=200)
methodology_version = models.ForeignKey(MethodologyVersion)
@@ -335,6 +353,7 @@
if w.question.id == question_id:
weight = w.weight
return weight
+
def from_xml(self, xmldoc, methodology_version, insert = True):
if not insert:
self.id = xmlMinidom.getNaturalAttribute(xmldoc, 'Id')
@@ -369,11 +388,24 @@
self.scenario = scenario
self.weight = xmlMinidom.getStringAttribute(xmldoc, 'weight')
self.question = Question.objects.get(pk=xmlMinidom.getNaturalAttribute(xmldoc, 'question_id'))
+ # If I am inserting I must check that there's no other Weight for the same
+ # couple ('question', 'scenario') as I have a unique_together constraint
+ if not self.id:
+ # I look for a Weight for the same question and scenario
+ try:
+ w = Weight.objects.get(scenario_id=self.scenario.id, question_id=self.question.id)
+ w.delete()
+ except:
+ # I didn't find one; nothing to do
+ pass
self.save()
def to_xml(self):
return '<Weight Id="' + str(self.id) + '" question_id="' + str(self.question.id) + '" weight="' + str(self.weight) + '"/>'
+ class Meta:
+ unique_together = ('question', 'scenario')
+
class Analysis(models.Model):
name = models.CharField(max_length=200)
description = models.CharField(max_length=2000)
@@ -388,18 +420,17 @@
def __str__(self):
return self.name
- def calculate_scores(self):
+ def calculate_scores(self, weight_scenario_id):
'''
Calculates scores for each couple (instance, page) and (instance, question)
Stores them on the db
'''
#let's get the weight from the scenario if any; the default is 1
try:
- weight_scenarios = self.methodology_version.weightscenario_set.filter(active=True)
- if len(weight_scenarios) == 1:
- weight_scenario = weight_scenarios[0]
+ if weight_scenario_id > 0:
+ weight_scenario = WeightScenario.objects.get(pk=weight_scenario_id)
else:
- raise Exception("There should be exactly one WeightScenario for MethodologyVersion " + str(self.methodology_version.id))
+ weight_scenario = self.weight_scenario
except:
# an empty one will set all weights to 1
weight_scenario = WeightScenario()
@@ -410,6 +441,7 @@
for instance in self.instance_set.all():
page.calculate_scores(instance, weight_scenario, self.instance_set.all())
self.methodology_version.create_graphs(self.instance_set.all())
+ return weight_scenario
# @staticmethod
# def create_graphs(object, pages, instances):
@@ -422,7 +454,26 @@
All but the MethodologyVersion so that we can independently import from xml
MethodologyVersion and Analysis
'''
- pass
+ if not insert:
+ self.id = xmlMinidom.getNaturalAttribute(xmldoc, 'Id')
+ self.name = xmlMinidom.getStringAttribute(xmldoc, 'Name')
+ self.comment = xmlMinidom.getStringAttribute(xmldoc, 'Comment')
+ self.created = xmlMinidom.getStringAttribute(xmldoc, 'Created')
+ self.methodology_version = MethodologyVersion.objects.get(pk=xmlMinidom.getNaturalAttribute(xmldoc, 'MethodologyVersionId'))
+ self.user_login = xmlMinidom.getStringAttribute(xmldoc, 'UserLogin')
+ self.visible = xmlMinidom.getStringAttribute(xmldoc, 'Visible')
+ self.protected = xmlMinidom.getStringAttribute(xmldoc, 'Protected')
+ #self.weight_scenario
+ xml_weight_scenario = xmldoc.getElementsByTagName('WeightScenario')[0]
+ ws = WeightScenario()
+ ws.from_xml(xml_weight_scenario, self.methodology_version, insert)
+ self.weight_scenario = ws
+ self.save()
+ #Instances
+ xml_instances = xmldoc.getElementsByTagName('Instance')
+ for xml_instance in xml_instances:
+ i = Instance()
+ i.from_xml(xml_instance, self, insert)
def to_xml(self):
str_xml = "<Description>" + self.description + "</Description>"
@@ -433,29 +484,45 @@
str_xml += instance.to_xml()
str_xml += "</Instances>"
- return '<Analysis Id="' + str(self.id) + '" Name="' + self.name + '" Created="' + str(self.created) + '" UserLogin="' + self.user_login + '">' + str_xml + "</Analysis>"
+ return '<Analysis Id="' + str(self.id) + '" MethodologyVersionId="' + str(self.methodology_version.id) + '" Name="' + self.name + '" Created="' + str(self.created) + '" Visible="' + str(self.visible) + '" Protected="' + str(self.protected) + '" UserLogin="' + self.user_login + '">' + str_xml + "</Analysis>"
class Instance(models.Model):
"""
It represents one of the entities we evaluate in the assessment
"""
name = models.CharField(max_length=200)
+ # name_for_search is not used yet; it is intended to provide a name to be used to search the web
name_for_search = models.CharField(max_length=200, default="")
analysis = models.ForeignKey(Analysis)
def __str__(self):
return self.name + " - " + self.name_for_search
- def from_xml(self, xmldoc, insert = True):
- pass
+ def from_xml(self, xmldoc, analysis, insert = True):
+ if not insert:
+ self.id = xmlMinidom.getNaturalAttribute(xmldoc, 'Id')
+ self.name = xmlMinidom.getStringAttribute(xmldoc, 'Name')
+ #ActualInstance
+ self.analysis = analysis
+ xml_actual_instance = xmldoc.getElementsByTagName(self.analysis.methodology_version.methodology.entity.actual_entity_class)[0]
+ module = importlib.import_module(self.analysis.methodology_version.methodology.entity.actual_entity_app + ".models")
+ actual_entity_class = getattr(module, self.analysis.methodology_version.methodology.entity.actual_entity_class)
+ self.actual_instance = actual_entity_class()
+ self.actual_instance.from_xml(xml_actual_instance, self, insert)
+ self.save()
+ #Answers
+ xml_answers = xmldoc.getElementsByTagName('Answer')
+ for xml_answer in xml_answers:
+ a = Answer()
+ a.from_xml(xml_answer, self, insert)
def to_xml(self):
str_xml = "<Answers>"
for answer in self.answer_set.all():
str_xml += answer.to_xml()
str_xml += "</Answers>"
-
- return '<Instance Id="' + str(self.id) + '" Name="' + self.name + '" NameForSearch="' + self.name_for_search + '">' + str_xml + "</Instance>"
+ str_xml += self.actual_instance.to_xml()
+ return '<Instance Id="' + str(self.id) + '" Name="' + self.name + '">' + str_xml + "</Instance>"
class PageScore(models.Model):
page = models.ForeignKey(Page)
@@ -477,14 +544,36 @@
score = models.FloatField(default=0)
notes = models.CharField(max_length=2000)
- def from_xml(self, xmldoc, insert = True):
- pass
+ def from_xml(self, xmldoc, instance, insert = True):
+ if not insert:
+ self.id = xmlMinidom.getNaturalAttribute(xmldoc, 'Id')
+ self.instance = instance
+ xml_question = xmldoc.getElementsByTagName('Question')[0]
+ question = Question.objects.get(pk = xmlMinidom.getNaturalAttribute(xml_question, 'Id'))
+ self.question = question
+ self.value_integer = xmlMinidom.getNaturalAttribute(xmldoc, 'ValueInteger')
+ xml_notes = xmldoc.getElementsByTagName('Notes')[0]
+ try:
+ self.notes = xml_notes.firstChild.data
+ except:
+ self.notes = ""
+ # If I am inserting I must check that there's no other answer for the same
+ # couple ('question', 'instance') as I have a unique_together constraint
+ if not self.id:
+ # I look for an answer for the same question and instance
+ try:
+ a = Answer.objects.get(instance_id=self.instance.id, question_id=self.question.id)
+ a.delete()
+ except:
+ # I didn't find one; nothing to do
+ pass
+ self.save()
def to_xml(self):
str_xml = "<Notes>" + self.notes + "</Notes>"
str_xml += '<Question Id="' + str(self.question.id) + '"></Question>'
- return '<Answer ValueInteger="' + str(self.value_integer) + '">' + str_xml + "</Answer>"
+ return '<Answer Id="' + str(self.id) + '" ValueInteger="' + str(self.value_integer) + '">' + str_xml + "</Answer>"
class Meta:
unique_together = ('question', 'instance',)
@@ -497,4 +586,8 @@
'''
Used to save uploaded xml file so that it can be later retrieved and imported
'''
- docfile = models.FileField(upload_to='documents/%Y/%m/%d')+ docfile = models.FileField(upload_to='documents/%Y/%m/%d')
+
+class MyModel(models.Model):
+ field1 = models.CharField(max_length=40, blank=False, null=False)
+ field2 = models.CharField(max_length=60, blank=True, null=True)