<commit_before>from django.http import HttpResponse, JsonResponse, Http404
from django.template.loader import render_to_string
from django.utils.decorators import method_decorator
from django.views import View

from corehq import privileges
from corehq.apps.accounting.decorators import requires_privilege_with_fallback
from corehq.apps.api.odata.utils import (
    get_case_odata_fields_from_config,
    get_form_odata_fields_from_config,
)
from corehq.apps.domain.decorators import basic_auth_or_try_api_key_auth
from corehq.apps.export.models import CaseExportInstance, FormExportInstance
from corehq.apps.export.views.utils import user_can_view_odata_feed
from corehq.apps.users.decorators import require_permission
from corehq.apps.users.models import Permissions
from corehq.util import get_document_or_404
from corehq.util.view_utils import absolute_reverse

odata_auth = method_decorator([
    basic_auth_or_try_api_key_auth,
    requires_privilege_with_fallback(privileges.ODATA_FEED),
    require_permission(Permissions.edit_data, login_decorator=None),
], name='dispatch')

class BaseODataView(View):

    def dispatch(self, request, *args, **kwargs):
        if not user_can_view_odata_feed(request.domain, request.couch_user):
            raise Http404()
        return super(BaseODataView, self).dispatch(request, *args, **kwargs)

@odata_auth
class ODataCaseServiceView(BaseODataView):

    urlname = 'odata_case_service_from_export_instance'
    table_urlname = 'odata_case_service_from_export_instance_table'

    def get(self, request, domain, config_id, **kwargs):
        table_id = int(kwargs.get('table_id', 0))
        urlname = ODataCaseMetadataView.urlname
        url_args = [domain, config_id]
        if table_id > 0:
            urlname = ODataCaseMetadataView.table_urlname
            url_args.append(table_id)
        service_document_content = {
            '@odata.context': absolute_reverse(urlname, args=url_args),
            'value': [{
                'name': 'feed',
                'kind': 'EntitySet',
                'url': 'feed',
            }]
        }
        return add_odata_headers(JsonResponse(service_document_content))

@odata_auth
class ODataCaseMetadataView(BaseODataView):

    urlname = 'odata_case_metadata_from_export_instance'
    table_urlname = 'odata_case_metadata_from_export_instance_table'

    def get(self, request, domain, config_id, **kwargs):
        table_id = int(kwargs.get('table_id', 0))
        config = get_document_or_404(CaseExportInstance, domain, config_id)
        metadata = render_to_string('api/odata_metadata.xml', {
            'fields': get_case_odata_fields_from_config(config, table_id),
            'primary_key': 'caseid' if table_id == 0 else 'number',
        })
        return add_odata_headers(HttpResponse(metadata, content_type='application/xml'))

@odata_auth
class ODataFormServiceView(BaseODataView):

    urlname = 'odata_form_service_from_export_instance'
    table_urlname = 'odata_form_service_from_export_instance_table'

    def get(self, request, domain, config_id, **kwargs):
        table_id = int(kwargs.get('table_id', 0))
        urlname = ODataFormMetadataView.urlname
        url_args = [domain, config_id]
        if table_id > 0:
            urlname = ODataFormMetadataView.table_urlname
            url_args.append(table_id)
        service_document_content = {
            '@odata.context': absolute_reverse(urlname, args=url_args),
            'value': [{
                'name': 'feed',
                'kind': 'EntitySet',
                'url': 'feed',
            }]
        }
        return add_odata_headers(JsonResponse(service_document_content))

@odata_auth
class ODataFormMetadataView(BaseODataView):

    urlname = 'odata_form_metadata_from_export_instance'
    table_urlname = 'odata_form_metadata_from_export_instance_table'

    def get(self, request, domain, config_id, **kwargs):
        table_id = int(kwargs.get('table_id', 0))
        config = get_document_or_404(FormExportInstance, domain, config_id)
        metadata = render_to_string('api/odata_metadata.xml', {
            'fields': get_form_odata_fields_from_config(config, table_id),
            'primary_key': 'formid' if table_id == 0 else 'number',
        })
        return add_odata_headers(HttpResponse(metadata, content_type='application/xml'))

def add_odata_headers(response):
    response['OData-Version'] = '4.0'
    return response
<commit_msg>allow primary keys to also get marked as sensitive<commit_after>from django.http import HttpResponse, JsonResponse, Http404
from django.template.loader import render_to_string
from django.utils.decorators import method_decorator
from django.views import View

from corehq import privileges
from corehq.apps.accounting.decorators import requires_privilege_with_fallback
from corehq.apps.api.odata.utils import (
    get_case_odata_fields_from_config,
    get_form_odata_fields_from_config,
)
from corehq.apps.domain.decorators import basic_auth_or_try_api_key_auth
from corehq.apps.export.models import CaseExportInstance, FormExportInstance
from corehq.apps.export.views.utils import user_can_view_odata_feed
from corehq.apps.users.decorators import require_permission
from corehq.apps.users.models import Permissions
from corehq.util import get_document_or_404
from corehq.util.view_utils import absolute_reverse

odata_auth = method_decorator([
    basic_auth_or_try_api_key_auth,
    requires_privilege_with_fallback(privileges.ODATA_FEED),
    require_permission(Permissions.edit_data, login_decorator=None),
], name='dispatch')

class BaseODataView(View):

    def dispatch(self, request, *args, **kwargs):
        if not user_can_view_odata_feed(request.domain, request.couch_user):
            raise Http404()
        return super(BaseODataView, self).dispatch(request, *args, **kwargs)

@odata_auth
class ODataCaseServiceView(BaseODataView):

    urlname = 'odata_case_service_from_export_instance'
    table_urlname = 'odata_case_service_from_export_instance_table'

    def get(self, request, domain, config_id, **kwargs):
        table_id = int(kwargs.get('table_id', 0))
        urlname = ODataCaseMetadataView.urlname
        url_args = [domain, config_id]
        if table_id > 0:
            urlname = ODataCaseMetadataView.table_urlname
            url_args.append(table_id)
        service_document_content = {
            '@odata.context': absolute_reverse(urlname, args=url_args),
            'value': [{
                'name': 'feed',
                'kind': 'EntitySet',
                'url': 'feed',
            }]
        }
        return add_odata_headers(JsonResponse(service_document_content))

@odata_auth
class ODataCaseMetadataView(BaseODataView):

    urlname = 'odata_case_metadata_from_export_instance'
    table_urlname = 'odata_case_metadata_from_export_instance_table'

    def get(self, request, domain, config_id, **kwargs):
        table_id = int(kwargs.get('table_id', 0))
        config = get_document_or_404(CaseExportInstance, domain, config_id)
        case_fields = get_case_odata_fields_from_config(config, table_id)

        field_names = [f.name for f in case_fields]
        primary_key = 'caseid' if table_id == 0 else 'number'
        if f'{primary_key} *sensitive*' in field_names:
            primary_key = f'{primary_key} *sensitive*'

        metadata = render_to_string('api/odata_metadata.xml', {
            'fields': case_fields,
            'primary_key': primary_key,
        })
        return add_odata_headers(HttpResponse(metadata, content_type='application/xml'))

@odata_auth
class ODataFormServiceView(BaseODataView):

    urlname = 'odata_form_service_from_export_instance'
    table_urlname = 'odata_form_service_from_export_instance_table'

    def get(self, request, domain, config_id, **kwargs):
        table_id = int(kwargs.get('table_id', 0))
        urlname = ODataFormMetadataView.urlname
        url_args = [domain, config_id]
        if table_id > 0:
            urlname = ODataFormMetadataView.table_urlname
            url_args.append(table_id)
        service_document_content = {
            '@odata.context': absolute_reverse(urlname, args=url_args),
            'value': [{
                'name': 'feed',
                'kind': 'EntitySet',
                'url': 'feed',
            }]
        }
        return add_odata_headers(JsonResponse(service_document_content))

@odata_auth
class ODataFormMetadataView(BaseODataView):

    urlname = 'odata_form_metadata_from_export_instance'
    table_urlname = 'odata_form_metadata_from_export_instance_table'

    def get(self, request, domain, config_id, **kwargs):
        table_id = int(kwargs.get('table_id', 0))
        config = get_document_or_404(FormExportInstance, domain, config_id)
        form_fields = get_form_odata_fields_from_config(config, table_id)

        field_names = [f.name for f in form_fields]
        primary_key = 'formid' if table_id == 0 else 'number'
        if f'{primary_key} *sensitive*' in field_names:
            primary_key = f'{primary_key} *sensitive*'

        metadata = render_to_string('api/odata_metadata.xml', {
            'fields': form_fields,
            'primary_key': primary_key,
        })
        return add_odata_headers(HttpResponse(metadata, content_type='application/xml'))

def add_odata_headers(response):
    response['OData-Version'] = '4.0'
    return response
<|endoftext|>


<commit_before>import itertools
import logging
from datetime import date

from django.apps import apps
from django.conf import settings
from django.db import connection, transaction
from django.db.models import Q

from dimagi.utils.chunked import chunked

from corehq.apps.accounting.models import Subscription
from corehq.apps.accounting.utils import get_change_status
from corehq.apps.custom_data_fields.dbaccessors import get_by_domain_and_type
from corehq.apps.domain.utils import silence_during_tests
from corehq.apps.locations.views import LocationFieldsView
from corehq.apps.products.views import ProductFieldsView
from corehq.apps.userreports.dbaccessors import (
    delete_all_ucr_tables_for_domain,
)
from corehq.apps.users.views.mobile import UserFieldsView
from corehq.blobs import CODES, get_blob_db
from corehq.blobs.models import BlobMeta
from corehq.form_processor.backends.sql.dbaccessors import doc_type_to_state
from corehq.form_processor.interfaces.dbaccessors import (
    CaseAccessors,
    FormAccessors,
)
from corehq.util.log import with_progress_bar

logger = logging.getLogger(__name__)

class BaseDeletion(object):

    def __init__(self, app_label):
        self.app_label = app_label

    def is_app_installed(self):
        try:
            return bool(apps.get_app_config(self.app_label))
        except LookupError:
            return False

class CustomDeletion(BaseDeletion):

    def __init__(self, app_label, deletion_fn):
        super(CustomDeletion, self).__init__(app_label)
        self.deletion_fn = deletion_fn

    def execute(self, domain_name):
        if self.is_app_installed():
            self.deletion_fn(domain_name)

class RawDeletion(BaseDeletion):

    def __init__(self, app_label, raw_query):
        super(RawDeletion, self).__init__(app_label)
        self.raw_query = raw_query

    def execute(self, cursor, domain_name):
        if self.is_app_installed():
            cursor.execute(self.raw_query, [domain_name])

class ModelDeletion(BaseDeletion):

    def __init__(self, app_label, model_name, domain_filter_kwarg):
        super(ModelDeletion, self).__init__(app_label)
        self.domain_filter_kwarg = domain_filter_kwarg
        self.model_name = model_name

    def get_model_class(self):
        return apps.get_model(self.app_label, self.model_name)

    def execute(self, domain_name):
        if not domain_name:
            # The Django orm will properly turn a None domain_name to a
            # IS NULL filter. We don't want to allow deleting records for
            # NULL domain names since they might have special meaning (like
            # in some of the SMS models).
            raise RuntimeError("Expected a valid domain name")
        if self.is_app_installed():
            model = self.get_model_class()
            model.objects.filter(**{self.domain_filter_kwarg: domain_name}).delete()

def _delete_domain_backend_mappings(domain_name):
    model = apps.get_model('sms', 'SQLMobileBackendMapping')
    model.objects.filter(is_global=False, domain=domain_name).delete()

def _delete_domain_backends(domain_name):
    model = apps.get_model('sms', 'SQLMobileBackend')
    model.objects.filter(is_global=False, domain=domain_name).delete()

