# Path: privacyscore/evaluation/site_evaluation.py
# class SiteEvaluation:
#     """
#     An evaluation for a site. It contains of multiple group evaluations as well
#     as an ordering of the groups used for ranking/comparison.
# 
#     It is required that each group defined in groups is present in evaluations
#     and vice versa.
#     """
#     # evaluations  : Dict[str, GroupEvaluation]  # GroupEvaluation for each group
#     # group_order  : list  # The priority order of the groups
#     rateable = True
# 
#     def __init__(self, evaluations: Dict[str, GroupEvaluation], group_order: list):
#         self.evaluations = evaluations
#         self.group_order = group_order
# 
#     def __str__(self) -> str:
#         return '; '.join(
#             '{}: {}'.format(group, str(self.evaluations[group]))
#             for group in self.group_order)
# 
#     def __repr__(self) -> str:
#         return '<SiteEvaluation {}>'.format(str(self))
# 
#     def __eq__(self, other) -> bool:
#         if (self.rateable and not other.rateable or
#                 other.rateable and not self.rateable):
#             return False
#         for group in self.group_order:
#             if (self.evaluations[group] != other.evaluations[group] or
#                     self.evaluations[group].good_ratio != other.evaluations[group].good_ratio):
#                 return False
#         return True
# 
#     def __lt__(self, other):
#         if self.rateable and not other.rateable:
#             return False
#         if not self.rateable and other.rateable:
#             return True
#         for group in self.group_order:
#             if self.evaluations[group] < other.evaluations[group]:
#                 return True
#             elif self.evaluations[group] > other.evaluations[group]:
#                 return False
# 
#         # All group ratings were equal -- compare good ratios
#         for group in self.group_order:
#             if self.evaluations[group].good_ratio < other.evaluations[group].good_ratio:
#                 # less
#                 return True
#             elif self.evaluations[group].good_ratio > other.evaluations[group].good_ratio:
#                 # greater
#                 return False
# 
#         # all good ratios were equal
#         return False
# 
#     def __le__(self, other):
#         return self < other or self == other
# 
#     def __gt__(self, other):
#         """
#         The groups are compared group-wise ordered by the given group priority.
#         If all groups are identical, the good ratios of the groups are compared.
#         If a compared group is exactly identical, the next group is checked.
#         """
#         if self.rateable and not other.rateable:
#             return True
#         if not self.rateable and other.rateable:
#             return False
#         for group in self.group_order:
#             if self.evaluations[group] > other.evaluations[group]:
#                 return True
#             elif self.evaluations[group] < other.evaluations[group]:
#                 return False
# 
#         # All group ratings were equal -- compare good ratios
#         for group in self.group_order:
#             if self.evaluations[group].good_ratio > other.evaluations[group].good_ratio:
#                 # greater
#                 return True
#             elif self.evaluations[group].good_ratio < other.evaluations[group].good_ratio:
#                 # less
#                 return False
# 
#         # all good ratios were equal
#         return False
# 
#     def __ge__(self, other):
#         return self > other or self == other
# 
#     def __iter__(self):
#         for group in self.group_order:
#             yield group, self.evaluations[group]
# 
#     @property
#     def rating(self):
#         if not self.evaluations:
#             return Rating('neutral')
#         return min(self.evaluations.values()).group_rating


import gzip
import os
import random
import string
from collections import OrderedDict
from datetime import datetime
from tldextract import extract
from typing import Iterable, Tuple, Union
from uuid import uuid4
from django.conf import settings
from django.contrib.auth import get_user_model
from django.contrib.postgres import fields as postgres_fields
from django.db import models, transaction
from django.db.models import Count, Prefetch, QuerySet
from django.db.models.expressions import RawSQL
from django.utils import timezone
from django.utils.functional import cached_property
from privacyscore.evaluation.site_evaluation import SiteEvaluation
        from privacyscore.scanner.tasks import schedule_scan
        from privacyscore.evaluation.evaluation import evaluate_result
        from privacyscore.evaluation.evaluation import evaluate_result
                scan_host=scan_host,
                test=test,
                identifier=identifier,
                mime_type=mime_type,
                data=data)

    def retrieve(self) -> bytes:
        """Retrieve the raw data."""
        if self.in_db:
            if isinstance(self.data, memoryview):
                return self.data.tobytes()
            return self.data
        path = os.path.join(settings.RAW_DATA_DIR, self.file_name)
        if path.endswith('.gz'):
            with gzip.open(path, 'rb') as f:
                return f.read()
        with open(path, 'rb') as f:
            return f.read()


class ScanResult(models.Model):
    """A single scan result key-value pair."""
    scan = models.OneToOneField(
        Scan, on_delete=models.CASCADE, related_name='result')

    result = postgres_fields.JSONField(null=True, blank=True)

    def __str__(self) -> str:
        return '{}'.format(str(self.scan))


