import os, time
from nose.tools import assert_raises
from webassets import Environment, Bundle
from webassets.exceptions import BundleError
from webassets.updater import TimestampUpdater, BundleDefUpdater, SKIP_CACHE
from webassets.cache import MemoryCache
from helpers import TempEnvironmentHelper

class TestBundleDefBaseUpdater:
    """Test the updater which caches bundle definitions to determine
    changes.
    """

    def setup(self):
        self.env = Environment(None, None)  # we won't create files
        self.env.cache = MemoryCache(capacity=100)
        self.bundle = Bundle(output="target")
        self.updater = BundleDefUpdater()

    def test_no_rebuild_required(self):
        # Fake an initial build
        self.updater.build_done(self.bundle, self.env)
        # without any changes, no rebuild is required
        assert self.updater.needs_rebuild(self.bundle, self.env) == False

        # Build of another bundle won't change that, i.e. we use the
        # correct caching key for each bundle.
        bundle2 = Bundle(output="target2")
        self.updater.build_done(bundle2, self.env)
        assert self.updater.needs_rebuild(self.bundle, self.env) == False

    def test_filters_changed(self):
        self.updater.build_done(self.bundle, self.env)
        self.bundle.filters += ('jsmin',)
        assert self.updater.needs_rebuild(self.bundle, self.env) == True

    def test_contents_changed(self):
        self.updater.build_done(self.bundle, self.env)
        self.bundle.contents += ('foo.css',)
        assert self.updater.needs_rebuild(self.bundle, self.env) == True

    def test_debug_changed(self):
        self.updater.build_done(self.bundle, self.env)
        self.bundle.debug = not self.bundle.debug
        assert self.updater.needs_rebuild(self.bundle, self.env) == True

    def test_depends_changed(self):
        # Changing the depends attribute of a bundle will NOT cause
        # a rebuild. This is a close call, and might just as well work
        # differently. I decided that the purity of the Bundle.__hash__
        # implementation in not including anything that isn't affecting
        # to the final output bytes was more important. If the user
        # is changing depends than after the next rebuild that change
        # will be effective anyway.
        self.updater.build_done(self.bundle, self.env)
        self.bundle.depends += ['foo']
        assert self.updater.needs_rebuild(self.bundle, self.env) == False

class TestTimestampUpdater(TempEnvironmentHelper):

    default_files = {'in': '', 'out': ''}

    def setup(self):
        TempEnvironmentHelper.setup(self)

        # Test the timestamp updater with cache disabled, so that the
        # BundleDefUpdater() base class won't interfere.
        self.m.cache = False
        self.m.updater = TimestampUpdater()

    def test_timestamp_behavior(self):
        bundle = self.mkbundle('in', output='out')

        # Set both times to the same timestamp
        now = self.setmtime('in', 'out')
        assert self.m.updater.needs_rebuild(bundle, self.m) == False

        # Make in file older than out file
        now = self.setmtime('in', mtime=now-100)
        now = self.setmtime('out', mtime=now)
        assert self.m.updater.needs_rebuild(bundle, self.m) == False

        # Make in file newer than out file
        now = self.setmtime('in', mtime=now)
        now = self.setmtime('out', mtime=now-100)
        assert self.m.updater.needs_rebuild(bundle, self.m) == True

    def test_source_file_deleted(self):
        """If a source file is deleted, rather than raising an error
        when failing to check it's timestamp, we ask for a rebuild.

        The reason is that when a wildcard is used to build the list of
        source files, this is the behavior we want: At the time of the
        update check, we are presumably using a cached version of the
        bundle contents. For the rebuild, the contents are refreshed.

        So if the file that is missing was included via a wildcard, the
        rebuild will go through, without the file. If a file is gone
        missing that he user specifically added to the bundle, then the
        build process is going to raise the error (this is tested
        separately).
        """
        self.create_files({'1.css': '', '2.css': ''})
        bundle = self.mkbundle('in', '*.css', output='out')

        # Set all mtimes to the same timestamp
        self.setmtime('in', 'out', '1.css', '2.css')
        assert self.m.updater.needs_rebuild(bundle, self.m) == False

        # Delete a wildcarded file
        os.unlink(self.path('1.css'))
        assert self.m.updater.needs_rebuild(bundle, self.m) == True

    def test_bundle_definition_change(self):
        """Test that the timestamp updater uses the base class
        functionality of determining a bundle definition change as
        well.
        """
        self.m.cache = MemoryCache(capacity=100)
        bundle = self.mkbundle('in', output='out')
        now = time.time()

        # Fake an initial build
        self.m.updater.build_done(bundle, self.m)

        # Make in file older than out file
        os.utime(self.path('in'), (now, now-100))
        os.utime(self.path('out'), (now, now))
        assert self.m.updater.needs_rebuild(bundle, self.m) == False

        # Change the bundle definition
        bundle.filters = 'jsmin'

        # Timestamp updater will says we need to rebuild.
        assert self.m.updater.needs_rebuild(bundle, self.m) == True
        self.m.updater.build_done(bundle, self.m)

    def test_depends(self):
        """Test the timestamp updater properly considers additional
        bundle dependencies.
        """
        self.create_files({'d.sass': '', 'd.other': ''})
        bundle = self.mkbundle('in', output='out', depends=('*.sass',))

        # First, ensure that the dependency definition is not
        # unglobbed until we actually need to do it.
        internal_attr = '_resolved_depends'
        assert not getattr(bundle, internal_attr, None)

        now = time.time()

        # Make all files older than the output
        now = self.setmtime('out')
        self.setmtime('in', 'd.sass', 'd.other', mtime=now-100)
        assert self.m.updater.needs_rebuild(bundle, self.m) == False

        # Touch the file that is supposed to be unrelated
        self.setmtime('d.other', mtime=now+100)
        assert self.m.updater.needs_rebuild(bundle, self.m) == False

        # Touch the dependency file - now a rebuild is required
        self.setmtime('d.sass', mtime=now+100)
        assert self.m.updater.needs_rebuild(bundle, self.m) == SKIP_CACHE

        # Finally, counter-check that our previous check for the
        # internal attribute was valid.
        assert hasattr(bundle, internal_attr)

    def test_depends_nested(self):
        """Test the dependencies of a nested bundle are checked too.
        """
        self.create_files({'dependency': ''})
        bundle = self.mkbundle('in', Bundle('in', depends='dependency'),
                               output='out', )
        now = self.setmtime('out')
        self.setmtime('in', mtime=now-100)
        self.setmtime('dependency', mtime=now+100)

        assert self.m.updater.needs_rebuild(bundle, self.m) == SKIP_CACHE

    def test_wildcard_dependency_deleted(self):
        """If a dependency is deleted, a rebuild is always
        required.

        [Regression] This used to raise an error.
        """
        self.create_files({'1.sass': '', '2.sass': ''})
        bundle = self.mkbundle('in', output='out', depends=('*.sass',))

        # Set mtimes so that no update is required
        self.setmtime('1.sass', '2.sass', 'in', 'out')
        assert self.m.updater.needs_rebuild(bundle, self.m) == False

        # Delete a dependency
        os.unlink(self.path('1.sass'))
        # Now we need to update
        assert self.m.updater.needs_rebuild(bundle, self.m) == SKIP_CACHE

    def test_static_dependency_missing(self):
        """If a statically referenced dependency does not exist,
        an error is raised.
        """
        bundle = self.mkbundle('in', output='out', depends=('file',))
        assert_raises(BundleError, self.m.updater.needs_rebuild, bundle, self.m)


"""
Bootcamp código[s]
Data: 10/03/2022
aula 06
tema: Funções

Observações: tipagem como boa prática. Por exemplo: def calcula_media(lst: list) -> float:
    Apesar de não ser necessário, ajuda no entendimento do código. Fica fácil para qualquer pessoa que esta função requer uma entrada do tipo list e irá retornar uma variável do tipo float.

Obs2: Doc string
    Utiliza-se para descrever melhor uma função, caso não esteja suficientemente esclarecido. Trata-se de boa prática e não se confunde com comentários (que usa hastag)

Obs3: def soma (a: int, b: int = 10)
    b se tornou um argumento opcional. A função deve recerber ao menos um argumento, para a. Quando houver parâmentros opcionais, eles devem ser colocados por último.
    No momento de chamar a função, pode usar por posição e por keyword (a=2, b=3). Pode misturar, mas nunca poderá o argumento poscional vir depois de argumentos por ketwords.

"""

def calcula_media(lst: list) -> float:
    return sum(lst) / len(lst)

def calcula_media_ponderada(valores: list, pesos: tuple or None = None) -> float:
    """ Calcula média ponderada quando as notas possuem pesos distintos"""
    if not pesos:
        pesos = (1,)*len(valores)

    numerador = 0
    divisor = sum(pesos)
    for valor, peso in zip(valores, pesos):
        numerador += valor*peso
    return numerador / divisor

fechamento = dict()

numero_de_alunos = int( input("Quantos alunos pretende cadastrar? "))
numero_de_notas = int( input("Quantas notas de cada alunos pretende cadastrar? "))

for _ in range(numero_de_alunos):
    nome = input("Informe o nome do aluno: ")
    fechamento[nome] = []

    for i in range(numero_de_notas):
        nota = int(input(f"Informe a {i +1}ª nota de {nome}: "))
        fechamento[nome].append(nota)

for aluno, notas in fechamento.items():
    media = calcula_media_ponderada(notas)
    print(f"A média do aluno(a) {aluno} é {media}")


class Licznik:
    ile = 0  # pole statyczne, poza initem!

    def __init__(self):
        Licznik.ile += 1  # odwolanie do pola statycznego
        self.ktory = Licznik.ile
        print(f'To jest obiekt nr {Licznik.ile}')

    # destruktor, on dziala zawsze na koncu! to wszystko, cala procedura niszczenia i tak sie dzieje, ale to tylko, zeby wyprintowac co sie tam dzieje
    def __del__(self):
        Licznik.ile -= 1
        print(f'niszcze obiekt nr {self.ktory}, pozostalo jeszcze {Licznik.ile}')

    @staticmethod #metoda statyczna dekorator, do modyfikacji funkcji
    def policz():
        return Licznik.ile

def main():
    a = Licznik()
    b = Licznik()
    c = Licznik()
    print(f'a to obiekt nr {a.ktory}')
    print(f'b to obiekt nr {b.ktory}')
    print(f'c to obiekt nr {c.ktory}')
    print(f'Liczba obiektow to: {Licznik.policz()}') # po tym wchodzi destruktor
    a = None
    b = None
    print(f'Liczba obiektow to: {Licznik.policz()}')

if __name__ == "__main__":
    main()


from collections import deque, defaultdict
def diff(str1, str2):
    diffNum = 0
    for c1, c2 in zip(str1, str2):
        if c1 != c2:
            diffNum += 1

        if diffNum > 1:
            return False
    return True

def bfs(begin, target, words, graph):
    visited = dict.fromkeys(words, False)
    queue = deque([[begin, 0]])
    visited[begin] = True
    answer = 0

    while queue:
        before, result = queue.popleft()
        if before == target:
            answer = result
            return answer

        for word in graph[before]:
            if not visited[word]:
                queue.append([word, result + 1])
                visited[word] = True
    return answer

def solution(begin, target, words):
    words.insert(0, begin)
    graph = defaultdict(list)

    for str1 in words:
        for str2 in words:
            if str1 == str2 or str2 == begin:
                continue

            if diff(str1, str2):
                graph[str1].append(str2)
    return bfs(begin, target, words, graph)

print(solution("hit", "cog", ["hot", "dot", "dog", "lot", "log", "cog"]))
print(solution("hit", "cog", ["hot", "dot", "dog", "lot", "log"]))


import asyncio, aiohttp, collections, tqdm
from aiohttp import web
from flags2_common import main, HTTPStatus, Result, save_flag

DEFAULT_CONCUR_REQ = 5
MAX_CONCUR_REQ = 1000

class FetchError(Exception):
    def __init__(self, country_code):
        self.country_code = country_code

async def get_flag(base_url, cc):
    url = '{}/{cc}/{cc}.gif'.format(base_url, cc=cc.lower())
    resp = await aiohttp.request('GET', url)
    if resp.status == 200:
        image = await resp.read()
        return image
    elif resp.status == 404:
        raise web.HTTPNotFound()
    else:
        raise aiohttp.HttpProcessingError(code=resp.status, message=resp.reason, headers=resp.headers)

async def download_one(cc, base_url, semaphore, verbose):
    try:
        with (await semaphore):
            image = await get_flag(base_url, cc)
    except web.HTTPNotFound:
        status = HTTPStatus.not_found
        msg = 'not found'
    except Exception as exc:
        raise FetchError(cc) from exc
    else:
        save_flag(image, cc.lower() + '.gif')
        status = HTTPStatus.ok
        msg = 'ok'
    if verbose and msg:
        print(cc, msg)
    return Result(status, cc)

def download_many(cc_list):
    loop = asyncio.get_event_loop()
    to_do = [download_one(cc) for cc in sorted(cc_list)]
    wait_coro = asyncio.wait(to_do)
    res, _ = loop.run_until_complete(wait_coro)
    loop.close()
    return len(res)

