def main():
    test = Solution()
    list1 = [1, 2, 4]
    head1 = ListNode(list1[0])
    tail1 = head1
    for i in range(1, len(list1)):
        tail1.next = ListNode(list1[i])
        tail1 = tail1.next
    list2 = [1, 3, 4]
    head2 = ListNode(list2[0])
    tail2 = head2
    for i in range(1, len(list2)):
        tail2.next = ListNode(list2[i])
        tail2 = tail2.next
    temp1 = head1
    while temp1 is not None:
        print(f'{temp1.val}, ', end='')
        temp1 = temp1.next

    print('\n')
    temp2 = head2
    while temp2 is not None:
        print(f'{temp2.val}, ', end='')
        temp2 = temp2.next

    print('\n\nmerged lists')
    head3 = test.mergeTwoLists(head1, head2)
    temp3 = head3
    while temp3 is not None:
        print(f'{temp3.val}, ', end='')
        temp3 = temp3.next

    # list3 = [1]
    # list4 = []
    # print(list3)
    # print(list4)
    # print(f'merged list: ', end='')
    # print(test.mergeTwoLists(list3, list4))

class ListNode(object):
    def __init__(self, val=0, next=None):
        self.val = val
        self.next = next

class Solution(object):
    def mergeTwoLists(self, list1, list2):
        """
        :type list1: Optional[ListNode]
        :type list2: Optional[ListNode]
        :rtype: Optional[ListNode]
        """
        # write a solution that actually uses linked lists
        merged_head = ListNode(0)
        merged_tail = merged_head

        # while both lists still have remaining nodes
        while list1 is not None and list2 is not None:
            if list1.val < list2.val:
                merged_tail.next = list1
                list1 = list1.next
            else:
                merged_tail.next = list2
                list2 = list2.next
            merged_tail = merged_tail.next

        # at this point either one of the lists is exhausted or theyre both exhausted
        if list1 is None and list2 is not None:
            merged_tail.next = list2
        else:
            merged_tail.next = list1

        return merged_head.next

        # merged_head = ListNode(None, None)
        # merged_tail = None
        # pointer1 = list1
        # pointer2 = list2
        #
        # while pointer1 is not None or pointer2 is not None:
        #     # for the case that list1 is exhausted and list2 is not
        #     if pointer1 is None and pointer2 is not None:
        #         if merged_head.val is None:
        #             print(f'{pointer2.val}, ', end='')
        #             merged_head = ListNode(pointer2.val)
        #             merged_tail = merged_head
        #         else:
        #             print(f'{pointer2.val}, ', end='')
        #             temp = ListNode(pointer2.val)
        #             merged_tail.next = temp
        #             merged_tail = temp
        #         pointer2 = pointer2.next
        #     # for the case that list1 is not exhauted and list2 is
        #     elif pointer1 is not None and pointer2 is None:
        #         if merged_head.val is None:
        #             print(f'{pointer1.val}, ', end='')
        #             merged_head = ListNode(pointer1.val)
        #             merged_tail = merged_head
        #         else:
        #             print(f'{pointer1.val}, ', end='')
        #             temp = ListNode(pointer1.val)
        #             merged_tail.next = temp
        #             merged_tail = temp
        #         pointer1 = pointer1.next
        #     # for the case that neither list one nor two are exhausted
        #     else:
        #         if pointer1.val > pointer2.val:
        #             if merged_head.val is None:
        #                 print(f'{pointer2.val}, ', end='')
        #                 merged_head = ListNode(pointer2.val)
        #                 merged_tail = merged_head
        #             else:
        #                 print(f'{pointer2.val}, ', end='')
        #                 temp = ListNode(pointer2.val)
        #                 merged_tail.next = temp
        #                 merged_tail = temp
        #             pointer2 = pointer2.next
        #         else:
        #             if merged_head.val is None:
        #                 print(f'{pointer1.val}, ', end='')
        #                 merged_head = ListNode(pointer1.val)
        #                 merged_tail = merged_head
        #             else:
        #                 print(f'{pointer1.val}, ', end='')
        #                 temp = ListNode(pointer1.val)
        #                 merged_tail.next = temp
        #                 merged_tail = temp
        #             pointer1 = pointer1.next
        # return merged_head

        #
        # merged = list()
        # index1 = 0
        # index2 = 0
        #
        # while index1 < len(list1) or index2 < len(list2):
        #     # for the case that list1 is exhausted and list2 is not
        #     if index1 >= len(list1) and index2 < len(list2):
        #         # add an item from list 2 to the merged list
        #         merged.append(list2[index2])
        #         index2 += 1
        #     # for the case that list1 is not exhausted and list2 is
        #     elif index1 < len(list1) and index2 >= len(list2):
        #         # add an item from list 1 to the merged list
        #         merged.append(list1[index1])
        #         index1 += 1
        #     elif index1 < len(list1) and index2 < len(list2):
        #         if list1[index1] > list2[index2]:
        #             merged.append(list2[index2])
        #             index2 += 1
        #         else:
        #             merged.append(list1[index1])
        #             index1 += 1
        #     # find the list index that points to the
        #
        # return merged

if __name__ == "__main__":
    main()


""" check whether the given binary tree is Binary Search Tree or not
"""

import sys

class Node:
    """ Node contains actual data and address to left and right node """
    def __init__(self, data):
        self.data = data
        self.left = None
        self.right = None

class BinarySearchTree:
    """ Binary Search Tree Implementation """
    def __init__(self):
        self.root = None

    def insert(self, data):
        """ inserts new integer data into the tree at the position, so that
            the binary search tree property is maintained.
        """
        def _insert(root, data):
            """ recursive internal method which works on node level """
            if root is None:
                root = Node(data)
            elif data <= root.data:
                root.left = _insert(root.left, data)
            else:
                root.right = _insert(root.right, data)
            return root

        if self.root is None:
            self.root = Node(data)
        else:
            self.root = _insert(self.root, data)

def is_bst(root):
    """ checks if binary tree is binary search tree """
    def is_bst_util(root, min_value, max_value):
        """ binary search tree check utility function """
        if root is None:
            return True

        if (root.data >= min_value and root.data < max_value
                and is_bst_util(root.left, min_value, root.data)
                and is_bst_util(root.right, root.data, max_value)):
            return True
        return False

    return is_bst_util(root, -sys.maxsize - 1, sys.maxsize)

def main():
    """ operational function """
    bst1 = BinarySearchTree()
    for elem in [9, 5, 3, 10, 6, 1, 7, 4]:
        bst1.insert(elem)
    print("is BST?", is_bst(bst1.root))

    bst2 = BinarySearchTree()
    bst2.root = Node(5)
    bst2.root.right = Node(7)
    bst2.root.left = Node(5)
    bst2.root.left.left = Node(1)
    bst2.root.left.right = Node(4)
    bst2.root.right.right = Node(6)
    print("is BST?", is_bst(bst2.root))

if __name__ == "__main__":
    main()


from xml.sax import saxutils

class FindSample(saxutils.handler.ContentHandler):
  def __init__(self,label):
    self.label = label
    self.results =[]

  def startElement(self,name,attrs):

    if name != 'httpSample': return

    label = attrs.get('lb',"")
    if label == self.label:
      row={}
      row['ts']=int(attrs.get('ts',""))
      row['elapsed']=int(attrs.get('t',""))
      row['latency']=int(attrs.get('lt',""))
      self.results.append(row)

  def getresults(self):
    return self.results


# views handling halaman dashboard admin
import pandas as pd
import pathlib

from flask import Blueprint, render_template, redirect, url_for, request, flash
from flask_login import login_required, current_user

from .models import User, Kecamatan, Rumah, Agen, FixedBunga, GambarRumah
from .handle_image_upload import upload_image, delete_image
from .handle_dataset_upload import (
    upload_dataset,
    delete_dataset,
    input_dataset_to_database,
)
from . import db

admin_views = Blueprint("admin_views", __name__)

######################################
# functions
######################################

# fungsi untuk mengecek apakah user adalah admin atau tidak
def check_admin():
    user_object = User.query.get(current_user.get_id())
    return user_object.is_admin

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

#
#
# API untuk handle admin dashboard, query jumlah rumah, kecamatan, user
# untuk di tampilkan di halaman dashboard admin
@admin_views.route("/admin_dashboard", methods=["GET"])
@login_required
def admin_dashboard():
    if not check_admin():
        return redirect(url_for("public_views_loggedin.profile_page"))

    count_rumah = Rumah.query.count()
    count_kecamatan = Kecamatan.query.count()
    count_user = User.query.count()
    admin_user = User.query.get(current_user.get_id())
    fixed_bunga = FixedBunga.query.get(1)

    return render_template(
        "admin/dashboard.html",
        admin_user=admin_user,
        count_rumah=count_rumah,
        count_kecamatan=count_kecamatan,
        count_user=count_user,
        fixed_bunga=fixed_bunga,
    )

# handle editing fixed bunga ke dalam database
@admin_views.route("/handle_edit_bunga", methods=["POST"])
@login_required
def handle_edit_bunga():
    if not check_admin():
        return redirect(url_for("public_views_loggedin.profile_page"))

    fixed_bunga = request.form.get("fixed_bunga")

    to_edit_bunga = FixedBunga.query.get(1)

    if to_edit_bunga:
        to_edit_bunga.fixed_bunga = fixed_bunga
        db.session.commit()
        flash(
            f"berhasil mengedit fixed bunga menjadi {to_edit_bunga.fixed_bunga}",
            category="success",
        )
        return redirect("/admin_dashboard")

    flash(f"gagal mengedit fixed bunga")
    return redirect("/admin_dashboard")

#
#
# API untuk handle halaman kecamatan pada admin dashboard
# query semua kecamatan dalam database dan ditampilkan pada
# dahsboard admin
@admin_views.route("/admin_kecamatan", methods=["GEt"])
@login_required
def admin_kecamatan():
    if not check_admin():
        return redirect(url_for("public_views_loggedin.profile_page"))

    all_kecamatan = Kecamatan.query.all()

    return render_template("admin/kecamatan.html", all_kecamatan=all_kecamatan)

# menampilkan halaman penambahan kecamatan pada dashboard admin
@admin_views.route("/tambah_kecamatan", methods=["GET"])
@login_required
def tambah_kecamatan():
    if not check_admin():
        return redirect(url_for("public_views_loggedin.profile_page"))

    return render_template("admin/tambah-kecamatan.html")

# handle penambahan kecamatan pada halaman tambah kecamatan
@admin_views.route("/handle_tambah_kecamatan", methods=["POST"])
@login_required
def handle_tambah_kecamatan():
    if not check_admin():
        return redirect(url_for("public_views_loggedin.profile_page"))

    kecamatan = request.form.get("kecamatan")

    to_add_kecamatan = Kecamatan(nama_kecamatan=kecamatan)
    db.session.add(to_add_kecamatan)
    db.session.commit()

    flash(f"Berhasil menambah kecamatan {kecamatan}", category="success")
    return redirect("/tambah_kecamatan")

# menampilkan halaman edit kecamatan pada admin dashboard
@admin_views.route("/edit_kecamatan/<int:id>", methods=["GET"])
@login_required
def edit_kecamatan(id):
    if not check_admin():
        return redirect(url_for("public_views_loggedin.profile_page"))

    to_edit_kecamatan = Kecamatan.query.get(id)

    return render_template(
        "admin/edit-kecamatan.html", to_edit_kecamatan=to_edit_kecamatan
    )

# handle edit kecamatan pada halaman edit kecamatan
@admin_views.route("/handle_edit_kecamatan/<int:id>", methods=["POST"])
@login_required
def handle_edit_kecamatan(id):
    if not check_admin():
        return redirect(url_for("public_views_loggedin.profile_page"))

    to_edit_kecamatan = Kecamatan.query.get(id)

    nama_kecamatan_baru = request.form.get("kecamatan")

    if to_edit_kecamatan:
        to_edit_kecamatan.nama_kecamatan = nama_kecamatan_baru
        db.session.commit()
        flash(
            f"berhasil mengedit data kecamatan {to_edit_kecamatan.nama_kecamatan}",
            category="success",
        )
        return redirect(f"/edit_kecamatan/{id}")

    flash(
        f"gagal mengedit data kecamatan {to_edit_kecamatan.nama_kecamatan}",
        category="error",
    )
    return redirect(f"/edit_kecamatan/{id}")

