#!/usr/bin/env python

""" Ansible inventory creation helpers """

from __future__ import print_function

import os
import time
import argparse
import json
import re
import utils

# TODO
# have config files - /etc/, ~/., local dir

# defaults for helpers
ANSIBLE_DYN_INV_DEFAULTS = {
  'ANSIBLE_DYN_INV_CACHE': 'false',
  'ANSIBLE_DYN_INV_CACHE_PATH': os.path.join(os.path.expanduser('~'),
                                             '.ansible-inventory-cache.json'),
  'ANSIBLE_DYN_INV_CACHE_MAX_AGE': '3600',
  'ANSIBLE_DYN_INV_ALL_HOSTGROUP': 'false',
  'ANSIBLE_DYN_INV_SSH_HOSTGROUPS': 'false'
}

# duh
SSH_PORT = 22

class InvalidArgument(ValueError):
  """ Custom exception for invalid arg """
  pass

class InventoryCache(object):
  """ Inventory cache class """
  def __init__(self, path, max_age):
    """ Create the object """

    self.path = path
    self.max_age = max_age

    if re.match(r'^\d+$', str(self.max_age)) is None:
      raise InvalidArgument('ERROR: Invalid cache max_age: %s\n' % self.max_age)

    self.max_age = int(self.max_age)

  def exists(self):
    """ Check if cache exists """
    return os.path.isfile(self.path)

  def is_valid(self):
    """ Check if cache is valid """
    if self.exists():
      mod_time = os.path.getmtime(self.path)
      current_time = time.time()
      if (mod_time + self.max_age) > current_time:
        return True
    return False

  def dump(self, data):
    """ Dump data to cache """
    with open(self.path, 'w') as file_desc:
      file_desc.write(json.dumps(data, indent=2))
    return data

  def load(self):
    """ Load data from cache """
    return json.loads(open(self.path).read())

class Inventory(object):
  """ Ansible Inventory base class """
  def __init__(self, **kwargs):
    """ Create the object """
    # load defaults
    for env_var in ANSIBLE_DYN_INV_DEFAULTS:
      if env_var not in os.environ:
        os.environ[env_var] = ANSIBLE_DYN_INV_DEFAULTS[env_var]

      val = os.environ[env_var]
      if val == 'true':
        val = True
      elif val == 'false':
        val = False

      # create instance attributes from env vars
      setattr(self, env_var.lower(), val)

    self.list_callback = kwargs.pop('list_callback')
    self.host_callback = kwargs.pop('host_callback')

    # Parse cmdline
    self.cmdline_args = {}
    self.parse_cmdline()

    self.list_callback['args'].update(self.cmdline_args)
    self.host_callback['args'].update(self.cmdline_args)

    # create cache object indepentdent of the inventory
    self.cache = None
    if self.ansible_dyn_inv_cache:
      self.cache = InventoryCache(self.ansible_dyn_inv_cache_path,
                                  self.ansible_dyn_inv_cache_max_age)

    # list_ds - create for --list action
    self.list_ds = None

    # host_ds - create for --host action
    self.host_ds = None

    # default - don't load from cache
    self.load_from_cache = False

  def parse_cmdline(self):
    """ Parse cmdline args """
    parser = argparse.ArgumentParser()
    parser.add_argument('-c', '--config',
                        help='json string having config for this inventory',
                        default='')
    parser.add_argument('-l', '--list', help='List inventory', action='store_true',
                        default=False)
    parser.add_argument('-r', '--refresh-cache', help='Refresh cached inventory',
                        action='store_true', default=False)
    parser.add_argument('-v', '--verbose', help='Verbose mode',
                        action='store_true', default=False)
    parser.add_argument('--host', help='host to query', default=False,
                        required=False)
    self.cmdline_args = vars(parser.parse_args())
    return self.cmdline_args

  def create_hostgroup_all(self):
    """ create "all" hostgroup if enabled """
    all_hosts = []
    if not self.load_from_cache:
      all_hosts = utils.get_all_hosts(self.list_ds, self.cmdline_args['verbose'])
      self.list_ds['all'] = all_hosts

  def create_hostgroup_ssh(self):
    """ Create "can_ssh", "cannot_ssh" hostgroup if enabled """
    if 'all' not in self.list_ds:
      self.create_hostgroup_all()

    if not self.load_from_cache:
      ssh_status = utils.port_conn_status(self.list_ds['all'], SSH_PORT,
                                          self.cmdline_args['verbose'])
      self.list_ds['can_ssh'] = {'hosts': []}
      self.list_ds['cannot_ssh'] = {'hosts': []}
      self.list_ds['can_ssh']['hosts'] = list(ssh_status['open'])
      self.list_ds['cannot_ssh']['hosts'] = list(ssh_status['closed'])

  def del_hostgroup(self, hostgroup):
    """ delete a hostgroup from self.list_ds """
    if hostgroup in self.list_ds:
      del self.list_ds[hostgroup]

  def execute(self):
    """ Execute action based on the cmdline args """

    if self.cache and self.cache.is_valid() and not self.cmdline_args['refresh_cache']:
      self.load_from_cache = True
      if self.cmdline_args['verbose']:
        print('STATUS: loading from cache: %s' % self.ansible_dyn_inv_cache_path)
      self.list_ds = self.cache.load()
    else:
      self.list_ds = self.list_callback['function'](self.list_callback['args'])

    if self.ansible_dyn_inv_all_hostgroup:
      self.create_hostgroup_all()
    else:
      self.del_hostgroup('all')

    if self.ansible_dyn_inv_ssh_hostgroups:
      self.create_hostgroup_ssh()
    else:
      self.del_hostgroup('can_ssh')
      self.del_hostgroup('cannot_ssh')

    # If caching is enabled and we didn't load from cache - we'd better save it
    # to the cache
    if self.cache and not self.load_from_cache:
      print('STATUS: dumping to cache: %s' % self.ansible_dyn_inv_cache_path)
      self.cache.dump(self.list_ds)

    if self.cmdline_args['list']:
      return self.list_ds

    if self.cmdline_args['host']:
      self.host_callback['args']['list_ds'] = self.list_ds
      self.host_callback['args']['host'] = self.cmdline_args['host']
      return self.host_callback['function'](self.host_callback['args'])

def create(**kwargs):
  """ Wrapper over BaseInventory class """
  inventory_obj = Inventory(**kwargs)
  return inventory_obj.execute()


import csv
import numpy as np
import torch
import torch.nn as nn
from tqdm import tqdm
from torch.utils.data import random_split
from torch.utils.tensorboard import SummaryWriter