def _delete_web_user_membership(domain_name):
    from corehq.apps.users.models import WebUser
    active_web_users = WebUser.by_domain(domain_name)
    inactive_web_users = WebUser.by_domain(domain_name, is_active=False)
    for web_user in list(active_web_users) + list(inactive_web_users):
        web_user.delete_domain_membership(domain_name)
        if settings.UNIT_TESTING and not web_user.domain_memberships:
            web_user.delete()
        else:
            web_user.save()

def _terminate_subscriptions(domain_name):
    today = date.today()

    with transaction.atomic():
        current_subscription = Subscription.get_active_subscription_by_domain(domain_name)

        if current_subscription:
            current_subscription.date_end = today
            current_subscription.is_active = False
            current_subscription.save()

            current_subscription.transfer_credits()

            _, downgraded_privs, upgraded_privs = get_change_status(current_subscription.plan_version, None)
            current_subscription.subscriber.deactivate_subscription(
                downgraded_privileges=downgraded_privs,
                upgraded_privileges=upgraded_privs,
                old_subscription=current_subscription,
                new_subscription=None,
            )

        Subscription.visible_objects.filter(
            Q(date_start__gt=today) | Q(date_start=today, is_active=False),
            subscriber__domain=domain_name,
        ).update(is_hidden_to_ops=True)

def _delete_all_cases(domain_name):
    logger.info('Deleting cases...')
    case_accessor = CaseAccessors(domain_name)
    case_ids = case_accessor.get_case_ids_in_domain()
    for case_id_chunk in chunked(with_progress_bar(case_ids, stream=silence_during_tests()), 500):
        case_accessor.soft_delete_cases(list(case_id_chunk))
    logger.info('Deleting cases complete.')

def _delete_all_forms(domain_name):
    logger.info('Deleting forms...')
    form_accessor = FormAccessors(domain_name)
    form_ids = list(itertools.chain(*[
        form_accessor.get_all_form_ids_in_domain(doc_type=doc_type)
        for doc_type in doc_type_to_state
    ]))
    for form_id_chunk in chunked(with_progress_bar(form_ids, stream=silence_during_tests()), 500):
        form_accessor.soft_delete_forms(list(form_id_chunk))
    logger.info('Deleting forms complete.')

def _delete_data_files(domain_name):
    get_blob_db().bulk_delete(metas=list(BlobMeta.objects.partitioned_query(domain_name).filter(
        parent_id=domain_name,
        type_code=CODES.data_file,
    )))

def _delete_custom_data_fields(domain_name):
    # The CustomDataFieldsDefinition instances are cleaned up as part of the
    # bulk couch delete, but we also need to clear the cache
    logger.info('Deleting custom data fields...')
    for field_view in [LocationFieldsView, ProductFieldsView, UserFieldsView]:
        get_by_domain_and_type.clear(domain_name, field_view.field_type)
    logger.info('Deleting custom data fields complete.')

# We use raw queries instead of ORM because Django queryset delete needs to
# fetch objects into memory to send signals and handle cascades. It makes deletion very slow
# if we have a millions of rows in stock data tables.
DOMAIN_DELETE_OPERATIONS = [
    RawDeletion('stock', """
        DELETE FROM stock_stocktransaction
        WHERE report_id IN (SELECT id FROM stock_stockreport WHERE domain=%s)
    """),
    RawDeletion('stock', "DELETE FROM stock_stockreport WHERE domain=%s"),
    RawDeletion('stock', """
        DELETE FROM commtrack_stockstate
        WHERE product_id IN (SELECT product_id FROM products_sqlproduct WHERE domain=%s)
    """),
    ModelDeletion('products', 'SQLProduct', 'domain'),
    ModelDeletion('locations', 'SQLLocation', 'domain'),
    ModelDeletion('locations', 'LocationType', 'domain'),
    ModelDeletion('stock', 'DocDomainMapping', 'domain_name'),
    ModelDeletion('domain_migration_flags', 'DomainMigrationProgress', 'domain'),
    ModelDeletion('sms', 'DailyOutboundSMSLimitReached', 'domain'),
    ModelDeletion('sms', 'SMS', 'domain'),
    ModelDeletion('sms', 'SQLLastReadMessage', 'domain'),
    ModelDeletion('sms', 'ExpectedCallback', 'domain'),
    ModelDeletion('ivr', 'Call', 'domain'),
    ModelDeletion('sms', 'Keyword', 'domain'),
    ModelDeletion('sms', 'PhoneNumber', 'domain'),
    ModelDeletion('sms', 'MessagingSubEvent', 'parent__domain'),
    ModelDeletion('sms', 'MessagingEvent', 'domain'),
    ModelDeletion('sms', 'QueuedSMS', 'domain'),
    ModelDeletion('sms', 'SelfRegistrationInvitation', 'domain'),
    CustomDeletion('sms', _delete_domain_backend_mappings),
    ModelDeletion('sms', 'MobileBackendInvitation', 'domain'),
    CustomDeletion('sms', _delete_domain_backends),
    CustomDeletion('users', _delete_web_user_membership),
    CustomDeletion('accounting', _terminate_subscriptions),
    CustomDeletion('form_processor', _delete_all_cases),
    CustomDeletion('form_processor', _delete_all_forms),
    ModelDeletion('aggregate_ucrs', 'AggregateTableDefinition', 'domain'),
    ModelDeletion('app_manager', 'AppReleaseByLocation', 'domain'),
    ModelDeletion('app_manager', 'LatestEnabledBuildProfiles', 'domain'),
    ModelDeletion('app_manager', 'ResourceOverride', 'domain'),
    ModelDeletion('app_manager', 'GlobalAppConfig', 'domain'),
    ModelDeletion('case_importer', 'CaseUploadRecord', 'domain'),
    ModelDeletion('case_search', 'CaseSearchConfig', 'domain'),
    ModelDeletion('case_search', 'CaseSearchQueryAddition', 'domain'),
    ModelDeletion('case_search', 'FuzzyProperties', 'domain'),
    ModelDeletion('case_search', 'IgnorePatterns', 'domain'),
    ModelDeletion('cloudcare', 'ApplicationAccess', 'domain'),
    ModelDeletion('consumption', 'SQLDefaultConsumption', 'domain'),
    ModelDeletion('data_analytics', 'GIRRow', 'domain_name'),
    ModelDeletion('data_analytics', 'MALTRow', 'domain_name'),
    ModelDeletion('data_dictionary', 'CaseType', 'domain'),
    ModelDeletion('data_interfaces', 'CaseRuleAction', 'rule__domain'),
    ModelDeletion('data_interfaces', 'CaseRuleCriteria', 'rule__domain'),
    ModelDeletion('data_interfaces', 'CaseRuleSubmission', 'rule__domain'),
    ModelDeletion('data_interfaces', 'CaseRuleSubmission', 'domain'),  # TODO
    ModelDeletion('data_interfaces', 'AutomaticUpdateRule', 'domain'),
    ModelDeletion('data_interfaces', 'DomainCaseRuleRun', 'domain'),
    ModelDeletion('domain', 'TransferDomainRequest', 'domain'),
    ModelDeletion('export', 'EmailExportWhenDoneRequest', 'domain'),
    CustomDeletion('export', _delete_data_files),
    ModelDeletion('locations', 'LocationFixtureConfiguration', 'domain'),
    ModelDeletion('ota', 'MobileRecoveryMeasure', 'domain'),
    ModelDeletion('ota', 'SerialIdBucket', 'domain'),
    ModelDeletion('phone', 'OwnershipCleanlinessFlag', 'domain'),
    ModelDeletion('phone', 'SyncLogSQL', 'domain'),
    ModelDeletion('registration', 'RegistrationRequest', 'domain'),
    ModelDeletion('reminders', 'EmailUsage', 'domain'),
    ModelDeletion('reports', 'ReportsSidebarOrdering', 'domain'),
    ModelDeletion('smsforms', 'SQLXFormsSession', 'domain'),
    ModelDeletion('translations', 'SMSTranslations', 'domain'),
    ModelDeletion('translations', 'TransifexBlacklist', 'domain'),
    ModelDeletion('userreports', 'AsyncIndicator', 'domain'),
    ModelDeletion('users', 'DomainRequest', 'domain'),
    ModelDeletion('users', 'SQLInvitation', 'domain'),
    ModelDeletion('zapier', 'ZapierSubscription', 'domain'),
    ModelDeletion('dhis2', 'Dhis2Connection', 'domain'),
    ModelDeletion('motech', 'RequestLog', 'domain'),
    ModelDeletion('couchforms', 'UnfinishedSubmissionStub', 'domain'),
    CustomDeletion('custom_data_fields', _delete_custom_data_fields),
    CustomDeletion('ucr', delete_all_ucr_tables_for_domain),
]

def apply_deletion_operations(domain_name):
    raw_ops, model_ops = _split_ops_by_type(DOMAIN_DELETE_OPERATIONS)

    with connection.cursor() as cursor:
        for op in raw_ops:
            op.execute(cursor, domain_name)

    for op in model_ops:
        op.execute(domain_name)

def _split_ops_by_type(ops):
    raw_ops = []
    model_ops = []
    for op in ops:
        if isinstance(op, RawDeletion):
            raw_ops.append(op)
        else:
            model_ops.append(op)
    return raw_ops, model_ops
<commit_msg>Updated DOMAIN_DELETE_OPERATIONS (PR1)<commit_after>import itertools
import logging
from datetime import date

from django.apps import apps
from django.conf import settings
from django.db import connection, transaction
from django.db.models import Q

from dimagi.utils.chunked import chunked

from corehq.apps.accounting.models import Subscription
from corehq.apps.accounting.utils import get_change_status
from corehq.apps.custom_data_fields.dbaccessors import get_by_domain_and_type
from corehq.apps.domain.utils import silence_during_tests
from corehq.apps.locations.views import LocationFieldsView
from corehq.apps.products.views import ProductFieldsView
from corehq.apps.userreports.dbaccessors import (
    delete_all_ucr_tables_for_domain,
)
from corehq.apps.users.views.mobile import UserFieldsView
from corehq.blobs import CODES, get_blob_db
from corehq.blobs.models import BlobMeta
from corehq.form_processor.backends.sql.dbaccessors import doc_type_to_state
from corehq.form_processor.interfaces.dbaccessors import (
    CaseAccessors,
    FormAccessors,
)
from corehq.util.log import with_progress_bar

logger = logging.getLogger(__name__)

class BaseDeletion(object):

    def __init__(self, app_label):
        self.app_label = app_label

    def is_app_installed(self):
        try:
            return bool(apps.get_app_config(self.app_label))
        except LookupError:
            return False

class CustomDeletion(BaseDeletion):

    def __init__(self, app_label, deletion_fn):
        super(CustomDeletion, self).__init__(app_label)
        self.deletion_fn = deletion_fn

    def execute(self, domain_name):
        if self.is_app_installed():
            self.deletion_fn(domain_name)

class RawDeletion(BaseDeletion):

    def __init__(self, app_label, raw_query):
        super(RawDeletion, self).__init__(app_label)
        self.raw_query = raw_query

    def execute(self, cursor, domain_name):
        if self.is_app_installed():
            cursor.execute(self.raw_query, [domain_name])

class ModelDeletion(BaseDeletion):

    def __init__(self, app_label, model_name, domain_filter_kwarg):
        super(ModelDeletion, self).__init__(app_label)
        self.domain_filter_kwarg = domain_filter_kwarg
        self.model_name = model_name

    def get_model_class(self):
        return apps.get_model(self.app_label, self.model_name)

    def execute(self, domain_name):
        if not domain_name:
            # The Django orm will properly turn a None domain_name to a
            # IS NULL filter. We don't want to allow deleting records for
            # NULL domain names since they might have special meaning (like
            # in some of the SMS models).
            raise RuntimeError("Expected a valid domain name")
        if self.is_app_installed():
            model = self.get_model_class()
            model.objects.filter(**{self.domain_filter_kwarg: domain_name}).delete()

