import os
import re
import struct
import numpy as np
import pandas as pd
import h5py
import netCDF4
import xarray as xr
import geopy.distance
import matplotlib
import matplotlib.pyplot as plt
from mpl_toolkits import mplot3d
# import horizon as hor
from topocalc.viewf import viewf, gradient_d8
import pickle
from geospatialtools import gdal_tools
# import tensorflow as tf
import demfuncs as dem
import tilefuncs as til
import string
from sklearn.linear_model import LinearRegression
from scipy.stats import gaussian_kde

import matplotlib
matplotlib.use('Agg')
# matplotlib.use('Qt5Agg') # dyn show plots

dem.matplotlib_update_settings()

# scenarios = ['10', '25', '100'] # number of HRUs in each simulation
# scenarios = ['100'] # number of HRUs in each simulation
# scenarios = ['sia10', 'sia25', 'sia100'] # ONLY cos(sia) used in the clustering
# scenarios = ['notnorm10', 'notnorm25', 'notnorm100'] # ONLY cos(sia) used in the clustering

datadir_all = os.path.join('..', '..', '..', 'Documents', 'res_hmc_light_p4')

DOMAINS = ['EastAlps']
# DOMAINS = ['EastAlps', 'Peru', 'Nepal']
ndomains = len(DOMAINS)

NHILLS = np.array([10])
# NHILLS = np.array([2, 5])
nnhills = len(NHILLS)
# nhills = [50]

# TERRVARS = []
# nterrvars = len(TERRVARS)

res_all = []

cosz = 0.7
adir = 0.5
phi = np.pi / 2
# flux_term = 'fdir'
do_averaging = False
aveblock = 55

all_res = []

# outfigdir = os.path.join(datadir, 'outfigdir')
# outdir = os.path.join(datadir, 'output')
outfigdir = os.path.join('//', 'home', 'enrico', 'Documents',
                       'dem_datasets', 'outfigdir')

read_data = True

if read_data:
    for ido, mydomain in enumerate(DOMAINS):
        for inh, mynhills in enumerate(NHILLS):

            datadir = os.path.join(datadir_all, 'res_{}_{}'.format(mydomain, mynhills))
            # datadir = os.path.join('..', '..', '..', 'Documents',
            #                        'res_{}'.format(mydomain),
            #                        'res_{}_light'.format(mydomain))

            modeldir = os.path.join('//', 'home', 'enrico', 'Documents',
                                       'dem_datasets', 'trained_models',
                                        'domain_EastAlps_buffer_0.1',
                                       'models_ave_{}'.format(aveblock),
                                       )

            res = til.read_tile_properties(datadir=datadir,
                                 do_averaging=do_averaging,
                                 aveblock= aveblock,
                                 cosz = cosz, phi = phi, adir=adir,
                                 modeldir=modeldir)
            all_res.append(res)

X, Y = np.meshgrid(all_res[0]['xlon_ea'], all_res[0]['ylat_ea']) # coords equal area in latlon
Xl, Yl = np.meshgrid(all_res[0]['xlon_latlon'], all_res[0]['ylat_latlon']) # coords equal area in latlon

matplotlib.use('Qt5Agg') # dyn show plots
hrus = res['mappedtile_hrus'].copy()
hrus[hrus < 0] = 0

Ct = res['map_tcf']
Vd = res['map_svf']

SS = res['map_sinssina']
SC = res['map_sinscosa']

zmap = res['map_ele']

# do this for elev, all terrain variables, hrus
X1 = X[      100:500,       -500:-100]
Y1 = Y[      100:500,       -500:-100]
hrus = hrus[100:500,       -500:-100]
SS = SS[      100:500,       -500:-100]
SC = SC[      100:500,       -500:-100]
Ct = Ct[      100:500,       -500:-100]
Vd = Vd[      100:500,       -500:-100]

zmap = zmap[      100:500,       -500:-100]

plt.figure(figsize=(5.5, 5))
cm0 = plt.pcolormesh(X1, Y1, hrus, cmap='Pastel1')
plt.ylabel('Latitude [N]')
plt.xlabel('Longitude [E]')
cbar0 = plt.colorbar(cm0)
plt.tight_layout()
# plt.title('tiles')
cbar0.set_label('Tiles')
plt.savefig(os.path.join(outfigdir, 'pastel_tiles_k_{}.png'.format(NHILLS[0])), dpi=100)
plt.show()

plt.figure(figsize=(5.5, 5))
cm0 = plt.pcolormesh(X1, Y1, zmap, cmap='terrain')
plt.ylabel('Latitude [N]')
plt.xlabel('Longitude [E]')
cbar0 = plt.colorbar(cm0)
cbar0.set_label('Elevation [m m.s.l.]')
plt.tight_layout()
plt.savefig(os.path.join(outfigdir, 'zmap_tiles_k_{}.png'.format(NHILLS[0])), dpi=100)
plt.show()

qmin = 0.02
qmax = 0.98
fig, axes = plt.subplots(nrows=2, ncols=2, figsize = (12, 10))

vmin = np.quantile(Ct, qmin)
vmax = np.quantile(Ct, qmax)
cm0 = axes[0,0].pcolormesh(X1, Y1, Ct, cmap='jet', vmin = vmin, vmax = vmax)
cbar0 = fig.colorbar(cm0, ax=axes[0,0], extend='both')
cbar0.set_label(r'$C_t$')

vmin = np.quantile(Vd, qmin)
vmax = np.quantile(Vd, qmax)
cm1 = axes[1,0].pcolormesh(X1, Y1, Vd, cmap='jet', vmin = vmin, vmax = vmax)
cbar1 = fig.colorbar(cm1, ax=axes[1,0], extend='both')
cbar1.set_label(r'$V_d$')

vmin = np.quantile(SS, qmin)
vmax = np.quantile(SS, qmax)
cm2 = axes[0,1].pcolormesh(X1, Y1, SS, cmap='jet', vmin = vmin, vmax = vmax)
cbar2 = fig.colorbar(cm2, ax=axes[0,1], extend='both')
cbar2.set_label(r'$\sin(\theta_s) \sin (\phi_s)$')

vmin = np.quantile(SC, qmin)
vmax = np.quantile(SC, qmax)
cm3 = axes[1,1].pcolormesh(X1, Y1, SC, cmap='jet', vmin = vmin, vmax = vmax)
cbar3 = fig.colorbar(cm3, ax=axes[1,1], extend='both')
cbar3.set_label(r'$\sin(\theta_s) \cos (\phi_s)$')

for i in range(2):
    for j in range(2):
        if j == 0:
            axes[i,j].set_ylabel('Latitude [N]')
        if i == 1:
            axes[i, j].set_xlabel('Longitude [E]')

plt.tight_layout()
plt.savefig(os.path.join(outfigdir, 'terrvars4_tiles_k_{}.png'.format(NHILLS[0])), dpi=100)
plt.show()

TILES = np.unique(hrus)

# TILES = np.array([til for til in list(TILES) if til in [5, 10, 15, 20, 25, 30, 35]])
# TILES = np.array([til for til in list(TILES) if til in [5, 10, 15, 20, 25, 30, 35]])
# TILES = np.flipud(np.unique(hrus))
ntiles = len(TILES)
colors = plt.cm.jet(np.linspace(0,1,ntiles))# Initialize holder for tiles
alphas = np.linspace(0.6, 0.1, ntiles)

# plt.figure()
fig, axes = plt.subplots(nrows=2, ncols=1, figsize=(5, 10))
for it, tile in enumerate(TILES):

    myct = Ct[hrus == tile]
    myvd = Vd[hrus == tile]
    myss = SS[hrus == tile]
    mysc = SC[hrus == tile]
    axes[0].scatter(myvd, mysc, marker='o', color = colors[it], alpha = alphas[it])
    axes[1].scatter(myct, myss, marker='o', color = colors[it], alpha = alphas[it])

axes[0].set_xlabel(r'$V_d$')
axes[0].set_ylabel(r'$\sin(\theta_s) \cos (\phi_s)$')
axes[1].set_xlabel(r'$C_t$')
axes[1].set_ylabel(r'$\sin(\theta_s) \sin (\phi_s)$')
plt.tight_layout()
plt.savefig(os.path.join(outfigdir, 'scatter_tiles_k_{}.png'.format(NHILLS[0])), dpi=100)
plt.show()

#
# plt.figure()
# for it, tile in enumerate(TILES):
#
#     myct = Ct[hrus == tile]
#     myvd = Vd[hrus == tile]
#     myss = SS[hrus == tile]
#     mysc = SC[hrus == tile]
#
#     # plt.plot(mysc, myss, 'o', color = colors[it])
#     plt.scatter(myct, mysc, marker='o', color = colors[it], alpha=alphas[it])
#
# # plt.xscale('log')
# # plt.xscale('log')
# plt.xlabel(r'$C_t$')
# plt.ylabel(r'$\sin(\theta_s) \sin (\phi_s)$')
# plt.savefig(os.path.join(outfigdir, 'scatter_tiles_2.png'), dpi=100)
# plt.show()
#


from lib_py.room import Room
from lib_py.entity import Entity
from lib_py.camera import OrthoCamera
from lib_py.runner import CollisionEngine, CollisionResponse, Scheduler, DynamicWorld
import physics.vars as var
import example

def f (player : example.Wrap1, item : example.Wrap1, x, y):
    item.setColor ([0, 0, 0, 0], [255, 0, 0, 255])
    print ('ciao')

def g (player : example.Wrap1, item : example.Wrap1, x, y):
    item.setColor ([255, 255, 255, 255], [0, 0, 0, 0])
    print ('ciao')

class Phy2DRoom(Room):
    def __init__(self, id:str, width, height, worldWidth: int, worldHeight : int):
        super().__init__(id, width, height)
        # adding pause button
        #self.keyl.addKey(key=32, func = f)
        #self.keyl.addKey(key=264, func = checkWarp)

        main = Entity (tag='main')
        main.camera = OrthoCamera(
            worldwidth = worldWidth,
            worldheight = worldHeight,
            camwidth = width,
            camheight = height,
            viewport = [0, 0, width, height],
            tag='maincam')
        self.add(main)

        # create the collision engine (maybe to put into the ctor of the room subclass)
        ce = CollisionEngine(80, 80)
        ce.addResponse (var.Tags.player, var.Tags.wall, CollisionResponse(onenter=f, onleave=g))
        self.addRunner(ce)
        self.addRunner(Scheduler())


from typing import List, Optional

try:
    from typing import TypedDict
except:
    from typing_extensions import TypedDict

import torch
import numpy as np

from utils import tensor

class Transition(TypedDict):
    state: torch.Tensor
    policy: torch.Tensor
    action: int
    reward: float
    new_state: torch.Tensor

def zero_transition(t: Transition):
    result = Transition(
                state=tensor(torch.zeros(t['state'].shape)),
                policy=tensor(torch.ones(t['policy'].shape)/t['policy'].shape[0]),
                action=tensor(0).long(),
                reward=tensor(0.),
                new_state=tensor(torch.zeros(t['new_state'].shape)))

    return result

class ReplayMemory:

    def __init__(self, max_size):
        self.episodes = []
        self.episode_lengths = []
        self.max_size = max_size

    def sample(self, n_samples=1, sample_length=1):
        p = np.array(self.episode_lengths)/sum(self.episode_lengths)
        sample_idx = np.random.choice(len(self.episodes), size=n_samples, p=p)
        sample_episodes = [self.episodes[i] for i in sample_idx]

        zero_transitions = [zero_transition(sample_episodes[0][0]) for _ in range(sample_length)]

        sample_trajectories = []
        for ep in sample_episodes:
            j = np.random.choice(len(ep))
            end_of_sample = min(len(ep), j+sample_length)
            n_zero_transitions = max(0, j+sample_length-len(ep))
            trajectory = ep[j:end_of_sample]+zero_transitions[0:n_zero_transitions]
            sample_trajectories.append(trajectory)
            assert len(trajectory) == sample_length

        assert len(sample_trajectories) == n_samples

        return sample_trajectories

    def append(self, episode: List[Transition]):
        self.episodes.append(episode)
        self.episode_lengths.append(len(episode))

        while sum(self.episode_lengths) > self.max_size:
            self.episodes.pop(0)
            self.episode_lengths.pop(0)

    def extend(self, *episodes: List[List[Transition]]):
        for episode in episodes:
            self.append(episode)

    def __len__(self):
        return sum(self.episode_lengths)