if __name__ == '__main__':
    main(download_many)


import os
from app import app, lm
from flask import render_template, flash, redirect, request, url_for
from flask.ext.login import login_user, login_required, logout_user, current_user
from app.models import User, Book, Author
from database import db_session
from forms import LoginForm, BookForm, AuthorForm, RegistrationForm, SearchForm
import random

#                       User/login
@lm.user_loader
def load_user(id):
  return User.query.get(int(id))

@lm.unauthorized_handler
def unauthorized():
  flash("Login required.", "danger")
  return redirect(url_for('index'))

@app.errorhandler(404)
def page_not_found(e):
    return render_template('404.html'), 404

@app.errorhandler(500)
def page_not_found(e):
    return render_template('500.html'), 500

@app.route('/register/', methods=('GET', 'POST'))
def register_view():
  if current_user.is_authenticated():
    flash('sorry, registration is available only for not-authorised users')
    return redirect(url_for('index'))
  form_r = RegistrationForm()
  form=LoginForm()
  if form_r.validate_on_submit() and form_r.validate_login():
      user = User()
      user.name = form_r.name.data
      user.email = form_r.email.data
      user.set_password(form_r.password.data)
      db_session.add(user)
      db_session.commit()
      flash('User %s created succesfully' %(user.email),'success')
      if current_user.is_authenticated():
          logout_user()
      login_user(user)
      return redirect(url_for('index'))
  return render_template('register.html',form = form, form_r=form_r, user=current_user, is_authenticated=current_user.is_authenticated())

@app.route('/login/', methods=['GET', 'POST'])
def login():
  form = LoginForm()
  if form.validate_on_submit():
      user = form.get_user()
      if user and user.check_password(form.password.data):
        login_user(user)
        flash('Welcome ' + user.email, 'success')
        return redirect(request.args.get("next") or url_for("index"))
      else:
        flash('wrong username or password', 'danger')
        return redirect(url_for("login"))
  return render_template("login.html", form=form)

@login_required
@app.route('/logout/')
def logout():
  logout_user()
  flash("You have logged out.", 'info')
  return redirect(url_for('index'))

##                                   index/Search
@app.route('/',methods=('GET', 'POST'))
def index():

    form_s = SearchForm()
    books = db_session.query(Book).all()
    authors = db_session.query(Author).all()

    return render_template("index.html", authors = authors, user=current_user, is_authenticated=current_user.is_authenticated(), books=books, form_s=form_s)

@app.route("/search/", methods=('GET', 'POST'))
def search():

  form_s = SearchForm()
  if form_s.validate_on_submit():
    books = Book.query.all()
    authors = Author.query.all()
    query = form_s.search.data.lower()
    result_books = []
    result_authors = []
    for book in books:
      if query in book.title.lower():
        if not book in result_books:
          result_books.append(book)
    for author in authors:
      if query in author.name.lower():
        result_authors.append(author)
        for b in author.books:
          if not b in result_books:
            result_books.append(b)
    flash("found %s book(s) and %s author(s)" %(len(result_books),len(result_authors)), 'info')
    return render_template('index.html', books=result_books, authors = result_authors, user=current_user,
                         is_authenticated=current_user.is_authenticated(), form_s=form_s)

  return redirect(url_for('index'))

##              BOOKS

@app.route('/books/')
@login_required
def book():
  form = BookForm(request.form)
  books = db_session.query(Book).all()
  return render_template("books.html", user=current_user, books=books,is_authenticated=current_user.is_authenticated())

@app.route('/book_add/', methods=['GET', 'POST'])
@login_required
def book_add():

  book_form = BookForm(request.form)
  book_form.authors.choices = [(p.id, p.name) for p in db_session.query(Author).order_by('id')]

  if book_form.validate_on_submit():
      book = Book()
      book.title = book_form.title.data
      book.authors = [db_session.query(Author).get(o) for o in book_form.authors.data]
      db_session.add(book)
      db_session.commit()
      flash('Successfully added.', 'success')
      return redirect(url_for('index'))

  return render_template("book_create.html", bform=book_form, user=current_user, is_authenticated=current_user.is_authenticated())

@app.route('/book/<id>', methods=['GET', 'POST'])
@login_required
def book_edit(id):

  book = db_session.query(Book).get(id)
  book_form = BookForm(request.form, obj=book)
  book_form.authors.choices = [(p.id, p.name) for p in db_session.query(Author).order_by('id')]

  if book_form.validate_on_submit():
      book = db_session.query(Book).get(id)
      book.title = book_form.title.data
      book.authors = [db_session.query(Author).get(o) for o in book_form.authors.data]
      db_session.commit()
      flash('Changes saved', 'info')
      return redirect(url_for('index'))

  book_form.authors.data = [p.id for p in book.authors]
  return render_template("book.html", bform=book_form, book=book, user=current_user, is_authenticated=current_user.is_authenticated())

@app.route('/book_rm/<id>', methods=['GET', 'POST'])
@login_required
def book_rm(id):
  book = db_session.query(Book).get(id)
  if book:
      db_session.delete(book)
      db_session.commit()
      flash('Deleted successfully.', 'warning')
  return redirect(url_for('index'))

##            AUTHORS
@app.route('/authors/')
@login_required
def author():

  authors = db_session.query(Author).all()
  return render_template("authors.html", user=current_user, is_authenticated=current_user.is_authenticated(), authors=authors)

@app.route('/author/<id>', methods=['GET', 'POST'])
@login_required
def author_edit(id):

  author = db_session.query(Author).get(id)
  author_form = AuthorForm(request.form, obj=author)
  author_form.books.choices = [(b.id, b.title) for b in db_session.query(Book).order_by('id')]

  if author_form.validate_on_submit():
      author = db_session.query(Author).get(id)
      author.name = author_form.name.data
      author.books = [db_session.query(Book).get(b) for b in author_form.books.data]
      db_session.commit()
      flash('Changes saved', 'info')
      return redirect(url_for('index'))

  author_form.books.data = [auth.id for auth in author.books]
  return render_template("author.html", bform=author_form, author=author, user=current_user, is_authenticated=current_user.is_authenticated())

@app.route('/author_add/', methods=['GET', 'POST'])
@login_required
def author_add():
  author_form = AuthorForm(request.form)
  author_form.books.choices = [(p.id, p.title) for p in db_session.query(Book).order_by('id')]

  if author_form.validate_on_submit():
      author = Author()
      author.name = author_form.name.data
      author.books = [db_session.query(Book).get(o) for o in author_form.books.data]
      db_session.add(author)
      db_session.commit()
      flash('Successfully added.', 'success')
      return redirect(url_for('index'))

  return render_template("author_create.html", bform=author_form, user=current_user, is_authenticated=current_user.is_authenticated())

@app.route('/author_rm/<id>', methods=['GET', 'POST'])
@login_required
def author_rm(id):
  author = db_session.query(Author).get(id)
  if author:
      db_session.delete(author)
      db_session.commit()
      flash('Deleted.', 'warning')
  return redirect(url_for('index'))

# random page
@app.route('/random', methods=['GET', 'POST'])
def random_page():
  boa=random.randint(1,2)   #boa = book(1) or author(2)
  id_list=[]
  if boa == 1:
    authors = db_session.query(Author).all()
    for i in authors: id_list.append(i.id)
    randid= random.choice(id_list)
    return redirect('/author/'+str(randid))
  books = db_session.query(Book).all()
  for i in books: id_list.append(i.id)
  randid= random.choice(id_list)
  return redirect('/book/'+str(randid))


from random import randint
from math import *
import turtle

number_of_turtles = 30
steps_of_time_number = 100
k = 1
d = {}

pool = [turtle.Turtle(shape='circle') for i in range(number_of_turtles)]
for unit in pool:
    unit.resizemode("user")
    unit.turtlesize(0.4,0.4)
    unit.penup()
    unit.speed(100)
    unit.goto(randint(-300, 300), randint(-300, 300))
    unit.rt(randint(0, 360))
    x=str(unit)
    vx = str((randint(0, 3)))
    vy = str((randint(0, 3)))
    v0 = sqrt(float(vx) ** 2 + float(vy) ** 2)
    d.update({x : {'vx' : vx, 'vy': vy, 'v0' : v0}})

for i in range(steps_of_time_number):
    n = 1
    for unit in pool:
        if k<=len(pool):
            angle = unit.heading()
            for test in pool:
                if unit != test:
                    if unit.distance(test) < 10:
                        x1 = round(unit.xcor(), 5)
                        x2 = round(test.xcor(), 5)
                        y1 = round(unit.ycor(), 5)
                        y2 = round(test.ycor(), 5)
                        mod = sqrt((x2 - x1) ** 2 + (y2 - y1) ** 2)
                        alpha = degrees(acos((y2 - y1)/mod))
                        beta = alpha = degrees(acos((x2 - x1) / mod))
                        if alpha > 90:
                            n += 1
                            alpha = 180 - alpha
                        if beta > 90:
                            n += 1
                        vx1 = float(d[str(unit)]['vx']) * cos(radians(alpha)) + float(d[str(unit)]['vy']) * cos(radians(90 - alpha)) * (-1) ** n
                        vx2 = float(d[str(test)]['vx']) * cos(radians(alpha)) + float(d[str(test)]['vy']) * cos(radians(90 - alpha)) * (-1) ** n
                        vy1 = float(d[str(unit)]['vx']) * sin(radians(alpha)) + float(d[str(unit)]['vy']) * cos(radians(90 - alpha)) * (-1) ** (n + 1)
                        vy2 = float(d[str(test)]['vx']) * cos(radians(alpha)) + float(d[str(test)]['vy']) * cos(radians(90 - alpha)) * (-1) ** (n + 1)
                        ux1 = vx2
                        ux2 = vx1
                        uy1 = vy1
                        uy2 = vy2
                        u01 = sqrt(vx1 ** 2 + vy1 ** 2)
                        u02 = sqrt(vx2 ** 2 + vy2 ** 2)
                        unit.setheading(unit.heading()-90)
                        test.setheading(test.heading()-90)
                        x = str(unit)
                        y = str(test)
                        d.update({x : {'vx' : str(ux1), 'vy': str(uy1), 'v0' : str(u01)}})
                        d.update({y : {'vx' : str(ux2), 'vy': str(uy2), 'v0' : str(u02)}})
            step = float(d[str(unit)]['v0'])
            if round(unit.xcor(), 5) >= 300 or round(unit.xcor(), 5) <= -300 or round(unit.ycor(), 5) >= 300 or round(unit.ycor(), 5) <= -300:
                    unit.setheading(unit.heading() - 270)
            unit.forward(step)
            k += 1
        else:
            k = 1


'''

Chapter : 7 - item : 4 - delete node in tree

ให้น้องรับ input แล้วนำ input นั้นมาสร้าง Binary Search Tree โดย input ตัวแรกสุดจะเป็น Root เสมอ

โดยมีการป้อน input ดังนี้

i <int> = insert data

d <int> = delete data

หมายเหตุ การลบนั้นจะใช้หลักการของ Inorder Successor และ จำนวน parameter มีได้มากสุด 3 ตัว

'''

class Node:
    def __init__(self, data):
        self.data = data
        self.left = None
        self.right = None

    def __str__(self):
        return str(self.data)

class BST:
    def __init__(self):
        self.root = None
        self.min =0
        self.max=0
    def insert(self, data):
        if self.root == None:
            self.root=Node(data)
            return self.root
        node = self.root
        while True:
            if data < node.data:
                if node.left == None:
                    node.left =Node(data)
                    return self.root
                node = node.left
            else:
                if node.right == None:
                    node.right = Node(data)
                    return self.root
                node = node.right
    def delete(self, node, data):
        if node is None:    # base case
            print("Error! Not Found DATA")
            return
        if node.data != data:   # not found
            if node.data > data:
                node.left = self.delete(node.left, data)  # not found left
            elif node.data < data:
                node.right = self.delete(node.right, data)  # not found right
        else:   # found !!!!

            if node.left is None:   # left None
                node = node.right
                return node
            elif node.right is None:  # right None
                node = node.left
                return node
            else:
                current = node.right
                while current.left is not None:
                    current = current.left

                node.data = current.data    # replace delete
                node.right = self.delete(node.right, current.data)  # permanent delete recursive.....

        return node
    def getMax(self):
        node =self.root
        while node.right != None:
            node =node.right
        return node.data
    def getMin(self):
        node =self.root
        while node.left != None:
            node = node.left
        return node.data

    def printTree(self, node, level = 0):
        if node != None:
            self.printTree(node.right, level + 1)
            print('     ' * level, node)
            self.printTree(node.left, level + 1)
T = BST()
inp = input('Enter Input : ').split(',')
for i in range (len(inp)):
    if inp[i][0] == 'i':
        print("insert " + (inp[i][2:]))
        T.root=T.insert(int(inp[i][2:]))
        T.printTree(T.root)
    if inp[i][0] == 'd':
        print("delete " + (inp[i][2:]))
        T.root=T.delete(T.root,int(inp[i][2:]))
        T.printTree(T.root)