def _delete_domain_backend_mappings(domain_name):
    model = apps.get_model('sms', 'SQLMobileBackendMapping')
    model.objects.filter(is_global=False, domain=domain_name).delete()

def _delete_domain_backends(domain_name):
    model = apps.get_model('sms', 'SQLMobileBackend')
    model.objects.filter(is_global=False, domain=domain_name).delete()

def _delete_web_user_membership(domain_name):
    from corehq.apps.users.models import WebUser
    active_web_users = WebUser.by_domain(domain_name)
    inactive_web_users = WebUser.by_domain(domain_name, is_active=False)
    for web_user in list(active_web_users) + list(inactive_web_users):
        web_user.delete_domain_membership(domain_name)
        if settings.UNIT_TESTING and not web_user.domain_memberships:
            web_user.delete()
        else:
            web_user.save()

def _terminate_subscriptions(domain_name):
    today = date.today()

    with transaction.atomic():
        current_subscription = Subscription.get_active_subscription_by_domain(domain_name)

        if current_subscription:
            current_subscription.date_end = today
            current_subscription.is_active = False
            current_subscription.save()

            current_subscription.transfer_credits()

            _, downgraded_privs, upgraded_privs = get_change_status(current_subscription.plan_version, None)
            current_subscription.subscriber.deactivate_subscription(
                downgraded_privileges=downgraded_privs,
                upgraded_privileges=upgraded_privs,
                old_subscription=current_subscription,
                new_subscription=None,
            )

        Subscription.visible_objects.filter(
            Q(date_start__gt=today) | Q(date_start=today, is_active=False),
            subscriber__domain=domain_name,
        ).update(is_hidden_to_ops=True)

def _delete_all_cases(domain_name):
    logger.info('Deleting cases...')
    case_accessor = CaseAccessors(domain_name)
    case_ids = case_accessor.get_case_ids_in_domain()
    for case_id_chunk in chunked(with_progress_bar(case_ids, stream=silence_during_tests()), 500):
        case_accessor.soft_delete_cases(list(case_id_chunk))
    logger.info('Deleting cases complete.')

def _delete_all_forms(domain_name):
    logger.info('Deleting forms...')
    form_accessor = FormAccessors(domain_name)
    form_ids = list(itertools.chain(*[
        form_accessor.get_all_form_ids_in_domain(doc_type=doc_type)
        for doc_type in doc_type_to_state
    ]))
    for form_id_chunk in chunked(with_progress_bar(form_ids, stream=silence_during_tests()), 500):
        form_accessor.soft_delete_forms(list(form_id_chunk))
    logger.info('Deleting forms complete.')

def _delete_data_files(domain_name):
    get_blob_db().bulk_delete(metas=list(BlobMeta.objects.partitioned_query(domain_name).filter(
        parent_id=domain_name,
        type_code=CODES.data_file,
    )))

def _delete_custom_data_fields(domain_name):
    # The CustomDataFieldsDefinition instances are cleaned up as part of the
    # bulk couch delete, but we also need to clear the cache
    logger.info('Deleting custom data fields...')
    for field_view in [LocationFieldsView, ProductFieldsView, UserFieldsView]:
        get_by_domain_and_type.clear(domain_name, field_view.field_type)
    logger.info('Deleting custom data fields complete.')

# We use raw queries instead of ORM because Django queryset delete needs to
# fetch objects into memory to send signals and handle cascades. It makes deletion very slow
# if we have a millions of rows in stock data tables.
DOMAIN_DELETE_OPERATIONS = [
    RawDeletion('stock', """
        DELETE FROM stock_stocktransaction
        WHERE report_id IN (SELECT id FROM stock_stockreport WHERE domain=%s)
    """),
    RawDeletion('stock', "DELETE FROM stock_stockreport WHERE domain=%s"),
    RawDeletion('stock', """
        DELETE FROM commtrack_stockstate
        WHERE product_id IN (SELECT product_id FROM products_sqlproduct WHERE domain=%s)
    """),
    ModelDeletion('products', 'SQLProduct', 'domain'),
    ModelDeletion('locations', 'SQLLocation', 'domain'),
    ModelDeletion('locations', 'LocationType', 'domain'),
    ModelDeletion('stock', 'DocDomainMapping', 'domain_name'),
    ModelDeletion('domain_migration_flags', 'DomainMigrationProgress', 'domain'),
    ModelDeletion('sms', 'DailyOutboundSMSLimitReached', 'domain'),
    ModelDeletion('sms', 'SMS', 'domain'),
    ModelDeletion('sms', 'SQLLastReadMessage', 'domain'),
    ModelDeletion('sms', 'ExpectedCallback', 'domain'),
    ModelDeletion('ivr', 'Call', 'domain'),
    ModelDeletion('sms', 'Keyword', 'domain'),
    ModelDeletion('sms', 'PhoneNumber', 'domain'),
    ModelDeletion('sms', 'MessagingSubEvent', 'parent__domain'),
    ModelDeletion('sms', 'MessagingEvent', 'domain'),
    ModelDeletion('sms', 'QueuedSMS', 'domain'),
    ModelDeletion('sms', 'SelfRegistrationInvitation', 'domain'),
    CustomDeletion('sms', _delete_domain_backend_mappings),
    ModelDeletion('sms', 'MobileBackendInvitation', 'domain'),
    CustomDeletion('sms', _delete_domain_backends),
    CustomDeletion('users', _delete_web_user_membership),
    CustomDeletion('accounting', _terminate_subscriptions),
    CustomDeletion('form_processor', _delete_all_cases),
    CustomDeletion('form_processor', _delete_all_forms),
    ModelDeletion('aggregate_ucrs', 'AggregateTableDefinition', 'domain'),
    ModelDeletion('app_manager', 'AppReleaseByLocation', 'domain'),
    ModelDeletion('app_manager', 'LatestEnabledBuildProfiles', 'domain'),
    ModelDeletion('app_manager', 'ResourceOverride', 'domain'),
    ModelDeletion('app_manager', 'GlobalAppConfig', 'domain'),
    ModelDeletion('case_importer', 'CaseUploadRecord', 'domain'),
    ModelDeletion('case_search', 'CaseSearchConfig', 'domain'),
    ModelDeletion('case_search', 'CaseSearchQueryAddition', 'domain'),
    ModelDeletion('case_search', 'FuzzyProperties', 'domain'),
    ModelDeletion('case_search', 'IgnorePatterns', 'domain'),
    ModelDeletion('cloudcare', 'ApplicationAccess', 'domain'),
    ModelDeletion('consumption', 'SQLDefaultConsumption', 'domain'),
    ModelDeletion('custom_data_fields', 'SQLCustomDataFieldsDefinition', 'domain'),
    ModelDeletion('data_analytics', 'GIRRow', 'domain_name'),
    ModelDeletion('data_analytics', 'MALTRow', 'domain_name'),
    ModelDeletion('data_dictionary', 'CaseType', 'domain'),
    ModelDeletion('data_interfaces', 'CaseRuleAction', 'rule__domain'),
    ModelDeletion('data_interfaces', 'CaseRuleCriteria', 'rule__domain'),
    ModelDeletion('data_interfaces', 'CaseRuleSubmission', 'rule__domain'),
    ModelDeletion('data_interfaces', 'CaseRuleSubmission', 'domain'),  # TODO
    ModelDeletion('data_interfaces', 'AutomaticUpdateRule', 'domain'),
    ModelDeletion('data_interfaces', 'DomainCaseRuleRun', 'domain'),
    ModelDeletion('domain', 'TransferDomainRequest', 'domain'),
    ModelDeletion('export', 'EmailExportWhenDoneRequest', 'domain'),
    CustomDeletion('export', _delete_data_files),
    ModelDeletion('locations', 'LocationFixtureConfiguration', 'domain'),
    ModelDeletion('ota', 'MobileRecoveryMeasure', 'domain'),
    ModelDeletion('ota', 'SerialIdBucket', 'domain'),
    ModelDeletion('phone', 'OwnershipCleanlinessFlag', 'domain'),
    ModelDeletion('phone', 'SyncLogSQL', 'domain'),
    ModelDeletion('registration', 'RegistrationRequest', 'domain'),
    ModelDeletion('reminders', 'EmailUsage', 'domain'),
    ModelDeletion('reports', 'ReportsSidebarOrdering', 'domain'),
    ModelDeletion('smsforms', 'SQLXFormsSession', 'domain'),
    ModelDeletion('translations', 'SMSTranslations', 'domain'),
    ModelDeletion('translations', 'TransifexBlacklist', 'domain'),
    ModelDeletion('userreports', 'AsyncIndicator', 'domain'),
    ModelDeletion('users', 'DomainRequest', 'domain'),
    ModelDeletion('users', 'SQLInvitation', 'domain'),
    ModelDeletion('zapier', 'ZapierSubscription', 'domain'),
    ModelDeletion('dhis2', 'Dhis2Connection', 'domain'),
    ModelDeletion('motech', 'RequestLog', 'domain'),
    ModelDeletion('couchforms', 'UnfinishedSubmissionStub', 'domain'),
    CustomDeletion('custom_data_fields', _delete_custom_data_fields),
    CustomDeletion('ucr', delete_all_ucr_tables_for_domain),
]

def apply_deletion_operations(domain_name):
    raw_ops, model_ops = _split_ops_by_type(DOMAIN_DELETE_OPERATIONS)

    with connection.cursor() as cursor:
        for op in raw_ops:
            op.execute(cursor, domain_name)

    for op in model_ops:
        op.execute(domain_name)

def _split_ops_by_type(ops):
    raw_ops = []
    model_ops = []
    for op in ops:
        if isinstance(op, RawDeletion):
            raw_ops.append(op)
        else:
            model_ops.append(op)
    return raw_ops, model_ops
<|endoftext|>


<commit_before>#!/usr/local/bin/python3

import sys, re, inspect, os, textwrap, shutil, jsonpickle, csv

from modules.bgcolors import BgColors
from modules.world import World
from modules.player import Player
from modules import actions
from modules import tiles
from modules import items
from modules import armor
from modules import weapons
from modules import serums
from modules import enemies
from modules import merchants
from modules import repair
from modules.helpers.health import Health
from modules.helpers.state import State

from tkinter import *
from openpyxl import load_workbook
from jsonpickle.unpickler import Unpickler

