<commit_before># -*- coding: utf-8 -*-
from openprocurement.api.utils import (
    get_now
)
from openprocurement.tender.core.utils import (
    optendersresource
)
from openprocurement.tender.belowthreshold.views.question import TenderQuestionResource

@optendersresource(name='aboveThresholdUA:Tender Questions',
                   collection_path='/tenders/{tender_id}/questions',
                   path='/tenders/{tender_id}/questions/{question_id}',
                   procurementMethodType='aboveThresholdUA',
                   description="Tender questions")
class TenderUaQuestionResource(TenderQuestionResource):

    def validate_question(self, operation):
        """ TODO move validators
        This class is inherited from below package, but validate_question function has different validators.
        For now, we have no way to use different validators on methods according to procedure type.
        """
        tender = self.request.validated['tender']
        now = get_now()
        if operation == 'add' and (now < tender.enquiryPeriod.startDate or now > tender.enquiryPeriod.endDate):
            self.request.errors.add('body', 'data', 'Can add question only in enquiryPeriod')
            self.request.errors.status = 403
            return
        if operation == 'update' and tender.status != 'active.tendering':
            self.request.errors.add('body', 'data', 'Can\'t update question in current ({}) tender status'.format(tender.status))
            self.request.errors.status = 403
            return
        question = self.request.validated['question']
        items_dict = {i.id: i.relatedLot for i in tender.items}
        if any([
            i.status != 'active'
            for i in tender.lots
            if question.questionOf == 'lot' and i.id == question.relatedItem or question.questionOf == 'item' and i.id == items_dict[question.relatedItem]
        ]):
            self.request.errors.add('body', 'data', 'Can {} question only in active lot status'.format(operation))
            self.request.errors.status = 403
            return
        if operation == 'update' and now > tender.enquiryPeriod.clarificationsUntil:
            self.request.errors.add('body', 'data', 'Can update question only before enquiryPeriod.clarificationsUntil')
            self.request.errors.status = 403
            return
        return True
<commit_msg>Update validators in question view<commit_after># -*- coding: utf-8 -*-
from openprocurement.api.utils import (
    get_now, raise_operation_error
)
from openprocurement.tender.core.utils import (
    optendersresource
)
from openprocurement.tender.belowthreshold.views.question import TenderQuestionResource

@optendersresource(name='aboveThresholdUA:Tender Questions',
                   collection_path='/tenders/{tender_id}/questions',
                   path='/tenders/{tender_id}/questions/{question_id}',
                   procurementMethodType='aboveThresholdUA',
                   description="Tender questions")
class TenderUaQuestionResource(TenderQuestionResource):

    def validate_question(self, operation):
        """ TODO move validators
        This class is inherited from below package, but validate_question function has different validators.
        For now, we have no way to use different validators on methods according to procedure type.
        """
        tender = self.request.validated['tender']
        now = get_now()
        if operation == 'add' and (now < tender.enquiryPeriod.startDate or now > tender.enquiryPeriod.endDate):
            raise_operation_error(self.request, 'Can add question only in enquiryPeriod')
        if operation == 'update' and tender.status != 'active.tendering':
            raise_operation_error(self.request, 'Can\'t update question in current ({}) tender status'.format(tender.status))
        question = self.request.validated['question']
        items_dict = {i.id: i.relatedLot for i in tender.items}
        if any([
            i.status != 'active'
            for i in tender.lots
            if question.questionOf == 'lot' and i.id == question.relatedItem or question.questionOf == 'item' and i.id == items_dict[question.relatedItem]
        ]):
            raise_operation_error(self.request, 'Can {} question only in active lot status'.format(operation))
        if operation == 'update' and now > tender.enquiryPeriod.clarificationsUntil:
            raise_operation_error(self.request, 'Can update question only before enquiryPeriod.clarificationsUntil')
        return True
<|endoftext|>


<commit_before># -*- coding: utf-8 -*-
#
# django-codenerix-pos
#
# Copyright 2017 Centrologic Computational Logistic Center S.L.
#
# Project URL : http://www.codenerix.com
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

import json
import uuid
import hashlib
from channels import Channel

from django.db import models
from django.utils.encoding import smart_text
from django.utils.translation import ugettext_lazy as _
from django.db.models import Q

from jsonfield import JSONField

from codenerix_payments.models import PaymentRequest

from codenerix.models import CodenerixModel
from codenerix_extensions.corporate.models import CorporateImage
from codenerix_products.models import ProductFinal
from codenerix_invoicing.models import BillingSeries
from codenerix_extensions.lib.cryptography import AESCipher

from codenerix.models import GenInterface
from codenerix.models_people import GenRole
from codenerix_extensions.helpers import get_external_method
from codenerix_pos.settings import CDNX_POS_PERMISSIONS

"""
Plant
    Zones
    CorporateImage
    BillingSeries

Zones
    POS (pantalla fisica)
        Hardware Los que tengo (muchos)
        Hardware Los que puedo usar (muchos)
        token --- pos client (software instalado, minimo el id)
        Salable products (POSProduct)

    Slot (mesas)

Hardware (ticket, dni, caja, dispositivo de firma, dispositivo de consulta)
    nombre
    configuracion
    tipo (ticket, dni, caja, firma, consulta)
    token
"""

# Changing this KEYS will affect to any client beacuse it is used for communication as a standard
KIND_POSHARDWARE_TICKET = "TICKET"
KIND_POSHARDWARE = (
    (KIND_POSHARDWARE_TICKET, _("Ticket printer")),
    ("DNIE", _("DNIe card reader")),
    ("CASH", _("Cash drawer")),
    ("WEIGHT", _("Weight")),
    ("SIGN", _("Signature pad")),
    ("QUERY", _("Query service (Ex: Barcode)")),  # Barcode reader, Point of Information for clients, etc...
)

class POSPlant(CodenerixModel):
    """
    Plant
    """
    corporate_image = models.ForeignKey(CorporateImage, related_name='posplants', verbose_name=_("Corporate image"), blank=False, null=False)
    billing_series = models.ForeignKey(BillingSeries, related_name='posplants', verbose_name='Billing series', blank=False, null=False)
    name = models.CharField(_("Name"), max_length=250, blank=False, null=False, unique=True)

    def __unicode__(self):
        return self.__str__()

    def __str__(self):
        return u"{}".format(smart_text(self.name))

    def __fields__(self, info):
        fields = []
        fields.append(('name', _("Name")))
        return fields

class POSZone(CodenerixModel):
    """
    Zone
    """
    plant = models.ForeignKey(POSPlant, related_name='zones', verbose_name=_("Plant"), blank=False, null=False)
    name = models.CharField(_("Name"), max_length=250, blank=False, null=False, unique=True)

    def __unicode__(self):
        return self.__str__()

    def __str__(self):
        return u"{}".format(smart_text(self.name))

    def __fields__(self, info):
        fields = []
        fields.append(('plant', _("Plant")))
        fields.append(('name', _("Name")))
        return fields

class POSHardware(CodenerixModel):
    """
    Hardware
    """
    pos = models.ForeignKey("POS", related_name='hardwares', verbose_name=_("Hardware"), blank=True, null=True)
    kind = models.CharField(_("Kind"), max_length=6, choices=KIND_POSHARDWARE, blank=False, null=False)
    name = models.CharField(_("Name"), max_length=250, blank=False, null=False, unique=True)
    enable = models.BooleanField(_('Enable'), default=True)
    uuid = models.UUIDField(default=uuid.uuid4, editable=False, unique=True)
    config = JSONField(_("config"), blank=True, null=True)
    value = JSONField(_("config"), blank=True, null=True)

    def __unicode__(self):
        return self.__str__()

    def __str__(self):
        return u"{}".format(smart_text(self.name))

    def __fields__(self, info):
        fields = []
        fields.append(('pos', _("POS")))
        fields.append(('get_kind_display', _("Kind")))
        fields.append(('name', _("Name")))
        fields.append(('enable', _("Enable")))
        fields.append(('uuid', _("UUID")))
        fields.append(('config', _("Config")))
        fields.append(('value', _("Value")))
        return fields

    def save(self, *args, **kwargs):
        if 'doreset' in kwargs:
            doreset = kwargs.pop('doreset')
        else:
            doreset = True

        result = super(POSHardware, self).save(*args, **kwargs)
        if doreset:
            self.pos.reset_client()
        return result

    def recv(self, msg):
        self.value = msg
        self.save(doreset=False)

    def send(self, msg=None, ref=None):
        '''
        Example of msg for each POSHARDWARE:
            TICKET: {'data': 'print this text, process thid dictionary or take my money'}
            CASH:   {'data': '...ANYTHING except None to open the Cash Drawer...' }
            DNIE:   {'data': '...ANYTHING except None to get again data from DNIe if connected...' }
            WEIGHT: {'data': '...ANYTHING except None to get the value of the last wegith' }
            SIGN:   --- NOT ALLOWED / NOT AVAILABLE ---
            QUERY:  --- NOT ALLOWED / NOT AVAILABLE ---
        '''
        if self.kind == 'TICKET':
            if msg is not None:
                data = msg
            else:
                raise IOError("Nothing to print???")
        elif self.kind in ['CASH', 'DNIE', 'WEIGHT']:
            data = 'DOIT'
        else:
            raise IOError("This Hardware can not send data anywhere")

        # Say it to send this message
        self.pos.send(data, ref, self.uuid)

class POS(CodenerixModel):
    '''
    Point of Service
    '''
    name = models.CharField(_("Name"), max_length=250, blank=False, null=False, unique=True)
    uuid = models.UUIDField(default=uuid.uuid4, editable=False, unique=True)
    key = models.CharField(_("Key"), max_length=32, blank=False, null=False, unique=True)
    zone = models.ForeignKey(POSZone, related_name='poss', verbose_name=_("Zone"))
    payments = models.ManyToManyField(PaymentRequest, related_name='poss', verbose_name=_("Payments"), blank=True, null=True)
    channel = models.CharField(_("Channel"), max_length=50, blank=True, null=True, unique=True, editable=False)
    # Hardware that can use
    hardware = models.ManyToManyField(POSHardware, related_name='poss', verbose_name=_("Hardware it can use"), blank=True, null=True)

    def __unicode__(self):
        return self.__str__()

    def __str__(self):
        return u"{}".format(smart_text(self.name))

    def __fields__(self, info):
        fields = []
        fields.append(('zone', _("Zone")))
        fields.append(('name', _("Name")))
        fields.append(('uuid', _("UUID")))
        fields.append(('key', _("Key")))
        fields.append(('channel', _("Channel")))
        fields.append(('hardware', _("Hardware")))
        return fields

    def save(self, *args, **kwargs):
        if 'doreset' in kwargs:
            doreset = kwargs.pop('doreset')
        else:
            doreset = True
        result = super(POS, self).save(*args, **kwargs)
        if doreset:
            self.reset_client()
        return result

    def reset_client(self):
        self.send({'action': 'reset'})

    def ping(self, uid=None):
        if uid is None:
            uidtxt = None
        else:
            uidtxt = uid.hex
        ref = hashlib.sha1(uuid.uuid4().hex.encode('utf-8')).hexdigest()
        self.send({'action': 'ping', 'ref': ref, 'uuid': uidtxt})
        return ref

    def send(self, data, ref=None, uid=None):

        if uid:
            # Message for some client
            message = {
                'action': 'msg',
                'message': {
                    'data': data,
                },
                'uuid': uid.hex,
            }
        else:
            # Message for the server
            message = data

        # Send message
        crypto = AESCipher()
        msg = json.dumps({'request': message, 'ref': ref})
        request = crypto.encrypt(msg, self.key).decode('utf-8')
        data = json.dumps({'message': request})
        Channel(self.channel).send({'text': data})