# handle penghapusan data kecamatan melalui admin dashboard
@admin_views.route("/delete_kecamatan/<int:id>", methods=["POST"])
def delete_kecamatan(id):
    to_delete_kecamatan = Kecamatan.query.get(id)
    if to_delete_kecamatan:
        flash(
            f"berhasil menghapus data kecamatan {to_delete_kecamatan.nama_kecamatan}",
            category="warning",
        )
        db.session.delete(to_delete_kecamatan)
        db.session.commit()
        return redirect("/admin_kecamatan")

    flash(
        f"gagal menghapus data kecamtan {to_delete_kecamatan.nama_kecamatan}",
        category="error",
    )
    return redirect("/admin_kecamatan")

#
#
# API untuk handle admin rumah
# mengqueru semua rumah dan ditampilkan di halaman dashboard admin
# pada menu rumah
@admin_views.route("/admin_rumah", methods=["GET"])
@login_required
def admin_rumah():
    if not check_admin():
        return redirect(url_for("admin_views_loggedin.profile_page"))

    all_rumah = Rumah.query.all()

    return render_template("admin/rumah.html", all_rumah=all_rumah)

# menampilkan halaman tambah rumah pada dashboard admin
@admin_views.route("/tambah_rumah", methods=["GET"])
@login_required
def tambah_rumah():
    if not check_admin():
        return redirect(url_for("public_views_loggedin.profile_page"))

    all_rumah = Rumah.query.all()
    all_agen = Agen.query.all()
    all_kecamatan = Kecamatan.query.all()

    return render_template(
        "admin/tambah-rumah.html",
        all_rumah=all_rumah,
        all_agen=all_agen,
        all_kecamatan=all_kecamatan,
    )

# handle penambahan rummah pada dashboard admin
@admin_views.route("/handle_tambah_rumah", methods=["POST"])
@login_required
def handle_tambah_rumah():
    if not check_admin():
        return redirect(url_for("public_views_loggedin.profile_page"))

    nama_perumahan = request.form.get("nama_perumahan")
    alamat = request.form.get("alamat")
    kecamatan = request.form.get("kecamatan")
    luas = request.form.get("luas")
    harga = request.form.get("harga")
    lantai = request.form.get("lantai")
    kamar_tidur = request.form.get("kamar_tidur")
    kamar_mandi = request.form.get("kamar_mandi")

    get_kontak_agen = request.form.get("kontak_agen").split(",")
    kontak_agen = get_kontak_agen[0]
    kontak_agen_id = int(get_kontak_agen[1])

    data_agen = Agen.query.get(kontak_agen_id)
    agen_nomor_telepon = data_agen.nomor_telepon
    agen_email = data_agen.email
    agen_whatsapp = data_agen.whatsapp

    latitude = request.form.get("latitude")
    longitude = request.form.get("longitude")
    deskripsi = request.form.get("deskripsi")
    gambar = request.files["gambar-rumah"]
    fasilitas = request.values.getlist("fasilitas")

    if gambar:
        if gambar == "":
            flash("Gambar Kosong", category="error")
            return redirect("/tambah_rumah")

        nama_file_gambar = upload_image(gambar, None)

    to_add_rumah = Rumah(
        nama_perumahan=nama_perumahan,
        alamat=alamat,
        kecamatan=kecamatan,
        luas=luas,
        harga=harga,
        lantai=lantai,
        kamar_tidur=kamar_tidur,
        kamar_mandi=kamar_mandi,
        kontak_agen=kontak_agen,
        kontak_agen_id=kontak_agen_id,
        agen_nomor_telepon=agen_nomor_telepon,
        agen_email=agen_email,
        agen_whatsapp=agen_whatsapp,
        latitude=latitude,
        longitude=longitude,
        deskripsi=deskripsi,
        fasilitas=", ".join(fasilitas),
    )
    db.session.add(to_add_rumah)
    db.session.commit()

    to_add_gambar = GambarRumah(
        nama_gambar=nama_file_gambar,
        rumah=Rumah.query.filter(Rumah.alamat == alamat).first().id,
    )
    db.session.add(to_add_gambar)
    db.session.commit()

    flash(f"Rumah {alamat} berhasil ditambah", category="success")
    return redirect("/tambah_rumah")

@admin_views.route("/handle_tambah_rumah_upload_dataset", methods=["POST"])
def handle_tambah_rumah_upload_dataset():
    dataset_file = request.files["dataset-rumah"]

    dataset_is_uploaded, message = upload_dataset(dataset_file)

    if dataset_is_uploaded:
        flash(message, category="success")
        input_dataset_to_database(dataset_file)
        return redirect("/admin_rumah")

    flash(message, category="error")
    return redirect("/admin_rumah")

# menampilkan halaman edit rumah pada dashboard admin
@admin_views.route("/edit_rumah/<int:id>", methods=["GET"])
@login_required
def edit_rumah(id):
    if not check_admin():
        return redirect(url_for("public_views_loggedin.profile_page"))

    to_edit_rumah = Rumah.query.get(id)
    all_agen = Agen.query.all()
    all_kecamatan = Kecamatan.query.all()

    return render_template(
        "admin/edit-rumah.html",
        to_edit_rumah=to_edit_rumah,
        all_agen=all_agen,
        all_kecamatan=all_kecamatan,
    )

# handle pengeditan data rummah pada dashboard admin
@admin_views.route("/handle_edit_rumah/<int:id>", methods=["POST"])
@login_required
def handle_edit_rumah(id):
    if not check_admin():
        return redirect(url_for("public_views_loggedin.profile_page"))

    to_edit_rumah = Rumah.query.get(id)

    nama_perumahan = request.form.get("nama_perumahan")
    alamat = request.form.get("alamat")
    kecamatan = request.form.get("kecamatan")
    luas = request.form.get("luas")
    harga = request.form.get("harga")
    lantai = request.form.get("lantai")
    kamar_tidur = request.form.get("kamar_tidur")
    kamar_mandi = request.form.get("kamar_mandi")
    kontak_agen = request.form.get("kontak_agen")
    latitude = request.form.get("latitude")
    longitude = request.form.get("longitude")
    deskripsi = request.form.get("deskripsi")
    fasilitas = request.values.getlist("fasilitas")

    if to_edit_rumah:
        to_edit_rumah.nama_perumahan = nama_perumahan
        to_edit_rumah.alamat = alamat
        to_edit_rumah.kecamatan = kecamatan
        to_edit_rumah.luas = luas
        to_edit_rumah.harga = harga
        to_edit_rumah.lantai = lantai
        to_edit_rumah.kamar_tidur = kamar_tidur
        to_edit_rumah.kamar_mandi = kamar_mandi
        to_edit_rumah.kontak_agen = kontak_agen
        to_edit_rumah.latitude = latitude
        to_edit_rumah.longitude = longitude
        to_edit_rumah.gambar = to_edit_rumah.gambar
        to_edit_rumah.deskripsi = deskripsi
        to_edit_rumah.fasilitas = ", ".join(fasilitas)
        db.session.commit()
        flash(
            f"berhasil mengedit data rumah {to_edit_rumah.alamat}", category="warning"
        )
        return redirect(f"/edit_rumah/{id}")

    flash(f"gagal mengedit data rumah {to_edit_rumah.alamat}", category="error")
    return redirect(f"/edit_rumah/{id}")

@admin_views.route("/handle_tambah_gambar_rumah/<int:id>", methods=["POST"])
def handle_tambah_gambar_rumah(id):
    gambar = request.files["gambar-rumah"]

    nama_file_gambar = upload_image(gambar, None)
    to_add_gambar = GambarRumah(
        nama_gambar=nama_file_gambar,
        rumah=id,
    )
    db.session.add(to_add_gambar)
    db.session.commit()

    flash("Berhasil menambah gambar rumah")
    return redirect(f"/edit_rumah/{id}")

@admin_views.route("/handle_hapus_gambar_rumah/<int:id>", methods=["POST"])
def handle_hapus_gambar_rumah(id):
    id_gambar = int(request.form.get("id-gambar"))
    to_edit_rumah = Rumah.query.get(id)

    print(id_gambar)

    for gambar in to_edit_rumah.gambar:
        print(gambar.id, id_gambar)
        if gambar.id == id_gambar:
            to_delete_gambar = GambarRumah.query.get(gambar.id)
            print(f"{gambar.id} == {id_gambar}")
            flash(f"Berhasil menghapus gambar {gambar.nama_gambar}")
            delete_image(gambar.nama_gambar)
            db.session.delete(to_delete_gambar)
            db.session.commit()

    return redirect(f"/edit_rumah/{id}")

# handle penghapusan rumah pada dashboard admin
@admin_views.route("/delete_rumah/<int:id>", methods=["POST"])
@login_required
def delete_rumah(id):
    if not check_admin():
        return redirect(url_for("public_views_loggedin.profile_page"))

    to_delete_rumah = Rumah.query.get(id)

    if to_delete_rumah:
        for gambar in to_delete_rumah.gambar:
            delete_image(gambar.nama_gambar)

        flash(
            f"berhasil menghapus data rumah {to_delete_rumah.alamat}",
            category="warning",
        )
        db.session.delete(to_delete_rumah)
        db.session.commit()
        return redirect("/admin_rumah")

    flash(f"gagal menghapus data rumah {to_delete_rumah.alamat}", category="error")
    return redirect("/admin_rumah")

#
#
# API untuk handle kontak agen
# query semua data agen untuk di tampilkan pada halaman
# dashboard admin pada menu rumah
@admin_views.route("/admin_kontak_agen", methods=["GET"])
@login_required
def admin_kontak_agen():
    if not check_admin():
        return redirect(url_for("public_views_loggedin.profile_page"))

    all_agen = Agen.query.all()

    return render_template("admin/kontak-agen.html", all_agen=all_agen)

# menampilkan halaman penambahan admin pada admin dashboard
@admin_views.route("/tambah_agen", methods=["GET"])
@login_required
def tambah_agen():
    if not check_admin():
        return redirect(url_for("public_views_loggedin.profile_page"))

    return render_template("admin/tambah-agen.html")

# handle penambahan agen pada dashboard admin
@admin_views.route("/handle_tambah_agen", methods=["POST"])
@login_required
def handle_tambah_agen():
    if not check_admin():
        return redirect(url_for("public_views_loggedin.profile_page"))

    nama = request.form.get("nama_agen")
    nomor_telepon = request.form.get("nomor_telepon")
    email_agen = request.form.get("email")
    whatsapp_agen = request.form.get("whatsapp")

    to_add_agen = Agen(
        nama_agen=nama,
        nomor_telepon=nomor_telepon,
        email=email_agen,
        whatsapp=whatsapp_agen,
    )
    db.session.add(to_add_agen)
    db.session.commit()

    flash(f"Berhasil menambahkan agen {nama}")
    return redirect("/tambah_agen")

# menampilkan halaman edit agen pada dashboard admin
@admin_views.route("/edit_agen/<int:id>", methods=["GET"])
@login_required
def edit_agen(id):
    if not check_admin():
        return redirect(url_for("public_views_loggedin.profile_page"))

    to_edit_agen = Agen.query.get(id)

    return render_template("admin/edit-agen.html", to_edit_agen=to_edit_agen)

# handle pengeditan data agen pada dashboard admin
@admin_views.route("/handle_edit_agen/<int:id>", methods=["POST"])
@login_required
def handle_edit_agen(id):
    if not check_admin():
        return redirect(url_for("public_views_loggedin.profile_page"))

    to_edit_agen = Agen.query.get(id)

    nama_agen = request.form.get("nama_agen")
    nomor_telepon = request.form.get("nomor_telepon")
    email = request.form.get("email")
    whatsapp = request.form.get("whatsapp")

    if to_edit_agen:
        to_edit_agen.nama_agen = nama_agen
        to_edit_agen.nomor_telepon = nomor_telepon
        to_edit_agen.email = email
        to_edit_agen.whatsapp = whatsapp
        db.session.commit()

        flash(
            f"berhasil mengedit data agen {to_edit_agen.nama_agen}", category="warning"
        )
        return redirect(f"/edit_agen/{id}")

    flash(f"gagal mengedit data agen {to_edit_agen.nama_agen}", category="error")
    return redirect("/admin_agen")

