from datetime import datetime
from typing import List

from pandas import DataFrame
import pytest

from avionix import ChartBuilder, ChartInfo, ObjectMeta
from avionix.kube.base_objects import KubernetesBaseObject
from avionix.kube.core import (
    Affinity,
    Binding,
    Capabilities,
    ClientIPConfig,
    ConfigMap,
    ConfigMapEnvSource,
    ConfigMapKeySelector,
    ConfigMapNodeConfigSource,
    ConfigMapProjection,
    DownwardAPIProjection,
    DownwardAPIVolumeFile,
    EndpointAddress,
    Endpoints,
    EndpointSubset,
    EnvFromSource,
    EnvVar,
    EnvVarSource,
    Event,
    EventSeries,
    EventSource,
    ExecAction,
    Handler,
    HostAlias,
    HostPathVolumeSource,
    HTTPGetAction,
    HTTPHeader,
    KeyToPath,
    LabelSelector,
    Lifecycle,
    LimitRange,
    LimitRangeItem,
    LimitRangeSpec,
    LocalVolumeSource,
    Namespace,
    NamespaceSpec,
    Node,
    NodeAffinity,
    NodeConfigSource,
    NodeSelector,
    NodeSelectorRequirement,
    NodeSelectorTerm,
    NodeSpec,
    ObjectFieldSelector,
    PersistentVolume,
    PersistentVolumeClaim,
    PersistentVolumeClaimSpec,
    PersistentVolumeClaimVolumeSource,
    PersistentVolumeSpec,
    Pod,
    PodAffinity,
    PodAffinityTerm,
    PodAntiAffinity,
    PodDNSConfig,
    PodDNSConfigOption,
    PodSecurityContext,
    PodTemplate,
    PreferredSchedulingTerm,
    Probe,
    ProjectedVolumeSource,
    ReplicationController,
    ReplicationControllerSpec,
    ResourceFieldSelector,
    ResourceQuota,
    ResourceQuotaSpec,
    ResourceRequirements,
    ScopedResourceSelectorRequirement,
    ScopeSelector,
    Secret,
    SecretEnvSource,
    SecretKeySelector,
    SecretProjection,
    SecurityContext,
    SELinuxOptions,
    Service,
    ServiceAccount,
    ServicePort,
    ServiceSpec,
    SessionAffinityConfig,
    Sysctl,
    Taint,
    TCPSocketAction,
    TopologySpreadConstraint,
    Volume,
    VolumeMount,
    VolumeNodeAffinity,
    VolumeProjection,
    WeightedPodAffinityTerm,
    WindowsSecurityContextOptions,
)
from avionix.kube.meta import LabelSelectorRequirement
from avionix.kube.reference import ObjectReference
from avionix.testing import kubectl_get
from avionix.testing.installation_context import ChartInstallationContext
from avionix.tests.utils import get_event_info, get_pod_with_options

def test_config_map(chart_info: ChartInfo, config_map: ConfigMap):
    builder = ChartBuilder(chart_info, [config_map])
    with ChartInstallationContext(builder):
        config_maps = kubectl_get("configmaps")
        assert config_maps["NAME"][0] == "test-config-map"
        assert config_maps["DATA"][0] == "1"

@pytest.fixture
def endpoints_metadata():
    return ObjectMeta(name="test-endpoints")

@pytest.fixture
def endpoints_no_subset(endpoints_metadata):
    return Endpoints(endpoints_metadata)

@pytest.fixture()
def endpoints_with_subset(endpoints_metadata):
    return Endpoints(
        endpoints_metadata,
        subsets=[
            EndpointSubset(
                addresses=[EndpointAddress("local", "10.9.8.7", None)],
                not_ready_addresses=None,
                ports=None,
            )
        ],
    )

def get_endpoints_info():
    info = DataFrame(kubectl_get("endpoints"))
    return info[info["NAME"] != "kubernetes"].reset_index(drop=True)

def test_endpoints_no_subset(chart_info: ChartInfo, endpoints_no_subset: Endpoints):
    builder = ChartBuilder(chart_info, [endpoints_no_subset])
    with ChartInstallationContext(builder):
        endpoints_info = get_endpoints_info()
        assert endpoints_info["NAME"][0] == "test-endpoints"
        assert endpoints_info["ENDPOINTS"][0] == "<none>"

def test_endpoints_with_subset(chart_info: ChartInfo, endpoints_with_subset: Endpoints):
    builder = ChartBuilder(chart_info, [endpoints_with_subset])
    with ChartInstallationContext(builder):
        endpoints_info = get_endpoints_info()
        assert endpoints_info["NAME"][0] == "test-endpoints"
        assert endpoints_info["ENDPOINTS"][0] == "10.9.8.7"

@pytest.mark.parametrize(
    "event",
    [
        Event(
            ObjectMeta(name="test-event"),
            ObjectReference("test-pod", name="test-ref"),
            message="test message",
            reason="testing",
            type="test-type",
        ),
        Event(
            ObjectMeta(name="test-event"), ObjectReference("test-pod", name="test-ref"),
        ),
        Event(
            ObjectMeta(name="test-event"),
            ObjectReference("test-pod", name="test-ref"),
            series=EventSeries(1),
        ),
        Event(
            ObjectMeta(name="test-event"),
            ObjectReference("test-pod", name="test-ref"),
            source=EventSource("test"),
        ),
        Event(
            ObjectMeta(name="test-event"),
            ObjectReference("test-pod", name="test-ref"),
            source=EventSource(host="test"),
        ),
        Event(
            ObjectMeta(name="test-event"),
            ObjectReference("test-pod", name="test-ref"),
            series=EventSeries(last_observed_time=datetime.now()),
        ),
        Event(
            ObjectMeta(name="test-event"),
            ObjectReference("test-pod", name="test-ref", namespace="default"),
            event_time=datetime.now(),
            first_timestamp=datetime.now(),
            last_timestamp=datetime.now(),
            reporting_instance="test",
            reporting_component="test",
            action="test",
            reason="testing",
        ),
    ],
)
def test_event(chart_info: ChartInfo, event: Event):
    builder = ChartBuilder(chart_info, [event])
    with ChartInstallationContext(builder):
        event_info = get_event_info()
        assert event_info["TYPE"][0] == (event.type if event.type is not None else "")
        assert event_info["REASON"][0] == (
            event.reason if event.reason is not None else ""
        )
        assert event_info["OBJECT"][0] == f"objectreference/{event.involvedObject.name}"
        assert event_info["MESSAGE"][0] == (
            event.message if event.message is not None else ""
        )

@pytest.fixture
def limit_range():
    return LimitRange(
        ObjectMeta(name="test-range"),
        LimitRangeSpec(limits=[LimitRangeItem({}, {}, {}, {})]),
    )

def test_create_limitrange(chart_info, limit_range):
    builder = ChartBuilder(chart_info, [limit_range])
    with ChartInstallationContext(builder):
        namespace_info = kubectl_get("limitranges")
        assert namespace_info["NAME"][0] == "test-range"

@pytest.mark.parametrize(
    "namespace",
    [
        Namespace(ObjectMeta(name="test-namespace")),
        Namespace(
            ObjectMeta(name="test-namespace-finalizers"), NamespaceSpec(["kubernetes"])
        ),
    ],
)
def test_namespace(chart_info, namespace: Namespace):
    builder = ChartBuilder(chart_info, [namespace])
    with ChartInstallationContext(builder):
        namespace_info = kubectl_get("namespaces")
        assert "test-namespace" in namespace_info["NAME"]

def get_node_info():
    node_info = DataFrame(kubectl_get("nodes"))
    return node_info[node_info["NAME"] != "minikube"].reset_index(drop=True)

class NodeInstallationContext(ChartInstallationContext):
    def wait_for_uninstall(self):
        pass

@pytest.mark.parametrize(
    "node",
    [
        Node(
            ObjectMeta(name="test-node"),
            NodeSpec(external_id="12345", pod_cidr="10.0.0.0/24"),
        ),
        Node(
            ObjectMeta(name="test-node"),
            NodeSpec(
                external_id="12345",
                pod_cidr="10.0.0.0/24",
                config_source=NodeConfigSource(
                    ConfigMapNodeConfigSource("test", "test", "default")
                ),
            ),
        ),
        Node(
            ObjectMeta(name="test-node"),
            NodeSpec(
                external_id="12345",
                pod_cidr="10.0.0.0/24",
                taints=[Taint("NoSchedule", "test")],
            ),
        ),
        Node(
            ObjectMeta(name="test-node"),
            NodeSpec(
                external_id="12345",
                pod_cidr="10.0.0.0/24",
                taints=[Taint("NoSchedule", "test", datetime.now())],
            ),
        ),
    ],
)
def test_node(chart_info, node: Node):
    builder = ChartBuilder(chart_info, [node])
    with NodeInstallationContext(
        builder,
        status_resource="node",
        expected_status={"Ready", "Unknown", "NotReady"},
    ):
        node_info = get_node_info()
        assert node_info["NAME"][0] == node.metadata.name
        assert node_info["STATUS"][0] in {"NotReady", "Unknown"}
        assert node_info["VERSION"][0] == ""

modes_expected_value = "RWX"

@pytest.fixture
def persistent_volume_spec():
    """
    A generic persistent volume spec
    """
    return PersistentVolumeSpec(
        ["ReadWriteMany"],
        capacity={"storage": 1},
        host_path=HostPathVolumeSource("/home/test/tmp"),
        storage_class_name="standard",
    )

@pytest.fixture
def persistent_volume(persistent_volume_spec):
    """
    A generic persistent volume
    """
    return PersistentVolume(
        ObjectMeta(name="test-persistent-volume"), persistent_volume_spec,
    )

@pytest.mark.parametrize(
    "persistent_volume_spec",
    [
        PersistentVolumeSpec(
            ["ReadWriteMany"],
            capacity={"storage": 1},
            host_path=HostPathVolumeSource("/home/test/tmp"),
            storage_class_name="standard",
        ),
        PersistentVolumeSpec(
            ["ReadWriteMany"],
            capacity={"storage": 1},
            storage_class_name="standard",
            local=LocalVolumeSource("test", "/usr/tmp"),
            node_affinity=VolumeNodeAffinity(
                NodeSelector(
                    [
                        NodeSelectorTerm(
                            match_expressions=[
                                NodeSelectorRequirement(
                                    "kubernetes.io/os", "In", ["linux"]
                                )
                            ]
                        )
                    ]
                )
            ),
        ),
    ],
)
def test_persistent_volume(chart_info, persistent_volume_spec):
    persistent_volume = PersistentVolume(
        ObjectMeta(name="test-persistent-volume"), persistent_volume_spec
    )
    builder = ChartBuilder(chart_info, [persistent_volume],)
    with ChartInstallationContext(builder):
        volume_info = kubectl_get("persistentvolumes")
        assert volume_info["NAME"][0] == persistent_volume.metadata.name
        assert persistent_volume.spec.capacity is not None
        assert volume_info["CAPACITY"][0] == str(
            persistent_volume.spec.capacity["storage"]
        )
        assert volume_info["ACCESS MODES"][0] == modes_expected_value

@pytest.fixture
def empty_persistent_volume_claim(access_modes):
    return PersistentVolumeClaim(
        ObjectMeta(name="test-persistent-volume-claim"),
        PersistentVolumeClaimSpec(
            access_modes, ResourceRequirements(requests={"storage": 1}),
        ),
    )

def test_empty_persistent_volume_claim(chart_info, empty_persistent_volume_claim):
    builder = ChartBuilder(chart_info, [empty_persistent_volume_claim])
    with ChartInstallationContext(builder):
        volume_info = kubectl_get("persistentvolumeclaims")
        assert volume_info["NAME"][0] == "test-persistent-volume-claim"
        assert volume_info["CAPACITY"][0] == "1"
        assert volume_info["ACCESS MODES"][0] == modes_expected_value