class POSSlot(CodenerixModel):
    '''
    Slots for Point of Service
    '''
    zone = models.ForeignKey(POSZone, related_name='slots', verbose_name=_("Zone"))
    name = models.CharField(_("Name"), max_length=250, blank=False, null=False, unique=True)
    # orders = models.ManyToManyField(SalesOrder, related_name='slots', editable=False, verbose_name=_("Orders"))
    pos_x = models.IntegerField(_('Pos X'), null=True, blank=True, default=None, editable=False)
    pos_y = models.IntegerField(_('Pos Y'), null=True, blank=True, default=None, editable=False)

    def __unicode__(self):
        return self.__str__()

    def __str__(self):
        return u"{}".format(smart_text(self.name))

    def __fields__(self, info):
        fields = []
        fields.append(('zone', _("Zone")))
        fields.append(('name', _("Name")))
        # fields.append(('orders', _("Orders")))
        return fields

class POSProduct(CodenerixModel):
    """
    Salable products in the POS
    """
    pos = models.ForeignKey(POS, related_name='posproducts', verbose_name=_("POS"))
    product = models.ForeignKey(ProductFinal, related_name='posproducts', verbose_name=_("Product"))
    enable = models.BooleanField(_('Enable'), default=True)

    class Meta(CodenerixModel.Meta):
        unique_together = (("pos", "product"))

    def __unicode__(self):
        return self.__str__()

    def __str__(self):
        return u"{} {}".format(smart_text(self.pos), smart_text(self.product))

    def __fields__(self, info):
        fields = []
        fields.append(('pos', _("POS")))
        fields.append(('product', _("Product")))
        fields.append(('enable', _("Enable")))
        return fields

class POSLog(CodenerixModel):
    """
    LOG for POS
    """
    pos = models.ForeignKey(POS, related_name='logs', verbose_name=_("POS"), editable=False, null=True)
    poshw = models.ForeignKey(POSHardware, related_name='logs', verbose_name=_("POS"), editable=False, null=True)
    uuid = models.UUIDField(default=uuid.uuid4, editable=False)
    log = JSONField(_("LOG"), blank=True, null=True)

    def __unicode__(self):
        return self.__str__()

    def __str__(self):
        return self.uuid.hex

    def __fields__(self, info):
        fields = []
        fields.append(('created', _("Created")))
        fields.append(('uuid', _("UUID")))
        fields.append(('pos', _("POS")))
        fields.append(('poshw', _("POSHardware")))
        fields.append(('log', _("Log")))
        return fields

    def __searchF__(self, info):

        # Build both lists
        poss = [(pos.pk, pos.name) for pos in POS.objects.all()]
        poshws = [(poshw.pk, poshw.name) for poshw in POSHardware.objects.all()]

        tf = {}
        tf['uuid'] = (_('UUID'), lambda x: Q(uuid__icontains=x), 'input')
        tf['pos'] = (_('POS'), lambda x: Q(pos__pk=x), poss)
        tf['poshw'] = (_('Hardware'), lambda x: Q(poshw__pk=x), poshws)
        return tf

# ############################
class ABSTRACT_GenPOSOperator(models.Model):  # META: Abstract class

    class Meta(object):
        abstract = True

class POSOperator(GenRole, CodenerixModel):
    class CodenerixMeta:
        abstract = ABSTRACT_GenPOSOperator
        rol_groups = {
            'POSOperator': CDNX_POS_PERMISSIONS['operator'],
        }
        rol_permissions = [
        ]

        force_methods = {
            'foreignkey_posoperator': ('CDNX_get_fk_info_posoperator', _('---')),
        }

    pos = models.ForeignKey(POS, related_name='pos_operators', verbose_name=_('POS'))
    enable = models.BooleanField(_("Enable"), blank=False, null=False, default=True)

    @staticmethod
    def foreignkey_external():
        return get_external_method(POSOperator, POSOperator.CodenerixMeta.force_methods['foreignkey_posoperator'][0])

    def __unicode__(self):
        return u"{}".format(smart_text(self.pk))

    def __str__(self):
        return self.__unicode__()

    def __fields__(self, info):
        fields = []
        fields.append(('pos', _("POS")))
        fields.append(('enable', _("Enable")))
        fields = get_external_method(POSOperator, '__fields_posoperator__', info, fields)
        return fields

# operators
class GenPOSOperator(GenInterface, ABSTRACT_GenPOSOperator):  # META: Abstract class
    pos_operator = models.OneToOneField(POSOperator, related_name='external', verbose_name=_("POS Operator"), null=True, on_delete=models.SET_NULL, blank=True)

    class Meta(GenInterface.Meta, ABSTRACT_GenPOSOperator.Meta):
        abstract = True

    @classmethod
    def permissions(cls):
        group = 'POSOperator'
        perms = []
        print(cls.posoperator.field.related_model)

        return None

        # print({group: {'gperm': None, 'dperm': perms, 'model': None},})
<commit_msg>Constants and new method POS.have_cash_drawer()<commit_after># -*- coding: utf-8 -*-
#
# django-codenerix-pos
#
# Copyright 2017 Centrologic Computational Logistic Center S.L.
#
# Project URL : http://www.codenerix.com
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

import json
import uuid
import hashlib
from channels import Channel

from django.db import models
from django.utils.encoding import smart_text
from django.utils.translation import ugettext_lazy as _
from django.db.models import Q

from jsonfield import JSONField

from codenerix_payments.models import PaymentRequest

from codenerix.models import CodenerixModel
from codenerix_extensions.corporate.models import CorporateImage
from codenerix_products.models import ProductFinal
from codenerix_invoicing.models import BillingSeries
from codenerix_extensions.lib.cryptography import AESCipher

from codenerix.models import GenInterface
from codenerix.models_people import GenRole
from codenerix_extensions.helpers import get_external_method
from codenerix_pos.settings import CDNX_POS_PERMISSIONS

"""
Plant
    Zones
    CorporateImage
    BillingSeries

Zones
    POS (pantalla fisica)
        Hardware Los que tengo (muchos)
        Hardware Los que puedo usar (muchos)
        token --- pos client (software instalado, minimo el id)
        Salable products (POSProduct)

    Slot (mesas)

Hardware (ticket, dni, caja, dispositivo de firma, dispositivo de consulta)
    nombre
    configuracion
    tipo (ticket, dni, caja, firma, consulta)
    token
"""

# Changing this KEYS will affect to any client beacuse it is used for communication as a standard
KIND_POSHARDWARE_TICKET = "TICKET"
KIND_POSHARDWARE_DNIE = "DNIE"
KIND_POSHARDWARE_CASH = "CASH"
KIND_POSHARDWARE_WEIGHT = "WEIGHT"
KIND_POSHARDWARE_SIGN = "SIGN"
KIND_POSHARDWARE_QUERY = "QUERY"

KIND_POSHARDWARE = (
    (KIND_POSHARDWARE_TICKET, _("Ticket printer")),
    (KIND_POSHARDWARE_DNIE, _("DNIe card reader")),
    (KIND_POSHARDWARE_CASH, _("Cash drawer")),
    (KIND_POSHARDWARE_WEIGHT, _("Weight")),
    (KIND_POSHARDWARE_SIGN, _("Signature pad")),
    (KIND_POSHARDWARE_QUERY, _("Query service (Ex: Barcode)")),  # Barcode reader, Point of Information for clients, etc...
)

class POSPlant(CodenerixModel):
    """
    Plant
    """
    corporate_image = models.ForeignKey(CorporateImage, related_name='posplants', verbose_name=_("Corporate image"), blank=False, null=False)
    billing_series = models.ForeignKey(BillingSeries, related_name='posplants', verbose_name='Billing series', blank=False, null=False)
    name = models.CharField(_("Name"), max_length=250, blank=False, null=False, unique=True)

    def __unicode__(self):
        return self.__str__()

    def __str__(self):
        return u"{}".format(smart_text(self.name))

    def __fields__(self, info):
        fields = []
        fields.append(('name', _("Name")))
        return fields

class POSZone(CodenerixModel):
    """
    Zone
    """
    plant = models.ForeignKey(POSPlant, related_name='zones', verbose_name=_("Plant"), blank=False, null=False)
    name = models.CharField(_("Name"), max_length=250, blank=False, null=False, unique=True)

    def __unicode__(self):
        return self.__str__()

    def __str__(self):
        return u"{}".format(smart_text(self.name))

    def __fields__(self, info):
        fields = []
        fields.append(('plant', _("Plant")))
        fields.append(('name', _("Name")))
        return fields

class POSHardware(CodenerixModel):
    """
    Hardware
    """
    pos = models.ForeignKey("POS", related_name='hardwares', verbose_name=_("Hardware"), blank=True, null=True)
    kind = models.CharField(_("Kind"), max_length=6, choices=KIND_POSHARDWARE, blank=False, null=False)
    name = models.CharField(_("Name"), max_length=250, blank=False, null=False, unique=True)
    enable = models.BooleanField(_('Enable'), default=True)
    uuid = models.UUIDField(default=uuid.uuid4, editable=False, unique=True)
    config = JSONField(_("config"), blank=True, null=True)
    value = JSONField(_("config"), blank=True, null=True)

    def __unicode__(self):
        return self.__str__()

    def __str__(self):
        return u"{}".format(smart_text(self.name))

    def __fields__(self, info):
        fields = []
        fields.append(('pos', _("POS")))
        fields.append(('get_kind_display', _("Kind")))
        fields.append(('name', _("Name")))
        fields.append(('enable', _("Enable")))
        fields.append(('uuid', _("UUID")))
        fields.append(('config', _("Config")))
        fields.append(('value', _("Value")))
        return fields

    def save(self, *args, **kwargs):
        if 'doreset' in kwargs:
            doreset = kwargs.pop('doreset')
        else:
            doreset = True

        result = super(POSHardware, self).save(*args, **kwargs)
        if doreset:
            self.pos.reset_client()
        return result

    def recv(self, msg):
        self.value = msg
        self.save(doreset=False)

    def send(self, msg=None, ref=None):
        '''
        Example of msg for each POSHARDWARE:
            TICKET: {'data': 'print this text, process thid dictionary or take my money'}
            CASH:   {'data': '...ANYTHING except None to open the Cash Drawer...' }
            DNIE:   {'data': '...ANYTHING except None to get again data from DNIe if connected...' }
            WEIGHT: {'data': '...ANYTHING except None to get the value of the last wegith' }
            SIGN:   --- NOT ALLOWED / NOT AVAILABLE ---
            QUERY:  --- NOT ALLOWED / NOT AVAILABLE ---
        '''
        if self.kind == 'TICKET':
            if msg is not None:
                data = msg
            else:
                raise IOError("Nothing to print???")
        elif self.kind in ['CASH', 'DNIE', 'WEIGHT']:
            data = 'DOIT'
        else:
            raise IOError("This Hardware can not send data anywhere")

        # Say it to send this message
        self.pos.send(data, ref, self.uuid)