#!/usr/bin/env python3
#-*- coding: utf-8 -*-

import numpy as np
import matplotlib.pyplot as plt
from functools import partial
from tqdm import tqdm
import h5py
import sys
import os

from hdflow import *
from pgan.data import Data
from models import *
from utilities import *

usage = """
Usage: train_joint.py config.cfg
"""

def main(pars):

    # Make data objects
    _, data, norms = make_data(
        physics_batch_size=pars.train.batch_size, Np=1200
    )

    # Load full x-coordinate array so that VGP can compute spatial extents
    with h5py.File('data_noise.h5', 'r') as fid:
        xn_ref = norms['x'](fid['x'][()])

    # Make models
    mean_net = MeanNetwork(norms, resnet=pars.pretrain.resnet)
    vgp = create_vgp(xn_ref, pars.prior.num_inducing_x, norms,
                     trainable_obs_variance=pars.likelihood.trainable_obs_variance)

    # Create optimizer
    optimizer = create_optimizer(pars.pretrain.optimizer, learning_rate=pars.train.lr)

    # Load pretrained solution
    if not pars.train.restore:
        print('Loading pretrain weights from', pars.train.meannet_checkdir)
        create_checkpoint_manager(
            pars.train.meannet_checkdir,
            mean_net=mean_net,
            restore=True
        )

    # Create checkpoint manager for all models
    print('Checkpoint directory:', pars.train.checkdir)
    print('Restore:', pars.train.restore)
    ckpt_manager = create_checkpoint_manager(
        pars.train.checkdir,
        mean_net=mean_net,
        vgp=vgp,
        optimizer=optimizer,
        restore=pars.train.restore
    )

    # Initialize Gauss-Hermite quadrature sample points and weights
    quadrature_size = 3
    grid, weights = np.polynomial.hermite.hermgauss(quadrature_size)
    grid = grid.astype(np.float64)
    weights = tf.convert_to_tensor(weights.astype(np.float64), dtype=DTYPE)
    grid = tf.convert_to_tensor(grid, dtype=DTYPE)

    # Pre-construct some constants
    KL_SCALE = tf.constant(pars.prior.kl, dtype=DTYPE)
    PROB_SCALE = tf.constant(pars.train.prob_scale, dtype=DTYPE)
    TB_STD = tf.constant(pars.likelihood.std, dtype=DTYPE)
    n_exp = tf.constant(pars.prior.n_exp, dtype=DTYPE)

    # Define joint function
    @tf.function
    def loss_function(batch_physics):

        Nb = tf.cast(tf.shape(batch_physics.x)[0], dtype=DTYPE)

        # Run forward model to get drag residuals
        log_likely, index_points, _ = _forward_model(
            mean_net, vgp, n_exp, batch_physics.x, grid, weights, TB_STD
        )
        nll = -1 * log_likely

        # Construct prior at inducing points
        xn_inducing = vgp.inducing_index_points
        x_inducing = norms['x'].inverse(xn_inducing)
        prior = distance_prior(x_inducing, pars.prior.l_scale,
                               prior_std=pars.prior.std)

        # Variational mean and covariance at inducing points
        C_post = vgp.covariance(index_points=xn_inducing)
        θ_mean = vgp.mean(index_points=xn_inducing)
        post = tfd.MultivariateNormalTriL(θ_mean, tf.linalg.cholesky(C_post))

        # Compute (reverse) KL divergence
        kl = KL_SCALE / Nb * tfd.kl_divergence(post, prior)

        # Done
        return [PROB_SCALE * nll, PROB_SCALE * kl]

    # JIT and evaluate loss function in order to get access to trainable variables
    batch = data.train_batch()
    lv = loss_function(batch)
    trainable_variables = list(vgp.trainable_variables)
    print('\nTrainable variables:')
    for v in trainable_variables:
        print(v.name, v.shape)
    print('')

    # Run optimization
    train_vals, test_vals = train(
        trainable_variables, loss_function, data, optimizer, ckpt_manager,
        n_epochs=pars.train.n_epochs, clip=5, logfile=pars.train.logfile, ckpt_skip=5
    )

def _forward_model(mean_net, vgp, n_exp, x, grid, weights, Tb_std):
    """
    Computes basal drag residual negative log-likelihood. Uses the 1D SSA momentum balance
    for a laterally-confined ice shelf with a rectangular cross-section.
    """
    # Physical constants
    rho_ice = tf.constant(917.0, dtype=DTYPE)
    rho_water = tf.constant(1024.0, dtype=DTYPE)
    g = tf.constant(9.80665, dtype=DTYPE)
    ε_0 = tf.constant(1.0e-5, dtype=DTYPE)
    B0 = tf.constant(400.0, dtype=DTYPE)
    W = tf.constant(30.0e3, dtype=DTYPE)
    Nb = tf.shape(x)[0]

    # Predict surface variables and un-normalize
    u, h = mean_net(x, inverse_norm=True)

    # Compute spatial gradients
    u_x = tf.gradients(u, x)[0]
    h_x = tf.gradients(h, x)[0]
    absu = tf.math.abs(u)
    usign = u / absu
    strain = tf.abs(u_x) + ε_0

    # Driving stress (kPa units)
    s_x = h_x * (1 - rho_ice / rho_water)
    Td = -1.0e-3 * rho_ice * g * h * s_x

    # Normalized index points
    Xn = normalize_tensor(x, mean_net.iW_in, mean_net.b_in, pos=True)

    # Pre-construct likelihood arrays
    Tb_loc = tf.zeros((Nb, 1), dtype=DTYPE)
    Tb_scale = Tb_std * tf.ones((Nb, 1), dtype=DTYPE)

    # Generate θ values using quadrature grid
    qf_loc = vgp.mean(index_points=Xn)
    qf_scale = vgp.stddev(index_points=Xn)
    qf_loc = _maybe_expand_dims_neg2(qf_loc)
    qf_scale = _maybe_expand_dims_neg2(qf_scale)
    weighted_ll = 0.0
    for i in range(3):

        # Compute θ at current quadrature grid point
        θ = np.sqrt(2.0) * qf_scale * grid[i] + qf_loc

        # Compute fluidity
        B = B0 * tf.exp(θ)

        # Effective viscosity
        eta = 0.5 * B * strain**((1.0 - n_exp) / n_exp)

        # Membrane stress
        Tm = 4 * tf.gradients(eta * h * u_x, x)[0]

        # Lateral drag
        Tl = 2 * usign * h / W * B * (5 * absu / W)**(1.0 / n_exp)

        # Drag residual
        Tb = Tm - Tl + Td

        # Compute weighted log-likelihood
        log_probs = tfd.Normal(loc=Tb_loc, scale=Tb_scale).log_prob(Tb)
        weighted_ll += weights[i] * tf.reduce_mean(log_probs)

    return weighted_ll, Xn, tf.squeeze(qf_loc)

def _maybe_expand_dims_neg2(a):
    """Inject a `1` into the shape of `a` only if `a` is non-scalar.
    Also handles the dynamic shape case.
    Args:
      a: a `Tensor`.
    Returns:
      maybe_expanded: a `Tensor` whose shape is unchanged if `a` was scalar,
      or, if `a` had shape `[..., A, B]`, a new `Tensor` which is the same as
      `a` but with shape `[..., A, 1, B]`.
    """
    if tf.TensorShape(a.shape).rank == 0:
        return a
    if tf.TensorShape(a.shape).rank is not None:
        return a[..., tf.newaxis]
    return tf.cond(tf.equal(tf.rank(a), 0),
                   lambda: a,
                   lambda: a[..., tf.newaxis])

if __name__ == '__main__':
    args = sys.argv[1:]
    if len(args) != 1:
        print(usage)
        sys.exit()
    pars = ParameterClass(args[0])
    main(pars)

# end of file


import time
from socket import *  # pylint: disable=wildcard-import

import net_test
import multinetwork_base
import packets

# TCP states. See include/net/tcp_states.h.
TCP_ESTABLISHED = 1
TCP_SYN_SENT = 2
TCP_SYN_RECV = 3
TCP_FIN_WAIT1 = 4
TCP_FIN_WAIT2 = 5
TCP_TIME_WAIT = 6
TCP_CLOSE = 7
TCP_CLOSE_WAIT = 8
TCP_LAST_ACK = 9
TCP_LISTEN = 10
TCP_CLOSING = 11
TCP_NEW_SYN_RECV = 12

TCP_NOT_YET_ACCEPTED = -1

class TcpBaseTest(multinetwork_base.MultiNetworkBaseTest):

  def tearDown(self):
    if hasattr(self, "s"):
      self.s.close()
    super(TcpBaseTest, self).tearDown()

  def OpenListenSocket(self, version, netid):
    self.port = packets.RandomPort()
    family = {4: AF_INET, 5: AF_INET6, 6: AF_INET6}[version]
    address = {4: "0.0.0.0", 5: "::", 6: "::"}[version]
    s = net_test.Socket(family, SOCK_STREAM, IPPROTO_TCP)
    s.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1)
    s.bind((address, self.port))
    # We haven't configured inbound iptables marking, so bind explicitly.
    self.SelectInterface(s, netid, "mark")
    s.listen(100)
    return s

  def _ReceiveAndExpectResponse(self, netid, packet, reply, msg):
    pkt = super(TcpBaseTest, self)._ReceiveAndExpectResponse(netid, packet,
                                                             reply, msg)
    self.last_packet = pkt
    return pkt

  def ReceivePacketOn(self, netid, packet):
    super(TcpBaseTest, self).ReceivePacketOn(netid, packet)
    self.last_packet = packet

  def RstPacket(self):
    return packets.RST(self.version, self.myaddr, self.remoteaddr,
                       self.last_packet)

  def IncomingConnection(self, version, end_state, netid):
    self.s = self.OpenListenSocket(version, netid)
    self.end_state = end_state

    remoteaddr = self.remoteaddr = self.GetRemoteAddress(version)
    myaddr = self.myaddr = self.MyAddress(version, netid)

    if version == 5: version = 4
    self.version = version

    if end_state == TCP_LISTEN:
      return

    desc, syn = packets.SYN(self.port, version, remoteaddr, myaddr)
    synack_desc, synack = packets.SYNACK(version, myaddr, remoteaddr, syn)
    msg = "Received %s, expected to see reply %s" % (desc, synack_desc)
    reply = self._ReceiveAndExpectResponse(netid, syn, synack, msg)
    if end_state == TCP_SYN_RECV:
      return

    establishing_ack = packets.ACK(version, remoteaddr, myaddr, reply)[1]
    self.ReceivePacketOn(netid, establishing_ack)

    if end_state == TCP_NOT_YET_ACCEPTED:
      return

    self.accepted, _ = self.s.accept()
    net_test.DisableLinger(self.accepted)

    if end_state == TCP_ESTABLISHED:
      return

    desc, data = packets.ACK(version, myaddr, remoteaddr, establishing_ack,
                             payload=net_test.UDP_PAYLOAD)
    self.accepted.send(net_test.UDP_PAYLOAD)
    self.ExpectPacketOn(netid, msg + ": expecting %s" % desc, data)

    desc, fin = packets.FIN(version, remoteaddr, myaddr, data)
    fin = packets._GetIpLayer(version)(str(fin))
    ack_desc, ack = packets.ACK(version, myaddr, remoteaddr, fin)
    msg = "Received %s, expected to see reply %s" % (desc, ack_desc)

    # TODO: Why can't we use this?
    #   self._ReceiveAndExpectResponse(netid, fin, ack, msg)
    self.ReceivePacketOn(netid, fin)
    time.sleep(0.1)
    self.ExpectPacketOn(netid, msg + ": expecting %s" % ack_desc, ack)
    if end_state == TCP_CLOSE_WAIT:
      return

    raise ValueError("Invalid TCP state %d specified" % end_state)