print("hallo wereld")
import logging
import datetime
import time
import requests
from sense_hat import SenseHat
import json
sense = SenseHat()

color = "black"
colornames = {}
colornames["red"] = (255,0,0)
colornames["green"] = (0,255,0)
colornames["blue"] = (0,0,255)
colornames["yellow"] = (255,255,0)
colornames["black"] = (0,0,0)
fsUrl = "https://services9.arcgis.com/7e6lF03RcLhwFtm5/arcgis/rest/services/Selected_Color/FeatureServer/0"
logFilepath = "/home/admin/Documents/logs/updatecolor_{}.log".format(datetime.datetime.now().strftime("%Y%m%d-%H%M%S"))

def main():
	logging.basicConfig(level=logging.DEBUG,format='%(asctime)s %(levelname)s - %(message)s',datefmt='%Y%m%d-%H:%M:%S',handlers=[logging.StreamHandler(),logging.FileHandler(logFilepath)])
	logging.info("Start update color v20231110.01")
	r = 0
	g = 0
	b = 0
	for i in range(0,254):
		sense.clear((r,i,b))
		#time.sleep(0.01)

	logging.info("Startting script")
	sense.show_message("starting",0.05)

	sense.color.gain = 16
	sense.color.integration_cycles = 256
	counter = 0

	logging.info("Showing M")
	sense.show_letter("M")
	x = 0
	y = 0
	rvalue = 75
	gvalue = 75
	while True:
		try:
			sense.set_pixel(x,y,colornames[color])
			y +=1
			if y > 7:
				y = 0
				x+=1
			if x > 7:
				x = 0
				if CheckConnection():
					rvalue = 75
					gvalue = 150
				else:
					rvalue = 150
					gvalue = 75
			sense.set_pixel(x,y,(rvalue,gvalue,75))
			#print("waiting for input")
			for event in sense.stick.get_events():
				logging.info(f"stick event: {event.direction},{event.action}")
				direction = event.direction
				if event.action=="pressed":
					if direction =="middle":
						SentColor()
					if direction == "up":
						SaveColor("red")
					if direction == "right":
						SaveColor("green")
					if direction == "down":
						SaveColor("blue")
					if direction == "left":
						SaveColor("yellow")
			time.sleep(0.1)
		except:
			logging.exception("Error in main loop")

def SaveColor(colorname):
	global color
	if colorname==color:
		colorname= "black"
	logging.info(f"Setting color to: {colorname}")
	sense.clear(colornames[colorname])
	color = colorname

def SentColor():
	try:
		text = f"sending  {color}"
		logging.info(text)
		sense.show_message(text,0.07, text_colour=colornames[color])

		#query feature for its objectid
		queryParams = {"f":"json","where":"1=1","outFields":"*"}
		queryUrl = f"{fsUrl}/query"

		r = requests.get(queryUrl,queryParams)
		print(r.text)
		results = r.json()
		feature = results["features"][0]
		logging.info(feature)
		#updating feature
		feature["attributes"]["color"] = color
		feature["attributes"]["color_count"] = feature["attributes"]["color_count"] + 1
		updateParams = {"f":"json","features":json.dumps([feature])}
		updateUrl = f"{fsUrl}/updateFeatures"

		r = requests.post(updateUrl,updateParams)
		logging.info(r.text)
		results = r.json()

		#{"updateResults":[{"objectId":1,"uniqueId":1,"globalId":null,"success":true}]}
		text = f"results: {results['updateResults'][0]['success']}"

		sense.show_message(text, text_colour=colornames[color])
	except:
		logging.exception("Error in SentColor")

def CheckConnection():
	logging.info("Checking connection")
	retValue = False

	try:
		params = {}
		params["f"] = "json"
		params["where"]="1=1"
		params["returncountOnly"]=True
		queryUrl = f"{fsUrl}/query"
		logging.info(f"requesting {queryUrl}")
		r = requests.get(queryUrl,params)

		result = r.json()
		logging.debug(f"result: {result}")

		if "count" in result:
			retValue = True
	except:
		logging.exception("Error getting value")
	return retValue

if __name__=="__main__":
	main()


from django.urls import path
from . import views

app_name = 'Card'
urlpatterns = [
    path('review_card', views.go_review),
    path('ShowCards', views.get_cards),
    path('addCard', views.add_card),
    path('ApplyPermission', views.apply_permission),
    path('ModifyCard', views.modify_card),
    path('RemoveCard', views.remove_card),
    path('GetMemoryCar', views.get_memory_card),
    path('RememberCard', views.remember_card),
    path('ForgetCard', views.forget_card)
]


import sys
import os
import numpy as np
import cv2 as cv
import tools as tool
import time as t
from PIL import	Image

args = sys.argv
folder_path = args[1]
sign_path = args[2]
dst_path = args[3]

t1 = t.time()

num_photos = len(os.listdir(os.getcwd()))
print("Processing", num_photos, "photos in", folder_path)
print("Using signature in", sign_path)

for filename in tool.get_files(folder_path):
	# Extract EXIF from original image
	im = Image.open(filename)
	exif_data = im.info['exif']

	# Run Signature tool
	signed = tool.sign_image(filename,sign_path,verbose=True)
	signed_filename = dst_path + "/" + filename
	cv.imwrite(signed_filename,signed)

	# Write EXIF on new image
	im_new = Image.open(signed_filename)
	image_new.save(signed_filename, 'JPEG', exif=exif_data)

t2 = t.time() - t1
print(" ")
print(num_photos,"photos processed in",round(t2,3),"s")
print("Signed photos saved in ",dst_path)


import sys

def binary_search_max(d: int, m: int, x: int) -> int:
    """ 二分探索でf(n)<=mを満たす最大のnを探索する
    """
    low = 0
    candidate = [i for i in range(d + 1, 36)]
    high = len(candidate) - 1
    while low <= high:
        mid = (low + high) // 2
        guess = candidate[mid]
        conveted_number = int(str(x), guess)

def main():
    def input():
        return sys.stdin.readline()[:-1]

    x = input()
    m = int(input())
    d = max(sorted(str(x), reverse=True))

    res = binary_search_max(int(d), int(m), int(x))
    print(res)

if __name__ == "__main__":
    main()


from Model_1.A_Libraries import *
from Model_1.A1_path import *
from Model_1.C_DataImport import dataImport

def load_images_labels_from_df(path, pathType, img_size):

    df = dataImport(path,pathType)
    images = []
    labels = []

    for _, row in df.iterrows():
        label = row['Labels']
        img_data = row['Images']
        img_resized = img_data.resize((img_size, img_size)) #resize images (128*128, 256*256 etc)
        img_array = np.array(img_resized) / 255.0  # Normalize pixel values
        images.append(img_array)
        labels.append(label)

    images = np.array(images)
    labels = np.array(labels)

    # Augmentation: A technique to create more and different images from existing images using various transformation method
    augmentation = preprocessing.image.ImageDataGenerator(
                                                        rotation_range=20, # image rotation range
                                                        width_shift_range=20, # horizontal shift during augmentation
                                                        height_shift_range=20, # vertical shift during augmentation
                                                        shear_range=20, # shear angle shift during augmentation
                                                        zoom_range=20, # image zoom-in or out during augmentation
                                                        horizontal_flip=True,
                                                        fill_mode='nearest', # how to fill empty spaces created during augmentation*
                                                        vertical_flip=True
                                                    )

    augmentation.fit(images)
    augmentedImage_generator = augmentation.flow(images, labels, batch_size=32)

    return augmentedImage_generator, len(images)

# different fill_mode: 1) nearest 2)constant 3)reflect 4)wrap


if __name__ == "__main__":
    n = int(input())
    arr = list(map(int, input().split()))

    x = max(arr)

    c = arr.count(x)

    for i in range(c):
        arr.remove(x)

    print(max(arr))


# Title: Week 4 - Calculate this, Computer
# Author Name: Anh Vo
# Date: Oct 4, 2020
# Description: Calculate the Term Grade Point Average (GPA)

# Greet the user
print("-----------WELCOME TO GPA CALCULATOR----------")

# Ask the user the number of courses taken
courseNum = int(input("Number of courses you take:---> "))

# Initialize Total units, total gradePoint of the term
totalU = 0
totalGradeP = 0

# Use for loops to ask questions
for course in range(courseNum):
#   Ask for Letter grade of each course
    letterG = input("\nLetter Grade of course "+ str((course+1))+ ":---> ").upper()

#   Convert letter grade to numerical equivalent
#   There is a deduction of 0.33 in grades
    numEqui = 0.00
    gradeA = ["A+","A","A-"]
    gradeB =["B+","B","B-"]
    gradeC = ["C+","C","C-"]
    fails = ["F", "FD", "N"]

    if letterG in gradeA:
        numEqui+= (4.33 - 0.33*gradeA.index(letterG))
    elif letterG in gradeB:
        numEqui+=(3.33 - 0.33*gradeB.index(letterG))
    elif letterG in gradeC:
        numEqui+=(2.33 - 0.33*gradeC.index(letterG))
    elif letterG == "D":
        numEqui+=1.00
    elif letterG in fails:
        numEqui+=0.00
    else:
        print("\nCannot define your letter grade")

#   Ask for the Unit of the course
    unit = int(input("\nUnit of course " + str((course+1)) +" :---> "))
    totalU += unit

#   Find Grade Point of each course
    gradeP = unit*numEqui
    totalGradeP+=gradeP

# Calculate GPA, round it to two decimal
gpa = totalGradeP/totalU
print("\nTerm Grade Point Average:",round(gpa,2))

# Minimum required GPA for continuation
if gpa < 2.40:
    print("\nYour GPA is under 2.40, you may be placed on probation within the School.")
if gpa < 2.0:
    print("\nIt's required that you must obtain a GPA of 2.00 to fulfill the program requirement.")


"""
926 Flip String to Monotone Increasing

A string of '0's and '1's is monotone increasing if it consists of some number of '0's (possibly 0), followed by some number of '1's (also possibly 0.)

We are given a string S of '0's and '1's, and we may flip any '0' to a '1' or a '1' to a '0'.

Return the minimum number of flips to make S monotone increasing.

Example 1:

Input: "00110"
Output: 1
Explanation: We flip the last digit to get 00111.
Example 2:

Input: "010110"
Output: 2
Explanation: We flip to get 011111, or alternatively 000111.
Example 3:

Input: "00011000"
Output: 2
Explanation: We flip to get 00000000.

Note:

1 <= S.length <= 20000
S only consists of '0' and '1' characters.
"""
class Solution:
    # my own solution by partitioning S to two parts S[:i] and S[i+1:]
    # we need to change all '1's in left part to '0', so we need to count '1' in S[:i]
    # we also need to change all '0's in right part to '1', so we need to count '0' in S[i+1:]
    # iterate all different partitioning positions and get the answer
    def minFlipsMonoIncr(self, S):
        """
        :type S: str
        :rtype: int
        """
        n = len(S)
        ones = [0]*(n+1)    # ones[i] is the count of '1' in S[:i]
        zeros = [0]*(n+1)   # zeros[i] is the count of '0' in S[-i:]
        for i in range(1, n+1):
            ones[i] = ones[i-1] + 1 if S[i-1] == '1' else ones[i-1]
            zeros[i] = zeros[i-1] + 1 if S[-i] == '0' else zeros[i-1]

        ans = 20001
        for i in range(n+1):
            ans = min(ans, ones[i] + zeros[n-i])

        return ans

test_cases = ['0', '1', '01', '10', '00', '11', '00110', '010110', '000110', '101010', "00011000"]
for S in test_cases:
    print(S, end = ' -> ')
    print(Solution().minFlipsMonoIncr(S))


"""
Config management for llm-api
"""

import logging
import os
from typing import Any, Dict, Optional

import yaml
from pydantic import BaseSettings

logger = logging.getLogger("llm-api.config")

class Settings(BaseSettings):  # pylint: disable=too-few-public-methods
    """
    Settings class to configure the app
    """

    models_dir: str = "./models"
    model_family: str
    model_params: Optional[Dict[str, Any]] = {}
    setup_params: Dict[str, Any] = {}
    host: str = "0.0.0.0"
    port: int = 8000
    log_level: str = "info"

    class Config:  # pylint: disable=too-few-public-methods
        """
        Configurations customizations
        """

        env_prefix = "LLM_API_"

        @classmethod
        def customise_sources(
            cls,
            init_settings,
            env_settings,
            file_secret_settings,
        ):
            """
            Customization of the config hooks to add a yaml file settings source
            """
            return (
                init_settings,
                env_settings,
                yaml_config_settings_source,
                file_secret_settings,
            )

def yaml_config_settings_source(
    base_settings: BaseSettings,  # pylint: disable=unused-argument
) -> Dict[str, Any]:
    """
    YAML file settings source
    """
    if not os.path.exists("config.yaml"):
        logger.warning("no config file found")
        return {}
    try:
        logger.info("loading config file config.yaml")
        with open("config.yaml", encoding="utf-8") as conf_file:
            data = yaml.load(conf_file, Loader=yaml.FullLoader)
        if data is None:
            logger.warning("config file is empty")
            return {}
        logger.info(str(data))
        return data
    except yaml.YAMLError as exp:
        raise exp