def same_seed(seed):
    torch.backends.cudnn.deterministic = True
    torch.backends.cudnn.benchmark = False
    np.random.seed(seed)
    torch.manual_seed(seed)
    if torch.cuda.is_available():
        torch.cuda.manual_seed(seed)
        torch.cuda.manual_seed_all(seed)

def calc_feature_correlation(train_data, threshold):
    cor_matrix = train_data.corr().abs()
    cor_matrix = cor_matrix['tested_positive.4'].drop('tested_positive.4')
    useful_feature = [train_data.columns.get_loc(index) for index, value in cor_matrix.items() if value > threshold]

    if not useful_feature:
        print('No features')

    return useful_feature

def select_feature(train_data, valid_data, test_data, features):
    y_train, y_valid = train_data[:,-1], valid_data[:,-1]
    raw_x_train, raw_x_valid, raw_x_test = train_data[:,:-1], valid_data[:,:-1], test_data

    return raw_x_train[:,features], raw_x_valid[:,features], raw_x_test[:,features], y_train, y_valid

def train_valid_split(data_set, valid_ratio, seed):
    valid_set_size = int(valid_ratio * len(data_set))
    train_set_size = len(data_set) - valid_set_size
    train_set, valid_set = random_split(data_set, [train_set_size, valid_set_size], generator=torch.Generator().manual_seed(seed))

    return np.array(train_set), np.array(valid_set)

def predict(test_loader, model, device):
    model.eval()
    preds = []
    for x in tqdm(test_loader):
        x = x.to(device)
        with torch.no_grad():
            pred = model(x)
            preds.append(pred.detach().cpu())
    preds = torch.cat(preds, dim=0).numpy()

    return preds

def save_pred(preds, file):
    with open(file, 'w') as fp:
        writer = csv.writer(fp)
        writer.writerow(['id', 'tested_positive'])
        for i, p in enumerate(preds):
            writer.writerow([i, p])

def trainer(args, train_loader, valid_loader, model, device):
    criterion = nn.MSELoss(reduction='mean')
    optimizer = getattr(torch.optim, args.optimizer)(model.parameters(), lr=args.lr, betas=(0.9, 0.98), weight_decay=args.weight_decay)
    scheduler = torch.optim.lr_scheduler.ReduceLROnPlateau(optimizer, mode='min', factor=0.5, patience=args.lr_patience, verbose=True)

    writer = SummaryWriter(args.tensorboard)

    epochs = args.epoch
    best_loss = 9999.
    step = 0
    early_stop_count = 0

    for epoch in range(epochs):
        model.train()
        train_losses = []

        pbar = tqdm(train_loader, position=0, leave=True)
        for x, y in pbar:
            optimizer.zero_grad()
            x, y = x.to(device), y.to(device)
            pred = model(x)
            loss = criterion(pred, y)
            loss.backward()
            optimizer.step()
            step += 1
            train_losses.append(loss.detach().item())

            pbar.set_description(f'Epoch [{epoch+1}/{epochs}]')
            pbar.set_postfix({'loss': loss.detach().item()})

        mean_train_loss = sum(train_losses) / len(train_losses)

        model.eval()
        valid_losses = []
        for x, y in valid_loader:
            x, y = x.to(device), y.to(device)
            with torch.no_grad():
                pred = model(x)
                loss = criterion(pred, y)

            valid_losses.append(loss.item())

        mean_valid_loss = sum(valid_losses) / len(valid_losses)
        print(f'Epoch [{epoch+1}/{epochs}]: Train loss: {mean_train_loss:.4f}, Valid loss: {mean_valid_loss:.4f}')
        writer.add_scalars('Loss', {'train_loss': mean_train_loss, 'val_loss': mean_valid_loss}, step)

        scheduler.step(mean_valid_loss)
        if mean_valid_loss < best_loss:
            best_loss = mean_valid_loss
            torch.save(model.state_dict(), args.save_model_path)
            print('Saving model with val loss {:.3f}...'.format(best_loss))
            early_stop_count = 0
        else:
            early_stop_count += 1

        if early_stop_count >= args.early_stop:
            print('\nModel is not improving, so we halt the training session.')
            print(f'Best Loss: {best_loss}')
            break


from PyQt5 import QtWidgets
from PyQt5.QtWidgets import QFileDialog, QWidget
from PyQt5.QtGui import *
from PyQt5.QtCore import *
from PyQt5 import QtCore
from easydict import EasyDict as edict
from pprint import pprint
from .helper import *

class MyTimer(QWidget):
    trigger = pyqtSignal()

    def __init__(self, mainWiz):
        super(MyTimer, self).__init__()
        self.state = "pause"
        # self.need_change_flag = False
        self.counter = edict()
        self.mainWiz = mainWiz

        self.init_counter()

        self.timer = QBasicTimer()  # QTimer()貌似不行，不知何故？
        # self.timer.start(1000, self)

        # 覆写计时器事件处理函数timerEvent()
        # if type == "mic":
        #     timeout = param.mic

    def start(self):
        self.state = WORK
        self.timer.start(1000, self)

    def init_counter(self):
        mic = edict()
        mic.work = 0
        mic.break_ = 0
        mic.overdraft = 0
        mic.idle = 0
        self.counter.mic = mic

        mac = edict()
        mac.work = 0
        mac.break_ = 0
        mac.overdraft = 0
        mac.idle = 0
        self.counter.mac = mac

        self.counter.total = 0
        # self.counter.check_idle = 0

    def timerEvent(self, event):
        self.trigger.emit()
        # pprint(self.counter)
        # pprint(self.mainWiz.param_setter.params.mic.work_duration)
        state = self.state
        param = self.mainWiz.param_setter.params
        wz = self.mainWiz

        if state == ["pause", "waiting"]:
            pass

        elif state == WORK:
            self.counter.mic.work += 1
            self.counter.mac.work += 1
            self.counter.total += 1
            self.counter.mic.idle = 0
            self.counter.mac.idle = 0

            if self.counter.mic.work > secs(param.mic.work_duration):
                # call MicWin
                self.state = IDLE
                wz.manager.show_mic()
                self.counter.mic.work = 0
            print(self.counter.mac.work, param.mac.work_duration)

            if self.counter.mac.work > secs(param.mac.work_duration):
                self.state = IDLE
                wz.manager.show_mac()
                self.counter.mac.work = 0

        elif state == MIC_BREAK:
            self.counter.mic.break_ += 1
            if self.counter.mic.break_ > secs(param.mic.break_duration):
                # call MicWin
                wz.mic_win.close()
                self.counter.mic.idle = 0
                self.counter.mic.break_ = 0
                self.state = WORK

        elif state == MAC_BREAK:
            self.counter.mac.break_ += 1
            if self.counter.mac.break_ > secs(param.mac.break_duration):
                # call MicWin
                wz.mac_win.close()
                self.counter.mac.idle = 0
                self.counter.mac.break_ = 0
                self.state = WORK

        elif state in [IDLE]:
            self.counter.mic.idle += 1
            self.counter.mac.idle += 1
            if self.counter.mic.idle > secs(param.mic.idle):
                self.counter.mic.work = 0
            if self.counter.mac.idle > secs(param.mac.idle):
                self.counter.mac.work = 0

        elif state in [MIC_OVER]:
            self.counter.mic.overdraft += 1
            self.counter.mac.work += 1
            self.counter.total += 1
            if self.counter.mic.overdraft > secs(param.mic.postpone):
                # call MicWin
                self.state = IDLE
                wz.manager.show_mic()
                self.counter.mic.work = 0

        elif state in [MAC_BREAK]:
            self.counter.mac.overdraft += 1
            self.counter.mic.work += 1
            self.counter.total += 1
            if self.counter.mac.overdraft > secs(param.mac.postpone):
                # call MicWin
                self.state = IDLE
                wz.manager.show_mac()
                self.counter.mac.work = 0

    def change_state(self, state):
        self.state = state