import numpy as np
import collections

def canlinski_harabasz_index(data,label):
    # 不同的label
    y_label = [i for i in list(collections.Counter(label).values())]
    # label数量
    n_label = len(y_label)
    # 初始化簇间,簇内协方差的值
    bk_tr,wk_tr = 0.0,0.0
    # 全局平均值
    mean = np.mean(data,axis=0)
    # 样本数量
    num = data.shape[0]
    for i in range(n_label):
        # 当前分类的样本
        current_clust = data[label == i]
        # 当前簇中心
        clust_mean = np.mean(current_clust,axis=0)
        # 簇间协方差计算
        bk_tr += len(current_clust) * np.sum((clust_mean-mean) ** 2)
        # 簇内协方差计算
        wk_tr += np.sum((current_clust-clust_mean) ** 2)
    # CHI计算
    s = (bk_tr * (num-n_label)) / (wk_tr * (n_label-1))
    return s


#!/usr/bin/env python

# Used to nicely plot data from the `log` folder

import numpy as np
import matplotlib.pyplot as plt
import math

FILE = 'log/20170408-14_52_11.csv'

ROLE = 0

data = np.genfromtxt(FILE, delimiter=',', dtype=float)

#data = data[-10000:,:]

print(data.shape)

fig, axarr = plt.subplots(2, 1)

plot1 = axarr[0]
plot2 = axarr[1]

#plt.subplot(211)

off = 6*ROLE

# Target
plot1.plot(data[:, (off+1)], data[:, (off+2)], 'r--')

# Actual
plot1.plot(data[:, (off+4)], data[:, (off+5)], 'b')

#plt.plot(x, magX, 'b')
#plt.plot(x, p(current), 'r--')

plot1.set_ylim(-2, 2)
plot1.set_xlim(-3, 3)

plot1.legend(['Target Position', 'Actual Position'], prop={'size':9})
plot1.set_title('Position (meters)')

plot1.set_aspect('equal', adjustable='box')

#plt.subplot(212)

#plt.show()

e = data[:,(off+1):(off+4)] - data[:, (off+4):(off+7)]

plot2.plot(data[:, 0], e[:, 0], 'r')
plot2.plot(data[:, 0], e[:, 1], 'g')
plot2.plot(data[:, 0], e[:, 2], 'b')

plot2.set_ylim(-0.5, 0.5)
plot2.set_title('Axis Errors (meters)')
plot2.plot([0, data[-1, 0]], [0,0], '--', color='0.75')

plot2.legend(['X', 'Y', 'Z', 'Zero Line'], prop={'size':9})

fig.tight_layout()

plt.show()
#plt.plot(data[:,1:3],)


import random
from logo import logo
import os
os.system('clear')
print(logo)
print("Welcome to the Number Guessing Game!")
print("I'm thinking of a number between 1 and 100.")
num_picked=random.randint(1,100)
print(f"Pssst, the correct answer is {num_picked}")

def easy (user_guess):
        if(user_guess > num_picked):
            print("Too High")
        elif(user_guess < num_picked):
            print("Too Low")
        elif(user_guess == num_picked):
            print(f"You got it! The answer was {user_guess}")
            return 0

def hard (user_guess):
        if(user_guess > num_picked):
            print("Too High")
        elif(user_guess < num_picked):
            print("Too Low")
        elif(user_guess == num_picked):
            print(f"You got it! The answer was {user_guess}")
            return 0

def play():
    diff_level=input("Choose a difficulty. Type 'easy' or 'hard': ").lower()
    if (diff_level == "easy"):
        chances=10
    elif(diff_level == "hard"):
        chances=5
    while chances != 0:
        if (diff_level == "easy"):
            print(f"You have {chances} attempts remaining to guess the number")
            guess_num=int(input("Make a guess: "))
            ret_val=easy(guess_num)
        elif (diff_level == "hard"):
            print(f"You have {chances} attempts remaining to guess the number")
            guess_num=int(input("Make a guess: "))
            ret_val=hard(guess_num)
        if (ret_val == 0):
                chances=0
        else:
            chances=chances-1
            if (chances >= 1):
                print("Guess Again")
    if (ret_val !=0):
        print("You've run out of guesses, you lose.")

play()


import os
import pandas as pd
from glob import glob
from pathlib import Path

# Set folder that script is placed in as current directory
current_dir = os.path.abspath(os.path.dirname(__file__))

# Create folder to house new csv files if folder does not exist
Path('csv_files').mkdir(parents=True, exist_ok=True)

# Bulk convert all sheets in xlsx files into one concatenated csv, be sure sheet headers are identical
for excel_file in glob('*.xlsx'):
    print(excel_file)
    dfs = pd.read_excel(excel_file, sheet_name=None)
    # Strip leading and trailing white spaces to ensure matching column headers
    for sheet_name in dfs:
        dfs[sheet_name].columns = dfs[sheet_name].columns.str.strip()
    df = pd.concat(dfs)
    csv_file = os.path.splitext(excel_file)[0]
    df.to_csv(f'csv_files/{csv_file}_combined.csv', index=None, header=True)


from turtle import Screen, Turtle
from paddle import Paddle
from ball import Ball
from scoreboard import ScoreBoard

import time

screen = Screen()
screen.setup(width=800, height=800)
screen.bgcolor("black")
screen.title("The Pong Game")
screen.tracer(0)

paddles = Paddle()

scoreboard = ScoreBoard()

ball = Ball()
ball.reset_ball()

game_is_on = True

UPLEFT = 135
UPRIGHT = 45
DOWNRIGHT = 315
DOWNLEFT = 225

LEFT = [135,225]
RIGHT = [45,315]

while game_is_on:

    screen.listen()
    screen.onkey(key="Up", fun= paddles.right_up)
    screen.onkey(key="Down", fun= paddles.right_down)
    screen.onkey(key="w", fun= paddles.left_up)
    screen.onkey(key="s", fun= paddles.left_down)

    ball.move_ball()

    ball.ball_heading()

    for paddle in paddles.left_paddle:
        # print(ball.distance(paddle))
        if ball.distance(paddle) < 25 and ball.heading()==UPLEFT:
            ball.setheading(UPRIGHT)
        if ball.distance(paddle) < 25 and ball.heading()==DOWNLEFT:
            ball.setheading(DOWNRIGHT)

    for paddle in paddles.right_paddle:
        # print(ball.distance(paddle))
        if ball.distance(paddle) < 25 and ball.heading()==UPRIGHT:
            ball.setheading(UPLEFT)
        if ball.distance(paddle) < 25 and ball.heading()==DOWNRIGHT:
            ball.setheading(DOWNLEFT)

    if ball.xcor() < -390:
        ball.reset_ball()
        scoreboard.update_right_score()

    if ball.xcor() > 390:
        ball.reset_ball()
        scoreboard.update_left_score()

    if scoreboard.right_score == 10 or scoreboard.left_score == 10:
        scoreboard.game_over()
        game_is_on = False

    screen.update()

    time.sleep(0.01)

screen.exitonclick()


from mxnet.gluon import nn
from mxnet import nd
from mxnet.contrib.ndarray import MultiBoxPrior
from mxnet import gluon

def class_predictor(num_anchors, num_class):
    return nn.Conv2D(num_anchors * (num_class + 1), 3, padding=1)

def box_predictor(num_anchors):
    return nn.Conv2D(num_anchors * 4, 3, padding=1)

def down_sample(num_filters):
    out = nn.HybridSequential()
    for _ in range(2):
        out.add(nn.Conv2D(num_filters, kernel_size=3, padding=1))
        out.add(nn.BatchNorm(in_channels=num_filters))
        out.add(nn.Activation('relu'))
    out.add(nn.MaxPool2D(2))
    out.hybridize()
    return out

def flatten_prediction(pred):
    return nd.flatten(nd.transpose(pred, axes=(0, 2, 3, 1)))

def concat_predictions(preds):
    return nd.concat(*preds, dim=1)

def body():
    out = nn.HybridSequential()
    for nfilters in [16,32,64]:
        out.add(down_sample(nfilters))
    return out

def toy_ssd_model(num_anchors, num_classes):
    downsamples= nn.Sequential()
    class_preds = nn.Sequential()
    box_preds = nn.Sequential()

    downsamples.add(down_sample(128))
    downsamples.add(down_sample(128))
    downsamples.add(down_sample(128))

    for scale in range(5):
        class_preds.add(class_predictor(num_anchors, num_classes))
        box_preds.add(box_predictor(num_anchors))

    return body(), downsamples, class_preds, box_preds

# print(toy_ssd_model(5, 2))

def toy_ssd_forward(x, body, downsamples, class_preds, box_preds, sizes, ratios):
    x = body(x)
    # 在每个预测层, 计算预设框，分类概率，偏移量
    # 然后在下采样到下一层预测层，重复
    default_anchors = []
    predicted_boxes = []
    predicted_classes = []

    for i in range(5):
        default_anchors.append(MultiBoxPrior(x,sizes=sizes[i], ratios=ratios[i]))
        predicted_boxes.append(flatten_prediction(box_preds[i](x)))
        predicted_classes.append(flatten_prediction(class_preds[i](x)))
        if i < 3:
            x = downsamples[i](x)
        elif i == 3:
            # 最后一层可以简单地用全局Pooling
            x = nd.Pooling(x, global_pool=True, pool_type='max', kernel=(4, 4))
    return default_anchors,predicted_classes, predicted_boxes

class ToySSD(gluon.Block):
    def __init__(self,num_class,**kwargs):
        super(ToySSD, self).__init__(**kwargs)
        # 5个预测层，每层负责的预设框尺寸不同，由小到大，符合网络的形状
        self.anchor_sizes = [[.2, .272], [.37, .447], [.54, .619], [.71, .79], [.88, .961]]
        # 每层的预设框都用 1，2，0.5作为长宽比候选
        self.anchor_ratios = [[1, 2, .5]] * 5
        self.num_classes = num_class

        with self.name_scope():
            self.body, self.downsamples, self.class_preds, self.box_preds = toy_ssd_model(4, self.num_classes)

    def forward(self, x):
        default_anchors, predicted_classes, predicted_boxes = toy_ssd_forward(x, self.body, self.downsamples,
                                                                              self.class_preds, self.box_preds,
                                                                              self.anchor_sizes, self.anchor_ratios)

        # 把从每个预测层输入的结果摊平并连接，以确保一一对应
        anchors = concat_predictions(default_anchors)
        box_preds = concat_predictions(predicted_boxes)
        class_preds = concat_predictions(predicted_classes)
        # 改变下形状，为了更方便地计算softmax
        class_preds = nd.reshape(class_preds, shape=(0, -1, self.num_classes + 1))

        return anchors, class_preds, box_preds

# # 新建一个2个正类的SSD网络
# net = ToySSD(2)
# net.initialize()
# x = nd.zeros((1, 3, 256, 256))
# default_anchors, class_predictions, box_predictions = net(x)
# print('Outputs:', 'anchors', default_anchors.shape, 'class prediction', class_predictions.shape, 'box prediction', box_predictions.shape)
# print('ok')


from Deck import Deck