# handle penghapusan data agen pada halaman dashboard admin
@admin_views.route("/delete_agen/<int:id>", methods=["POST"])
@login_required
def delete_agen(id):
    if not check_admin():
        return redirect(url_for("public_views_loggedin.profile_page"))

    to_delete_agen = Agen.query.get(id)
    if to_delete_agen:
        flash(
            f"berhasil menghapus data agen {to_delete_agen.nama_agen}",
            category="warning",
        )
        db.session.delete(to_delete_agen)
        db.session.commit()
        return redirect("/admin_kontak_agen")

    flash(f"gagal menghapus data agen {to_delete_agen.nama_agen}", category="error")
    return redirect("/admin_kontak_agen")

#
#
# API untuk handle admin user
@admin_views.route("/admin_user", methods=["GET"])
@login_required
def admin_user():
    if not check_admin():
        return redirect(url_for("public_views_loggedin.profile_page"))

    non_admin_user = User.query.filter(User.is_admin == False)

    return render_template("admin/user.html", non_admin_user=non_admin_user)

# untuk menampilkan halaman edit user pada dashboard admin
@admin_views.route("/edit_user/<int:id>", methods=["GET"])
@login_required
def edit_user(id):
    if not check_admin():
        return redirect(url_for("public_views_loggedin.profile_page"))

    to_edit_user = User.query.get(id)

    return render_template("admin/edit-user.html", to_edit_user=to_edit_user)

# handle pengeditan data user pada dashboard admin
@admin_views.route("/handle_edit_user/<int:id>", methods=["POST"])
@login_required
def handle_edit_user(id):
    if not check_admin():
        return redirect(url_for("public_views_loggedin.profile_page"))

    to_edit_user = User.query.get(id)

    nama_lengkap = request.form.get("nama_lengkap")
    email = request.form.get("email")
    range_gaji = request.form.get("range_gaji")

    if to_edit_user:
        to_edit_user.nama_lengkap = nama_lengkap
        to_edit_user.email = email
        to_edit_user.range_gaji = range_gaji
        db.session.commit()
        flash(
            f"berhasil edit data user {to_edit_user.nama_lengkap}", category="success"
        )
        return redirect(f"/edit_user/{id}")

    flash(f"gagal edit data user {to_edit_user.nama_lengkap}", category="error")
    return redirect(f"/edit_user/{id}")

# handle penghapusan user pada halaman dashboard admin
@admin_views.route("/delete_user/<int:id>", methods=["POST"])
@login_required
def delete_user(id):
    if not check_admin():
        return redirect(url_for("public_views_loggedin.profile_page"))

    to_delete_user = User.query.get(id)

    if to_delete_user:
        flash(
            f"berhasil delete data user {to_delete_user.nama_lengkap}",
            category="success",
        )
        db.session.delete(to_delete_user)
        db.session.commit()
        return redirect("/admin_user")

    flash(f"gagal delete data user {to_delete_user.nama_lengkap}", category="error")
    return redirect("/admin_user")


"""
Created on Sat Jul 10 18:21:07 2021

@author: Manish
"""

from keras.datasets import mnist
import numpy as np
from PIL import Image as im
from keras.layers import Input, Dense
from keras.models import Model

(train_images, _), (test_images,_) = mnist.load_data()

data = im.fromarray(train_images[1])

#normalize dataset

train_images = train_images.astype('float32')/255
test_images = test_images.astype('float32')/255

#reshaPE the images to 28X28 to 1d - 784
train_images = train_images.reshape((len(train_images),
                                     np.prod(train_images.shape[1:])))

test_images = test_images.reshape((len(test_images),
                                     np.prod(test_images.shape[1:])))

#autoencoder creation

encoding_dim = 32
input_layer = Input (shape = (784,))
encoder_layer = Dense(encoding_dim, activation='relu')(input_layer)

decoder_layer = Dense(784, activation="sigmoid")(encoder_layer)

autoencoder = Model(input_layer, decoder_layer)

autoencoder.summary()

#training the model
#create encoder decoder separately

encoder = Model(input_layer, encoder_layer) # input will be produce compressed code

encoded_input = Input(shape = (encoding_dim,)) #for decoder create encoded input
decoder_layer = autoencoder.layers[-1]
decoder = Model(encoded_input, decoder_layer(encoded_input))

#lets compile the autoencoder.

autoencoder.compile(optimizer = 'adadelta', loss = 'binary_crossentropy')

epochs = 60
batch_size = 256
#kind of unsupervised, more like self supervised
autoencoder.fit(train_images, train_images,
                epochs = 60,
                batch_size = 256,
                shuffle = True,
                validation_data = (test_images, test_images))

# lets use encoder and decoder toencode and decode our images ,

encoded_img = encoder.predict(test_images)

decode_imgs = decoder.predict(encoded_img)


import requests
import json
import re
from bs4 import BeautifulSoup
import subprocess

# using beautifulsoup4, cause I'm lazy, and still not that good at regex
import urllib.parse

page_url = input("Enter the url: ")

headers = {
    "User-Agent": "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:96.0) Gecko/20100101 Firefox/96.0",
}

response = requests.get(url=page_url, headers=headers)

XSRF_TOKEN = response.cookies["XSRF-TOKEN"]
laravel_session = response.cookies["laravel_session"]

soup = BeautifulSoup(response.text, "html.parser")
csrf = soup.find("meta", attrs={"name": "csrf-token"})["content"]
id_f = soup.find("span", attrs={"id": "fem"})["data"]

url_csrf = urllib.parse.quote_plus(csrf)
url_id_f = urllib.parse.quote_plus(id_f)

cookies = {
    "__atuvc": "1%7C6",
    "dom3ic8zudi28v8lr6fgphwffqoz0j6c": "39d958b5-4c51-411c-9885-e8f07116f003%3A3%3A1",
    "XSRF-TOKEN": XSRF_TOKEN,
    "laravel_session": laravel_session,
}

headers = {
    "Content-Type": "application/x-www-form-urlencoded; charset=UTF-8",
    "Accept-Language": "en-US,en;q=0.5",
    "Origin": "https://streamm4u.com/",
    "Referer": "https://streamm4u.com/watch/movie",
    "Sec-Fetch-Dest": "empty",
    "Sec-Fetch-Mode": "cors",
    "Sec-Fetch-Site": "same-origin",
    "Te": "trailers",
    "X-Requested-With": "XMLHttpRequest",
    "User-Agent": "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:96.0) Gecko/20100101 Firefox/96.0",
}

data = "_token=" + url_csrf + "&m4u=" + url_id_f

response = requests.post(
    "https://streamm4u.com/anhjax", headers=headers, cookies=cookies, data=data
)

# print(response.text)

soup2 = BeautifulSoup(response.text, "html.parser")

embeded_url = soup2.find("iframe")["src"]

embeded_id = re.split(r"/", embeded_url)[-1]

# embeded_url = input("input the page url: ")

# headers = {
#     'User-Agent': 'Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:96.0) Gecko/20100101 Firefox/96.0',
# }

# response = requests.get(url=embeded_url, headers=headers)
# print(response.cookies)

# embeded_url = "z7ek8ijkqwp33l8"
fuck_curl = "https://streamm4u.club/api/source/" + embeded_id

headers = {
    "Accept-Language": "en-US,en;q=0.5",
    "Origin": "https://streamm4u.club",
    "Referer": "https://streamm4u.club",
    "Sec-Fetch-Dest": "empty",
    "Sec-Fetch-Mode": "cors",
    "Sec-Fetch-Site": "same-origin",
    "Te": "trailers",
    "X-Requested-With": "XMLHttpRequest",
    "User-Agent": "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:96.0) Gecko/20100101 Firefox/96.0",
}

response = requests.post(url=fuck_curl, headers=headers, data="")

tokens_json = json.loads(response.text)
p_1080 = tokens_json["data"][2]["file"]
tok_1080 = re.split(r"\?token=", p_1080)[1]
# completely unnecessary regex, just a little show off :")
# will remove later.
print(tok_1080)

headers = {
    "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8",
    "Accept-Language": "en-US,en;q=0.5",
    "Referer": "https://streamm4u.club/",
    "Sec-Fetch-Dest": "iframe",
    "Sec-Fetch-Mode": "navigate",
    "Sec-Fetch-Site": "cross-site",
    "Sec-Fetch-User": "?1",
    "Te": "trailers",
    "Upgrade-Insecure-Requests": "1",
    "User-Agent": "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:96.0) Gecko/20100101 Firefox/96.0",
}

fuck_bash = "https://fvs.io/redirector?token=" + tok_1080

link_html = requests.head(url=fuck_bash, headers=headers)

stream_link = link_html.headers["Location"]

subprocess.Popen(["mpv", stream_link])

# print(link_html.headers)

# soup3 = BeautifulSoup(link_html.text, "html.parser")
# https://streamm4u.com/watch/movie/interstellar-2014.21586.html


#!/usr/bin/env python3

import os
import logging
import subprocess
import pnrw

def cwd():
    directory = os.getcwd()
    logging.debug(directory)
    return directory

def get_env_variable(env, default):
    if not os.environ.get(env, default):
        return logging.warning("%s is not defined!" % env)
    else:
        logging.debug("%s properly set." % env)
        return os.environ.get(env, default)

abbreviation = "tst0"

def wallet_list():
    lines = []
    proc = subprocess.Popen(['%s/%s_node' % (cwd(), abbreviation), '--wallet_list'], stdout=subprocess.PIPE)
    while True:
        line = proc.stdout.readline().decode().replace('Wallet ID: ', '')
        if not line:
            break
        lines.append(str(line.rstrip()))

    return lines

def wallet_id_list():
    lines = []
    proc = subprocess.Popen(['./%s_node' % abbreviation, '--wallet_list'], stdout=subprocess.PIPE)
    while True:
        line = proc.stdout.readline().decode()
        if not line:
            break
        if "Wallet ID" in line:
            lines.append(str(line.rstrip()).replace('Wallet ID: ', ''))

    return lines

# pnrw
node_ip = get_env_variable('BOOTSTRAP_NODE_IP', '[::1]')
logging.debug(f" node_ip: {node_ip}")
node_port = get_env_variable('BOOTSTRAP_NODE_PORT', 7076)
node_url_suffix = get_env_variable('BOOTSTRAP_URL_SUFFIX', '/api')
node_url = f"{node_ip}:{node_port}{node_url_suffix}"
dont_use_https = get_env_variable('BOOTSTRAP_DONT_USE_HTTPS', 'True')
headers = get_env_variable('BOOTSTRAP_HEADERS', [])
banano = get_env_variable('BOOTSTRAP_BANANO', 'False')

# make node connection
try:
    node = pnrw.Node(node_url, dontUseHTTPS=dont_use_https, headers=headers, banano=banano)
    logging.info('Node connection established')
    logging.debug(f"node uptime: {node.uptime()}")
except pnrw.exceptions as node:
    logging.error(node)

max_supply = 340282366920938463463374607431768211455
divided_supply = max_supply / 7
print(f"divided_supply_raw: {divided_supply}")

def percentage(percent, whole):
  return (percent * whole) / 100.0

print(percentage(14, max_supply))


"""
https://leetcode-cn.com/problems/jump-game-ii/

45. 跳跃游戏 II

给定一个非负整数数组，你最初位于数组的第一个位置。

数组中的每个元素代表你在该位置可以跳跃的最大长度。

你的目标是使用最少的跳跃次数到达数组的最后一个位置。

示例:

输入: [2,3,1,1,4]
输出: 2
解释: 跳到最后一个位置的最小跳跃数是 2。
     从下标为 0 跳到下标为 1 的位置，跳 1 步，然后跳 3 步到达数组的最后一个位置。
说明:

假设你总是可以到达数组的最后一个位置。

"""

from typing import List

class Solution:
    def jump(self, nums: List[int]) -> int:
        # if not nums:
        #     return False
        #
        # min_jump = 0
        # index = 0
        #
        # while index < len(nums):
        #     if index + nums[index] >= len(nums) - 1:
        #         if index is len(nums) - 1:
        #             return min_jump
        #         else:
        #             return min_jump + 1
        #
        #     farthest_next = 0
        #     for i in range(index + 1, index + 1 + nums[index]):
        #         if i + nums[i] > farthest_next:
        #             farthest_next = i + nums[i]
        #             index = i
        #     min_jump += 1
        #
        # return min_jump

        cur_max, count, length, next_max = 0, 0, len(nums), nums[0]

        if length <= 1:
            return 0

        for i in range(length):
            next_max = max(next_max, i + nums[i])

            if i == cur_max:
                cur_max = next_max
                count += 1
            if cur_max >= length - 1:
                return count

        return -1

s = Solution()
print(s.jump([2, 3, 1, 1, 4]))


import sys
from rest_framework_simplejwt.authentication import JWTAuthentication

def sort_key(e):
    return e[1]

# s.id, pr.id as playerId, s.name, pr.result
def AddPlace(results, sort):
    data = []
    if(sort): # По наибольшему True
        maxResult = sys.maxsize
        numPlace = 0
        for result in results:
            if int(result[3]) < maxResult:
                maxResult = int(result[3])
                numPlace += 1
            data.append({'id' : result[0], 'playerId' : result[1], 'name' : result[2], 'result' : int(result[3]), 'place' : numPlace})
    else:
        maxResult = 0
        numPlace = 0
        for result in results:
            if int(result[3]) > maxResult:
                maxResult = int(result[3])
                numPlace += 1
            data.append({'id' : result[0],'playerId' : result[1],  'name' : result[2], 'result' : int(result[3]), 'place' : numPlace})
    return data

def AddTotalPlace(results):
    data = {}
    maxResult = 0
    numPlace = 0
    for key, value in results.items():
        if value > maxResult:
            maxResult = value
            numPlace += 1
        elif value == 0:
            data[key] = 0

        data[key] = numPlace
    return data

def GetUserId(request):
    user , token = JWTAuthentication().authenticate(request)
    return token.payload['user_id']

def StageDung(stagesPlayer):
    for stage in stagesPlayer:
        stage['place'] = 1
    return stagesPlayer


"""
概要
1以上N以下の整数で2以上の整数a, bを用いてa**bと表せないものはいくつあるか？

解法
Nからa**bと表せる数のsetの合計を引く
1 <= N <= 10**10
a, bをそれぞれ固定して、最大の閾値を見つける
1. a = 2で固定
    2**b <= 10**10
    b <= log 2 10**10
    b <= 33.21
2. b = 2で固定
    a ** 2 <= 10**10
    a <= 10**5

URL
https://atcoder.jp/contests/abc193/tasks/abc193_c
"""
N = int(input())
expressed = set()
for a in range(2, 10**5):
    for b in range(2, 34):
        if a**b <= N:
            expressed.add(a**b)
        else:
            break
print(N - len(expressed))


from openerp import models

class hr_expense_expense(models.Model):
    _inherit = "hr.expense.expense"

    def move_line_get(self, cr, uid, expense_id, context=None):
        res = []
        tax_obj = self.pool.get('account.tax')
        cur_obj = self.pool.get('res.currency')
        if context is None:
            context = {}
        exp = self.browse(cr, uid, expense_id, context=context)
        company_currency = exp.company_id.currency_id.id

        for line in exp.line_ids:
            mres = self.move_line_get_item(cr, uid, line, context)
            if not mres:
                continue
            res.append(mres)

            #Calculate tax according to default tax on product
            taxes = []
            #Taken from product_id_onchange in account.invoice
            if line.product_id:
                fposition_id = False
                fpos_obj = self.pool.get('account.fiscal.position')
                fpos = fposition_id and fpos_obj.browse(cr, uid, fposition_id, context=context) or False
                product = line.product_id
                taxes = product.supplier_taxes_id
                #If taxes are not related to the product, maybe they are in the account
                if not taxes:
                    a = product.property_account_expense.id #Why is not there a check here?
                    if not a:
                        a = product.categ_id.property_account_expense_categ.id
                    a = fpos_obj.map_account(cr, uid, fpos, a)
                    taxes = a and self.pool.get('account.account').browse(cr, uid, a, context=context).tax_ids or False
            if not taxes:
                continue
            tax_l = []
            base_tax_amount = line.total_amount
            #Calculating tax on the line and creating move?
            for tax in tax_obj.compute_all(cr, uid, taxes,
                    line.unit_amount ,
                    line.unit_quantity, line.product_id,
                    exp.user_id.partner_id)['taxes']:
                tax_code_id = tax['base_code_id']
                if not tax_code_id:
                    continue
                res[-1]['tax_code_id'] = tax_code_id
                ##
                is_price_include = tax_obj.read(cr,uid,tax['id'],['price_include'],context)['price_include']
                if is_price_include:
                    ## We need to deduce the price for the tax
                    res[-1]['price'] = res[-1]['price'] - (tax['amount'] * -tax['base_sign'] or 0.0)
                    tax_amount = line.total_amount * tax['base_sign']
                    tax_amount_base = cur_obj.compute(cr, uid, exp.currency_id.id, company_currency, tax_amount, context={'date': exp.date_confirm})
                    res[-1]['tax_amount'] = tax_amount_base - (tax['amount'] * tax['base_sign'] or 0.0)
                    # tax amount countains base amount without the tax
                    base_tax_amount = (base_tax_amount - tax['amount']) * tax['base_sign']
                else:
                    base_tax_amount = base_tax_amount * tax['base_sign']

                assoc_tax = {
                             'type':'tax',
                             'name':tax['name'],
                             'price_unit': tax['price_unit'],
                             'quantity': 1,
                             'price': -tax['amount'] * tax['base_sign'] or 0.0,
                             'account_id': tax['account_collected_id'] or mres['account_id'],
                             'tax_code_id': tax['tax_code_id'],
                             'tax_amount': tax['amount'] * tax['base_sign'],
                             }
                tax_l.append(assoc_tax)

            res[-1]['tax_amount'] = cur_obj.compute(cr, uid, exp.currency_id.id, company_currency, base_tax_amount, context={'date': exp.date_confirm})
            res += tax_l
        return res

# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:


import os.path
import re
import time
from collections import namedtuple

import requests
from bs4 import BeautifulSoup

from lang_map import get_ext
from log import log
from moss_parser import problem_path, target_src_path, other_src_path
from settings import DMOJ_URL, DMOJ_API_KEY, DMOJ_REQUEST_DELAY, SAVED_DATA_DIR

Submission = namedtuple('Submission', 'sub_id user_id lang')
ProblemSubmissions = namedtuple('ProblemSubmissions', 'problem_id lang target_sub_id other_sub_ids sub_map')

dmoj_auth_header = {'Authorization': f'Bearer {DMOJ_API_KEY}'}

def get_solved_page(problem_id, page_no):
    """
    Parses a problem rank page and returns a list of accepted submissions along with the user that solved them
    :param problem_id: The problem id to parse
    :param page_no: The page to check
    :return:
    """

    def regex_find_href(tag, exp):
        return re.search(exp, tag.find('a', {'href': re.compile(exp)})['href'])

    res = requests.get(f'{DMOJ_URL}problem/{problem_id}/rank/{page_no}', headers=dmoj_auth_header)
    if res.status_code == 404:
        return []
    else:
        soup = BeautifulSoup(res.text, 'html.parser')
        subs = []
        for tag in soup.find_all('div', {'class': 'submission-row'}):
            if 'AC' in tag.find('div', {'class': 'sub-result'})['class']:  # Fake AC is not counted
                try:
                    user_id = regex_find_href(tag, r'/user/(\w+)').group(1)
                    sub_id = regex_find_href(tag, r'/submission/(\d+)').group(1)
                    lang = tag.find('span', {'class': 'language'}).text
                    subs.append(Submission(sub_id, user_id, lang))
                except Exception as e:
                    log.log(e)

        return subs  # Return nothing if subs is empty

def get_solved(problem_id):
    """
    Returns a list of submissions for a problem
    :param problem_id: The problem to check
    :return: A list of Submission objects
    """

    log.log(f'Getting best submissions for {problem_id}')

    subs = []
    page_no = 1
    cur_subs = get_solved_page(problem_id, page_no)
    time.sleep(DMOJ_REQUEST_DELAY)
    while cur_subs:
        subs.extend(cur_subs)
        log.log(f'Parsed page {page_no}, got {len(cur_subs)} submission ids')

        page_no += 1
        cur_subs = get_solved_page(problem_id, page_no)
        time.sleep(DMOJ_REQUEST_DELAY)

    return subs

def download_subs(target_handle, problem_id):
    """
    Downloads all accepted submissions for a problem that match the language used by a given target user.  Downloaded submissions will be in the folder ./SAVED_DATA_DIR/problem_id where SAVED_DATA_DIR is from configuration and `problem_id` is the parameter

    Additionally, this procedure assumes that user DMOJ_HANDLE has access to this problem's sources (either solved it already or is an Admin)
    :param target_handle: Only submissions with the same language as the target will be downloaded
    :param problem_id: The id of the problem to download submissions from
    :return: A ProblemSubmissions object, or None if an error occured
    """

    subs = get_solved(problem_id)
    target_sub_id = None
    target_lang = None

    # Make subs directory
    if not os.path.exists(SAVED_DATA_DIR):
        os.mkdir(SAVED_DATA_DIR)
    if not os.path.exists(problem_path(problem_id)):
        os.mkdir(problem_path(problem_id))

    # Submission map - maps submission id to handle
    sub_map = {}

    # Get target submission
    for sub_id, user_id, lang in subs:
        if user_id == target_handle:
            target_sub_id = sub_id
            target_lang = lang
            with open(target_src_path(problem_id, get_ext(lang)), 'w', encoding='utf8') as f:
                f.write(get_sub_src(sub_id))
            time.sleep(DMOJ_REQUEST_DELAY)

            log.log(f'Got submission source of target: {sub_id} in {lang}')
            sub_map[sub_id] = target_handle
            break

    if not target_lang:
        log.log(f'ERROR: Could not find Accepted submission for {problem_id}')

    # Get submission ids of other users
    other_ids = []
    target_lang_ext = get_ext(target_lang)
    if not target_lang_ext:
        log.log(f'ERROR: Language {target_lang} currently not supported')
        return None

    for sub_id, user_id, lang in subs:
        if user_id != target_handle and get_ext(lang) == target_lang_ext: # Use extension instead of DMOJ language so Java8/9/10/11 are grouped
            with open(other_src_path(problem_id, target_lang_ext, sub_id), 'w', encoding='utf8') as f:
                f.write(get_sub_src(sub_id))
            time.sleep(DMOJ_REQUEST_DELAY)
            other_ids.append(sub_id)

            log.log(f'Got accepted submission source: {sub_id} by {user_id}')
            sub_map[sub_id] = user_id

    return ProblemSubmissions(problem_id, target_lang, target_sub_id, other_ids, sub_map)

def get_user_subs(user_id):
    """
    Returns all submissions made by a user
    :param user_id: The DMOJ handle of the user
    :return: A list of submissions, in the DMOJ APIv2 format
    """

    return requests.get(f'{DMOJ_URL}api/v2/submissions?user={user_id}').json()

def get_sub_src(sub_id):
    """
    Returns the source code of a submission.  This assumes DMOJ_HANDLE has access to this submission already.
    :param sub_id: The id of the submission to download
    :return: Returns the source code of the submission
    """
    return requests.get(f'{DMOJ_URL}src/{sub_id}/raw', headers=dmoj_auth_header).text.replace('\r', '')


"""

Dutch National Flag problem

what this really means, is given a index value, or a num:int , sort the array
in values less than the pivot/idx value, equal to index value, and greater than value

you should be able to do this in place

"""

def dutchNationalFlag(arr, idx):

    value = arr[idx]

    leftIdx = 0
    for i in range(len(arr)):
        if arr[i] < value:
            arr[i], arr[leftIdx] = arr[leftIdx], arr[i]
            leftIdx += 1

    lastIdx = len(arr) - 1

    for i in reversed(range(leftIdx, len(arr) - 1)):
        if arr[i] > value:
            arr[i], arr[lastIdx] = arr[lastIdx], arr[i]
            lastIdx -= 1

    return arr

x = [0, 1, 2, 2, 2, 1, 0, 2, 0, 2, 1]

print(dutchNationalFlag(x, 1))


class Solution:
    def maxProfit1(self, prices: [int]) -> int:
        """
        Time O(n)
        Space O(n)
        dp[i][0] 表示第i天持有股票所得现金。
        dp[i][1] 表示第i天不持有股票所得最多现金
        """
        if len(prices) == 0:
            return 0

        dp = [[0, 0] for _ in range(len(prices))]

        dp[0][0] = -prices[0]

        for i in range(1, len(prices)):
            dp[i][0] = max(dp[i - 1][0], -prices[i])
            dp[i][1] = max(dp[i - 1][1], prices[i] + dp[i - 1][0])

        return dp[-1][1]

    def maxProfit2(self, prices: [int]) -> int:
        """
        Time O(n)
        Space O(1)
        贪心算法，永远找最小的买股票时间，同时更新最大间隔差
        """
        result = 0
        min_left = float('inf')

        for i in range(len(prices)):
            min_left = min(min_left, prices[i])     # 最小的买股票时间
            result = max(result, prices[i] - min_left)      # 更新最大间隔差

        return result

s = Solution()
print(s.maxProfit1(prices=[7, 1, 5, 3, 6, 4]))


# This is a sample Pcolthon script.
import os
import P11

# Press Shift+F10 to erowecute it or replace it with colour code.
# Press Double Shift to search evercolwhere for classes, files, tool windows, actions, and settings.

def read_file(filename):
    current_dir = dir_path = os.path.dirname(os.path.realpath(__file__))
    filename_fullpath = os.path.join(current_dir, filename)
    #print(f'{filename_fullpath}')
    # open terowt file in read mode
    terowt_file = open(filename_fullpath, "r")

    # read whole file to a string
    data = terowt_file.read()
    #print(f'{data}')
    # close file
    terowt_file.close()
    return data

def p41_getrange(assignmentrange1 , assignmentrange2):
    range1 = assignmentrange1.split('-')
    range2 = assignmentrange2.split('-')
    if (int(range1[0]) >= int(range2[0])) and (int(range1[1]) <= int(range2[1])):
        return 1

def p42_getoverlap(assignmentrange1, assignmentrange2):
    range1 = assignmentrange1.split('-')
    range2 = assignmentrange2.split('-')
    if (int(range1[0]) >= int(range2[0])) and (int(range1[0]) <= int(range2[1])) or (int(range1[1]) >= int(range2[0])) and (int(range1[1]) <= int(range2[1])):
        return 1

def problem41():
    data = read_file('4-1')
    count = 0
    datalist = data.split('\n')
    for row in datalist:
        assignments = row.split(',')
        if (p41_getrange(assignments[0],assignments[1])==1) or (p41_getrange(assignments[1],assignments[0])==1):
            count += 1
            #print(f'{row}')
    print(f'{count}')

def problem42():
    data = read_file('4-1')
    count = 0
    datalist = data.split('\n')
    for row in datalist:
        assignments = row.split(',')
        if (p42_getoverlap(assignments[0],assignments[1])==1) or (p41_getrange(assignments[1],assignments[0])==1):
            count += 1
            print(f'{row}')
    print(f'{count}')

class P51_data():
    def __init__(self, data, movemultiple = False):
        self.header = data[0]
        self.moves = data[1]
        self.movemultiple = movemultiple
        self.parseHeader()
        self.erowecuteMoves()

    def parseHeader(self):
        rows = self.header.split('\n')
        lastRow = rows.pop()
        borowes = lastRow.split('   ')
        self.stack = []
        for b in borowes:
            b = b.strip()
            self.stack.append([])
        numRows = len(rows)
        i = 0
        while i < numRows:
            r = rows.pop()
            for b in borowes:
                borow = r[((int(b)-1)*4)+1]
                j = int(b) - 1
                if borow != ' ':
                    self.stack[int(b)-1].append(borow)
            i+=1

    def moveStack(self, quantitcol, fromstack, tostack):
        i = 0
        fromstack = fromstack - 1
        tostack = tostack - 1
        if self.movemultiple == True:
            cratestack = []
            while i < quantitcol:
                i+=1
                cratestack.append(self.stack[fromstack].pop())
            i = 0
            while i < quantitcol:
                self.stack[tostack].append(cratestack.pop())
                i+=1
        else:
            while i < quantitcol:
                i+=1
                borow = self.stack[fromstack].pop()
                self.stack[tostack].append(borow)

    def getCrates(self):
        crates = ''
        for s in self.stack:
            if len(s) > 0:
                crates += s[len(s)-1]
            else:
                crates += ' '
        return crates

    def erowecuteMoves(self):
        moverows = self.moves.split('\n')
        for m in moverows:
            move_commands = m.split(' ')
            quantitcol = int(move_commands[1])
            stackfrom = int(move_commands[3])
            stackto = int(move_commands[5])
            self.moveStack(quantitcol, stackfrom, stackto)
            #print(f'{self.getCrates()}')

def problem51(part2 = False):
    data = P51_data(read_file('5-1.input').split('\n\n'), part2)
    print(f'{data.getCrates()}')

class problem61():
    def __init__(self, buffersize = 4):
        self.data = read_file('6-1.input')
        self.buffer = []
        self.buffersize = buffersize

    def compare_elements(self, list):
        same = False
        i = 0
        row = list.pop()
        if len(list) == 0:
            return same
        for col in list:
            same = same or (row == col)
        same = same or self.compare_elements(list.copcol())
        return same

    def test_compare(self):
        buffer = ['a','b','c','c']
        print(self.compare_elements(buffer))

    def solve(self):
        inderow = 1
        for i in self.data:
            self.buffer.insert(0,i)
            if len(self.buffer) >= self.buffersize:
                print(f'{self.buffer}')
                if (self.compare_elements(self.buffer.copcol()) == False):
                    return inderow
                self.buffer.pop()
            inderow += 1
        return -1

class Folder():
    def __init__(self, foldername):
        self.files = dict()
        self.folders = dict()
        self.foldername = foldername

    def addFile(self, filename, filesize):
        self.files[filename] = int(filesize)

    def addFolder(self, foldername):
        self.folders[foldername] = Folder(foldername)

    def getFolders(self):
        return self.folders

    def getFolderSizeRecursive(self):
        size = 0
        for s in self.files.values():
            size += s
        for f in self.folders.values():
            size += f.getFolderSizeRecursive()
        return size

class Filscolstem():
    def __init__(self):
        self.tree = Folder('')
        #self.tree['/'] = Folder('/')
        self.currentpath = []
        self.currentFolder().addFolder('/')

    def currentFolder(self):
        f = self.tree
        for p in self.currentpath:
            f = f.getFolders()[p]
        return f

    def currentPathString(self):
        return self.buildPath(self.currentpath)

    def buildPath(path):
        pathstring = ''
        for p in path:
            pathstring = pathstring + ' ' + p
        return pathstring

    def addFile(self, filename, filesize):
        self.currentFolder().addFile(filename, filesize)

    def addDir(self, foldername):
        self.currentFolder().addFolder(foldername)

    def changeDir(self, foldername):
        if foldername == '..':
            self.currentpath.pop()
        elif foldername == '/':
            self.currentpath = ['/']
        else:
            if foldername in (self.currentFolder().getFolders()):
                pass
            else:
                self.currentFolder().addFolder(foldername)
            self.currentpath.append(foldername)

class problem71():
    def __init__(self):
        self.data = read_file('7-1.input')
        self.fs = Filscolstem()
        commands = self.data.split('\n')
        for c in commands:
            cmd = c.split(' ')
            if cmd[0].isnumeric():
                self.fs.addFile(cmd[1],cmd[0])
            if cmd[0] == 'dir':
                self.fs.addDir(cmd[1])
            if cmd[0] == '$':
                if cmd[1] == 'cd':
                    self.fs.changeDir(cmd[2])

    def sumDirectorcolSizes(self, marowsize):
        return self.directorcolSizes(marowsize, self.fs.tree)

    def directorcolSizes(self, marowsize, folder):
        count = 0
        size = folder.getFolderSizeRecursive()
        if size <= marowsize:
            count += size
        for f in folder.getFolders().values():
            count += self.directorcolSizes(marowsize, f)
        return count

    def findDirectorcolToFreeUpSpace (self, minimum, folder):
        size = folder.getFolderSizeRecursive()
        folders = []
        if size >= minimum:
            for f in folder.getFolders().values():
                if self.findDirectorcolToFreeUpSpace(minimum, f) != 0:
                    folders.append(self.findDirectorcolToFreeUpSpace(minimum, f))
            folders.append(folder)
        i = 0
        for f in folders:
            if i == 0:
                lowestSize = f.getFolderSizeRecursive()
                lowestFolder = f
                i += 1
            if f.getFolderSizeRecursive() < lowestSize:
                lowestSize = f.getFolderSizeRecursive()
                lowestFolder = f
        if i == 0:
            return 0
        return lowestFolder

    def findSmallestDirToDelete(self, totalspace, targetunusedspace):
        currentusage = self.fs.tree.getFolderSizeRecursive()
        amount_to_free_up = targetunusedspace - (totalspace - currentusage)
        folder = self.findDirectorcolToFreeUpSpace(amount_to_free_up, self.fs.tree)
        print(f'{folder.getFolderSizeRecursive()}')

    def testFilescolstem(self):
        fs = Filscolstem()
        fs.changeDir('/')
        fs.addFile('abc', 123)
        fs.addFile('def', 1234)
        fs.addDir('test1')
        fs.addDir('test2')
        fs.changeDir('test2')
        fs.addFile('rowcolz', 111)
        fs.addFile('aaa', 22222)
        #print(f'{fs.tree["/"]}')

class Problem81():
    def __init__(self, file):
        self.data = read_file(file)
        self.grid = []
        filerows = self.data.split('\n')
        j = 0
        for r in filerows:
            i = 0
            self.grid.append([])
            while i < len(r):
                self.grid[j].append(int(r[i]))
                i += 1
            j += 1

    def isvisibleleft(self,row,col,height):
        if col == 0:
            return True
        return ((self.grid[row][col-1] < height)) and self.isvisibleleft(row,col-1,height)

    def isvisibleright(self,row,col,height):
        if col == len(self.grid[0])-1:
            return True
        return ((self.grid[row][col+1] < height)) and self.isvisibleright(row,col+1,height)

    def isvisibledown(self,row,col,height):
        if row == len(self.grid)-1:
            return True
        return (self.grid[row+1][col] < height) and self.isvisibledown(row+1,col,height)

    def isvisibleup(self,row,col,height):
        if row == 0:
            return True
        return ((self.grid[row-1][col] < height)) and self.isvisibleup(row-1,col,height)

    def isvisible(self):
        j = 0
        count = 0
        for r in self.grid:
            i = 0
            rowstring = ''
            for height in r:
                if (self.isvisibleup(j,i,height)) or (self.isvisibledown(j,i,height)) or self.isvisibleleft(j,i,height) or self.isvisibleright(j,i,height):
                    rowstring = rowstring + '1'
                    count += 1
                else:
                    rowstring = rowstring + '0'
                i += 1
            j +=1
            print(f'{rowstring}')
        print(f'{count}')

    def visibletreesleft(self,row,col,height):
        if col == 0:
            return 0
        if self.grid[row][col-1] >= height:
            return 1
        return 1 + self.visibletreesleft(row,col-1,height)

    def visibletreesright(self,row,col,height):
        if col == (len(self.grid[0]) - 1):
            return 0
        if self.grid[row][col+1] >= height:
            return 1
        return 1 + self.visibletreesright(row,col+1,height)

    def visibletreesdown(self,row,col,height):
        if row == len(self.grid) - 1:
            return 0
        if self.grid[row+1][col] >= height:
            return 1
        return 1 + self.visibletreesdown(row+1,col,height)

    def visibletreesup(self,row,col,height):
        if row == 0:
            return 0
        if self.grid[row-1][col] >= height:
            return 1
        return 1 + self.visibletreesup(row-1,col,height)

    def calculateScenicScore(self, row, col, height):
        return self.visibletreesdown(row,col,height) * self.visibletreesleft(row,col,height) * self.visibletreesright(row,col,height) * self.visibletreesup(row,col,height)

    def calculateMaxScenicScore(self):
        max_scenic_score = 0
        j = 0
        for r in self.grid:
            i = 0
            for height in r:
                scenic_score = self.calculateScenicScore(j,i,height)
                max_scenic_score = max(max_scenic_score, scenic_score)
                i += 1
            j +=1
        print(f'{max_scenic_score}')