@pytest.fixture
def pod_template(pod_template_spec):
    return PodTemplate(ObjectMeta(name="test-pod-template"), pod_template_spec)

def test_create_pod_template(chart_info: ChartInfo, pod_template: PodTemplate):
    builder = ChartBuilder(chart_info, [pod_template])
    with ChartInstallationContext(builder):
        template_info = kubectl_get("podtemplates")
        assert template_info["NAME"][0] == "test-pod-template"
        assert template_info["CONTAINERS"][0] == "test-container-0"
        assert template_info["IMAGES"][0] == "k8s.gcr.io/echoserver:1.4"

@pytest.fixture
def replication_controller(pod_template_spec):
    return ReplicationController(
        ObjectMeta(name="test-replication-controller"),
        spec=ReplicationControllerSpec(pod_template_spec, selector={"type": "master"}),
    )

def test_replication_controller(chart_info, replication_controller):
    builder = ChartBuilder(chart_info, [replication_controller])
    with ChartInstallationContext(builder):
        replication_info = kubectl_get("replicationcontrollers")
        assert replication_info["NAME"][0] == "test-replication-controller"
        assert replication_info["DESIRED"][0] == "1"
        assert replication_info["CURRENT"][0] == "1"

@pytest.mark.parametrize(
    "resource_quota",
    [
        ResourceQuota(
            ObjectMeta(name="test-resource-quota"),
            spec=ResourceQuotaSpec(hard={"cpu": 1}),
        ),
        ResourceQuota(
            ObjectMeta(name="test-resource-quota-w-scope"),
            spec=ResourceQuotaSpec(
                hard={"cpu": 1},
                scope_selector=ScopeSelector(
                    [ScopedResourceSelectorRequirement("DoesNotExist", "PriorityClass")]
                ),
            ),
        ),
    ],
)
def test_resource_quota(chart_info, resource_quota):
    builder = ChartBuilder(chart_info, [resource_quota])
    with ChartInstallationContext(builder):
        quota_info = kubectl_get("resourcequotas")
        assert quota_info["NAME"][0] == resource_quota.metadata.name
        assert quota_info["REQUEST"][0] == "cpu: 0/1"

def get_secret_info():
    info = DataFrame(kubectl_get("secrets"))
    return info[info["NAME"] == "test-secret"].reset_index(drop=True)

@pytest.mark.parametrize("secret_data", [{"secret_key": "test"}, None, {}])
def test_secret(chart_info, secret_data: dict):
    builder = ChartBuilder(
        chart_info, [Secret(ObjectMeta(name="test-secret"), secret_data)]
    )
    with ChartInstallationContext(builder):
        secret_info = get_secret_info()
        assert secret_info["NAME"][0] == "test-secret"
        assert secret_info["DATA"][0] == str(len(secret_data)) if secret_data else "0"

def get_service_info():
    info = DataFrame(kubectl_get("services"))
    return info[info["NAME"] != "kubernetes"].reset_index(drop=True)

@pytest.mark.parametrize(
    "service_spec",
    [
        ServiceSpec([ServicePort(80)]),
        ServiceSpec(
            [
                ServicePort(80, name="port1"),
                ServicePort(8080, protocol="UDP", name="port2"),
            ],
            external_ips=["152.0.0.0"],
        ),
        ServiceSpec(
            [ServicePort(80)],
            session_affinity_config=SessionAffinityConfig(ClientIPConfig(10)),
        ),
    ],
)
def test_service(chart_info, service_spec: ServiceSpec):
    builder = ChartBuilder(
        chart_info, [Service(ObjectMeta(name="test-service"), service_spec)]
    )
    with ChartInstallationContext(builder):
        service_info = get_service_info()
        assert service_info["NAME"][0] == "test-service"
        assert service_info["PORT(S)"][0] == ",".join(
            [
                f"{port.port}/{port.protocol if port.protocol else 'TCP'}"
                for port in service_spec.ports
            ]
        )
        assert service_info["EXTERNAL-IP"][0] == (
            service_spec.externalIPs[0] if service_spec.externalIPs else "<none>"
        )

@pytest.fixture
def nonempty_service_account():
    return ServiceAccount(
        ObjectMeta(name="test-service-account"),
        secrets=[ObjectReference("test", name="test-ref")],
    )

def get_service_account_info():
    info = DataFrame(kubectl_get("serviceaccounts"))
    return info[info["NAME"] != "default"].reset_index(drop=True)

def test_empty_service_account(chart_info, empty_service_account):
    builder = ChartBuilder(chart_info, [empty_service_account])
    with ChartInstallationContext(builder):
        service_account_info = get_service_account_info()
        assert service_account_info["NAME"][0] == "test-service-account"

def test_nonempty_service_account(chart_info, nonempty_service_account):
    builder = ChartBuilder(chart_info, [nonempty_service_account])
    with ChartInstallationContext(builder):
        service_account_info = get_service_account_info()
        assert service_account_info["NAME"][0] == "test-service-account"
        assert service_account_info["SECRETS"][0] == "2"

@pytest.fixture
def binding():
    binding = Binding(
        metadata=ObjectMeta(name="test-pod"),
        target=ObjectReference("test", name="test_object", namespace="test"),
    )
    return binding

@pytest.mark.skip(reason="Still need to figure out this test")
def test_create_binding(chart_info: ChartInfo, binding: Binding, pod: Pod):
    builder = ChartBuilder(chart_info, [binding, pod])
    with ChartInstallationContext(builder):
        kubectl_get("bindings")

@pytest.fixture
def persistent_volume_claim(persistent_volume):
    """
    A generic persistent volume claim
    """
    return PersistentVolumeClaim(
        ObjectMeta(name="test-pv-claim"),
        PersistentVolumeClaimSpec(
            persistent_volume.spec.accessModes,
            resources=ResourceRequirements(
                requests={"storage": persistent_volume.spec.capacity["storage"]}
            ),
        ),
    )

@pytest.mark.parametrize(
    "mounts_or_devices",
    [
        {"volume_mount": VolumeMount("test-volume", "~/tmp")},
        # {"volume_device": VolumeDevice("test-volume", "~/tmp")},
    ],
)
def test_persistent_volume_on_pod(
    chart_info, persistent_volume, persistent_volume_claim, mounts_or_devices: dict
):
    builder = ChartBuilder(
        chart_info,
        [
            persistent_volume,
            get_pod_with_options(
                Volume(
                    "test-volume",
                    persistent_volume_claim=PersistentVolumeClaimVolumeSource(
                        persistent_volume_claim.metadata.name, read_only=True
                    ),
                ),
                # command=["bash", "-c", "mkdir ~/tmp; nginx -g 'daemon off;'"],
                **mounts_or_devices,
            ),
            persistent_volume_claim,
        ],
    )
    with ChartInstallationContext(builder):
        # Check pod ready
        pod_info = kubectl_get("pods", wide=True)
        assert pod_info["NAME"][0] == "test-pod"
        assert pod_info["READY"][0] == "1/1"

        # Check volume bound
        volume_info = kubectl_get("persistentvolume")
        assert volume_info["NAME"][0] == "test-persistent-volume"
        assert volume_info["CAPACITY"][0] == "1"
        assert volume_info["ACCESS MODES"][0] == "RWX"
        assert volume_info["RECLAIM POLICY"][0] == "Retain"
        assert volume_info["STATUS"][0] == "Bound"
        assert volume_info["CLAIM"][0] == "default/test-pv-claim"

        claim_info = kubectl_get("persistentvolumeclaims")
        assert claim_info["NAME"][0] == "test-pv-claim"
        assert claim_info["STATUS"][0] == "Bound"
        assert claim_info["CAPACITY"][0] == "1"
        assert claim_info["ACCESS MODES"][0] == "RWX"

@pytest.mark.parametrize(
    "volume",
    [
        Volume(
            name="config-map-projection",
            projected=ProjectedVolumeSource(
                [
                    VolumeProjection(
                        ConfigMapProjection(
                            "test", True, items=[KeyToPath("test", "tmp/")]
                        ),
                    )
                ],
            ),
        ),
        Volume(
            name="project-downward-api",
            projected=ProjectedVolumeSource(
                [
                    VolumeProjection(
                        downward_api=DownwardAPIProjection(
                            [
                                DownwardAPIVolumeFile(
                                    "labels", ObjectFieldSelector("metadata.labels")
                                )
                            ]
                        )
                    )
                ]
            ),
        ),
        Volume(
            name="project-secret",
            projected=ProjectedVolumeSource(
                [VolumeProjection(secret=SecretProjection("my-secret", True))]
            ),
        ),
        # Volume(
        #     name="project-service-account-token",
        #     projected=ProjectedVolumeSource(
        #         [VolumeProjection(
        #             service_account_token=ServiceAccountTokenProjection("vault-token"))]
        #     )
        # )
    ],
)
def test_projected_volumes(chart_info, volume: Volume):
    builder = ChartBuilder(chart_info, [get_pod_with_options(volume)])
    with ChartInstallationContext(builder):
        pod_info = kubectl_get("pods", wide=True)
        assert pod_info["NAME"][0] == "test-pod"
        assert pod_info["READY"][0] == "1/1"

@pytest.mark.parametrize(
    "pod,other_resources",
    [
        (get_pod_with_options(), None),
        (
            get_pod_with_options(
                name="pod-security-1", pod_security_context=PodSecurityContext(10000)
            ),
            None,
        ),
        (
            get_pod_with_options(
                name="pod-security-2",
                pod_security_context=PodSecurityContext(
                    sysctls=[Sysctl("kernel.shm_rmid_forced", "0")]
                ),
            ),
            None,
        ),
        (
            get_pod_with_options(
                name="env-var-config-map",
                environment_var=EnvVar(
                    "from_config_map",
                    value_from=EnvVarSource(ConfigMapKeySelector("config-map", "key")),
                ),
            ),
            [ConfigMap(ObjectMeta(name="config-map"), {"key": "value"})],
        ),
        (
            get_pod_with_options(
                name="env-var-objectfield",
                environment_var=EnvVar(
                    "from_field_selector",
                    value_from=EnvVarSource(
                        field_ref=ObjectFieldSelector("metadata.name")
                    ),
                ),
            ),
            None,
        ),
        (
            get_pod_with_options(
                name="env-var-resource",
                environment_var=EnvVar(
                    "from_resource_field_selector",
                    value_from=EnvVarSource(
                        resource_field_ref=ResourceFieldSelector(
                            "test-container-0", "requests.memory"
                        )
                    ),
                ),
            ),
            None,
        ),
        (
            get_pod_with_options(
                name="env-var-secret-key",
                environment_var=EnvVar(
                    "from_resource_field_selector",
                    value_from=EnvVarSource(
                        secret_key_ref=SecretKeySelector("test-secret", "secret_key")
                    ),
                ),
            ),
            [Secret(ObjectMeta(name="test-secret"), {"secret_key": "test"})],
        ),
        (
            get_pod_with_options(
                name="secuirty-context-all",
                container_security_context=SecurityContext(
                    capabilities=Capabilities(["ALL"])
                ),
            ),
            None,
        ),
        (
            get_pod_with_options(
                name="security-context-drop",
                container_security_context=SecurityContext(
                    capabilities=Capabilities(drop=["NET_BIND_SERVICE"])
                ),
            ),
            None,
        ),
        (
            get_pod_with_options(
                name="security-context-linux",
                container_security_context=SecurityContext(
                    se_linux_options=SELinuxOptions(level="2")
                ),
            ),
            None,
        ),
        (
            get_pod_with_options(
                name="lifecyle-pre-stop",
                lifecycle=Lifecycle(pre_stop=Handler(tcp_socket=TCPSocketAction(8080))),
            ),
            None,
        ),
        (
            get_pod_with_options(
                name="lifecyle-post-start",
                lifecycle=Lifecycle(post_start=Handler(ExecAction(["echo", "yes"]))),
            ),
            None,
        ),
        (
            get_pod_with_options(
                name="lifecycle-http-int",
                lifecycle=Lifecycle(
                    post_start=Handler(http_get=HTTPGetAction("/my/path", 8080))
                ),
            ),
            None,
        ),
        (
            get_pod_with_options(
                name="lifecycle-http-name",
                lifecycle=Lifecycle(
                    post_start=Handler(http_get=HTTPGetAction("/my/path", "port"))
                ),
            ),
            None,
        ),
        (
            get_pod_with_options(
                name="host-alias", host_alias=HostAlias(["test.com"], "129.0.0.0")
            ),
            None,
        ),
        (
            get_pod_with_options(
                name="security-context-windows",
                container_security_context=SecurityContext(
                    windows_options=WindowsSecurityContextOptions("test", "test")
                ),
            ),
            None,
        ),
        (
            get_pod_with_options(
                name="env-from",
                env_from=[
                    EnvFromSource(ConfigMapEnvSource("config-map")),
                    EnvFromSource(secret_ref=SecretEnvSource("test-secret")),
                ],
            ),
            [
                ConfigMap(ObjectMeta(name="config-map"), {"key": "value"}),
                Secret(ObjectMeta(name="test-secret"), {"secret_key": "test"}),
            ],
        ),
        (
            get_pod_with_options(
                name="topology-spread",
                topology_spread=TopologySpreadConstraint(1, "t", "ScheduleAnyway"),
            ),
            None,
        ),
        (
            get_pod_with_options(
                name="dns-config-option",
                dns_config=PodDNSConfig(options=[PodDNSConfigOption("test")]),
            ),
            None,
        ),
        (
            get_pod_with_options(
                name="dns-config-no-option", dns_config=PodDNSConfig(["1.1.1.1"])
            ),
            None,
        ),
        (get_pod_with_options(name="epehemeral", ephemeral=True), None),
        (
            get_pod_with_options(
                name="required-node-affinity",
                affinity=Affinity(
                    node_affinity=NodeAffinity(
                        required_during_scheduling_ignored_during_execution=NodeSelector(
                            [
                                NodeSelectorTerm(
                                    match_expressions=[
                                        NodeSelectorRequirement(
                                            "kubernetes.io/os", "Exists"
                                        )
                                    ]
                                )
                            ]
                        )
                    )
                ),
            ),
            None,
        ),
        (
            get_pod_with_options(
                name="node-affinity",
                affinity=Affinity(
                    node_affinity=NodeAffinity(
                        [
                            PreferredSchedulingTerm(
                                NodeSelectorTerm(
                                    match_fields=[
                                        NodeSelectorRequirement(
                                            "metadata.name", "In", ["minikube"]
                                        ),
                                    ]
                                ),
                                weight=2,
                            ),
                            PreferredSchedulingTerm(
                                NodeSelectorTerm(
                                    match_expressions=[
                                        NodeSelectorRequirement("test", "Exists")
                                    ],
                                ),
                                weight=1,
                            ),
                        ],
                    )
                ),
            ),
            None,
        ),
        (
            get_pod_with_options(
                name="pod-affinity",
                affinity=Affinity(
                    PodAffinity(
                        [
                            WeightedPodAffinityTerm(
                                PodAffinityTerm(
                                    "minikube.k8s.io/name", namespaces=["default"],
                                ),
                                weight=10,
                            ),
                            WeightedPodAffinityTerm(
                                PodAffinityTerm(topology_key="minikube.k8s.io/name"),
                                weight=3,
                            ),
                        ],
                    ),
                ),
            ),
            None,
        ),
        (
            get_pod_with_options(
                name="required-pod-affinity",
                affinity=Affinity(
                    PodAffinity(
                        required_during_scheduling_ignored_during_execution=[
                            PodAffinityTerm(
                                "kubernetes.io/arch",
                                LabelSelector(
                                    match_expressions=[
                                        LabelSelectorRequirement(
                                            "app.kubernetes.io/managed-by", "Exists",
                                        )
                                    ],
                                ),
                            ),
                        ]
                    ),
                ),
            ),
            [get_pod_with_options(name="affinity-pod")],
        ),
        (
            get_pod_with_options(
                name="anti-affinity",
                affinity=Affinity(
                    pod_anti_affinity=PodAntiAffinity(
                        [
                            WeightedPodAffinityTerm(
                                PodAffinityTerm("T", namespaces=["default"]), weight=2
                            )
                        ],
                    ),
                ),
            ),
            None,
        ),
        (
            get_pod_with_options(
                name="required-anti-affinity",
                affinity=Affinity(
                    pod_anti_affinity=PodAntiAffinity(
                        required_during_scheduling_ignored_during_execution=[
                            PodAffinityTerm(topology_key="t")
                        ],
                    ),
                ),
            ),
            None,
        ),
    ],
)
def test_pod(chart_info, pod: Pod, other_resources: List[KubernetesBaseObject]):
    if other_resources is None:
        other_resources = []
    builder = ChartBuilder(chart_info, other_resources + [pod])
    with ChartInstallationContext(builder):
        pod_info = DataFrame(kubectl_get("pods"))
        pod_info = pod_info[pod_info["NAME"] == pod.metadata.name].reset_index(
            drop=True
        )
        assert pod_info["NAME"][0] == pod.metadata.name
        assert pod_info["READY"][0] == "1/1"
        assert pod_info["STATUS"][0] == "Running"

@pytest.mark.parametrize(
    "probe",
    [
        Probe(
            http_get=HTTPGetAction("/", 8080, [HTTPHeader("GET", "yes")]),
            period_seconds=1,
            failure_threshold=10,
        ),
        Probe(
            http_get=HTTPGetAction("/", 8080), period_seconds=1, failure_threshold=10
        ),
        Probe(
            exec=ExecAction(["echo", "good"]), period_seconds=1, failure_threshold=10
        ),
        Probe(tcp_socket=TCPSocketAction(8080), period_seconds=1, failure_threshold=10),
    ],
)
def test_container_probes(chart_info, probe: Probe):
    pod = get_pod_with_options(readiness_probe=probe)
    builder = ChartBuilder(chart_info, [pod])
    with ChartInstallationContext(
        builder, expected_status={"1/1"}, status_field="READY"
    ):
        pod_info = kubectl_get("pods")
        assert pod_info["NAME"][0] == "test-pod"
        assert pod_info["READY"][0] == "1/1"
        assert pod_info["STATUS"][0] == "Running"


import json
from dataclasses import dataclass
from typing import Any, List

from dataclasses_json import DataClassJsonMixin

from llama_index.output_parsers.base import OutputParserException, StructuredOutput
from llama_index.output_parsers.utils import _marshal_llm_to_json
from llama_index.types import BaseOutputParser

def _escape_curly_braces(input_string: str) -> str:
    # Replace '{' with '{{' and '}' with '}}' to escape curly braces
    return input_string.replace("{", "{{").replace("}", "}}")

FORMAT_STR = """The output should be ONLY JSON formatted as a JSON instance.

Here is an example:
[
    {
        choice: 1,
        reason: "<insert reason for choice>"
    },
    ...
]
"""

@dataclass
class Answer(DataClassJsonMixin):
    choice: int
    reason: str

class SelectionOutputParser(BaseOutputParser):
    REQUIRED_KEYS = frozenset(Answer.__annotations__)

    def _filter_dict(self, json_dict: dict) -> dict:
        """Filter recursively until a dictionary matches all REQUIRED_KEYS."""
        output_dict = json_dict
        for key, val in json_dict.items():
            if key in self.REQUIRED_KEYS:
                continue
            elif isinstance(val, dict):
                output_dict = self._filter_dict(val)
            elif isinstance(val, list):
                for item in val:
                    if isinstance(item, dict):
                        output_dict = self._filter_dict(item)

        return output_dict

    def _format_output(self, output: List[dict]) -> List[dict]:
        output_json = []
        for json_dict in output:
            valid = True
            for key in self.REQUIRED_KEYS:
                if key not in json_dict:
                    valid = False
                    break

            if not valid:
                json_dict = self._filter_dict(json_dict)

            output_json.append(json_dict)

        return output_json

    def parse(self, output: str) -> Any:
        json_string = _marshal_llm_to_json(output)
        try:
            json_obj = json.loads(json_string)
        except json.JSONDecodeError as e_json:
            try:
                import yaml

                # NOTE: parsing again with pyyaml
                #       pyyaml is less strict, and allows for trailing commas
                #       right now we rely on this since guidance program generates
                #       trailing commas
                json_obj = yaml.safe_load(json_string)
            except yaml.YAMLError as e_yaml:
                raise OutputParserException(
                    f"Got invalid JSON object. Error: {e_json} {e_yaml}. "
                    f"Got JSON string: {json_string}"
                )
            except NameError as exc:
                raise ImportError("Please pip install PyYAML.") from exc

        if isinstance(json_obj, dict):
            json_obj = [json_obj]

        if not json_obj:
            raise ValueError(f"Failed to convert output to JSON: {output!r}")

        json_output = self._format_output(json_obj)
        answers = [Answer.from_dict(json_dict) for json_dict in json_output]
        return StructuredOutput(raw_output=output, parsed_output=answers)

    def format(self, prompt_template: str) -> str:
        return prompt_template + "\n\n" + _escape_curly_braces(FORMAT_STR)


from dataclasses import dataclass, field
from typing import Optional
from ojp.capabilities_response import CapabilitiesResponse
from ojp.check_status_response import CheckStatusResponse
from ojp.data_ready_acknowledgement import DataReadyAcknowledgement
from ojp.data_received_acknowledgement import DataReceivedAcknowledgement
from ojp.service_delivery import ServiceDelivery
from ojp.subscription_response import SubscriptionResponse
from ojp.terminate_subscription_response import TerminateSubscriptionResponse

__NAMESPACE__ = "http://www.siri.org.uk/siri"

@dataclass
class OjpresponseStructure:
    """Type for OJP Response - Groups individual functional responses.

    :ivar subscription_response:
    :ivar terminate_subscription_response:
    :ivar data_ready_acknowledgement:
    :ivar service_delivery:
    :ivar data_received_acknowledgement:
    :ivar check_status_response:
    :ivar capabilities_response: Responses with the capabilities of an
        implementation. Answers a CapabilityRequest.
    """
    class Meta:
        name = "OJPResponseStructure"

    subscription_response: Optional[SubscriptionResponse] = field(
        default=None,
        metadata={
            "name": "SubscriptionResponse",
            "type": "Element",
            "namespace": "http://www.siri.org.uk/siri",
        }
    )
    terminate_subscription_response: Optional[TerminateSubscriptionResponse] = field(
        default=None,
        metadata={
            "name": "TerminateSubscriptionResponse",
            "type": "Element",
            "namespace": "http://www.siri.org.uk/siri",
        }
    )
    data_ready_acknowledgement: Optional[DataReadyAcknowledgement] = field(
        default=None,
        metadata={
            "name": "DataReadyAcknowledgement",
            "type": "Element",
            "namespace": "http://www.siri.org.uk/siri",
        }
    )
    service_delivery: Optional[ServiceDelivery] = field(
        default=None,
        metadata={
            "name": "ServiceDelivery",
            "type": "Element",
            "namespace": "http://www.siri.org.uk/siri",
        }
    )
    data_received_acknowledgement: Optional[DataReceivedAcknowledgement] = field(
        default=None,
        metadata={
            "name": "DataReceivedAcknowledgement",
            "type": "Element",
            "namespace": "http://www.siri.org.uk/siri",
        }
    )
    check_status_response: Optional[CheckStatusResponse] = field(
        default=None,
        metadata={
            "name": "CheckStatusResponse",
            "type": "Element",
            "namespace": "http://www.siri.org.uk/siri",
        }
    )
    capabilities_response: Optional[CapabilitiesResponse] = field(
        default=None,
        metadata={
            "name": "CapabilitiesResponse",
            "type": "Element",
            "namespace": "http://www.siri.org.uk/siri",
        }
    )


#!/usr/bin/env python3

import os
import tensorflow as tf
import numpy as np
from Bio import SeqIO
from Utility import run
import re
from Utility import append_time_ram_stamp_to_file
from itertools import product
import time

def convert_data_one_hot_with_Ns_spread_str_to_numbers(seqs) -> list[list[float]]:
    return list(map(lambda l: [[float(x) for x in i.split("_")] for i in l], seqs))

def read_data_one_hot_with_Ns_spread_str(config, add_one_terminal_symbol = False) -> list[list[str]]:
    '''
    bc i can only pad batches with scalar, i have multi hot encoded strings for every base
    and pad with str that encodes terminal emission
    then i can convert these a string corresponding to a base to its multi hot encoded version
    '''
    start = time.perf_counter()
    append_time_ram_stamp_to_file(f"read_data_one_hot_with_Ns_spread_str() start ", config.bench_path, start)
    seqs = []
    base_to_id_dict = dict([(base, id) for id, base in enumerate("ACGTI")])
    def base_to_id(b):
        b = b.upper()
        try:
            return base_to_id_dict[b]
        except:
            return 5

    with open(config.fasta_path,"r") as handle:
        if config.only_primates or config.only_diverse:
            with open(config.primates_path, "r") as primates_handle:
                primates = set()
                # this file is just a list of ids of primates
                for line in primates_handle:
                    primates.add(line.strip())

            # a list containing the ids of the species that should be used as input
            species_to_use = []
            species_in_combinded_fasta = set()
            number_of_primats_in_current_fasta = 0

            for record in SeqIO.parse(handle,"fasta"):
                species_name = re.search("(\w+?_\w+?)\.", record.id).group(1)
                species_in_combinded_fasta.add(species_name)
                if species_name in primates:
                    number_of_primats_in_current_fasta += 1
                    if config.only_primates:
                        species_to_use.append(species_name)
            # print("number_of_primats_in_current_fasta", number_of_primats_in_current_fasta)

        if config.only_diverse and config.only_diverse:
            # list all files in a dir whos path is stored in config.only_diverse
            all_files = []
            for file in os.listdir(config.diverse_trees_path):
                if file.endswith(".txt"):
                    all_files.append(os.path.join(config.diverse_trees_path, file))
            all_files = sorted(all_files)
            print(all_files)
            for file in all_files:
                species_in_file = set()
                with open(file, "r") as file_handle:
                    for line in file_handle:
                        species_in_file.add(line.strip())
                # find the size of the overlap of the set species_in_combinded_fasta and species_in_file
                overlap = species_in_combinded_fasta.intersection(species_in_file)
                print("species_in_combinded_fasta", len(species_in_combinded_fasta))
                print("species_in_file", len(species_in_file))
                if len(overlap) == number_of_primats_in_current_fasta:
                    overlap.add("Homo_sapiens")
                    species_to_use = list(overlap)
                    break

    with open(config.fasta_path,"r") as handle:
        for record in SeqIO.parse(handle,"fasta"):
            if config.only_primates or config.only_diverse:
                # print("using species:", species_to_use)
                species_name = re.search("(\w+?_\w+?)\.", record.id).group(1)
                # print("species_to_use", species_to_use)
                # print("species_name", species_name)
                if species_name not in species_to_use:
                    continue

            if config.only_human:
                species_name = re.search("(\w+?_\w+?)\.", record.id).group(1)
                # print("species_to_use", species_to_use)
                # print("species_name", species_name)
                if not re.search("Homo_sap",species_name):
                    continue

            seq = record.seq
            seq_of_one_hot = []
            last_bases = [4] * config.order # 4 is padded left flank by place holder symbol
            for i, base in enumerate(seq):
                t = (last_bases + [base_to_id(base)])
                matching_ids = [] # t might contain N, so more that one id match to this tuple
                allowd_bases = [[0,1,2,3] if b == 5 else [b] for b in t]
                # TODO here, stop codons are allowed. B has just zeros at these positions.
                # this results in a very slight shift of there parameters
                allowed_ho_emissions = list(product(*allowd_bases))
                entry_of_one_hot = np.zeros(config.model.number_of_emissions)
                for allowed_ho_emission in allowed_ho_emissions:
                    entry_of_one_hot[config.model.emission_tuple_to_id(allowed_ho_emission)] = 1
                entry_of_one_hot /= sum(entry_of_one_hot)
                entry_of_one_hot = "_".join([str(x) for x in entry_of_one_hot])
                seq_of_one_hot.append(entry_of_one_hot)
                last_bases = last_bases[1:] + [base_to_id(base)] if config.order > 0 else []
                # print(list(entry_of_one_hot))
                # for i in range(len(entry_of_one_hot)):
                #     if entry_of_one_hot[i] != 0:
                #         print(config.model.emission_id_to_str(i), end = ", ")
            if add_one_terminal_symbol:
                entry_of_one_hot = np.zeros(config.model.number_of_emissions, dtype = np.float32)
                entry_of_one_hot[config.model.emission_tuple_to_id("X")] = 1
                entry_of_one_hot = "_".join([str(x) for x in entry_of_one_hot])
                seq_of_one_hot.append(entry_of_one_hot)
            seqs.append(seq_of_one_hot)
    append_time_ram_stamp_to_file(f"read_data_one_hot_with_Ns_spread_str() end ", config.bench_path, start)
    assert len(seqs) != 0, "no seqs read"
    print("actual number of species used as input:", len(seqs))

    if config.only_human:
        seqs.append(seqs[0])
        print("added human sequence to input")
        print("len(seqs)", len(seqs))

    return seqs

def remove_long_seqs(seqs):
    len_of_seqs = [len(seq) for seq in seqs]
    # median
    med = np.median(len_of_seqs)
    # create a list starting in 2 ending in 10 with step size 0.1
    l = np.arange(2,10,0.1)
    for f in l:
        number_of_too_long_seqs = 0
        for lenght in len_of_seqs:
            if lenght > f * med:
                number_of_too_long_seqs += 1
        if number_of_too_long_seqs < 0.09 * len(seqs):
            break

    # remove all seqs that are longer than f * med
    seqs = [seq for seq in seqs if len(seq) <= f * med]

    # assert that there are still more than 90% of the seqs left
    assert len(seqs) > 0.89 * len(len_of_seqs), "to many seqs removed"
    return seqs

def read_data_with_order(config, alphabet = ["A","C","G","T"], add_one_terminal_symbol = False, verbose = False):
    seqs = []
    def log(s):
        if verbose:
            print(s)

    base_to_id = dict([(base, id) for id, base in enumerate(alphabet)])
    with open(config.fasta_path,"r") as handle:
        log(f"opened: {config.fasta_path}")
        for record in SeqIO.parse(handle,"fasta"):
            seq = record.seq
            log(f"seq = {seq}")
            seq_of_tuple_ids = [] # 21, 124
            last_bases = [4] * config.order # 4 is padded left flank
            for base in seq:
                t = (last_bases + [base_to_id[base]])
                seq_of_tuple_ids.append(config.model.emission_tuple_to_id(t))
                last_bases = last_bases[1:] + [base_to_id[base]] if config.order > 0 else []
            if add_one_terminal_symbol:
                seq_of_tuple_ids.append(config.model.emission_tuple_to_id("X"))
            seqs.append(seq_of_tuple_ids)
    log(f"read {len(seqs)} sequnces")
    return seqs

def get_batch_input_from_tf_printed_file(path):
    input = []
    with open(path, "r") as file:
        seq = []
        for line in file:
            line = line.strip()
            if len(line) == 0:
                input.append(seq)
                seq = []
            else:
                line = re.sub("[\[\]]","", line)
                line = line.split(" ")
                line = [float(x) for x in line]
                seq.append(line)
        if len(seq) != 0:
            input.append(seq)
    return tf.constant(input, dtype = tf.float32)


#from GUI import tk_entry_alb_suffix

def findtextures():
    import os, fnmatch
    import Settings
    #Set directory
    os.chdir(Settings.folder_path)

    #CREATE LIST WITH FOLDER FILES
    file_list = []
    for i in os.listdir():
        file_list.append(i)

    def findfile(pattern, path):
        result = []
        for name in os.listdir():
            if fnmatch.fnmatch(name, pattern):
                result.append(name)
        return result
    #find('jpg', folder_path)
    Settings.tex_Albedo.append(findfile('*albedo*', Settings.folder_path))
    Settings.tex_Normal.append(findfile('*normal*', Settings.folder_path))
    Settings.tex_Roughness.append(findfile('*roughness*', Settings.folder_path))
    Settings.tex_Metalness.append(findfile('*metalness*', Settings.folder_path))
    Settings.tex_Height.append(findfile('*disp*', Settings.folder_path))
    Settings.tex_AO.append(findfile('*_ao*', Settings.folder_path))

if __name__ == "__main__":
    findtextures()

def ResetTextureValues():
    import Settings
    Settings.tex_Albedo = []
    Settings.tex_Normal = []
    Settings.tex_Roughness = []
    Settings.tex_Metalness = []
    Settings.tex_Height = []
    Settings.tex_AO = []

if __name__ == "__main__":
    ResetTextureValues()

def debug():
    import Settings
    print(Settings.tex_Albedo)
    print(Settings.tex_Normal)
    print(Settings.tex_Roughness)
    print(Settings.tex_Metalness)
    print(Settings.tex_AO)
    print(Settings.tex_Height)
if __name__ == "__main__":
    debug()

def convertimg():
    import os, fnmatch
    from shutil import copy2
    from PIL import Image as pillowimage
    import Settings

    import Settings
    print(Settings.tex_Albedo)
    print(Settings.tex_Normal)
    print(Settings.tex_Roughness)
    print(Settings.tex_Metalness)
    print(Settings.tex_AO)
    print(Settings.tex_Height)

    #print(dir(os))
    #print(os.getcwd())
    #Set directory
    os.chdir(Settings.folder_path)
    conv_fold_name = 'Converted'

    #CREATE FOLDER CONVERTED
    file_list = []
    for i in os.listdir():
        file_list.append(i)
    if conv_fold_name not in file_list:
        os.mkdir('Converted')

    def imgprocess(srcname,folder,width,height,format, name, suffix):
        imgn = pillowimage.open(srcname)
        img_adj = imgn.resize((width, height))
        img_adj.save(folder+name+suffix+format)

    print('FINAL DEBUG BEFOR CONVERSION')
    debug()

    if Settings.tex_Albedo:
        if not Settings.tex_Albedo == 'None':
            print('Converting: '+Settings.tex_albedo)
            imgprocess(Settings.tex_Albedo,Settings.destination_folder, int(Settings.width_px), int(Settings.height_px),Settings.c_format, Settings.c_TextureName,Settings.c_AlbedoSuffix)

    if Settings.tex_Normal:
        if not Settings.tex_Normal == 'None':
            print('Converting: '+Settings.tex_normal)
            imgprocess(Settings.tex_Normal,Settings.destination_folder, int(Settings.width_px), int(Settings.height_px),Settings.c_format, Settings.c_TextureName,Settings.c_NormalSuffix)

    if Settings.tex_Roughness:
        if not Settings.tex_Roughness == 'None':
            print('Converting: '+Settings.tex_roughness)
            imgprocess(Settings.tex_Roughness,Settings.destination_folder, int(Settings.width_px), int(Settings.height_px),Settings.c_format, Settings.c_TextureName,Settings.c_RoughnessSuffix)

    if Settings.tex_Metalness:
        if not Settings.tex_Metalness == 'None':
            print('Converting: '+Settings.tex_metalness)
            imgprocess(Settings.tex_Metalness,Settings.destination_folder, int(Settings.width_px), int(Settings.height_px),Settings.c_format, Settings.c_TextureName,Settings.c_MetalnessSuffix)

    if Settings.tex_Height:
        if not Settings.tex_Height == 'None':
            print('Converting: '+Settings.tex_height)
            imgprocess(Settings.tex_Height,Settings.destination_folder, int(Settings.width_px), int(Settings.height_px),Settings.c_format, Settings.c_TextureName,Settings.c_HeightSuffix)
    if Settings.tex_AO:
        if not Settings.tex_AO == 'None':
            print('Converting: '+Settings.tex_AO)
            imgprocess(Settings.tex_AO,Settings.destination_folder, int(Settings.width_px), int(Settings.height_px),Settings.c_format, Settings.c_TextureName,Settings.c_AOSuffix)

    print('DONE')

if __name__ == "__main__":
    convertimg()

#IF RESOLUTION LEFT AT NONE FUNCTION KEEPS THE ORIGINAL RESOLUTION

#EXAMPLE:
#dir = r'C:\Users\lreznicek\Desktop\Asphalt_Fine_tk3mebkew_8K_surface_ms\packer'
#aimgName = 'TESTIMAGE.tga'
#aimgR = 'tk3mebkew_8K_AO.jpg'
#aimgG = 'tk3mebkew_8K_Roughness.jpg'
#aimgB = None
#packRGBA(dir,aimgName,SimgR=None, SimgG=aimgG,SimgB=aimgB,imgResW=None,imgResH=None, SimgA=aimgR)

def packRGBA(dir,imgName, SimgR=None, SimgG=None, SimgB=None, SimgA=None, imgResW=None, imgResH=None):
    import os
    from PIL import Image as P_Image
    from PIL import ImageOps as P_ImageOps

    #SET DIRECTORY
    os.chdir(dir)

    #DETERMINE SOURCE RESOLUTION
    for i in [SimgR,SimgG,SimgB,SimgA]:
        if i == None:
            continue
        else:
            imr = P_Image.open(i)
            SwidthR, SheightR = imr.size
            break

    #SET SOURCE WIDTH AND HEIGHT IF NOT SPECIFIED IN FUNCTION
    if imgResW is None:
        imgResW = SwidthR

    if imgResH is None:
        imgResH = SheightR

    tRes = (imgResW, imgResH)

    #CREATE EMPTY IMAGES IF NONE ARE SPECIFIED IN FUNCTION, CONVERT INPUT TEXTURES TO GRAYSCALE, SET RESOLUTION
    if SimgR is None:
        imgRg = P_Image.new('L', tRes, color='#808080')
    else:
        imgR = P_Image.open(SimgR)
        imgR = imgR.resize(tRes)
        imgRg = P_ImageOps.grayscale(imgR)

    if SimgG is None:
        imgGg = P_Image.new('L',tRes,color='#808080')
    else:
        imgG = P_Image.open(SimgG)
        imgG = imgG.resize(tRes)
        imgGg = P_ImageOps.grayscale(imgG)

    if SimgB is None:
        imgBg = P_Image.new('L',tRes,color='#808080')
    else:
        imgB = P_Image.open(SimgB)
        imgB = imgB.resize(tRes)
        imgBg = P_ImageOps.grayscale(imgB)

    if SimgA is None:
        pass
    else:
        imgA = P_Image.open(SimgA)
        imgA = imgA.resize(tRes)
        imgAg = P_ImageOps.grayscale(imgA)

    #MERGE GRAYSCALE IMAGES
    if SimgA is None:
        imageRGB = P_Image.merge('RGB', (imgRg,imgGg,imgBg))
    else:
        imageRGB = P_Image.merge('RGBA', (imgRg,imgGg,imgBg,imgAg))

    #SAVE PACKED IMAGE
    imageRGB.save(imgName)

    #OUTPUT
    print('PACKED')

if __name__ == "__main__":
    pass


import numpy as np
import torch.nn as nn
from noise_layers.identity import Identity
from noise_layers.jpeg_compression import JpegCompression
from noise_layers.quantization import Quantization

class Noiser(nn.Module):
    """
    This module allows to combine different noise layers into a sequential noise module. The
    configuration and the sequence of the noise layers is controlled by the noise_config parameter.
    """
    def __init__(self, noise_layers: list, device):
        super(Noiser, self).__init__()
        self.noise_layers = [Identity()]
        for layer in noise_layers:
            if type(layer) is str:
                if layer == 'JpegPlaceholder':
                    self.noise_layers.append(JpegCompression(device))
                elif layer == 'QuantizationPlaceholder':
                    self.noise_layers.append(Quantization(device))
                else:
                    raise ValueError(f'Wrong layer placeholder string in Noiser.__init__().'
                                     f' Expected "JpegPlaceholder" or "QuantizationPlaceholder" but got {layer} instead')
            else:
                self.noise_layers.append(layer)
        # self.noise_layers = nn.Sequential(*noise_layers)

    def forward(self, encoded_and_cover):
        random_noise_layer = np.random.choice(self.noise_layers, 1)[0]
        return random_noise_layer(encoded_and_cover)


"""
同时掷三个骰子：如果你同时掷三个 D6 骰子，可能得到的最小点数为 3，而最大点数为 18。
请通过可视化展示同时掷三个 D6 骰子的结果。
"""
import pygal

from die import Die

die_1 = Die()
die_2 = Die()
die_3 = Die()

results = [die_1.roll() + die_2.roll() + die_3.roll() for roll_num in range(1000000)]

max_result = die_1.num_sides + die_2.num_sides + die_3.num_sides
frequencies = [results.count(value) for value in range(3, max_result + 1)]

hist = pygal.Bar()

hist.title = "Results of rolling three D6 dice 1,000,000 times."
hist.x_labels = [str(x) for x in range(3, max_result + 1)]
hist.x_title = "Result"
hist.y_title = "Frequency of Result"

hist.add('D6 + D6 + D6', frequencies)
hist.render_to_file('three_dice_visual.svg')


from baseclasses import SimpleTestCase
from tempfile import NamedTemporaryFile
import os, sys
sys.path.append(os.path.abspath('..'))
import modules.shell.sh
import modules.shell.php

class FSEnum(SimpleTestCase):

    def test_help(self):
        help_output = self._warn(":help" )
        self.assertRegexpMatches(help_output, '|[\s]module[\s]+|[\s]description[\s]+|[\n]{%i}' % (len(self.term.modhandler.modules_classes)+2))
        self.assertNotRegexpMatches(help_output, '\n'*4)

        help_shell_output = self._warn(":help shell" )
        sh_descr = modules.shell.sh.Sh.__doc__
        php_descr = modules.shell.php.Php.__doc__
        self.assertRegexpMatches(help_shell_output, '\[shell\.sh\] %s[\s\S]+usage:[\s\S]+\[shell\.php\] %s[\s\S]+usage:[\s\S]+' % (sh_descr, php_descr))
        self.assertNotRegexpMatches(help_shell_output, '\n'*4)

        help_nonexistant_output = self._warn(":help nonexistant" )
        self.assertRegexpMatches(help_nonexistant_output, '')

        help_shell_sh_output = self._warn(":help shell.sh" )
        self.assertRegexpMatches(help_shell_sh_output, 'usage:[\s\S]+%s[\s\S]+positional arguments:[\s\S]+optional arguments:[\s\S]+stored arguments:[\s\S]+' % (sh_descr))
        self.assertNotRegexpMatches(help_shell_sh_output, '\n'*3)


import requests
from bs4 import BeautifulSoup

def count_func(url,word):

	request= requests.get(url)
	soupp=BeautifulSoup(request.content,"html.parser")
	s=soupp.find(text=lambda text:text and word in text )
	try:
		lenn=len(s)
		print(lenn)
		if(len>0):
			return 2
		else:
			return -1
	except:
		print("")

def next_page(link):
	req = requests.get(link)
	Soup97 = BeautifulSoup(req.content, "html.parser")
	href_tag = Soup97.find("link",rel = "next")
	sports_link = href_tag['href']
	return sports_link

my_url="https://propakistani.pk/ "
req= requests.get(my_url)
content= req.content
soup = BeautifulSoup(content, "html.parser")
a1= soup.find("a", attrs={"title":"Sports"})
href2=a1['href']

#here
inp = raw_input("Enter the word(s) : ")
count=0
check=0
url11=[]
for j in range(5):
	req22= requests.get(href2)
	content22= req22.content
	soup11 = BeautifulSoup(content22, "html.parser")
	for i in soup11.find_all("a", attrs={"rel":"bookmark"}):
		url11.append(i['href'])
		check=check+1
	href2=next_page(href2)

while(count < 149):
	if(count%2==0):
		countt = count_func(url11[count], inp)
		if (countt<0):
			print("does not exist")
		else:
			print('\nUrl1: {}\ncontains: {}'.format(url11[count], inp))
	count=count+1
print("program over")


# -*- coding: utf8 -*-

from torch.utils.tensorboard import SummaryWriter

from .singleton import singleton

class BaseSummary:

    def add(self, data):
        # Called many times per epoch, must save data
        raise NotImplementedError()

    def write_metrics(self):
        # Perform final computation and write the summary
        raise NotImplementedError()

    def reset(self):
        raise NotImplementedError()

@singleton
class SumAgg:
    def __init__(self, cfg=None, out_path=None, disable=False):

        if disable:
            self.disabled = True
            self.ignore_iter = True
            return
        else:
            self.disabled = False

        # First call to SumAgg must give cfg and out_path
        assert cfg is not None
        assert out_path is not None

        self.cfg = cfg
        self.out_path = out_path

        self.tensorboard_writer = SummaryWriter(log_dir=str(out_path / "tensorboard"))

        self.summaries = {}

        self.epoch_metrics = {}

    def add_summary(self, summary):
        if self.disabled:
            return

        self.summaries[summary.name] = summary

    def add_summaries(self, summaries):
        if self.disabled:
            return

        for s in summaries:
            self.add_summary(s)

    def start_epoch(self, phase, epoch):
        if self.disabled:
            return

        self.phase = phase
        self.epoch = epoch
        self.ignore_iter = False

        # Reset data
        for s_name in self.summaries:
            s = self.summaries[s_name]
            s.reset()

    def set_ignore_iter(self, ignore_iter):
        if self.disabled:
            return

        self.ignore_iter = ignore_iter

    def is_compute_summary(self):
        return not self.ignore_iter

    def add(self, name, data, force=False):
        if self.disabled:
            return

        s = self.summaries[name]
        if not self.ignore_iter or force:
            if s.add is not None:
                s.add(data)

    def update(self, data_dict, force=False):
        if self.disabled:
            return

        for name in data_dict:
            self.add(name, data_dict[name], force)

    def end_epoch(self):
        if self.disabled:
            return

        for s_name in self.summaries:
            s = self.summaries[s_name]
            s.write_metrics()

    def close(self):
        if self.disabled:
            return

        self.tensorboard_writer.close()


# -*- coding: utf-8 -*-

# @Time : 2022-07-29 17:25:09
# @Author : 石张毅
# @Site :  中国人民解放军总医院
# @introduce: http://211.166.249.33/admin-portal-index.html

import scrapy

import re
import copy
from Qinghai.tools.utils import Utils_
from Qinghai.tools.DB_mysql import *
from Qinghai.tools.re_time import Times
import datetime
from Qinghai.tools.uredis import Redis_DB
import scrapy