class Layout:
    """ Layout of the game, organizes the cards' placement """
    def __init__(self):
        """ layout is made up of 7 tables, 4 foundations, and 1 pile"""
        self.table1 = []
        self.table2 = []
        self.table3 = []
        self.table4 = []
        self.table5 = []
        self.table6 = []
        self.table7 = []
        self.foundation1 = []
        self.foundation2 = []
        self.foundation3 = []
        self.foundation4 = []
        self.pile = []

    def build_table(self):
        """ places the initial cards in the tables (28 cards) and puts the rest in the pile (24 cards) """
        deckObj = Deck()
        deckObj.build_deck()
        game_deck = deckObj.main_deck

        #moves initial cards to tables
        self.__from_deck_to_table(game_deck, self.table1, 1)
        self.__from_deck_to_table(game_deck, self.table2, 2)
        self.__from_deck_to_table(game_deck, self.table3, 3)
        self.__from_deck_to_table(game_deck, self.table4, 4)
        self.__from_deck_to_table(game_deck, self.table5, 5)
        self.__from_deck_to_table(game_deck, self.table6, 6)
        self.__from_deck_to_table(game_deck, self.table7, 7)

        #adds empty element to foundations
        self.foundation1.append("  ")
        self.foundation2.append("  ")
        self.foundation3.append("  ")
        self.foundation4.append("  ")

        self.pile += game_deck
        game_deck.clear()

    def manage_table(self):
        """ manages an individual table"""
        tables = self.get_tables()
        for table in tables:
            try:
                if not table[-1].face_up:
                    table[-1].change_face()
            except:
                pass

    def manage_foundation(self, foundation):
        """ manages an individual foundation """
        pass

    def manage_pile(self, cmd):
        """ manages the pile """
        #moves card in the front (index -1) to back (index 0)
        if "next card" in cmd:
            self.pile.insert(0, self.pile.pop(-1))
        if "current card" in cmd:
            self.pile[-1].change_face()
            return self.pile[-1].get_card_string()

    @staticmethod
    def __from_deck_to_table(deck, table, amount):
        """ takes a card from the main deck and puts it in an individual table.
            Also flips the last card that was placed in the table to face up  """
        for i in range(amount):
            card = deck[-1]
            deck.remove(card)
            table.append(card)
            i += 1

        table[-1].change_face()

    def translate_cmd(self, cmd):
        #checks if cmd is a table
        if "t" in cmd:
            for i in range(1, 8):
                if str(i) in cmd:
                    return self.get_tables()[i - 1]
        #checks if cmd is a foundation
        if "f" in cmd:
            for i in range(1, 5):
                if str(i) in cmd:
                    return self.get_foundations()[i - 1]
        #checks if cmd is the pile
        if "pile" in cmd:
            return self.pile
        #checks if cmd is a card rank and if so then which
        if "S" in cmd or "s" in cmd or "C" in cmd or "c" in cmd or "D" in cmd or "d" in cmd or "H" in cmd or "h" in cmd:
            rank = ""
            for i in range(1, 14):
                if str(i) in cmd:
                    rank = str(i)
            suit = cmd[1].capitalize()
            return suit + rank

    def get_tables(self):
        """ returns all the tables(1-7) in a list"""
        return [self.table1, self.table2, self.table3, self.table4, self.table5, self.table6, self.table7]

    def get_foundations(self):
        return [self.foundation1, self.foundation2, self.foundation3, self.foundation4]

    def move_card(self, origin, destination):
        origin_card = origin[-1]
        if "K" in origin_card.get_card_string():
            destination.append(origin_card)
            origin.remove(origin_card)
        else:
            destination.append(origin_card)
            origin.remove(origin_card)
        self.manage_table()

    def move_group(self, origin_table, top_card, destination_table):
        top_card_index = origin_table.index(top_card)
        group = origin_table[top_card_index, -1]
        origin_table + group
        for card in group:
            for i in origin_table:
                if i == card:
                    origin_table.remove(origin_table.index(card))
        destination_table + group
        self.manage_table()

layout = Layout()
layout.build_table()


'''Crie um programa que leia o nome de uma cidade e diga se ela começa ou não com o nome "SANTO" '''
import math
# zona de teste
# nome_cidade_inicial = "santos gunari".split()

# Declarando variável
nome_cidade_inicial = input().split()

# Aqui eu pego apenas o indice 0, sendo se for "SANTOS" irá ter como resutlado "True" e "False" não tendo.
apenasSantos = nome_cidade_inicial[0]
aux = apenasSantos.casefold()
semEspaço = aux.strip()
aux2 = "santo" in semEspaço

# Imprimindo o resultado de acordo com a saída desejada.
print(aux2)

# print("{}".format(aux))

Exercícios Curso em vídeo de Python/Nome da cidade.py


from datetime import timedelta
from odoo import api, fields, models

class SaleOrder(models.Model):
    _inherit = 'sale.order'

    @api.multi
    def action_confirm(self):

        # <AndriusD code
        def filter_rests(rec):
            product = rec.product_id
            return product.is_bike and product.type == 'service'

        for line in self.mapped('order_line').filtered(filter_rests):
            line.create_bike_rents()  # /AndriusD code>

        return super(SaleOrder, self).action_confirm()

class SaleOrderLine(models.Model):
    _inherit = 'sale.order.line'

    rent_end_date = fields.Datetime(string='Rent End Date', compute='_compute_rent_end_date')
    bike_rent_id = fields.Many2one('bike.rent', string='Rent ID')

    def create_bike_rents(self):
        for line in self.product_id.rented_bike_ids:
            rent_rec = self.env['bike.rent'].create({
                'notes': self.product_id.description_sale,
                'price': line.lst_price,
                'partner_id': self.order_partner_id.id,
                'bike_id': line.id,
                'rent_time': self.product_id.rent_duration,
                'sale_id': self.order_id.id
            })
            self.bike_rent_id = rent_rec.id

    @api.multi
    def _compute_rent_end_date(self):
        for line in self.filtered(lambda x: x.product_id.type == 'service' and x.product_id.is_bike):
            if line.bike_rent_id.rent_stop:
                line.rent_end_date = line.bike_rent_id.rent_stop
            else:
                line.rent_end_date = fields.Datetime.now() + timedelta(days=line.product_id.rent_duration)


from __future__ import annotations
from Elements.Pieces.Pieces import Pieces
from Elements.Player import Player
from Elements.Board import Board
from config import config
import threading

class Game:

    """Classe de gestion des parties de jeu blokus
    """
    def __init__(self : Game, joueurs : list[Player]|None,plateau : Board|None,taille : int,online : bool = False) -> None:
        """Constructeur créant une partie avec des joueurs et un plateau de taille n

        Args:
            self (Game): game
            joueurs (list[Player] | None): liste de joueurs ou rien
            plateau (Board | None): plateau de jeu ou rien
            taille (int): taille du plateau de jeu
        """
        self.__joueurs : list[Player] = joueurs or [Player(11,"matthieu"),Player(12,"aurelian"),Player(13,"gauthier"),Player(14,"inconnu")]
        self.__joueursAbandon : list[Player] = []
        self.__online : bool = online
        self.__currentPlayerPos : int = -1
        if self.__online:
            self.__currentPlayerPos : int = 0
        self.__plateau : Board = plateau or Board(taille)
        self.__enCours = True

        for pj in self.__joueurs:
            pj.resetPiece()

    def enCours(self) -> bool:
        return self.__enCours

    def end(self):
        self.__enCours=False

    def start(self):
        threading.Timer(0.5,self.__nextPlayer).start()

    def getNextPlayer(self : Game, nbPlayer : int) -> int:
        """Méthode qui permet de récuperer l'id du joueur suivant

        Args:
            self (Game): Game
            nbPlayer : id du joueur current

        Returns:
            int: id du joueur suivant
        """
        pos = (nbPlayer+1)%len(self.__joueurs)
        while  self.__joueurs[pos] in self.__joueursAbandon and len(self.__joueursAbandon) != len(self.__joueurs):
            pos = (pos+1)%len(self.__joueurs)
        if len(self.__joueursAbandon) != len(self.__joueurs):
            return pos
        else:
            return -1

    def getPlayers(self : Game) -> list[Player]:
        """Méthode getter permettant d'avoir la liste contenant les joueurs dans le jeu

        Args:
            self (Game): game

        Returns:
            list[Player]: liste contenant les joueurs de la partie
        """
        return self.__joueurs

    def setPlayers(self : Game, list : list[Player]):
        self.__joueurs : list[Player] = list

    def getCurrentPlayer(self : Game) -> Player:
        """Méthode getter permettant d'avoir la liste contenant les joueurs dans le jeu

        Args:
            self (Game): game

        Returns:
            list[Player]: liste contenant les joueurs de la partie
        """
        return self.__joueurs[self.__currentPlayerPos]

    def getBoard(self : Game) -> Board:
        """Méthode getter permettant d'obtenir le plateau du jeu

        Args:
            self (Game): game

        Returns:
            Board: plateau du jeu
        """
        return self.__plateau

    def getCurrentPlayerId(self : Game) -> int:
        """Méthode getter permettant d'obtenir l'id du joueur courant

        Args:
            self (Game): Game

        Returns:
            int: l'id du joueur courant
        """
        return self.__currentPlayerPos

    def getCurrentPlayers(self : Game) -> list[Player]:
        """Méthode getter petmettant d'obtenir la liste des joueurs
        encore actuellement dans la partie.

        Args:
            self (Game): Game

        Returns:
            list: La liste des joueurs encore dans la partie
        """
        tableau = []
        for joueur in self.getPlayers():
            if joueur not in self.__joueursAbandon:
                tableau.append(joueur)
        return tableau

    def addSurrenderedPlayer(self : Game) -> bool|list[Player]:
        """Méthode qui permet d'ajouter un joueur dans la liste des joueurs qui ont abandonné et de donne le status de la partie
        voir : getWinners()

        Args:
            self (Game): Game

        Returns:
            bool|list[Player]: false si il la game n'est pas terminée sinon retourne la liste des joueurs gagnant
        """
        self.__joueursAbandon.append(self.__joueurs[self.__currentPlayerPos])
        self.__nextPlayer()
        if not self.__online:
            config.Config.controller.updateBoard() #actualise le plateau avec le joueur courant
        if self.getWinners():
            if not self.__online:
                config.Config.controller.vueJeu.changeTextPartie(" ",0)
                config.Config.controller.vueJeu.partieTermine
        return self.getWinners()

    def addSurrenderedPlayerOnline(self: Game, player) -> bool|list[Player]:
        if not self.__online:
            return False
        if player not in self.__joueursAbandon:
            if self.getCurrentPlayer() == player:
                self.addSurrenderedPlayer()
            else:
                self.__joueursAbandon.append(player)
        return self.getWinners()

    def isPlayerSurrendered(self : Game) -> bool:
        """Méthode permettant de savoir si le joueur courant a abandonné

        Args:
            self (Game): Game

        Returns:
            bool: vrai s'il a abandonné sinon faux
        """
        return self.__joueurs[self.__currentPlayerPos] in self.__joueursAbandon

    def getSurrenderedPlayer(self):
        return self.__joueursAbandon

    def __nextPlayer(self : Game) :
        """Méthode qui permet de sélectionné le prochain joueur pour être le joueur courant

        Args:
            self (Game): Game
        """
        self.__currentPlayerPos = (self.__currentPlayerPos+1)%len(self.__joueurs)
        while self.__joueurs[self.__currentPlayerPos] in self.__joueursAbandon and len(self.__joueursAbandon) != len(self.__joueurs):
            self.__currentPlayerPos = (self.__currentPlayerPos+1)%len(self.__joueurs)

        if not self.__online:
            config.Config.controller.updateBoard() #actualise le plateau avec le joueur courant
            if len(self.__joueursAbandon) != len(self.__joueurs):
                config.Config.controller.vueJeu.changeTextPartie("C'est à " + self.__joueurs[self.__currentPlayerPos].getName() + " de jouer",self.__currentPlayerPos)

                if self.getCurrentPlayer().getAI():
                    self.getCurrentPlayer().getAI().play()
                    # except:
                    #     try:
                    #         if config.Config.controller:
                    #             print("controller ici mais partie quitter")
                    #             pass
                    #     except:
                    #         print("plus de controller")
                    #         exit(1)
                return True
            else:
                return False

####################################################################################################################

    def isGameFinished(self : Game) -> bool:
        """Méthode getter qui indique si la partie est terminée ou non en regardant si tout les joueurs sont dans le tableau
        des joueurs qui ont abandonné

        Args:
            self (Game): Game

        Returns:
            bool: vrai si la partie est fini sinon faux
        """
        return len(self.__joueursAbandon) == len(self.__joueurs)

    def countBlocks(self : Game,joueur : Player) -> int:
        """Méthode permettant d'obtenir le nombre de cubes posés sur la grille de jeu par un joueur

        Args:
            self (Game): Game
            joueur (Player): Joueur de la partie

        Returns:
            int: nombre de cubes posés par le joueur sur la grille de jeu
        """
        counter = 0
        for i in range(self.__plateau.getBoardSize()):
            for y in range(self.__plateau.getBoardSize()):
                if (joueur.getColor() == self.__plateau.getColorAt(i,y)):
                    counter+=1
        return counter

    def getWinners(self : Game) -> list[Player]:
        """Méthode permettant de savoir si la partie est fini ou non et d'obtenir les vainqueurs de la partie si fini

        Args:
            self (Game): _description_

        Returns:
            bool|list[Player]: false si il la game n'est pas terminée sinon retourne la liste des joueurs gagnant
        """
        if (len(self.__joueursAbandon) == len(self.__joueurs)):
            blockCount = []
            winners = []
            for joueur in self.__joueurs:
                blockCount.append(self.countBlocks(joueur))
            for i in range(len(blockCount)):
                if blockCount[i] == max(blockCount):
                    winners.append(self.__joueurs[i])
            return winners
        return []

    def getWinnersName(self : Game) -> list[str]:
        winners = self.getWinners()
        new = []
        if winners:
            for player in winners:
                new.append(player.getName())
            return new
        return False

    def playTurn(self : Game, piece : Pieces , colonne : int, ligne : int, dc : int, dl : int, rotation = None,flip = None) -> bool:
        """Méthode qui permet de jouer le tour du joueur courant

        Args:
            - piece : Pieces -> pièce jouée
            - joueur : Player -> joueur de la pièce
            - colonne : int -> colonne du premier cube de la piece
            - ligne : int -> ligne du premier cube de la piece
            - dc : int -> décalage entre la colonne du premier cube de la piece et celle de l'origine de la piece.
            - dl : int -> décalage entre la ligne du premier cube de la piece et celle de l'origine de la piece.

        Returns:
            - bool: vrai si la pièce est ajouter sur le plateau,sinon faux
        """
        if self.__online:
            if len(self.__joueursAbandon) != len(self.__joueurs):
                if(rotation or flip):
                    piece = piece.ajoutRotationFlip(rotation,flip)
                ajout= self.__plateau.ajouterPiece(piece,int(colonne),int(ligne),self.getCurrentPlayer(),int(dc),int(dl))
                if ajout: # si une pièce peut être ajouter
                    self.getCurrentPlayer().removePiece(str(piece.getIdentifiant()))
                    self.getCurrentPlayer().ajoutTour()

                    if (len(self.getCurrentPlayer().getPieces()) == 0): # si un joueur a fini
                        self.addSurrenderedPlayer()
                    else:
                        self.__nextPlayer()
                    # prep tour suivant

                    # config.Config.controller.updatePlayers(self.getCurrentPlayer())

                    return True
                return False

            else:
                # call fonction winner
                return False
        else:

            if len(self.__joueursAbandon) != len(self.__joueurs):

                ajout= self.__plateau.ajouterPiece(piece,int(colonne),int(ligne),self.getCurrentPlayer(),int(dc),int(dl))
                if ajout: # si une pièce peut être ajouter
                    self.getCurrentPlayer().removePiece(str(piece.getIdentifiant()))
                    config.Config.controller.vueJeu.removePiece(self.__currentPlayerPos,piece.getIdentifiant())
                    self.getCurrentPlayer().ajoutTour()

                    rota = piece.getRotation()
                    flip = piece.getFlip()
                    config.Config.controller.json.append({"num_tour" : config.Config.controller.tour,
                        "joueur" : self.getCurrentPlayerId(),
                        "num_piece" : piece.getIdentifiant(),
                        "position_plateau" : [int(colonne),int(ligne)],
                        "rotation" : rota,
                        "flip" : flip,
                        "decalage" : [int(dc),int(dl)]})
                    config.Config.controller.tour += 1

                    if (len(self.getCurrentPlayer().getPieces()) == 0): # si un joueur a fini
                        self.addSurrenderedPlayer()
                    else:
                        self.__nextPlayer()
                    config.Config.controller.updateBoard()

                    return True
                return False

            else:
                # call fonction winner
                return False


# To make it easier, just view the functions as actual functions. This will make stuff much more clear.

class PersonV1:

    def __init__(self, name, job = None, pay = None): # If the default value, if nothing is parsed in when the class is called, one may equate for instance job = None, in order to set the default value.
        self.name = name
        self.job = job # self.job and job are two different variables that happen to have the same name.
        self.pay = pay

class PersonV2:

    def __init__(self, name, job = None, pay = None): # If the default value, if nothing is parsed in when the class is called, one may equate for instance job = None, in order to set the default value.
        self.name = name
        self.job = job # self.job and job are two different variables that happen to have the same name.
        self.pay = pay

    def lasName(self):
        return self.name.split()[-1] # This is putting it into the class the last name feature

    def giveRaise(self, percent):
        self.pay = int(self.pay * (1+percent)) # This removes the necessity to hardcode the raise below. Programming etiquette.

if __name__ == "__main__":
    x = PersonV1("Dude", "hello", "world")
    #print(x.job)
    bob = PersonV1("Bob Blah", job ="dev", pay=100000)
    bob.pay *= 1.1  # What is worth noting here is that bob.pay refers to the variable saved in the object Bob,
                    # structured as a class, which shows some interesting potential for data manipulation!
    #print("%.2f" % bob.pay)
    #print(bob.pay)

    sue = PersonV2("Sue Blah", pay = 8888)
    print(sue.pay)
    sue.giveRaise(.5)
    print(sue.pay)
# In print(".2f" % pay) where %.2f refers to 2 decimal point. Intriguing indeed.


# Problem found on internet:
# Given a string s, find the longest palindromic substring in s. You may assume that the maximum length of s is 1000.

# Example:
# Input: "babad"
# Output: "bab"
# Note: "aba" is also a valid answer

# Input: "cbbd"
# Output: "bb"

def findPal(s):
  length = len(s)
  for i in range(length):
    if (s[i] != s[length - 1 - i]):
      return False
  return True

s = 'abbba'
print(s + " is a palinedrome = " + str(findPal(s)))

def findPalSubs(s):
  length = len(s)
  listOfPalSubs = []
  for i in range(length):
    for j in range(i + 1, length + 1):
      if findPal(s[i:j]):
        listOfPalSubs.append(s[i:j])
  longestPalSub = ''
  maxLength = 0
  for palSub in listOfPalSubs:
    if len(palSub) > maxLength:
      longestPalSub = palSub
      maxLength = len(palSub)

  return longestPalSub
s = 'abba'
print(findPalSubs(s))
s = 'babad'
print(findPalSubs(s))
s = 'cbbd'
print(findPalSubs(s))
s = 'referannaracecar'
print(findPalSubs(s))

## Thoughts
# A palinedrom is defined by a string where it reads the same backwards as forwards.
# First, figure out how to find a palinedrome
# Loop through string upto len(s)/2, check the opposite character and see if it matches

# Second, figure out how to get a list of palinedromes in a given string.
# A brute force solution would be to try run a nested loop and pass in s[i:j]


#!/bin/env python3
# coding:  utf8

# 转换k8s的context文件
# config  --> json (有改写)

import pprint
import yaml
import json
import os

yaml_file=os.path.join(os.path.expanduser('~'),'.kube/config')

yaml_f=open(yaml_file)
configs=yaml.load(yaml_f,Loader=yaml.FullLoader)

clusters=configs['clusters']
contexts=configs['contexts']
users=configs['users']

contexts_new=[]
for context in contexts:
    c={}
    c["name"]=context["name"]
    c["cluster"]={}
    c["user"]={}
    context_cluster_name=context["context"]["cluster"]
    context_user_name=context["context"]["user"]
    for cluster in clusters:
        if cluster["name"] == context_cluster_name:
            c["cluster"].update(cluster["cluster"])
            c["cluster"]["name"]=cluster["name"]
            # print(cluster)
            break
    for user in users:
        if user["name"] == context_user_name:
            c["user"].update(user["user"])
            c["user"]["name"]=user["name"]
            break
    contexts_new.append(c)

# pprint.pprint(contexts_new,indent=4)
print(json.dumps(contexts_new,indent=4))

# output=os.path.join(os.path.expanduser('~'),'.kube/config.json')
# with open(output,'w') as f:
#     json.dump(contexts_new,f,indent=4)


import pandas as pd
import numpy as np

df = pd.read_excel("./Timetable/test_3_v2.xlsx")

writer = pd.ExcelWriter("./Timetable/Cust_course.xlsx")

index_list =[]
#print(df.to_string())

j = 0
for i in range(0, len(df.index)):
    if pd.notnull(df['COURSE TITLE'].iloc[i]) and df.iloc[i, 2] != "Tutorial" and df.iloc[i, 2] != "Practical":
        if i==len(df.index)-1:
            break
        if pd.isnull(df['COURSE TITLE'].iloc[i+1]):
            index_list += [i]
        elif (df.iloc[i+1,2]=="Practical" or df.iloc[i+1,2]=="Tutorial") and pd.isnull(df['COURSE TITLE'].iloc[i+2]):
            index_list+=[i]

        # if i==len(df.index)-1:
        #     index_list += [i]
        #     break
        # while pd.isnull(df['COURSE TITLE'].iloc[i+j+1]) or "Tutorial" == df.iloc[i + j + 1, 2] or df.iloc[i + j + 1, 2] == "Practical":
        #     if df.iloc[i+j+1, 6]=="L2" or df.iloc[i+j+1, 6]=="T2" or df.iloc[i+j+1, 6]=="P2":
        #         index_list += [i]
        #         j=0
        #         break
        #     j+=1
        #     if i+j==len(df.index):
        #         j=0
        #         break

#print(index_list)
j=0
for i in index_list:
    while pd.isnull(df['COURSE TITLE'].iloc[i+j+1]) or df.iloc[i+j+1, 2] == "Tutorial" or df.iloc[i+j+1, 2] == "Practical":
        j+=1
    df1=df.iloc[i:i+j+1,:]
    df1.reset_index()
    j=0
    name1 = str(df.iloc[i,0])
    df1.to_excel(writer, sheet_name=name1)
    writer.save()
    print(df1.to_string())
writer.close()


import logging
import adsk.fusion, adsk.core
import sys, os

FACE_ID = 'faceID'
REV_ID = 'revId'
ID = 'id'
DEBUGLEVEL = logging.NOTSET

NORMAL_MODE = 0x0
MINIMAL_MODE = 0x1
MORTISE_ALONG_LONGSIDE_MODE = 0x2
MORTISE_ALONG_SHORTSIDE_MODE = 0x4
FROMTOP_MODE = 0x8

RADIOBUTTONLIST_ID = 'seButtonList'
COMMAND_ID = "scribeEdgeBtn"
EDIT_ID = "scribeEdgeEditBtn"
FEATURE_ID = COMMAND_ID + 'Feature'
NORMAL_ID = 'scribeEdgeNormalId'
MINIMAL_ID = 'scribeEdgeMinimalId'

_app = adsk.core.Application.get()
_ui = _app.userInterface
_design: adsk.fusion.Design = _app.activeProduct
_rootComp = _design.rootComponent

# get parent folder path
_appPath = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))