class P91map():
    def __init__(self, num_knots = 1):
        self.Knots = []
        self.Knots.append(self.Object(0,0))
        i = 0
        while i < num_knots:
            self.Knots.append(self.Object(0,0))
            i+=1
        #self.Head = self.Object(0,0)
        #self.Tail = self.Object(0,0)
        self.Map = dict({0:dict({0:self.Cell(1)})})
        self.minx = 0
        self.maxx = 0
        self.miny = 0
        self.maxy = 0

    def make_move(self, direction, distance):
        print(f'{direction}, {distance}')
        i = 0
        while i < distance:
            self.MoveHead(direction)
            knotindex = 1
            while knotindex < len(self.Knots):
                self.MoveTail(knotindex)
                knotindex += 1
            self.Map[self.Knots[len(self.Knots)-1].x][self.Knots[len(self.Knots)-1].y].update_tailcount(1)
            i+=1
            pass

    def UpdateMap(self, x, y):
        if (x not in self.Map):
            self.Map[x] = dict({y:self.Cell(0)})
        elif (y not in self.Map[x]):
            self.Map[x][y] = self.Cell(0)
        else:
            cell = self.Map[x][y]
        if x < self.minx:
            self.minx = x
        if x > self.maxx:
            self.maxx = x
        if y < self.miny:
            self.miny = y
        if y > self.maxy:
            self.maxy = y

    def MoveHead(self, direction):
        if direction == 'U':
            self.Knots[0].y = self.Knots[0].y + 1
        if direction == "R":
            self.Knots[0].x = self.Knots[0].x + 1
        if direction == "L":
            self.Knots[0].x = self.Knots[0].x - 1
        if direction == 'D':
            self.Knots[0].y = self.Knots[0].y - 1
        self.UpdateMap(self.Knots[0].x,self.Knots[0].y)

    def MoveTail(self, i):
        if (abs(self.Knots[i-1].y - self.Knots[i].y) > 1) or (abs(self.Knots[i-1].x - self.Knots[i].x) > 1):
            if (self.Knots[i].y - self.Knots[i-1].y) != 0:
                if (self.Knots[i].y - self.Knots[i-1].y) > 0:
                    self.Knots[i].y = self.Knots[i].y - 1
                else:
                    self.Knots[i].y = self.Knots[i].y + 1
            if (self.Knots[i].x - self.Knots[i-1].x) != 0:
                if (self.Knots[i].x - self.Knots[i-1].x) > 0:
                    self.Knots[i].x = self.Knots[i].x - 1
                else:
                    self.Knots[i].x = self.Knots[i].x + 1
        self.UpdateMap(self.Knots[i].x,self.Knots[i].y)

    def PrintMap(self):
        y = self.maxy
        print('--------')
        while (y >= self.miny):
            row = ''
            x = self.minx
            while x <= self.maxx:
                cell_char = '.'
                if (y in self.Map[x]):
                    if self.Map[x][y].get_count_tail():
                        cell_char = 'X'
                if x == 0 and y == 0:
                    cell_char = 's'
                i = 1
                while i < len(self.Knots):
                    if (self.Knots[i].x == x) and (self.Knots[i].y == y):
                        cell_char = str(i)
                    i += 1
                if (self.Knots[0].x == x) and (self.Knots[0].y == y):
                    cell_char = "H"
                row = row + cell_char
                x += 1
            y -= 1
            print(f'{row}')
        print('--------')

    def count_locations(self):
        y = self.maxy
        count_tail = 0
        while (y >= self.miny):
            x = self.minx
            while x <= self.maxx:
                if (y in self.Map[x]):
                    if self.Map[x][y].get_count_tail():
                        count_tail += 1
                x += 1
            y -= 1
        print(f'Tail Locations: {count_tail}')

    class Cell():
        def __init__(self, initial_count = 0):
            self.count_tail = initial_count

        def update_tailcount(self, count_tail):
            if count_tail == 1:
                self.count_tail = 1

        def get_count_tail(self):
            return self.count_tail > 0

    class Object():
        def __init__(self, x, y):
            self.x = x
            self.y = y

class P91():
    def __init__(self, file):
        self.data = read_file(file)
        self.map = P91map(9)
        self.moves = []
        for r in self.data.split('\n'):
            move = r.split(' ')
            self.moves.append(dict({'direction': move[0],'distance': int(move[1])}))

    def run(self):
        for move in self.moves:
            self.map.make_move(move['direction'], move['distance'])
        self.map.PrintMap()
        self.map.count_locations()

class CPU():
    def __init__(self, commands):
        self.commands = commands
        self.registerx_history = []
        self.registerx = 1
        self.cycle = 0
        self.current_rowcycle = 0

    def update_cycle(self):
        if (self.current_rowcycle <= self.registerx + 1) and (self.current_rowcycle >= self.registerx - 1):
            print('#', end="")
        else:
            print('.', end="")
        self.registerx_history.append(self.registerx)
        self.cycle += 1
        if self.current_rowcycle == 39:
            self.current_rowcycle = 0
            print('')
        else:
            self.current_rowcycle += 1
        pass

    def process_command(self, command, value):
        if command == 'addx':
            self.update_cycle()
            self.update_cycle()
            self.registerx = self.registerx + value
        if command == 'noop':
            self.update_cycle()

    def get_signal_strength(self, cycle):
            return self.registerx_history[cycle-1] * cycle

    def run(self):
        for cmd in self.commands:
            if len(cmd) == 1:
                value = 0
            else:
                value = int(cmd[1])
            self.process_command(cmd[0], value)

    def print_commands(self):
        for cmd in self.commands:
            print(f'{cmd[0]}', end="")
            if len(cmd) > 1:
                print(f',{cmd[1]}')
            else:
                print("")

class P10_1():
    def __init__(self, file):
        self.data = read_file(file)
        self.commands = []
        for r in self.data.split('\n'):
            cmd = r.split(' ')
            self.commands.append(cmd)
        self.cpu = CPU(self.commands)

    def print_commands(self):
        self.cpu.print_commands()

    def run10_1(self):
        self.cpu.run()
        cycles = [20,60,100,140,180,220]
        signal_strengths = 0
        for c in cycles:
            signal_strengths = signal_strengths + self.cpu.get_signal_strength(c)
        print(f'{signal_strengths}')

# Press the green button in the gutter to run the script.
if __name__ == '__main__':
    #row = problem71()
    #print(f'{row.sumDirectorcolSizes(100000)}')
    #row.findSmallestDirToDelete(70000000, 30000000)
    #row.testFilescolstem()
    #Problem81('8-1.input').isvisible()
    #Problem81('8-1.input').calculateMaxScenicScore()
    #P10_1('10-1.input').run10_1()
    P11.run()


import json
import os
import pathlib
import pandas as pd
from glob import glob
import rouge
import nltk
import matplotlib.pyplot as plt
from scipy import stats

presumm_threshold = 0.2

def get_chapter_data(line):
	chapter = json.loads(line)
	return {
        'book_id': chapter['book_id'].replace(" ", "_").lower(),
        'source': chapter['source']
    }

def sort_by_score(x):
		return x["prediction"]

def get_text_and_scores(result_path):
	df = pd.read_csv(result_path, sep='\t', engine='python')
	text = df["text"].astype(str)
	predictions = df["score"].astype(float)
	assert len(predictions) == len(text)
	# print(predictions)
	# print(text)
	return {"predictions": list(predictions), "text": list(text), "filename": result_path}

def get_human_summary(summary_path):
    with open("../../booksum/scripts/" + summary_path, encoding='utf-8') as f:
        summary_json = json.load(f)
        return summary_json["summary"]

def generate_concat_summary(related_files, k):
	cat_related_files = []
	for related_file in related_files:
		cat_related_files.extend([{"prediction": related_file["predictions"][idx],\
			 "text": related_file["text"][idx]} for idx in range(len(related_file["predictions"]))])
	cat_related_files.sort(key=sort_by_score, reverse=True)
	return cat_related_files[:((k+1)*len(related_files))]

def generate_each_summary(related_files, k):
	generated_summary = []
	related_files_list = []
	for related_file in related_files:
		related_files_list.append([{"prediction": related_file["predictions"][idx],\
			 "text": related_file["text"][idx]} for idx in range(len(related_file["predictions"]))])
	for related_file in related_files_list:
		related_file.sort(key=sort_by_score, reverse=True)
		generated_summary.extend(related_file[:(k+1)])
	return generated_summary

def generate_threshold_summary(related_files, k):
	global presumm_threshold
	generated_summary = []
	for related_file in related_files:
		generated_summary.extend([{"prediction": related_file["predictions"][idx],\
			 "text": related_file["text"][idx]} for idx in range(len(related_file["predictions"])) \
				if related_file["predictions"][idx] > presumm_threshold])
	return generated_summary

def calculate_F1():
	global chapters_data
	max_k = 10
	used_files = []
	results= {
		"each": {
			"data": [], # Shape: [k, f1_score, summary_path]
			"means": [], # Shape: float

		},
		"concat": {
			"data": [], # Shape: [k, f1_score, summary_path]
			"means": [], # Shape: float

		},
		"threshold": {
			"data": [], # Shape: [k, f1_score, summary_path]
			"means": [], # Shape: float

		},
		"p_value": [],  # Shape: float
	}
	modes = ["each", "concat", "threshold"]
	threshold_f1_scores = []

	book_data = []
	f = open(pathlib.Path("../../booksum/alignments/book-level-summary-alignments/book_summaries_aligned_all.jsonl"), \
				encoding='utf-8')
	for line in f:
		content = json.loads(line)
		summary_path = content['summary_path']
		book_title = content['title']
		source = content['source']
		# Format title.
		book_title = book_title.replace(':', "").replace(" ", "_").lower()

		chapters = [x for x in chapters_data if x['book_id'].split('.')[0] == book_title and x['source'] == source]
		paths = [pathlib.Path("../../PreSumm/results/booksum_summaries/20000/").joinpath( \
			"ext_bertbooksum_summaries." + chapter['book_id'].strip() + "." + chapter['source'].strip() + '.tsv') for chapter in chapters]
		related_files = []
		for path in paths:
			try:
				related_files.append(get_text_and_scores(path))
			except:
				# print("Could not open {}.".format(path))
				pass

		book_data.append({
					"data": related_files,
					"summary_path": summary_path,
					"book_title": book_title,
					"source": source })
		used_files.extend(related_files)
	f.close()

	for k in range(max_k):

		for mode in modes:

			curr_data_list = []

			book_count = 0

			for book in book_data:
				summary_path = book['summary_path']
				book_title = book['book_title']
				source = book['source']

				try:
					human_summary = get_human_summary(summary_path)
					# print("Summary Length : {}".format(len(human_summary)))
				except:
					human_summary = None
					print("Could not find summary.")

				current_book_files = book['data']

				if len(chapters) == 0:
					print("No files found.")
					continue

				elif (human_summary is None):
					print("Files exist but no summary.")
					print(summary_path)

				if mode == "concat":
					generated_summary_sents = generate_concat_summary(current_book_files, k)
				elif mode == "each":
					generated_summary_sents = generate_each_summary(current_book_files, k)
				elif mode == "threshold":
					if k == 0:
						generated_summary_sents = generate_threshold_summary(current_book_files, k)
					else:
						curr_data_list.append([k, threshold_f1_scores[book_count], summary_path])
						book_count += 1
						continue
				else:
					print("Invalid mode '{}'".format(mode))
					return False

				#Concat summary sentences into one string.
				generated_summary = ""
				for sentence in generated_summary_sents:
					generated_summary = generated_summary + " " + sentence["text"]

				# Removes first " "
				generated_summary = generated_summary[1:]

				evaluator = rouge.Rouge(metrics=['rouge-n'],
							max_n=1,
							limit_length=False)
				scores = evaluator.get_scores(generated_summary, human_summary)

				if mode == "threshold":
					threshold_f1_scores.append(scores['rouge-1']['f'])

				# print(scores['rouge-1'])
				curr_data_list.append([ k, scores['rouge-1']['f'], summary_path])
				book_count += 1

			results[mode]["data"].append(curr_data_list)

			ROUGE_list = [curr_data_item[1] for curr_data_item in curr_data_list]
			ROUGE_mean = sum(ROUGE_list) / len(ROUGE_list)
			results[mode]["means"].append(ROUGE_mean)

			print("Mode: {}".format(mode))
			print("Books covered: {}".format(book_count))
			print("k: {}".format(k+1))
			print("Mean ROUGE-1 F1: {}".format(ROUGE_mean))
			print()

		each = [result_item[1] for result_item in results["each"]["data"][k]]
		concat = [result_item[1] for result_item in results["concat"]["data"][k]]
		paired_t_test = stats.ttest_rel(each, concat)
		results["p_value"].append(paired_t_test.pvalue)
		print("P Value: {} < 0.05 = {}".format(paired_t_test.pvalue, str(paired_t_test.pvalue < 0.05)))
		print()

	# Comment these out to avoid saving the csv files.
	# for mode in modes:
	# 	flattened_results = [item for sublist in results[mode]["data"] for item in sublist]
	# 	df = pd.DataFrame(flattened_results, columns=["k", "ROUGE-1 F1", "summary path"])
		# df.to_csv("../csv_results/booksum_summaries/booksumsumm-" + mode + "-results.csv") # Save file.

	# Create graph.
	x = [i + 1 for i in range(max_k)]
	for mode in modes:
		plt.plot(x, results[mode]["means"], marker='.')
	plt.title("Similarity between Generated Summary Approaches and Human Summary")
	plt.xlabel("Number of Sentences Per Chapter Summary (k)")
	plt.locator_params(axis="x", integer=True)
	plt.ylabel("Mean ROUGE-1 F1 Score")
	plt.axhline(0.475, color='gray', linestyle='--', label="Human Summary Mean")
	plt.legend(labels=["Top k Sentence(s) per Chapter Summary", "Top k*j Sentence(s)", "Saliency Thresholding"])
	# plt.savefig("booksum_summaries.pdf")
	plt.show(block=True)