class Qh301Spider(scrapy.Spider):
    name = 'qh_301'
    def __init__(self, *args, **kwargs):
        super(Qh301Spider, self).__init__()
        self.cates = [
            {"cate": "1698", "pages": 2},
        ]
        self.t = Times()
        self.c_time = datetime.datetime.utcnow() - datetime.timedelta(days=3)

    def start_requests(self):
        url = f"http://211.166.249.33/admin-portal-proclamation-type-0-page_num-20-p-1.html"
        yield scrapy.Request(url=url, callback=self.parse, dont_filter=True)

    def parse(self, response, **kwargs):
        # print(response.text)
        # 列表页链接和发布时间
        count_list = response.xpath('//*[@class="contListTab "]/tbody//tr')
        if count_list is []:
            return
        for count in count_list:
            item = dict()
            # 列表页链接和发布时间
            link =count.xpath('./@onclick').get()
            res = re.findall('/admin.*?html', link)[0]
            item['link'] = response.urljoin(res)
            item['title'] = count.xpath('./td[3]/p/text()').get()
            if item['title'] is None:
                continue
            item['type'] = count.xpath('./td[2]/span/text()').get().replace('[', '').replace(']', '')

            item['items'] = count.xpath('./td[1]/span/text()').get()
            pub_time = count.xpath('./td[4]/text()').get()
            PUBLISH = self.t.datetimes(pub_time)
            item['publish_time'] = PUBLISH.strftime('%Y-%m-%d')  # 发布时间
            # print(item['publish_time'],item['link'],item['title'],item['item'],item['type'])
            item['uid'] = 'zf' + Utils_.md5_encrypt(item['title'] + item['link'] + item['publish_time'])
            ctime = self.t.datetimes(item['publish_time'])
            if ctime < self.c_time:
                print('文章发布时间大于规定时间，不予采集', item['link'])
                return
            if Redis_DB().Redis_pd(item['uid']) is True:  # 数据去重
                print(item['uid'], '\033[0;35m <=======此数据已采集=======> \033[0m')
                return
            yield scrapy.Request(item['link'], callback=self.parse_info, meta={'item': copy.deepcopy(item)},
                                 dont_filter=True)

    def parse_info(self, response):
        if response.status != 200:
            return
        item = response.meta['item']
        # 标题
        item['uuid'] = ''

        item['intro'] = ''
        item['abs'] = '1'
        from lxml import etree
        html = etree.HTML(response.text)
        div_data = html.xpath('//*[@class="contDetailLeft"]')
        item['content'] = etree.tostring(div_data[0], encoding='utf-8').decode()
        item['purchaser'] = ''
        item['create_time'] = str(datetime.datetime.now().strftime('%Y-%m-%d'))
        item['proxy'] = ''
        item['update_time'] = ''
        item['deleted'] = ''
        item['province'] = ''
        item['base'] = ''
        item['data_source'] = '00695'
        item['end_time'] = ''
        item['status'] = ''
        item['serial'] = ''
        # print(item)
        yield item


from io import StringIO

from colorama import Back, Fore

from sudoku.grid import CellStatus, Grid
from sudoku.grid import get_cell_address

def render_as_text(grid: Grid, use_color: bool = True) -> str:
    """
    Generates and returns textual representation of the given grid.

    Paramaters:
            grid (sudoku.grid.Grid):    The grid to be rendered.
            use_colors (bool):          True if ANSI escape sequences are to be used to highlight
                                        predefined cells (and thus distinguish them from the
                                        completed cells); False otherwise.

    Returns:
        str: The generated textual representation of the given grid.
    """
    renderer = _GridTextRenderer(grid, use_color)
    return renderer.render()

class _GridTextRenderer:
    """
    Simple renderer that can take an instance of the sudoku.grid.Grid class and
    generate a textual grid presenting the cell values of the given grid. Optionally,
    ANSI escape sequences can be used to highlight predefined cells.
    """

    _BORDER_LINE_TEMPLATE = "+-------+-------+-------+"

    _CELL_LINE_TEMPLATE = "| ? ? ? | ? ? ? | ? ? ? |"

    _GRID_BACKGROUND = Back.BLACK

    _GRID_FOREGROUND = Fore.WHITE

    _PREDEFINED_CELL_FOREGROUND = Fore.RED

    def __init__(self, grid: Grid, use_colors: bool = False) -> None:
        self._grid = grid
        self._use_colors = use_colors
        self._output = StringIO()

    def render(self) -> str:
        """
        Creates and returns a string representation of the grid this rendered has been initialized
        with.
        """
        if self._use_colors:
            self._output.write("\n" + self._GRID_FOREGROUND + self._GRID_BACKGROUND)
        self._write_border()

        for range_of_rows in range(0, 3), range(3, 6), range(6, 9):
            for row in range_of_rows:
                self._write_cells(row)
            self._write_border()

        if self._use_colors:
            self._output.write("\n" + Fore.RESET + Back.RESET)
        return self._output.getvalue()

    def _write_border(self) -> None:
        if self._use_colors:
            self._output.write(self._GRID_FOREGROUND + self._GRID_BACKGROUND)
        self._output.write(self._BORDER_LINE_TEMPLATE)
        if self._use_colors:
            self._output.write(Fore.RESET + Back.RESET)
        self._output.write("\n")

    def _write_cells(self, row: int) -> None:
        output = self._CELL_LINE_TEMPLATE
        for column in range(9):
            cell_address = get_cell_address(row, column)
            cell_value = " "
            if self._grid.get_cell_status(cell_address) != CellStatus.UNDEFINED:
                cell_value = str(self._grid.get_cell_value(cell_address))
            if self._use_colors and self._grid.get_cell_status(cell_address) == CellStatus.PREDEFINED:
                cell_value = self._decorate_with_color(cell_value)
            output = output.replace("?", cell_value, 1)
        if self._use_colors:
            self._output.write(self._GRID_FOREGROUND + self._GRID_BACKGROUND)
        self._output.write(output)
        if self._use_colors:
            self._output.write(Fore.RESET + Back.RESET)
        self._output.write("\n")

    def _decorate_with_color(self, cell_value: str) -> str:
        return self._GRID_BACKGROUND + self._PREDEFINED_CELL_FOREGROUND + \
            cell_value + self._GRID_BACKGROUND + self._GRID_FOREGROUND


from flask import Flask, jsonify, request
from PIL import Image
from itertools import groupby
import numpy as np
import tensorflow as tf
from tensorflow import keras
import urllib.request

app = Flask(__name__)
@app.route("/")
def idx():
    return "abcfd"

#Run on http://127.0.0.1:5000

# @app.route("/calculate")
# def apitest():
#     return "API working"

# if __name__ == "__main__":
#   app.run(host="0.0.0.0", debug=False, port=5005)

elements_pred=[]
def calculate(img_loc):
    global elements_pred
    'loading image'
    urllib.request.urlretrieve(img_loc,"input.png")
    image = Image.open("input.png").convert("L")
    image.show()

    'resizing to 28 height pixels'
    w = image.size[0]
    h = image.size[1]
    r = w / h # aspect ratio
    new_w = int(r * 28)
    new_h = 28
    new_image = image.resize((new_w, new_h))

    'converting to a numpy array'
    new_image_arr = np.array(new_image)

    'inverting the image to make background = 0'
    new_inv_image_arr = 255 - new_image_arr

    'rescaling the image'
    final_image_arr = new_inv_image_arr / 255.0

    'splitting image array into individual digit arrays using non zero columns'
    m = final_image_arr.any(0)
    out = [final_image_arr[:,[*g]] for k, g in groupby(np.arange(len(m)), lambda x: m[x] != 0) if k]

    '''
    iterating through the digit arrays to resize them to match input
    criteria of the model = [mini_batch_size, height, width, channels]
    '''
    num_of_elements = len(out)
    elements_list = []

    for x in range(0, num_of_elements):

        img = out[x]

        #adding 0 value columns as fillers
        width = img.shape[1]
        filler = (final_image_arr.shape[0] - width) / 2

        if filler.is_integer() == False:    #odd number of filler columns
            filler_l = int(filler)
            filler_r = int(filler) + 1
        else:                               #even number of filler columns
            filler_l = int(filler)
            filler_r = int(filler)

        arr_l = np.zeros((final_image_arr.shape[0], filler_l)) #left fillers
        arr_r = np.zeros((final_image_arr.shape[0], filler_r)) #right fillers

        #concatinating the left and right fillers
        help_ = np.concatenate((arr_l, img), axis= 1)
        element_arr = np.concatenate((help_, arr_r), axis= 1)

        element_arr.resize(28, 28, 1) #resize array 2d to 3d

        #storing all elements in a list
        elements_list.append(element_arr)

    elements_array = np.array(elements_list)

    'reshaping to fit model input criteria'
    elements_array = elements_array.reshape(-1, 28, 28, 1)

    'predicting using the model'
    #model = keras.models.load_model("C:\\Users\\Priyam_Shukla\\Downloads\\Final Year Project\\model1")
    model = keras.models.load_model("model1")
    elements_pred =  model.predict(elements_array)
    elements_pred = np.argmax(elements_pred, axis = 1)
    print(elements_pred)

def math_expression_generator(arr):

    op = {
              10,   # = "/"
              11,   # = "+"
              12,   # = "-"
              13    # = "*"
                  }

    m_exp = []
    temp = []

    'creating a list separating all elements'
    for item in arr:
        if item not in op:
            temp.append(item)
        else:
            m_exp.append(temp)
            m_exp.append(item)
            temp = []
    if temp:
        m_exp.append(temp)

    'converting the elements to numbers and operators'
    i = 0
    num = 0
    for item in m_exp:
        if type(item) == list:
            if not item:
                m_exp[i] = ""
                i = i + 1
            else:
                num_len = len(item)
                for digit in item:
                    num_len = num_len - 1
                    num = num + ((10 ** num_len) * digit)
                m_exp[i] = str(num)
                num = 0
                i = i + 1
        else:
            m_exp[i] = str(item)
            m_exp[i] = m_exp[i].replace("10","/")
            m_exp[i] = m_exp[i].replace("11","+")
            m_exp[i] = m_exp[i].replace("12","-")
            m_exp[i] = m_exp[i].replace("13","*")

            i = i + 1

    'joining the list of strings to create the mathematical expression'
    separator = ' '
    m_exp_str = separator.join(m_exp)

    return (m_exp_str)

@app.route("/func", methods = ['POST'])

def func():
    'creating the mathematical expression'
    with app.app_context():
        #test code
        image_loc = request.form.get('image_url')
        calculate(image_loc)
        m_exp_str = math_expression_generator(elements_pred)

    'calculating the mathematical expression using eval()'
    while True:
        try:
            answer = eval(m_exp_str)    #evaluating the answer
            answer = round(answer, 2)
            equation  = m_exp_str + " = " + str(answer)
            print(equation)   #printing the equation
            result={"answer":equation}
            return jsonify(result)
            #break

        except SyntaxError:
            print("Invalid predicted expression!!")
            print("Following is the predicted expression:")
            print(m_exp_str)
            break

#print(func())

# if __name__=="__main__":
#     app.run(debug=True)


import json
import re

CONTACT_FILE_PATH = "contacts.json"
MENU_PRINT = """
The following is a list of useable commands:
    "add": Adds a contact.
    "delete": Deletes a contact.
    "list": Lists all contacts.
    "search": Searches for a contact by name.
    "q": Quits the program and saves the contact list.
        """

def read_contacts(file_path):
    try:
        with open(file_path, 'r') as f:
            contacts = json.load(f)['contacts']
    except FileNotFoundError:
        contacts = []

    return contacts

def write_contacts(file_path, contacts):
    with open(file_path, 'w') as f:
        contacts = {"contacts": contacts}
        json.dump(contacts, f)

def verify_email_address(email):
    if email == "":
        return True

    if "@" not in email:
        return False

    split_email = email.split("@")
    identifier = "".join(split_email[:-1])
    domain = split_email[-1]

    if len(identifier) < 1:
        return False

    if "." not in domain:
        return False

    split_domain = domain.split(".")

    for section in split_domain:
        if len(section) == 0:
            return False

    return True

def verify_phone_number(phone_number):
    print(re.sub(r'\W+', '', phone_number))
    return re.search("\d{10}", re.sub(r'\W+', '', phone_number)) or phone_number in ["", None]

def required(entry):
    return entry not in ["", None]

def is_contact_duplicated(contacts, candidate):
    return any(contact["first_name"] == candidate["first_name"]
               and contact["last_name"] == candidate["last_name"] for contact in contacts)