_customScribeEdgeFeatureDef: adsk.fusion.CustomFeatureDefinition = None


# Exercício Python 109: Modifique as funções que foram criadas no desafio 107 para que elas aceitem um parâmetro a
# mais, informando se o valor retornado por elas vai ser ou não formatado pela função moeda(), desenvolvida no
# desafio 108.

from Exercícios.desafiosfinais.desafio109 import moeda

pr = float(input('Digite um preço: R$ '))
ma = float(input(f'De quantos % será o aumento de {moeda.moeda(pr)}? -> '))
me = float(input(f'De quantos % será a redução de {moeda.moeda(pr)}? -> '))

moeda.resumo(pr, ma, me)

Aula Python - Curso em video/Exercícios/desafiosfinais/desafio109/__init__.py


import os
import re
import sys
import yaml
import json
import atexit
import logging
import argparse
import tempfile
import subprocess
from os import path
from glob import glob
from kubernetes import config, client
from jsonpath_ng import ext as jsonpath_ext

from . import __version__
from . import models, api, utils

class KomposeEx(object):
    def __init__(self, args=None, logger=None):
        self.logger = logger or logging.getLogger(__name__)
        cmd = "kompose-ex" if args else sys.argv[0]
        sys_args = args or sys.argv[1:]
        self.cmd = " ".join([cmd, *sys_args])
        self.args, self.args_unknown = self.parse_args(args=sys_args)
        self.version = __version__.__version__
        self.annotations = {
            "kompose-ex.cmd": self.cmd,
            "kompose-ex.version": self.version
        }
        self.compose = {}

    def recreate_compose(self):
        for service_name, service in self.compose.get("services", {}).items():
            labels = service.get("labels", {})
            labels.update(self.annotations)
            service["labels"] = labels
            controller_type = labels.get("kompose.controller.type", "").lower()
            controller_ex_type = labels.get("kompose-ex.controller.type", "").lower()
            service_ex_type = labels.get("kompose-ex.service.type", "").lower()
            if controller_type and controller_ex_type:
                raise Exception("kompose-ex.controller.type was specified with kompose.controller.type")

            if controller_ex_type == "cronjob" and not labels.get("kompose-ex.cronjob.schedule"):
                raise Exception(
                    "kompose-ex.controller.type 'cronjob' was specified without kompose-ex.cronjob.schedule"
                )

            ports = service.get("ports", []) or service.get("expose", [])
            if service_ex_type == "ingress-nginx" and not ports:
                raise Exception(
                    "kompose-ex.controller.type 'ingress-nginx' was specified without expose or ports"
                )

            udp_ports = False
            for port in ports:
                if port.split("/")[-1].lower() == "udp":
                    udp_ports = True
                    break

            if service_ex_type == "ingress-nginx" and udp_ports:
                raise Exception(
                    "kompose-ex.controller.type 'ingress' was does not support udp ports"
                )

            if controller_ex_type == "cronjob":
                restart = service.get("restart", "no")
                if service.get("restart", "no") not in ["no", "on-failure"]:
                    service["restart"] = "on-failure"
                    self.logger.warning(
                        f"Restart policy '{restart}' in service challenge is not supported, convert it to 'on-failure'"
                    )
                if service.pop("expose", []) + service.pop("ports", []):
                    self.logger.warning(
                        f"Service \"{service_name}\" won't be created because kompose-ex.controller.type is 'cronjob'"
                    )

            expose_tls = labels.get("kompose-ex.service.expose.tls", "false").lower() == "true"
            if expose_tls and not labels.get("kompose.service.expose"):
                raise Exception("kompose-ex.service.expose.tls was specified without kompose.service.expose")

            if expose_tls and not labels.get("kompose.service.expose.tls-secret"):
                labels["kompose.service.expose.tls-secret"] = "null"

        # Recreate compose
        compose_path = tempfile.mktemp(prefix="docker-compose.", suffix=".yml", dir=".")
        with open(compose_path, "w", encoding="UTF-8") as fw:
            yaml.safe_dump(self.compose, stream=fw, indent=self.args.indent, width=0x7fffffff)

        # Delete compose file on exit
        atexit.register(self.destroy, compose_path)
        return compose_path

    def destroy(self, compose_path):
        try:
            os.remove(compose_path)
        except Exception as ex:
            self.logger.error(ex.args[-1])

    @staticmethod
    def parse_args(args=None):
        sys_args = args or sys.argv[1:]
        parser = argparse.ArgumentParser(prog=__version__.__title__)
        parser.add_argument("command", choices=[
            "convert", "deploy", "update-records", "patch-ingress",
            "rollout-restart", "version", "install"
        ])
        parser.add_argument("-f", "--file", dest="file", default="docker-compose.yml")
        parser.add_argument("-o", "--out", dest="out", default="")
        parser.add_argument("-c", "--chart", action="store_true", dest="chart")
        parser.add_argument("-j", "--json", action="store_true", dest="json")
        parser.add_argument("-n", "--namespace", dest="namespace", default="default")
        parser.add_argument("-v", "--verbose", action="count", dest="verbose", default=0)
        parser.add_argument("--indent", dest="indent", type=int, default=2)
        group = parser.add_mutually_exclusive_group()
        group.add_argument("-s", "--skip", action="store_true", dest="skip")
        group.add_argument("-d", "--clean", action="count", dest="clean", default=0)
        parser.add_argument("--deny-ingress", action="store_true", dest="deny_ingress")
        group = parser.add_mutually_exclusive_group()
        group.add_argument("--deny-egress", action="store_true", dest="deny_egress")
        group.add_argument("--deny-egress-cidr", action="extend", nargs="+", metavar="CIDR", dest="deny_egress_cidr")
        parser.add_argument("--create-namespace", action="store_true", dest="create_namespace")
        parser.add_argument("--delete-namespace", action="store_true", dest="delete_namespace")
        parser.add_argument("--eks-kubeconfig", dest="eks_kubeconfig")
        parser.add_argument("--rollout-restart", action="store_true", dest="rollout_restart")
        group = parser.add_mutually_exclusive_group()
        group.add_argument("--route53-hostedzone", dest="route53_hostedzone")
        group.add_argument("--route53-hostedzone-id", dest="route53_hostedzone_id")
        parser.add_argument("--version", dest="version", default="latest")
        parser.add_argument("--patch-ingress", action="store_true", dest="patch_ingress")
        parser.add_argument("--tcp-services-configmap", dest="tcp_services_configmap",
                            default="ingress-nginx/tcp-services")
        parser.add_argument("--ingress-service", dest="ingress_service",
                            default="ingress-nginx/ingress-nginx-controller")
        args_known, args_unknown = parser.parse_known_args(args=sys_args)

        namespace = args_known.namespace
        command = args_known.command
        if command not in ["convert", "deploy", "update-records", "rollout-restart"]:
            return args_known, args_unknown

        if not path.exists(args_known.file):
            parser.error(f"file {args_known.file} is not exist")

        if command == "update-records" and \
                not any([args_known.route53_hostedzone, args_known.route53_hostedzone_id]):
            parser.error(f"update-records argument --route53-hostedzone/--route53-hostedzone-id is not set")

        if command == "deploy" and not re.match(r"^[a-z\d]([-a-z\d]*[a-z\d])?$", namespace):
            parser.error(
                f"The Namespace {json.dumps(namespace)} is invalid: "
                f"metadata.name: Invalid value: {json.dumps(namespace)}: "
                "a lowercase RFC 1123 label must consist of lower case alphanumeric characters or '-', "
                "and must start and end with an alphanumeric character (e.g. 'my-name',  or '123-abc', "
                "regex used for validation is '[a-z0-9]([-a-z0-9]*[a-z0-9])?')"
            )

        return args_known, args_unknown

    @staticmethod
    def parse_records(labels):
        records = []
        kompose_expose = labels.get("kompose.service.expose")
        if kompose_expose:
            records.extend(map(str.strip, kompose_expose.split(",")))

        kompose_ex_expose = labels.get("kompose-ex.service.expose")
        if kompose_ex_expose:
            records.extend(map(str.strip, kompose_ex_expose.split(",")))

        return records

    def kompose_convert(self, kompose_path="kompose", compose_path=None):
        files = glob(path.join(self.directory, "bin", "kompose*"))
        if files:
            kompose_path = files[0]

        args = []
        if self.args.chart:
            args.append("-c")
            if not self.args.out:
                self.args.out = path.splitext(self.args.file)[0]
        if self.args.json:
            args.append("-j")
        if self.args.verbose > 1:
            args.append("-v")
        if self.args.out:
            args.extend(["-o", self.args.out])
        if self.args.indent != 2:
            args.extend(["--indent", str(self.args.indent)])

        return_code, _output = utils.process_output(
            args=[
                kompose_path, "convert",
                "-f", compose_path or self.args.file,
                *args,
                *self.args_unknown
            ],
            stderr=subprocess.STDOUT,
            logger=self.logger
        )

        return return_code

    @staticmethod
    def pop_kompose_kubernetes_object(kind, service_name, yaml_object=None, yaml_path=None, file_ext="yaml"):
        if not any([yaml_object, yaml_path]):
            raise Exception("parameter yaml_object/yaml_path is not set")

        if yaml_object:
            jsonpath_expr = jsonpath_ext.parser.parse(
                f"$.items[?(@.kind == '{kind}' & @.metadata.name== {repr(service_name)})]"
            )
            res = jsonpath_expr.find(yaml_object)[0].value
            yaml_object["items"].remove(res)
        else:
            f_path = path.join(yaml_path, f"{service_name}-{kind.lower()}.{file_ext}")
            with open(f_path) as fr:
                res = yaml.safe_load(fr)
            os.remove(f_path)
        return res

    def kompose_ex_convert(self, services):
        file_ext = "json" if self.args.json else "yaml"
        is_file = path.isfile(self.args.out)
        out_path = self.args.out
        if self.args.chart:
            out_path = path.join(out_path, "templates")
        output = {}
        kompose_items = []
        if is_file:
            with open(self.args.out, "r", encoding="UTF-8") as fr:
                output = yaml.safe_load(fr)
                kompose_items = output["items"]

        items = {}
        network_policy_api_version = "networking.k8s.io/v1"

        # Deny ingress
        if self.args.deny_ingress:
            items["deny-ingress-network-policy"] = models.V1NetworkPolicy(
                api_version=network_policy_api_version,
                metadata=models.V1ObjectMeta(
                    name="deny-ingress",
                    annotations=self.annotations,
                ),
                spec=models.V1NetworkPolicySpec(
                    ingress=[{
                        "from": [{
                            "podSelector": {}
                        }]
                    }],
                    pod_selector={},
                    policy_types=["Ingress"]
                )
            ).to_dict()

        # Deny egress
        if self.args.deny_egress:
            items["deny-egress-network-policy"] = models.V1NetworkPolicy(
                api_version=network_policy_api_version,
                metadata=models.V1ObjectMeta(
                    name="deny-egress",
                    annotations=self.annotations,
                ),
                spec=models.V1NetworkPolicySpec(
                    egress=[{
                        "to": [{
                            "podSelector": {}
                        }]
                    }],
                    pod_selector={},
                    policy_types=["Egress"]
                )
            ).to_dict()

        # Deny egress to cidr list
        if self.args.deny_egress_cidr:
            items["deny-egress-cidr-network-policy"] = models.V1NetworkPolicy(
                api_version=network_policy_api_version,
                metadata=models.V1ObjectMeta(
                    name="deny-egress-cidr",
                    annotations=self.annotations,
                ),
                spec=models.V1NetworkPolicySpec(
                    egress=[{
                        "to": [{
                            "ipBlock": {
                                "cidr": "0.0.0.0/0",
                                "except": self.args.deny_egress_cidr
                            }
                        }]
                    }],
                    pod_selector={},
                    policy_types=["Egress"]
                )
            ).to_dict()

        cron_restart_services = {}
        for service_name, service in services.items():
            allow_egress = service.get("allow_egress", False)
            allow_ingress = (service["public"] and self.args.deny_ingress) or service.get("allow_ingress", False)

            if service["rollout-restart-cronjob-schedule"]:
                cron_restart_services[service_name] = service

            # Fix ReadOnly
            if service["service"].get("read_only", False):
                manifest = self.pop_kompose_kubernetes_object(
                    kind=service["controller"],
                    service_name=service_name,
                    yaml_object=output if output else None,
                    yaml_path=None if output else out_path
                )
                containers = manifest["spec"]["template"]["spec"]["containers"]
                for container in containers:
                    if container.get("name") != service_name:
                        continue

                    container["securityContext"] = container.get("securityContext", {})
                    container["securityContext"].update({
                        "readOnlyRootFilesystem": True
                    })
                manifest["metadata"]["annotations"]["kompose-ex.updated"] = "true"
                items[f"{service_name}-{service['controller']}"] = manifest

            # Fix DaemonSet
            if service["controller"] == "daemonset":
                daemonset = self.pop_kompose_kubernetes_object(
                    kind="DaemonSet",
                    service_name=service_name,
                    yaml_object=output if output else None,
                    yaml_path=None if output else out_path
                )
                daemonset["spec"]["selector"] = {
                    "matchLabels": {
                        "io.kompose.service": service_name
                    }
                }
                daemonset["metadata"]["annotations"]["kompose-ex.updated"] = "true"
                items[f"{service_name}-daemonset"] = daemonset

            # Fix Ingress
            if service["ingress"]["class"] or service["ingress"]["tls"]:
                ingress = self.pop_kompose_kubernetes_object(
                    kind="Ingress",
                    service_name=service_name,
                    yaml_object=output if output else None,
                    yaml_path=None if output else out_path
                )

                if service["ingress"]["tls"]:
                    for tls_rule in ingress["spec"]["tls"]:
                        tls_rule.pop("secretName", None)

                if service["ingress"]["class"]:
                    ingress["spec"]["ingressClassName"] = service["ingress"]["class"]

                ingress["metadata"]["annotations"]["kompose-ex.updated"] = "true"
                items[f"{service_name}-ingress"] = ingress

            # Allow ingress to service
            if allow_ingress:
                items[f"allow-ingress-{service_name}-network-policy"] = models.V1NetworkPolicy(
                    api_version=network_policy_api_version,
                    metadata=models.V1ObjectMeta(
                        name=f"allow-ingress-{service_name}",
                        annotations=service["labels"],
                    ),
                    spec=models.V1NetworkPolicySpec(
                        ingress=[{}],
                        pod_selector={
                            "matchLabels": {
                                "io.kompose.service": service_name
                            }
                        },
                        policy_types=["Ingress"]
                    )
                ).to_dict()

            # Allow Egress from service
            if allow_egress:
                items[f"allow-egress-{service_name}-network-policy"] = models.V1NetworkPolicy(
                    api_version=network_policy_api_version,
                    metadata=models.V1ObjectMeta(
                        name=f"allow-egress-{service_name}",
                        annotations=service["labels"],
                    ),
                    spec=models.V1NetworkPolicySpec(
                        egress=[{}],
                        pod_selector={
                            "matchLabels": {
                                "io.kompose.service": service_name
                            }
                        },
                        policy_types=["Egress"]
                    )
                ).to_dict()

            # Create CronJob
            if service["cronjob"]:
                pod = self.pop_kompose_kubernetes_object(
                    kind="Pod",
                    service_name=service_name,
                    yaml_object=output if output else None,
                    yaml_path=None if output else out_path
                )
                if not is_file:
                    f_path = path.normpath(path.join(out_path, f"{service_name}-pod.{file_ext}"))
                    self.logger.info(f"Kubernetes file {json.dumps(f_path)} deleted")

                backoff_limit = service["labels"].get("kompose-ex.pod.backoff_limit", None)
                if backoff_limit:
                    backoff_limit = int(backoff_limit)

                items[f"{service_name}-cronjob"] = models.V1CronJob(
                    api_version="batch/v1",
                    metadata=models.V1ObjectMeta(
                        name=service_name,
                        annotations=pod["metadata"]["annotations"],
                        labels=pod["metadata"]["labels"],
                    ),
                    spec=models.V1CronJobSpec(
                        schedule=service["cronjob-schedule"],
                        concurrency_policy=service["cronjob-concurrency-policy"],
                        job_template=models.V1JobTemplateSpec(
                            spec=models.V1JobSpec(
                                backoff_limit=backoff_limit,
                                template=models.V1PodTemplateSpec(
                                    spec=pod["spec"]
                                )
                            )
                        )
                    )
                ).to_dict()

        if cron_restart_services:
            # Create service account
            items["rollout-restart-service-account"] = models.V1ServiceAccount(
                metadata=models.V1ObjectMeta(
                    name="rollout-restart",
                    annotations=self.annotations,
                ),
            ).to_dict()

            # Create role
            items["rollout-restart-role"] = models.V1Role(
                api_version="rbac.authorization.k8s.io/v1",
                metadata=models.V1ObjectMeta(
                    name="rollout-restart",
                    annotations=self.annotations,
                ),
                rules=[{
                    "apiGroups": [
                        "apps",
                        "extensions"
                    ],
                    "resources": [
                        "deployments",
                        "daemonsets",
                        "statefulsets"
                    ],
                    "resourceNames": [
                        *cron_restart_services
                    ],
                    "verbs": [
                        "get",
                        "patch"
                    ]
                }]
            ).to_dict()

            # Create role binding for service account
            items["rollout-restart-role-binding"] = models.V1RoleBinding(
                api_version="rbac.authorization.k8s.io/v1",
                metadata=models.V1ObjectMeta(
                    name="rollout-restart",
                    annotations=self.annotations,
                ),
                role_ref={
                    "apiGroup": "rbac.authorization.k8s.io",
                    "kind": "Role",
                    "name": "rollout-restart"
                },
                subjects=[{
                    "kind": "ServiceAccount",
                    "name": "rollout-restart",
                }]
            ).to_dict()

            # Create restart cronjobs
            for service_name, service in cron_restart_services.items():
                items[f"{service_name}-rollout-restart-cronjob"] = models.V1CronJob(
                    api_version="batch/v1",
                    metadata=models.V1ObjectMeta(
                        name=f"rollout-restart-{service_name}",
                        annotations=service["labels"],
                    ),
                    spec=models.V1CronJobSpec(
                        concurrency_policy="Forbid",
                        schedule=service["rollout-restart-cronjob-schedule"],
                        job_template=models.V1JobTemplateSpec(
                            spec=models.V1JobSpec(
                                template=models.V1PodTemplateSpec(
                                    spec={
                                        "serviceAccountName": "rollout-restart",
                                        "restartPolicy": "Never",
                                        "containers": [{
                                            "name": "kubectl",
                                            "image": "bitnami/kubectl",
                                            "command": [
                                                "kubectl",
                                                "rollout",
                                                "restart",
                                                f"{service['controller']}/{service_name}"
                                            ]
                                        }]
                                    }
                                )
                            )
                        )
                    )
                ).to_dict()

        if not items:
            return

        # If output is file
        if is_file:
            with open(out_path, "w", encoding="UTF-8") as fw:
                kompose_items.extend(items.values())
                if self.args.json:
                    json.dump(output, fw, indent=self.args.indent)
                else:
                    yaml.safe_dump(output, stream=fw, indent=self.args.indent, width=0x7fffffff)
            self.logger.info(f"Kubernetes file {json.dumps(out_path)} updated")
            return

        # If output is directory
        for item_name, item in items.items():
            updated = item["metadata"]["annotations"].get("kompose-ex.updated")
            f_path = path.normpath(path.join(out_path, f"{item_name}.{file_ext}"))
            with open(f_path, "w") as fw:
                if self.args.json:
                    json.dump(item, fw, indent=self.args.indent)
                else:
                    yaml.safe_dump(item, stream=fw, indent=self.args.indent, width=0x7fffffff)

            self.logger.info(f"Kubernetes file {json.dumps(f_path)} {'updated' if updated else 'created'}")

    def get_services(self):
        services = {}
        _services = self.compose.get("services", [])
        for name, service in _services.items():
            public = True
            labels = service.get("labels", {})
            service_type = (
                    labels.get("kompose-ex.service.type", "").lower() or
                    labels.get("kompose.service.type", "").lower()
            )
            if "kompose.service.expose" in labels:
                service_type = "ingress"

            if service_type not in ["loadbalancer", "nodeport", "ingress", "ingress-nginx"]:
                public = False

            services[name] = {
                "type": service_type,
                "public": public,
                "labels": labels,
                "service": service,
                "build": "build" in service,
                "image-pull-policy": labels.get("kompose.image-pull-policy", "Never").lower(),
                "ingress": {
                    "tls": (
                            labels.get("kompose-ex.service.expose.tls", "false").lower() == "true" and
                            labels.get("kompose.service.expose.tls-secret", "").lower() == "null"
                    ),
                    "class": (
                            labels.get("kompose.service.expose.ingress-class-name", "") or
                            labels.get("kompose-ex.service.expose.ingress-class-name", "")
                    ).lower()
                },
                "records": self.parse_records(labels=labels),
                "controller": (
                        labels.get("kompose-ex.controller.type", "").lower() or
                        labels.get("kompose.controller.type", "deployment").lower()
                ),
                "allow_egress": labels.get("kompose-ex.egress.allow", "false").lower() == "true",
                "allow_ingress": labels.get("kompose-ex.ingress.allow", "false").lower() == "true",
                "cronjob": labels.get("kompose-ex.controller.type", "").lower() == "cronjob",
                "cronjob-schedule": labels.get("kompose-ex.cronjob.schedule"),
                "cronjob-concurrency-policy": labels.get("kompose-ex.cronjob.concurrency_policy", "Allow"),
                "rollout-restart-cronjob-schedule": labels.get("kompose-ex.rollout-restart.cronjob.schedule"),
            }

        return services

    @property
    def directory(self):
        homedir = path.expanduser('~')
        return path.join(homedir, ".kompose-ex")

    def install(self, version="latest"):
        install_directory = path.join(self.directory, "bin")
        os.makedirs(install_directory, exist_ok=True)
        kompose_version = utils.install_kompose(install_directory, version=version)
        self.logger.info(f"kompose {kompose_version} installed")

    def convert(self, services, compose_path):
        # Skip conversion (Only deploy)
        skip = self.args.skip and self.args.command == "deploy"
        if skip:
            return 0

        # Clean files
        if self.args.clean:
            utils.clean(self.args.out)

        # Convert docker compose yaml using kompose
        return_code = self.kompose_convert(compose_path=compose_path)
        if return_code:
            raise Exception("kompose conversion failed")

        # Convert with kompose-ex
        self.kompose_ex_convert(services)

        return 0

    def deploy(self):
        # Delete namespace
        if self.args.delete_namespace:
            api.delete_namespace(self.args.namespace)

        # Create namespace
        if self.args.create_namespace or self.args.delete_namespace:
            api.create_namespace(self.args.namespace)

        # Apply kubernetes files
        out_path = self.args.out
        if self.args.chart:
            out_path = path.join(out_path, "templates")
        api.apply(out_path, namespace=self.args.namespace, verbose=self.args.verbose > 1)

        # Clean files
        if self.args.clean > 1:
            utils.clean(self.args.out)

    def update_records(self, services):
        # Update Rout53 DNS Records
        provider = None
        provider_kwargs = {}
        if any([self.args.route53_hostedzone, self.args.route53_hostedzone_id]):
            from .dns import route53

            route53_hostedzone_id = self.args.route53_hostedzone_id
            if not route53_hostedzone_id:
                route53_hostedzone_id = route53.get_hosted_zones_by_name(self.args.route53_hostedzone)
            provider = route53
            provider_kwargs = dict(zone_id=route53_hostedzone_id)

        if not provider:
            return

        for service_name, service in services.items():
            records = service.get("records", [])
            if not records or not service.get("public"):
                return

            name = service_name
            namespace = self.args.namespace
            if service["type"] == "ingress-nginx":
                namespace, _, name = self.args.ingress_service.partition("/")
                if not name:
                    namespace, name = "default", name

            balancer_address = api.load_balancer_address(
                name=name,
                namespace=namespace,
                ingress=service.get("type", "") == "ingress"
            )
            for record in records:
                provider.update_cname_record(name=record, record=balancer_address, **provider_kwargs)
                self.logger.info(f"Route53 record {record} is set to {balancer_address}")

    def update_kubeconfig(self, name=None):
        name = name or self.args.eks_kubeconfig
        args = [
            "aws", "eks",
            "update-kubeconfig",
            "--name", name
        ]
        if self.args.verbose > 1:
            args.append("--verbose")

        return_code, _output = utils.process_output(
            args=args,
            stderr=subprocess.STDOUT,
            logger=self.logger
        )
        if return_code:
            raise Exception("eks kubeconfig creation failed")

    def rollout_restart(self, services):
        for service_name, service in services.items():
            if service["image-pull-policy"] != "always":
                continue

            res = api.rollout_restart(
                service_name,
                namespace=self.args.namespace,
                controller=service["controller"]
            )
            object_name = api.get_object_name(res)
            self.logger.info(f"{object_name} restarted")

    def patch_ingress(self, services):
        core_api = client.CoreV1Api()

        patched = False
        for service_name, service in services.items():
            if service["type"] != "ingress-nginx":
                continue

            _service = service.get("service")
            ports = _service.get("ports", []) or _service.get("expose", [])
            if not ports:
                continue

            configmap_data = {}
            service_ports = []
            for port in ports:
                port = int(port.split(":")[0])
                configmap_data[port] = f"{self.args.namespace}/{service_name}:{port}"
                service_ports.append({
                    "name": f"{port}",
                    "port": port,
                    "protocol": "TCP",
                    "targetPort": port,
                })

            namespace, _, name = self.args.tcp_services_configmap.partition("/")
            if not namespace:
                namespace, name = "default", namespace

            res = core_api.patch_namespaced_config_map(
                name=name,
                namespace=namespace,
                body={
                    "data": configmap_data
                }
            )
            if not patched:
                self.logger.info(f"{api.get_object_name(res)} patched")

            namespace, _, name = self.args.ingress_service.partition("/")
            if not namespace:
                namespace, name = "default", namespace

            res = core_api.patch_namespaced_service(
                name=name,
                namespace=namespace,
                body={
                    "spec": {
                        "ports": service_ports
                    }
                }
            )
            if not patched:
                self.logger.info(f"{api.get_object_name(res)} patched")

            patched = True
            self.logger.info(f"{service['controller']}.apps/{service_name} exposed")

    def run(self):
        # Print version
        if self.args.command == "version":
            print(self.version)
            return 0

        # Install requirements
        if self.args.command == "install":
            self.install(version=self.args.version)
            return 0

        # Load compose yaml
        with open(self.args.file, "r", encoding="UTF-8") as fr:
            self.compose = yaml.safe_load(fr.read())

        # Recreate compose yaml
        compose_path = self.recreate_compose()
        if not compose_path:
            return 1

        # Get compose services
        services = self.get_services()

        # Convert docker-compose to kubernetes objects
        if self.args.command in ["convert", "deploy"]:
            self.convert(services, compose_path)

        if self.args.command == "convert":
            return 0

        # Load kubernetes config
        if self.args.eks_kubeconfig:
            self.update_kubeconfig()
        config.load_config()

        # Deploy kubernetes objects
        if self.args.command == "deploy":
            self.deploy()

        # Patch ingress controller
        patch_ingress = self.args.command == "deploy" and self.args.patch_ingress
        if patch_ingress or self.args.command == "patch-ingress":
            self.patch_ingress(services)

        #  Restart kubernetes objects
        rollout_restart = self.args.command == "deploy" and self.args.rollout_restart
        if rollout_restart or self.args.command == "rollout-restart":
            self.rollout_restart(services)

        #  Update DNS cname records
        if self.args.command in ["deploy", "update-records"]:
            self.update_records(services)

        return 0

    def start(self):
        try:
            return self.run()
        except Exception as ex:
            self.logger.fatal(ex)
        return 1

    @classmethod
    def main(cls, args=None):
        kompose = cls(args=args)

        # Configure basic logger
        logging.basicConfig(
            level=logging.INFO if not kompose.args.verbose else logging.DEBUG,
            format="%(asctime)s %(levelname)s %(message)s",
            datefmt="%d-%m-%y %H:%M:%S"
        )

        return kompose.start()