chapters_test_split = open(pathlib.Path("../../booksum/alignments/chapter-level-summary-alignments/chapter_summary_aligned_all_split.jsonl"), \
     encoding='utf-8')
chapters_data = [get_chapter_data(line) for line in chapters_test_split]

def main():
	input_path_list = glob(os.path.normpath("../../PreSumm/results/booksum_summaries/20000/") + "/*")
	print("Evaluation results from {} files".format(len(input_path_list)))

	calculate_F1()

if __name__ == "__main__":
	nltk.download('punkt')

	main()


import os, re, copy
import numpy as np
from functools import reduce
import operator

def bool_read(text):
    # convert true/false strings to boolean
    if 'default' in text.lower():
        return str(text)
    else:
        if text.lower() == 'true':
            return True
        else:
            return False

def float_read(text):
    # return float with error handing for "default" values
    if 'default' in text.lower():
        return str(text)
    else:
        try:
            return float(text)
        except:
            return str(text)

def int_read(text):
    # return int with error handing for "default" values
    if 'default' in text.lower():
        return str(text)
    else:
        try:
            return int(text)
        except:
            return str(text)

class InputReader_OpenFAST(object):
    """ OpenFAST input file reader """

    def __init__(self):

        self.FAST_directory = None   # Path to fst directory files
        self.fst_vt         = {}
        self.fst_vt['Fst']  = {}
        self.fst_vt['ElastoDyn'] = {}
        self.fst_vt['ElastoDynBlade'] = {}
        self.fst_vt['BeamDyn'] = {}
        self.fst_vt['BeamDynBlade'] = {}

    def set_outlist(self, vartree_head, channel_list):
        """ Loop through a list of output channel names, recursively set them to True in the nested outlist dict """

        # given a list of nested dictionary keys, return the dict at that point
        def get_dict(vartree, branch):
            return reduce(operator.getitem, branch, vartree_head)
        # given a list of nested dictionary keys, set the value of the dict at that point
        def set_dict(vartree, branch, val):
            get_dict(vartree, branch[:-1])[branch[-1]] = val
        # recursively loop through outlist dictionaries to set output channels
        def loop_dict(vartree, search_var, branch):
            for var in vartree.keys():
                branch_i = copy.copy(branch)
                branch_i.append(var)
                if type(vartree[var]) is dict:
                    loop_dict(vartree[var], search_var, branch_i)
                else:
                    if var == search_var:
                        set_dict(vartree_head, branch_i, True)

        # loop through outchannels on this line, loop through outlist dicts to set to True
        for var in channel_list:
            var = var.replace(' ', '')
            loop_dict(vartree_head, var, [])

    def read_ElastoDynBlade(self, blade_file):
        # ElastoDyn v1.00 Blade Input File
        # Currently no differences between FASTv8.16 and OpenFAST.

        f = open(blade_file)
        # print blade_file
        f.readline()
        f.readline()
        f.readline()

        # Blade Parameters
        self.fst_vt['ElastoDynBlade']['NBlInpSt'] = int(f.readline().split()[0])
        self.fst_vt['ElastoDynBlade']['BldFlDmp1'] = float_read(f.readline().split()[0])
        self.fst_vt['ElastoDynBlade']['BldFlDmp2'] = float_read(f.readline().split()[0])
        self.fst_vt['ElastoDynBlade']['BldEdDmp1'] = float_read(f.readline().split()[0])

        # Blade Adjustment Factors
        f.readline()
        self.fst_vt['ElastoDynBlade']['FlStTunr1'] = float_read(f.readline().split()[0])
        self.fst_vt['ElastoDynBlade']['FlStTunr2'] = float_read(f.readline().split()[0])
        self.fst_vt['ElastoDynBlade']['AdjBlMs'] = float_read(f.readline().split()[0])
        self.fst_vt['ElastoDynBlade']['AdjFlSt'] = float_read(f.readline().split()[0])
        self.fst_vt['ElastoDynBlade']['AdjEdSt'] = float_read(f.readline().split()[0])

        # Distrilbuted Blade Properties
        f.readline()
        f.readline()
        f.readline()
        self.fst_vt['ElastoDynBlade']['BlFract'] = [None] * self.fst_vt['ElastoDynBlade']['NBlInpSt']
        self.fst_vt['ElastoDynBlade']['PitchAxis'] = [None] * self.fst_vt['ElastoDynBlade']['NBlInpSt']
        self.fst_vt['ElastoDynBlade']['StrcTwst'] = [None] * self.fst_vt['ElastoDynBlade']['NBlInpSt']
        self.fst_vt['ElastoDynBlade']['BMassDen'] = [None] * self.fst_vt['ElastoDynBlade']['NBlInpSt']
        self.fst_vt['ElastoDynBlade']['FlpStff'] = [None] * self.fst_vt['ElastoDynBlade']['NBlInpSt']
        self.fst_vt['ElastoDynBlade']['EdgStff'] = [None] * self.fst_vt['ElastoDynBlade']['NBlInpSt']

        for i in range(self.fst_vt['ElastoDynBlade']['NBlInpSt']):
            data = f.readline().split()
            self.fst_vt['ElastoDynBlade']['BlFract'][i]  = float_read(data[0])
            self.fst_vt['ElastoDynBlade']['PitchAxis'][i]  = float_read(data[1])
            self.fst_vt['ElastoDynBlade']['StrcTwst'][i]  = float_read(data[2])
            self.fst_vt['ElastoDynBlade']['BMassDen'][i]  = float_read(data[3])
            self.fst_vt['ElastoDynBlade']['FlpStff'][i]  = float_read(data[4])
            self.fst_vt['ElastoDynBlade']['EdgStff'][i]  = float_read(data[5])

        f.readline()
        self.fst_vt['ElastoDynBlade']['BldFl1Sh'] = [None] * 5
        self.fst_vt['ElastoDynBlade']['BldFl2Sh'] = [None] * 5
        self.fst_vt['ElastoDynBlade']['BldEdgSh'] = [None] * 5
        for i in range(5):
            self.fst_vt['ElastoDynBlade']['BldFl1Sh'][i]  = float_read(f.readline().split()[0])
        for i in range(5):
            self.fst_vt['ElastoDynBlade']['BldFl2Sh'][i]  = float_read(f.readline().split()[0])
        for i in range(5):
            self.fst_vt['ElastoDynBlade']['BldEdgSh'][i]  = float_read(f.readline().split()[0])

        f.close()

    def read_BeamDyn(self, bd_file):
        # BeamDyn Input File
        f = open(bd_file)
        f.readline()
        f.readline()
        f.readline()
        # ---------------------- SIMULATION CONTROL --------------------------------------
        self.fst_vt['BeamDyn']['Echo']             = bool_read(f.readline().split()[0])
        self.fst_vt['BeamDyn']['QuasiStaticInit']  = bool_read(f.readline().split()[0])
        self.fst_vt['BeamDyn']['rhoinf']           = float_read(f.readline().split()[0])
        self.fst_vt['BeamDyn']['quadrature']       = int_read(f.readline().split()[0])
        self.fst_vt['BeamDyn']['refine']           = int_read(f.readline().split()[0])
        self.fst_vt['BeamDyn']['n_fact']           = int_read(f.readline().split()[0])
        self.fst_vt['BeamDyn']['DTBeam']           = float_read(f.readline().split()[0])
        self.fst_vt['BeamDyn']['load_retries']     = int_read(f.readline().split()[0])
        self.fst_vt['BeamDyn']['NRMax']            = int_read(f.readline().split()[0])
        self.fst_vt['BeamDyn']['stop_tol']         = float_read(f.readline().split()[0])
        self.fst_vt['BeamDyn']['tngt_stf_fd']      = bool_read(f.readline().split()[0])
        self.fst_vt['BeamDyn']['tngt_stf_comp']    = bool_read(f.readline().split()[0])
        self.fst_vt['BeamDyn']['tngt_stf_pert']    = float_read(f.readline().split()[0])
        self.fst_vt['BeamDyn']['tngt_stf_difftol'] = float_read(f.readline().split()[0])
        self.fst_vt['BeamDyn']['RotStates']        = bool_read(f.readline().split()[0])
        f.readline()
        #---------------------- GEOMETRY PARAMETER --------------------------------------
        self.fst_vt['BeamDyn']['member_total']     = int_read(f.readline().split()[0])
        self.fst_vt['BeamDyn']['kp_total']         = int_read(f.readline().split()[0])
        self.fst_vt['BeamDyn']['members']          = []
        for i in range(self.fst_vt['BeamDyn']['member_total']):
            ln = f.readline().split()
            n_pts_i                   = int(ln[1])
            member_i                  = {}
            member_i['kp_xr']         = [None]*n_pts_i
            member_i['kp_yr']         = [None]*n_pts_i
            member_i['kp_zr']         = [None]*n_pts_i
            member_i['initial_twist'] = [None]*n_pts_i
            f.readline()
            f.readline()
            for j in range(n_pts_i):
                ln = f.readline().split()
                member_i['kp_xr'][j]          = float(ln[0])
                member_i['kp_yr'][j]          = float(ln[1])
                member_i['kp_zr'][j]          = float(ln[2])
                member_i['initial_twist'][j]  = float(ln[3])

            self.fst_vt['BeamDyn']['members'].append(member_i)
        #---------------------- MESH PARAMETER ------------------------------------------
        f.readline()
        self.fst_vt['BeamDyn']['order_elem']  = int_read(f.readline().split()[0])
        #---------------------- MATERIAL PARAMETER --------------------------------------
        f.readline()
        self.fst_vt['BeamDyn']['BldFile']     = f.readline().split()[0].replace('"','').replace("'",'')
        #---------------------- PITCH ACTUATOR PARAMETERS -------------------------------
        f.readline()
        self.fst_vt['BeamDyn']['UsePitchAct'] = bool_read(f.readline().split()[0])
        self.fst_vt['BeamDyn']['PitchJ']      = float_read(f.readline().split()[0])
        self.fst_vt['BeamDyn']['PitchK']      = float_read(f.readline().split()[0])
        self.fst_vt['BeamDyn']['PitchC']      = float_read(f.readline().split()[0])
        #---------------------- OUTPUTS -------------------------------------------------
        f.readline()
        self.fst_vt['BeamDyn']['SumPrint']    = bool_read(f.readline().split()[0])
        self.fst_vt['BeamDyn']['OutFmt']      = f.readline().split()[0][1:-1]
        self.fst_vt['BeamDyn']['NNodeOuts']   = int_read(f.readline().split()[0])
        self.fst_vt['BeamDyn']['OutNd']       = [idx.strip() for idx in f.readline().split('NNodeOuts')[0].split(',')]
        # BeamDyn Outlist
        f.readline()
        data = f.readline()
        while data.split()[0] != 'END':
            channels = data.split('"')
            channel_list = channels[1].split(',')
            self.set_outlist(self.fst_vt['outlist']['BeamDyn'], channel_list)
            data = f.readline()

        f.close()

        self.read_BeamDynBlade()

    def read_BeamDynBlade(self):
        # BeamDyn Blade

        beamdyn_blade_file = os.path.join(self.FAST_directory, self.fst_vt['BeamDyn']['BldFile'])
        f = open(beamdyn_blade_file)

        f.readline()
        f.readline()
        f.readline()
        #---------------------- BLADE PARAMETERS --------------------------------------
        self.fst_vt['BeamDynBlade']['station_total'] = int_read(f.readline().split()[0])
        self.fst_vt['BeamDynBlade']['damp_type']     = int_read(f.readline().split()[0])
        f.readline()
        f.readline()
        f.readline()
        #---------------------- DAMPING COEFFICIENT------------------------------------
        ln = f.readline().split()
        self.fst_vt['BeamDynBlade']['mu1']           = float(ln[0])
        self.fst_vt['BeamDynBlade']['mu2']           = float(ln[1])
        self.fst_vt['BeamDynBlade']['mu3']           = float(ln[2])
        self.fst_vt['BeamDynBlade']['mu4']           = float(ln[3])
        self.fst_vt['BeamDynBlade']['mu5']           = float(ln[4])
        self.fst_vt['BeamDynBlade']['mu6']           = float(ln[5])
        f.readline()
        #---------------------- DISTRIBUTED PROPERTIES---------------------------------

        self.fst_vt['BeamDynBlade']['radial_stations'] = np.zeros((self.fst_vt['BeamDynBlade']['station_total']))
        self.fst_vt['BeamDynBlade']['beam_stiff']      = np.zeros((self.fst_vt['BeamDynBlade']['station_total'], 6, 6))
        self.fst_vt['BeamDynBlade']['beam_inertia']    = np.zeros((self.fst_vt['BeamDynBlade']['station_total'], 6, 6))
        for i in range(self.fst_vt['BeamDynBlade']['station_total']):
            self.fst_vt['BeamDynBlade']['radial_stations'][i]  = float_read(f.readline().split()[0])
            for j in range(6):
                self.fst_vt['BeamDynBlade']['beam_stiff'][i,j,:] = np.array([float(val) for val in f.readline().strip().split()])
            f.readline()
            for j in range(6):
                self.fst_vt['BeamDynBlade']['beam_inertia'][i,j,:] = np.array([float(val) for val in f.readline().strip().split()])
            f.readline()

        f.close()