settings = Settings()


# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, val=0, next=None):
#         self.val = val
#         self.next = next
class Solution:
    def rotateRight(self, head: Optional[ListNode], k: int) -> Optional[ListNode]:
        if not head or k == 0 or not head.next:
            return head
        # 统计链表结点数
        cnt = 1
        cur = head
        # 从第2个节点开始遍历
        while cur.next:
            cur = cur.next
            cnt += 1

        k = k % cnt
        if k == 0:
            return head

        # 首尾相连
        cur.next = head
        # 移动后最后一个节点号
        for i in range(cnt-k):
             cur = cur.next

        head_new = cur.next
        cur.next = None

        return head_new


from typing import List

#~~~~~~~ Part 1 ~~~~~~~#

with open('day_03_input.txt') as f:
    binary_number_list = [x for x in f.read().splitlines()]

# Setup
quantity_of_binary_numbers = len(binary_number_list)
length_of_the_binary_numbers = len(binary_number_list[0])

map_from_index_to_number_of_ones = [0] * length_of_the_binary_numbers

# Iterate over the binary numbers, counting the 1s at each index
for binary_num in binary_number_list:
    for digit_index, digit in enumerate(binary_num):
        if digit == '1':
            map_from_index_to_number_of_ones[digit_index] += 1

# Find Gamma
gamma_rate_in_binary = ''
for index in range(length_of_the_binary_numbers):
    if map_from_index_to_number_of_ones[index] > 0.5 * quantity_of_binary_numbers:
        gamma_rate_in_binary += '1'
    else:
        gamma_rate_in_binary += '0'
gamma_rate_in_decimal = int(gamma_rate_in_binary, 2)

# Calculate Epsilon from Gamma
epsilon_rate_in_binary = ''.join(list(map(lambda digit: str(1 - int(digit)), gamma_rate_in_binary)))
epsilon_rate_in_decimal = int(epsilon_rate_in_binary, 2)

# Finale
print(f'Gamma rate in binary: {gamma_rate_in_binary}')
print(f'Gamma rate in decimal: {gamma_rate_in_decimal}')

print(f'Epsilon rate in binary: {epsilon_rate_in_binary}')
print(f'Epsilon rate in decimal: {epsilon_rate_in_decimal}')

print(f'Product: {gamma_rate_in_decimal * epsilon_rate_in_decimal}')

#~~~~~~~ Part 2 ~~~~~~~#

# Helpful Functions
def is_1_most_popular_at_index(binary_number_list: List[str], index: int) -> bool:
    length_of_list = len(binary_number_list)
    total_ones = 0
    for binary_num in binary_number_list:
        if binary_num[index] == '1':
            total_ones += 1
    return 2*total_ones >= length_of_list

def get_rating(starting_list: List[str], one_is_most_popular_filter: str) -> str:
    rating_candidates = starting_list + []

    for index in range(len(starting_list)):
        if is_1_most_popular_at_index(rating_candidates, index):
            # 1 is the most (or equally as) popular at this position
            rating_candidates = list(filter(lambda binary_num: binary_num[index] == one_is_most_popular_filter, rating_candidates))
        else:
            # 1 is the least popular at this position
            rating_candidates = list(filter(lambda binary_num: binary_num[index] != one_is_most_popular_filter, rating_candidates))

        if len(rating_candidates) == 1:
            return rating_candidates[0]

# Find o_2 and co_2 ratings
o_2_rating_binary = get_rating(binary_number_list, one_is_most_popular_filter='1')
co_2_rating_binary = get_rating(binary_number_list, one_is_most_popular_filter='0')

o_2_rating_decimal = int(o_2_rating_binary, 2)
co_2_rating_decimal = int(co_2_rating_binary, 2)

# Finale
print(f'O_2 rate in binary: {o_2_rating_binary}')
print(f'O_2 rate in decimal: {o_2_rating_decimal}')

print(f'CO_2 rate in binary: {co_2_rating_binary}')
print(f'CO_2 rate in decimal: {co_2_rating_decimal}')

print(f'Product: {o_2_rating_decimal * co_2_rating_decimal}')


from datetime import date

from django.core.validators import MaxValueValidator

from rest_framework import serializers
from rest_framework.exceptions import ValidationError
from rest_framework.validators import UniqueTogetherValidator

from birthdata.models import Town, Writer

class WriterSerializer(serializers.Serializer):
    firstname = serializers.CharField(max_length=100)
    patronymic = serializers.CharField(max_length=100)
    lastname = serializers.CharField(max_length=100)
    birth_place = serializers.SlugRelatedField(
        slug_field='name',
        queryset=Town.objects
    )
    birth_date = serializers.DateField(
        format='%d.%m.%Y',
        input_formats=['%d.%m.%Y', 'iso-8601'],
        validators=[MaxValueValidator(date(1999, 12, 31))]
    )

    class Meta:
        validators = [
            UniqueTogetherValidator(
                queryset=Writer.objects,
                fields=['firstname', 'patronymic', 'lastname']
            )
        ]

    def validate(self, attrs):
        set_attrs = set(
            [attrs['firstname'], attrs['patronymic'], attrs['lastname']]
        )
        if len(set_attrs) != 3:
            raise ValidationError(
                'Имя, отчество и фамилия не могут совпадать между собой',
                code='duplicate values'
            )
        return attrs

    def create(self, validated_data):
        return Writer.objects.create(**validated_data)


import json
from collections import defaultdict
from functools import wraps
from flask import current_app, Response
from flask_login import login_user
from flask_principal import (Identity, Permission, RoleNeed,
                                 session_identity_loader, identity_changed)
from sqlalchemy import func

#from web.lib.utils import default_handler
from web.models import (Category, Property, Attribute, ShelterPicture,
                        ShelterDocument, Shelter, Section)

admin_role = RoleNeed('admin')
admin_permission = Permission(admin_role)

def jsonify(func):
    """Will cast results of func as a result, and try to extract
    a status_code for the Response object"""
    @wraps(func)
    def wrapper(*args, **kwargs):
        status_code = 200
        result = func(*args, **kwargs)
        if isinstance(result, Response):
            return result
        elif isinstance(result, tuple):
            result, status_code = result
        return Response(json.dumps(result, default=scoped_default_handler()),
                        mimetype='application/json', status=status_code)
    return wrapper

def login_user_bundle(user):
    login_user(user)
    identity_changed.send(current_app, identity=Identity(user.id))
    session_identity_loader()
    # eventually update the last_seen field

def load_shelter_info(shelter_id, section_name):
    shelter = Shelter.query.filter(Shelter.id==shelter_id).first()
    if not shelter:
        raise Exception("No such shelter")

    section = Section.query.filter(
            func.lower(Section.name)==func.lower(section_name.replace('-', ' '))).first()
    if not section:
        raise Exception("No such section")

    categories = defaultdict(list)
    documents = defaultdict(list)
    pictures = defaultdict(list)

    for category in section.categories:

        if category.name == 'Walls & frame':
            superstructure_type = Property.query.filter(
                    Property.shelter_id==shelter.id,
                    Property.category.has(name="Walls & Frame"),
                    Property.category.has(Category.parent_id!=None)).first()
            if superstructure_type:
                superstructure_type_string = superstructure_type.get_values_as_string()
            else:
                superstructure_type_string = ""
        else:
            superstructure_type_string = ""

        for sub_category in category.sub_categories:
            if category.name == 'Walls & frame' and \
                sub_category.name != 'Walls & Frame' and \
                superstructure_type_string.lower()!=sub_category.name.lower():
                continue

            categories[sub_category.name].extend(
                Property.query.filter(
                                    Property.shelter_id==shelter.id,
                                    Property.category.has(name=sub_category.name))
                                .join(Attribute)
                                .order_by(Attribute.display_position.asc())
                                )
            pictures[sub_category.name].extend(
                ShelterPicture.query.filter(
                                    ShelterPicture.shelter_id==shelter.id,
                                    ShelterPicture.category_id==sub_category.id)
                                )
            documents[sub_category.name].extend(
                ShelterDocument.query.filter(
                                    ShelterDocument.shelter_id==shelter.id,
                                    ShelterDocument.category_id==sub_category.id)
                                )
    return shelter, section, categories, pictures, documents


import os
import numpy as np
import pandas as pd
from datetime import datetime
import matplotlib.pyplot as plt
from ohcoachtools.gpscoordtools import gpspoint_to_fieldlocal
from ohcoachtools.myconstants import *
from ohcoachtools.field import Field

if __name__ == '__main__':
    # Load stadium coordinates
    field_filepath = os.path.join(DATA_DIR, 'field_01.csv')
    field_coord = np.array(pd.read_csv(field_filepath, sep=',', header=None))
    field = Field()
    field.set_gps_corners(field_coord)

    # Read gps data
    gps_filepath = os.path.join(DATA_DIR, 'sample_01.och')
    och_df = pd.read_csv(gps_filepath, sep=',', header=0, names=OCH_HEADER)

    # Convert strings to datetimes
    och_df[LABEL_DATETIME] = och_df[LABEL_DATETIME].apply(
        lambda x: datetime.strptime(x, '%Y.%m.%d.%H.%M.%S.%f')
    )
    # Compute local coordinates
    och_df[[LABEL_X, LABEL_Y]] = och_df.apply(
        lambda x: gpspoint_to_fieldlocal(x[LABEL_LATITUDE], x[LABEL_LONGITUDE], field),
        axis=1, result_type='expand'
    )

    # Visualization
    plt.plot(och_df[LABEL_X], och_df[LABEL_Y])
    plt.title('Player Trajectory')
    plt.xlim(0, field.width)
    plt.ylim(0, field.height)
    plt.grid(True)
    plt.show()


#!/usr/bin/python
import math, re, os
from subprocess import run
"""
This main program body contains following:

    3) NamelistCreator:
        The namelist creater is used to create the namelists for WRF and
        WPS. The program is very flexible and thus any namelist can be
        modified due to different usage or systems.

"""