# Path: privacyscore/evaluation/site_evaluation.py
# class SiteEvaluation:
#     """
#     An evaluation for a site. It contains of multiple group evaluations as well
#     as an ordering of the groups used for ranking/comparison.
# 
#     It is required that each group defined in groups is present in evaluations
#     and vice versa.
#     """
#     # evaluations  : Dict[str, GroupEvaluation]  # GroupEvaluation for each group
#     # group_order  : list  # The priority order of the groups
#     rateable = True
# 
#     def __init__(self, evaluations: Dict[str, GroupEvaluation], group_order: list):
#         self.evaluations = evaluations
#         self.group_order = group_order
# 
#     def __str__(self) -> str:
#         return '; '.join(
#             '{}: {}'.format(group, str(self.evaluations[group]))
#             for group in self.group_order)
# 
#     def __repr__(self) -> str:
#         return '<SiteEvaluation {}>'.format(str(self))
# 
#     def __eq__(self, other) -> bool:
#         if (self.rateable and not other.rateable or
#                 other.rateable and not self.rateable):
#             return False
#         for group in self.group_order:
#             if (self.evaluations[group] != other.evaluations[group] or
#                     self.evaluations[group].good_ratio != other.evaluations[group].good_ratio):
#                 return False
#         return True
# 
#     def __lt__(self, other):
#         if self.rateable and not other.rateable:
#             return False
#         if not self.rateable and other.rateable:
#             return True
#         for group in self.group_order:
#             if self.evaluations[group] < other.evaluations[group]:
#                 return True
#             elif self.evaluations[group] > other.evaluations[group]:
#                 return False
# 
#         # All group ratings were equal -- compare good ratios
#         for group in self.group_order:
#             if self.evaluations[group].good_ratio < other.evaluations[group].good_ratio:
#                 # less
#                 return True
#             elif self.evaluations[group].good_ratio > other.evaluations[group].good_ratio:
#                 # greater
#                 return False
# 
#         # all good ratios were equal
#         return False
# 
#     def __le__(self, other):
#         return self < other or self == other
# 
#     def __gt__(self, other):
#         """
#         The groups are compared group-wise ordered by the given group priority.
#         If all groups are identical, the good ratios of the groups are compared.
#         If a compared group is exactly identical, the next group is checked.
#         """
#         if self.rateable and not other.rateable:
#             return True
#         if not self.rateable and other.rateable:
#             return False
#         for group in self.group_order:
#             if self.evaluations[group] > other.evaluations[group]:
#                 return True
#             elif self.evaluations[group] < other.evaluations[group]:
#                 return False
# 
#         # All group ratings were equal -- compare good ratios
#         for group in self.group_order:
#             if self.evaluations[group].good_ratio > other.evaluations[group].good_ratio:
#                 # greater
#                 return True
#             elif self.evaluations[group].good_ratio < other.evaluations[group].good_ratio:
#                 # less
#                 return False
# 
#         # all good ratios were equal
#         return False
# 
#     def __ge__(self, other):
#         return self > other or self == other
# 
#     def __iter__(self):
#         for group in self.group_order:
#             yield group, self.evaluations[group]
# 
#     @property
#     def rating(self):
#         if not self.evaluations:
#             return Rating('neutral')
#         return min(self.evaluations.values()).group_rating


# Path: privacyscore/backend/models.py
import gzip
import os
import random
import string
from collections import OrderedDict
from datetime import datetime
from tldextract import extract
from typing import Iterable, Tuple, Union
from uuid import uuid4
from django.conf import settings
from django.contrib.auth import get_user_model
from django.contrib.postgres import fields as postgres_fields
from django.db import models, transaction
from django.db.models import Count, Prefetch, QuerySet
from django.db.models.expressions import RawSQL
from django.utils import timezone
from django.utils.functional import cached_property
from privacyscore.evaluation.site_evaluation import SiteEvaluation
        from privacyscore.scanner.tasks import schedule_scan
        from privacyscore.evaluation.evaluation import evaluate_result
        from privacyscore.evaluation.evaluation import evaluate_result

                scan_host=scan_host,
                test=test,
                identifier=identifier,
                mime_type=mime_type,
                data=data)

    def retrieve(self) -> bytes:
        """Retrieve the raw data."""
        if self.in_db:
            if isinstance(self.data, memoryview):
                return self.data.tobytes()
            return self.data
        path = os.path.join(settings.RAW_DATA_DIR, self.file_name)
        if path.endswith('.gz'):
            with gzip.open(path, 'rb') as f:
                return f.read()
        with open(path, 'rb') as f:
            return f.read()


class ScanResult(models.Model):
    """A single scan result key-value pair."""
    scan = models.OneToOneField(
        Scan, on_delete=models.CASCADE, related_name='result')

    result = postgres_fields.JSONField(null=True, blank=True)

    def __str__(self) -> str:
        return '{}'.format(str(self.scan))


    def evaluate(self, group_order: list) -> SiteEvaluation: