"""
    dashCO2.crud
    ~~~~~~~~~~~~

    Infraestructura para listar y exportar mediciones y configurar
    dispositivos.

"""

import operator

import arrow
from flask import (
    flash,
    has_app_context,
    make_response,
    redirect,
    request,
)
from flask_admin import Admin, AdminIndexView, expose
from flask_admin.actions import action
from flask_admin.contrib.sqla import ModelView
from flask_admin.form import rules
from flask_admin.helpers import get_redirect_target
from markupsafe import Markup
from sqlalchemy import and_, desc, func
from wtforms import Form, HiddenField, IntegerField, StringField
from wtforms.validators import AnyOf, InputRequired, NumberRange

from .shared import DAY

def init_app(app, auth=None):

    if auth is None:

        class Auth:
            """Dummy auth in case it is not provided."""

            users = ("admin",)

            @staticmethod
            def get_current_user(*args, **kwargs):
                return "admin"

            @staticmethod
            def login_required(*args, **kwargs):
                def _inner(f):
                    return f

                return _inner

        auth = Auth()

    from . import config, models, shared
    from .models import Record
    from .shared import (
        COLORS,
        firmware_version_exists,
        get_latest_firmware_version,
    )

    @app.template_filter()
    def insert_logout(text):
        """Convert a string to all caps."""
        for prefix in ("http://", "https://"):
            sz = len(prefix)
            if text[:sz] == prefix:
                return prefix + "log:out@" + text[sz:]
        return text

    class SecureModelView(ModelView):
        def is_accessible(self):
            return auth.get_current_user() in auth.users

        def inaccessible_callback(self, name, **kwargs):
            # redirect to login page if user doesn't have access
            return redirect("/admin")

        def get_current_user(self):
            return auth.get_current_user()

    def format_utc(value):
        return (
            arrow.Arrow.utcfromtimestamp(value)
            .to(config.TIMEZONE)
            .format("YYYY-MM-DD HH:mm:ss")
        )

    ##############
    # Formatters
    ##############

    def _timestamp_formatter(column):
        def _inner(view, context, model, name):
            value = getattr(model, column)
            if value:
                return format_utc(value)
            else:
                return ""

        return _inner

    def _last_calibration_formatter(view, context, model, name):
        value = model.last_calibration
        if value == config.NO_CAL:
            return "N/A"
        if value:
            return format_utc(value)
        else:
            return ""

    def _last_seen_formatter(view, context, model, name):
        rec = (
            Record.query.filter(
                Record.serial_number == model.serial_number
            )
            .order_by(desc(Record.timestamp))
            .first()
        )
        if rec:
            return format_utc(rec.timestamp)
        else:
            return "N/A"

    def _links_formatter(view, context, model, name):
        base = f"/admin/%s/?flt1_serial_number_equals={model.serial_number}"
        day_link = base % "day"
        week_link = base % "week"
        month_link = base % "month"
        return Markup(
            f"24 h
 "
            f"7 d
 "
            f"30 d"
        )

    def _dict_formatter(column, conversion, default="N/A"):
        def _inner(view, context, model, name):
            return conversion.get(getattr(model, column), default)

        return _inner

    #########
    # Vistas
    #########

    class RecordView(SecureModelView):
        named_filter_urls = True

        can_delete = False
        can_create = False
        can_edit = False
        can_view_details = True

        column_searchable_list = ["serial_number"]
        column_filters = ["serial_number"]
        can_export = True

        column_formatters = {
            "timestamp": _timestamp_formatter("timestamp"),
            "ntp_epoch": _timestamp_formatter("ntp_epoch"),
        }

    class WithFilter:
        def get_query(self):
            return self.session.query(self.model).filter(
                self._my_filter()
            )

        def get_count_query(self):
            return (
                self.session.query(func.count("*"))
                .select_from(self.model)
                .filter(self._my_filter())
            )

    class RelativeTemporalFilter(WithFilter):
        _column = ""
        _delta_ts = 0
        _operator = None

        def _my_filter(self):
            now = arrow.utcnow().timestamp

            if self._operator == "between":
                return getattr(self.model, self._column).between(
                    now - self._delta_ts[0], now - self._delta_ts[1]
                )

            return self._operator(
                getattr(self.model, self._column), now - self._delta_ts
            )

    class DayView(RelativeTemporalFilter, RecordView):
        _column = "timestamp"
        _delta_ts = DAY
        _operator = operator.gt

    class WeekView(RelativeTemporalFilter, RecordView):
        _column = "timestamp"
        _delta_ts = 7 * DAY
        _operator = operator.gt

    class MonthView(RelativeTemporalFilter, RecordView):
        _column = "timestamp"
        _delta_ts = 30 * DAY
        _operator = operator.gt

    class HiddenView:
        def is_visible(self):
            return False

    class DeviceView(SecureModelView):
        @action("firmware", "Actualizar firmware")
        def action_firmware_update(self, ids):
            url = get_redirect_target() or self.get_url(".index_view")
            sigil = "&" if "?" in url else "?"
            return redirect(
                url + f"{sigil}action=firmware_update", code=307
            )

        @action("recalibrate", "Recalibrar")
        def action_recalibrate(self, ids):
            url = get_redirect_target() or self.get_url(".index_view")
            sigil = "&" if "?" in url else "?"
            return redirect(
                url + f"{sigil}action=recalibrate", code=307
            )

        @action("screen_mode", "Modo pantalla")
        def action_screen_mode(self, ids):
            url = get_redirect_target() or self.get_url(".index_view")
            sigil = "&" if "?" in url else "?"
            return redirect(
                url + f"{sigil}action=screen_mode", code=307
            )

        @action("acq_period", "Período de adquisición")
        def action_acq_period(self, ids):
            url = get_redirect_target() or self.get_url(".index_view")
            sigil = "&" if "?" in url else "?"
            return redirect(url + f"{sigil}action=acq_period", code=307)

        @expose("/", methods=["POST"])
        def index(self):
            if request.method == "POST":
                url = get_redirect_target() or self.get_url(
                    ".index_view"
                )
                action = request.args.get("action", None)
                if action == "firmware_update":
                    change_form = ChangeFirmwareForm()
                    new_title = "Actualizar Firmware"
                    msg = f"Última versión: {get_latest_firmware_version()}"
                elif action == "recalibrate":
                    change_form = RecalibrateForm()
                    new_title = "Recalibrar"
                    msg = "Escriba 'recalibrar' para confirmar (sin comillas)"
                elif action == "screen_mode":
                    change_form = ChangeScreenModeForm()
                    new_title = "Modo pantalla"
                    msg = ""
                elif action == "acq_period":
                    change_form = ChangeAcqPeriodForm()
                    new_title = "Período de adquisición [ms]"
                    msg = ""
                else:
                    return self.index_view()

                ids = request.form.getlist("rowid")
                joined_ids = ",".join(ids)
                change_form.ids.data = joined_ids
                self._template_args["modal_title"] = new_title
                self._template_args["modal_url"] = url
                self._template_args["modal_change_form"] = change_form
                self._template_args["modal_change_modal"] = True
                self._template_args["modal_next"] = f"device.{action}"
                self._template_args["modal_count"] = len(ids)
                self._template_args["modal_msg"] = msg
                return self.index_view()

        @expose("/firmware_update/", methods=["POST"])
        def firmware_update(self):
            if request.method == "POST":
                if self.get_current_user() != "admin":
                    flash(
                        f"El usuario {self.get_current_user()} no "
                        f"tiene permisos para actualizar el firmware.",
                        category="error",
                    )
                    return redirect(self.get_url(".index_view"))
                url = get_redirect_target() or self.get_url(
                    ".index_view"
                )
                change_form = ChangeFirmwareForm(request.form)
                ids = change_form.ids.data.split(",")
                if change_form.validate():
                    firmware_version = change_form.firmware_version.data

                    if not firmware_version_exists(firmware_version):
                        flash(
                            f"La version {firmware_version} del firmware"
                            f"no está disponible en el servidor.",
                            category="error",
                        )
                        return redirect(url)

                    _update_mappings = [
                        {
                            "id": rowid,
                            "firmware_version": firmware_version,
                        }
                        for rowid in ids
                    ]
                    self.session.bulk_update_mappings(
                        models.Device, _update_mappings
                    )
                    self.session.commit()
                    flash(
                        "Set firmware_version for {} device{} to {}.".format(
                            len(ids),
                            "s" if len(ids) > 1 else "",
                            firmware_version,
                        ),
                        category="info",
                    )
                    return redirect(url)
                else:
                    # Form didn't validate
                    self._template_args[
                        "modal_title"
                    ] = "Actualizar Firmware"
                    self._template_args["modal_url"] = url
                    self._template_args[
                        "modal_change_form"
                    ] = change_form
                    self._template_args["modal_change_modal"] = True
                    self._template_args[
                        "modal_next"
                    ] = "device.firmware_update"
                    self._template_args["modal_count"] = len(ids)
                    return self.index_view()

        @expose("/recalibrate/", methods=["POST"])
        def recalibrate(self):
            if request.method == "POST":
                if self.get_current_user() != "admin":
                    flash(
                        f"El usuario {self.get_current_user()} no tiene "
                        f"permisos para actualizar el iniciar "
                        f"una calibración.",
                        category="error",
                    )
                    return redirect(self.get_url(".index_view"))
                url = get_redirect_target() or self.get_url(
                    ".index_view"
                )
                change_form = RecalibrateForm(request.form)
                ids = change_form.ids.data.split(",")
                ids = tuple(int(val) for val in ids)
                if change_form.validate():
                    devices = models.Device.query.filter(
                        models.Device.id.in_(ids)
                    ).all()
                    for dev in devices:
                        if str(dev.last_calibration)[-1] == "9":
                            dev.last_calibration -= 9
                        else:
                            dev.last_calibration += 1

                    self.session.commit()
                    flash(
                        f"La recalibración se ha iniciado para {len(devices)} "
                        f"dispositivos{'s' if len(devices) > 1 else ''}. "
                        f"Puede demorar un poco ...",
                        category="info",
                    )
                    return redirect(url)
                else:
                    # Form didn't validate
                    self._template_args["modal_title"] = "Recalibrar"
                    self._template_args["modal_url"] = url
                    self._template_args[
                        "modal_change_form"
                    ] = change_form
                    self._template_args["modal_change_modal"] = True
                    self._template_args[
                        "modal_next"
                    ] = "device.recalibrate"
                    self._template_args["modal_count"] = len(ids)
                    return self.index_view()

        @expose("/screen_mode/", methods=["POST"])
        def screen_mode(self):
            if request.method == "POST":
                url = get_redirect_target() or self.get_url(
                    ".index_view"
                )
                change_form = ChangeScreenModeForm(request.form)
                ids = change_form.ids.data.split(",")
                if change_form.validate():
                    screen_mode = change_form.screen_mode.data
                    _update_mappings = [
                        {"id": rowid, "screen_mode": screen_mode}
                        for rowid in ids
                    ]
                    self.session.bulk_update_mappings(
                        models.Device, _update_mappings
                    )
                    self.session.commit()
                    flash(
                        "Set screen_mode for {} device{} to {}.".format(
                            len(ids),
                            "s" if len(ids) > 1 else "",
                            screen_mode,
                        ),
                        category="info",
                    )
                    return redirect(url)
                else:
                    # Form didn't validate
                    self._template_args["modal_title"] = "Modo pantalla"
                    self._template_args["modal_url"] = url
                    self._template_args[
                        "modal_change_form"
                    ] = change_form
                    self._template_args["modal_change_modal"] = True
                    self._template_args[
                        "modal_next"
                    ] = "device.screen_mode"
                    self._template_args["modal_count"] = len(ids)
                    return self.index_view()

        @expose("/acq_period/", methods=["POST"])
        def acq_period(self):
            if request.method == "POST":
                url = get_redirect_target() or self.get_url(
                    ".index_view"
                )
                change_form = ChangeAcqPeriodForm(request.form)
                ids = change_form.ids.data.split(",")
                if change_form.validate():
                    acq_period = change_form.acq_period.data
                    _update_mappings = [
                        {"id": rowid, "acq_period": acq_period}
                        for rowid in ids
                    ]
                    self.session.bulk_update_mappings(
                        models.Device, _update_mappings
                    )
                    self.session.commit()
                    flash(
                        "Set acq_period for {} device{} to {}.".format(
                            len(ids),
                            "s" if len(ids) > 1 else "",
                            acq_period,
                        ),
                        category="info",
                    )
                    return redirect(url)
                else:
                    # Form didn't validate
                    self._template_args[
                        "modal_title"
                    ] = "Período de adquisición [ms]"
                    self._template_args["modal_url"] = url
                    self._template_args[
                        "modal_change_form"
                    ] = change_form
                    self._template_args["modal_change_modal"] = True
                    self._template_args[
                        "modal_next"
                    ] = "device.acq_period"
                    self._template_args["modal_count"] = len(ids)
                    return self.index_view()

        column_default_sort = "serial_number"

        list_template = "custom_list.html"

        named_filter_urls = True

        can_delete = False
        can_create = False
        can_view_details = True

        column_searchable_list = ["serial_number"]
        column_filters = [
            "serial_number",
            "building",
            "floor",
            "room",
            "firmware_version",
            "reference_device",
        ]
        can_export = True

        cols = []
        column_list = [
            "serial_number",
            "acq_period",
            "screen_mode",
            "last_calibration",
            "firmware_version",
            "reference_device",
            "building",
            "floor",
            "room",
        ]
        column_list += ["last_seen", "links"]

        column_details_list = [
            "serial_number",
            "acq_period",
            "screen_mode",
            "last_calibration",
            "firmware_version",
            "reference_device",
            "building",
            "floor",
            "room",
            "hardware_info",
        ]
        column_details_list += ["last_seen", "links"]

        _user_form_edit_rules = (
            "acq_period",
            "screen_mode",
            "building",
            "floor",
            "room",
        )

        _admin_form_edit_rules = _user_form_edit_rules + (
            "firmware_version",
            "last_calibration",
            "reference_device",
        )

        column_formatters = {
            "screen_mode": _dict_formatter(
                "screen_mode", {0: "on", 1: "minimal", 2: "off"}
            ),
            "last_calibration": _last_calibration_formatter,
            "last_seen": _last_seen_formatter,
            "links": _links_formatter,
        }

        form_choices = {
            "screen_mode": [(0, "full"), (1, "minimal"), (2, "off")],
        }

        form_args = dict(
            acq_period=dict(
                validators=[
                    NumberRange(
                        5 * 1000,
                        10 * 60 * 1000,
                        message="Usar valores entre 5000 ms y 600000 ms "
                        "(5 seg y 10 min)",
                    )
                ]
            ),
        )

        @property
        def _form_edit_rules(self):
            return rules.RuleSet(self, self.form_edit_rules)

        @_form_edit_rules.setter
        def _form_edit_rules(self, value):
            pass

        @property
        def form_edit_rules(self):
            if (
                not has_app_context()
                or self.get_current_user() == "admin"
            ):
                return self._admin_form_edit_rules

            return self._user_form_edit_rules

    class LastCalibrationDayView(
        HiddenView, RelativeTemporalFilter, DeviceView
    ):
        _column = "last_calibration"
        _delta_ts = DAY
        _operator = operator.gt

    class LastCalibrationWeekView(
        HiddenView, RelativeTemporalFilter, DeviceView
    ):
        _column = "last_calibration"
        _delta_ts = (7 * DAY, DAY)
        _operator = "between"

    class LastCalibrationMonthView(
        HiddenView, RelativeTemporalFilter, DeviceView
    ):
        _column = "last_calibration"
        _delta_ts = (30 * DAY, 7 * DAY)
        _operator = "between"

    class LastCalibrationYearView(
        HiddenView, RelativeTemporalFilter, DeviceView
    ):
        _column = "last_calibration"
        _delta_ts = (365 * DAY, 30 * DAY)
        _operator = "between"

    class LastCalibrationLongerView(HiddenView, WithFilter, DeviceView):
        def _my_filter(self):
            abs_ts = arrow.utcnow().timestamp - 365 * DAY
            return and_(
                models.Device.last_calibration != config.NO_CAL,
                models.Device.last_calibration < abs_ts,
            )

    class LastCalibrationNoView(HiddenView, WithFilter, DeviceView):
        def _my_filter(self):
            return models.Device.last_calibration == config.NO_CAL

    class ChangeFirmwareForm(Form):
        ids = HiddenField()
        firmware_version = IntegerField(validators=[InputRequired()])

    class RecalibrateForm(Form):
        ids = HiddenField()
        confirmation = StringField(
            validators=[
                AnyOf(
                    ["recalibrar"],
                    message="Escriba 'recalibrar' para confirmar "
                    "(sin comillas)",
                )
            ]
        )

    class ChangeScreenModeForm(Form):
        ids = HiddenField()
        screen_mode = IntegerField(
            validators=[
                AnyOf(
                    (0, 1, 2),
                    message="Usar 0 (full), 1 (minimal) y 2 (off)",
                )
            ]
        )

    class ChangeAcqPeriodForm(Form):
        ids = HiddenField()
        acq_period = IntegerField(
            validators=[
                NumberRange(
                    5 * 1000,
                    10 * 60 * 1000,
                    message="Usar valores entre 5000 ms y 600000 ms "
                    "(5 seg y 10 min)",
                )
            ]
        )

    class ByStatusView(HiddenView, WithFilter, DeviceView):

        _status = None

        def is_visible(self):
            return False

        def _my_filter(self):
            try:
                offline_secs = int(
                    request.args.get("offline_secs", None)
                )
            except Exception:
                offline_secs = None
            grouped_devices = models.get_devices_by_status(offline_secs)
            return models.Device.serial_number.in_(
                grouped_devices[self._status]
            )

    class ByOfflineStatus(ByStatusView):
        _status = COLORS.OFFLINE

    class ByDangerStatus(ByStatusView):
        _status = COLORS.DANGER

    class ByWarningStatus(ByStatusView):
        _status = COLORS.WARNING

    class ByOkStatus(ByStatusView):
        _status = COLORS.OK

    class IndexView(HiddenView, AdminIndexView):
        @expose("/login")
        @auth.login_required
        def login(self):
            return redirect(self.get_url(".index"))

        @expose("/")
        @auth.login_required(optional=True)
        def index(self):
            current_user = auth.get_current_user()
            if current_user is None:
                return self.render("anon.html")

            try:
                offline_secs = int(
                    request.args.get(
                        "offline_secs", config.CONSIDER_OFFLINE_SEC
                    )
                )
            except Exception:
                offline_secs = config.CONSIDER_OFFLINE_SEC

            summary = models.summarize_devices(
                offline_secs, config.NO_CAL
            )

            rendered = self.render(
                "my_index.html",
                by_status=summary["by_status"],
                by_firmware_version=summary["by_firmware_version"],
                by_last_calibration=summary["by_last_calibration"],
                by_building=summary["by_building"],
                COLORS=COLORS,
                total=summary["total"],
                last_firmware_version=get_latest_firmware_version(),
                current_user=current_user,
            )
            resp = make_response(rendered)
            resp.set_cookie(
                shared.MAGIC_COOKIE_KEY,
                shared.MAGIC_COOKIE,
                samesite="Lax",
            )
            return resp

    admin = Admin(
        app,
        name="Monitoreo de CO2",
        base_template="my_base.html",
        template_mode="bootstrap4",
        index_view=IndexView(),
    )

    admin.add_view(
        DeviceView(models.Device, models.db.session, name="Sensores")
    )
    admin.add_view(
        RecordView(models.Record, models.db.session, name="Registros")
    )
    admin.add_view(
        DayView(
            models.Record,
            models.db.session,
            endpoint="/day",
            name="Últimas 24h",
        )
    )
    admin.add_view(
        WeekView(
            models.Record,
            models.db.session,
            endpoint="/week",
            name="Últimos 7d",
        )
    )
    admin.add_view(
        MonthView(
            models.Record,
            models.db.session,
            endpoint="/month",
            name="Últimos 30d",
        )
    )

    admin.add_view(
        ByOkStatus(
            models.Device,
            models.db.session,
            endpoint="/special/by_status/ok",
        )
    )
    admin.add_view(
        ByOfflineStatus(
            models.Device,
            models.db.session,
            endpoint="/special/by_status/offline",
        )
    )
    admin.add_view(
        ByWarningStatus(
            models.Device,
            models.db.session,
            endpoint="/special/by_status/warning",
        )
    )
    admin.add_view(
        ByDangerStatus(
            models.Device,
            models.db.session,
            endpoint="/special/by_status/danger",
        )
    )

    admin.add_view(
        LastCalibrationDayView(
            models.Device,
            models.db.session,
            endpoint="/special/last_calibration/day",
        )
    )
    admin.add_view(
        LastCalibrationWeekView(
            models.Device,
            models.db.session,
            endpoint="/special/last_calibration/week",
        )
    )
    admin.add_view(
        LastCalibrationMonthView(
            models.Device,
            models.db.session,
            endpoint="/special/last_calibration/month",
        )
    )
    admin.add_view(
        LastCalibrationYearView(
            models.Device,
            models.db.session,
            endpoint="/special/last_calibration/year",
        )
    )
    admin.add_view(
        LastCalibrationLongerView(
            models.Device,
            models.db.session,
            endpoint="/special/last_calibration/longer",
        )
    )
    admin.add_view(
        LastCalibrationNoView(
            models.Device,
            models.db.session,
            endpoint="/special/last_calibration/nocal",
        )
    )


from django.shortcuts import render,redirect
from django.contrib.auth.decorators import login_required

from .forms import ProfileForm
from django.contrib import messages
# Create your views here.

@login_required
def profile_view(request):
    return render(request,'oauth/profile.html')

@login_required
def change_profile_view(request):
    if request.method == 'POST':
        # 上传文件需要使用request.FILES
        form = ProfileForm(request.POST,request.FILES,instance=request.user)
        if form.is_valid():
            form.save()
            # 添加一条信息,表单验证成功就重定向到个人信息页面
            messages.add_message(request,messages.SUCCESS,'个人信息更新成功！')
            return redirect('oauth:profile')
    else:
        # 不是POST请求就返回空表单
        form = ProfileForm(instance=request.user)
    return render(request,'oauth/change_profile.html',context={'form':form})


#!/usr/bin/python

class Zillion():
	def __init__(self, digits):
		if digits == "": raise RuntimeError
		dit = False
		for i in digits:
			if i not in "1234567890, ": raise RuntimeError
		for i in digits:
			if i in "123467890":
				dit = True
		if not dit:raise RuntimeError

		self.degit = [i for i in digits if i != " " if i != ","]
		return None

	def increment(self):
		count = -1
		try:
			while self.degit[count] == "9":
				self.degit[count] = "0"
				count -= 1
			else:
				self.degit[count] = str(int(self.degit[count]) + 1)
		except IndexError:
			self.degit = ["1"] + ["0"]*len(self.degit)
	def isZero(self):
		for i in self.degit:
			if i != "0":
				return False
		else:
			return True

	def toString(self):
		return "".join(self.degit)


import bpy
import bmesh
import operator
import math

from . import settings
from . import utilities_bake
from . import op_bake

class op(bpy.types.Operator):
	bl_idname = "uv.textools_texture_select"
	bl_label = "Select Texture"
	bl_description = "Select the texture and bake mode"
	bl_options = {'REGISTER', 'UNDO'}

	name = bpy.props.StringProperty(
		name="image name",
		default = ""
	)

	@classmethod
	def poll(cls, context):
		return True

	def execute(self, context):
		select_texture(self, context)
		return {'FINISHED'}

def select_texture(self, context):
	print("Select "+self.name)

	# Set bake mode
	for mode in op_bake.modes:
		if mode in self.name:
			print("Found mode: "+mode)

			prop = bpy.context.scene.bl_rna.properties["TT_bake_mode"]
			enum_values = [e.identifier for e in prop.enum_items]

			# find matching enum
			for key in enum_values:
				print("TT_bake "+key)
				if mode in key:
					print("set m: "+key)
					bpy.context.scene.TT_bake_mode = key
					break;

			break

	# Set background image
	if self.name in bpy.data.images:
		image = bpy.data.images[self.name]
		for area in bpy.context.screen.areas:
			if area.type == 'IMAGE_EDITOR':
				area.spaces[0].image = image

'''
class op_ui_image_select(bpy.types.Operator):
	bl_idname = "uv.textools_ui_image_select"
	bl_label = "Select image"
	bl_description = "Select this image"

	image_name = bpy.props.StringProperty(
		name="image name",
		default = ""
	)

	@classmethod
	def poll(cls, context):
		return True

	def execute(self, context):
		# bpy.context.scene.tool_settings.use_uv_select_sync = False
		# bpy.ops.mesh.select_all(action='SELECT')

		print("Select image {}".format(self.image_name))
		# bpy.ops.image.save_as()
		return {'FINISHED'}
'''


import argparse
import hashlib
import os
import sys
import tempfile
import urllib.request
import zipfile

# update these if the E2E test data changes
ARCHIVE_BLOB_URL = "https://onnxruntimetestdata.blob.core.windows.net/training/onnxruntime_training_data.zip?snapshot=2020-04-14T02:10:05.3158245Z"
ARCHIVE_SHA256_DIGEST = "ea4168a801ded478f4e2af08232cb1174913caac300d5bf73b2652dc6894372c"

def _download(url, local_path):
  urllib.request.urlretrieve(url, local_path)

def _get_sha256_digest(file_path):
  alg = hashlib.sha256()
  read_bytes_length = 8192

  with open(file_path, mode="rb") as archive:
    while True:
      read_bytes = archive.read(read_bytes_length)
      if len(read_bytes) == 0: break
      alg.update(read_bytes)

  return alg.hexdigest()

def _check_file_sha256_digest(path, expected_digest):
  actual_digest = _get_sha256_digest(path)
  match = actual_digest.lower() == expected_digest.lower()
  if not match:
    raise RuntimeError(
        "SHA256 digest mismatch, expected: {}, actual: {}".format(expected_digest.lower(), actual_digest.lower()))

def _extract_archive(archive_path, target_dir):
  with zipfile.ZipFile(archive_path) as archive:
    archive.extractall(target_dir)

def main():
  parser = argparse.ArgumentParser(description="Downloads training end-to-end test data.")
  parser.add_argument("target_dir", help="The test data destination directory.")
  args = parser.parse_args()

  with tempfile.TemporaryDirectory() as temp_dir:
    archive_path = os.path.join(temp_dir, "archive.zip")
    print("Downloading E2E test data from '{}'...".format(ARCHIVE_BLOB_URL))
    _download(ARCHIVE_BLOB_URL, archive_path)
    _check_file_sha256_digest(archive_path, ARCHIVE_SHA256_DIGEST)
    print("Extracting to '{}'...".format(args.target_dir))
    _extract_archive(archive_path, args.target_dir)
    print("Done.")

if __name__ == "__main__":
  sys.exit(main())


#! /usr/bin/python2

# import actionlib library used for calling actions
import actionlib
import rospy

# import custom action file. Since actions are based on messages, notice how we import actions from the msg directory of a package.
from beginner_tutorials.msg import my_actAction, my_actResult, my_actFeedback

class Server():

    def __init__(self):
        # create a simple ActionServer by passing the name, action type, and callback function as its parameters.
        # auto_start has to be declared explicitly and always has to be set to False to prevent autostarting the server (can break your code otherwise).
        self.my_server = actionlib.SimpleActionServer('simple_server', my_actAction, self.execute, auto_start = False)
        # start server
        self.my_server.start()

    def execute(self, action):

        self.res = my_actResult()
        self.res.result = "Success"
        # Once the necessary function is executed, the server notifies the client that the goal is complete by calling set_succeeded.
        self.my_server.set_succeeded(self.res)

        print(self.res.result)
        print(action.threshold)

        # Some condition for feedback
        feedback = my_actFeedback()
        feedback.feed = 10.0
        server.publish_feedback(feedback)

rospy.init_node('Action_Server')

# initialize object called server to call the Server() class.
server = Server()

rospy.spin()


#Implments the linear regression model. Accuracy of 40%

import pandas as pd
import csv, math , datetime
import time
import numpy as np
from sklearn import preprocessing, cross_validation, svm
from sklearn.linear_model import LinearRegression, LogisticRegression
import matplotlib.pyplot as plt
from matplotlib import style
style.use('ggplot')
#All the libraries required
df = pd.read_csv("loaddata.txt")
df = df[['Date','Hour','Minute','Volume']]
#our data frame contains the follwoing we can choose what we want
forcast_col='Volume'
#the column that we want to predict
df.fillna(-99999, inplace=True)
#print(df)
forecast_out = int(math.ceil(0.02*len(df)))
#this is the logic we need to know, how many days prediction can be calculated in this eqaution.
df['label'] = df[forcast_col].shift(-forecast_out)
#print(df)
#print(forecast_out)

"""
df = pd.read_csv("loaddata.txt")
df = df[['Date','Hour','Minute','Volume']]
#our data frame contains the follwoing we can choose what we want
forcast_col='Volume'
#the column that we want to predict
df.fillna(-99999, inplace=True)
#print(df)
forecast_out = int(math.ceil(0.02*len(df)))
#this is the logic we need to know, how many days prediction can be calculated in this eqaution.
df['label'] = df[forcast_col].shift(-forecast_out)
#print(df)
#print(forecast_out)
"""

X = np.array(df.drop(['label'],1))
X = preprocessing.scale(X)
X_lately = X[-forecast_out:]
#This contains all the data till the forecasy_out value
X = X[:-forecast_out:]
df.dropna(inplace=True)
#print(df)
df.dropna(inplace=True)
y = np.array(df['label'])
y = np.array(df['label'])
#print(len(X),len(y))
X_train, X_test, y_train, y_test = cross_validation.train_test_split(X, y, test_size=0.3)
#the size of the testing data
clf = LinearRegression()
clf.fit(X_train,y_train)
accuracy = clf.score(X_test,y_test)
forecast_set = clf.predict(X_lately)
print('Linear Regression accuracy: ', accuracy*100,'%')
df['Volume'].plot()
df['label'].plot()
plt.legend(loc=4)
plt.xlabel('Records')
plt.ylabel('Volume in MW')
plt.show()


# YOLOv5 ЁЯЪА by Ultralytics, GPL-3.0 license
"""
Dataloaders and dataset utils
"""
import os
import random

import numpy as np
import torch
from torch.utils.data import DataLoader, distributed

from .datasets.loadimagesandlabels import LoadImagesAndLabels
from .loaders.infinitedataloader import InfiniteDataLoader
from ..utils.torchutil import torch_distributed_zero_first
from ..utils.logger import LOGGER
from .. import PIN_MEMORY, RANK

def seed_worker(worker_id):
    # Set dataloader worker seed https://pytorch.org/docs/stable/notes/randomness.html#dataloader
    worker_seed = torch.initial_seed() % 2 ** 32
    np.random.seed(worker_seed)
    random.seed(worker_seed)

def create_dataloader(path,
                      imgsz,
                      batch_size,
                      stride,
                      single_cls=False,
                      hyp=None,
                      augment=False,
                      cache=False,
                      pad=0.0,
                      rect=False,
                      rank=-1,
                      workers=8,
                      image_weights=False,
                      quad=False,
                      prefix='',
                      shuffle=False):
    if rect and shuffle:
        LOGGER.warning('WARNING тЪая╕П --rect is incompatible with DataLoader shuffle, setting shuffle=False')
        shuffle = False
    with torch_distributed_zero_first(rank):  # init dataset *.cache only once if DDP
        dataset = LoadImagesAndLabels(
            path,
            imgsz,
            batch_size,
            augment=augment,  # augmentation
            hyp=hyp,  # hyperparameters
            rect=rect,  # rectangular batches
            cache_images=cache,
            single_cls=single_cls,
            stride=int(stride),
            pad=pad,
            image_weights=image_weights,
            prefix=prefix)

    batch_size = min(batch_size, len(dataset))
    nd = torch.cuda.device_count()  # number of CUDA devices
    nw = min([os.cpu_count() // max(nd, 1), batch_size if batch_size > 1 else 0, workers])  # number of workers
    sampler = None if rank == -1 else distributed.DistributedSampler(dataset, shuffle=shuffle)
    loader = DataLoader if image_weights else InfiniteDataLoader  # only DataLoader allows for attribute updates
    generator = torch.Generator()
    generator.manual_seed(6148914691236517205 + RANK)
    return loader(dataset,
                  batch_size=batch_size,
                  shuffle=shuffle and sampler is None,
                  num_workers=nw,
                  sampler=sampler,
                  pin_memory=PIN_MEMORY,
                  collate_fn=LoadImagesAndLabels.collate_fn4 if quad else LoadImagesAndLabels.collate_fn,
                  worker_init_fn=seed_worker,
                  generator=generator), dataset

# Classification dataloaders -------------------------------------------------------------------------------------------
from .datasets.classificationdataset import ClassificationDataset

def create_classification_dataloader(path,
                                     imgsz=224,
                                     batch_size=16,
                                     augment=True,
                                     cache=False,
                                     rank=-1,
                                     workers=8,
                                     shuffle=True):
    # Returns Dataloader object to be used with YOLOv5 Classifier
    with torch_distributed_zero_first(rank):  # init dataset *.cache only once if DDP
        dataset = ClassificationDataset(root=path, imgsz=imgsz, augment=augment, cache=cache)
    batch_size = min(batch_size, len(dataset))
    nd = torch.cuda.device_count()
    nw = min([os.cpu_count() // max(nd, 1), batch_size if batch_size > 1 else 0, workers])
    sampler = None if rank == -1 else distributed.DistributedSampler(dataset, shuffle=shuffle)
    generator = torch.Generator()
    generator.manual_seed(6148914691236517205 + RANK)
    return InfiniteDataLoader(dataset,
                              batch_size=batch_size,
                              shuffle=shuffle and sampler is None,
                              num_workers=nw,
                              sampler=sampler,
                              pin_memory=PIN_MEMORY,
                              worker_init_fn=seed_worker,
                              generator=generator)  # or DataLoader(persistent_workers=True)


class Cinema:
    def __init__(self):
        self.peliculas = {
            "peli1": "11.30am",
            "peli2": "02.00pm",
            "peli3": "04.30pm",
            "peli4": "07.00pm"
        }
        self.alimentos = {
            "alimento1": "2000",
            "alimento2": "4000",
            "alimento3": "6000",
            "alimento4": "8000"
        }
        self.proximas_peliculas = ["proxima1", "proxima2", "proxima3", "proxima4"]
        self.empleados = {"lalo": "1234", "jhon": "5674"}
        self.cupones = 0

        self.contadores_tikets = [0, 0, 0, 0]
        self.contadores_alimentos = [0, 0, 0, 0]

        while self.cupones < 50:
            self.cl = input("""
                Si es empleado, digite 0.
                Si es cliente:
                ¿Qué tipo de cliente es usted?
                1. Cliente Frecuente
                2. Visitante

                Si es administrador, digite su contraseña: """)
            if self.cl == "0":
                self.empleado()
            elif self.cl == "1":
                self.menu_cliente_frecuente()
            elif self.cl == "2":
                self.menu_visitante()
            elif self.cl == "god":
                self.admin()

    def empleado(self):
        # Implementa la lógica para el empleado aquí
        pass

    def menu_cliente_frecuente(self):
        self.usua = input("Digite su usuario: ")
        self.contra = input("Digite su contraseña: ")
        if self.usua in self.empleados and self.empleados[self.usua] == self.contra:
            self.accfre = input("""
                ¿Qué desea hacer?
                1. Ver lista de películas
                2. Comprar tiquetes
                3. Comprar comidas
                4. Reservar películas
                """)

            if self.accfre == "1":
                print("Lista de películas:")
                for pelicula, hora in self.peliculas.items():
                    print(f"{pelicula}: {hora}")

            elif self.accfre == "2":
                print("Lista de películas:")
                for pelicula, _ in self.peliculas.items():
                    print(pelicula)
                pelicula_elegida = input("¿De qué película desea el tiquete? (peli1, peli2, peli3, peli4) ")
                if pelicula_elegida in self.peliculas:
                    index = list(self.peliculas.keys()).index(pelicula_elegida)
                    self.contadores_tikets[index] += 1
                    print(f"Ha adquirido un tiquete para {pelicula_elegida}.")
                    self.cupones += 1

            elif self.accfre == "3":
                print("Lista de comidas:")
                for comida, precio in self.alimentos.items():
                    print(f"{comida}: ${precio}")
                comida_elegida = input("¿Qué alimento desea? (alimento1, alimento2, alimento3, alimento4) ")
                if comida_elegida in self.alimentos:
                    index = list(self.alimentos.keys()).index(comida_elegida)
                    self.contadores_alimentos[index] += 1
                    print(f"Ha adquirido {comida_elegida}.")
                    self.cupones += 1

            elif self.accfre == "4":
                pelicula_reservada = input("¿Qué película desea reservar? (proxima1, proxima2, proxima3, proxima4) ")
                if pelicula_reservada in self.proximas_peliculas:
                    print(f"Ha reservado {pelicula_reservada}.")

        else:
            print("Credenciales incorrectas.")

    def menu_visitante(self):
        self.accfree = input("""
                ¿Qué desea hacer?
                1. Ver lista de películas
                2. Comprar tiquetes
                3. Comprar comidas
                """)

        if self.accfree == "1":
            print("Lista de películas:")
            for pelicula, hora in self.peliculas.items():
                print(f"{pelicula}: {hora}")

        elif self.accfree == "2":
            print("Lista de películas:")
            for pelicula, _ in self.peliculas.items():
                print(pelicula)
            pelicula_elegida = input("¿De qué película desea el tiquete? (peli1, peli2, peli3, peli4) ")
            if pelicula_elegida in self.peliculas:
                index = list(self.peliculas.keys()).index(pelicula_elegida)
                self.contadores_tikets[index] += 1
                print(f"Ha adquirido un tiquete para {pelicula_elegida}.")
                self.cupones += 1

        elif self.accfree == "3":
            print("Lista de comidas:")
            for comida, precio in self.alimentos.items():
                print(f"{comida}: ${precio}")
            comida_elegida = input("¿Qué alimento desea? (alimento1, alimento2, alimento3, alimento4) ")
            if comida_elegida in self.alimentos:
                index = list(self.alimentos.keys()).index(comida_elegida)
                self.contadores_alimentos[index] += 1
                print(f"Ha adquirido {comida_elegida}.")
                self.cupones += 1

    def admin(self):
        tiv = [self.contadores_tikets]
        tia = [self.contadores_alimentos]
        print("Tiquetes vendidos por película:")
        for pelicula, cantidad in zip(self.peliculas.keys(), self.contadores_tikets):
            print(f"{pelicula}: {cantidad} tiquetes vendidos")
        print("Comidas vendidas por tipo:")
        for comida, cantidad in zip(self.alimentos.keys(), self.contadores_alimentos):
            print(f"{comida}: {cantidad} unidades vendidas")

if __name__ == "__main__":
    cinema = Cinema()


import uuid
from django.db.models.signals import post_save
from django.dispatch import receiver
from boto3.session import Session
from api import settings
from django.db import models
from hall.models import Hall
from django.contrib.postgres.fields import ArrayField
from datetime import datetime,timedelta
from django.utils.dateparse import parse_datetime
from django.db.models.signals import pre_delete
from django.dispatch import receiver
from botocore.client import Config
from random import randint

session = Session(aws_access_key_id=settings.AWS_ACCESS_KEY_ID,
                          aws_secret_access_key=settings.AWS_SECRET_ACCESS_KEY)

s3_client = session.client('sns','us-east-2')

SERVICE_TYPES = (
        (1, "Wedding"),
        (2, "Preaching"),
        (3, "Circumcision"),
        (4, "Other"),
        (5, "Wedding2")
    )

class Reservation(models.Model):

    id = models.UUIDField(primary_key=True,default=uuid.uuid4, editable=False)
    service_type = models.PositiveSmallIntegerField(choices=SERVICE_TYPES, default=1)
    name1 = models.TextField(max_length=100,default="",blank=True,null=True)
    name2 = models.TextField(max_length=50,default="",blank=True,null=True)
    phone = models.TextField(max_length=10)
    hall = models.ForeignKey(Hall, on_delete=models.PROTECT, related_name="hall")
    date = models.DateTimeField(default=datetime.now)
    expired = models.BooleanField(default=False)
    portion = ArrayField(ArrayField(models.SmallIntegerField()))
    wedding_count = models.PositiveSmallIntegerField(default=1)
    duration = models.PositiveIntegerField(default=5)
    duration_end = models.DateTimeField(default=datetime.now)
    payment_done = models.BooleanField(default=False)
    code = models.IntegerField(default=11111111)
    count_of_visit = models.IntegerField(default=0)
    num_of_unpaid  = models.IntegerField(default=0)
    hidden = models.BooleanField(default=False)

    def save(self, *args, **kwargs):
        if self.code == 11111111:
            self.code = randint(11111112, 99999999)
        if isinstance(self.date,datetime):
            self.duration_end = self.date + timedelta(weeks=52 * self.duration)
        else:
            self.duration_end = parse_datetime(self.date) + timedelta(weeks=52 * self.duration)

        super().save(*args, **kwargs)

class ReservationImage(models.Model):
    reservation = models.ForeignKey(Reservation, related_name='images',on_delete=models.CASCADE)
    name = models.SlugField()

    def __str__(self):
        return self.name

@receiver(pre_delete, sender=Reservation)
def log_deleted_question(sender, instance, using, **kwargs):
    images = ReservationImage.objects.filter(reservation=instance)

    if len(images) > 0:
        s3_client = session.client('s3', region_name="us-east-2",
                                   config=Config(signature_version='s3v4'))
        s3_resource = session.resource('s3', region_name="us-east-2", config=Config(signature_version='s3v4'))
        my_bucket = s3_resource.Bucket(settings.AWS_STORAGE_BUCKET_NAME)
        my_bucket_resized = s3_resource.Bucket(settings.AWS_STORAGE_BUCKET_NAME_RESIZED)
        obj = []
        obj_resized = []

        for image in images:
            obj.append({'Key': 'photos/' + str(instance.id) + '/' + image.name + "/image.jpg"})
            obj_resized.append({'Key': 'resized-photos/' + str(instance.id) + '/' + image.name + "/image.jpg"})

        my_bucket.delete_objects(
            Delete={
                'Objects': obj,
            }
        )
        my_bucket_resized.delete_objects(
            Delete={
                'Objects': obj_resized,
            }
        )


# -*- coding: utf-8 -*-
from openerp import models, fields, api
from .budget_common_report_wizard import Common

class BudgetPlanUnitAnalysisReportWizard(models.TransientModel, Common):

    _name = 'budget.plan.unit.analysis.report.wizard'

    fiscalyear_id = fields.Many2one(
        'account.fiscalyear',
        string='Financial Year',
        required=True,
    )
    org_id = fields.Many2one(
        'res.org',
        string='Org',
    )
    sector_id = fields.Many2one(
        'res.sector',
        string='Sector',
    )
    subsector_id = fields.Many2one(
        'res.subsector',
        string='Subsector',
    )
    division_id = fields.Many2one(
        'res.division',
        string='Division',
    )
    section_id = fields.Many2one(
        'res.section',
        string='Section',
    )
    budget_method = fields.Selection(
        [('revenue', 'Revenue'),
         ('expense', 'Expense')],
        string='Budget Method',
        default='expense',
    )

    @api.multi
    def xls_export(self):
        fields = ['fiscalyear_id', 'org_id', 'sector_id', 'subsector_id',
                  'division_id', 'section_id', 'budget_method']
        report_name = 'budget_plan_unit_analysis_report_xls'
        return self._get_report(fields, report_name)


import time
import sys

def get_given():
    print('\nSeparate with commas!')
    print('E.G: 42, 23, 21, 15, 3, 6, 12, 21 (This will automatically get sorted)')
    user_input = input("> ")

    separated = user_input.split(',')
    numbered = list(map(lambda x: int(x.strip()) , separated))

    return sorted(numbered)

def ordinalize(number):
    if number == 11 or number == 12 or number == 13:
        return str(number ) + 'th'

    last_number = str(number)[-1]

    if last_number == '1':
        return str(number) + 'st'
    elif last_number == '2':
        return str(number) + 'nd'
    elif last_number == '3':
        return str(number) + 'rd'
    else:
        return str(number) + 'th'

def separate_decimals(float_val):
    splitted = str(float_val).split('.')

    if len(splitted) == 2:
        # There is a decimal
        return (int(splitted[0]), int(splitted[1]))
    else:
        # There is no decimal
        return (int(splitted[0]), 0)

def custom_round(number):
    whole, dec = separate_decimals(number)
    first_dec = int(str(dec)[0])

    if first_dec >= 5:
        return whole + 1
    else:
        return whole

def linear_interpolation(k, denominator, given):
    first_answer = (k * (len(given) + 1)) / denominator
    final_answer = 0
    whole, dec = separate_decimals(first_answer)

    dec = float('0.' + str(dec))

    letter = None
    if denominator == 4:
        letter = 'Q'
    elif denominator == 10:
        letter = 'D'
    else:
        letter = 'P'

    print('-'*50)
    print('LINEAR INTERPOLATION METHOD')

    print(f'\n{letter}{k} = k(n + 1) / {denominator}')
    print(f'{letter}{k} = {k}({len(given)} + 1) / {denominator}')
    print(f'{letter}{k} = {k}({len(given) + 1}) / {denominator}')
    print(f'{letter}{k} = {k * (len(given) + 1)} / {denominator}')
    print(f'{letter}{k} = {ordinalize(first_answer)}')

    if dec != 0.0:
        first_num = given[int(whole) - 1]
        second_num = given[int(whole)]

        final_answer = first_num + (dec * (second_num - first_num))

        print(f'\n{letter}{k} = {ordinalize(int(whole))} + {dec}({ordinalize(int(whole + 1))} - {ordinalize(int(whole))})')
        print(f'{letter}{k} = {first_num} + {dec}({second_num} - {first_num})')
        print(f'{letter}{k} = {first_num} + {dec}({second_num - first_num})')
        print(f'{letter}{k} = {first_num} + {dec * (second_num - first_num)}')
        print(f'{letter}{k} = {final_answer}')
    else:
        final_answer = given[int(whole) - 1]

        print(f'\nSince "Q{k} class" ({first_answer}) is a whole number. We can just get the position and we have our final answer')
        print(f'Q{k} = {final_answer}')

def general_method(k, denominator, given):
    letter = None
    if denominator == 4:
        letter = 'Q'
    elif denominator == 10:
        letter = 'D'
    else:
        letter = 'P'

    print('-'*50)
    print('GENERAL METHOD')

    first_answer = (k * len(given)) / denominator

    print(f'\n{letter}{k} = kn / {denominator}')
    print(f'{letter}{k} = ({k})({len(given)}) / {denominator}')
    print(f'{letter}{k} = {k * len(given)} / {denominator}')
    print(f'{letter}{k} = {ordinalize(first_answer)}')

    whole, dec = separate_decimals(first_answer)

    if dec != 0:
        rounded = custom_round(first_answer)

        print(f'{letter}{k} = {ordinalize(rounded)}')
        print(f'{letter}{k} = {given[rounded - 1]}')
    else:
        final_answer = (given[int(whole) - 1] + given[int(whole)]) / 2

        print(f'\n{letter}{k} = ({ordinalize(int(whole))} + {ordinalize(int(whole+1))}) / 2')
        print(f'{letter}{k} = ({given[int(whole) - 1]} + {given[int(whole)]}) / 2')
        print(f'{letter}{k} = {given[int(whole) - 1] + given[int(whole)]} / 2')
        print(f'{letter}{k} = {final_answer}')

        i, final_answer_dec = separate_decimals(final_answer)

        if final_answer_dec != 0:
            print(f'{letter}{k} = {custom_round(final_answer)}')

def mendenhall_sincich_method(k, denominator, given):
    first_answer = (k * (len(given) + 1)) / denominator
    whole, dec = separate_decimals(first_answer)

    letter = None
    round_up_down_median = ''
    if denominator == 4:
        letter = 'Q'

        if k == 2:
            round_up_down_median = 'median'
        elif k < 2:
            round_up_down_median = 'up'
        else:
            round_up_down_median = 'down'
    elif denominator == 10:
        letter = 'D'

        if k == 5:
            round_up_down_median = 'median'
        elif k < 5:
            round_up_down_median = 'up'
        else:
            round_up_down_median = 'down'
    else:
        letter = 'P'

        if k == 50:
            round_up_down_median = 'median'
        elif k < 50:
            round_up_down_median = 'up'
        else:
            round_up_down_median = 'down'

    print('-'*50)
    print('MENDELHALL AND SINCICH METHOD')

    print(f'\n{letter}{k} = k(n + 1) / {denominator}')
    print(f'{letter}{k} = {k}({len(given)} + 1) / {denominator}')
    print(f'{letter}{k} = {k}({len(given) + 1}) / {denominator}')
    print(f'{letter}{k} = {k * (len(given) + 1)} / {denominator}')
    print(f'{letter}{k} = {ordinalize(first_answer)}')

    if dec == 0:
        print(f'{letter}{k} = {given[int(whole) - 1]}')
        return

    if round_up_down_median == 'median':
        final_answer = (given[int(whole) - 1] + given[int(whole)]) / 2

        print(f'\n{letter}{k} = ({ordinalize(int(whole))} + {ordinalize(int(whole+1))}) / 2')
        print(f'{letter}{k} = ({given[int(whole) - 1]} + {given[int(whole)]}) / 2')
        print(f'{letter}{k} = {given[int(whole) - 1] + given[int(whole)]} / 2')
        print(f'{letter}{k} = {final_answer}')

        i, final_answer_dec = separate_decimals(final_answer)

        if final_answer_dec != 0:
            print(f'{letter}{k} = {custom_round(final_answer)}')

    elif round_up_down_median == 'up':
        next_number = int(whole) + 1

        print(f'{letter}{k} = {ordinalize(next_number)}')
        print(f'{letter}{k} = {given[next_number - 1]}')
    else:
        print(f'{letter}{k} = {ordinalize(int(whole))}')
        print(f'{letter}{k} = {given[int(whole) - 1]}')

def solve(k, denominator, given):
    print('\nSelect method:')
    method_chosen = input('[a] General Method \n[b] Mendenhall and Sinchich Method \n[c] Linear Interpolation Method\n[d] All \n> ').lower()

    if method_chosen == 'a':
        general_method(k, denominator, given)
    elif method_chosen == 'b':
        mendenhall_sincich_method(k, denominator, given)
    elif method_chosen == 'd':
        general_method(k, denominator, given)
        mendenhall_sincich_method(k, denominator, given)
        linear_interpolation(k, denominator, given)
    else:
        linear_interpolation(k, denominator, given)

    print('-'*50)

def main():
    given = get_given()

    while True:
        print('\nYour given: ' + ', '.join(map(lambda x: str(x), given)))
        choice = input('[Q]uantile \n[D]ecile \n[P]ercentile \n[E]xit \n> ').lower()

        if choice == 'q':
            k = int(input('Input Qx = '))

            solve(k, 4, given)
            time.sleep(5)
        elif choice == 'd':
            k = int(input('Input Dx = '))

            solve(k, 10, given)
            time.sleep(5)
        elif choice == 'p':
            k = int(input('Input Px = '))

            solve(k, 100, given)
            time.sleep(5)
        elif choice == 'e':
            print('\nWag ka magpapahuli')
            time.sleep(3)
            sys.exit()

if __name__ == "__main__":
    try:
        main()
    except KeyboardInterrupt:
        print('\n\nWag ka magpapahuli')
        time.sleep(3)


# Ayan Chakraborty 18EC10075
# CS60050 ML MiniProject 3 Code: CS4
# Code for Hierarchial Algo

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt

# returns the euclidean distance between 2 data samples
def euclidean_distance(v1, v2):
	return np.linalg.norm(v1 - v2)

# read the dataset excluding the 1st coloumn which is the index coloumn
df = pd.read_csv("cricket_4_unlabelled.csv", index_col = 0)

# Z-Score normalization of each coloumn
cols = list(df.columns)
for col in cols:
	df[col] = (df[col] - df[col].mean())/df[col].std(ddof = 0)

# Convert the dataset into numpy array
X = df.to_numpy()
scores = []

# Initializations
num_clusters = X.shape[0]
data_indices = [[] for temp in range(num_clusters)]
class_ids = np.zeros((1, X.shape[0]))

# Initially each data sample is a cluster
for i in range(X.shape[0]):
	data_indices[i].append(i)

# Do hierarchial merging until only single cluster left
while(num_clusters > 1):
	k = num_clusters

	# Initialize the proximity matrix
	proximity_mat = np.zeros((num_clusters, num_clusters))

	# All diagonal elements set to infinity (Just for ease of calculation so that the minimum distance returned will not be to its own center (i.e, 0))
	np.fill_diagonal(proximity_mat, np.inf)

	# Compute the Proximity matrix
	for i in range(num_clusters):
		for j in range((i+1), num_clusters):
			# ALl possible distances between any two points in the two clusters
			dists = [[euclidean_distance(X[index_1,:], X[index_2,:]) for index_2 in data_indices[j]] for index_1 in data_indices[i]]
			# Choose the minimum distance (Single Linkage)
			proximity_mat[i, j] = np.amin(dists)
			# Due to symmetry
			proximity_mat[j, i] = proximity_mat[i, j]

	# Co-ordinates of the point where minimum distance between two clusters
	index = np.unravel_index(proximity_mat.argmin(), proximity_mat.shape)
	# Index of 1st Cluster to be merged
	min_index = min(index[0], index[1])
	# Index of 2nd Cluster to be merged
	max_index = max(index[0], index[1])

	# Merging the two clusters
	for i in range(num_clusters):
		if i == min_index:
			# Append the 2nd cluster to the 1st Cluster
			data_indices[i] = data_indices[min_index] + data_indices[max_index]

	# Delete the 2nd cluster
	del data_indices[max_index]
	# Update the number of clusters
	num_clusters = num_clusters - 1

	# Compute the cluster index for each data sample (for ease of calcualation of Silhouette score)
	for i in range(num_clusters):
		for index in data_indices[i]:
			class_ids[0, index] = i

	# print(len(data_indices))

	# Recompute the proximity matrix to account for 1 less cluster
	proximity_mat = np.zeros((num_clusters, num_clusters))
	np.fill_diagonal(proximity_mat, np.inf)

	for i in range(num_clusters):
		for j in range((i+1), num_clusters):
			dists = [[euclidean_distance(X[index_1,:], X[index_2,:]) for index_2 in data_indices[j]] for index_1 in data_indices[i]]
			proximity_mat[i, j] = np.amin(dists)
			proximity_mat[j, i] = proximity_mat[i, j]

	print("Now computing Sihoutte coefficients")
	sil_coeffs = np.zeros((1, X.shape[0]))

	# Silgouette score calculation
	for i in range(X.shape[0]):
		# Cluster ID of current data sample
		class_id = int(class_ids[0, i])
		# Mean distance to all data samples in the same cluster
		intra_dist = np.mean(np.array([euclidean_distance(X[i,:], X[j,:]) for j in data_indices[class_id]]))
		# Choose the cluster whose sinngle linkage distance is minimum
		min_index = np.argmin(proximity_mat[class_id, :])
		# Calculate the mean distance to all points in that cluster
		inter_dist = np.mean(np.array([euclidean_distance(X[i,:], X[j,:]) for j in data_indices[min_index]]))
		# Calculate the silhouette score
		sil_coeffs[0,i] = (inter_dist - intra_dist)/(max(intra_dist, inter_dist))

	print("The average Sihoutte coefficient for k = {}, is: {}".format(k, np.mean(np.array(sil_coeffs))))
	# if(num_clusters <= 6):
	scores.append(np.mean(np.array(sil_coeffs)))

k = np.arange(2, X.shape[0]+1)

# To make from [2, X.shape[0]]
scores.reverse()
np.savetxt("data.csv", scores, delimiter = ",")

# plotting
plt.xlabel("Value of K (number of clusters)")
plt.ylabel("Silhoutte Coefficient Score")
plt.title("Variation of Silhoutte scores with K")
plt.plot(k,	scores)
plt.savefig("result_1.jpg")


#Creación de una instancia
#Ejemplo de objetos del tipo animal

class Animal:
    def __init__(self,e,a):
        self.especie=e
        self.edad=a
    def correr(self):
        print('Soy un {}.'
              'Estoy corriendo'.format(self.especie))

    def crecer(self,edad=0):
        if(self.edad+edad)>14:
            self.vivo=False

        else:
            self.edad+=edad
            self.vivo=True

#Se instancia un perro
perro=Animal('perro',3)

#Para obtener algunos atributos
print("hola soy un {} "
      "tengo {} años".format(perro.especie,perro.edad))

#Se pueden ejecutar algunas funciones

perro.crecer(10)
print("hola soy un {} "
      "tengo {} años".format(perro.especie,perro.edad))
#perro.crecer(-10)
perro.crecer(2)
#adicionalmente se pueden consultar atributos

if perro.vivo:
    print("hola soy un {} "
          "tengo {} años".format(perro.especie, perro.edad))
else:
    print('...Me morí...RIP')


import os
import graphviz

os.environ["PATH"] += os.pathsep + 'C:/Users/fabio/anaconda3/Library/bin/graphviz'

# Classes

# Und-Verknüpfungselement
class ANDNODE:
    def __init__(self, name):
        self.name = name
        self.nodes = []

    def add(self, node):
        self.nodes.append(node)

    def print(self, Graph):
        Graph.node(self.name, label=self.name + ' (&)', shape='rectangle')
        for node in self.nodes:
            Graph.edge(self.name, node.name)
            if not isinstance(node, EVENT):
                node.print(Graph)

    def topdown(self, mat):
        if self == TOP:
            mat[0] = self.nodes
            i = 0
            while i < len(mat):
                mat_node = False
                for i in range(len(mat)):
                    for j in range(len(mat[i])):
                        if not isinstance(mat[i][j], EVENT):
                            mat = mat[i][j].topdown(mat)
                            mat_node = True
                            break
                    if i == len(mat) - 1:
                        i = len(mat)
                    if mat_node:
                        break
        else:
            mat_node = False
            for i in range(len(mat)):
                for j in range(len(mat[i])):
                    if mat[i][j].name == self.name:
                        del mat[i][j]
                        for node in self.nodes:
                            mat[i].append(node)
                        mat_node = True
                        break
                if mat_node:
                    break
        return mat

# Oder-Verknüpfungselement
class ORNODE:
    def __init__(self, name):
        self.name = name
        self.nodes = []

    def add(self, node):
        self.nodes.append(node)

    def print(self, Graph):
        Graph.node(self.name, label=self.name + ' (>=1)', shape='rectangle')
        for node in self.nodes:
            Graph.edge(self.name, node.name)
            if not isinstance(node, EVENT):
                node.print(Graph)

    def topdown(self, mat):
        if self == TOP:
            del mat[0]
            anzahl_and = sum(isinstance(node, ANDNODE) for node in self.nodes)
            if anzahl_and < len(self.nodes):
                for i in range(len(self.nodes)):
                    if not isinstance(self.nodes[i], ANDNODE):
                        mat.append([self.nodes[i]])
            else:
                for i in range(len(self.nodes)):
                    mat.append([self.nodes[i]])
            i = 0
            while i < len(mat):
                mat_node = False
                for i in range(len(mat)):
                    for j in range(len(mat[i])):
                        if not isinstance(mat[i][j], EVENT):
                            mat = mat[i][j].topdown(mat)
                            mat_node = True
                            break
                    if i == len(mat) - 1:
                        i += 1
                    if mat_node:
                        break
        else:
            mat_node = False
            for i in range(len(mat)):
                for j in range(len(mat[i])):
                    if mat[i][j].name == self.name:
                        mat_kopie = mat[i]
                        del mat[i]
                        anzahl_and = sum(isinstance(node, ANDNODE) for node in self.nodes)
                        if anzahl_and < len(self.nodes):
                            for node in self.nodes:
                                if not isinstance(node, ANDNODE):
                                    mat_kopie[j] = node
                                    mat.append(list(mat_kopie))
                            mat_node = True
                            break
                        else:
                            for node in self.nodes:
                                mat_kopie[j] = node
                                mat.append(list(mat_kopie))
                            mat_node = True
                            break
                if mat_node:
                    break
        return mat

# Ausfallwahrscheinlichkeitselement
class EVENT:
    def __init__(self, name, probability):
        self.name = name
        self.probability = probability

    def print(self, Graph):
        Graph.node(self.name, label=self.name + ' (' + str(self.probability) + ')', shape='ellipse')

# Verbindungskante
class CONNECT:
    def __init__(self, name, node):
        self.name = name
        self.node = node

    def print(self, Graph):
        Graph.node(self.name, label=self.name, shape='point')
        Graph.edge(self.name, self.node.name)
        if not isinstance(self.node, EVENT):
            self.node.print(Graph)

# BDD-Node
class NODE:
    def __init__(self, name):
        self.name = name
        self.left = None
        self.right = None

    def print(self, Graph):
        Graph.node(self.name, label=self.name, shape='ellipse')
        self.left.print(Graph)
        self.right.print(Graph)

# BDD-Ausfallwahrscheinlichkeitselement
class BDDEVENT:
    def __init__(self, name, probability):
        self.name = name
        self.probability = probability

    def print(self, Graph):
        Graph.node(self.name, label=self.name + ' (' + str(self.probability) + ')', shape='ellipse')

# FT in BDD umwandeln
class FT2BDD:
    def __init__(self, root):
        self.root = root

    def create(self):
        bdd = NODE(self.root.name)
        bdd = self.build(bdd, self.root)
        return bdd

    def build(self, bdd_node, ft_node):
        if isinstance(ft_node, EVENT):
            return BDDEVENT(ft_node.name, ft_node.probability)
        elif isinstance(ft_node, ANDNODE):
            if bdd_node.left is None:
                bdd_node.left = self.build(bdd_node.left, ft_node.nodes[0])
                bdd_node.right = self.build(bdd_node.right, ft_node.nodes[1])
            else:
                bdd_node.right = self.build(bdd_node.right, ft_node)
            return bdd_node
        elif isinstance(ft_node, ORNODE):
            if bdd_node.left is None:
                bdd_node.left = self.build(bdd_node.left, ft_node.nodes[0])
                bdd_node.right = self.build(bdd_node.right, ft_node.nodes[1])
            else:
                left = NODE(bdd_node.name + 'L')
                right = NODE(bdd_node.name + 'R')
                left = self.build(left, ft_node.nodes[0])
                right = self.build(right, ft_node.nodes[1])
                bdd_node.left = left
                bdd_node.right = right
            return bdd_node

    def show(self, bdd):
        Graph = graphviz.Digraph('BDD', filename='BDD.gv', format='png')
        bdd.print(Graph)
        Graph.view()

# Print FT using Graphviz
def print_ft(ft):
    Graph = graphviz.Digraph('FT', filename='FT.gv', format='png')
    ft.print(Graph)
    Graph.view()

# Print BDD using Graphviz
def print_bdd(bdd):
    Graph = graphviz.Digraph('BDD', filename='BDD.gv', format='png')
    bdd.print(Graph)
    Graph.view()

# Sample usage
if __name__ == '__main__':
    # Create FT
    E1 = EVENT('E1', 0.1)
    E2 = EVENT('E2', 0.2)
    E3 = EVENT('E3', 0.15)
    E4 = EVENT('E4', 0.25)

    AND1 = ANDNODE('AND1')
    AND1.add(E1)
    AND1.add(E2)

    AND2 = ANDNODE('AND2')
    AND2.add(E3)
    AND2.add(E4)

    OR1 = ORNODE('OR1')
    OR1.add(AND1)
    OR1.add(AND2)

    FT = OR1

    # Print FT
    print_ft(FT)

    # Convert FT to BDD
    converter = FT2BDD(FT)
    BDD = converter.create()

    # Print BDD
    print_bdd(BDD)


import math
import sys

# http://neerc.ifmo.ru/wiki/index.php?title=%D0%94%D0%B2%D0%BE%D0%B8%D1%87%D0%BD%D0%B0%D1%8F_%D0%BA%D1%83%D1%87%D0%B0
# https://habr.com/ru/post/112222/
class MaxHeap:
    def __init__(self):
        self.heap = []

    @property
    def last_idx(self):
        return len(self.heap) - 1

    def _swap(self, i, j):
        self.heap[i], self.heap[j] = self.heap[j], self.heap[i]

    def _parent(self, i: int) -> int:
        assert i >= 0
        return math.floor((i - 1) / 2)

    def _children(self, i: int) -> tuple:
        left, right = (2*i + 1, 2*i + 2)

        if left == self.last_idx:
            return (left, left)
        elif left > self.last_idx:
            return None

        return left, right

    def _shift_up(self, i):
        parent = self._parent(i)

        if (self.heap[i] > self.heap[parent]) and parent != -1:
            self._swap(i, parent)
            self._shift_up(parent)

    def _shift_down(self, i):
        if self._children(i):
            left, right = self._children(i)

            child = max(((self.heap[left], left), (self.heap[right], right)))
            if (self.heap[i] < child[0]):
                self._swap(i, child[1])
                self._shift_down(child[1])

    def push(self, item):
        self.heap.append(item)
        self._shift_up(self.last_idx)

    def pop(self):
        self._swap(0, self.last_idx)

        item = self.heap.pop()
        self._shift_down(0)

        return item

    def print(self, heap=None, i=0, d=0):
        if heap is None:
            heap = self.heap

        if i >= len(self.heap):
            return

        l, r = (2*i + 1, 2*i + 2)
        self.print(heap, r, d=d+1)
        print("   "*d + str(heap[i]))
        self.print(heap, l, d=d+1)

def main():
    heap = MaxHeap()

    instr = (op for op in sys.stdin)
    n = next(instr)

    for op in instr:
        if op.startswith("ExtractMax"):
            hmax = heap.pop()
            print(hmax)
        else:
            new = int(op.split()[1])
            print(f"INSERT {new}")
            heap.push(new)
        heap.print()
        print("-"*20)

def test():
    heap = MaxHeap()
    # heap.heap = [29, 19, 20, 5, 12, 10, 12, 3, 1, 9, 8, 6]
    # heap.heap = [200, 5, 10]

    # assert heap._parent(0) == -1
    # assert heap._parent(1) == 0
    # assert heap._parent(5) == 2
    # assert heap._parent(10) == 4

    # assert heap._children(0) == (1, 2)
    # assert heap._children(4) == (9, 10)
    # assert heap._children(3) == (7, 8)

    # heap.push(200)
    # heap.print()
    # print("-"*30)

    # heap.push(5)
    # heap.print()
    # print("-"*30)

    # heap.push(10)
    # heap.print()
    # print("-"*30)

    # heap.push(500)
    # heap.print()
    # print("-"*30)

    # heap.print()
    # print("-"*20)

    # heap.push(30)

    # heap.print()
    # print("-"*20)

    # hmax = heap.pop()
    # print("Max", hmax)
    # heap.print()
    # print("-"*20)

    # hmax = heap.pop()
    # print("Max", hmax)
    # heap.print()
    # print("-"*20)

    # hmax = heap.pop()
    # print("Max", hmax)
    # heap.print()

if __name__ == "__main__":
    main()
    # test()


# -*- coding: utf-8 -*-
"""
Created on Wed Sep 12 11:31:56 2018

@author: MSeidl
"""

# Import necessary libraries

BlockStart = int(input('enter the first Block to be scanned: '))
BlockEnd = int(input('enter the last Block to be scanned: '))

class ReturnValue(object):
    def __init__(self):
        self.BlockNumber = 0
        self.TransactionCount = 0
        self.GasUsed = 0
        self.Difficulty = 0
        self.GasLimit = 0
        self.Miner = 0
        self.Size = 0
        self.Timestamp = 0
        self.UncleCount = 0

import web3
import json
import datetime
import pandas as pd
import logging

from web3 import Web3, IPCProvider, HTTPProvider
from web3.middleware import geth_poa_middleware

# Logging, based on: https://docs.python.org/3/howto/logging-cookbook.html
logger = logging.getLogger("MarketLog")
logger.setLevel(logging.DEBUG)
fh = logging.FileHandler("Logs/" + datetime.datetime.now().isoformat().replace(":","_")[:19] + "_ChainLog.log")
fh.setLevel(logging.DEBUG)
ch = logging.StreamHandler()
ch.setLevel(logging.DEBUG) #change this later to Info
formatter = logging.Formatter('%(asctime)s - %(levelname)s - %(message)s')
fh.setFormatter(formatter)
ch.setFormatter(formatter)
logger.addHandler(fh)
logger.addHandler(ch)

fr = open('DA_address.txt')
DA_Address = fr.read().split('\n')[0]
fr.close()
fr = open('Register_address.txt')
R_Address = fr.read().split('\n')[0]
fr.close()
fr = open('web3_host.txt')
web3_host = fr.read().split('\n')[0]
fr.close()

fr = open('compiled_sol.json')
compiled_sol = fr.read()
fr.close()
compiled_sol = json.loads(compiled_sol)

# TO BE IMPLEMENTED (bei nächsten Markt Neustart wird GridFee auch mit abgespeichert)
#GF_Address = "0x1d27b6552BD56D88Db230CfEE98a7Db0C9Fa3614"

# Establishing Connection to Local Ganache Blockchain
web3 = Web3(HTTPProvider(web3_host))
web3.middleware_stack.inject(geth_poa_middleware, layer=0)

# Connect to existing Double Auction and GridFee contract
contract_interface = compiled_sol['<stdin>:' + 'DoubleAuction']
DA_Contract = web3.eth.contract(abi=contract_interface['abi'], bytecode=contract_interface['bin'])
DA_Contract = DA_Contract(DA_Address)

#contract_interface = compiled_sol['<stdin>:' + 'GridFee']
#GF_Contract = web3.eth.contract(abi=contract_interface['abi'], bytecode=contract_interface['bin'])
#GF_Contract = GF_Contract(GF_Address)

contract_interface = compiled_sol['<stdin>:' + 'Register']
R_Contract = web3.eth.contract(abi=contract_interface['abi'], bytecode=contract_interface['bin'])
R_Contract = R_Contract(R_Address)

columnNames = ['Blocknumber', 'TransactionCount', 'GasUsed', 'GasLimit', 'Difficulty', 'Miner', 'Size', 'TimeStamp', 'UncleCount']

#create csv file only with column headers
df = pd.DataFrame(columns=columnNames)
csv_name = "CSVs/" + datetime.datetime.now().isoformat().replace(":","_")[:19] + "_ChainListener.csv"
df.to_csv(csv_name, sep='\t', encoding='utf-8')
f = open(csv_name, 'a') # Open csv file in append mode

Output = []
Output.append(ReturnValue())

def fillCSV():
    for i in range (len(Output)):
        df = pd.DataFrame(columns=columnNames,index=range(1))
        df['Blocknumber'] = Output[i].BlockNumber
        df['TransactionCount'] = Output[i].TransactionCount
        df['GasUsed'] = Output[i].GasUsed
        df['GasLimit'] = Output[i].GasLimit
        df['Difficulty'] = Output[i].Difficulty
        df['Miner'] = Output[i].Miner
        df['Size'] = Output[i].Size
        df['TimeStamp'] = Output[i].Timestamp
        df['UncleCount'] = Output[i].UncleCount

        df.to_csv(f, header = False, encoding='utf-8',index=False)
        logger.info("in CSV BlockNumber: " + str(Output[i].BlockNumber))
    f.close()
try:
    counter = BlockStart
    counterIDs = 0
    while True:
        for i in range(counter,web3.eth.blockNumber+1):
            if i == BlockEnd:
                fillCSV()
                logger.info("DONE")
                exit()

            Output.append(ReturnValue())
            counterIDs += 1

            logger.info('BlockNumber: ' + str(i))

            block = web3.eth.getBlock(i)
            Output[counterIDs].BlockNumber = i
            Output[counterIDs].TransactionCount = web3.eth.getBlockTransactionCount(i)
            Output[counterIDs].GasUsed = block['gasUsed']
            Output[counterIDs].GasLimit = block['gasLimit']
            Output[counterIDs].Difficulty = block['difficulty']
            Output[counterIDs].Miner = block['miner']
            Output[counterIDs].Size = block['size']
            Output[counterIDs].Timestamp = block['timestamp']
            Output[counterIDs].UncleCount = len(block['uncles'])

        counter = i+1

except KeyboardInterrupt:
    fillCSV()
    logger.info("Ausführung erfolgreich beendet")
except Exception as e:
    logger.debug("unexpected error")
    logger.error("what happened here?", exc_info=True)
    fillCSV()