class Timing(QtWidgets.QWidget):
    def __init__(self, mainWiz):
        self.mainWiz = mainWiz
        wz = self.mainWiz
        super(Timing, self).__init__()
        self.timer = MyTimer(mainWiz)

        self.mic_work_pbar = MyProgress(wz.timer_win.mic_work_pbar)
        self.mac_work_pbar = MyProgress(wz.timer_win.mac_work_pbar)
        self.total_pbar = MyProgress(wz.timer_win.total_pbar)
        self.mic_work_pbar.set_style("green")
        self.mac_work_pbar.set_style("blue")
        self.total_pbar.set_style("yellow")

        self.mic_break_pbar = MyProgress(wz.mic_win.progressBar)
        self.mac_break_pbar = MyProgress(wz.mac_win.progressBar)

        self.mic_post_pbar = self.mic_work_pbar
        self.mac_post_pbar = self.mac_work_pbar
        self.mic_idle_pbar = self.mic_work_pbar
        self.mac_idle_pbar = self.mac_work_pbar

        self.param = self.mainWiz.param_setter.params

        # self.state = self.timer.state  # work, break, pause, overdraft, idle

    def set_pbar_max(self):
        state = self.timer.state
        if state == WORK:
            self.mic_work_pbar.set_max(secs(self.param.mic.work_duration))
            self.mac_work_pbar.set_max(secs(self.param.mac.work_duration))
        elif state == IDLE:
            self.mic_idle_pbar.set_max(secs(self.param.mic.idle))
            self.mac_idle_pbar.set_max(secs(self.param.mac.idle))
        elif state == MIC_OVER:
            self.mic_post_pbar.set_max(secs(self.param.mic.postpone))
        elif state == MAC_OVER:
            self.mac_post_pbar.set_max(secs(self.param.mac.postpone))

        self.total_pbar.set_max(secs(self.param.total_time))
        self.mic_break_pbar.set_max(secs(self.param.mic.break_duration))
        self.mac_break_pbar.set_max(secs(self.param.mac.break_duration))

    # def pbar_format(self):
    #     self.mic_work_pbar.set

    def set_pbar_val(self):
        state = self.timer.state
        counter = self.timer.counter
        if state == WORK:
            self.mic_work_pbar.set_val(counter.mic.work)
            self.mic_work_pbar.set_style("green")
            self.mic_work_pbar.set_format(sec2tuple(counter.mic.work))
            self.mac_work_pbar.set_val(counter.mac.work)
            self.mac_work_pbar.set_style("blue")
            self.mac_work_pbar.set_format(sec2tuple(counter.mac.work))
        elif state == MIC_BREAK:
            self.mic_break_pbar.set_val(counter.mic.break_)
        elif state == MAC_BREAK:
            self.mac_break_pbar.set_val(counter.mac.break_)
        elif state == MIC_OVER:
            self.mic_post_pbar.set_val(counter.mic.overdraft)
            self.mic_post_pbar.set_style("orange")
            self.mic_post_pbar.set_format(sec2tuple(counter.mic.overdraft))
            self.mac_work_pbar.set_val(counter.mac.work)
        elif state == MAC_OVER:
            self.mac_post_pbar.set_val(counter.mac.overdraft)
            self.mac_post_pbar.set_style("red")
            self.mac_post_pbar.set_format(sec2tuple(counter.mac.overdraft))
            self.mic_work_pbar.set_val(counter.mic.work)
        elif state == IDLE:
            self.mic_idle_pbar.set_val(counter.mic.idle)
            self.mic_idle_pbar.set_style("gray")
            self.mic_idle_pbar.set_format(sec2tuple(counter.mic.idle))
            self.mac_idle_pbar.set_val(counter.mac.idle)
            self.mac_idle_pbar.set_style("gray")
            self.mac_idle_pbar.set_format(sec2tuple(counter.mac.idle))

        self.total_pbar.set_val(counter.total)

    def set_logic(self):
        wz = self.mainWiz
        wz.param_setter.value_changed_signal.connect(self.set_pbar_max)
        self.timer.trigger.connect(self.set_pbar_val)
        self.timer.trigger.connect(self.set_pbar_max)
        # self.set_pbar_max()


from psychopy import core, visual

from psychoscripts.utils.logging import CornerLogger, PsychopyLogger
from psychoscripts.utils.visual_screen import get_default_psychopy_win

EXP_NAME = "isi_sweeps"

window = get_default_psychopy_win()

data_logger = PsychopyLogger()

# Draw the stimuli and update the window
corner_logger = CornerLogger(window, data_logger)
corner_logger.log_string(EXP_NAME)

window.close()
core.quit()


import pickle
import pandas as pd
import numpy as np
from pydantic import BaseModel
from typing import List
from sklearn import preprocessing
from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware

app = FastAPI()

origins = ["*"]

app.add_middleware(
    CORSMiddleware,
    allow_origins=origins,
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
)

@app.get("/", tags=["Root"])
async def read_root():
    return {"message": "Welcome to the API!"}

class Data(BaseModel):
    data: List[int]