# The only way the program stops is if the player wins, loses, or quits. To handle this behavior,
# games usually run inside a loop. On each iteration, the game state is updated and input is received
# from the human player. In graphical games, the loop runs many times per second. Since we dont need
# to continually refresh the players screen for a text game, our code will actually pause until the player provides input.
class App :
	player = None

	def __init__(self):
		# override the standard sys output to redirect the typical built-in print() command
		sys.stdout.write = self.print_redirect

		self.next_method 	= None
		self.action 		= None
		self.tag			= None

		########### SETUP THE GAME WINDOW FRAME #############
		# Initialize the tkinter object
		self.root = Tk()
		# set window opacity
		self.root.attributes('-alpha', 0.85)
		self.root.geometry("900x800")
		# set the application title
		self.root.title("The Europa Protocol - Adventure Game")

		# bind an event exection on the "enter" key user event
		self.root.bind('<Return>', self.inputText)

		# Set the frame background, font color, and size of the text window
		self.mainframe = Text(self.root, bg='black', fg='white')
		self.mainframe.grid(column=0, row=0, sticky=(N,W,E,S))

		# The "columnconfigure"/"rowconfigure" bits just tell Tk that if the main window is resized, the frame should expand to take up the extra space.
		self.mainframe.columnconfigure(0, weight=1)
		self.mainframe.rowconfigure(0, weight=1)

		### Create the textbox for inputting commands
		# Declare the textbox variable
		self.inputline = StringVar()
		# initialize the textbox widget
		self.inputline_entry = Entry(self.root, textvariable=self.inputline)
		self.inputline_entry.grid(sticky=(W,E,S))

		# focus the cursor in the inputline action box
		self.inputline_entry.focus_set()

		# make the application window expandable
		self.root.grid_columnconfigure(0, weight=1)
		self.root.grid_rowconfigure(0, weight=1)

		# initialize all the Text widget tag configurations to be used to change colors later
		BgColors(self.mainframe)

		self.print_intro()
		# attempt to load previous game state, or create new game state if no previous is found
		self.load_game_state()

	def inputText(self, event, player=None):
		if (self.player and Health.is_alive(self.player)) or not player:
			# get the text from the input box
			i = self.inputline.get().lower().strip()
			# delete the contents from the input box
			self.inputline_entry.delete(0,'end')
			# send the contents of the input box to the print function
			print("\n" + BgColors.NORMAL + "Your Action: " + i )
			# execute the next method in line, set by previous call
			#eval('self.%s(%s)' % (self.next_method, i))
			self.next_method(i)

	def print_redirect(self, inputStr):
		# set an empty tag tuple
		#tag = ('NORMAL',)
		tag = None
		if BgColors.HEADER in inputStr :
			tag = ('HEADER',)
		elif BgColors.OKBLUE in inputStr :
			tag = ('OKBLUE',)
		elif BgColors.SKYBLUE in inputStr :
			tag = ('SKYBLUE',)
		elif BgColors.CADETBLUE in inputStr :
			tag = ('CADETBLUE',)
		elif BgColors.OKGREEN in inputStr :
			tag = ('OKGREEN',)
		elif BgColors.WARNING in inputStr :
			tag = ('WARNING',)
		elif BgColors.FAIL in inputStr :
			tag = ('FAIL',)
		elif BgColors.NORMAL in inputStr :
			tag = ('NORMAL',)
		elif BgColors.ENDC in inputStr:
			tag = ()

		if not tag and self.tag :
			tag = self.tag

		self.tag = tag

		# replace reference to [color] and [endc] identifier in text string
		inputStr = re.sub(r'(\[!\w+!])', '', inputStr)
		# add the text to the window widget
		self.mainframe.configure(state='normal')
		self.mainframe.insert("end-1c", inputStr, tag)
		self.mainframe.configure(state='disabled')
		# automtically scroll to the end of the mainframe window
		self.mainframe.see(END)

	def load_game_state(self):
		# check if there is a game save file with a previously saved state
		if os.path.exists('res/saved/gsave.pkl') :
			# prompt the user to answer if they want to load from a saved state
			#action_input = input( BgColors.HEADER + 'Load Saved Game? [y/n]: ' + BgColors.ENDC).lower()
			print( BgColors.HEADER + 'Load Saved Game? [y/n]: ' + BgColors.ENDC )
			self.next_method = self.load_game_state_check
		# otherwise a save file was not found
		else :
			# create the world state from scratch
			self.create_new_world()

	def load_game_state_check(self, input):
		# if the answer is yes, they want to load from the previous save, then attempt to load
		if input.lower() == 'y' :
			# open the save state file
			with open('res/saved/gsave.pkl', 'r') as output:
				# assign player object as the pickled object, decoded
				self.player = jsonpickle.decode(output.read())
				# assign the world object as the player.world property
				self.world = self.player.world

			self.load_starting_position()
		# if the user answered no, they do not want to load from saved state, then start a new game and load all objects with original states
		elif input.lower() == 'n' :
			self.create_new_world()

		# if the user didn't answer with a yes or no response, then loop again with an error message
		elif input.lower() not in ['y','n'] :
			print("{}You must provide a [y/n] answer!{}".format(BgColors.FAIL, BgColors.ENDC))
			self.load_game_state()

	def create_new_world(self):
		self.world = World()
		self.player = Player(self.world)

		self.load_starting_position()

	def load_starting_position(self):
		# These lines load the starting room and display the text
		self.player.room = self.world.tile_exists(self.player.location_x, self.player.location_y)

		# print the room intro text
		#print(re.sub(r'(^[ \t]+|[ \t]+(?=:))', '', "\n" + BgColors.NORMAL + self.player.room.intro_text() + BgColors.ENDC, flags=re.M))
		print(BgColors.NORMAL + "─"*70)
		print(BgColors.NORMAL + "\n" + self.player.room.intro_text() + BgColors.ENDC)
		self.world.tile_exists(self.player.location_x, self.player.location_y).visited = True

		# start the main play execution sequence
		self.play()

	def play(self):
		# check if the player is alive, end game if not
		if not Health.is_alive(self.player):
			State.game_end()

		# if player is alive, and has not achieved victory, then continue with main logic
		elif not self.player.victory :
			# The first thing the loop does is find out what room the player is in and then executes the behavior for that room.
			self.player.room = self.world.tile_exists(self.player.location_x, self.player.location_y)

			if not (isinstance(self.action, (actions.ItemAction,actions.HiddenAction))) and ( (issubclass(self.player.room.__class__, tiles.EnemyRoom) and isinstance(self.action, actions.Attack)) or issubclass(self.player.room.__class__, tiles.LeaveCaveRoom) ):
				self.player.room.modify_player(self.player)

			# display the mini help options for available options (not extended help view)
			#if not isinstance(self.action, actions.HiddenAction):
			self.player.help()

			# prompt the user to input an action
			#print(BgColors.HEADER + '\n\nAction: ' + BgColors.ENDC, end='')
			self.next_method = self.do_action_check
			self.inputline_entry.focus()

	def do_action_check(self, input):
		# get the available actions for the room from the available actions method in each tile class
		available_actions = self.player.room.available_actions(self.player)

		action_found = False
		for action in available_actions:
			#  If the human player provided a matching hotkey, then we execute the associated action using the do_action method.
			if input.strip().split(' ')[0] in action.hotkey:
				action_found = True
				# if there is a space in the command input, then split the content on the space, and use the second item as the key/index passed to the action command
				if len(input.split(' ',1)) > 1:
					action.kwargs.update( {'item': input.split(' ')[1]} )

					# this must mean an additional argument was passed, like a keycode to follow the usage of a keypad
					if len(input.split(' ')) > 2:
						action.kwargs.update( {'code': input.split(' ')[2]} )

				action.kwargs.update({'player': self.player})

				# set the instance action attribute for use in other class methods
				self.action = action
				print("\n" + BgColors.NORMAL + "─"*70)

				#self.player.do_action(action, **action.kwargs)

					# Now we need to allow the Player class to take an Action and run the action`s internally-bound method.
				#def do_action(self, action, *args, **kwargs):
				#action_method = getattr(self, action.method.__name__)
				#if action_method:
				#action_method(*args, **kwargs)
				action.method(**action.kwargs)

				break
		# if the action was not found in the available action list
		if not action_found:
			self.action = None
			print("\n" + BgColors.NORMAL + "─"*70)
			print("{}You can't do that! Choose an action from the list below.\nExample: '[command] [#]' to interact with an item.{}".format(BgColors.FAIL, BgColors.ENDC))

			#self.player.help()
		# execute the self.play() iteration again to maintain the loop
		self.play()

	def print_intro(self):
		print( """
 _____ _            _____                              ____            _                  _
|_   _| |__   ___  | ____|   _ _ __ ___  _ __   __ _  |  _ \ _ __ ___ | |_ ___   ___ ___ | |
  | | | '_ \ / _ \ |  _|| | | | '__/ _ \| '_ \ / _` | | |_) | '__/ _ \| __/ _ \ / __/ _ \| |
  | | | | | |  __/ | |__| |_| | | | (_) | |_) | (_| | |  __/| | | (_) | || (_) | (_| (_) | |
  |_| |_| |_|\___| |_____\__,_|_|  \___/| .__/ \__,_| |_|   |_|  \___/ \__\___/ \___\___/|_|
                                        |_|
{}Copyright (C) 2015  Corey Farmer

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program.  If not, see <http://www.gnu.org/licenses/>

Type '?' to view a full list of available actions and ways to
interact within the game.
""".format(BgColors.CADETBLUE) )

class Environment:
	def __init__(self):
		self.map_file = 'res/map.xlsx'
		self.map_output = 'map.txt'

	# create the tab delimited file from the map xlsx document, if found
	def convert_xlsx(self):
		if os.path.isfile(self.map_file):
			wb = load_workbook(self.map_file)
			sh = wb.get_sheet_by_name(self.map_output)

			with open("res/%s" % self.map_output, 'w') as f:
				c = csv.writer(f, delimiter='\t')
				for r in sh.rows:
					c.writerow([cell.value for cell in r])

if __name__ == "__main__":
	try:
		e = Environment()
		e.convert_xlsx()

		a = App()
		a.root.mainloop()

	except Exception:
		raise

	<commit_msg>Update game.py<commit_after>#!/usr/local/bin/python3

import sys, re, inspect, os, textwrap, shutil, jsonpickle, csv

from modules.bgcolors import BgColors
from modules.world import World
from modules.player import Player
from modules import actions
from modules import tiles
from modules import items
from modules import armor
from modules import weapons
from modules import serums
from modules import enemies
from modules import merchants
from modules import repair
from modules.helpers.health import Health
from modules.helpers.state import State

from tkinter import *
from openpyxl import load_workbook
from jsonpickle.unpickler import Unpickler

# The only way the program stops is if the player wins, loses, or quits. To handle this behavior,
# games usually run inside a loop. On each iteration, the game state is updated and input is received
# from the human player. In graphical games, the loop runs many times per second. Since we dont need
# to continually refresh the players screen for a text game, our code will actually pause until the player provides input.
class App :
	player = None

	def __init__(self):
		# override the standard sys output to redirect the typical built-in print() command
		sys.stdout.write = self.print_redirect

		self.next_method 	= None
		self.action 		= None
		self.tag			= None

		########### SETUP THE GAME WINDOW FRAME #############
		# Initialize the tkinter object
		self.root = Tk()
		# set window opacity
		self.root.attributes('-alpha', 0.90)
		self.root.geometry("850x800")
		# set the application title
		self.root.title("The Europa Protocol - Adventure Game")

		# bind an event exection on the "enter" key user event
		self.root.bind('<Return>', self.inputText)

		# Set the frame background, font color, and size of the text window
		self.mainframe = Text(self.root, bg='black', fg='white')
		self.mainframe.grid(column=0, row=0, sticky=(N,W,E,S))

		# The "columnconfigure"/"rowconfigure" bits just tell Tk that if the main window is resized, the frame should expand to take up the extra space.
		self.mainframe.columnconfigure(0, weight=1)
		self.mainframe.rowconfigure(0, weight=1)

		### Create the textbox for inputting commands
		# Declare the textbox variable
		self.inputline = StringVar()
		# initialize the textbox widget
		self.inputline_entry = Entry(self.root, textvariable=self.inputline)
		self.inputline_entry.grid(sticky=(W,E,S))

		# focus the cursor in the inputline action box
		self.inputline_entry.focus_set()

		# make the application window expandable
		self.root.grid_columnconfigure(0, weight=1)
		self.root.grid_rowconfigure(0, weight=1)

		# initialize all the Text widget tag configurations to be used to change colors later
		BgColors(self.mainframe)

		self.print_intro()
		# attempt to load previous game state, or create new game state if no previous is found
		self.load_game_state()

	def inputText(self, event, player=None):
		if (self.player and Health.is_alive(self.player)) or not player:
			# get the text from the input box
			i = self.inputline.get().lower().strip()
			# delete the contents from the input box
			self.inputline_entry.delete(0,'end')
			# send the contents of the input box to the print function
			print("\n" + BgColors.NORMAL + "Your Action: " + i )
			# execute the next method in line, set by previous call
			#eval('self.%s(%s)' % (self.next_method, i))
			self.next_method(i)

	def print_redirect(self, inputStr):
		# set an empty tag tuple
		#tag = ('NORMAL',)
		tag = None
		if BgColors.HEADER in inputStr :
			tag = ('HEADER',)
		elif BgColors.OKBLUE in inputStr :
			tag = ('OKBLUE',)
		elif BgColors.SKYBLUE in inputStr :
			tag = ('SKYBLUE',)
		elif BgColors.CADETBLUE in inputStr :
			tag = ('CADETBLUE',)
		elif BgColors.OKGREEN in inputStr :
			tag = ('OKGREEN',)
		elif BgColors.WARNING in inputStr :
			tag = ('WARNING',)
		elif BgColors.FAIL in inputStr :
			tag = ('FAIL',)
		elif BgColors.NORMAL in inputStr :
			tag = ('NORMAL',)
		elif BgColors.ENDC in inputStr:
			tag = ()

		if not tag and self.tag :
			tag = self.tag

		self.tag = tag

		# replace reference to [color] and [endc] identifier in text string
		inputStr = re.sub(r'(\[!\w+!])', '', inputStr)
		# add the text to the window widget
		self.mainframe.configure(state='normal')
		self.mainframe.insert("end-1c", inputStr, tag)
		self.mainframe.configure(state='disabled')
		# automtically scroll to the end of the mainframe window
		self.mainframe.see(END)

	def load_game_state(self):
		# check if there is a game save file with a previously saved state
		if os.path.exists('res/saved/gsave.pkl') :
			# prompt the user to answer if they want to load from a saved state
			#action_input = input( BgColors.HEADER + 'Load Saved Game? [y/n]: ' + BgColors.ENDC).lower()
			print( BgColors.HEADER + 'Load Saved Game? [y/n]: ' + BgColors.ENDC )
			self.next_method = self.load_game_state_check
		# otherwise a save file was not found
		else :
			# create the world state from scratch
			self.create_new_world()

	def load_game_state_check(self, input):
		# if the answer is yes, they want to load from the previous save, then attempt to load
		if input.lower() == 'y' :
			# open the save state file
			with open('res/saved/gsave.pkl', 'r') as output:
				# assign player object as the pickled object, decoded
				self.player = jsonpickle.decode(output.read())
				# assign the world object as the player.world property
				self.world = self.player.world

			self.load_starting_position()
		# if the user answered no, they do not want to load from saved state, then start a new game and load all objects with original states
		elif input.lower() == 'n' :
			self.create_new_world()

		# if the user didn't answer with a yes or no response, then loop again with an error message
		elif input.lower() not in ['y','n'] :
			print("{}You must provide a [y/n] answer!{}".format(BgColors.FAIL, BgColors.ENDC))
			self.load_game_state()

	def create_new_world(self):
		self.world = World()
		self.player = Player(self.world)

		self.load_starting_position()

	def load_starting_position(self):
		# These lines load the starting room and display the text
		self.player.room = self.world.tile_exists(self.player.location_x, self.player.location_y)

		# print the room intro text
		#print(re.sub(r'(^[ \t]+|[ \t]+(?=:))', '', "\n" + BgColors.NORMAL + self.player.room.intro_text() + BgColors.ENDC, flags=re.M))
		print(BgColors.NORMAL + "─"*70)
		print(BgColors.NORMAL + "\n" + self.player.room.intro_text() + BgColors.ENDC)
		self.world.tile_exists(self.player.location_x, self.player.location_y).visited = True

		# start the main play execution sequence
		self.play()

	def play(self):
		# check if the player is alive, end game if not
		if not Health.is_alive(self.player):
			State.game_end()

		# if player is alive, and has not achieved victory, then continue with main logic
		elif not self.player.victory :
			# The first thing the loop does is find out what room the player is in and then executes the behavior for that room.
			self.player.room = self.world.tile_exists(self.player.location_x, self.player.location_y)

			if not (isinstance(self.action, (actions.ItemAction,actions.HiddenAction))) and ( (issubclass(self.player.room.__class__, tiles.EnemyRoom) and isinstance(self.action, actions.Attack)) or issubclass(self.player.room.__class__, tiles.LeaveCaveRoom) ):
				self.player.room.modify_player(self.player)

			# display the mini help options for available options (not extended help view)
			#if not isinstance(self.action, actions.HiddenAction):
			self.player.help()

			# prompt the user to input an action
			#print(BgColors.HEADER + '\n\nAction: ' + BgColors.ENDC, end='')
			self.next_method = self.do_action_check
			self.inputline_entry.focus()

	def do_action_check(self, input):
		# get the available actions for the room from the available actions method in each tile class
		available_actions = self.player.room.available_actions(self.player)

		action_found = False
		for action in available_actions:
			#  If the human player provided a matching hotkey, then we execute the associated action using the do_action method.
			if input.strip().split(' ')[0] in action.hotkey:
				action_found = True
				# if there is a space in the command input, then split the content on the space, and use the second item as the key/index passed to the action command
				if len(input.split(' ',1)) > 1:
					action.kwargs.update( {'item': input.split(' ')[1]} )

					# this must mean an additional argument was passed, like a keycode to follow the usage of a keypad
					if len(input.split(' ')) > 2:
						action.kwargs.update( {'code': input.split(' ')[2]} )

				action.kwargs.update({'player': self.player})

				# set the instance action attribute for use in other class methods
				self.action = action
				print("\n" + BgColors.NORMAL + "─"*70)

				#self.player.do_action(action, **action.kwargs)

					# Now we need to allow the Player class to take an Action and run the action`s internally-bound method.
				#def do_action(self, action, *args, **kwargs):
				#action_method = getattr(self, action.method.__name__)
				#if action_method:
				#action_method(*args, **kwargs)
				action.method(**action.kwargs)

				break
		# if the action was not found in the available action list
		if not action_found:
			self.action = None
			print("\n" + BgColors.NORMAL + "─"*70)
			print("{}You can't do that! Choose an action from the list below.\nExample: '[command] [#]' to interact with an item.{}".format(BgColors.FAIL, BgColors.ENDC))

			#self.player.help()
		# execute the self.play() iteration again to maintain the loop
		self.play()

	def print_intro(self):
		print( """
 _____ _            _____                              ____            _                  _
|_   _| |__   ___  | ____|   _ _ __ ___  _ __   __ _  |  _ \ _ __ ___ | |_ ___   ___ ___ | |
  | | | '_ \ / _ \ |  _|| | | | '__/ _ \| '_ \ / _` | | |_) | '__/ _ \| __/ _ \ / __/ _ \| |
  | | | | | |  __/ | |__| |_| | | | (_) | |_) | (_| | |  __/| | | (_) | || (_) | (_| (_) | |
  |_| |_| |_|\___| |_____\__,_|_|  \___/| .__/ \__,_| |_|   |_|  \___/ \__\___/ \___\___/|_|
                                        |_|
{}Copyright (C) 2015  Corey Farmer

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

Type '?' to view a full list of available actions and ways to
interact within the game.
""".format(BgColors.CADETBLUE) )

class Environment:
	def __init__(self):
		self.map_file = 'res/map.xlsx'
		self.map_output = 'map.txt'

	# create the tab delimited file from the map xlsx document, if found
	def convert_xlsx(self):
		if os.path.isfile(self.map_file):
			wb = load_workbook(self.map_file)
			sh = wb.get_sheet_by_name(self.map_output)

			with open("res/%s" % self.map_output, 'w', newline='') as f:
				c = csv.writer(f, delimiter='\t')
				for r in sh.rows:
					c.writerow([cell.value for cell in r])

if __name__ == "__main__":
	try:
		e = Environment()
		e.convert_xlsx()

		a = App()
		a.root.mainloop()

	except Exception:
		raise

<|endoftext|>


<commit_before>from django import forms
from corehq.apps.locations.models import Location, root_locations
from django.template.loader import get_template
from django.template import Template, Context
from corehq.apps.locations.util import load_locs_json, allowed_child_types

class ParentLocWidget(forms.Widget):
    def render(self, name, value, attrs=None):
        return get_template('locations/manage/partials/parent_loc_widget.html').render(Context({
                    'name': name,
                    'value': value,
                    'locations': load_locs_json(self.domain, value),
                }))

class LocTypeWidget(forms.Widget):
    def render(self, name, value, attrs=None):
        return get_template('locations/manage/partials/loc_type_widget.html').render(Context({
                    'name': name,
                    'value': value,
                }))

class LocationForm(forms.Form):
    parent_id = forms.CharField(label='Parent', required=False, widget=ParentLocWidget())
    name = forms.CharField(max_length=100)
    location_type = forms.CharField(widget=LocTypeWidget())

    def __init__(self, location, *args, **kwargs):
        self.location = location
        kwargs['initial'] = self.location._doc
        kwargs['initial']['parent_id'] = self.cur_parent_id

        super(LocationForm, self).__init__(*args, **kwargs)

        self.fields['parent_id'].widget.domain = self.location.domain

    @property
    def cur_parent_id(self):
        try:
            return self.location.lineage[0]
        except Exception:
            return None

    def clean_parent_id(self):
        parent_id = self.cleaned_data['parent_id']

        if self.cur_parent_id is not None and self.cur_parent_id != parent_id:
            raise forms.ValidationError('Sorry, you cannot move locations around yet!')

        self.cleaned_data['parent'] = Location.get(parent_id) if parent_id else None
        return parent_id

    def clean_name(self):
        name = self.cleaned_data['name']

        parent = self.cleaned_data['parent']
        siblings = [loc for loc in (parent.children if parent else root_locations(self.location.domain)) if loc._id != self.location._id]
        if name in [loc.name for loc in siblings]:
            raise forms.ValidationError('name conflicts with another location with this parent')

        return name

    def clean_location_type(self):
        loc_type = self.cleaned_data['location_type']

        child_types = allowed_child_types(self.location.domain, self.cleaned_data['parent'])
        # neither of these should be seen in normal usage
        if not child_types:
            raise forms.ValidationError('the selected parent location cannot have sub-locations!')
        elif loc_type not in child_types:
            raise forms.ValidationError('not valid for the select parent location')

        return loc_type

    def save(self, instance=None, commit=True):
        if self.errors:
            raise ValueError('form does not validate')

        location = instance or self.location

        for field in ('name', 'location_type'):
            setattr(location, field, self.cleaned_data[field])
        location.lineage = Location(parent=self.cleaned_data['parent_id']).lineage

        if commit:
            location.save()

        return location
<commit_msg>bugfix<commit_after>from django import forms
from corehq.apps.locations.models import Location, root_locations
from django.template.loader import get_template
from django.template import Template, Context
from corehq.apps.locations.util import load_locs_json, allowed_child_types

class ParentLocWidget(forms.Widget):
    def render(self, name, value, attrs=None):
        return get_template('locations/manage/partials/parent_loc_widget.html').render(Context({
                    'name': name,
                    'value': value,
                    'locations': load_locs_json(self.domain, value),
                }))

class LocTypeWidget(forms.Widget):
    def render(self, name, value, attrs=None):
        return get_template('locations/manage/partials/loc_type_widget.html').render(Context({
                    'name': name,
                    'value': value,
                }))

class LocationForm(forms.Form):
    parent_id = forms.CharField(label='Parent', required=False, widget=ParentLocWidget())
    name = forms.CharField(max_length=100)
    location_type = forms.CharField(widget=LocTypeWidget())

    def __init__(self, location, *args, **kwargs):
        self.location = location
        kwargs['initial'] = self.location._doc
        kwargs['initial']['parent_id'] = self.cur_parent_id

        super(LocationForm, self).__init__(*args, **kwargs)

        self.fields['parent_id'].widget.domain = self.location.domain

    @property
    def cur_parent_id(self):
        try:
            return self.location.lineage[0]
        except Exception:
            return None

    def clean_parent_id(self):
        parent_id = self.cleaned_data['parent_id']

        if self.location._id is not None and self.cur_parent_id != parent_id:
            raise forms.ValidationError('Sorry, you cannot move locations around yet!')

        self.cleaned_data['parent'] = Location.get(parent_id) if parent_id else None
        return parent_id

    def clean_name(self):
        name = self.cleaned_data['name']

        parent = self.cleaned_data.get('parent')
        siblings = [loc for loc in (parent.children if parent else root_locations(self.location.domain)) if loc._id != self.location._id]
        if name in [loc.name for loc in siblings]:
            raise forms.ValidationError('name conflicts with another location with this parent')

        return name

    def clean_location_type(self):
        loc_type = self.cleaned_data['location_type']

        child_types = allowed_child_types(self.location.domain, self.cleaned_data.get('parent'))
        # neither of these should be seen in normal usage
        if not child_types:
            raise forms.ValidationError('the selected parent location cannot have sub-locations!')
        elif loc_type not in child_types:
            raise forms.ValidationError('not valid for the select parent location')

        return loc_type

    def save(self, instance=None, commit=True):
        if self.errors:
            raise ValueError('form does not validate')

        location = instance or self.location

        for field in ('name', 'location_type'):
            setattr(location, field, self.cleaned_data[field])
        location.lineage = Location(parent=self.cleaned_data['parent_id']).lineage

        if commit:
            location.save()

        return location
<|endoftext|>


<commit_before>import pygame
import random

class Game:

    def __init__(self):
        pygame.init()
        self.screen_size = (400, 600)
        self.screen = pygame.display.set_mode(self.screen_size)
        pygame.display.set_caption('Flappy Bird')

        self.img_sizes = {'Bird':(34, 24), 'Pipe':(52, 620)}
        self.score_img = {}
        self.clock = pygame.time.Clock()
        self.ground = self.screen_size[1]-self.img_sizes['Bird'][1]
        self.roof = 0

        self.space_between_pipes = 110 # Space between top and bottom pipes
        self.pipe_limits = 50 # Boundary to blit pipes
        # Upper and lower bound limits to pass to randint
        self.rand_low = self.space_between_pipes + self.pipe_limits
        self.rand_high = self.screen_size[1] - self.pipe_limits

        self.x_bird = self.screen_size[0]/3.0
        self.y_bird = self.screen_size[1]/2.0

        self.x_pipe = 350
        self.y_pipe = random.randint(self.rand_low, self.rand_high)

        self.x_second_pipe = 576
        self.y_second_pipe = random.randint(self.rand_low, self.rand_high)

        self.bird_img_sel = 0
        self.y_increase = 0.0
        self.pipes_stop = 0
        self.score_dozen, self.score_unity = 0, 0
        self.mouse_position = (0, 0)

        self.background_img = \
            pygame.image.load('media/images/background-day.png')
        self.pipe_img_bottom = \
            pygame.image.load('media/images/pipe-green-bottom.png')
        self.pipe_img_top = \
            pygame.image.load('media/images/pipe-green-top.png')

    def bird(self, x, y, image_sel):
        """Simple function to bring life to the bird."""
        if image_sel == 0:
            self.bird_img = \
                pygame.image.load('media/images/yellowbird-midflap.png')
        elif image_sel == 1:
            self.bird_img = \
                pygame.image.load('media/images/yellowbird-upflap.png')
        elif image_sel == 2:
            self.bird_img = \
                pygame.image.load('media/images/yellowbird-downflap.png')
        self.screen.blit(self.bird_img, (x, y))

    def pipes(self):
        """Simple function to update the pipes positions."""

        pipes_speed = 2

        if self.x_pipe <= -self.img_sizes['Pipe'][0]:
            self.x_pipe = self.screen_size[0]
            self.y_pipe = random.randint(self.rand_low, self.rand_high)
        if self.x_second_pipe <= -self.img_sizes['Pipe'][0]:
            self.x_second_pipe = self.screen_size[0]
            self.y_second_pipe = random.randint(self.rand_low, self.rand_high)
        elif self.pipes_stop == 0:
            self.x_second_pipe -= pipes_speed
            self.x_pipe -= pipes_speed

        self.blit_pipes()

    def blit_pipes(self):
        """Blits the pipes to their current position."""

        # Blit first pipe
        y_top = self.y_pipe-(self.img_sizes['Pipe'][1]+self.space_between_pipes)
        self.screen.blit(self.pipe_img_top, (self.x_pipe, y_top))
        self.screen.blit(self.pipe_img_bottom, (self.x_pipe, self.y_pipe))

        # Blit second pipe
        y_top = self.y_second_pipe - \
            (self.img_sizes['Pipe'][1]+self.space_between_pipes)
        self.screen.blit(self.pipe_img_top, (self.x_second_pipe, y_top))
        self.screen.blit(self.pipe_img_bottom, \
            (self.x_second_pipe, self.y_second_pipe))

    def gameover(self):
        """Prints 'game over' when the bird hit the ground or the roof."""
        self.text = pygame.image.load('media/images/gameover.png')
        self.restart_button_img = \
            pygame.image.load('media/images/restart-button.png')
        self.screen.blit(self.text, [104, 250])
        self.screen.blit(self.restart_button_img, [135, 450])

    def restart_button(self):
        """Wait for a mouse click to reset or finish the game."""
        while self.mouse_position == (0, 0):
            for event in pygame.event.get():
                if event.type == pygame.QUIT:
                    return 0
                if event.type == pygame.MOUSEBUTTONDOWN:
                    self.mouse_position = pygame.mouse.get_pos()

        if 135 <= self.mouse_position[0] <= 265:
            if 450 <= self.mouse_position[1] <= 490:
                self.mouse_position = (0, 0)
                return self.play()

    def load_score_images(self):
        """Load external files (images) for the score."""
        self.score_img[0] = pygame.image.load('media/images/0.png')
        self.score_img[1] = pygame.image.load('media/images/1.png')
        self.score_img[2] = pygame.image.load('media/images/2.png')
        self.score_img[3] = pygame.image.load('media/images/3.png')
        self.score_img[4] = pygame.image.load('media/images/4.png')
        self.score_img[5] = pygame.image.load('media/images/5.png')
        self.score_img[6] = pygame.image.load('media/images/6.png')
        self.score_img[7] = pygame.image.load('media/images/7.png')
        self.score_img[8] = pygame.image.load('media/images/8.png')
        self.score_img[9] = pygame.image.load('media/images/9.png')

    def score(self):
        """Show the actual score over the screen."""
        self.screen.blit(self.score_img[self.score_dozen], [190, 100])
        self.screen.blit(self.score_img[self.score_unity], [210, 100])

    def play(self):
        """Initialize the software."""
        self.load_score_images()
        while True:
            for event in pygame.event.get():
                if event.type == pygame.QUIT:
                    return 0
                if event.type == pygame.MOUSEBUTTONDOWN:
                    self.mouse_position = pygame.mouse.get_pos()
                if not self.pipes_stop == 1:
                    if event.type == pygame.KEYUP:
                        self.bird_img_sel = 2
                    if event.type == pygame.KEYDOWN:
                        if event.key == pygame.K_UP:
                            self.y_increase = -5
                            self.bird_img_sel = 1

            # Initialize the bird and the background.
            self.screen.blit(self.background_img, (0, 0))
            self.bird(self.x_bird, self. y_bird, self.bird_img_sel)
            self.y_bird += self.y_increase

            self.y_increase += 0.25 #Simulates gravity acceleration

            self.pipes() # Update pipes

            # Count the score.
            if self.x_bird > self.x_pipe+48 and self.x_bird < self.x_pipe+52:
                if self.score_unity == 9:
                    self.score_dozen += 1
                    self.score_unity = 0
                else:
                    self.score_unity += 1
            self.score()

            if (self.y_bird > self.ground+4) or (self.y_bird < self.roof-4):
                # Bird dies
                self.gameover()
                pygame.display.flip()
                return 2
                self.y_increase = 0
                self.pipes_stop = 1

            elif ((self.x_bird + self.img_sizes['Bird'][0])>=self.x_pipe+3) and\
                    (self.x_bird<=(self.x_pipe+50)):
                if ((self.y_bird + self.img_sizes['Bird'][1])>=self.y_pipe) or \
                    (self.y_bird<=(self.y_pipe-self.space_between_pipes)):
                    # Bird dies
                    self.gameover()
                    pygame.display.flip()
                    return 2
                    self.y_increase = 0
                    self.pipes_stop = 1
            elif ((self.x_bird+self.img_sizes['Bird'][0])>=self.x_second_pipe+3)\
                    and(self.x_bird<=(self.x_second_pipe+50)):
                if ((self.y_bird+self.img_sizes['Bird'][1])>=self.y_second_pipe)\
                        or(self.y_bird<=(self.y_second_pipe - \
                                                self.space_between_pipes)):
                    # Bird dies
                    self.gameover()
                    pygame.display.flip()
                    return 2
                    self.y_increase = 0
                    self.pipes_stop = 1
            else:
                self.pipes_stop = 0

            # Update the screen.
            pygame.display.flip()
            self.clock.tick(60)
<commit_msg>Fix score counting<commit_after>import pygame
import random