class Namelist_creator:
    """

    """
    # Important Parameters
    # Time control :
    # Format: YYYY MM DD hh mm ss

    # Domains:

    # Ensembles:
    NUM_ensemble_member       = 0
    NUM_input_ensemble_member = 0
    IF_ensemble_run           = False
    # Others:
    STR_DIR="./"

    def __init__(self, STR_wrf_namelist="namelist.input", STR_wps_namelist="namelist.wps", STR_DIR="./", debug_in = False):
        print("Start the namelist creator by Python")
        print("    Author: Y.-S. Lu                ")
        print("    First Edition: 24.04.2020       ")
        print("              ... during COVID-19   ")

        # ENSEMBLE SETTING UP
        self.IF_SPPT  = False
        self.IF_SKEBS = False
        self.STR_connect_symbol = "_"
        self.debug    = debug_in
        # FILENAME

        self.STR_wrf_namelist = STR_wrf_namelist
        self.STR_wps_namelist = STR_wps_namelist
        self.STR_DIR          = STR_DIR

        # ARR of press_pa
        self.ARR_press_pa = [ 201300, 200100, 100000, 95000, 90000, 85000, 80000, 75000, \
                               70000,  65000,  60000, 55000, 50000, 45000, 40000, 35000, \
                               30000,  25000,  20000, 15000, 10000,  5000,  1000 ]

        self.ARR_wps_share_all   = ["wrf_core","max_dom","start_date","end_date","interval_seconds","active_grid","subgrid_ratio_x","subgrid_ratio_y","io_form_geogrid","opt_output_from_geogrid_path","debug_level","start_date","end_date","start_year","start_month","start_day","start_hour","start_minute","start_second","end_year","end_month","end_day","end_hour","end_minute","end_second"]

        self.ARR_wps_geogrid_all =  ["parent_id","parent_grid_ratio","i_parent_start","j_parent_start","s_we","e_we","s_sn","e_sn","geog_data_res","dx","dy","map_proj","ref_lat","ref_lon","ref_x","ref_y","truelat1","truelat2","stand_lon","geog_data_path","opt_geogrid_tbl_path","geog_data_res","geog_data_res"]

        self.ARR_ungrib_all      = ["out_format","prefix","ec_rec_len","pmin"]

        self.ARR_metgrid_all     = ["fg_name", "constants_name", "io_form_metgrid", "opt_output_from_metgrid_path", "opt_metgrid_tbl_path", "process_only_bdy"]

        self.ARR_mod_levs_all    = ["press_pa"]

        self.ARR_plotfmt_all     = ["ix","jx","ioff","joff"]

        self.ARR_share           = [ "wrf_core",            "max_dom",     "start_date",       "end_date",\
                                     "interval_seconds","active_grid","subgrid_ratio_x","subgrid_ratio_y",\
                                     "io_form_geogrid", "opt_output_from_geogrid_path"]

        self.ARR_geogrid         = [ "parent_id", "parent_grid_ratio", "i_parent_start", "j_parent_start",\
                                     "e_we", "e_sn","geog_data_res","dx","dy",\
                                     "map_proj","ref_lat","ref_lon",\
                                     "truelat1","truelat2","stand_lon","geog_data_path","geog_data_res"]

        self.ARR_ungrib          = ["out_format", "prefix"]

        self.ARR_metgrid         = ["fg_name"   , "io_form_metgrid"]

        self.ARR_mod_levs        = ["press_pa"]

        self.ARR_plotfmt         = ["ix","jx","ioff","joff"]

        # ARR of WRFs

        self.ARR_time_control = ['run_days', 'run_hours', 'run_minutes', 'run_seconds', 'start_year', 'start_month', 'start_day', 'start_hour', 'start_minute', 'start_second', 'end_year', 'end_month', 'end_day', 'end_hour', 'end_minute', 'end_second', 'interval_seconds', 'input_from_file', 'history_interval', 'history_outname', 'bdy_inname', 'input_inname', 'frames_per_outfile', 'auxhist1_outname', 'auxhist2_outname', 'auxhist1_interval', 'auxhist2_interval', 'frames_per_auxhist1', 'frames_per_auxhist2', 'aux1_time', 'aux2_time', 'interpolation_time', 'interpolation_number', 'restart', 'restart_interval', 'override_restart_timers', 'io_form_history', 'io_form_restart', 'io_form_input', 'io_form_boundary', 'debug_level', 'io_form_auxinput2', 'io_form_auxhist1', 'io_form_auxhist2', 'auxinput1_inname']

        self.ARR_domains     = ['time_step', 'time_step_fract_num', 'time_step_fract_den', 'max_dom', 'e_we', 'e_sn', 'e_vert', 'p_top_requested', 'num_metgrid_levels', 'num_metgrid_soil_levels', 'dx', 'dy', 'grid_id', 'parent_id', 'i_parent_start', 'j_parent_start', 'parent_grid_ratio', 'feedback', 'use_adaptive_time_step', 'step_to_output_time', 'target_cfl', 'max_step_increase_pct', 'starting_time_step', 'max_time_step', 'min_time_step', 'adaptation_domain', 'interp_type', 'smooth_option', 'sfcp_to_sfcp']

        self.ARR_physics     = ['mp_physics', 'ra_lw_physics', 'ra_sw_physics', 'sf_sfclay_physics', 'sf_surface_physics', 'bl_pbl_physics', 'cu_physics', 'radt', 'bldt', 'cudt', 'isftcflx', 'isfflx', 'ifsnow', 'icloud', 'surface_input_source', 'num_soil_layers', 'sf_urban_physics', 'maxiens', 'maxens', 'maxens2', 'maxens3', 'ensdim', 'topo_wind', 'num_land_cat', 'ysu_st']

        self.ARR_dynamics    = ['w_damping', 'diff_opt', 'km_opt', 'diff_6th_opt', 'diff_6th_factor', 'time_step_sound', 'base_temp', 'damp_opt', 'dampcoef', 'khdif', 'kvdif', 'non_hydrostatic', 'moist_adv_opt', 'scalar_adv_opt']

        self.ARR_bdy_control = ['spec_bdy_width', 'spec_zone', 'relax_zone', 'specified', 'nested']

        self.ARR_namelist_quilt = ['nio_tasks_per_group', 'nio_groups']

        self.ARR_stoch_skebs = ['skebs', 'stoch_vertstruc_opt', 'tot_backscat_psi', 'tot_backscat_t', 'ztau_psi', 'ztau_t', 'nens', 'ISEED_SKEBS']

        self.ARR_stoch_sppt  = ['sppt', 'nens', 'timescale_sppt', 'gridpt_stddev_sppt', 'ISEED_SPPT']

        # WPS NAMELISTS:
        # Share:
        self.DIC_share_common_para = {\
            "wrf_core"                         : {"VALUE":   "ARW"          , "DATA_TYPE": "STR", "ARR_TYPE" :"S",\
                                                                              "STR_FMT" : "\'{0:s}\',"},
            "max_dom"                          : {"VALUE":   0              , "DATA_TYPE": "INT", "ARR_TYPE" :"P"   },
            "interval_seconds"                 : {"VALUE":   10800          , "DATA_TYPE": "INT", "ARR_TYPE" :"S"   },
            "active_grid"                      : {"VALUE":   True           , "DATA_TYPE": "BLN", "ARR_TYPE" :"M"   },
            "subgrid_ratio_x"                  : {"VALUE":   1              , "DATA_TYPE": "INT", "ARR_TYPE" :"S"   },
            "subgrid_ratio_y"                  : {"VALUE":   1              , "DATA_TYPE": "INT", "ARR_TYPE" :"S"   },
            "io_form_geogrid"                  : {"VALUE":   2              , "DATA_TYPE": "INT", "ARR_TYPE" :"S"   },
            "opt_output_from_geogrid_path"     : {"VALUE":   "./"           , "DATA_TYPE": "STR", "ARR_TYPE" :"S",\
                                                                              "STR_FMT" : "\'{0:s}\',"},
            "debug_level"                      : {"VALUE":   0              , "DATA_TYPE": "INT", "ARR_TYPE" :"S"   },
            "start_date"                       : {"VALUE":  ["2006-08-16_12:00:00", "2006-08-16_12:00:00"],\
                                                                              "DATA_TYPE": "STR", "ARR_TYPE" :"M",\
                                                                              "STR_FMT" : "\'{0:s}\',"},
            "end_date"                         : {"VALUE":  ["2006-08-16_18:00:00", "2006-08-16_18:00:00"],\
                                                                              "DATA_TYPE": "STR", "ARR_TYPE" :"M",\
                                                                              "STR_FMT" : "\'{0:s}\',"},
            "start_year"                       : {"VALUE":  [ 0, 0         ], "DATA_TYPE": "INT", "ARR_TYPE" :"P"   },
            "start_month"                      : {"VALUE":  [ 0, 0         ], "DATA_TYPE": "INT", "ARR_TYPE" :"P"   },
            "start_day"                        : {"VALUE":  [ 0, 0         ], "DATA_TYPE": "INT", "ARR_TYPE" :"P"   },
            "start_hour"                       : {"VALUE":  [ 0, 0         ], "DATA_TYPE": "INT", "ARR_TYPE" :"P"   },
            "start_minute"                     : {"VALUE":  [ 0, 0         ], "DATA_TYPE": "INT", "ARR_TYPE" :"P"   },
            "start_second"                     : {"VALUE":  [ 0, 0         ], "DATA_TYPE": "INT", "ARR_TYPE" :"P"   },
            "end_year"                         : {"VALUE":  [ 0, 0         ], "DATA_TYPE": "INT", "ARR_TYPE" :"P"   },
            "end_month"                        : {"VALUE":  [ 0, 0         ], "DATA_TYPE": "INT", "ARR_TYPE" :"P"   },
            "end_day"                          : {"VALUE":  [ 0, 0         ], "DATA_TYPE": "INT", "ARR_TYPE" :"P"   },
            "end_hour"                         : {"VALUE":  [ 0, 0         ], "DATA_TYPE": "INT", "ARR_TYPE" :"P"   },
            "end_minute"                       : {"VALUE":  [ 0, 0         ], "DATA_TYPE": "INT", "ARR_TYPE" :"P"   },
            "end_second"                       : {"VALUE":  [ 0, 0         ], "DATA_TYPE": "INT", "ARR_TYPE" :"P"   }}

        # Geogrid
        self.DIC_geogrid_common_para = {\
            "parent_id"                        : {"VALUE":  [ 0, 0         ], "DATA_TYPE": "INT", "ARR_TYPE" :"P"   },
            "parent_grid_ratio"                : {"VALUE":  [ 0, 0         ], "DATA_TYPE": "INT", "ARR_TYPE" :"P"   },
            "i_parent_start"                   : {"VALUE":  [ 0, 0         ], "DATA_TYPE": "INT", "ARR_TYPE" :"P"   },
            "j_parent_start"                   : {"VALUE":  [ 0, 0         ], "DATA_TYPE": "INT", "ARR_TYPE" :"P"   },
            "s_we"                             : {"VALUE":  [ 0, 0         ], "DATA_TYPE": "INT", "ARR_TYPE" :"P"   },
            "e_we"                             : {"VALUE":  [ 0, 0         ], "DATA_TYPE": "INT", "ARR_TYPE" :"P"   },
            "s_sn"                             : {"VALUE":  [ 0, 0         ], "DATA_TYPE": "INT", "ARR_TYPE" :"P"   },
            "e_sn"                             : {"VALUE":  [ 0, 0         ], "DATA_TYPE": "INT", "ARR_TYPE" :"P"   },
            "geog_data_res"                    : {"VALUE":  ['modis_30s+2m','modis_30s','modis_30s']   ,\
                                                                              "DATA_TYPE": "STR", "ARR_TYPE" :"M",\
                                                                              "STR_FMT" : "\'{0:s}\',"              },
            "dx"                               : {"VALUE":  15000           , "DATA_TYPE": "INT", "ARR_TYPE" :"P"   },
            "dy"                               : {"VALUE":  15000           , "DATA_TYPE": "INT", "ARR_TYPE" :"P"   },
            "map_proj"                         : {"VALUE":  'lambert'       , "DATA_TYPE": "STR", "ARR_TYPE" :"S"   ,\
                                                                              "STR_FMT" : "\'{0:s}\',"},
            "ref_lat"                          : {"VALUE":  45              , "DATA_TYPE": "FLT", "ARR_TYPE" :"S"   },
            "ref_lon"                          : {"VALUE":  8.5             , "DATA_TYPE": "FLT", "ARR_TYPE" :"S"   },
            "ref_x"                            : {"VALUE":  45              , "DATA_TYPE": "FLT", "ARR_TYPE" :"S"   },
            "ref_y"                            : {"VALUE":  8.5             , "DATA_TYPE": "FLT", "ARR_TYPE" :"S"   },
            "truelat1"                         : {"VALUE":  30.0            , "DATA_TYPE": "FLT", "ARR_TYPE" :"S"   },
            "truelat2"                         : {"VALUE":  60.0            , "DATA_TYPE": "FLT", "ARR_TYPE" :"S"   },
            "stand_lon"                        : {"VALUE":   8.5            , "DATA_TYPE": "FLT", "ARR_TYPE" :"S"   },
            "geog_data_path"                   : {"VALUE": '/path/to/geo'   , "DATA_TYPE": "STR", "ARR_TYPE" :"S",\
                                                                              "STR_FMT" : "\'{0:s}\',"},
            "opt_geogrid_tbl_path"             : {"VALUE": 'geogrid'       ,  "DATA_TYPE": "STR", "ARR_TYPE" :"S",\
                                                                              "STR_FMT" : "\'{0:s}\',"},
            "geog_data_res"                    : {"VALUE": ['usgs_lakes+10m','usgs_lakes+2m']   ,\
                                                                              "DATA_TYPE": "STR", "ARR_TYPE" :"M",\
                                                                              "STR_FMT" : "\'{0:s}\',"}}

        # Ungrib
        self.DIC_ungrib_common_para = {\
            "out_format"                       : {"VALUE": "WPS"            , "DATA_TYPE": "STR", "ARR_TYPE" :"S",\
                                                                              "STR_FMT" : "\'{0:s}\',"              },
            "prefix"                           : {"VALUE": "FILE"           , "DATA_TYPE": "STR", "ARR_TYPE" :"S",\
                                                                              "STR_FMT" : "\'{0:s}\',"              },
            "ec_rec_len"                       : {"VALUE": 26214508         , "DATA_TYPE": "INT", "ARR_TYPE" :"S"   },
            "pmin"                             : {"VALUE": 100              , "DATA_TYPE": "FLT", "ARR_TYPE" :"S"   }}

        # Metgrid
        self.DIC_metgrid_common_para = {\
            "fg_name"                          : {"VALUE": ["FILE"]         , "DATA_TYPE": "STR", "ARR_TYPE" :"N",\
                                                                              "STR_FMT" : "\'{0:s}\',"              },
            "constants_name"                   : {"VALUE": "./TAVGSFC"      , "DATA_TYPE": "STR", "ARR_TYPE" :"S",\
                                                                              "STR_FMT" : "\'{0:s}\',"              },
            "io_form_metgrid"                  : {"VALUE": 2                , "DATA_TYPE": "INT", "ARR_TYPE" :"S"   },
            "opt_output_from_metgrid_path"     : {"VALUE": "./"             , "DATA_TYPE": "STR", "ARR_TYPE" :"S"   ,
                                                                              "STR_FMT" : "\'{0:s}\',"              },
            "opt_metgrid_tbl_path"             : {"VALUE": "metgrid/"       , "DATA_TYPE": "STR", "ARR_TYPE" :"S"   ,
                                                                              "STR_FMT" : "\'{0:s}\',"              },
            "process_only_bdy"                 : {"VALUE": 5                , "DATA_TYPE": "INT", "ARR_TYPE" :"S"   }}

        # mod_levs
        self.DIC_mod_levs_common_para = {\
            "press_pa"                         : {"VALUE": self.ARR_press_pa, "DATA_TYPE": "FLT", "ARR_TYPE" :"M"   }}

        # Plotfmt
        self.DIC_plotfmt_common_para = {\
            "ix"                               : {"VALUE": 100              , "DATA_TYPE": "INT", "ARR_TYPE" :"S"   },
            "jx"                               : {"VALUE": 100              , "DATA_TYPE": "INT", "ARR_TYPE" :"S"   },
            "ioff"                             : {"VALUE": 30               , "DATA_TYPE": "INT", "ARR_TYPE" :"S"   },
            "joff"                             : {"VALUE": 30               , "DATA_TYPE": "INT", "ARR_TYPE" :"S"   }}

        # WRF NAMELIST:
        # Time_Control common parameters:
        self.DIC_time_control_common_para = {\
            "run_days"                         : { "VALUE":  0           , "DATA_TYPE" : "INT" , "ARR_TYPE" :"P"},
            "run_hours"                        : { "VALUE":  0           , "DATA_TYPE" : "INT" , "ARR_TYPE" :"P"},
            "run_minutes"                      : { "VALUE":  0           , "DATA_TYPE" : "INT" , "ARR_TYPE" :"P"},
            "run_seconds"                      : { "VALUE":  0           , "DATA_TYPE" : "INT" , "ARR_TYPE" :"P"},
            "start_year"                       : { "VALUE":  0           , "DATA_TYPE" : "INT" , "ARR_TYPE" :"P"},
            "start_month"                      : { "VALUE":  0           , "DATA_TYPE" : "INT" , "ARR_TYPE" :"P"},
            "start_day"                        : { "VALUE":  0           , "DATA_TYPE" : "INT" , "ARR_TYPE" :"P"},
            "start_hour"                       : { "VALUE":  0           , "DATA_TYPE" : "INT" , "ARR_TYPE" :"P"},
            "start_minute"                     : { "VALUE":  0           , "DATA_TYPE" : "INT" , "ARR_TYPE" :"P"},
            "start_second"                     : { "VALUE":  0           , "DATA_TYPE" : "INT" , "ARR_TYPE" :"P"},
            "end_year"                         : { "VALUE":  0           , "DATA_TYPE" : "INT" , "ARR_TYPE" :"P"},
            "end_month"                        : { "VALUE":  0           , "DATA_TYPE" : "INT" , "ARR_TYPE" :"P"},
            "end_day"                          : { "VALUE":  0           , "DATA_TYPE" : "INT" , "ARR_TYPE" :"P"},
            "end_hour"                         : { "VALUE":  0           , "DATA_TYPE" : "INT" , "ARR_TYPE" :"P"},
            "end_minute"                       : { "VALUE":  0           , "DATA_TYPE" : "INT" , "ARR_TYPE" :"P"},
            "end_second"                       : { "VALUE":  0           , "DATA_TYPE" : "INT" , "ARR_TYPE" :"P"},
            "interval_seconds"                 : { "VALUE":  10800       , "DATA_TYPE" : "INT" , "ARR_TYPE" :"S"},
            "input_from_file"                  : { "VALUE":  True        , "DATA_TYPE" : "BLN" , "ARR_TYPE" :"M"},
            "history_interval"                 : { "VALUE":  60          , "DATA_TYPE" : "INT" , "ARR_TYPE" :"M"},
            "history_outname"                  : { "VALUE":  'wrfout'      , "DATA_TYPE" : "STR" , "ARR_TYPE" :"S",\
                                                   "STR_FMT" : "\'{0:s}_d<domain>{2:s}{1:s}\',"},
            "bdy_inname"                       : { "VALUE":  'wrfbdy'      , "DATA_TYPE" : "STR" , "ARR_TYPE" :"S",\
                                                   "STR_FMT" : "\'{0:s}{1:s}_d<domain>\',"},
            "input_inname"                     : { "VALUE":  'wrfinput'    , "DATA_TYPE" : "STR" , "ARR_TYPE" :"S",\
                                                   "STR_FMT" : "\'{0:s}{1:s}_d<domain>\',"},
            "rst_outname"                      : { "VALUE":  'wrfrst'      , "DATA_TYPE" : "STR" , "ARR_TYPE" :"S",\
                                                   "STR_FMT" : "\'{0:s}_d<domain>{2:s}{1:s}\',"},
            "rst_inname"                       : { "VALUE":  'wrfrst'      , "DATA_TYPE" : "STR" , "ARR_TYPE" :"S",\
                                                   "STR_FMT" : "\'{0:s}_d<domain>{2:s}{1:s}\',"},
            "frames_per_outfile"               : { "VALUE":  1000          , "DATA_TYPE" : "INT" , "ARR_TYPE" :"M"},
            "auxhist1_outname"                 : { "VALUE":  'auxhist1'    , "DATA_TYPE" : "STR" , "ARR_TYPE" :"S",\
                                                   "STR_FMT" : "\'{0:s}_d<domain>{2:s}{1:s}\',"},
            "auxhist2_outname"                 : { "VALUE":  'meteofrance' , "DATA_TYPE" : "STR" , "ARR_TYPE" :"S",\
                                                   "STR_FMT" : "\'{0:s}_d<domain>{2:s}{1:s}\',"},
            "auxhist1_interval"                : { "VALUE":  15          , "DATA_TYPE" : "INT" , "ARR_TYPE" :"S"},
            "auxhist2_interval"                : { "VALUE":  60          , "DATA_TYPE" : "INT" , "ARR_TYPE" :"S"},
            "frames_per_auxhist1"              : { "VALUE":  1000        , "DATA_TYPE" : "INT" , "ARR_TYPE" :"M"},
            "frames_per_auxhist2"              : { "VALUE":  1000        , "DATA_TYPE" : "INT" , "ARR_TYPE" :"M"},
            "aux1_time"                        : { "VALUE":  15          , "DATA_TYPE" : "INT" , "ARR_TYPE" :"S"},
            "aux2_time"                        : { "VALUE":  60          , "DATA_TYPE" : "INT" , "ARR_TYPE" :"S"},
            "interpolation_time"               : { "VALUE":  10          , "DATA_TYPE" : "INT" , "ARR_TYPE" :"S"},
            "interpolation_number"             : { "VALUE":  8           , "DATA_TYPE" : "INT" , "ARR_TYPE" :"S"},
            "restart"                          : { "VALUE":  False       , "DATA_TYPE" : "BLN" , "ARR_TYPE" :"S"},
            "override_restart_timers"          : { "VALUE":  False       , "DATA_TYPE" : "BLN" , "ARR_TYPE" :"S"},
            "restart_interval"                 : { "VALUE":  50000       , "DATA_TYPE" : "INT" , "ARR_TYPE" :"S"},
            "io_form_history"                  : { "VALUE":  2           , "DATA_TYPE" : "INT" , "ARR_TYPE" :"S"},
            "io_form_restart"                  : { "VALUE":  2           , "DATA_TYPE" : "INT" , "ARR_TYPE" :"S"},
            "io_form_input"                    : { "VALUE":  2           , "DATA_TYPE" : "INT" , "ARR_TYPE" :"S"},
            "io_form_boundary"                 : { "VALUE":  2           , "DATA_TYPE" : "INT" , "ARR_TYPE" :"S"},
            "debug_level"                      : { "VALUE":  0           , "DATA_TYPE" : "INT" , "ARR_TYPE" :"S"},
            "io_form_auxinput2"                : { "VALUE":  2           , "DATA_TYPE" : "INT" , "ARR_TYPE" :"S"},
            "io_form_auxhist1"                 : { "VALUE":  2           , "DATA_TYPE" : "INT" , "ARR_TYPE" :"S"},
            "io_form_auxhist2"                 : { "VALUE":  2           , "DATA_TYPE" : "INT" , "ARR_TYPE" :"S"},
            "auxinput1_inname"                 : { "VALUE":  'met_em'    , "DATA_TYPE" : "STR" , "ARR_TYPE" :"S",\
                                                   "STR_FMT" : "\'{0:s}{2:s}.d<domain>.<date>\',"}}

        # Domain Common Parameters:
        self.DIC_domains_common_para= {\
            "time_step"                        : { "VALUE":  20          , "DATA_TYPE" : "INT" , "ARR_TYPE" :"S"},
            "time_step_fract_num"              : { "VALUE":  0           , "DATA_TYPE" : "INT" , "ARR_TYPE" :"S"},
            "time_step_fract_den"              : { "VALUE":  1           , "DATA_TYPE" : "INT" , "ARR_TYPE" :"S"},
            "max_dom"                          : { "VALUE":  1           , "DATA_TYPE" : "INT" , "ARR_TYPE" :"P"},
            "e_we"                             : { "VALUE":  180         , "DATA_TYPE" : "INT" , "ARR_TYPE" :"M"},
            "e_sn"                             : { "VALUE":  180         , "DATA_TYPE" : "INT" , "ARR_TYPE" :"M"},
            "e_vert"                           : { "VALUE":  50          , "DATA_TYPE" : "INT" , "ARR_TYPE" :"M"},
            "p_top_requested"                  : { "VALUE":  5000        , "DATA_TYPE" : "INT" , "ARR_TYPE" :"S"},
            "num_metgrid_levels"               : { "VALUE":  42          , "DATA_TYPE" : "INT" , "ARR_TYPE" :"S"},
            "num_metgrid_soil_levels"          : { "VALUE":  4           , "DATA_TYPE" : "INT" , "ARR_TYPE" :"S"},
            "dx"                               : { "VALUE":  20000       , "DATA_TYPE" : "FLT" , "ARR_TYPE" :"P"},
            "dy"                               : { "VALUE":  20000       , "DATA_TYPE" : "FLT" , "ARR_TYPE" :"P"},
            "grid_id"                          : { "VALUE":  [1,1]       , "DATA_TYPE" : "INT" , "ARR_TYPE" :"P"},
            "parent_id"                        : { "VALUE":  [1,1]       , "DATA_TYPE" : "INT" , "ARR_TYPE" :"P"},
            "i_parent_start"                   : { "VALUE":  [1,1]       , "DATA_TYPE" : "INT" , "ARR_TYPE" :"P"},
            "j_parent_start"                   : { "VALUE":  [100,100]   , "DATA_TYPE" : "INT" , "ARR_TYPE" :"P"},
            "parent_grid_ratio"                : { "VALUE":  [1,3]       , "DATA_TYPE" : "INT" , "ARR_TYPE" :"P"},
            "feedback"                         : { "VALUE":  1           , "DATA_TYPE" : "INT" , "ARR_TYPE" :"S"},
            "use_adaptive_time_step"           : { "VALUE":  True        , "DATA_TYPE" : "BLN" , "ARR_TYPE" :"S"},
            "step_to_output_time"              : { "VALUE":  False       , "DATA_TYPE" : "BLN" , "ARR_TYPE" :"S"},
            "target_cfl"                       : { "VALUE":  1.2         , "DATA_TYPE" : "FLT" , "ARR_TYPE" :"M"},
            "max_step_increase_pct"            : { "VALUE":  5           , "DATA_TYPE" : "INT" , "ARR_TYPE" :"M"},
            "starting_time_step"               : { "VALUE":  20          , "DATA_TYPE" : "INT" , "ARR_TYPE" :"M"},
            "max_time_step"                    : { "VALUE":  100         , "DATA_TYPE" : "INT" , "ARR_TYPE" :"M"},
            "min_time_step"                    : { "VALUE":  -1          , "DATA_TYPE" : "INT" , "ARR_TYPE" :"M"},
            "interp_type"                      : { "VALUE":  2           , "DATA_TYPE" : "INT" , "ARR_TYPE" :"S"},
            "adaptation_domain"                : { "VALUE":  1           , "DATA_TYPE" : "INT" , "ARR_TYPE" :"S"},
            "smooth_option"                    : { "VALUE":  1           , "DATA_TYPE" : "INT" , "ARR_TYPE" :"S"},
            "sfcp_to_sfcp"                     : { "VALUE":  False       , "DATA_TYPE" : "BLN" , "ARR_TYPE" :"S"}}

        # PHYSICS
        self.DIC_physics_common_para = {\
            "mp_physics"                       : { "VALUE":  6           , "DATA_TYPE" : "INT" , "ARR_TYPE" :"M"},
            "ra_lw_physics"                    : { "VALUE":  1           , "DATA_TYPE" : "INT" , "ARR_TYPE" :"M"},
            "ra_sw_physics"                    : { "VALUE":  1           , "DATA_TYPE" : "INT" , "ARR_TYPE" :"M"},
            "sf_sfclay_physics"                : { "VALUE":  1           , "DATA_TYPE" : "INT" , "ARR_TYPE" :"M"},
            "sf_surface_physics"               : { "VALUE":  1           , "DATA_TYPE" : "INT" , "ARR_TYPE" :"M"},
            "bl_pbl_physics"                   : { "VALUE":  1           , "DATA_TYPE" : "INT" , "ARR_TYPE" :"M"},
            "cu_physics"                       : { "VALUE":  [  1,  0 ]  , "DATA_TYPE" : "INT" , "ARR_TYPE" :"A"},
            "radt"                             : { "VALUE":  [ 20,  6 ]  , "DATA_TYPE" : "INT" , "ARR_TYPE" :"A"},
            "bldt"                             : { "VALUE":  0           , "DATA_TYPE" : "INT" , "ARR_TYPE" :"M"},
            "cudt"                             : { "VALUE":  0           , "DATA_TYPE" : "INT" , "ARR_TYPE" :"M"},
            "isftcflx"                         : { "VALUE":  0           , "DATA_TYPE" : "INT" , "ARR_TYPE" :"S"},
            "isfflx"                           : { "VALUE":  1           , "DATA_TYPE" : "INT" , "ARR_TYPE" :"S"},
            "ifsnow"                           : { "VALUE":  1           , "DATA_TYPE" : "INT" , "ARR_TYPE" :"S"},
            "icloud"                           : { "VALUE":  1           , "DATA_TYPE" : "INT" , "ARR_TYPE" :"S"},
            "surface_input_source"             : { "VALUE":  1           , "DATA_TYPE" : "INT" , "ARR_TYPE" :"S"},
            "num_soil_layers"                  : { "VALUE":  5           , "DATA_TYPE" : "INT" , "ARR_TYPE" :"S"},
            "sf_urban_physics"                 : { "VALUE":  0           , "DATA_TYPE" : "INT" , "ARR_TYPE" :"M"},
            "maxiens"                          : { "VALUE":  1           , "DATA_TYPE" : "INT" , "ARR_TYPE" :"S"},
            "maxens"                           : { "VALUE":  3           , "DATA_TYPE" : "INT" , "ARR_TYPE" :"S"},
            "maxens2"                          : { "VALUE":  3           , "DATA_TYPE" : "INT" , "ARR_TYPE" :"S"},
            "maxens3"                          : { "VALUE":  16          , "DATA_TYPE" : "INT" , "ARR_TYPE" :"S"},
            "ensdim"                           : { "VALUE":  144         , "DATA_TYPE" : "INT" , "ARR_TYPE" :"S"},
            "topo_wind"                        : { "VALUE":  0           , "DATA_TYPE" : "INT" , "ARR_TYPE" :"S"},
            "num_land_cat"                     : { "VALUE":  20          , "DATA_TYPE" : "INT" , "ARR_TYPE" :"S"},
            "hail_opt"                         : { "VALUE":  1           , "DATA_TYPE" : "INT" , "ARR_TYPE" :"S"},
            "ysu_st"                           : { "VALUE":  0.25        , "DATA_TYPE" : "FLT" , "ARR_TYPE" :"S"}}

        #       DYNAMICS
        self.DIC_dynamics_common_para = {\
            "w_damping"                        : { "VALUE":  1           , "DATA_TYPE" : "INT" , "ARR_TYPE" :"S"},
            "diff_opt"                         : { "VALUE":  1           , "DATA_TYPE" : "INT" , "ARR_TYPE" :"S"},
            "km_opt"                           : { "VALUE":  4           , "DATA_TYPE" : "INT" , "ARR_TYPE" :"S"},
            "diff_6th_opt"                     : { "VALUE":  0           , "DATA_TYPE" : "INT" , "ARR_TYPE" :"S"},
            "diff_6th_factor"                  : { "VALUE":  0.12        , "DATA_TYPE" : "FLT" , "ARR_TYPE" :"M"},
            "time_step_sound"                  : { "VALUE":  6           , "DATA_TYPE" : "INT" , "ARR_TYPE" :"M"},
            "base_temp"                        : { "VALUE":  290.        , "DATA_TYPE" : "FLT" , "ARR_TYPE" :"S"},
            "damp_opt"                         : { "VALUE":  0           , "DATA_TYPE" : "INT" , "ARR_TYPE" :"S"},
            "dampcoef"                         : { "VALUE":  0.2         , "DATA_TYPE" : "FLT" , "ARR_TYPE" :"S"},
            "khdif"                            : { "VALUE":  0           , "DATA_TYPE" : "INT" , "ARR_TYPE" :"S"},
            "kvdif"                            : { "VALUE":  0           , "DATA_TYPE" : "INT" , "ARR_TYPE" :"S"},
            "non_hydrostatic"                  : { "VALUE":  True        , "DATA_TYPE" : "BLN" , "ARR_TYPE" :"M"},
            "moist_adv_opt"                    : { "VALUE":  1           , "DATA_TYPE" : "INT" , "ARR_TYPE" :"M"},
            "scalar_adv_opt"                   : { "VALUE":  1           , "DATA_TYPE" : "INT" , "ARR_TYPE" :"M"}}

        #       BDY_CONTROL
        self.DIC_bdy_control_common_para = {\
            "spec_bdy_width"                   : { "VALUE":  5             , "DATA_TYPE" : "INT" , "ARR_TYPE" :"S"},
            "spec_zone"                        : { "VALUE":  1             , "DATA_TYPE" : "INT" , "ARR_TYPE" :"S"},
            "relax_zone"                       : { "VALUE":  4             , "DATA_TYPE" : "INT" , "ARR_TYPE" :"S"},
            "specified"                        : { "VALUE":  [True ,False] , "DATA_TYPE" : "BLN" , "ARR_TYPE" :"A"},
            "nested"                           : { "VALUE":  [False, True] , "DATA_TYPE" : "BLN" , "ARR_TYPE" :"A"}}

        #       NAMELIST_QUILT
        self.DIC_namelist_quilt_common_para = {\
            "nio_tasks_per_group"              : { "VALUE":  0           , "DATA_TYPE" : "INT" , "ARR_TYPE" :"S"},
            "nio_groups"                       : { "VALUE":  1           , "DATA_TYPE" : "INT" , "ARR_TYPE" :"S"}}

        #       STOCK: SKEB
        self.DIC_stoch_skebs_common_para = {\
            "skebs"                            : { "VALUE":      1      , "DATA_TYPE" : "INT" , "ARR_TYPE" :"S"},
            "stoch_vertstruc_opt"              : { "VALUE":      0      , "DATA_TYPE" : "INT" , "ARR_TYPE" :"S"},
            "tot_backscat_psi"                 : { "VALUE": 1.0E-5      , "DATA_TYPE" : "SCI" , "ARR_TYPE" :"S"},
            "tot_backscat_t"                   : { "VALUE": 1.0E-6      , "DATA_TYPE" : "SCI" , "ARR_TYPE" :"S"},
            "ztau_psi"                         : { "VALUE":  10800      , "DATA_TYPE" : "INT" , "ARR_TYPE" :"S"},
            "ztau_t"                           : { "VALUE":  10800      , "DATA_TYPE" : "INT" , "ARR_TYPE" :"S"},
            "nens"                             : { "VALUE":      0      , "DATA_TYPE" : "INT" , "ARR_TYPE" :"S"},
            "ISEED_SKEBS"                      : { "VALUE":    100      , "DATA_TYPE" : "INT" , "ARR_TYPE" :"S"}}

        #       STOCK: SPPT
        self.DIC_stoch_sppt_common_para = {\
            "sppt"                             : { "VALUE":      1      , "DATA_TYPE" : "INT" , "ARR_TYPE" :"S"},
            "nens"                             : { "VALUE":      0      , "DATA_TYPE" : "INT" , "ARR_TYPE" :"S"},
            "ISEED_SPPT"                       : { "VALUE":    100      , "DATA_TYPE" : "INT" , "ARR_TYPE" :"S"},
            "timescale_sppt"                   : { "VALUE":  21600      , "DATA_TYPE" : "INT" , "ARR_TYPE" :"S"},
            "gridpt_stddev_sppt"               : { "VALUE":    0.3      , "DATA_TYPE" : "FLT" , "ARR_TYPE" :"S"}}

    def read_user_specific(self, run_time=[], start_time= [], end_time=[], max_dom=0, \
                                 e_we=[], e_sn=[], dx=15000, dy=15000,\
                                 grid_id =[], parent_id = [], \
                                 i_parent_start=[], j_parent_start=[], parent_grid_ratio=[]):
        ARR_run_time   = run_time
        ARR_start_time = start_time
        ARR_end_time   = end_time

        # Checking Date and Time based on the intervals
        ARR_END_DATE_CHK  = Tools.calendar_cal(ARR_start_time, ARR_run_time)

        if Tools.run_time_cal(ARR_END_DATE_CHK) != Tools.run_time_cal(ARR_end_time):
            ARR_end_time  = ARR_END_DATE_CHK
            print("WARNING: The end date is not match with the interval time")
            print("       : The end date is changed as:{0:04d}-{1:02d}-{2:02d}_{3:02d}:{4:02d}:{5:02d}".format(\
                    ARR_end_time[0], ARR_end_time[1],ARR_end_time[2],ARR_end_time[3],ARR_end_time[4],ARR_end_time[5]))

        if max_dom == 0 :
            NUM_MAX_DOM  = 1
        else:
            NUM_MAX_DOM  = max_dom
        self.NUM_MAX_DOM = NUM_MAX_DOM
        self.DIC_user = {\
        "run_days"                         : {"VALUE": [ ARR_run_time[2] ], "DATA_TYPE": "IND" ,"STR_FMT": "     {0:02d}," },\
        "run_hours"                        : {"VALUE": [ ARR_run_time[3] ], "DATA_TYPE": "IND" ,"STR_FMT": "     {0:02d},"},\
        "run_minutes"                      : {"VALUE": [ ARR_run_time[4] ], "DATA_TYPE": "IND" ,"STR_FMT": "     {0:02d},"},\
        "run_seconds"                      : {"VALUE": [ ARR_run_time[5] ], "DATA_TYPE": "IND" ,"STR_FMT": "     {0:02d},"},\
        "start_year"                       : {"VALUE": [ ARR_start_time[0] for d in range(NUM_MAX_DOM)], "DATA_TYPE": "INT","STR_FMT": "   {0:04d},"},\
        "start_month"                      : {"VALUE": [ ARR_start_time[1] for d in range(NUM_MAX_DOM)], "DATA_TYPE": "INT","STR_FMT": "     {0:02d},"},\
        "start_day"                        : {"VALUE": [ ARR_start_time[2] for d in range(NUM_MAX_DOM)], "DATA_TYPE": "INT","STR_FMT": "     {0:02d},"},\
        "start_hour"                       : {"VALUE": [ ARR_start_time[3] for d in range(NUM_MAX_DOM)], "DATA_TYPE": "INT","STR_FMT": "     {0:02d},"},\
        "start_minute"                     : {"VALUE": [ ARR_start_time[4] for d in range(NUM_MAX_DOM)], "DATA_TYPE": "INT","STR_FMT": "     {0:02d},"},\
        "start_second"                     : {"VALUE": [ ARR_start_time[5] for d in range(NUM_MAX_DOM)], "DATA_TYPE": "INT","STR_FMT": "     {0:02d},"},\
        "end_year"                         : {"VALUE": [ ARR_end_time[0] for d in range(NUM_MAX_DOM)], "DATA_TYPE": "INT","STR_FMT": "   {0:04d},"},\
        "end_month"                        : {"VALUE": [ ARR_end_time[1] for d in range(NUM_MAX_DOM)], "DATA_TYPE": "INT","STR_FMT": "     {0:02d},"},\
        "end_day"                          : {"VALUE": [ ARR_end_time[2] for d in range(NUM_MAX_DOM)], "DATA_TYPE": "INT","STR_FMT": "     {0:02d},"},\
        "end_hour"                         : {"VALUE": [ ARR_end_time[3] for d in range(NUM_MAX_DOM)], "DATA_TYPE": "INT","STR_FMT": "     {0:02d},"},\
        "end_minute"                       : {"VALUE": [ ARR_end_time[4] for d in range(NUM_MAX_DOM)], "DATA_TYPE": "INT","STR_FMT": "     {0:02d},"},\
        "end_second"                       : {"VALUE": [ ARR_end_time[5] for d in range(NUM_MAX_DOM)], "DATA_TYPE": "INT","STR_FMT": "     {0:02d},"},\
        "max_dom"                     : {"VALUE":  [ NUM_MAX_DOM ]            , "DATA_TYPE": "INT","STR_FMT": "{0:7d},"},\
        "e_we"                        : {"VALUE":          e_we               , "DATA_TYPE": "INT","STR_FMT": "{0:7d},"},\
        "e_sn"                        : {"VALUE":          e_sn               , "DATA_TYPE": "INT","STR_FMT": "{0:7d},"},\
#        "e_vert"                      : {"VALUE": self.ARR_e_vert, "DATA_TYPE": "INT","STR_FMT": "{0:7d},"},\
        "dx"                          : {"VALUE":        [ dx ]               , "DATA_TYPE": "INT","STR_FMT": "{0:7.3f},"},\
        "dy"                          : {"VALUE":        [ dy ]               , "DATA_TYPE": "INT","STR_FMT": "{0:7.3f},"},\
        "grid_id"                     : {"VALUE":          grid_id            , "DATA_TYPE": "INT","STR_FMT": "{0:7d},"},\
        "parent_id"                   : {"VALUE":          parent_id          , "DATA_TYPE": "INT","STR_FMT": "{0:7d},"},\
        "i_parent_start"              : {"VALUE":          i_parent_start     , "DATA_TYPE": "INT","STR_FMT": "{0:7d},"},\
        "j_parent_start"              : {"VALUE":          j_parent_start     , "DATA_TYPE": "INT","STR_FMT": "{0:7d},"},\
        "parent_grid_ratio"           : {"VALUE":          parent_grid_ratio  , "DATA_TYPE": "INT","STR_FMT": "{0:7d},"},\
#        "max_step_increase_pct"       : {"VALUE": self.ARR_max_step_increase_pct, "DATA_TYPE": "INT","STR_FMT": "{0:7d},"},\
#        "starting_time_step"          : {"VALUE": self.ARR_starting_time_step, "DATA_TYPE": "INT","STR_FMT": "{0:7d},"},\
#        "max_time_step"               : {"VALUE": self.ARR_max_time_step, "DATA_TYPE": "INT","STR_FMT": "{0:7d},"},\
        }
        return 0

    def BLN2WRFSTR(self, BL_in):
        if BL_in:
            STR_out = " .true."
        else:
            STR_out = ".false."
        return STR_out

    def write_namelist(self, DIC_in, ARR_in):
        DIC_DATA_TYPE_STR = {"FLT": "{0:7.2f},","BLN": "{0:s},","INT": "{0:7d},", "SCI": "{0:1.1E}," , "STR": "\'{0:s}\'," }
        for ARR_item in ARR_in :
            self.FILE.write(" {0:s} = ".format(ARR_item.ljust(25, ' ')))
            if self.debug: print("Working on var: {0:s}".format(ARR_item))
            if DIC_in[ARR_item]["ARR_TYPE"] == "S":
                # the ARR_TYPE as single input number
                if DIC_in[ARR_item]["DATA_TYPE"] == "BLN":
                    self.FILE.write(DIC_DATA_TYPE_STR[DIC_in[ARR_item]["DATA_TYPE"]].format(self.BLN2WRFSTR(DIC_in[ARR_item]["VALUE"])))
                elif DIC_in[ARR_item]["DATA_TYPE"] == "STR":
                    if self.IF_ensemble_run:
                        self.FILE.write(DIC_in[ARR_item]["STR_FMT"].format(DIC_in[ARR_item]["VALUE"],\
                                "{0:05d}".format(self.NUM_ensemble_member), \
                                self.STR_connect_symbol, \
                                "{0:05d}".format(self.NUM_input_ensemble_member)))
                    else:
                        self.FILE.write(DIC_in[ARR_item]["STR_FMT"].format(DIC_in[ARR_item]["VALUE"], ""              , ""))
                else:
                    self.FILE.write(DIC_DATA_TYPE_STR[DIC_in[ARR_item]["DATA_TYPE"]].format(DIC_in[ARR_item]["VALUE"]))
            elif DIC_in[ARR_item]["ARR_TYPE"] == "M":
                # the ARR_TYPE as multi input number but same all in a row
                for d in range(self.NUM_MAX_DOM):
                    if DIC_in[ARR_item]["DATA_TYPE"] == "BLN":
                        self.FILE.write(DIC_DATA_TYPE_STR[DIC_in[ARR_item]["DATA_TYPE"]].format(self.BLN2WRFSTR(DIC_in[ARR_item]["VALUE"])))
                    else:
                        self.FILE.write(DIC_DATA_TYPE_STR[DIC_in[ARR_item]["DATA_TYPE"]].format(DIC_in[ARR_item]["VALUE"][d]))

            elif DIC_in[ARR_item]["ARR_TYPE"] == "N":
                # the ARR_TYPE as multi input number but same all in a row
                for d in range( len(DIC_in[ARR_item]["VALUE"]) ):
                    if DIC_in[ARR_item]["DATA_TYPE"] == "BLN":
                        self.FILE.write(DIC_DATA_TYPE_STR[DIC_in[ARR_item]["DATA_TYPE"]].format(self.BLN2WRFSTR(DIC_in[ARR_item]["VALUE"])))
                    else:
                        self.FILE.write(DIC_DATA_TYPE_STR[DIC_in[ARR_item]["DATA_TYPE"]].format(DIC_in[ARR_item]["VALUE"][d]))
            elif DIC_in[ARR_item]["ARR_TYPE"] == "P":
            # the ARR_TYPE as multi input number but must be user specific
                if len(self.DIC_user[ARR_item]["VALUE"]) == 1:
                    self.FILE.write(self.DIC_user[ARR_item]["STR_FMT"].format(self.DIC_user[ARR_item]["VALUE"][0]))
                else:
                    for d in range(self.NUM_MAX_DOM):
                        if DIC_in[ARR_item]["DATA_TYPE"] == "BLN":
                            self.FILE.write(self.DIC_user[ARR_item]["STR_FMT"].format(self.BLN2WRFSTR(self.DIC_user[ARR_item]["VALUE"][d])))
                        else:
                            self.FILE.write(self.DIC_user[ARR_item]["STR_FMT"].format(self.DIC_user[ARR_item]["VALUE"][d]))

            elif DIC_in[ARR_item]["ARR_TYPE"] == "A":
            # the ARR_TYPE as multi input number but can be different in a row
                for d in range(self.NUM_MAX_DOM):
                    if DIC_in[ARR_item]["DATA_TYPE"] == "BLN":
                        if d == 0:
                            self.FILE.write(DIC_DATA_TYPE_STR[DIC_in[ARR_item]["DATA_TYPE"]].format(self.BLN2WRFSTR(DIC_in[ARR_item]["VALUE"][0])))
                        else:
                            self.FILE.write(DIC_DATA_TYPE_STR[DIC_in[ARR_item]["DATA_TYPE"]].format(self.BLN2WRFSTR(DIC_in[ARR_item]["VALUE"][-1])))

                    else:
                        if d == 0:
                            self.FILE.write(DIC_DATA_TYPE_STR[DIC_in[ARR_item]["DATA_TYPE"]].format(DIC_in[ARR_item]["VALUE"][0]))
                        else:
                            self.FILE.write(DIC_DATA_TYPE_STR[DIC_in[ARR_item]["DATA_TYPE"]].format(DIC_in[ARR_item]["VALUE"][-1]))

            self.FILE.write("\n")

    def create_wps_namelist(self):
        self.FILE     = open("{0:s}/{1:s}".format(self.STR_DIR, self.STR_wps_namelist), "w")
        print("Starting creating the namelist for wps: {0:s}".format(self.STR_wps_namelist))
        print("starting creating the namelist: {0:s}".format(self.STR_wps_namelist))
        self.FILE.write("&share\n")
        self.write_namelist(self.DIC_share_common_para, self.ARR_share)
        self.FILE.write("/\n")
        self.FILE.write("&geogrid\n")
        self.write_namelist(self.DIC_geogrid_common_para, self.ARR_geogrid)
        self.FILE.write("/\n")
        self.FILE.write("&ungrib\n")
        self.write_namelist(self.DIC_ungrib_common_para, self.ARR_ungrib)
        self.FILE.write("/\n")
        self.FILE.write("&metgrid\n")
        self.write_namelist(self.DIC_metgrid_common_para, self.ARR_metgrid)
        self.FILE.write("/\n")

        self.FILE.close()
        return 0

    def create_a_namelist(self):
        if self.IF_ensemble_run :
            self.FILE     = open("{0:s}/{1:s}{2:05d}".format(self.STR_DIR, self.STR_wrf_namelist, self.NUM_ensemble_member), "w")
        else:
            self.FILE     = open("{0:s}/{1:s}".format(self.STR_DIR, self.STR_wrf_namelist), "w")

        print("starting creating the namelist: {0:s}".format(self.STR_wrf_namelist))
        self.FILE.write("&time_control\n")
        self.write_namelist(self.DIC_time_control_common_para, self.ARR_time_control)
        self.FILE.write("/\n")
        self.FILE.write("&domains\n")
        self.write_namelist(self.DIC_domains_common_para, self.ARR_domains)
        self.FILE.write("/\n")
        self.FILE.write("&physics\n")
        self.write_namelist(self.DIC_physics_common_para, self.ARR_physics)
        self.FILE.write("/\n")
        self.FILE.write("&fdda\n")
        self.FILE.write("/\n")
        self.FILE.write("&dynamics\n")
        self.write_namelist(self.DIC_dynamics_common_para, self.ARR_dynamics)
        self.FILE.write("/\n")
        self.FILE.write("&bdy_control\n")
        self.write_namelist(self.DIC_bdy_control_common_para, self.ARR_bdy_control)
        self.FILE.write("/\n")
        self.FILE.write("&namelist_quilt\n")
        self.write_namelist(self.DIC_namelist_quilt_common_para, self.ARR_namelist_quilt)
        self.FILE.write("/\n")
        if self.IF_SKEBS:
            self.FILE.write("&stoch\n")
            self.write_namelist(self.DIC_stoch_skebs_common_para, self.ARR_stoch_skebs)
            self.FILE.write("/\n")
        elif self.IF_SPPT:
            self.FILE.write("&stoch\n")
            self.write_namelist(self.DIC_stoch_sppt_common_para, self.ARR_stoch_sppt)
            self.FILE.write("/\n")

        self.FILE.close()
        return 0