# Define endpoint for making predictions
@app.post('/predict')
def predict(data: Data):
    # Load model from .pkl file
    with open('./WrappingModel.pkl','rb') as file:
        model = pickle.load(file)
        # Convert input data to DataFrame
        data_array = np.array(data.data).reshape(1, -1)
        # Make prediction
        prediction = model.predict(data_array)
        # Return Prediction as JSON response
        return {'prediction': prediction[0]}


t = int(input())
for tc in range(1, t + 1):
    A = list(input())
    lenA = len(A)
    cnt = 0
    result = 0
    for i in range(lenA):
        if cnt < i:
            result += 1
            cnt += 1
        cnt += int(A[i])
    print(f'#{tc} {result}')


from const import *
import urllib.request
import json

top250 = []

i = 1
for st in range(0, 250, 20):
    url = TOP_API.format(BASE_URL, st, 20, API_KEY)

    request = urllib.request.Request(url, headers=HEADERS)
    res = urllib.request.urlopen(request)
    data = res.read().decode('utf-8')

    data = json.loads(data)

    movies = data['subjects']
    for m in movies:
        new_m = (m['id'], i)
        top250.append(new_m)
        i += 1

with open('douban.txt', 'a', encoding='utf8') as f:
    for t in top250:
        f.write('{}{}{}\n'.format(t[0], PARTITION, t[1]))

with open('douban.txt', 'r', encoding='utf8') as f:
    print(f.readlines())


### ONGOING WORK not finished because not sure it is useful.

from pathlib import Path
import os, time, sys, shutil
import logging
logging.basicConfig(format='[{}] %(asctime)s -- %(message)s'.format(sys.argv[0]),
        level=logging.INFO, stream=sys.stdout)

import xarray as xr
from xgcm import Grid

from itidenatl.tools import files as uf, dataio as io, compute as uc
#from proj_utils import load_grid_ds#, proj_pres, get_pres_one_dg as get_pres
from itidenatl import gridop as gop

if len(sys.argv)==1:
    print("usage: proj_uv_custdist.py iday [u/v [jy_beg [jy_end]]]")
    os._exit()
iday = sys.argv[1]
da = uf.get_date_from_iday(iday)
var = sys.argv[2] if len(sys.argv)>2 else "u"

homedir = Path(os.getenv("HOME"))
workdir = Path(os.getenv("WORKDIR"))
scratch = Path(os.getenv("SCRATCHDIR"))
worksha = Path("/work/CT1/ige2071/SHARED")
grid_mode_pres = workdir/"eNATL60_grid_vmodes_proj_pres.zarr"
grid_mode_uv = workdir/f"eNATL60_grid_vmodes_proj_{var}.zarr"

inp_chks = {"t":1, "z":10, "y":100, "x":-1}
wrk_chks = {"t":1, "z":10, "y":100, "x":-1}
ydim = "y_r" if var=="v" else "y_c"
xdim = "x_r" if var=="u" else "x_c"
str_chks = {"mode":1, "t":24, ydim:400, xdim:-1}
finish = True

if len(sys.argv)==4:
    if sys.argv[3] == "finish":
        regy = None
    else:
        regy = slice(int(sys.argv[3]), None)
elif len(sys.argv)==5:
    regy = slice(int(sys.argv[3]), int(sys.argv[4]))
    finish = False
else:
    regy = slice(0, None)
sk_y, sk_t = 100, 6
store_grid, store_uv = True, False

out_file = worksha/f"modal_proj/modamp_{var}/modamp_{var}_global_{da}.zarr"
log_dir = homedir/"working_on/processing/log_proj_uv"
log_file = f"proj_{var}_{iday}.log"
from_files = {"grid_mode_uv": grid_mode_uv, "grid_mode_pres": grid_mode_pres}
varname = {"u":"vozocrtx", "v":"vomecrty"}[var]
from_files[varname] = uf.get_eNATL_path(varname, iday)
from_files["sossheig"] = uf.get_eNATL_path("sossheig", iday)
file_list = scratch/f"prov_proj-{var}_{iday}_file-list.txt"
tmp_fil = scratch/f"prov_proj_{var}_{iday}.zarr"

ditp = "x" if var == "u" else "y"

### local routines
verbose = False

### local routines
def open_grid_file(isel=None, add_zl=False):
    ds = xr.open_zarr(from_files["grid_mode_uv"])
    ds = ds.reset_coords([f"{var}mask", f"{var}maskutil"], drop=True)
    if add_zl:
        dg = xr.open_zarr(from_files["grid_mode_pres"])
        ds = ds.assign_coords(z_l=dg.z_l)
        dg.close(); del dg
    ds = ds.chunk({d:wrk_chks[d[0]] for d in ds.dims if d[0] in wrk_chks})
    if isel is not None:
        ds = ds.isel(isel)
    return ds

def interp_xy(da, xgrid):

    res = xgrid.interp(da, ditp.upper(), boundary="extend")
    return res.chunk({f"{ditp}_r":wrk_chks[ditp]})

def prep_grid_ychk(ds, regy):
    """ load grid and ssh, interpolate velocity on mean grid """
    dg = open_grid_file(add_zl=True) # open uv grid, with both vertical grids
    ssh_path = from_files["sossheig"] # add ssh
    dg = dg.merge(io.open_one_var(ssh_path, chunks=wrk_chks, varname="sossheig")\
                  .rename({"sossheig":"ssh_inst"})
                 ) # add ssh -- this also add T grid
    xgrid = Grid(dg, periodic=False)
    dg["sossheig"] = interp_xy(dg.ssh_inst, xgrid) - dg["sossheig"] # ssh pert on uv grid
    sdg = dg.drop("ssh_inst").drop_dims([ditp+"_c"], errors="ignore")\
            .get([f"depth_{var}_m", "sossheig", f"e3{var}_m", "hbot"])\
            .isel({ydim:regy}).copy() # take only what is needed and y-subdomain

    print("opened grid")
    if store_grid:
        for v in list(sdg.coords)+list(sdg.data_vars):
            sdg[v].encoding.pop("chunks", None)
        sdg.to_zarr(tmp_fil, mode="w", compute=True, consolidated=True)
        sdg.close(); del sdg
        sdg = xr.open_zarr(tmp_fil)
        print("stored grid")
    sdg = xr.merge([sdg.drop("sossheig").persist(), sdg.sossheig]) # persist a few needed grid components
    print("persisted grid -- now interpolating velocity")
    return sdg, xgrid