class Game:

    def __init__(self):
        pygame.init()
        self.screen_size = (400, 600)
        self.screen = pygame.display.set_mode(self.screen_size)
        pygame.display.set_caption('Flappy Bird')

        self.img_sizes = {'Bird':(34, 24), 'Pipe':(52, 620)}
        self.score_img = {}
        self.clock = pygame.time.Clock()
        self.ground = self.screen_size[1]-self.img_sizes['Bird'][1]
        self.roof = 0

        self.space_between_pipes = 110 # Space between top and bottom pipes
        self.pipe_limits = 50 # Boundary to blit pipes
        # Upper and lower bound limits to pass to randint
        self.rand_low = self.space_between_pipes + self.pipe_limits
        self.rand_high = self.screen_size[1] - self.pipe_limits

        self.x_bird = self.screen_size[0]/3.0
        self.y_bird = self.screen_size[1]/2.0

        self.x_pipe = 350
        self.y_pipe = random.randint(self.rand_low, self.rand_high)

        self.x_second_pipe = 576
        self.y_second_pipe = random.randint(self.rand_low, self.rand_high)

        self.bird_img_sel = 0
        self.y_increase = 0.0
        self.pipes_stop = 0
        self.score_dozen, self.score_unity = 0, 0
        self.mouse_position = (0, 0)

        self.background_img = \
            pygame.image.load('media/images/background-day.png')
        self.pipe_img_bottom = \
            pygame.image.load('media/images/pipe-green-bottom.png')
        self.pipe_img_top = \
            pygame.image.load('media/images/pipe-green-top.png')

    def bird(self, x, y, image_sel):
        """Simple function to bring life to the bird."""
        if image_sel == 0:
            self.bird_img = \
                pygame.image.load('media/images/yellowbird-midflap.png')
        elif image_sel == 1:
            self.bird_img = \
                pygame.image.load('media/images/yellowbird-upflap.png')
        elif image_sel == 2:
            self.bird_img = \
                pygame.image.load('media/images/yellowbird-downflap.png')
        self.screen.blit(self.bird_img, (x, y))

    def pipes(self):
        """Simple function to update the pipes positions."""

        pipes_speed = 2

        if self.x_pipe <= -self.img_sizes['Pipe'][0]:
            self.x_pipe = self.screen_size[0]
            self.y_pipe = random.randint(self.rand_low, self.rand_high)
        if self.x_second_pipe <= -self.img_sizes['Pipe'][0]:
            self.x_second_pipe = self.screen_size[0]
            self.y_second_pipe = random.randint(self.rand_low, self.rand_high)
        elif self.pipes_stop == 0:
            self.x_second_pipe -= pipes_speed
            self.x_pipe -= pipes_speed

        self.blit_pipes()

    def blit_pipes(self):
        """Blits the pipes to their current position."""

        # Blit first pipe
        y_top = self.y_pipe-(self.img_sizes['Pipe'][1]+self.space_between_pipes)
        self.screen.blit(self.pipe_img_top, (self.x_pipe, y_top))
        self.screen.blit(self.pipe_img_bottom, (self.x_pipe, self.y_pipe))

        # Blit second pipe
        y_top = self.y_second_pipe - \
            (self.img_sizes['Pipe'][1]+self.space_between_pipes)
        self.screen.blit(self.pipe_img_top, (self.x_second_pipe, y_top))
        self.screen.blit(self.pipe_img_bottom, \
            (self.x_second_pipe, self.y_second_pipe))

    def gameover(self):
        """Prints 'game over' when the bird hit the ground or the roof."""
        self.text = pygame.image.load('media/images/gameover.png')
        self.restart_button_img = \
            pygame.image.load('media/images/restart-button.png')
        self.screen.blit(self.text, [104, 250])
        self.screen.blit(self.restart_button_img, [135, 450])

    def restart_button(self):
        """Wait for a mouse click to reset or finish the game."""
        while self.mouse_position == (0, 0):
            for event in pygame.event.get():
                if event.type == pygame.QUIT:
                    return 0
                if event.type == pygame.MOUSEBUTTONDOWN:
                    self.mouse_position = pygame.mouse.get_pos()

        if 135 <= self.mouse_position[0] <= 265:
            if 450 <= self.mouse_position[1] <= 490:
                self.mouse_position = (0, 0)
                return self.play()

    def load_score_images(self):
        """Load external files (images) for the score."""
        self.score_img[0] = pygame.image.load('media/images/0.png')
        self.score_img[1] = pygame.image.load('media/images/1.png')
        self.score_img[2] = pygame.image.load('media/images/2.png')
        self.score_img[3] = pygame.image.load('media/images/3.png')
        self.score_img[4] = pygame.image.load('media/images/4.png')
        self.score_img[5] = pygame.image.load('media/images/5.png')
        self.score_img[6] = pygame.image.load('media/images/6.png')
        self.score_img[7] = pygame.image.load('media/images/7.png')
        self.score_img[8] = pygame.image.load('media/images/8.png')
        self.score_img[9] = pygame.image.load('media/images/9.png')

    def score(self):
        """Show the actual score over the screen."""
        self.screen.blit(self.score_img[self.score_dozen], [190, 100])
        self.screen.blit(self.score_img[self.score_unity], [210, 100])

    def play(self):
        """Initialize the software."""
        self.load_score_images()
        while True:
            for event in pygame.event.get():
                if event.type == pygame.QUIT:
                    return 0
                if event.type == pygame.MOUSEBUTTONDOWN:
                    self.mouse_position = pygame.mouse.get_pos()
                if not self.pipes_stop == 1:
                    if event.type == pygame.KEYUP:
                        self.bird_img_sel = 2
                    if event.type == pygame.KEYDOWN:
                        if event.key == pygame.K_UP:
                            self.y_increase = -5
                            self.bird_img_sel = 1

            # Initialize the bird and the background.
            self.screen.blit(self.background_img, (0, 0))
            self.bird(self.x_bird, self. y_bird, self.bird_img_sel)
            self.y_bird += self.y_increase

            self.y_increase += 0.25 #Simulates gravity acceleration

            self.pipes() # Update pipes

            # Count the score.
            if (self.x_bird > self.x_pipe+50 and self.x_bird < self.x_pipe+52)\
                    or (self.x_bird > self.x_second_pipe+50 and \
                        self.x_bird < self.x_second_pipe+52):
                if self.score_unity == 9:
                    self.score_dozen += 1
                    self.score_unity = 0
                else:
                    self.score_unity += 1
            self.score()

            if (self.y_bird > self.ground+4) or (self.y_bird < self.roof-4):
                # Bird dies
                self.gameover()
                pygame.display.flip()
                return 2
                self.y_increase = 0
                self.pipes_stop = 1

            elif ((self.x_bird + self.img_sizes['Bird'][0])>=self.x_pipe+3) and\
                    (self.x_bird<=(self.x_pipe+50)):
                if ((self.y_bird + self.img_sizes['Bird'][1])>=self.y_pipe) or \
                    (self.y_bird<=(self.y_pipe-self.space_between_pipes)):
                    # Bird dies
                    self.gameover()
                    pygame.display.flip()
                    return 2
                    self.y_increase = 0
                    self.pipes_stop = 1
            elif ((self.x_bird+self.img_sizes['Bird'][0])>=self.x_second_pipe+3)\
                    and(self.x_bird<=(self.x_second_pipe+50)):
                if ((self.y_bird+self.img_sizes['Bird'][1])>=self.y_second_pipe)\
                        or(self.y_bird<=(self.y_second_pipe - \
                                                self.space_between_pipes)):
                    # Bird dies
                    self.gameover()
                    pygame.display.flip()
                    return 2
                    self.y_increase = 0
                    self.pipes_stop = 1
            else:
                self.pipes_stop = 0

            # Update the screen.
            pygame.display.flip()
            self.clock.tick(60)
<|endoftext|>


<commit_before>import sys
import pygame

class PlayerShip(object):

    SPEED = 3

    def __init__(self, start_x, start_y, max_x, max_y, ship_height, ship_width):
        self._x = start_x
        self._y = start_y
        self._max_x = max_x
        self._max_y = max_y
        self._ship_height = ship_height
        self._ship_width = ship_width
        self.moving_up = False
        self.moving_down = False
        self.moving_left = False
        self.moving_right = False

    def move_up(self):
        self._y -= PlayerShip.SPEED

    def move_down(self):
        self._y += PlayerShip.SPEED

    def move_left(self):
        self._x -= PlayerShip.SPEED

    def move_right(self):
        self._x += PlayerShip.SPEED

    def update(self):
        if self.moving_up:
            self.move_up()
        if self.moving_down:
            self.move_down()
        if self.moving_left:
            self.move_left()
        if self.moving_right:
            self.move_right()

    def check_bounds(self):
        if self._x < 0:
            self._x = 0
        if self._x > self._max_x - self._ship_width:
            self._x = self._max_x - self._ship_width
        if self._y < 0:
            self._y = 0
        if self._y > self._max_y - self._ship_height:
            self._y = self._max_y - self._ship_height

    def get_position(self):
        self.check_bounds()
        return (self._x, self._y)

    def get_shot_location(self):
        return (self._x + 20, self._y + 20)

class Shot(object):

    def __init__(self, start_location):
        self._position = start_location

    def get_position(self):
        return self._position

    def update_position(self):
        self._position = (self._position[0] + 4, self._position[1])

    def out_of_bounds(self, width):
        return self._position[0] > width

def process_events():
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            exit_game()
        if event.type == pygame.KEYDOWN:
            if event.key == pygame.K_UP:
                player.moving_up = True
            elif event.key == pygame.K_DOWN:
                player.moving_down = True
            elif event.key == pygame.K_LEFT:
                player.moving_left = True
            elif event.key == pygame.K_RIGHT:
                player.moving_right = True
        if event.type == pygame.KEYUP:
            if event.key == pygame.K_UP:
                player.moving_up = False
            elif event.key == pygame.K_DOWN:
                player.moving_down = False
            elif event.key == pygame.K_LEFT:
                player.moving_left = False
            elif event.key == pygame.K_RIGHT:
                player.moving_right = False

def exit_game():
    pygame.quit()
    sys.exit()

def update_screen():
    screen.fill(black)
    screen.blit(player_image, player.get_position())
    for s in shots:
        screen.blit(shot_image, s.get_position())
    pygame.display.update()

def fire_shot():
    global shot_timer
    if shot_timer > 0:
        return
    shot_location = player.get_shot_location()
    new_shot = Shot(shot_location)
    shots.append(new_shot)
    shot_timer = 8

def update_shots():
    global shot_timer
    shot_timer -= 1
    for s in shots:
        s.update_position()
        if s.out_of_bounds(640):
            shots.remove(s)

pygame.init()

size = width, height = 640, 480
black = 0, 0, 0

screen = pygame.display.set_mode(size)
player_image = pygame.image.load("resources/PlayerShip.png")
player = PlayerShip(0, 0, width, height, player_image.get_height(), player_image.get_width())
clock = pygame.time.Clock()

shot_image = pygame.image.load("resources/Shot.png")
shots = []
shot_timer = 0

while True:
    process_events()

    pressed_keys = pygame.key.get_pressed()
    if pressed_keys[pygame.K_LCTRL]:
        fire_shot()

    player.update()
    update_shots()

    update_screen()

    clock.tick(60)
<commit_msg>Simplified the PlayerShip object.<commit_after>import sys
import pygame

class PlayerShip(object):

    SPEED = 3

    def __init__(self, start_x, start_y, max_x, max_y, ship_height, ship_width):
        self._x = start_x
        self._y = start_y
        self._max_x = max_x - ship_width
        self._max_y = max_y - ship_height
        self.moving_up = False
        self.moving_down = False
        self.moving_left = False
        self.moving_right = False

    def move_up(self):
        self._y -= PlayerShip.SPEED
        self._y = max(self._y, 0)

    def move_down(self):
        self._y += PlayerShip.SPEED
        self._y = min(self._y, self._max_y)

    def move_left(self):
        self._x -= PlayerShip.SPEED
        self._x = max(self._x, 0)

    def move_right(self):
        self._x += PlayerShip.SPEED
        self._x = min(self._x, self._max_x)

    def update(self):
        if self.moving_up:
            self.move_up()
        if self.moving_down:
            self.move_down()
        if self.moving_left:
            self.move_left()
        if self.moving_right:
            self.move_right()

    def get_position(self):
        return (self._x, self._y)

    def get_shot_location(self):
        return (self._x + 20, self._y + 20)

class Shot(object):

    def __init__(self, start_location):
        self._position = start_location

    def get_position(self):
        return self._position

    def update_position(self):
        self._position = (self._position[0] + 4, self._position[1])

    def out_of_bounds(self, width):
        return self._position[0] > width

def process_events():
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            exit_game()
        if event.type == pygame.KEYDOWN:
            if event.key == pygame.K_UP:
                player.moving_up = True
            elif event.key == pygame.K_DOWN:
                player.moving_down = True
            elif event.key == pygame.K_LEFT:
                player.moving_left = True
            elif event.key == pygame.K_RIGHT:
                player.moving_right = True
        if event.type == pygame.KEYUP:
            if event.key == pygame.K_UP:
                player.moving_up = False
            elif event.key == pygame.K_DOWN:
                player.moving_down = False
            elif event.key == pygame.K_LEFT:
                player.moving_left = False
            elif event.key == pygame.K_RIGHT:
                player.moving_right = False

def exit_game():
    pygame.quit()
    sys.exit()

def update_screen():
    screen.fill(black)
    screen.blit(player_image, player.get_position())
    for s in shots:
        screen.blit(shot_image, s.get_position())
    pygame.display.update()

def fire_shot():
    global shot_timer
    if shot_timer > 0:
        return
    shot_location = player.get_shot_location()
    new_shot = Shot(shot_location)
    shots.append(new_shot)
    shot_timer = 8

def update_shots():
    global shot_timer
    shot_timer -= 1
    for s in shots:
        s.update_position()
        if s.out_of_bounds(640):
            shots.remove(s)

pygame.init()

size = width, height = 640, 480
black = 0, 0, 0

screen = pygame.display.set_mode(size)
player_image = pygame.image.load("resources/PlayerShip.png")
player = PlayerShip(0, 0, width, height, player_image.get_height(), player_image.get_width())
clock = pygame.time.Clock()