class POS(CodenerixModel):
    '''
    Point of Service
    '''
    name = models.CharField(_("Name"), max_length=250, blank=False, null=False, unique=True)
    uuid = models.UUIDField(default=uuid.uuid4, editable=False, unique=True)
    key = models.CharField(_("Key"), max_length=32, blank=False, null=False, unique=True)
    zone = models.ForeignKey(POSZone, related_name='poss', verbose_name=_("Zone"))
    payments = models.ManyToManyField(PaymentRequest, related_name='poss', verbose_name=_("Payments"), blank=True, null=True)
    channel = models.CharField(_("Channel"), max_length=50, blank=True, null=True, unique=True, editable=False)
    # Hardware that can use
    hardware = models.ManyToManyField(POSHardware, related_name='poss', verbose_name=_("Hardware it can use"), blank=True, null=True)

    def __unicode__(self):
        return self.__str__()

    def __str__(self):
        return u"{}".format(smart_text(self.name))

    def __fields__(self, info):
        fields = []
        fields.append(('zone', _("Zone")))
        fields.append(('name', _("Name")))
        fields.append(('uuid', _("UUID")))
        fields.append(('key', _("Key")))
        fields.append(('channel', _("Channel")))
        fields.append(('hardware', _("Hardware")))
        return fields

    def have_cash_drawer(self):
        return self.hardwares.filter(kind=KIND_POSHARDWARE_CASH).exists()

    def save(self, *args, **kwargs):
        if 'doreset' in kwargs:
            doreset = kwargs.pop('doreset')
        else:
            doreset = True
        result = super(POS, self).save(*args, **kwargs)
        if doreset:
            self.reset_client()
        return result

    def reset_client(self):
        self.send({'action': 'reset'})

    def ping(self, uid=None):
        if uid is None:
            uidtxt = None
        else:
            uidtxt = uid.hex
        ref = hashlib.sha1(uuid.uuid4().hex.encode('utf-8')).hexdigest()
        self.send({'action': 'ping', 'ref': ref, 'uuid': uidtxt})
        return ref

    def send(self, data, ref=None, uid=None):

        if uid:
            # Message for some client
            message = {
                'action': 'msg',
                'message': {
                    'data': data,
                },
                'uuid': uid.hex,
            }
        else:
            # Message for the server
            message = data

        # Send message
        crypto = AESCipher()
        msg = json.dumps({'request': message, 'ref': ref})
        request = crypto.encrypt(msg, self.key).decode('utf-8')
        data = json.dumps({'message': request})
        Channel(self.channel).send({'text': data})

class POSSlot(CodenerixModel):
    '''
    Slots for Point of Service
    '''
    zone = models.ForeignKey(POSZone, related_name='slots', verbose_name=_("Zone"))
    name = models.CharField(_("Name"), max_length=250, blank=False, null=False, unique=True)
    # orders = models.ManyToManyField(SalesOrder, related_name='slots', editable=False, verbose_name=_("Orders"))
    pos_x = models.IntegerField(_('Pos X'), null=True, blank=True, default=None, editable=False)
    pos_y = models.IntegerField(_('Pos Y'), null=True, blank=True, default=None, editable=False)

    def __unicode__(self):
        return self.__str__()

    def __str__(self):
        return u"{}".format(smart_text(self.name))

    def __fields__(self, info):
        fields = []
        fields.append(('zone', _("Zone")))
        fields.append(('name', _("Name")))
        # fields.append(('orders', _("Orders")))
        return fields

class POSProduct(CodenerixModel):
    """
    Salable products in the POS
    """
    pos = models.ForeignKey(POS, related_name='posproducts', verbose_name=_("POS"))
    product = models.ForeignKey(ProductFinal, related_name='posproducts', verbose_name=_("Product"))
    enable = models.BooleanField(_('Enable'), default=True)

    class Meta(CodenerixModel.Meta):
        unique_together = (("pos", "product"))

    def __unicode__(self):
        return self.__str__()

    def __str__(self):
        return u"{} {}".format(smart_text(self.pos), smart_text(self.product))

    def __fields__(self, info):
        fields = []
        fields.append(('pos', _("POS")))
        fields.append(('product', _("Product")))
        fields.append(('enable', _("Enable")))
        return fields

class POSLog(CodenerixModel):
    """
    LOG for POS
    """
    pos = models.ForeignKey(POS, related_name='logs', verbose_name=_("POS"), editable=False, null=True)
    poshw = models.ForeignKey(POSHardware, related_name='logs', verbose_name=_("POS"), editable=False, null=True)
    uuid = models.UUIDField(default=uuid.uuid4, editable=False)
    log = JSONField(_("LOG"), blank=True, null=True)

    def __unicode__(self):
        return self.__str__()

    def __str__(self):
        return self.uuid.hex

    def __fields__(self, info):
        fields = []
        fields.append(('created', _("Created")))
        fields.append(('uuid', _("UUID")))
        fields.append(('pos', _("POS")))
        fields.append(('poshw', _("POSHardware")))
        fields.append(('log', _("Log")))
        return fields

    def __searchF__(self, info):

        # Build both lists
        poss = [(pos.pk, pos.name) for pos in POS.objects.all()]
        poshws = [(poshw.pk, poshw.name) for poshw in POSHardware.objects.all()]

        tf = {}
        tf['uuid'] = (_('UUID'), lambda x: Q(uuid__icontains=x), 'input')
        tf['pos'] = (_('POS'), lambda x: Q(pos__pk=x), poss)
        tf['poshw'] = (_('Hardware'), lambda x: Q(poshw__pk=x), poshws)
        return tf

# ############################
class ABSTRACT_GenPOSOperator(models.Model):  # META: Abstract class

    class Meta(object):
        abstract = True

class POSOperator(GenRole, CodenerixModel):
    class CodenerixMeta:
        abstract = ABSTRACT_GenPOSOperator
        rol_groups = {
            'POSOperator': CDNX_POS_PERMISSIONS['operator'],
        }
        rol_permissions = [
        ]

        force_methods = {
            'foreignkey_posoperator': ('CDNX_get_fk_info_posoperator', _('---')),
        }

    pos = models.ForeignKey(POS, related_name='pos_operators', verbose_name=_('POS'))
    enable = models.BooleanField(_("Enable"), blank=False, null=False, default=True)

    @staticmethod
    def foreignkey_external():
        return get_external_method(POSOperator, POSOperator.CodenerixMeta.force_methods['foreignkey_posoperator'][0])

    def __unicode__(self):
        return u"{}".format(smart_text(self.pk))

    def __str__(self):
        return self.__unicode__()

    def __fields__(self, info):
        fields = []
        fields.append(('pos', _("POS")))
        fields.append(('enable', _("Enable")))
        fields = get_external_method(POSOperator, '__fields_posoperator__', info, fields)
        return fields

# operators
class GenPOSOperator(GenInterface, ABSTRACT_GenPOSOperator):  # META: Abstract class
    pos_operator = models.OneToOneField(POSOperator, related_name='external', verbose_name=_("POS Operator"), null=True, on_delete=models.SET_NULL, blank=True)

    class Meta(GenInterface.Meta, ABSTRACT_GenPOSOperator.Meta):
        abstract = True

    @classmethod
    def permissions(cls):
        group = 'POSOperator'
        perms = []
        print(cls.posoperator.field.related_model)

        return None

        # print({group: {'gperm': None, 'dperm': perms, 'model': None},})
<|endoftext|>


<commit_before>"""
Models for actual Polling Stations and Polling Districts!
"""
from itertools import groupby
import urllib.parse

from django.contrib.gis.db import models
from django.core.exceptions import ObjectDoesNotExist
from django.db.models import JSONField
from django.utils.translation import ugettext as _

from core.opening_times import OpeningTimes
from councils.models import Council
from uk_geo_utils.helpers import Postcode

class PollingDistrict(models.Model):
    name = models.CharField(blank=True, null=True, max_length=255)
    council = models.ForeignKey(Council, null=True, on_delete=models.CASCADE)
    internal_council_id = models.CharField(blank=True, max_length=100)
    extra_id = models.CharField(blank=True, null=True, max_length=100)
    area = models.MultiPolygonField(null=True, blank=True)
    # This is NOT a FK, as we might not have the polling station at
    # the point of import
    polling_station_id = models.CharField(blank=True, max_length=255)

    class Meta:
        unique_together = ("council", "internal_council_id")

    objects = models.Manager()

    def __unicode__(self):
        name = self.name or "Unnamed"
        return "%s (%s)" % (name, self.council)

class PollingStation(models.Model):
    council = models.ForeignKey(
        Council, null=True, db_index=True, on_delete=models.CASCADE
    )
    internal_council_id = models.CharField(blank=True, max_length=100, db_index=True)
    postcode = models.CharField(blank=True, null=True, max_length=100)
    address = models.TextField(blank=True, null=True)
    location = models.PointField(null=True, blank=True)
    # This is NOT a FK, as we might not have the polling district at
    # the point of import
    polling_district_id = models.CharField(blank=True, max_length=255)

    class Meta:
        unique_together = ("council", "internal_council_id")
        index_together = [
            ["council", "internal_council_id"],
            ["council", "polling_district_id"],
        ]

    def __str__(self):
        return "{0} ({1})".format(self.internal_council_id, self.council)

    @property
    def formatted_address(self):
        if not self.address:
            return None
        return "\n".join([x[0].strip() for x in groupby(self.address.split(","))])

class CustomFinderManager(models.Manager):
    def get_custom_finder(self, geocoder, postcode):
        try:
            code = geocoder.get_code("lad")
            if code.startswith("N"):
                finder = self.get(pk="N07000001")
                finder.message = _(finder.message)
                """
                EONI's poling station finder requires postcode to have a space :(
                http://www.eoni.org.uk/Offices/Postcode-Search-Results?postcode=BT5+7TQ
                will produce a result, whereas
                http://www.eoni.org.uk/Offices/Postcode-Search-Results?postcode=BT57TQ
                will not.

                We might need to take a more sophisticated approach as we add more custom finders
                that accept postcodes (e.g: a postcode format flag in the database).
                At the moment I only have this one to work with.
                """
                finder.encoded_postcode = urllib.parse.quote(
                    Postcode(postcode).with_space
                )
            else:
                finder = self.get(pk=code)

            return finder
        except ObjectDoesNotExist:
            return None