def zinterp_uv_ychk(ds, dg, xgrid):
    """interpolate velocity on mean grid.
    Computing u*e3u for subsequent projection
    expects a subdomain
    """
    data = ds[varname]
    res = xgrid.diff(xgrid.interp(data, "Z", boundary="extrapolate"),
                     "Z", boundary="extend").chunk({"z_c":wrk_chks["z"]})
    delz = gop.get_del_zt(dg[f"depth_{var}_m"], ssh=dg.sossheig, hbot=dg.hbot).astype("float32")
    sds = ( data * dg[f"e3{var}_m"] + delz * res
          ).to_dataset(name=data.name).reset_coords(drop=True)

    if store_uv:
        uc.custom_distribute(sds, to_dir=tmp_fil, dims={"t":sk_t}, verbose=verbose)
        del sds, dg
        sds = xr.open_zarr(tmp_fil)
        print("stored interpolated velocity")
    return sds

def proj_ychk(ds, regy):
    dg = open_grid_file(isel={ydim:regy})
    #dg = ds_g.get(["phi", "norm"]).reset_coords(drop=True).copy()
    phi = dg.phi.reset_coords(drop=True).persist()
    norm = dg.norm.reset_coords(drop=True).persist()
    dg.close(); del dg
    amod = (ds[varname] * phi).sum("z_c")/norm

    amod = amod.to_dataset(name=varname) #proj_pres(sds.pres, ds_g)
    fname = f"modamp_{var}_{iday}_y{regy.start}-{regy.stop}.zarr"
    uc.custom_distribute(amod, to_dir=scratch/fname, dims={"t":sk_t}, verbose=verbose)
    return scratch/fname

################################################################################
##########   - - -   Start Main Work   - - -   #################################
################################################################################
if __name__ == "__main__":
    if (log_dir/log_file.format(da)).exists():
        raise ValueError("{} already processed? found corresponding log file".format(da))
        os._exit()
    logging.info("will process date {} (i_day {})".format(da,iday))

    from dask.distributed import LocalCluster, Client#, wait
    import dask
    dask.config.set({"distributed.workers.memory.spill":0.8})
    if False:
        cluster = LocalCluster(n_workers=7, local_directory=scratch)
        client = Client(cluster)
    else:
        from dask_mpi import initialize
        initialize(nthreads=8, interface="ib0", memory_limit=10e9,
                    dashboard=False, local_directory=scratch)
        client = Client()
    logging.info("Cluster should be connected -- dashboard at {}".format(client.dashboard_link))

    if regy is not None:
        tmes = time.time()
        ds = io.open_one_var(from_files[varname],
                             chunks=inp_chks, varname=varname\
                            ).reset_coords(drop=True)
        logging.info("opened uv data -- ellapsed time {:.1f} s".format(time.time()-tmes))

        ds_g = open_grid_file()
        if regy is not None and regy.stop is None:
            regy = slice(0, ds_g.dims[ydim])
        ds_g.close(); del ds_g

        for jy in range(regy.start, regy.stop, sk_y):
            regy = slice(jy, jy+sk_y)

            tmes, tmeg = time.time(), time.time()
            sdg, xgrid = prep_grid_ychk(ds, regy)
            logging.info("prep grid, took {:.1f} s".format(time.time()-tmes))

            tmes = time.time()
            sds = zinterp_uv_ychk(ds, sdg, xgrid)
            logging.info("interp uv on mean grid, took {:.1f} s".format(time.time()-tmes))

            tmes = time.time()
            filnam = proj_ychk(sds, regy)
            logging.info("projected and stored, took {:.1f} s".format(time.time()-tmes))

            if not store_uv:
                del sdg
            del sds
            with open(file_list, "a") as fp:
                fp.write(str(filnam)+"\n")
            logging.info("jy={}-{} took {:.1f} s".format(jy,jy+sk_y, time.time()-tmeg))
            #client.restart()
        shutil.rmtree(tmp_fil)

### read files, rechunk and store
    if finish:
        tmes = time.time()
        with open(file_list, "r") as fp:
            file_listes = list(set(r.rstrip('\n') for r in fp.readlines()))
        ds = xr.open_mfdataset(file_listes, engine="zarr")
        ds = ds.chunk(str_chks)
        ds[varname].encoding.pop("chunks")
        attrs = dict(description = f"{var}-velocityp modal amplitude, resulting from the projection "
                         "of the horizontal velocity on the vertical modes",
                     day_of_simulation = da, iday = iday,
                     simulation = "eNATL60 (with tides)",
                     from_files = [str(v) for v in from_files.values()],
                     generating_script = sys.argv[0],
                     date_generated = logging.time.strftime("%Y-%m-%d (%a at %H h)"),
                     creator = "N. Lahaye (noe.lahaye@inria.fr)"
                     )
        ds.attrs = attrs
        ds[varname].attrs.update(dict(long_name=f"{ditp}-component of horizontal velocity modal amplitude",
                                      units="m/s"
                                                          ))
        ds.to_zarr(out_file, mode="w", compute=True, consolidated=True, safe_chunks=True)
        logging.info(f"rechunked and stored final file in {out_file}"
                       "; took {:.1f} s; THE END".format(time.time()-tmes))
        for f in file_listes:
            shutil.rmtree(f)
        #file_list.unlink()

        ### create log file with some information
        with open(log_dir/log_file.format(da), "w") as fp:
            fp.write("JOB ID: {}\n".format(os.getenv("SLURM_JOBID")))
            fp.write("python script: {}\n".format(sys.argv[0]))
            fp.write(f"i_day {iday}, date {da}\n")
            fp.write(f"nk_t {sk_t}, sk_y {sk_y}\n")
            fp.write(f"read chunks {inp_chks}, working chunks {wrk_chks}, store chunks {str_chks}\n")


#!/usr/bin/env python3

from os import path
import string

prio = string.ascii_lowercase + string.ascii_uppercase

with open(path.join(path.dirname(__file__), "input.txt")) as f:
    lines = f.read().splitlines()

    part1 = 0
    for line in lines:
        half = len(line) // 2
        a, b = line[:half], line[half:]
        part1 += sum(prio.index(c) + 1 for c in set(a) & set(b))
    print("Part 1:", part1)

    part2 = 0
    for a, b, c in zip(lines[::3], lines[1::3], lines[2::3]):
        part2 += sum(prio.index(c) + 1 for c in set(a) & set(b) & set(c))
    print("Part 2:", part2)


from __future__ import absolute_import, print_function
import pytest
import os
from mantid.api import AnalysisDataService

from tests import DATA_DIR

from addie.rietveld.braggtree import BraggTree, BankRegexException
from addie.main import MainWindow
from addie.rietveld import event_handler

@pytest.fixture
def main_window(qtbot):
    main_window = MainWindow()
    return main_window