if __name__ == "main" :
    print("No Warranty for usage.")


import streamlit as st
import re
import pandas as pd
import emoji
import os
import spacy
from arabert.preprocess import ArabertPreprocessor
from sklearn.metrics import accuracy_score
from sklearn.metrics import precision_score
from sklearn.metrics import recall_score
from sklearn.metrics import f1_score, classification_report

@st.cache
def clean_text(text):
    arabic_punctuations = '''`÷×؛<>_()*&^%][ـ،/:"؟.,'{}~¦+|?�!”…“#•–ـ''' # define arabic punctuations
    text = re.sub(r'@\S+', '', text) # remove profile tags
    text = re.sub("[a-zA-Z]", " ", text) # remove english letters
    text = re.sub('\n', ' ', text) # remove \n from text
    text = re.sub(r'\d+', '', text) #remove number
    text = re.sub(r'http\S+', '', text) # remove links
    text = re.sub(r'#\S+', '', text) # remove hashtags
    text = emoji.replace_emoji(text, '') # remove emojies
    # text = text.translate(str.maketrans('','', arabic_punctuations)) # remove punctuation
    text = re.sub(' +', ' ',text) # remove extra space
    text = text.strip() #remove whitespaces
    text = text.replace('@', '')

    return text

@st.cache(allow_output_mutation=True)
def load_arabert():
    model_name = "aubmindlab/bert-base-arabertv2"
    arabert_prep = ArabertPreprocessor(model_name=model_name)
    return arabert_prep