CONTACT_FIELDS = [
    {"key": "first_name", "display": "First name: ", "rules": [required]},
    {"key": "last_name", "display": "Last name: ", "rules": [required]},
    {"key": "mobile_phone_number", "display": "Mobile phone number: ",
        "rules": [verify_phone_number]},
    {"key": "home_phone_number", "display": "Home phone Number: ",
        "rules": [verify_phone_number]},
    {"key": "email_address", "display": "Email address: ",
        "rules": [verify_email_address]},
    {"key": "address", "display": "Address: ", "rules": []}
]

def add_contact(contacts):
    new_contact = {}
    for field in CONTACT_FIELDS:
        entry = input(field["display"]).strip()
        for rule in field["rules"]:
            if not rule(entry):
                print("You entered invalid information, this contact was not added.")
                return
        new_contact[field["key"]] = entry
    if is_contact_duplicated(contacts, new_contact):
        print("A contact with this name already exists.")
        print("You entered invalid information, this contact was not added.")
        return
    contacts.append(new_contact)

def search_for_contact(contacts):
    entry = {}
    for field in CONTACT_FIELDS:
        if field["key"] in ["last_name", "first_name"]:
            entry[field["key"]] = input(field["display"]).strip().lower()

    res = list(filter(
        lambda x: entry["first_name"] in x["first_name"] and entry["last_name"] in x["last_name"],
        contacts))

    if not res:
        print("No contact found")

    for idx, contact in enumerate(res):
        display_contact(idx, contact)

def delete_contact(contacts):
    entry = {}
    for field in CONTACT_FIELDS:
        if field["key"] in ["last_name", "first_name"]:
            entry[field["key"]] = input(field["display"]).strip()

    res = list(filter(lambda x: (x[key] == entry[key]
                                 for key in ["last_name", "first_name"]), contacts))

    if len(res) <= 0:
        print("No contact with this name exists.")
        return

    display_contact(1, res[0])

    confirm = input(
        "Are you sure you would like to delete this contact (y/n)? ").strip().lower()
    if confirm in ["yes", "y"]:
        contacts.remove(res[0])
        print("Contact deleted!")
    return

def list_contacts(contacts):
    for idx, contact in enumerate(contacts):
        display_contact(idx, contact)

def display_contact(idx, contact):
    print(f"{idx+1}. {contact['first_name']} {contact['last_name']}")
    for field in CONTACT_FIELDS:
        if field["key"] in ["first_name", "last_name"] or contact[field["key"]] == "":
            continue
        print(f"      {field['display']}{contact[field['key']]}")

def main(contacts_path):
    contacts = read_contacts(contacts_path)
    commands = {"add": add_contact, "delete": delete_contact,
                "search": search_for_contact, "list": list_contacts}
    print("*********************************")
    print("* Welcome to your contact list! *")
    print("*********************************")
    while True:
        print(MENU_PRINT)
        command = input("Type a command: ")

        if command in ["q", "quit", "exit"]:
            write_contacts(contacts_path, contacts)
            print("\nContacts were saved successfully.\n")
            break
        elif command not in commands.keys():
            print("Invalid input")
            continue
        else:
            print("\n")
            commands[command](contacts)
            print("\n--")

if __name__ == "__main__":
    main(CONTACT_FILE_PATH)


from django.urls import path,include
from . import views

app_name = 'quiz'
urlpatterns = [
    path('', views.index, name='index'),
    path('index/', views.index, name='index'),
    path('startquiz/', views.start_quiz, name='startquiz'),
    path('signup/', views.signup,name='signup'),
    path('startquiz/<int:page_id>', views.startquizmonitor, name='startquiz'),
]


from sqlalchemy.ext.asyncio import AsyncSession
from models.database import OrmFamalyLoveImage
from sqlalchemy import asc, func, select, text
from sqlalchemy.orm import selectinload
from .abstract import AbstractDALFamalyLoveImage
from functools import lru_cache

class DALFamalyLoveImage(AbstractDALFamalyLoveImage):
    async def create(
        self: 'DALFamalyLoveImage',
        famaly_love_quiz_id: int,
        image_path: str,
        is_male: bool,
        session: AsyncSession
    ) -> OrmFamalyLoveImage:
        orm_famaly_love_image = OrmFamalyLoveImage(
            famaly_love_quiz_id=famaly_love_quiz_id,
            image_path=image_path,
            is_male=is_male
        )
        session.add(orm_famaly_love_image)
        await session.flush()
        await session.refresh(orm_famaly_love_image)
        return orm_famaly_love_image

    async def get_by_id(
        self: 'DALFamalyLoveImage',
        id: int,
        session: AsyncSession
    ) -> OrmFamalyLoveImage:
        orm_famaly_love_image = await session.execute(
            select(OrmFamalyLoveImage)
            .where(OrmFamalyLoveImage.id == id)
        )
        return orm_famaly_love_image.scalar()

    async def get_count(
        self: 'DALFamalyLoveImage',
        session: AsyncSession
    ) -> int:
        count_famaly_love_images = await session.execute(
            select(func.count())
            .select_from(OrmFamalyLoveImage)
        )
        return count_famaly_love_images.scalar()

    async def update_by_id(
        self: 'DALFamalyLoveImage',
        id: int,
        image_path: str,
        session: AsyncSession
    ) -> OrmFamalyLoveImage:
        orm_famaly_love_image = await self.get_by_id(id)
        if not orm_famaly_love_image:
            return None
        orm_famaly_love_image.image_path = image_path
        session.add(orm_famaly_love_image)

    async def delete_by_id(
        self: 'DALFamalyLoveImage',
        id: int,
        session: AsyncSession
    ) -> OrmFamalyLoveImage:
        orm_famaly_love_image = await session.execute(
            select(OrmFamalyLoveImage)
            .where(OrmFamalyLoveImage.id == id)
        )
        if not orm_famaly_love_image:
            return None
        await session.delete(orm_famaly_love_image)

@lru_cache()
def get_DAL_famaly_love_image() -> DALFamalyLoveImage:
    return DALFamalyLoveImage()


from splinter import Browser
from bs4 import BeautifulSoup
import pandas as pd
from selenium import webdriver
import time

# create path to chromedriver
def init_browser():
    executable_path = {'executable_path': 'chromedriver.exe'}
    return Browser('chrome', **executable_path, headless=False)

# scrape Mars data
def scrape():
    browser = init_browser()

    mars = {}

   ##NASA Mars News
    url = "https://mars.nasa.gov/news/?page=0&per_page=40&order=publish_date+desc%2Ccreated_at+desc&search=&category=19%2C165%2C184%2C204&blank_scope=Latest"
    browser.visit(url)

    html = browser.html
    soup = BeautifulSoup(html, "html.parser")

    mars["news_title"] = soup.find("div", class_="content_title").text
    mars["news_p"] = soup.find("div", class_="rollover_description_inner").text

   ##JPL Mars Space Images - Featured Image
    pic_url = "https://www.jpl.nasa.gov/spaceimages/?search=&category=Mars"
    browser.visit(pic_url)

    browser.click_link_by_partial_text("FULL IMAGE")
    time.sleep(5)

    browser.click_link_by_partial_text("more info")

    pic_html = browser.html
    pic_soup = BeautifulSoup(pic_html, "html.parser")
    base_url = "https://www.jpl.nasa.gov"
    image_url = pic_soup.find("figure", class_="lede").a["href"]
    mars["featured_image_url"] = base_url + image_url

   ##Mars weather
    tweet_url = "https://twitter.com/marswxreport?lang=en"
    browser.visit(tweet_url)
    tweet_html = browser.html
    tweet_soup = BeautifulSoup(tweet_html, "html.parser")

    mars["mars_weather"] = tweet_soup.find("p", class_="TweetTextSize TweetTextSize--normal js-tweet-text tweet-text").text

   ##Mars facts
    table = pd.read_html("https://space-facts.com/mars/")
    df = table[0]
    df.columns = ["Description", "Value"]
    mars["facts_table"] = df.to_html()

   ##Mars hemispheres
    hemi_url = "https://astrogeology.usgs.gov/search/results?q=hemisphere+enhanced&k1=target&v1=Mars"
    browser.visit(hemi_url)
    hemi_html = browser.html
    hemi_soup = BeautifulSoup(hemi_html, "html.parser")

    cerberus= "https://astropedia.astrogeology.usgs.gov/download/Mars/Viking/cerberus_enhanced.tif/full.jpg"
    schiaparelli = "https://astropedia.astrogeology.usgs.gov/download/Mars/Viking/schiaparelli_enhanced.tif/full.jpg"
    syrtis_major = "https://astropedia.astrogeology.usgs.gov/download/Mars/Viking/syrtis_major_enhanced.tif/full.jpg"
    valles_marineris = "https://astropedia.astrogeology.usgs.gov/download/Mars/Viking/valles_marineris_enhanced.tif/full.jpg"
    img_urls = [cerberus, schiaparelli, syrtis_major, valles_marineris]

    img_titles = []
    titles = hemi_soup.find_all("h3")

    for title in titles:
        img_titles.append(title.get_text())

    mars["hemisphere_image_urls"] = [{"title": img_titles, "img_url": img_urls} for img_titles, img_urls in zip(img_titles, img_urls)]

    return mars


import pandas as pd
import xml.etree.ElementTree as ET
import matplotlib.pyplot as plt
from datetime import datetime
import time
import numpy as np
from sklearn.model_selection  import GridSearchCV
from sklearn import preprocessing
import argparse
from sklearn.svm import SVR
from sklearn.linear_model import LinearRegression
from sklearn.model_selection import train_test_split
from sklearn import metrics
from sklearn.metrics import mean_squared_error, r2_score
from joblib import dump, load
from sklearn.model_selection import cross_val_predict
from sklearn.preprocessing import MinMaxScaler