@pytest.fixture
def rietveld_event_handler(qtbot):
    return event_handler

@pytest.fixture
def bragg_tree(qtbot, main_window):
    return BraggTree(main_window)

@pytest.fixture
def bragg_tree_loaded(qtbot, rietveld_event_handler, main_window):
    filenames = ['GSAS_NaNO3_230C.gsa', 'GSAS_NaNO3_275C.gsa']
    bragg_file_names = [ os.path.join(DATA_DIR, f) for f in filenames ]
    rietveld_event_handler.load_bragg_files(main_window, bragg_file_names)
    bragg_tree = main_window.rietveld_ui.treeWidget_braggWSList
    return bragg_tree

@pytest.fixture
def test_get_tree_structure(qtbot, bragg_tree_loaded):
    """Test we can get the Bragg tree structure without exception"""
    bragg_tree_loaded._get_tree_structure()

@pytest.fixture
def test_add_bragg_ws_group(qtbot, bragg_tree):
    """Test we can add a list of banks to workspace group"""
    ws_group_name = "WorkspaceGroup"
    bank_angles = [20, 30, 90]
    bank_list = list()
    for i, angle in enumerate(bank_angles):
        bank_list.append('Bank {} - {}'.format(i + 1, angle))
    bragg_tree.add_bragg_ws_group(ws_group_name, bank_list)

@pytest.fixture
def test_get_bank_id(qtbot, bragg_tree):
    """Test we can extract a bank id from bank workspace name"""
    target = 12345
    bank_wksp_name = "Bank {} - 90.0".format(target)
    bank_id = bragg_tree._get_bank_id(bank_wksp_name)
    assert int(bank_id) == target

@pytest.fixture
def test_get_bank_id_exception(qtbot, bragg_tree):
    """Test for raised exception from a bad workspace name"""
    bad_ws = "Bank jkl 1 -- 90.0"
    with pytest.raises(BankRegexException):
        bragg_tree._get_bank_id(bad_ws)

@pytest.fixture
def test_do_plot_ws(qtbot, bragg_tree_loaded):
    """Test for plotting selected bank workspace"""
    group_index = bragg_tree_loaded.model().index(1,0)
    bank_index = bragg_tree_loaded.model().index(0,0,group_index)
    bragg_tree_loaded.setCurrentIndex(bank_index)
    print(AnalysisDataService.getObjectNames())
    ws = AnalysisDataService.retrieve('GSAS_NaNO3_230C')
    print(ws.id())
    bragg_tree_loaded.do_plot_ws()

@pytest.fixture
def test_do_plot_ws_exception(qtbot):
    """Test for raised exception from MainWindow==None"""
    bragg_tree = BraggTree(None)
    with pytest.raises(NotImplementedError):
        bragg_tree.do_plot_ws()


class Solution:
    def maxPoints(self, points: List[List[int]]) -> int:
        def gcd(a, b):
            if a == 0:
                return b
            if b == 0:
                return a
            return gcd(b, a%b)
        n = len(points)
        if n < 3:
            return n
        weight = {}
        for p in points:
            if (p[0], p[1]) not in weight:
                weight[(p[0], p[1])] = 1
            else:
                weight[(p[0], p[1])] += 1
        lines = {}
        for i in range(1, n):
            for j in range(i):
                dx = points[i][0] - points[j][0]
                dy = points[i][1] - points[j][1]
                g = gcd(dx, dy)
                slope = (dx/g, dy/g) if dx != 0 else float('inf')
                y_int = points[i][1] - slope[1]/slope[0]*points[i][0] if slope != float('inf') else str(points[i][0])
                if (slope, y_int) not in lines:
                    lines[(slope, y_int)] = set({(points[i][0], points[i][1]), (points[j][0], points[j][1])})
                else:
                    lines[(slope, y_int)].update({(points[i][0], points[i][1]), (points[j][0], points[j][1])})
        def process(x):
            ans = 0
            for i in x:
                ans += weight[i]
            return ans
        return max([process(x) for x in lines.values()])


from enigma import *
from Screens.Screen import Screen
from Components.ActionMap import ActionMap
from Components.MenuList import MenuList
from Components.GUIComponent import GUIComponent
from Components.HTMLComponent import HTMLComponent
from Tools.Directories import fileExists
from Components.MultiContent import MultiContentEntryText, MultiContentEntryPixmapAlphaTest

def SimpleEntry(name, picture):
    res = [(name, picture)]
    picture = '/usr/lib/enigma2/python/Plugins/SystemPlugins/DeviceManager/icons/' + picture
    if name == '---':
        if fileExists(picture):
            res.append(MultiContentEntryPixmapAlphaTest(pos=(0, 22), size=(470, 4), png=loadPNG(picture)))
    else:
        if fileExists(picture):
            res.append(MultiContentEntryPixmapAlphaTest(pos=(0, 0), size=(48, 48), png=loadPNG(picture)))
        res.append(MultiContentEntryText(pos=(60, 10), size=(420, 38), font=0, text=name))
    return res

class ExtrasList(MenuList, HTMLComponent, GUIComponent):

    def __init__(self, list, enableWrapAround=False):
        GUIComponent.__init__(self)
        self.l = eListboxPythonMultiContent()
        self.list = list
        self.l.setList(list)
        self.l.setFont(0, gFont('Regular', 21))
        self.l.setItemHeight(48)
        self.onSelectionChanged = []
        self.enableWrapAround = enableWrapAround
        self.last = 0

    GUI_WIDGET = eListbox

    def postWidgetCreate(self, instance):
        instance.setContent(self.l)
        instance.selectionChanged.get().append(self.selectionChanged)
        if self.enableWrapAround:
            self.instance.setWrapAround(True)

    def selectionChanged(self):
        isDiv = False
        try:
            for element in self.list[self.getSelectionIndex()]:
                if element[0] == '---':
                    isDiv = True
                    if self.getSelectionIndex() < self.last:
                        self.up()
                    else:
                        self.down()

        except Exception as e:
            pass

        self.last = self.getSelectionIndex()
        if not isDiv:
            for f in self.onSelectionChanged:
                f()


import math

def jumpSearch(arr, n, x):
    step = int(math.sqrt(n))
    prev = 0

    while arr[min(step, n)-1] < x:
        prev = step
        step += int(math.sqrt(n))
        if prev > n:
            return -1
    while arr[prev] < x:
        prev += 1

        if prev == min(step, n):
            return -1

    if arr[prev] == x:
        return prev
    return -1

print('enter the array elements')
s = input()
arr = [int(y) for y in s.split()]

print('Enter the number to search')