def main(args=None):
    return KomposeEx.main(args=args)


#! /usr/bin/env python

from setuptools import setup

# https://stackoverflow.com/questions/27664504/how-to-add-package-data-recursively-in-python-setup-py
# compensating for python's worthless packaging system
import os

def package_files(directory):
    paths = []
    for (path, directories, filenames) in os.walk(directory):
        for filename in filenames:
            paths.append(os.path.join('..', path, filename))
    return paths

openjdk_files = package_files(os.path.join('semgenjar','jre'))
print('openjdk_files')
print(openjdk_files)

setup(name='pysemgenjar-packr',
      version='0.1.5',
      description='Jar file and embedded openjdk for pysemgen',
      author='J. Kyle Medley',
      packages=['semgenjar'],
      include_package_data=True,
      package_data={'semgenjar': [
          'semgenapi',
          'SemSimAPI.jar',
          'config.json',
          ]+openjdk_files},
      install_requires=[
        #'tellurium>=2.1.0',
        ],
      )


from hardware.speed_controller import SpeedController
from hardware.steering_controller import SteeringController
from gps_interface.ublox_interface import UBX

from adafruit_blinka.board import raspi_40pin as board
import busio
import adafruit_ads1x15.ads1115 as ADC
import adafruit_mcp4725 as DAC
from adafruit_ads1x15.analog_in import AnalogIn
import digitalio as DIO
import yaml