shot_image = pygame.image.load("resources/Shot.png")
shots = []
shot_timer = 0

while True:
    process_events()

    pressed_keys = pygame.key.get_pressed()
    if pressed_keys[pygame.K_LCTRL]:
        fire_shot()

    player.update()
    update_shots()

    update_screen()

    clock.tick(60)
<|endoftext|>


<commit_before>#!/usr/bin/env python
#game.py

#base class for your game_class that you make
class Game(object):
	#class-specific escape codes for user-input
	escapes = [":w", ":q", ":wq", ":r"]

	#defualt constructor, sets up some general variables you might want
	#you can call this with:
	#	super(your_game, self).__init__(player1, player2)
	def __init__(self, player1, player2, be_quiet = False):
		#integer to keep track of the current turn
		self.turn = 0

		#integer to keep track of who won or -1 if the game isn't over.
		self.winner = -1

		#bool that determines whether to print things to screen.
		self.quiet = be_quiet

		#the number of players in the game
		#alpha-beta pruning assumes two players, so having more might be an issue.
		self.num_players = 2

		#list for keeping track of the players.
		#index 0 is not used so that each player
		#is at the index of their turn.
		self.players = [None, player1, player2]

		#history of all game_state strings of the game.
		self.history = []

	#gets the current turn number
	#get_turn : Game -> Int
	def get_turn(self):
		return self.turn

	#returns True if the current player is human
	#is_human_turn : Game -> Bool
	def is_human_turn(self):
		return self.players[self.get_player_num()].is_human()

	#returns the current player object
	#current_player : Game -> Player
	def current_player(self):
		return self.players[self.get_player_num()]

	#handles an escape code that the player may use when doing their turn
	#saving, and evaluating are general things you would have to do.
	def handle_escape(self, code):
		if code == ":w":
			print "UnemplementedError: saving"
		elif code == ":wq":
			print "UnemplementedError: saving"
			raise SystemExit
		elif code == ":q":
			raise SystemExit
		elif code == ":r":
			pass

	#returns the number of the current player (1 or 2 by default)
	#get_player_num : Game -> Int
	def get_player_num(self):
	### required by player.py ###
		return (self.turn % self.num_players) + 1

	#standard python __repr__() function
	#__repr__ : Game -> Str
	def __repr__(self):
		return self.__str__()

	#returns True if the game is over
	#is_game_over : Game -> Bool
	def is_game_over(self):
	### required by alphabeta.py ###
		return self.winner != -1

	#method to play the game, if you look closely,
	#the do_turn method actually does all the work, have fun.
	#play : Game -> Int
	def play(self):
		self.history += [str(self)]
		while self.winner == -1:
			self.do_turn()
			self.history += [str(self)]
		if not self.quiet:
			self.opg()
			if self.winner != 0:
				print "PLAYER" + str(self.winner) + " IS THE WINNER!!!"
			else:
				print "IT WAS A DRAW!"
		return self.winner

	#method to add history of the game to a file
	#requires that the  FILE be open and have a write() method
	#record_history_to_file : Game x FILE -> _
	def record_history_to_file(self, FILE):
		for state in self.history:
			FILE.write(state + '~' + str(self.winner) + '\n')

	#method to get a dictionary of (Game_State, Move) pairs.
	#this assumes 2 things:
	#	1) len(self.get_child_states()) == len(self.get_child_moves())
	#	2) self.get_child_states[x] is the state created by doing move self.get_child_moves[x]
	#get_child_state2move_dict : Game -> {Game_State: Move}
	def get_child_state2move_dict(self):
	### required by alphabeta.py ###
		keys = self.get_child_states()
		values = self.get_child_moves()
		d = {keys[x] : values[x] for x in range(len(keys))}
		return d

	#the remainder of the functions are specific to your implementation.
	#along with these, you should also write a more specific __init__
	#or some other way to create a default game state.

	#ideally, this returns a str that is unique to this game's
	#current state, to be used as a way to create games from a
	#string, henceforth known as a Game_State
	#__str__ : Game -> Game_State
	def __str__(self):
	### required by alphabeta.py ###
		pass

	#should return a list containing the possible game_states
	#that could result from the current player doing their turn.
	#NOTE: you should use __str__ to create the game_states.
	### Keep in mind the requirements noted in get_child_state2move_dict above. ###
	#get_child_states : Game -> [Game_State]
	def get_child_states(self):
	### required by alphabeta.py ###
		pass

	#similar to the previous method, except returns a valid move for your game.
	#its up to you to decide the format for a move that should be used here,
	#and is returned from Player.choose_move
	### Keep in mind the requirements noted in get_child_state2move_dict above. ###
	#get_child_moves : Game -> [Move]
	def get_child_moves(self):
	### required by player.py ###
		pass

	#this is where the magic happens.
	#things to do in this method (your needs may vary):
	#	-print the board (possibly only if the current player is human):
	#		human = self.is_human_turn()
	#		if human:
	#			self.opg()
	#	-print stuff for the human
	#		if human:
	#			print <information on playing your turn>
	#	-get the move:
	#		move = self.current_player().choose_move(self)
	#	-check if the move returned is valid, and if it is, update any
	#	 state variables that need to change (such as the turn counter)
	def do_turn(self):
		pass

	#method to return an empty class of your type
	#this is done so you can pass whatever arguments your
	#class's __init__ needs
	#make_new_instance : Game -> Game
	def make_new_instance(self):
	### required by alphabeta.py ###
		pass

	#essentially the inverse of the __str__ operation
	#should take a game state, and change the state of the
	#game class to match.
	#load_state_from_string : Game x Game_State -> _
	def load_state_from_string(self, state):
	### required by alphabeta.py ###
		pass

	#method for showing the game to the user.
	#short for OutPutGame
	#opg : Game -> _
	def opg(self):
		pass

	#Checks if the game is over.
	#stores self.winner as one of {0, 1, 2}
	#depending on if {draw, player1 wins, player2 wins}
	#and returns self.winner
	#check_winner : Game -> Int
	def check_winner(self):
		pass
<commit_msg>updated escape codes<commit_after>#!/usr/bin/env python
#game.py

#base class for your game_class that you make
class Game(object):
	#class-specific escape codes for user-input
	escapes = [":w", ":q", ":wq", ":r", ":m"]

	#defualt constructor, sets up some general variables you might want
	#you can call this with:
	#	super(your_game, self).__init__(player1, player2)
	def __init__(self, player1, player2, be_quiet = False):
		#integer to keep track of the current turn
		self.turn = 0

		#integer to keep track of who won or -1 if the game isn't over.
		self.winner = -1

		#bool that determines whether to print things to screen.
		self.quiet = be_quiet

		#the number of players in the game
		#alpha-beta pruning assumes two players, so having more might be an issue.
		self.num_players = 2

		#list for keeping track of the players.
		#index 0 is not used so that each player
		#is at the index of their turn.
		self.players = [None, player1, player2]

		#history of all game_state strings of the game.
		self.history = []

	#gets the current turn number
	#get_turn : Game -> Int
	def get_turn(self):
		return self.turn

	#returns True if the current player is human
	#is_human_turn : Game -> Bool
	def is_human_turn(self):
		return self.players[self.get_player_num()].is_human()

	#returns the current player object
	#current_player : Game -> Player
	def current_player(self):
		return self.players[self.get_player_num()]

	#handles an escape code that the player may use when doing their turn
	#saving, and evaluating are general things you would have to do.
	def handle_escape(self, code):
		if code == ":w":
			print "UnemplementedError: saving"
		elif code == ":wq":
			print "UnemplementedError: saving"
			raise SystemExit
		elif code == ":q":
			raise SystemExit
		elif code == ":r":
			pass
		elif code == ":m":
			print self.get_child_moves()

	#returns the number of the current player (1 or 2 by default)
	#get_player_num : Game -> Int
	def get_player_num(self):
	### required by player.py ###
		return (self.turn % self.num_players) + 1

	#standard python __repr__() function
	#__repr__ : Game -> Str
	def __repr__(self):
		return self.__str__()

	#returns True if the game is over
	#is_game_over : Game -> Bool
	def is_game_over(self):
	### required by alphabeta.py ###
		return self.winner != -1

	#method to play the game, if you look closely,
	#the do_turn method actually does all the work, have fun.
	#play : Game -> Int
	def play(self):
		self.history += [str(self)]
		while self.winner == -1:
			self.do_turn()
			self.history += [str(self)]
		if not self.quiet:
			self.opg()
			if self.winner != 0:
				print "PLAYER" + str(self.winner) + " IS THE WINNER!!!"
			else:
				print "IT WAS A DRAW!"
		return self.winner

	#method to add history of the game to a file
	#requires that the  FILE be open and have a write() method
	#record_history_to_file : Game x FILE -> _
	def record_history_to_file(self, FILE):
		for state in self.history:
			FILE.write(state + '~' + str(self.winner) + '\n')

	#method to get a dictionary of (Game_State, Move) pairs.
	#this assumes 2 things:
	#	1) len(self.get_child_states()) == len(self.get_child_moves())
	#	2) self.get_child_states[x] is the state created by doing move self.get_child_moves[x]
	#get_child_state2move_dict : Game -> {Game_State: Move}
	def get_child_state2move_dict(self):
	### required by alphabeta.py ###
		keys = self.get_child_states()
		values = self.get_child_moves()
		d = {keys[x] : values[x] for x in range(len(keys))}
		return d

	#the remainder of the functions are specific to your implementation.
	#along with these, you should also write a more specific __init__
	#or some other way to create a default game state.

	#ideally, this returns a str that is unique to this game's
	#current state, to be used as a way to create games from a
	#string, henceforth known as a Game_State
	#__str__ : Game -> Game_State
	def __str__(self):
	### required by alphabeta.py ###
		pass

	#should return a list containing the possible game_states
	#that could result from the current player doing their turn.
	#NOTE: you should use __str__ to create the game_states.
	### Keep in mind the requirements noted in get_child_state2move_dict above. ###
	#get_child_states : Game -> [Game_State]
	def get_child_states(self):
	### required by alphabeta.py ###
		pass

	#similar to the previous method, except returns a valid move for your game.
	#its up to you to decide the format for a move that should be used here,
	#and is returned from Player.choose_move
	### Keep in mind the requirements noted in get_child_state2move_dict above. ###
	#get_child_moves : Game -> [Move]
	def get_child_moves(self):
	### required by player.py ###
		pass

	#this is where the magic happens.
	#things to do in this method (your needs may vary):
	#	-print the board (possibly only if the current player is human):
	#		human = self.is_human_turn()
	#		if human:
	#			self.opg()
	#	-print stuff for the human
	#		if human:
	#			print <information on playing your turn>
	#	-get the move:
	#		move = self.current_player().choose_move(self)
	#	-check if the move returned is valid, and if it is, update any
	#	 state variables that need to change (such as the turn counter)
	def do_turn(self):
		pass

	#method to return an empty class of your type
	#this is done so you can pass whatever arguments your
	#class's __init__ needs
	#make_new_instance : Game -> Game
	def make_new_instance(self):
	### required by alphabeta.py ###
		pass

	#essentially the inverse of the __str__ operation
	#should take a game state, and change the state of the
	#game class to match.
	#load_state_from_string : Game x Game_State -> _
	def load_state_from_string(self, state):
	### required by alphabeta.py ###
		pass

	#method for showing the game to the user.
	#short for OutPutGame
	#opg : Game -> _
	def opg(self):
		pass

	#Checks if the game is over.
	#stores self.winner as one of {0, 1, 2}
	#depending on if {draw, player1 wins, player2 wins}
	#and returns self.winner
	#check_winner : Game -> Int
	def check_winner(self):
		pass
<|endoftext|>