x = int(input())

result = jumpSearch(arr, len(arr), x)

if result != -1:
    print('Element is present at index:', result)

else:
    print('Element not present in the array')


import numpy as np
import pymc as pm

from bn_testing.terms import (
    Linear,
    Polynomial,
    Constant,
)

class Conditional(object):
    """
    Base class of conditional distributions
    """

    def make_term(self, parents, node):
        """
        Builds a term randomly.

        :param list parents: Name of the parent nodes.
        :param str node: Name of the node whose term  should be made

        :returns: A term
        :rtype: bn_testing.term.Term
        """
        raise NotImplementedError()

    def init(self, random):
        self.random = random

    def make_noise(self):
        return pm.Normal.dist(mu=0, sigma=0.05)

    def make_source(self):
        return pm.Beta.dist(
            alpha=self.random.uniform(1, 5),
            beta=self.random.uniform(1, 5),
        )

    def __call__(self, parents, node):
        """
        """
        return self.make_term(parents=parents, node=node)

class LinearConditional(Conditional):
    """
    Linear conditionals
    """

    def __init__(self, coef_min=0.5, coef_max=1):
        self.coef_min = coef_min
        self.coef_max = coef_max

    def make_term(self, parents, node):
        n_parents = len(parents)
        signs = self.random.choice([-1, 1], size=n_parents)
        coefs = signs*self.random.uniform(self.coef_min, self.coef_max, size=n_parents)
        return Linear(
            parents=parents,
            coefs=coefs
        )

class PolynomialConditional(Conditional):
    """
    Conditional that builds randomized polynomial terms

    :param int min_terms: Minimal number of terms in a generated polynomial
    :param int min_terms: Maximal number of terms in a generated polynomial
    :param int max_degree_add: Number to add on the number of variables in a monomial to get its
        largest possible degree
    :param bool with_tanh: Whether :py:func:`numpy.tanh` should be applied onto the monmial
    :param bool with_log: Whether each monomial should be wrapped by :py:func:`log1p` expression

    """

    def __init__(self, min_terms=1, max_terms=5, max_degree_add=10, with_tanh=True, with_log=False):
        self.min_terms = min_terms
        self.max_terms = max_terms
        self.max_degree_add = max_degree_add
        self.with_tanh = with_tanh
        self.with_log = with_log

    def _get_random_exponent(self, degree, n_variables):
        """
        Computes a random monomial exponent in `n_variables` many variables of given degree where
        no variable vanishes.

        :param int degree: Sum of all exponents
        :param int n_variables: Number of variables

        :returns: Integer Array of length `n_variables` that sum to `degree` where no entry
            is zero.
        :rtype: numpy.ndarray

        """
        assert degree >= n_variables
        return np.ones(n_variables) + self.random.multinomial(
            degree - n_variables,
            [1/n_variables]*n_variables
        )

    def make_term(self, parents, node):
        n_parents = len(parents)

        n_monomials = self.random.randint(self.min_terms, self.max_terms+1)
        degree = n_parents+self.random.randint(1, self.max_degree_add)

        exponents = [
            self._get_random_exponent(
                degree=degree,
                n_variables=n_parents,
            ) for _ in range(n_monomials)
        ]

        signs = self.random.choice([-1, 1], size=n_monomials)
        coefs = signs * self.random.uniform(1, 10, size=n_monomials)
        return Polynomial(
            parents=parents,
            exponents=exponents,
            coefs=coefs,
            intercept=0,
            with_tanh=self.with_tanh,
            with_log=self.with_log,
        )

class ConstantConditional(Conditional):
    """
    A conditional yielding constant values. Used in intervensions and to compute causal effects.
    """

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

    def make_term(self, parents, node):
        return Constant(parents=parents, value=self.value)

    def make_noise(self):
        return pm.math.constant(0)

    def make_source(self):
        return pm.math.constant(self.value)


from odoo import api, fields, models, _
from odoo.exceptions import ValidationError

class ExtraComponent(models.Model):
    _name = "extra.component"
    _description = "BOM Extra Component"
    _rec_name = 'name'

    name = fields.Char('Package Name', required=True)
    max_qty = fields.Integer(string="Maximum Amount")
    min_qty = fields.Integer(string="Minimum Amount")
    description = fields.Text(string='Description')
    product_ids = fields.Many2many('product.product', string="Products")

class MrpBom(models.Model):
    _inherit = 'mrp.bom'

    extra_component_ids = fields.Many2many('extra.component',  string='Extra')


# -*- coding: utf-8 -*-
import logging
from copy import copy

import bson
import six

from nvesta.library.rb.classes import Undefined

__author__ = 'viruzzz-kun'

logger = logging.getLogger(__name__)

class RefBookRecordMeta(object):
    __slots__ = ['beg_version', 'end_version', 'delete', 'draft', 'edit']

    def __init__(self, db_record=None):
        self.beg_version = None
        self.end_version = None
        self.delete = False
        self.draft = False
        self.edit = None
        if db_record:
            self.set_record(db_record)

    def set_record(self, db_record):
        self.beg_version = db_record.get('beg_version', None)
        self.end_version = db_record.get('end_version', None)
        self.delete = db_record.get('delete', False)
        self.draft = db_record.get('draft', False)
        self.edit = db_record.get('edit', None)

    def update(self, data):
        for key, value in six.iteritems(data):
            if key in self.__slots__:
                setattr(self, key, value)
        return self

    def as_db_record(self):
        return {
            key: getattr(self, key)
            for key in self.__slots__
        }

    def __json__(self):
        return self.as_db_record()

    @classmethod
    def from_rb_meta(cls, rb_meta):
        result = cls()
        result.beg_version = rb_meta.version
        return result