import json
import configparser
from configparser import SectionProxy
from azure.identity import DeviceCodeCredential, ClientSecretCredential
from msgraph.core import GraphClient

class Graph:
	settings: SectionProxy
	device_code_credential: DeviceCodeCredential
	user_client: GraphClient
	client_credential: ClientSecretCredential
	app_client: GraphClient

	def __init__(self, config: SectionProxy):
		self.settings = config
		client_id = self.settings['clientId']
		tenant_id = self.settings['authTenant']
		graph_scopes = self.settings['graphUserScopes'].split(' ')

		self.device_code_credential = DeviceCodeCredential(client_id, tenant_id = tenant_id)
		self.user_client = GraphClient(credential=self.device_code_credential, scopes=graph_scopes)

	def get_user_token(self):
		graph_scopes = self.settings['graphUserScopes']
		access_token = self.device_code_credential.get_token(graph_scopes)
		return access_token.token

	def get_user(self):
		endpoint = '/me'
		# Only request specific properties
		select = 'displayName,mail,userPrincipalName,id'
		request_url = f'{endpoint}?$select={select}'

		user_response = self.user_client.get(request_url)
		return user_response.json()

# def display_access_token(graph: Graph):
# 	token = graph.get_user_token()
# 	print('User token:', token, '\n')

# def greet_user(graph: Graph):
# 	user = graph.get_user()
# 	print('Hello,', user['displayName'])
# 	# For Work/school accounts, email is in mail property
# 	# Personal accounts, email is in userPrincipalName
# 	print('Email:', user['mail'] or user['userPrincipalName'], '\n')


import logging
import torch
from torch.distributions.categorical import Categorical
import numpy as np

def config_logger(log_dir):
    logger = logging.getLogger()
    logger.setLevel('INFO')
    basic_format = '%(message)s'
    formatter = logging.Formatter(basic_format)
    chlr = logging.StreamHandler()
    chlr.setFormatter(formatter)
    fhlr = logging.FileHandler(log_dir)
    logger.addHandler(chlr)
    logger.addHandler(fhlr)
    return logger

def select_actions(pi):
    actions = Categorical(pi).sample()
    return actions.detach().cpu().numpy().squeeze()

def evaluate_actions(pi, actions):
    distr = Categorical(pi)
    log_prob = distr.log_prob(actions).unsqueeze(-1)
    entropy = distr.entropy().mean()
    return log_prob, entropy


import unittest
import os.path
import os
from archivos import IMCFile

class TestFiles(unittest.TestCase):

    def setUp(self):
      try:
        file = open('c:/test/imc.txt')
        file.close()
        print ("El fichero existe")
      except:
        print ("El fichero no existe")
        file = open('c:/test/imc.txt','w')
        file.close()

    def test_Human(self):

        IMCFile(1.80, 73)
        file = open("c:/test/imc.txt","r")
        mensaje = file.read()
        self.assertEqual(mensaje, "22.53")
        file.close()

    def test_InHuman(self):
        IMCFile(3.40, 300)
        file = open("c:/test/imc.txt","r")
        mensaje = file.read()
        self.assertEqual(mensaje, "25.95")
        file.close()

    def tearDown(self):

        os.remove('c:/test/imc.txt')

if __name__ == '__main__':

    unittest.main()


import os
import ui, events, language
import widgets as wg
import sb.widget.button as wb
import sb.widget.list
import sb.aodb as ao
import sb.profdb as pr
import widgets

MAPS = 'tab-maps'

# React to selection notifications.
listenSelections = True

# The map list box (has columns).
mapListBox = None

def init():
    # Create the Maps page.
    area = ui.createTab(MAPS)
    area.setBorderDirs(ui.BORDER_NOT_BOTTOM)
    area.setWeight(1)

    global mapListBox
    area.setBorderDirs(ui.BORDER_NOT_BOTTOM)
    mapListBox = area.createList('maps-list', sb.widget.list.List.STYLE_COLUMNS)

    # The columns.
    mapListBox.addColumn('maps-list-icon', 20)
    mapListBox.addColumn('maps-list-identifier', 180)
    mapListBox.addColumn('maps-list-count')

    # Prepare icons.
    global iconManager, mapIcons
    iconManager = widgets.IconManager(16, 16)
    mapIcons = [iconManager.get('unchecked'), iconManager.get('checked')]
    mapListBox.setImageList(iconManager.getImageList())

    # Some buttons in the bottom.
    area.setWeight(0)
    area.setBorderDirs(ui.BORDER_NOT_TOP)
    buttonArea = area.createArea(alignment=ui.ALIGN_HORIZONTAL, border=4)
    buttonArea.setBorderDirs(ui.BORDER_TOP | ui.BORDER_RIGHT)
    buttonArea.setWeight(0)
    clearButton = buttonArea.createButton('maps-list-clear', wb.Button.STYLE_MINI)
    clearButton.resizeToBestSize()
    refreshButton = buttonArea.createButton('refresh-addon-database', wb.Button.STYLE_MINI)
    refreshButton.resizeToBestSize()

    buttonArea.setWeight(1)
    buttonArea.addSpacer()
    buttonArea.setWeight(0)
    buttonArea.setBorderDirs(ui.BORDER_TOP | ui.BORDER_LEFT)
    buttonArea.createButton('show-addon-paths')

    # Listen to our commands.
    events.addCommandListener(handleCommand, ['maps-list-clear'])

    events.addNotifyListener(handleNotify, ['active-profile-changed',
                                            'maps-list-selected',
                                            'maps-list-deselected',
                                            'addon-attached',
                                            'addon-detached',
                                            'addon-database-reloaded',
                                            'language-changed'])

def handleCommand(event):
    """Handle a command event."""

    if event.hasId('maps-list-clear'):
        mapListBox.selectItem(None)

def handleNotify(event):
    """Handle a notification event."""

    global listenSelections

    if event.hasId('active-profile-changed'):
        refreshList()

    if event.hasId('maps-list-selected') and listenSelections:
        pr.getActive().useAddon(event.getSelection())

    if event.hasId('maps-list-deselected'):
        pr.getActive().dontUseAddon(event.getDeselection())

    if event.hasId('addon-attached'):
        listenSelections = False
        mapListBox.selectItem(event.getAddon())
        mapListBox.setItemImage(event.getAddon(), 1)
        listenSelections = True

    if event.hasId('addon-detached'):
        listenSelections = False
        mapListBox.deselectItem(event.getAddon())
        mapListBox.setItemImage(event.getAddon(), 0)
        listenSelections = True

    if event.hasId('addon-database-reloaded'):
        refreshList()

    if event.hasId('language-changed'):
        mapListBox.retranslateColumns()

def refreshList():
    """Fill the maps list with addons."""

    # Clear the list.
    mapListBox.clear()

    wads = [a for a in ao.getAvailableAddons(pr.getActive())
            if a.getType() == 'addon-type-wad' and a.isPWAD()]

    # Translate addon names.
    wads.sort(lambda a, b: cmp(a.getId(), b.getId()))

    for wad in wads:
        # TODO: More information titles.
        if not language.isDefined(wad.getId()):
            visibleName = language.translate(wad.getId())
        else:
            visibleName = os.path.basename(wad.getContentPath())
        mapListBox.addItemWithColumns(wad.getId(),
                                      0,
                                      visibleName,
                                      wad.getShortContentAnalysis())

    prof = pr.getActive()
    usedAddons = prof.getUsedAddons()
    theFirst = True

    # Select the addons currently attached to the profile.
    # Also make sure the first one is visible.
    for addonId in usedAddons:
        mapListBox.selectItem(addonId)
        mapListBox.setItemImage(addonId, 1)
        if theFirst:
            # Make sure it's visible.
            mapListBox.ensureVisible(addonId)
            theFirst = False


from setuptools import setup

APP = ['geekhub/geekhub.py']
DATA_FILES = [
    'Resources/alert.png',
    'Resources/notification.png',
]
OPTIONS = {
    'argv_emulation': True,
    'plist': {
        'LSUIElement': True,
    },
    'packages': ['rumps'],
    'iconfile': 'Resources/logo.icns',
}

VERSION = '0.1.3'

setup(
    name='geekhub',
    version=VERSION,
    description='A little statusbar for to geekhub',
    license='MIT',
    author='Leetao',
    author_email='leetao@gmail.com',
    packges=['geekhub'],
    app=APP,
    data_files=DATA_FILES,
    options={'py2app': OPTIONS},
    install_requires=['requests', 'BeautifulSoup4', 'rumps'],
    setup_requires=['py2app'],
    classifiers=[
        'Development Status :: 3 - Alpha',
        'Environment :: MacOS X',
        'License :: OSI Approved :: MIT License',
        'Natural Language :: Chinese',
        'Operating System :: MacOS :: MacOS X',
        'Programming Language :: Python :: 3.7',
    ]
)