@st.cache
def preprocess_text(text):
  text = re.sub("[a-zA-Z]", " ", text) # remove english letters
  text = re.sub(r'[ء-ي]+@', '', text) # remove profile tags
  text = re.sub(r'[ء-ي]+#', '', text) # remove profile tags
  arabert_prep = load_arabert()
  text = arabert_prep.preprocess(text)
  return text

def get_prediction(text, model):
    result = model(text).cats
    label = sorted(result, key=result.get, reverse=True)[0]
    score = result[label]

    return label, score

@st.cache
def convert_df(df):
    return df.to_csv().encode('utf-8')

@st.cache
def compute_score(target, predicted, score):
    if score == 'accuracy':
        return accuracy_score(target, predicted)
    elif score == 'recall':
        return recall_score(target, predicted, pos_label='not Misogyny')
    elif score == 'precision':
        return precision_score(target, predicted, pos_label='not Misogyny')
    elif score == 'f1_score':
        return f1_score(target, predicted, pos_label='not Misogyny')

@st.cache
def classify_from_df(df, column):
    predicted_classes_off = []
    scores_off = []
    letmi = []
    armis = []
    letmi_armis = []
    fb_votes = []
    scores_misg = []
    path = './models/vaw_misogyny_models/'
    misg = {}
    misg_paths = []
    models = []
    # get misogyny models
    for i in os.listdir(path):
        models.append(i)
        misg_paths.append(path+i)

    # load misogyny models
    loaded_misg_models = []
    for i in misg_paths:
        loaded_misg_models.append(spacy.load(i))

    # classify with models
    predictions_misg = []

    for t in list(df[column]):
        text_cleaned = preprocess_text(t)
        # offensive
        label, score = get_prediction(text_cleaned, st.session_state['nlp_off'])
        label = label.replace('_', ' ')
        predicted_classes_off.append(label)
        scores_off.append(score)
        # misogyny
        for i in range(len(loaded_misg_models)):
            label_misg, score_misg = get_prediction(text_cleaned, loaded_misg_models[i])
            label_misg = 'not Misogyny' if label_misg == 'none' else 'Misogyny'
            if models[i] not in misg.keys():
                misg[models[i]] = []

            misg[models[i]].append(label_misg)

    df_output = pd.DataFrame(list(zip(list(df[column]), predicted_classes_off, scores_off, misg['ArMIS'], misg['LetMI'], misg['LetMI_ArMIS'], misg['Model_fb_data_votes'])), columns=['Text', 'Offensiveness (predicted)', 'Score (Offensiveness)', 'Misogyny (ArMIS)', 'Misogyny (LetMI)', 'Misogyny (LetMI_ArMIS)', 'Misogyny (Model_fb_data_votes)'])
    return df_output