class RefBookRecord(object):
    """
    :type rb: RefBook
    """
    __slots__ = ['data', 'rb', 'meta', '_id']
    rb = None

    def __init__(self, record=None):
        self.meta = meta = RefBookRecordMeta.from_rb_meta(self.rb.meta)
        meta.draft = True
        self.data = {}
        self._id = None
        if record:
            self.set_rb_record(record)

    # DB Data Manipulations

    def set_rb_record(self, record):
        """
        Загрузка документа из БД в объект
        @param record: Документ в БД
        @type record: dict
        """
        self.data.clear()
        for description in self.rb.meta.fields:
            key = description.key
            value = record.get(key, Undefined)
            if value is not Undefined:
                self.data[key] = value
            else:
                self.data[key] = None

        _id = record.get('_id', Undefined)
        if isinstance(_id, bson.ObjectId):
            self._id = _id
        elif isinstance(_id, basestring):
            self._id = bson.ObjectId(_id)
        elif _id is not Undefined:
            self._id = None

        _meta = record.get('_meta', Undefined)
        if not (_meta is Undefined or _meta is None):
            self.meta = RefBookRecordMeta(_meta)
        elif not self.meta:
            self.meta = meta = RefBookRecordMeta.from_rb_meta(self.rb.meta)
            meta.draft = True

    def as_db_record(self, with_id=False):
        """
        Преобразование записи к документу БД
        @return: Документ
        @rtype: dict
        """
        if self._id and with_id:
            return dict(
                self.data,
                _id=self._id,
                _meta=self.meta.as_db_record(),
            )
        else:
            return dict(
                self.data,
                _meta=self.meta.as_db_record(),
            )

    # Basic Data Manipulations

    def update(self, record, weak=True):
        """
        Обновление данных записи.
        - Если запись не завиксирована в справочнике, то редактируется на месте
        - Если зафиксирована, но отредактирована, то изменяется редактируемая версия (._meta.edit)
        - Если зафиксирована, но не отредактирована, то создаётся редактируемая версия и п.2
        @param record: свежие данные для редактирования
        @param weak: если True, то запись PATCH-ится, иначе перезаписывается
        """
        if self.meta.draft:
            # Если это драфт для следующей версии, но меняем его на месте
            data = self.data
        else:
            if self.meta.edit is None:
                # Если это не драфт, но и не изменённая прежде запись, создаём новую версию
                self.meta.edit = data = copy(self.data)
            else:
                # Если это не драфт, и он уже редактировался, берём редактируемую версию
                data = self.meta.edit

        skipped = set()  # здесь будут сохраняться коды полей, которые не присутствуют в передаваемом документе
        for description in self.rb.meta.fields:
            key = description.key
            value = record.get(key, Undefined)
            if value is not Undefined:
                data[key] = value
            else:
                skipped.add(key)

        if not weak:
            for key in skipped:
                data[key] = None

        if self.meta.edit == self.data:
            # Если изменённая версия идентична имеющейся, считаем запись неизменённой
            self.meta.edit = None

        self.meta.delete = False  # запись не будет считаться удалённой

        return self

    def delete(self):
        """
        Удаление записи из справочника
        """
        if not self.meta.end_version:
            self.meta.delete = True
            self.meta.edit = None
        return self

    def reset(self):
        """
        Откат всех изменений версии к фиксированной
        @return:
        """
        if self.meta.end_version is not None:
            logger.warning(u'Resetting fixed record for some reason: _id = %s', self.data.get('_id', 'UNSAVED'))
            return

        if self.meta.edit:
            self.meta.edit = None

        if self.meta.delete:
            self.meta.delete = False

        if self.meta.draft:
            self.rb.delete_record(self)

    # Auxiliary helpers

    def save(self):
        self.rb.save(self)
        return self

    @classmethod
    def for_refbook(cls, refbook):
        class RefBookRecordF(RefBookRecord):
            rb = refbook
        return RefBookRecordF

    def __contains__(self, item):
        return item in self.rb.meta

    def __getitem__(self, item):
        if item in self.rb.meta:
            return self.data.get(item)

    def __setitem__(self, key, value):
        if key in self.rb.meta:
            self.data[key] = value

    def __iter__(self):
        return iter(self.data)

    def get(self, item, default=None):
        if item in self.rb.meta:
            return self.data.get(item, default)
        return default

    def as_json(self, edge=True, with_meta=False):
        from nvesta.library.rb.registry import RefBookRegistry

        if edge:
            data = self.meta.edit or self.data
        else:
            data = self.data

        result = {}
        for description in self.rb.meta.fields:
            key = description.key
            value = data.get(key)
            result[key] = value
            if description.link:
                add_key = description.link['key']
                rb_code = description.link['code']
                rb_field = description.link['linked_field']
                as_list = description.link.get('list')
                ref_book = RefBookRegistry.get(rb_code)
                if as_list:
                    result[add_key] = ref_book.find({rb_field: value})
                else:
                    result[add_key] = ref_book.find_one({rb_field: value})

        if self._id:
            result['_id'] = str(self._id)

        if with_meta:
            _meta = self.meta.__json__()
            dirty = bool(_meta.pop('edit', False))
            result['_meta'] = dict(_meta, dirty=dirty)
        return result

    def __json__(self):
        return self.as_json(False)


import requests
from bot_db import get_cursor, add_to_db2

# table = 'app_freebotip'
check_query = "SELECT id FROM app_linkedinuser WHERE bot_ip=%s"
check_query2 = "SELECT id FROM app_freebotip WHERE bot_ip=%s"

insert_query = """INSERT INTO app_freebotip (`bot_ip`) VALUES(%s)"""

SERVER_IP = None

def get_ip():
    global SERVER_IP
    if SERVER_IP:
        return SERVER_IP

    res = requests.get('http://ip.42.pl/raw')
    ip = res.text.strip()
    SERVER_IP = ip
    print('ip:', ip)
    return ip

def get_db_row(cur, sql, *values):
    cur.execute(sql, values)
    return cur.fetchone()

def check_bot_ip(cur, ip):

    row = get_db_row(cur, check_query, ip)

    if row is None:
        print('{0} ip is not used in linkedinUser table'.format(ip))
        row = get_db_row(cur, check_query2, ip)
    return row

def check_and_add_ip(cur=None):
    if cur is None:
        cur = get_cursor()

    ip = get_ip()

    row = check_bot_ip(cur, ip)
    if row is None:
        print('{0} ip is not in app_freebotip table'.format(ip))
        add_to_db2(cur, insert_query, ip)


# Желан резултат
# Започва тренировката 30см по-ниско от целта
# За всяка височина има право на 3 скока, като за да бъде успешен трябва да бъде над височината на летвата
# При успешен скок, височината се вдига с 5см
# Тренировката приключва при 3 неуспешни скока на една и съща височина или при достигане на желаната височина

target_height = int(input())
stick_height = target_height - 30
total_jumps = 0
failed = False
while stick_height <= target_height:
    bad_jumps = 0
    for jumps in range(1, 4):
        total_jumps += 1
        height_jump = int(input())
        if height_jump > stick_height:
            stick_height += 5
            break
        else:
            bad_jumps += 1
    if bad_jumps == 3:
        failed = True
        break
if failed:
    print(f"Tihomir failed at {stick_height}cm after {total_jumps} jumps.")
else:
    print(f"Tihomir succeeded, he jumped over {target_height}cm after {total_jumps} jumps.")