class CustomFinder(models.Model):
    """
    Store details of areas that have their own
    custom polling station finders
    and/or a message that we might want to show.

    Example content:

    record = CustomFinder(
        area_code='E07000082'
        base_url='https://stroud.maps.arcgis.com/apps/webappviewer/index.html?id=ea6bf4b3655542c1a05c8d7e87d32bb1'
        can_pass_postcode=False
        message="Stroud District Council has its own polling station finder:"
    )
    record.save()

    record = CustomFinder(
        area_code='W06000008'
        base_url=''
        can_pass_postcode=False
        message='
We're working on it!
Ceredigion Council have provided polling station data. It will be available soon.'
    )
    record.save()

    record = CustomFinder(
        area_code='N07000001'
        base_url='http://www.eoni.org.uk/Offices/Postcode-Search-Results?postcode='
        can_pass_postcode=True
        message='The Electoral Office of Northern Ireland has its own polling station finder:'
    )
    record.save()
    """

    area_code = models.CharField(
        max_length=9, primary_key=True, help_text="The GSS code for this area"
    )
    base_url = models.CharField(
        blank=True,
        max_length=255,
        help_text="The landing page for the polling station finder",
    )
    can_pass_postcode = models.BooleanField(
        default=False, help_text="Does the URL have '?postcode=' in it?"
    )
    message = models.TextField(
        blank=True, default="This council has its own polling station finder:"
    )

    objects = CustomFinderManager()

class AdvanceVotingStation(models.Model):
    name = models.CharField(max_length=100)
    postcode = models.CharField(blank=True, null=True, max_length=100)
    address = models.TextField(blank=True, null=True)
    location = models.PointField(null=True, blank=True)
    opening_times = JSONField(null=True)
    council = models.ForeignKey(Council, null=True, on_delete=models.CASCADE)

    def __str__(self):
        return f"{self.name} ({self.postcode})"

    def save(self, **kwargs):
        self.address = "\n".join(
            [line.lstrip() for line in self.address.split("\n")]
        ).strip()
        return super().save(**kwargs)

    @property
    def opening_times_table(self):
        return OpeningTimes.from_dict(self.opening_times).as_table()
<commit_msg>Only show NI CustomFinder when there is no NI data<commit_after>"""
Models for actual Polling Stations and Polling Districts!
"""
from itertools import groupby
import urllib.parse

from django.contrib.gis.db import models
from django.core.exceptions import ObjectDoesNotExist
from django.db.models import JSONField
from django.utils.translation import ugettext as _

from core.opening_times import OpeningTimes
from councils.models import Council
from uk_geo_utils.helpers import Postcode

class PollingDistrict(models.Model):
    name = models.CharField(blank=True, null=True, max_length=255)
    council = models.ForeignKey(Council, null=True, on_delete=models.CASCADE)
    internal_council_id = models.CharField(blank=True, max_length=100)
    extra_id = models.CharField(blank=True, null=True, max_length=100)
    area = models.MultiPolygonField(null=True, blank=True)
    # This is NOT a FK, as we might not have the polling station at
    # the point of import
    polling_station_id = models.CharField(blank=True, max_length=255)

    class Meta:
        unique_together = ("council", "internal_council_id")

    objects = models.Manager()

    def __unicode__(self):
        name = self.name or "Unnamed"
        return "%s (%s)" % (name, self.council)

class PollingStation(models.Model):
    council = models.ForeignKey(
        Council, null=True, db_index=True, on_delete=models.CASCADE
    )
    internal_council_id = models.CharField(blank=True, max_length=100, db_index=True)
    postcode = models.CharField(blank=True, null=True, max_length=100)
    address = models.TextField(blank=True, null=True)
    location = models.PointField(null=True, blank=True)
    # This is NOT a FK, as we might not have the polling district at
    # the point of import
    polling_district_id = models.CharField(blank=True, max_length=255)

    class Meta:
        unique_together = ("council", "internal_council_id")
        index_together = [
            ["council", "internal_council_id"],
            ["council", "polling_district_id"],
        ]

    def __str__(self):
        return "{0} ({1})".format(self.internal_council_id, self.council)

    @property
    def formatted_address(self):
        if not self.address:
            return None
        return "\n".join([x[0].strip() for x in groupby(self.address.split(","))])

class CustomFinderManager(models.Manager):
    def get_custom_finder(self, geocoder, postcode):
        try:
            from addressbase.models import UprnToCouncil

            eoni_data_in_db = UprnToCouncil.objects.filter(
                uprn__postcode__startswith="BT"
            ).exists()

            code = geocoder.get_code("lad")
            if code.startswith("N") and not eoni_data_in_db:
                finder = self.get(pk="N07000001")
                finder.message = _(finder.message)
                """
                EONI's poling station finder requires postcode to have a space :(
                http://www.eoni.org.uk/Offices/Postcode-Search-Results?postcode=BT5+7TQ
                will produce a result, whereas
                http://www.eoni.org.uk/Offices/Postcode-Search-Results?postcode=BT57TQ
                will not.

                We might need to take a more sophisticated approach as we add more custom finders
                that accept postcodes (e.g: a postcode format flag in the database).
                At the moment I only have this one to work with.
                """
                finder.encoded_postcode = urllib.parse.quote(
                    Postcode(postcode).with_space
                )
            else:
                finder = self.get(pk=code)

            return finder
        except ObjectDoesNotExist:
            return None

class CustomFinder(models.Model):
    """
    Store details of areas that have their own
    custom polling station finders
    and/or a message that we might want to show.

    Example content:

    record = CustomFinder(
        area_code='E07000082'
        base_url='https://stroud.maps.arcgis.com/apps/webappviewer/index.html?id=ea6bf4b3655542c1a05c8d7e87d32bb1'
        can_pass_postcode=False
        message="Stroud District Council has its own polling station finder:"
    )
    record.save()

    record = CustomFinder(
        area_code='W06000008'
        base_url=''
        can_pass_postcode=False
        message='
We're working on it!
Ceredigion Council have provided polling station data. It will be available soon.'
    )
    record.save()

    record = CustomFinder(
        area_code='N07000001'
        base_url='http://www.eoni.org.uk/Offices/Postcode-Search-Results?postcode='
        can_pass_postcode=True
        message='The Electoral Office of Northern Ireland has its own polling station finder:'
    )
    record.save()
    """

    area_code = models.CharField(
        max_length=9, primary_key=True, help_text="The GSS code for this area"
    )
    base_url = models.CharField(
        blank=True,
        max_length=255,
        help_text="The landing page for the polling station finder",
    )
    can_pass_postcode = models.BooleanField(
        default=False, help_text="Does the URL have '?postcode=' in it?"
    )
    message = models.TextField(
        blank=True, default="This council has its own polling station finder:"
    )

    objects = CustomFinderManager()

class AdvanceVotingStation(models.Model):
    name = models.CharField(max_length=100)
    postcode = models.CharField(blank=True, null=True, max_length=100)
    address = models.TextField(blank=True, null=True)
    location = models.PointField(null=True, blank=True)
    opening_times = JSONField(null=True)
    council = models.ForeignKey(Council, null=True, on_delete=models.CASCADE)

    def __str__(self):
        return f"{self.name} ({self.postcode})"

    def save(self, **kwargs):
        self.address = "\n".join(
            [line.lstrip() for line in self.address.split("\n")]
        ).strip()
        return super().save(**kwargs)

    @property
    def opening_times_table(self):
        return OpeningTimes.from_dict(self.opening_times).as_table()
<|endoftext|>


<commit_before># -*- coding: utf-8 -*-
#!/usr/bin/env python

import webapp2,jinja2,os,datetime
import ctrpmodels

def normalize(groupname):
    return groupname.lower().replace('\'','').replace(' ','-')

JINJA_ENVIRONMENT = jinja2.Environment(
    loader=jinja2.FileSystemLoader(os.path.dirname(__file__)),
    extensions=['jinja2.ext.autoescape'])
JINJA_ENVIRONMENT.filters['normalize'] = normalize