if __name__ == "__main__":

    # Setup GPS
    gps = UBX(port="/dev/ttyACM0", baud=9600)
    gps.start_reading()

    # I2C Setup
    i2c = busio.I2C(board.SCL, board.SDA)

    # Setup Steering Controller
    steering_controller = SteeringController(i2c=i2c)

    # Setup Speed Controller
    speed_controller = SpeedController(i2c=i2c, gps=gps)

    try:
        while True:
            print("<S> to test Steering Control")
            print("<D> to test Speed Control")
            user_input = input("Enter value:\n")
            try:
                assert user_input in ["S", "s", "D", "d"], "Please enter a valid option!"
            except AssertionError:
                continue

            if user_input.upper() == "S":
                print("Steering control selected...")
                steering_controller.start_steering_control_thread()
                try:
                    while True:
                        angle = input("Steering Angle:\n")
                        try:
                            angle = float(angle)
                        except TypeError:
                            print("Please enter a number")
                            continue

                        steering_controller.set_steering_angle(angle=angle)
                except KeyboardInterrupt:
                    print("Stopping steering control")
                    steering_controller.stop_steering_control_thread()
                    continue

            elif user_input.upper() == "D":
                print("Speed control selected...")
                speed_controller.start_speed_control_thread()
                try:
                    while True:
                        speed = input("Speed:\n")
                        try:
                            speed = float(speed)
                        except TypeError:
                            print("Please enter a number")
                            continue

                        speed_controller.set_speed(speed=speed)
                except KeyboardInterrupt:
                    print("Stopping speed control")
                    speed_controller.stop_speed_control_thread()
                    continue

    except KeyboardInterrupt:
        print("Exiting...")
        exit(0)


#! /usr/bin/env python3.3
'''get list of repos'''

import p4gf_config
import p4gf_group
from   p4gf_l10n      import NTR
import p4gf_util

class RepoList:
    '''build list of repos available to user'''

    def __init__(self):
        '''empty list'''
        self.repos = []

    @staticmethod
    def list_for_user(p4, user):
        '''build list of repos visible to user'''
        result = RepoList()

        for view in p4gf_util.view_list(p4):
            #check user permissions for view
            # PERM_PUSH will avoid checking the repo config file for read-permission-check = user
            view_perm = p4gf_group.ViewPerm.for_user_and_view(p4,
                                                            user,
                                                            view,
                                                            p4gf_group.PERM_PUSH)
            #sys.stderr.write("view: {}, user: {}, perm: {}".format(view, user, view_perm))
            if view_perm.can_push():
                perm = NTR('push')
            elif view_perm.can_pull():
                perm = NTR('pull')
            else:
                continue

            config = p4gf_config.get_repo(p4, view)
            charset = config.get(p4gf_config.SECTION_REPO, p4gf_config.KEY_CHARSET, fallback='')
            desc = config.get(p4gf_config.SECTION_REPO, p4gf_config.KEY_DESCRIPTION, fallback='')
            result.repos.append((view, perm, charset, desc))

        result.repos.sort(key=lambda tup: tup[0])
        return result


# Demos use of the emd.Custom class

from typing import Optional,Union
import numpy as np
from os.path import basename

from py4DSTEM.emd import (
    Custom,
    Array,
    Metadata
)

class MyCustomClass(Custom):
    """
    """

    def __init__(
        self,
        data,
        name = 'my_custom_class'
        ):
        """ `data` is a numpy array
        """
        Custom.__init__(self,name=name)

        # define some data arrays
        self.data = Array(
            data = data,
            name = 'data'
        )
        self.moredata = Array(
            data = np.tile(data,(2,2)),
            name = 'moredata'
        )

        # add some metadata
        self.metadata = Metadata(
            name = 'my_metadata',
            data = {
                'cats' : 'aregreat'
            }
        )

    # write inherited from Custom

    # read

    @classmethod
    def _get_constructor_args(cls,group):
        """
        """
        # get EMD group data
        emd_data = cls._get_emd_attr_data(cls,group)

        kwargs = {
            'name' : basename(group.name),
            'data' : emd_data['data'].data
        }

        return kwargs


import numpy as np

class OrthoPoly:
    """
    Orthogonal Polynomial approximation
    on given data, interval

    Implements Gram-Schmidt orthogonalization
    to construct the polynomial basis

    Parameters
    func: function to approximate
    interval: tuple (start, end)

    """
    def __init__(self, func, interval=[-1,1], n=3):
        """
        Gram-Schmidt to construct orthogonal polynomial basis
        Returns the m approximated points using n degree polynomial

        Parameters
        n: number of polynomials to use as basis
        m: number of points to evaluate the function at
        """
        self.func = func
        self.interval = interval
        self.n = n

    def __call__(self, x):
        m = len(x)
        data = self.func(x)

        # gram-schmidt
        poly = [np.ones(m)]
        if self.n > 1:
            for i in range(1,self.n):
                tempx = x**i
                for j in range(len(poly)):
                    tempx -= (tempx @ poly[j] / (poly[j] @ poly[j])) * poly[j]
                poly.append(tempx.copy())

        # calculate coefficients
        ck = []
        ak = []
        for polys in poly:
            ck.append(np.trapz(polys**2, x))
            ak.append(np.trapz(polys * data, x) / ck[-1])

        # output
        out = np.zeros(m)
        for i, polys in enumerate(poly):
            out += ak[i] * polys
        return(out)


from django.conf.urls import url

from workflow.views import manager_view, viewport_view, add_workflow, remove_workflow, create_workflow

app_name = 'workflow'
urlpatterns = [

    url(r'^manager/$', manager_view, name='manager'),
    url(r'^add/$', add_workflow, name='add_workflow'),
    url(r'^create/$', create_workflow, name='create_workflow'),
    url(r'^pop/$', remove_workflow, name='remove_workflow'),
    url(r'^$', viewport_view, name='viewport')
]