class ECAR:
    energia = []
    Day_hour = []
    Day_week = []
    Durata_ricarica = []
    Next_charge = []
    Weekend = []
    event = []
    en = [] #valori di energia assorbiti nel corso del tempo
    maxpower = []
    X = pd.DataFrame()
    y = pd.DataFrame()
    X_scaled = pd.DataFrame()
    y_scaled = pd.DataFrame()
    differenza = 0
    ymin = 0
    scaler1 = MinMaxScaler()
    scaler2 = MinMaxScaler()
    def __init__(self,path):
        tree = ET.parse(path)
        root = tree.getroot()
        index = 0
        for i in root[:]:
            self.event.append(float(root[index][0].text))
            self.energia.append(float(root[index][1].text))
            self.Day_hour.append(float(root[index][2].text))
            self.Day_week.append(float(root[index][3].text))
            self.Durata_ricarica.append(float(root[index][4].text))
            self.en.append(float(root[index][6].text))
            self.maxpower.append(float(root[index][7].text))
            self.Next_charge.append(float(root[index][8].text))
            self.Weekend.append((root[index][5].text))
            index = index + 1
        df = pd.DataFrame({"Event" : self.event,"Energia_assorbita_Wh" : self.energia,"Day_hour" : self.Day_hour,"Day_week": self.Day_week,"Next_charge_minuti": self.Next_charge,"Weekend": self.Weekend,"Durata_ricarica_minuti": self.Durata_ricarica,"Energia" : self.en, "MaxPower" : self.maxpower})
        self.y = df[['Next_charge_minuti']]
        self.X = df[['Event','Energia_assorbita_Wh','Day_hour','Day_week','Durata_ricarica_minuti',"Energia","MaxPower"]]
        self.scaler1 = preprocessing.StandardScaler().fit(self.X)
        self.scaler2 = preprocessing.StandardScaler().fit(self.y)
        self.scale_data()

    def scale_data(self):
        self.X_scaled = self.scaler1.transform(self.X)
        self.y_scaled = self.scaler2.transform(self.y)

    def show_test_result(self,y_reale,y_pred):
            print('Mean Absolute Error:', metrics.mean_absolute_error(y_reale, y_pred))
            print('Mean Squared Error:', metrics.mean_squared_error(y_reale, y_pred))
            print('Root Mean Squared Error:', np.sqrt(mean_squared_error(y_reale,y_pred)))
            ascisse1 = []
            for i in (range(0,len(y_pred))):
                      ascisse1.append(i)
                    #  print("Inizio prossima ricarica (reale)",y_reale[i],"Inizio prossima ricarica (predetto)",y_pred[i])

            plt.plot(ascisse1,[x/60 for x in y_reale] ,label = 'Reale')
            plt.plot(ascisse1,[x/60 for x in y_pred] ,label = 'Predizione')
            plt.legend(loc = 'upper left')
            plt.show()
            plt.figure(2)

    def show_result(self,y_pred,length):
            print("Prossima ricarica tra (minuti)")
            print(y_pred[0])
            for i in range (1, length):    #aspetto che l'utente mi dica next per mostrare la successiva predizione
                command = input()
                if (command == "next"):
                    print("Prossima ricarica tra (minuti)")
                    print(y_pred[i])
                else:
                    i = i - 1

    def test(self,train):
        self.scale_data()
        algoritmo = "dynamic"
        parser = argparse.ArgumentParser(description='Get the key')  #leggo l'algoritmo da utilizzare
        parser.add_argument('mood', action="store")
        algoritmo = parser.parse_args()

        svr_rbf = SVR(kernel = 'poly', gamma = 0.06, C = 120)  #set kernel
        size = int((len(self.X_scaled[:])/100)*train)   #calcolo il numero dei campioni su cui voglio fare il training iniziale

        if (algoritmo.mood == "dynamic"):
            X_train = self.X_scaled[:size,:]
            X_test = self.X_scaled[size,:]
            y_train = self.y_scaled[:size,:]
            y_test = self.y_scaled[size,:]
            y_pred = []
            y_reale = []
            for i in range(0,len(self.X_scaled[:]) - size - 1):    #effettuo la predizione ed effettuo nuovamente il training
                y_pred.append(abs(self.scaler2.inverse_transform(svr_rbf.fit(X_train, y_train.ravel()).predict(X_test.reshape(1,-1)))))     #effettuo la prediione dei risultati
                training = svr_rbf.fit(X_train,y_train.ravel())
                X_train = np.vstack([X_train,X_test])   #aggiungo una riga al modello di training
                X_test = self.X_scaled[size + i + 1]   #faccio il test sul campione successivo
                y_train = np.append(y_train,y_test)
                y_test = self.y_scaled[size + i +1]
                y_reale.append(self.scaler2.inverse_transform(y_test))
            del y_reale[0]
            y_reale.append(0)
            self.show_test_result(y_reale,y_pred)
        else:
            if (algoritmo.mood == "SVR"):
                 X_train, X_test, y_train, y_test = train_test_split(self.X_scaled,self.y_scaled ,test_size=1 - train/100, random_state=0,shuffle = False)
                 training = svr_rbf.fit(X_train,y_train.ravel())
                 y_pred = training.predict(X_test)
                 print(X_test)
                 self.show_test_result(self.scaler2.inverse_transform(y_test),abs(self.scaler2.inverse_transform(y_pred)))

    def training(self):
        svr_rbf = SVR(kernel = 'poly', gamma = 0.06, C = 120)
        model_training = svr_rbf.fit(self.X_scaled,self.y_scaled.ravel())
        dump(model_training,'/home/just/Documenti/training_model')
        return model_training

    def predict(self,prediction):
            df1 = pd.read_csv(prediction)
            training = load('/home/just/Documenti/training_model')
            parser = argparse.ArgumentParser(description='Get the key')  #leggo l'algoritmo da utilizzare
            parser.add_argument('mood', action="store")
            algoritmo = parser.parse_args()
            if (algoritmo.mood == "SVR"):                                   #leggo il mood e mostro i risultati predetti
                    y_pred = training.predict(self.scaler1.transform(df1.iloc[:,:7])).reshape(-1,1)
                    self.show_result(abs(y_pred),len(df1.iloc[:]) - 1)

            if (algoritmo.mood == "dynamic"):
                y_reale = []
                for i in range (0,len(df1.iloc[:,1])-1):
                    y_pred = training.predict(self.scaler1.transform(df1.iloc[i,:7].values.reshape(1,-1)))
                    self.X_scaled = np.vstack([self.X_scaled,self.scaler1.transform(df1.iloc[i,:7].values.reshape(1,-1))])
                    self.y_scaled = np.vstack([self.y_scaled,df1.iloc[i,8].reshape(1,1)])
                    training = self.training()
                    y_reale.append(y_pred)
                self.show_result([abs(y) for y in y_reale],len(df1.iloc[:]) - 1)

auto = ECAR('/home/just/Documenti/data.xml')
auto.test(85)
auto.training()
auto.predict("/home/just/Scaricati/prediction_model.csv")


import tensorflow as tf
import numpy as np
import pandas as pd
from tensorflow.keras.layers import Dense, Input, Reshape, Flatten, LeakyReLU
from tensorflow.keras.models import Model
from tensorflow.keras.optimizers import Adam
from Input_Handler import InputHandler
import logging
tf.get_logger().setLevel(logging.ERROR)

class WGAN():

    def __init__(self, input_shape=(68,), noise_dim=100, gen_hidden_dim=256, dis_hidden_dim=64, learning_rate=0.0002, batch_size=64, n_critic=5):
        print("[*] Starting WGAN __init__")
        self.input_shape = input_shape
        self.noise_dim = noise_dim
        self.gen_hidden_dim = gen_hidden_dim
        self.dis_hidden_dim = dis_hidden_dim
        self.learning_rate = learning_rate
        self.batch_size = batch_size
        self.n_critic = n_critic
        self.clip_value = 0.01
        print("[+] Initialized basic vars...")
        # Build and compile the discriminator
        self.discriminator = self.build_discriminator()
        self.discriminator.compile(loss=self.wasserstein_loss, optimizer=Adam(learning_rate, beta_1=0.5, beta_2=0.9))
        print("[+] Finished generating discriminator...")
        # Build the generator
        self.generator = self.build_generator()
        print("[+] Finished generating generator...")
        # Build the combined model
        self.combined = self.build_combined()
        print("[+] Finished generating combined...")
        # Load the data
        self.input_handler = InputHandler()
        test_data, train_data = self.input_handler.get_data_from_csv(unNorm=False)
        self.test_data = test_data.drop('malicious', axis=1)
        self.test_data_label = test_data['malicious']
        self.train_data = train_data.drop('malicious', axis=1)
        self.train_data_label = train_data['malicious']
        print("[+] Extracted data completely...")

    def wasserstein_loss(self, y_true, y_pred):
        return tf.keras.backend.mean(y_true * y_pred)

    def build_generator(self):
        input_noise = Input(shape=(self.noise_dim,))
        x = Dense(self.gen_hidden_dim, activation='relu')(input_noise)
        x = Dense(self.gen_hidden_dim, activation='relu')(x)
        x = Dense(np.prod(self.input_shape), activation='tanh')(x)
        output = Reshape(self.input_shape)(x)
        model = Model(input_noise, output)
        return model

    def build_discriminator(self):
        input_data = Input(shape=self.input_shape)
        x = Flatten()(input_data)
        x = Dense(self.dis_hidden_dim)(x)
        x = LeakyReLU(alpha=0.2)(x)
        x = Dense(self.dis_hidden_dim)(x)
        x = LeakyReLU(alpha=0.2)(x)
        output = Dense(1)(x)
        model = Model(input_data, output)
        return model

    def build_combined(self):
        input_noise = Input(shape=(self.noise_dim,))
        generated_data = self.generator(input_noise)
        validity = self.discriminator(generated_data)
        model = Model(input_noise, validity)
        model.compile(loss=self.wasserstein_loss, optimizer=Adam(self.learning_rate, beta_1=0.5, beta_2=0.9))
        return model

    def generate_samples(self, num_samples):
        noise = np.random.normal(0, 1, (num_samples, self.noise_dim))
        generated_samples = self.generator.predict(noise)
        return generated_samples

    def generate_noise(self, n_samples):
        return np.random.normal(0, 1, (n_samples, self.noise_dim))

    def train(self, epochs=5000):
        print("[*] Starting Training...")
#        self.train_data = np.array(self.train_data)
#        self.train_data = np.reshape(self.train_data, (-1, self.input_shape[0]))
        for epoch in range(epochs):
            # Train the discriminator for n_critic iterations
            for _ in range(self.n_critic):
                # Select a random batch of data
                idx = np.random.randint(0, self.train_data.shape[0], self.batch_size)
                real_data = self.train_data.iloc[idx]
                # Generate a batch of fake data
                noise = np.random.normal(0, 1, (self.batch_size, self.noise_dim))
                fake_data = self.generator.predict(noise)
                # Clip the weights of the discriminator
                for layer in self.discriminator.layers:
                    weights = layer.get_weights()
                    weights = [np.clip(w, -self.clip_value, self.clip_value) for w in weights]
                    layer.set_weights(weights)
                # Train the discriminator on real and fake data
                d_loss_real = self.discriminator.train_on_batch(real_data, -np.ones((self.batch_size, 1)))
                d_loss_fake = self.discriminator.train_on_batch(fake_data, np.ones((self.batch_size, 1)))
                d_loss = 0.5 * np.add(d_loss_fake, d_loss_real)
            self.discriminator.trainable = False
            # Train generator
            gan_input = self.generate_noise(len(self.train_data))
            y_gen = -np.ones((len(self.train_data), 1))
            g_loss = self.combined.train_on_batch(gan_input, y_gen)
            # Print progress
            print("[+] Epoch: %d  Discriminator Loss: %f  Generator Loss: %f" % (epoch, d_loss, g_loss))
            # Save generator every 500 epochs
#            if epoch % 500 == 0:
#                self.save_model(epoch)


# This file is where the detection of objects inside of an image occurs.

if __name__ == "__main__":
    print("You're running the wrong file. Please run main.py instead.")
    exit()

import torch
from torch import nn
from torchvision.transforms import transforms
import cv2

class Net(nn.Module):
    def __init__(self):
        super(Net, self).__init__()
        self.main = nn.Sequential(
            nn.Conv2d(3, 64, 4, 2, 1, bias=False),
            nn.LeakyReLU(0.2, True),
            nn.Conv2d(64, 128, 4, 2, 1, bias=False),
            nn.LeakyReLU(0.2, True),
            nn.MaxPool2d(2, 2),
            nn.Conv2d(128, 256, 4, 2, 1, bias=False),
            nn.LeakyReLU(0.2, True),
            nn.MaxPool2d(2, 2),
            nn.Conv2d(256, 512, 4, 2, 1, bias=False),
            nn.LeakyReLU(0.2, True),
            nn.MaxPool2d(2, 2),
            nn.Flatten(),
            nn.Linear(2048, 1024),
            nn.LeakyReLU(0.2, True),
            nn.Linear(1024, 601),
            nn.Sigmoid()
        )

    def forward(self, x):
        return self.main(x)

'''
def detect(imagePath):
    tags = [
        "placeholder"
    ]
    model = train.Net()
    model.load_state_dict(torch.load("weights.pth"))
    model.eval()
    return tags[model(PIL.Image.open(imagePath).convert())]
'''

THRESHOLD = 0.5
MAX_TAGS = 20

def detect(imagePath, eventQueue):
    with open("tags.txt") as f:
        tags = f.read().split("\n")
    model = Net()
    model.load_state_dict(torch.load("weights.pth", "cpu")["model"])
    model.eval()
    estimate = model(transforms.F.to_tensor(cv2.resize(cv2.imread(imagePath, cv2.IMREAD_COLOR), (256, 256))).view((1, 3, 256, 256)).float())
    # tags = model(PIL.Image.open(imagePath))
    output = []
    for i, e in enumerate(estimate[0]):
        if e > THRESHOLD:
            output.append((tags[i], round(e.item(), 3) * 100))
    output.sort(key=lambda a: str(a[1]) + a[0], reverse=True)
    print(estimate)
    eventQueue.append(("detect finished", {"tags": output[:MAX_TAGS]}))