class Display(webapp2.RequestHandler):
    def get(self):

        q = ctrpmodels.Global.query()
        r = q.fetch()
        template_values = {
            'last_updated': datetime.datetime.now(),
            'title' : 'Main'
        }
        template = JINJA_ENVIRONMENT.get_template('templates/header.html')
        self.response.write(template.render(template_values))

        self.response.write('
\n')

        groups = ctrpmodels.Group.query_for_t17_display()
        for group in groups:
            template_values = {'group' : group}
            template = JINJA_ENVIRONMENT.get_template('templates/group.html')
            self.response.write(template.render(template_values))

        self.response.write('
\n')

        template_values = {}
        template = JINJA_ENVIRONMENT.get_template('templates/footer.html')
        self.response.write(template.render(template_values))

    def build_tooltips(self):

        self.response.content_type = 'application/javascript'
        self.response.write('$(function() {\n')
        self.response.write('$(document).tooltip({\n')
        self.response.write('items: "[ttid]",\n')
        self.response.write('content: function() {\n')
        self.response.write('var tooltips = {};\n')

        groups = ctrpmodels.Group.query_for_t17_display()
        for raid in ['hm','brf']:
            for group in groups:
                normaltext = ""
                heroictext = ""
                mythictext = ""
                bosses = []
                groupraid = getattr(group,raid)
                raidbosses = getattr(ctrpmodels.Constants,raid+'bosses')

                for boss in groupraid.bosses:
                    bosses.append((boss.name, boss.normaldead, boss.heroicdead, boss.mythicdead))
                index_dict = {item: index for index, item in enumerate(raidbosses)}
                bosses.sort(key=lambda t:index_dict[t[0]])

                for boss in bosses:
                    if boss[1] != None:
                        normaltext += "
"+boss[0]+"
";
                    else:
                        normaltext += "
"+boss[0]+"
";
                    if boss[2] != None:
                        heroictext += "
"+boss[0]+"
";
                    else:
                        heroictext += "
"+boss[0]+"
";
                    if boss[3] != None:
                        mythictext += "
"+boss[0]+"
";
                    else:
                        mythictext += "
"+boss[0]+"
";

                template_values = {
                    'name': group.name,
                    'raid': raid,
                    'normaltext': normaltext,
                    'heroictext': heroictext,
                    'mythictext': mythictext,
                }
                template = JINJA_ENVIRONMENT.get_template('templates/group-tooltip.js')
                self.response.write(template.render(template_values))

        self.response.write('\n');
        self.response.write('var element = $(this);\n')
        self.response.write('var ttid = element.attr("ttid");\n')
        self.response.write('return tooltips[ttid];\n')
        self.response.write('}});\n')
        self.response.write('});\n')

class DisplayText(webapp2.RequestHandler):
    def get(self):

        q = ctrpmodels.Global.query()
        r = q.fetch()

        template_values = {
            'last_updated': datetime.datetime.now(),
            'title' : 'Text Display'
        }
        template = JINJA_ENVIRONMENT.get_template('templates/header.html')
        self.response.write(template.render(template_values))

        # get the group data from the datastore, and order it in decreasing order
        # so that further progressed teams show up first.  break ties by
        # alphabetical order of group names
        groups = ctrpmodels.Group.query_for_t17_display()

        for group in groups:
            self.response.write('%s (Avg ilvl: %d)
' % (group.name,group.avgilvl))
            self.writeProgress(group.brf)
            self.writeProgress(group.hm)
            self.response.write('
')
        template_values = {}
        template = JINJA_ENVIRONMENT.get_template('templates/footer.html')
        self.response.write(template.render(template_values))

    def writeProgress(self, raid):
        self.response.write("%s: %d/%dN %d/%dH %d/%dM
" %
                        (raid.raidname, raid.normal, raid.numbosses,
                         raid.heroic, raid.numbosses, raid.mythic,
                         raid.numbosses))

class DisplayHistory(webapp2.RequestHandler):
    def get(self):
        q = ctrpmodels.Global.query()
        r = q.fetch()

        lastupdated = r[0].lastupdated

        template_values = {
            'last_updated': r[0].lastupdated,
            'title' : 'History'
        }
        template = JINJA_ENVIRONMENT.get_template('templates/header.html')
        self.response.write(template.render(template_values))

        # add the beginnings of the table
        self.response.write('
')

        # request all of the history entries, sorted in reverse order by date
        curdate = datetime.date.today()
        oneday = datetime.timedelta(1)

        # this is a time object at 2AM AZ time (or 9AM UTC)
        az2am = datetime.time(9)

        for i in range(0,13):
            self.response.write('

\n')
            self.response.write(''+str(curdate)+'	\n')
            self.response.write('

\n')
            q = ctrpmodels.History.query(ctrpmodels.History.date == curdate)
            r = q.fetch()
            if (len(r) == 0):
                # if there were no results for this date, add just a simple
                # entry displaying nothing
                self.response.write('
\n')

                self.response.write('')
                if (i == 0):
                    current = datetime.datetime.now()
                    if (current > lastupdated):
                        self.response.write('Data not parsed for today yet')
                    else:
                        self.response.write('No new kills for this date!')
                else:
                    self.response.write('No new kills for this date!')
                self.response.write('	\n')
                self.response.write('
\n')
            else:
                # if there were results, grab the entries for the day and sort
                # them by group name
                updates = r[0].updates
                updates = sorted(updates, key=lambda k: k.group)

                # Grab the global data so we can populate the template with
                # a couple of the values.
                q2 = ctrpmodels.Global.query()
                r2 = q2.fetch()

                # now loop through the groups and output the updates in some
                # fashion.  sort the updates BRF -> HM, then M -> H -> N
                for u in updates:

                    template_values = {
                        'history': u,
                        'num_brf_bosses': ctrpmodels.Constants.num_brf_bosses,
                        'num_hm_bosses': ctrpmodels.Constants.num_hm_bosses,
                    }
                    template = JINJA_ENVIRONMENT.get_template(
                        'templates/history.html')
                    self.response.write(template.render(template_values))

            self.response.write('
\n')
            curdate -= oneday

        self.response.write('
\n')
        template_values = {}
        template = JINJA_ENVIRONMENT.get_template('templates/footer.html')
        self.response.write(template.render(template_values))
<commit_msg>Remove extra unneeded db query<commit_after># -*- coding: utf-8 -*-
#!/usr/bin/env python

import webapp2,jinja2,os,datetime
import ctrpmodels

def normalize(groupname):
    return groupname.lower().replace('\'','').replace(' ','-')

JINJA_ENVIRONMENT = jinja2.Environment(
    loader=jinja2.FileSystemLoader(os.path.dirname(__file__)),
    extensions=['jinja2.ext.autoescape'])
JINJA_ENVIRONMENT.filters['normalize'] = normalize

class Display(webapp2.RequestHandler):
    def get(self):

        q = ctrpmodels.Global.query()
        r = q.fetch()
        template_values = {
            'last_updated': datetime.datetime.now(),
            'title' : 'Main'
        }
        template = JINJA_ENVIRONMENT.get_template('templates/header.html')
        self.response.write(template.render(template_values))

        self.response.write('
\n')

        groups = ctrpmodels.Group.query_for_t17_display()
        for group in groups:
            template_values = {'group' : group}
            template = JINJA_ENVIRONMENT.get_template('templates/group.html')
            self.response.write(template.render(template_values))

        self.response.write('
\n')

        template_values = {}
        template = JINJA_ENVIRONMENT.get_template('templates/footer.html')
        self.response.write(template.render(template_values))

    def build_tooltips(self):

        self.response.content_type = 'application/javascript'
        self.response.write('$(function() {\n')
        self.response.write('$(document).tooltip({\n')
        self.response.write('items: "[ttid]",\n')
        self.response.write('content: function() {\n')
        self.response.write('var tooltips = {};\n')

        groups = ctrpmodels.Group.query_for_t17_display()
        for raid in ['hm','brf']:
            for group in groups:
                normaltext = ""
                heroictext = ""
                mythictext = ""
                bosses = []
                groupraid = getattr(group,raid)
                raidbosses = getattr(ctrpmodels.Constants,raid+'bosses')

                for boss in groupraid.bosses:
                    bosses.append((boss.name, boss.normaldead, boss.heroicdead, boss.mythicdead))
                index_dict = {item: index for index, item in enumerate(raidbosses)}
                bosses.sort(key=lambda t:index_dict[t[0]])

                for boss in bosses:
                    if boss[1] != None:
                        normaltext += "
"+boss[0]+"
";
                    else:
                        normaltext += "
"+boss[0]+"
";
                    if boss[2] != None:
                        heroictext += "
"+boss[0]+"
";
                    else:
                        heroictext += "
"+boss[0]+"
";
                    if boss[3] != None:
                        mythictext += "
"+boss[0]+"
";
                    else:
                        mythictext += "
"+boss[0]+"
";

                template_values = {
                    'name': group.name,
                    'raid': raid,
                    'normaltext': normaltext,
                    'heroictext': heroictext,
                    'mythictext': mythictext,
                }
                template = JINJA_ENVIRONMENT.get_template('templates/group-tooltip.js')
                self.response.write(template.render(template_values))

        self.response.write('\n');
        self.response.write('var element = $(this);\n')
        self.response.write('var ttid = element.attr("ttid");\n')
        self.response.write('return tooltips[ttid];\n')
        self.response.write('}});\n')
        self.response.write('});\n')

class DisplayText(webapp2.RequestHandler):
    def get(self):

        q = ctrpmodels.Global.query()
        r = q.fetch()

        template_values = {
            'last_updated': datetime.datetime.now(),
            'title' : 'Text Display'
        }
        template = JINJA_ENVIRONMENT.get_template('templates/header.html')
        self.response.write(template.render(template_values))

        # get the group data from the datastore, and order it in decreasing order
        # so that further progressed teams show up first.  break ties by
        # alphabetical order of group names
        groups = ctrpmodels.Group.query_for_t17_display()

        for group in groups:
            self.response.write('%s (Avg ilvl: %d)
' % (group.name,group.avgilvl))
            self.writeProgress(group.brf)
            self.writeProgress(group.hm)
            self.response.write('
')
        template_values = {}
        template = JINJA_ENVIRONMENT.get_template('templates/footer.html')
        self.response.write(template.render(template_values))

    def writeProgress(self, raid):
        self.response.write("%s: %d/%dN %d/%dH %d/%dM
" %
                        (raid.raidname, raid.normal, raid.numbosses,
                         raid.heroic, raid.numbosses, raid.mythic,
                         raid.numbosses))

class DisplayHistory(webapp2.RequestHandler):
    def get(self):
        q = ctrpmodels.Global.query()
        r = q.fetch()

        lastupdated = r[0].lastupdated

        template_values = {
            'last_updated': r[0].lastupdated,
            'title' : 'History'
        }
        template = JINJA_ENVIRONMENT.get_template('templates/header.html')
        self.response.write(template.render(template_values))

        # add the beginnings of the table
        self.response.write('
')

        # request all of the history entries, sorted in reverse order by date
        curdate = datetime.date.today()
        oneday = datetime.timedelta(1)

        # this is a time object at 2AM AZ time (or 9AM UTC)
        az2am = datetime.time(9)

        for i in range(0,13):
            self.response.write('

\n')
            self.response.write(''+str(curdate)+'	\n')
            self.response.write('

\n')
            q = ctrpmodels.History.query(ctrpmodels.History.date == curdate)
            r = q.fetch()
            if (len(r) == 0):
                # if there were no results for this date, add just a simple
                # entry displaying nothing
                self.response.write('
\n')

                self.response.write('')
                if (i == 0):
                    current = datetime.datetime.now()
                    if (current > lastupdated):
                        self.response.write('Data not parsed for today yet')
                    else:
                        self.response.write('No new kills for this date!')
                else:
                    self.response.write('No new kills for this date!')
                self.response.write('	\n')
                self.response.write('
\n')
            else:
                # if there were results, grab the entries for the day and sort
                # them by group name
                updates = r[0].updates
                updates = sorted(updates, key=lambda k: k.group)

                # now loop through the groups and output the updates in some
                # fashion.  sort the updates BRF -> HM, then M -> H -> N
                for u in updates:

                    template_values = {
                        'history': u,
                        'num_brf_bosses': ctrpmodels.Constants.num_brf_bosses,
                        'num_hm_bosses': ctrpmodels.Constants.num_hm_bosses,
                    }
                    template = JINJA_ENVIRONMENT.get_template(
                        'templates/history.html')
                    self.response.write(template.render(template_values))

            self.response.write('
\n')
            curdate -= oneday

        self.response.write('
\n')
        template_values = {}
        template = JINJA_ENVIRONMENT.get_template('templates/footer.html')
        self.response.write(template.render(template_values))
<|endoftext|>


<commit_before># -*- coding: utf-8 -*-
import httplib as http

from nose.tools import *  # flake8: noqa

from tests.base import ApiTestCase, DbTestCase
from tests import factories
from tests.utils import make_drf_request

from api.base.settings.defaults import API_BASE
from api.base.serializers import JSONAPISerializer
from api.nodes.serializers import NodeSerializer, RelationshipField

class TestApiBaseSerializers(ApiTestCase):

    def setUp(self):
        super(TestApiBaseSerializers, self).setUp()

        self.node = factories.ProjectFactory(is_public=True)

        for i in range(5):
            factories.ProjectFactory(is_public=True, parent=self.node)

        self.url = '/{}nodes/{}/'.format(API_BASE, self.node._id)

    def test_counts_not_included_in_link_fields_by_default(self):

        res = self.app.get(self.url)
        relationships = res.json['data']['relationships']
        for relation in relationships.values():
            link = relation['links'].values()[0]
            assert_not_in('count', link['meta'])

    def test_counts_included_in_link_fields_with_related_counts_query_param(self):

        res = self.app.get(self.url, params={'related_counts': True})
        relationships = res.json['data']['relationships']
        for key, relation in relationships.iteritems():
            field = NodeSerializer._declared_fields[key]
            if (field.meta or {}).get('count'):
                link = relation['links'].values()[0]
                assert_in('count', link['meta'])

    def test_related_counts_excluded_query_param_false(self):

        res = self.app.get(self.url, params={'related_counts': False})
        relationships = res.json['data']['relationships']
        for relation in relationships.values():
            link = relation['links'].values()[0]
            assert_not_in('count', link['meta'])

    def test_invalid_param_raises_bad_request(self):

        res = self.app.get(self.url, params={'related_counts': 'fish'}, expect_errors=True)
        assert_equal(res.status_code, http.BAD_REQUEST)

class TestRelationshipField(DbTestCase):

    # We need a Serializer to test the Relationship field (needs context)
    class BasicNodeSerializer(JSONAPISerializer):

        parent = RelationshipField(
            related_view='nodes:node-detail',
            related_view_kwargs={'node_id': 'pk'}
        )

        parent_with_meta = RelationshipField(
            related_view='nodes:node-detail',
            related_view_kwargs={'node_id': 'pk'},
            related_meta={'count': 'get_count', 'extra': 'get_extra'},
        )

        class Meta:
            type_ = 'nodes'

        def get_count(self, obj):
            return 1

        def get_extra(self, obj):
            return 'foo'

    # TODO: Expand tests

    # Regression test for https://openscience.atlassian.net/browse/OSF-4832
    def test_serializing_meta(self):
        req = make_drf_request()
        project = factories.ProjectFactory()
        node = factories.NodeFactory(parent=project)
        data = self.BasicNodeSerializer(node, context={'request': req}).data['data']

        meta = data['relationships']['parent_with_meta']['links']['related']['meta']
        assert_not_in('count', meta)
        assert_in('extra', meta)
        assert_equal(meta['extra'], 'foo')
<commit_msg>Add tests for relationship field with both self and related fields and test for multiple kwargs<commit_after># -*- coding: utf-8 -*-
import httplib as http

from nose.tools import *  # flake8: noqa

from tests.base import ApiTestCase, DbTestCase
from tests import factories
from tests.utils import make_drf_request

from api.base.settings.defaults import API_BASE
from api.base.serializers import JSONAPISerializer
from api.nodes.serializers import NodeSerializer, RelationshipField

class TestApiBaseSerializers(ApiTestCase):

    def setUp(self):
        super(TestApiBaseSerializers, self).setUp()

        self.node = factories.ProjectFactory(is_public=True)

        for i in range(5):
            factories.ProjectFactory(is_public=True, parent=self.node)

        self.url = '/{}nodes/{}/'.format(API_BASE, self.node._id)

    def test_counts_not_included_in_link_fields_by_default(self):

        res = self.app.get(self.url)
        relationships = res.json['data']['relationships']
        for relation in relationships.values():
            link = relation['links'].values()[0]
            assert_not_in('count', link['meta'])

    def test_counts_included_in_link_fields_with_related_counts_query_param(self):

        res = self.app.get(self.url, params={'related_counts': True})
        relationships = res.json['data']['relationships']
        for key, relation in relationships.iteritems():
            field = NodeSerializer._declared_fields[key]
            if (field.meta or {}).get('count'):
                link = relation['links'].values()[0]
                assert_in('count', link['meta'])

    def test_related_counts_excluded_query_param_false(self):

        res = self.app.get(self.url, params={'related_counts': False})
        relationships = res.json['data']['relationships']
        for relation in relationships.values():
            link = relation['links'].values()[0]
            assert_not_in('count', link['meta'])

    def test_invalid_param_raises_bad_request(self):

        res = self.app.get(self.url, params={'related_counts': 'fish'}, expect_errors=True)
        assert_equal(res.status_code, http.BAD_REQUEST)

class TestRelationshipField(DbTestCase):

    # We need a Serializer to test the Relationship field (needs context)
    class BasicNodeSerializer(JSONAPISerializer):

        parent = RelationshipField(
            related_view='nodes:node-detail',
            related_view_kwargs={'node_id': 'pk'}
        )

        parent_with_meta = RelationshipField(
            related_view='nodes:node-detail',
            related_view_kwargs={'node_id': 'pk'},
            related_meta={'count': 'get_count', 'extra': 'get_extra'},
        )

        self_and_related_field = RelationshipField(
            related_view='nodes:node-detail',
            related_view_kwargs={'node_id': 'pk'},
            self_view='nodes:node-contributors',
            self_view_kwargs={'node_id': 'pk'},
        )

        contributor_detail = RelationshipField(
            related_view='nodes:node-contributor-detail',
            related_view_kwargs={'node_id': 'pk', 'user_id': 'hkdpx'},
        )

        class Meta:
            type_ = 'nodes'

        def get_count(self, obj):
            return 1

        def get_extra(self, obj):
            return 'foo'

    # TODO: Expand tests

    # Regression test for https://openscience.atlassian.net/browse/OSF-4832
    def test_serializing_meta(self):
        req = make_drf_request()
        project = factories.ProjectFactory()
        node = factories.NodeFactory(parent=project)
        data = self.BasicNodeSerializer(node, context={'request': req}).data['data']

        meta = data['relationships']['parent_with_meta']['links']['related']['meta']
        assert_not_in('count', meta)
        assert_in('extra', meta)
        assert_equal(meta['extra'], 'foo')

    def test_self_and_related_fields(self):
        req = make_drf_request()
        project = factories.ProjectFactory()
        node = factories.NodeFactory(parent=project)
        data = self.BasicNodeSerializer(node, context={'request': req}).data['data']

        relationship_field = data['relationships']['self_and_related_field']['links']
        assert_in('/v2/nodes/{}/contributors/'.format(node._id), relationship_field['self']['href'])
        assert_in('/v2/nodes/{}/'.format(node._id), relationship_field['related']['href'])

    def test_field_with_two_kwargs(self):
        req = make_drf_request()
        project = factories.ProjectFactory()
        node = factories.NodeFactory(parent=project)
        data = self.BasicNodeSerializer(node, context={'request': req}).data['data']
        field = data['relationships']['contributor_detail']['links']
        assert_in('/v2/nodes/{}/contributors/{}/'.format(node._id, 'hkdpx'), field['related']['href'])
<|endoftext|>


<commit_before>'''
 Author      : DORIAN JAVA BROWN
 Version     : N/A
 Copyright   : All Rights Reserve; You may use, distribute and modify this code.
 Description : This program provides the user with options on how much tip the customer should leave the waiter/waitress
 '''

import os

total = 21.49

def newReceipt():
 # menu display
print('\n\n\t\t JUICEY BURGER\n\n')
print('')
print('1 Juicey Burger  $ 18.99')
print('1 Orange Drink   $  1.00')
print('-------------------------------------------')
print('')
print('Sub Total:       $ 19.99')
print('Local Tax:       $  1.50')
print('Bill Total:      )
print('\n\n')

 print
def cls():
  os.system('cls' if os.name == 'nt' else 'clear')

def opt():        # opt abbreviation for option
    #ABCDE Option, if statements

  answer = raw_input('Correct ?  ')

  if answer == 'YES' or answer == 'Yes' or answer == 'yes' :
  cls()

  # tip suggestion list
  print('\n\n\t Tip Suggestions')
  print('----------------------------------')
  print('A)  %%20           $ %0.3f' %((total * .20)))
  print('B)  %%15           $ %0.3f' %((total * .15)))
  print('C)  %%10           $ %0.3f' %((total * .10)))
  print('D)   %%5           $ %0.3f' %((total * .05)))
  print('E)  No Thank You /n/n')

elif answer == 'NO' or answer == 'No' or answer == 'no' :

else:
      print('\n\n\t\t error:. invaild value \n\n')
      print ('\n\n\t\t please wait one moment for assistance...\n\n')

def receipt():

# menu display
print('\n\n\t\t JUICEY BURGER\n\n')
print('')
print('1 Juicey Burger  $ 18.99')
print('1 Orange Drink   $  1.00')
print('-------------------------------------------')
print('')
print('Sub Total:       $ 19.99')
print('Local Tax:       $  1.50')
print('Bill Total:      $ 21.49')
print('\n\n')

#https://www.youtube.com/watch?annotation_id=annotation_3770292585&feature=iv&src_vid=bguKhMnvmb8&v=LtGEp9c6Z-U

receipt()
opt()
result()
<commit_msg>Update TipCalculator.py<commit_after>'''
 Author      : DORIAN JAVA BROWN
 Version     : N/A
 Copyright   : All Rights Reserve; You may use, distribute and modify this code.
 Description : This program provides the user with options on how much tip the customer should leave the waiter/waitress
 '''

import os

total = 21.49

def newReceipt():
 # menu display
print('\n\n\t\t JUICEY BURGER\n\n')
print('')
print('1 Juicey Burger  $ 18.99')
print('1 Orange Drink   $  1.00')
print('-------------------------------------------')
print('')
print('Sub Total:       $ 19.99')
print('Local Tax:       $  1.50')
print('Bill Total:      )
print('\n\n')

 print
def cls():
  os.system('cls' if os.name == 'nt' else 'clear')

def opt():        # opt abbreviation for option
    #ABCDE Option, if statements

  answer = raw_input('Correct ?  ')

  if answer == 'YES' or answer == 'Yes' or answer == 'yes' :
  cls()

  # tip suggestion list
  print('\n\n\t Tip Suggestions')
  print('----------------------------------')
  print('A)  %%20           $ %0.3f' %((total * .20)))
  print('B)  %%15           $ %0.3f' %((total * .15)))
  print('C)  %%10           $ %0.3f' %((total * .10)))
  print('D)   %%5           $ %0.3f' %((total * .05)))
  print('E)  No Thank You /n/n')

elif answer == 'NO' or answer == 'No' or answer == 'no' :

else:
      print('\n\n\t\t error:. invaild value \n\n')
      print ('\n\n\t\t please wait one moment for assistance...\n\n')

def receipt():

# menu display
print('\n\n\t\t JUICEY BURGER\n\n')
print('')
print('1 Juicey Burger  $ 18.99')
print('1 Orange Drink   $  1.00')
print('-------------------------------------------')
print('')
print('Sub Total:       $ 19.99')
print('Local Tax:       $  1.50')
print('Bill Total:      $ 21.49')
print('\n\n')

#https://www.youtube.com/watch?annotation_id=annotation_3770292585&feature=iv&src_vid=bguKhMnvmb8&v=LtGEp9c6Z-U

receipt()
opt()
result()eeeee
<|endoftext|>


<commit_before># -*- coding: utf-8 -*-
"""
===========================================================================
Crystal structure classes (:mod:`sknano.core.crystallography._structures`)
===========================================================================

.. currentmodule:: sknano.core.crystallography._structures

"""
from __future__ import absolute_import, division, print_function, \
    unicode_literals
# from builtins import super
# from builtins import dict
from future import standard_library
standard_library.install_aliases()
# from future.utils import with_metaclass

__docformat__ = 'restructuredtext en'

import inspect
# import numbers
# from abc import ABCMeta, abstractproperty

import numpy as np

from sknano.core.math import Vector

from sknano.core.atoms import StructureAtom as Atom, StructureAtoms as Atoms
from ._lattices import CrystalLattice

__all__ = ['CrystalStructure', 'DiamondStructure',
           'HexagonalClosePackedStructure',
           'CubicClosePackedStructure', 'FCCStructure', 'HexagonalStructure',
           'Gold', 'Copper', 'pymatgen_structure', 'AlphaQuartz']

class CrystalStructure:
    """Abstract base class for crystal structures."""

    def __init__(self, lattice=None, basis=None, coords=None, cartesian=False):

        atoms = None

        if basis is None:
            atoms = Atoms()
        elif basis is not None:
            atoms = Atoms(atoms=basis)
            if coords is not None:
                for atom, pos in zip(atoms, coords):
                    if not cartesian:
                        pos = lattice.fractional_to_cartesian(pos)
                    atom.r = Vector(pos)

        self._atoms = atoms
        self.lattice = lattice
        self.basis = basis
        self.fmtstr = "lattice={lattice!r}, basis={basis!r}"

    def __repr__(self):
        return "{}({})".format(self.__class__.__name__,
                               self.fmtstr.format(**self.todict()))

    @property
    def atoms(self):
        return self._atoms

    @property
    def basis(self):
        """Crystal structure basis."""
        return self._basis

    @basis.setter
    def basis(self, value):
        self._basis = value

    @property
    def lattice(self):
        return self._lattice

    @lattice.setter
    def lattice(self, value):
        if not isinstance(value, CrystalLattice):
            value = CrystalLattice(cell_matrix=value)
        self._lattice = value

    def __getattr__(self, name):
        if name != '_atoms':
            return getattr(self._atoms, name)

    def __setattr__(self, name, value):
        if name.startswith('_'):
            super().__setattr__(name, value)
        else:
            setattr(self._atoms, name, value)

    def __delattr__(self, name):
        if name.startswith('_'):
            super().__delattr__(name)
        else:
            delattr(self._atoms, name)

    @property
    def unit_cell(self):
        pass

    @classmethod
    def from_pymatgen_structure(cls, structure):
        atoms = Atoms()
        for site in structure.sites:
            atoms.append(Atom(element=site.specie.symbol,
                              x=site.x, y=site.y, z=site.z))
        return cls(lattice=CrystalLattice(
                   cell_matrix=structure.lattice.matrix),
                   basis=atoms)

    @classmethod
    def from_spacegroup(cls, sg, lattice, basis, coords, scaling_matrix=None):
        if not isinstance(basis, list):
            basis = [basis]
        if len(basis) != len(coords):
            if isinstance(coords, list) and len(coords) != 0 and \
                    isinstance(coords[0], (int, float)):
                coords = [coords]
                cls.from_spacegroup(sg, lattice, basis, coords,
                                    scaling_matrix=scaling_matrix)

        structure = \
            pymatgen_structure(sg, lattice.cell_matrix, basis, coords,
                               classmethod='from_spacegroup')
        if scaling_matrix is not None and \
                isinstance(scaling_matrix,
                           (int, float, tuple, list, np.ndarray)):
            structure.make_supercell(scaling_matrix)
        structure = CrystalStructure.from_pymatgen_structure(structure)
        return cls(lattice=structure.lattice, basis=structure.basis)

    def todict(self):
        """Return `dict` of `CrystalStructure` parameters."""
        return dict(lattice=self.lattice, basis=self.basis)

def pymatgen_structure(*args, classmethod=None, **kwargs):
    try:
        from pymatgen import Structure
    except ImportError as e:
        print(e)
    else:
        constructor = None
        if classmethod is None:
            constructor = Structure
        else:
            constructor = getattr(Structure, classmethod, None)

        pmg_sig = inspect.signature(constructor)
        bound_sig = pmg_sig.bind(*args, **kwargs)
        return constructor(*bound_sig.args, **bound_sig.kwargs)

        # atoms = Atoms()
        # for site in structure.sites:
        #     atoms.append(Atom(element=site.specie.symbol,
        #                       x=site.x, y=site.y, z=site.z))
        # return CrystalStructure(lattice=CrystalLattice(
        #                         cell_matrix=structure.lattice.matrix),
        #                         basis=atoms)

class DiamondStructure(CrystalStructure):
    """Abstract representation of diamond structure."""
    def __init__(self, a=3.567, scaling_matrix=None):
        diamond = \
            pymatgen_structure(227, CrystalLattice.cubic(a).cell_matrix, ["C"],
                               [[0, 0, 0]], classmethod='from_spacegroup')
        if scaling_matrix is not None and \
                isinstance(scaling_matrix,
                           (int, float, tuple, list, np.ndarray)):
            diamond.make_supercell(scaling_matrix)
        diamond = CrystalStructure.from_pymatgen_structure(diamond)
        super().__init__(lattice=diamond.lattice, basis=diamond.basis)

class HexagonalClosePackedStructure(CrystalStructure):
    """Abstract representation of hexagonal close-packed structure."""
    pass

class CubicClosePackedStructure(CrystalStructure):
    """Abstract representation of cubic close-packed structure."""
    pass

class HexagonalStructure(CrystalStructure):
    @classmethod
    def from_spacegroup(cls, sg, a, c, basis, coords, scaling_matrix=None):
        lattice = CrystalLattice.hexagonal(a, c)
        # lattice = CrystalLattice(a=a, b=a, c=c, alpha=90, beta=90, gamma=60)
        return CrystalStructure.from_spacegroup(sg, lattice, basis, coords,
                                                scaling_matrix=scaling_matrix)

class FCCStructure(CrystalStructure):
    @classmethod
    def from_spacegroup(cls, sg, a, basis, coords, scaling_matrix=None):
        lattice = CrystalLattice.cubic(a)
        return CrystalStructure.from_spacegroup(sg, lattice, basis, coords,
                                                scaling_matrix=scaling_matrix)

class AlphaQuartz(HexagonalStructure):
    def __init__(self, a=4.916, c=5.405, scaling_matrix=None):
        lattice = CrystalLattice.hexagonal(a, c)
        basis = 3 * ["Si"]
        basis.extend(6 * ["O"])
        basis = Atoms(atoms=[Atom(element=s) for s in basis])
        coords = [[0.4697, 0.0000, 0.0000],
                  [0.0000, 0.4697, 0.6667],
                  [0.5305, 0.5303, 0.3333],
                  [0.4133, 0.2672, 0.1188],
                  [0.2672, 0.4133, 0.5479],
                  [0.7328, 0.1461, 0.7855],
                  [0.5867, 0.8539, 0.2145],
                  [0.8539, 0.5867, 0.4521],
                  [0.1461, 0.7328, 0.8812]]
        structure = pymatgen_structure(lattice.cell_matrix,
                                       basis.symbols,
                                       coords)
        if scaling_matrix is not None and \
                isinstance(scaling_matrix,
                           (int, float, tuple, list, np.ndarray)):
            structure.make_supercell(scaling_matrix)
        structure = CrystalStructure.from_pymatgen_structure(structure)
        super().__init__(structure.lattice, structure.basis)
        # super().__init__(lattice, basis, coords)

        # quartz = \
        #     HexagonalStructure.from_spacegroup(154, a, c, ["Si", "O"],
        #                                        [[0.4697, 0.0000, 0.0000],
        #                                         [0.4135, 0.2669, 0.1191]],
        #                                        scaling_matrix=scaling_matrix)
        # super().__init__(quartz.lattice, quartz.basis)

class Gold(FCCStructure):
    def __init__(self, a=4.078, scaling_matrix=None):

        gold = FCCStructure.from_spacegroup(225, a, ["Au"], [[0, 0, 0]],
                                            scaling_matrix=scaling_matrix)
        super().__init__(gold.lattice, gold.basis)

class Copper(FCCStructure):
    def __init__(self, a=3.615, scaling_matrix=None):
        copper = FCCStructure.from_spacegroup(225, a, ["Cu"], [[0, 0, 0]],
                                              scaling_matrix=scaling_matrix)
        super().__init__(copper.lattice, copper.basis)
<commit_msg>removing `pymatgen_structure` function and updating imports<commit_after># -*- coding: utf-8 -*-
"""
===========================================================================
Crystal structure classes (:mod:`sknano.core.crystallography._structures`)
===========================================================================

.. currentmodule:: sknano.core.crystallography._structures

"""
from __future__ import absolute_import, division, print_function, \
    unicode_literals
# from builtins import super
# from builtins import dict
from future import standard_library
standard_library.install_aliases()
# from future.utils import with_metaclass

__docformat__ = 'restructuredtext en'

# import numbers
# from abc import ABCMeta, abstractproperty

import numpy as np

from sknano.core.math import Vector

from sknano.core.atoms import StructureAtom as Atom, StructureAtoms as Atoms
from ._3D_lattices import CrystalLattice
from ._extras import pymatgen_structure

__all__ = ['CrystalStructure', 'DiamondStructure',
           'HexagonalClosePackedStructure',
           'CubicClosePackedStructure', 'FCCStructure', 'HexagonalStructure',
           'Gold', 'Copper', 'AlphaQuartz']

class CrystalStructure:
    """Abstract base class for crystal structures."""

    def __init__(self, lattice=None, basis=None, coords=None, cartesian=False):

        atoms = None

        if basis is None:
            atoms = Atoms()
        elif basis is not None:
            atoms = Atoms(atoms=basis)
            if coords is not None:
                for atom, pos in zip(atoms, coords):
                    if not cartesian:
                        pos = lattice.fractional_to_cartesian(pos)
                    atom.r = Vector(pos)

        self._atoms = atoms
        self.lattice = lattice
        self.basis = basis
        self.fmtstr = "lattice={lattice!r}, basis={basis!r}"

    def __repr__(self):
        return "{}({})".format(self.__class__.__name__,
                               self.fmtstr.format(**self.todict()))

    @property
    def atoms(self):
        return self._atoms

    @property
    def basis(self):
        """Crystal structure basis."""
        return self._basis

    @basis.setter
    def basis(self, value):
        self._basis = value

    @property
    def lattice(self):
        return self._lattice

    @lattice.setter
    def lattice(self, value):
        if not isinstance(value, CrystalLattice):
            value = CrystalLattice(cell_matrix=value)
        self._lattice = value

    def __getattr__(self, name):
        if name != '_atoms':
            return getattr(self._atoms, name)

    def __setattr__(self, name, value):
        if name.startswith('_'):
            super().__setattr__(name, value)
        else:
            setattr(self._atoms, name, value)

    def __delattr__(self, name):
        if name.startswith('_'):
            super().__delattr__(name)
        else:
            delattr(self._atoms, name)

    @property
    def unit_cell(self):
        pass

    @classmethod
    def from_pymatgen_structure(cls, structure):
        atoms = Atoms()
        for site in structure.sites:
            atoms.append(Atom(element=site.specie.symbol,
                              x=site.x, y=site.y, z=site.z))
        return cls(lattice=CrystalLattice(
                   cell_matrix=structure.lattice.matrix),
                   basis=atoms)

    @classmethod
    def from_spacegroup(cls, sg, lattice, basis, coords, scaling_matrix=None):
        if not isinstance(basis, list):
            basis = [basis]
        if len(basis) != len(coords):
            if isinstance(coords, list) and len(coords) != 0 and \
                    isinstance(coords[0], (int, float)):
                coords = [coords]
                cls.from_spacegroup(sg, lattice, basis, coords,
                                    scaling_matrix=scaling_matrix)

        structure = \
            pymatgen_structure(sg, lattice.cell_matrix, basis, coords,
                               classmethod='from_spacegroup')
        if scaling_matrix is not None and \
                isinstance(scaling_matrix,
                           (int, float, tuple, list, np.ndarray)):
            structure.make_supercell(scaling_matrix)
        structure = CrystalStructure.from_pymatgen_structure(structure)
        return cls(lattice=structure.lattice, basis=structure.basis)

    def todict(self):
        """Return `dict` of `CrystalStructure` parameters."""
        return dict(lattice=self.lattice, basis=self.basis)

class DiamondStructure(CrystalStructure):
    """Abstract representation of diamond structure."""
    def __init__(self, a=3.567, scaling_matrix=None):
        diamond = \
            pymatgen_structure(227, CrystalLattice.cubic(a).cell_matrix, ["C"],
                               [[0, 0, 0]], classmethod='from_spacegroup')
        if scaling_matrix is not None and \
                isinstance(scaling_matrix,
                           (int, float, tuple, list, np.ndarray)):
            diamond.make_supercell(scaling_matrix)
        diamond = CrystalStructure.from_pymatgen_structure(diamond)
        super().__init__(lattice=diamond.lattice, basis=diamond.basis)

class HexagonalClosePackedStructure(CrystalStructure):
    """Abstract representation of hexagonal close-packed structure."""
    pass

class CubicClosePackedStructure(CrystalStructure):
    """Abstract representation of cubic close-packed structure."""
    pass

class HexagonalStructure(CrystalStructure):
    @classmethod
    def from_spacegroup(cls, sg, a, c, basis, coords, scaling_matrix=None):
        lattice = CrystalLattice.hexagonal(a, c)
        # lattice = CrystalLattice(a=a, b=a, c=c, alpha=90, beta=90, gamma=60)
        return CrystalStructure.from_spacegroup(sg, lattice, basis, coords,
                                                scaling_matrix=scaling_matrix)

class FCCStructure(CrystalStructure):
    @classmethod
    def from_spacegroup(cls, sg, a, basis, coords, scaling_matrix=None):
        lattice = CrystalLattice.cubic(a)
        return CrystalStructure.from_spacegroup(sg, lattice, basis, coords,
                                                scaling_matrix=scaling_matrix)

class AlphaQuartz(HexagonalStructure):
    def __init__(self, a=4.916, c=5.405, scaling_matrix=None):
        lattice = CrystalLattice.hexagonal(a, c)
        basis = 3 * ["Si"]
        basis.extend(6 * ["O"])
        basis = Atoms(atoms=[Atom(element=s) for s in basis])
        coords = [[0.4697, 0.0000, 0.0000],
                  [0.0000, 0.4697, 0.6667],
                  [0.5305, 0.5303, 0.3333],
                  [0.4133, 0.2672, 0.1188],
                  [0.2672, 0.4133, 0.5479],
                  [0.7328, 0.1461, 0.7855],
                  [0.5867, 0.8539, 0.2145],
                  [0.8539, 0.5867, 0.4521],
                  [0.1461, 0.7328, 0.8812]]
        structure = pymatgen_structure(lattice.cell_matrix,
                                       basis.symbols,
                                       coords)
        if scaling_matrix is not None and \
                isinstance(scaling_matrix,
                           (int, float, tuple, list, np.ndarray)):
            structure.make_supercell(scaling_matrix)
        structure = CrystalStructure.from_pymatgen_structure(structure)
        super().__init__(structure.lattice, structure.basis)
        # super().__init__(lattice, basis, coords)

        # quartz = \
        #     HexagonalStructure.from_spacegroup(154, a, c, ["Si", "O"],
        #                                        [[0.4697, 0.0000, 0.0000],
        #                                         [0.4135, 0.2669, 0.1191]],
        #                                        scaling_matrix=scaling_matrix)
        # super().__init__(quartz.lattice, quartz.basis)

class Gold(FCCStructure):
    def __init__(self, a=4.078, scaling_matrix=None):

        gold = FCCStructure.from_spacegroup(225, a, ["Au"], [[0, 0, 0]],
                                            scaling_matrix=scaling_matrix)
        super().__init__(gold.lattice, gold.basis)

class Copper(FCCStructure):
    def __init__(self, a=3.615, scaling_matrix=None):
        copper = FCCStructure.from_spacegroup(225, a, ["Cu"], [[0, 0, 0]],
                                              scaling_matrix=scaling_matrix)
        super().__init__(copper.lattice, copper.basis)
<|endoftext|>


<commit_before>import sys
import os
import os.path
from jinja2 import Template
from ConfigParser import ConfigParser
import StringIO

if __name__ == "__main__":
    if len(sys.argv) != 3:
        print("Usage: <program> <deploy_cfg_template_file> <file_with_properties>")
        print("Properties from <file_with_properties> will be applied to <deploy_cfg_template_file>")
        print("template which will be overwritten with .orig copy saved in the same folder first.")
        sys.exit(1)
    file = open(sys.argv[1], 'r')
    text = file.read()
    t = Template(text)
    config = ConfigParser()
    if os.path.isfile(sys.argv[2]):
        config.read(sys.argv[2])
    elif "KBASE_ENDPOINT" in os.environ:
        kbase_endpoint = os.environ.get("KBASE_ENDPOINT")
        props = "[global]\n" + \
                "kbase_endpoint = " + kbase_endpoint + "\n" + \
                "job_service_url = " + kbase_endpoint + "/userandjobstate\n" + \
                "workspace_url = " + kbase_endpoint + "/ws\n" + \
                "shock_url = " + kbase_endpoint + "/shock-api\n" + \
                "handle_url = " + kbase_endpoint + "/handle_service\n" + \
                "srv_wiz_url = " + kbase_endpoint + "/service_wizard\n" + \
                "njsw_url = " + kbase_endpoint + "/njs_wrapper\n"
        if "AUTH_SERVICE_URL" in os.environ:
            props += "auth_service_url = " + os.environ.get("AUTH_SERVICE_URL") + "\n"
        elif "auth2services" in kbase_endpoint:
            props += "auth_service_url = " + kbase_endpoint + "/auth/api/legacy/KBase/Sessions/Login\n"
        props += "auth_service_url_allow_insecure = " + \
                 os.environ.get("AUTH_SERVICE_URL_ALLOW_INSECURE", "false") + "\n"
        config.readfp(StringIO.StringIO(props))
    else:
        raise ValueError('Neither ' + sys.argv[2] + ' file nor KBASE_ENDPOINT env-variable found')
    props = dict(config.items("global"))
    output = t.render(props)
    with open(sys.argv[1] + ".orig", 'w') as f:
        f.write(text)
    with open(sys.argv[1], 'w') as f:
        f.write(output)
<commit_msg>Support for secure config-parameters<commit_after>import sys
import os
import os.path
from jinja2 import Template
from ConfigParser import ConfigParser
import StringIO

if __name__ == "__main__":
    if len(sys.argv) != 3:
        print("Usage: <program> <deploy_cfg_template_file> <file_with_properties>")
        print("Properties from <file_with_properties> will be applied to <deploy_cfg_template_file>")
        print("template which will be overwritten with .orig copy saved in the same folder first.")
        sys.exit(1)
    file = open(sys.argv[1], 'r')
    text = file.read()
    t = Template(text)
    config = ConfigParser()
    if os.path.isfile(sys.argv[2]):
        config.read(sys.argv[2])
    elif "KBASE_ENDPOINT" in os.environ:
        kbase_endpoint = os.environ.get("KBASE_ENDPOINT")
        props = "[global]\n" + \
                "kbase_endpoint = " + kbase_endpoint + "\n" + \
                "job_service_url = " + kbase_endpoint + "/userandjobstate\n" + \
                "workspace_url = " + kbase_endpoint + "/ws\n" + \
                "shock_url = " + kbase_endpoint + "/shock-api\n" + \
                "handle_url = " + kbase_endpoint + "/handle_service\n" + \
                "srv_wiz_url = " + kbase_endpoint + "/service_wizard\n" + \
                "njsw_url = " + kbase_endpoint + "/njs_wrapper\n"
        if "AUTH_SERVICE_URL" in os.environ:
            props += "auth_service_url = " + os.environ.get("AUTH_SERVICE_URL") + "\n"
        props += "auth_service_url_allow_insecure = " + \
                 os.environ.get("AUTH_SERVICE_URL_ALLOW_INSECURE", "false") + "\n"
        for key in os.environ:
            if key.startswith('KBASE_SECURE_CONFIG_PARAM_'):
                param_name = key[len('KBASE_SECURE_CONFIG_PARAM_'):]
                props += param_name + " = " + os.environ.get(key) + "\n"
        config.readfp(StringIO.StringIO(props))
    else:
        raise ValueError('Neither ' + sys.argv[2] + ' file nor KBASE_ENDPOINT env-variable found')
    props = dict(config.items("global"))
    output = t.render(props)
    with open(sys.argv[1] + ".orig", 'w') as f:
        f.write(text)
    with open(sys.argv[1], 'w') as f:
        f.write(output)
<|endoftext|>


<commit_before>import jogovelha
import sys

erroInicializar = False
jogo = jogovelha.inicializar()

if len(jogo) != 3:
	erroInicializar = True
else:
	for linha in jogo:
		if len(linha) != 3:
			erroInicializar = True
		else:
			for elemento in linha:
				if elemento != '.':
					erroInicializar = True
<commit_msg>Update testes.py<commit_after>import jogovelha
import sys

erroInicializar = False
jogo = jogovelha.inicializar()

if len(jogo) != 3:
	erroInicializar = True
else:
	for linha in jogo:
		if len(linha) != 3:
			erroInicializar = True
		else:
			for elemento in linha:
				if elemento != '.':
					erroInicializar = True
if erroInicializar:
	sys.exit(1)
else:
	sys.exit(0)
<|endoftext|>