#!/usr/bin/python3
#
# first program to learn python and Gtk
# Capture images an create a timelapse using an RPI camera
# requires: ffmpeg, raspistill (optional gthumb for triage)
# antoine@ginies.org
#

import gi
from PIL import Image
import configparser
import subprocess
import sys
import io
import time
import threading
import os.path
import glob
from datetime import datetime

gi.require_version('Gst', '1.0')
gi.require_version('GdkX11', '3.0')
gi.require_version('GstVideo', '1.0')
gi.require_version("Gtk", "3.0")
from gi.repository import Gtk, Gio, GLib, GObject, Gst, GstVideo

Gst.init(None)
video_dev = "/dev/video0"

def read_config():
    config = configparser.ConfigParser()
    STARTCONFIGFILE = '/etc/config.ini'
    if os.path.isfile(STARTCONFIGFILE):
        print("reading /etc/config.ini")
        config.read(STARTCONFIGFILE)
#        config.close()
    else:
        CONFIGFILE = 'config.ini'
        if os.path.isfile('config.ini'):
            print("reading config.ini")
            config.read('config.ini')
            return config
        else:
            print("No config creating one!")
            f = open("config.ini","w+")
            config.read('config.ini')
            if config.has_section("all") != True:
                config.add_section('all')
            if config.has_section("img") != True:
                config.add_section('img')
            if config.has_section("video") != True:
                config.add_section('video')
            config.set('all', 'configfile', 'config.ini')
            config.set('all', 'working_dir', '/tmp/')
            config.set('all', 'live_camera_180', "true")
            config.set('img', 'rotation', '180')
            config.set('img', 'image_name', 'image')
            config.set('img', 'width', '1920')
            config.set('img', 'height', '1080')
            config.set('img', 'quality', '10')
            config.set('img', 'encoding', 'jpg')
            config.set('img', 'timelapse', '3000')
            config.set('img', 'extra', '')
            config.set('video', 'framerate', '30')
            config.set('video', 'setpts', '0.3*PTS')
            config.set('video', 'vcodec', 'libx264')
            config.set('video', 'width', '1920')
            config.set('video', 'height', '1080')
            config.set('video', 'extra', '')
            config.write(f)
            f.close()
            return config

class DisplayVideoConf(Gtk.Window):
    def __init__(self, parent):
        Gtk.Window.__init__(self, title="FFMPEG Video Settings", transient_for=parent)

        self.set_default_size(640, 480)
        self.set_border_width(10)

        def show_video_help(button):
            #self.help_button.set_sensitive(False)
            win = Gtk.Window(title="ffmpeg --help", transient_for=parent)
            win.set_default_size(800, 700)
            win.set_border_width(10)

            # get help
            cmd = "ffmpeg --help"
            proc = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
            rc = proc.wait()
            outs, errs = proc.communicate(timeout=2)
            textview = Gtk.TextView()
            textbuffer = textview.get_buffer()
            textview.set_editable(False)
            scrolled = Gtk.ScrolledWindow()
            scrolled.add(textview)
            end_iter = textbuffer.get_end_iter()
            textbuffer.insert(end_iter, outs.decode("utf8"))

            box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=10, border_width=12)
            box.pack_start(scrolled, True, True, 0)
            win.add(box)
            win.show_all()

        def on_clicked_ok(button_ok):
            print("saving file")
            fp = open(config.get('all', 'configfile'), 'w')
            config.set('video', 'framerate', entry_framerate.get_text())
            config.set('video', 'setpts', entry_setpts.get_text())
            config.set('video', 'vcodec', entry_vcodec.get_text())
            config.set('video', 'width', entry_vwidth.get_text())
            config.set('video', 'height', entry_vheight.get_text())
            config.set('video', 'extra', entry_vextra.get_text())
            config.write(fp)
            fp.close()
            self.destroy()

        def on_clicked_cancel(button_cancel):
            print("cancel")
            self.destroy()

        #
        # read from config file
        config = read_config()

        self.help_ffmpeg = Gtk.Button(label="ffmpeg Help")
        self.help_ffmpeg.connect("clicked", show_video_help)

        # rotate or not
        box_framerate = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=10)
        entry_framerate = Gtk.Entry()
        label_framerate = Gtk.Label("Framerate")
        if config.has_option('video', 'framerate'):
            entry_framerate.set_text(config.get('video', 'framerate'))
        else:
            entry_framerate.set_text("30")

        box_vwidth = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=10)
        entry_vwidth = Gtk.Entry()
        label_vwidth = Gtk.Label("Video Width (1920)")
        if config.has_option('video', 'width'):
            entry_vwidth.set_text(config.get('video', 'width'))
        else:
            entry_vwidth.set_text("1920")

        box_vheight = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=10)
        entry_vheight = Gtk.Entry()
        label_vheight = Gtk.Label("Video Height (1080)")
        if config.has_option('video', 'height'):
            entry_vheight.set_text(config.get('video', 'height'))
        else:
            entry_vheight.set_text("1080")

        box_steptps = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=10)
        entry_setpts = Gtk.Entry()
        label_setpts = Gtk.Label("Video Acceleration (NOT USED)")
        if config.has_option('video', 'setpts'):
            entry_setpts.set_text(config.get('video', 'setpts'))
        else:
            entry_setpts.set_text("0.3*PTS")

        box_vcodec = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=10)
        entry_vcodec = Gtk.Entry()
        label_vcodec = Gtk.Label("Video Codec")
        if config.has_option('video', 'vcodec'):
            entry_vcodec.set_text(config.get('video', 'vcodec'))
        else:
            entry_vcodec.set_text('libx264')

        box_vextra = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=10)
        entry_vextra = Gtk.Entry()
        label_vextra = Gtk.Label("Extra Options (See Help)")
        if config.has_option('video', 'extra'):
            entry_vextra.set_text(config.get('video', 'extra'))
        else:
            entry_vextra.set_text("")

        box_ok_cancel= Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=10)
        button_ok = Gtk.Button.new_with_mnemonic("_Ok")
        button_ok.connect("clicked", on_clicked_ok)
        button_cancel = Gtk.Button.new_with_mnemonic("_Cancel")
        button_cancel.connect("clicked", on_clicked_cancel)

        box_framerate.pack_start(label_framerate, False, False, 0)
        box_framerate.pack_end(entry_framerate, False, False, 0)
        box_vheight.pack_start(label_vheight, False, False, 0)
        box_vheight.pack_end(entry_vheight, False, False, 0)
        box_vwidth.pack_start(label_vwidth, False, False, 0)
        box_vwidth.pack_end(entry_vwidth, False, False, 0)
        box_vcodec.pack_start(label_vcodec, False, False, 0)
        box_vcodec.pack_end(entry_vcodec, False, False, 0)
        box_steptps.pack_start(label_setpts, False, False, 0)
        box_steptps.pack_end(entry_setpts, False, False, 0)
        box_vextra.pack_start(label_vextra, False, False, 0)
        box_vextra.pack_end(entry_vextra, False, False, 0)
        box_ok_cancel.pack_start(button_cancel, False, False, 0)
        box_ok_cancel.pack_end(button_ok, False, False, 0)

        vbox = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=10)
        vbox.set_spacing(20)
        self.add(vbox)
        vbox.pack_start(self.help_ffmpeg, False, False, 0)

        vboxvideo = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=10)
        vboxvideo.pack_start(box_framerate, False, False, 0)
        vboxvideo.pack_start(box_vwidth, False, False, 0)
        vboxvideo.pack_start(box_vheight, False, False, 0)
        vboxvideo.pack_start(box_vcodec, False, False, 0)
        vboxvideo.pack_start(box_steptps, False, False, 0)
        framevideo = Gtk.Frame()
        framevideo.add(vboxvideo)
        framevideo.show()

        vboxmore = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=10)
        vboxmore.pack_start(box_vextra, False, False, 0)
        framemore = Gtk.Frame()
        framemore.add(vboxmore)
        framemore.show()

        vbox.add(framevideo)
        vbox.add(framemore)
        vbox.pack_end(box_ok_cancel, False, False, 0)
        self.show_all()

class DisplayAllConf(Gtk.Window):
    def __init__(self, parent):
        Gtk.Window.__init__(self, title="Application Settings", transient_for=parent)

        self.set_default_size(640, 480)
        self.set_border_width(10)

        def on_clicked_ok(button_ok):
            print("saving file")
            fp = open(entry_info_config.get_text(), 'w')
            config.set('all', 'configfile', entry_info_config.get_text())
            config.set('all', 'working_dir', entry_working_dir.get_text())
            if self.live_camera_180.get_active() == 1:
                config.set('all', 'live_camera_180', 'true')
            else:
                config.set('all', 'live_camera_180', 'false')
            config.write(fp)
            fp.close()
            self.destroy()

        def on_clicked_cancel(button_cancel):
            print("cancel")
            self.destroy()

        def on_file_clicked(widget):
            dialog = Gtk.FileChooserDialog(
                title="Please choose a file", parent=self, action=Gtk.FileChooserAction.OPEN
            )
            dialog.add_buttons(
                Gtk.STOCK_CANCEL,
                Gtk.ResponseType.CANCEL,
                Gtk.STOCK_OPEN,
                Gtk.ResponseType.OK,
            )

            filter_ini = Gtk.FileFilter()
            filter_ini.set_name("ini file")
            filter_ini.add_pattern("*.ini")
            dialog.add_filter(filter_ini)

            response = dialog.run()
            if response == Gtk.ResponseType.OK:
                print("Open clicked")
                print("File selected: " + dialog.get_filename())
                entry_info_config.set_text(dialog.get_filename())
            elif response == Gtk.ResponseType.CANCEL:
                print("Cancel clicked")

            dialog.destroy()

        def on_button_revert_camera(self, button, live_camera_180):
            if button.get_active():
                state = "on"
                print("Camera upside down")
            else:
                print("Camera normal mode")
                state = "off"

        #
        # read from config file
        config = read_config()

        box_info_config = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=10)
        entry_info_config = Gtk.Entry()
        label_info_config = Gtk.Label("Path to config file")
        if config.has_option('all', 'configfile'):
            entry_info_config.set_text(config.get('all', 'configfile'))
        else:
            entry_info_config.set_text("config.ini")
        file_info_config = Gtk.Button(label="Choose File")
        file_info_config.connect("clicked", on_file_clicked)

        box_working_dir = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=10)
        entry_working_dir = Gtk.Entry()
        label_working_dir = Gtk.Label("Working Directory")
        if config.has_option('all', 'working_dir'):
            entry_working_dir.set_text(config.get('all', 'working_dir'))
        else:
            entry_working_dir.set_text("/tmp/")

        box_ok_cancel= Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=10)
        button_ok = Gtk.Button.new_with_mnemonic("_Ok")
        button_ok.connect("clicked", on_clicked_ok)
        button_cancel = Gtk.Button.new_with_mnemonic("_Cancel")
        button_cancel.connect("clicked", on_clicked_cancel)

        box_live_camera_180= Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=10)
        self.label_camera_180 = Gtk.Label()
        self.label_camera_180.set_text("180 Camera Rotation")
        self.live_camera_180 = Gtk.CheckButton()
        if config.get('all', 'live_camera_180') == "true":
            self.live_camera_180.set_active("True")
        else:
            self.live_camera_180.set_active("True")
        self.live_camera_180.connect("toggled", on_button_revert_camera, "1")

        box_info_config.pack_start(label_info_config, False, False, 0)
        box_info_config.pack_start(entry_info_config, False, False, 0)
        box_info_config.pack_end(file_info_config, False, False, 0)
        box_working_dir.pack_start(label_working_dir, False, False, 0)
        box_working_dir.pack_end(entry_working_dir, False, False, 0)
        box_live_camera_180.pack_start(self.label_camera_180, False, False, 0)
        box_live_camera_180.pack_end(self.live_camera_180, False, False, 0)

        box_ok_cancel.pack_start(button_cancel, False, False, 0)
        box_ok_cancel.pack_end(button_ok, False, False, 0)

        vboxconf = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=10)
        vboxconf.pack_start(box_info_config, False, False, 0)
        vboxconf.pack_start(box_working_dir, False, False, 0)
        vboxconf.pack_start(box_live_camera_180, False, False, 0)
        frameconf = Gtk.Frame()
        frameconf.add(vboxconf)
        frameconf.show()

        vbox = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=10)
        vbox.set_spacing(20)
        self.add(vbox)

        vbox.add(frameconf)
        vbox.pack_end(box_ok_cancel, False, False, 0)
        self.show_all()

class DisplayImageConf(Gtk.Window):
    def __init__(self, parent):
        Gtk.Window.__init__(self, title="Rpi Camera Settings", transient_for=parent)

        self.set_default_size(640, 480)
        self.set_border_width(10)

        def show_help(button):
            #self.help_button.set_sensitive(False)
            win = Gtk.Window(title="Raspistill help", transient_for=parent)
            win.set_default_size(800, 700)
            win.set_border_width(10)

            # get help
            cmd = "raspistill --help"
            proc = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
            rc = proc.wait()
            outs, errs = proc.communicate(timeout=2)
            textview = Gtk.TextView()
            textbuffer = textview.get_buffer()
            textview.set_editable(False)
            scrolled = Gtk.ScrolledWindow()
            scrolled.add(textview)
            end_iter = textbuffer.get_end_iter()
            textbuffer.insert(end_iter, outs.decode("utf8"))

            box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=10, border_width=12)
            box.pack_start(scrolled, True, True, 0)
            win.add(box)
            win.show_all()

        def on_clicked_ok(button_ok):
            print("saving file")
            fp = open(config.get('all', 'configfile'), 'w')
            config.set('img', 'rotation', entry_rot.get_text())
            config.set('img', 'image_name', entry_image_name.get_text())
            config.set('img', 'width', entry_width.get_text())
            config.set('img', 'height', entry_height.get_text())
            config.set('img', 'quality', entry_quality.get_text())
            config.set('img', 'encoding', combo_encoding.get_active_text())
            config.set('img', 'timelapse', entry_timelapse.get_text())
            config.set('img', 'extra', entry_extra.get_text())
            config.write(fp)
            fp.close()
            self.destroy()

        def on_encoding_changed(combo):
            text = combo.get_active_text()
            if text is not None:
                print("DEBUG Selected: encoding=%s" % text)

        def on_clicked_cancel(button_cancel):
            print("cancel")
            self.destroy()

        #
        # read from config file
        config = read_config()

        self.help_button = Gtk.Button(label="raspistill Help")
        self.help_button.connect("clicked", show_help)

        # rotate or not
        box_rot = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=10)
        entry_rot = Gtk.Entry()
        label_rot = Gtk.Label("Image Rotation")
        if config.has_option('img', 'rotation'):
            entry_rot.set_text(config.get('img', 'rotation'))
        else:
            entry_rot.set_text("0")

        box_width = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=10)
        entry_width = Gtk.Entry()
        label_width = Gtk.Label("Image Width (1920)")
        if config.has_option('img', 'width'):
            entry_width.set_text(config.get('img', 'width'))
        else:
            entry_width.set_text("1920")

        box_height = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=10)
        entry_height = Gtk.Entry()
        label_height = Gtk.Label("Image Height (1080)")
        if config.has_option('img', 'height'):
            entry_height.set_text(config.get('img', 'height'))
        else:
            entry_height.set_text("1080")

        box_timelapse = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=10)
        entry_timelapse = Gtk.Entry()
        label_timelapse = Gtk.Label("Time between captures (in ms)")
        if config.has_option('img', 'timelapse'):
            entry_timelapse.set_text(config.get('img', 'timelapse'))
        else:
            entry_timelapse.set_text("3000")

        box_quality = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=10)
        entry_quality = Gtk.Entry()
        label_quality = Gtk.Label("Quality")
        if config.has_option('img', 'quality'):
            entry_quality.set_text(config.get('img', 'quality'))
        else:
            entry_quality.set_text("10")

        box_encoding = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=10)
        encoding_list = [ "jpg", "bmp", "gif", "png"]
        combo_encoding = Gtk.ComboBoxText()
        combo_encoding.set_entry_text_column(0)
        combo_encoding.connect("changed", on_encoding_changed)
        for data in encoding_list:
            combo_encoding.append_text(data)
        combo_encoding.set_active(0)
        label_encoding = Gtk.Label("Encoding format")
        # jpg bmp gif png
        # TOFIX
        if config.has_option('img', 'encoding'):
            print("IN CONFIG: " + config.get('img', 'encoding'))
            #combo_encoding.set_active_iter(config.get('all', 'encoding'))

        box_image_name = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=10)
        entry_image_name = Gtk.Entry()
        label_image_name = Gtk.Label("Image Name (prefix)")
        if config.has_option('img', 'image_name'):
            entry_image_name.set_text(config.get('img', 'image_name'))
        else:
            entry_image_name.set_text('image_')

        box_extra = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=10)
        entry_extra = Gtk.Entry()
        label_extra = Gtk.Label("Extra Options (See Help)")
        if config.has_option('img', 'extra'):
            entry_extra.set_text(config.get('img', 'extra'))
        else:
            entry_extra.set_text("")

        box_ok_cancel= Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=10)
        button_ok = Gtk.Button.new_with_mnemonic("_Ok")
        button_ok.connect("clicked", on_clicked_ok)
        button_cancel = Gtk.Button.new_with_mnemonic("_Cancel")
        button_cancel.connect("clicked", on_clicked_cancel)

        box_rot.pack_start(label_rot, False, False, 0)
        box_rot.pack_end(entry_rot, False, False, 0)
        box_height.pack_start(label_height, False, False, 0)
        box_height.pack_end(entry_height, False, False, 0)
        box_width.pack_start(label_width, False, False, 0)
        box_width.pack_end(entry_width, False, False, 0)
        box_image_name.pack_start(label_image_name, False, False, 0)
        box_image_name.pack_end(entry_image_name, False, False, 0)
        box_encoding.pack_start(label_encoding, False, False, 0)
        box_encoding.pack_end(combo_encoding, False, False, 0)
        box_ok_cancel.pack_start(button_cancel, False, False, 0)
        box_ok_cancel.pack_end(button_ok, False, False, 0)
        box_timelapse.pack_start(label_timelapse, False, False, 0)
        box_timelapse.pack_end(entry_timelapse, False, False, 0)
        box_extra.pack_start(label_extra, False, False, 0)
        box_extra.pack_end(entry_extra, False, False, 0)

        vbox = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=10)
        vbox.set_spacing(20)
        self.add(vbox)
        vbox.pack_start(self.help_button, False, False, 0)

        vboximg = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=10)
        vboximg.pack_start(box_image_name, False, False, 0)
        vboximg.pack_start(box_rot, False, False, 0)
        vboximg.pack_start(box_width, False, False, 0)
        vboximg.pack_start(box_height, False, False, 0)
        vboximg.pack_start(box_encoding, False, False, 0)
        vboximg.pack_start(box_quality, False, False, 0)
        frameimage = Gtk.Frame()
        frameimage.add(vboximg)
        frameimage.show()

        vboxmore = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=10)
        vboxmore.pack_start(box_timelapse, False, False, 0)
        vboxmore.pack_start(box_extra, False, False, 0)
        framemore = Gtk.Frame()
        framemore.add(vboxmore)
        framemore.show()
        vbox.add(frameimage)
        vbox.add(framemore)
        vbox.pack_end(box_ok_cancel, False, False, 0)
        self.show_all()

class LogInterFace(Gtk.Window):
    def __init__(self, command):

        Gtk.Window.__init__(self,
                title="Log Interface",
                default_width=500,
                default_height=400,
                )
        self.cancellable = Gio.Cancellable()

        self.start_button = Gtk.Button(label="Show log")
        self.start_button.connect("clicked", self.on_start_clicked)

        textview = Gtk.TextView()
        self.textbuffer = textview.get_buffer()
        scrolled = Gtk.ScrolledWindow()
        scrolled.add(textview)
        self.command = command
        progress = Gtk.ProgressBar(show_text=True)

        box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=6, border_width=12)
        box.pack_start(self.start_button, False, True, 0)
        box.pack_start(progress, False, True, 0)
        box.pack_start(scrolled, True, True, 0)

        self.add(box)

    def autoscroll(self, *args):
        adj = self.scrolled.get_vadjustment()
        adj.set_value(adj.get_upper() - adj.get_page_size())

    def append_text(self, text):
        iter_ = self.textbuffer.get_end_iter()
        self.textbuffer.insert(iter_, "[%s] %s\n" % (str(time.time()), text))

class MainBox(Gtk.Window):
    def __init__(self):
        Gtk.Window.__init__(self, title="RPI Camera")

        self.set_default_size(320, 280)
        self.set_border_width(20)

        self.img = Image.open('cover.jpg')
        newimg = self.img.resize((200, 200))
        newimg.save('/tmp/_cover.jpg')
        self.live = Gtk.Image()
        self.live.set_from_file("/tmp/_cover.jpg")
        self.live_on_button = Gtk.Button(label="Live ON")
        self.live_on_button.connect("clicked", self.start_live)
        self.live_off_button = Gtk.Button(label="Live OFF")
        self.live_off_button.set_sensitive(False)
        self.live_off_button.connect("clicked", self.stop_live)
        # vbox contains status and live
        self.vboxlive = Gtk.Box()
        self.vboxlive.set_orientation(Gtk.Orientation.VERTICAL)
        self.vboxlive.set_spacing(10)
        hboxlive = Gtk.Box()
        hboxlive.set_orientation(Gtk.Orientation.HORIZONTAL)
        hboxlive.set_spacing(10)
        hboxlive.pack_start(self.live_on_button, False, False, 0)
        hboxlive.pack_end(self.live_off_button, False, False, 0)

        # Create DrawingArea for video widget
        self.drawingarea = Gtk.DrawingArea()
        #self.drawingarea.set_size_request(400, 300)

        # Needed or else the drawing area will be really small (1px)
        self.drawingarea.set_hexpand(True)
        self.drawingarea.set_vexpand(True)
        #self.vboxlive.add(self.drawingarea)
        self.vboxlive.add(hboxlive)
        self.vboxlive.add(self.live)

        #info
        info = Gtk.Label()
        info.set_text("\nCreate a Timelapse based on RPI camera captures\n")
        self.all_settings_button = Gtk.Button(label="All Settings")
        self.all_settings_button.set_tooltip_text("Configure general options")
        self.all_settings_button.connect("clicked", self.on_set_all_conf)

        # current status
        self.status = Gtk.Label()
        self.status.set_text("Capture OFF")
        self.nb_capture = Gtk.Label()
        self.c_button = Gtk.Button(label="Capture")
        self.c_button.set_tooltip_text("Start capturing timelapse")
        self.c_button.connect("clicked", self.start_capture)
        self.t_button = Gtk.Button(label="Test")
        self.t_button.set_tooltip_text("Test a capture with current setting")
        self.t_button.connect("clicked", self.test_capture)
        self.test_spinner= Gtk.Spinner()
        self.s_button = Gtk.Button(label="Stop")
        self.s_button.set_tooltip_text("Stop to capture timelapse")
        self.s_button.set_sensitive(False)
        self.s_button.connect("clicked", self.stop_capture)

        self.settings_button = Gtk.Button(label="Settings")
        self.settings_button.set_tooltip_text("Configure all options for the Timelapse")
        #https://developer.gnome.org/gnome-devel-demos/stable/tooltip.py.html.en
        # with a tooltip with a given text in the Pango markup language
        #BLAL.set_tooltip_markup("Open an <i>existing</i> file")
        self.settings_button.connect("clicked", self.on_set_image_conf)
        self.settings_button.set_sensitive(True)

        vbox = Gtk.Box()
        vbox.set_orientation(Gtk.Orientation.VERTICAL)
        vbox.set_spacing(10)
        self.add(vbox)

        hboxinfo =Gtk.Box()
        hboxinfo.set_orientation(Gtk.Orientation.HORIZONTAL)
        hboxinfo.set_spacing(10)
        hboxinfo.pack_start(info, True, True, 10)
        hboxinfo.pack_start(self.all_settings_button, True, True, 10)
        frameinfo = Gtk.Frame()
        frameinfo.add(hboxinfo)
        frameinfo.show()

        # vbox contains status and live
        vboxs = Gtk.Box()
        vboxs.set_orientation(Gtk.Orientation.VERTICAL)
        vboxs.set_spacing(10)
        vboxs.pack_start(self.status, True, False, 1)
        vboxs.pack_start(self.test_spinner, False, False, 0)
        self.nb_capture.set_visible(False)
        vboxs.pack_start(self.nb_capture, False, False, 0)

        framestatus = Gtk.Frame()
        framestatus.set_label("Status")
        framestatus.add(vboxs)
        framestatus.show()

        self.framelive = Gtk.Frame()
        self.framelive.set_label("Live (OFF)")
        self.framelive.set_tooltip_text("Live ON/OFF | Capture (ON/OFF)")
        self.framelive.add(self.vboxlive)
        self.framelive.show()

        # create a hboxbut for button line and frame
        hboxbut = Gtk.Box()
        hboxbut.set_spacing(10)
        hboxbut.pack_start(self.settings_button, True, True, 0)
        hboxbut.pack_start(self.t_button, True, True, 0)
        hboxbut.pack_start(self.c_button, True, True, 0)
        hboxbut.pack_end(self.s_button, True, True, 0)
        framebut = Gtk.Frame()
        framebut.set_label("Image Capture Command")
        framebut.add(hboxbut)
        framebut.show()

        self.hboxrender = Gtk.Box()
        self.hboxrender.set_orientation(Gtk.Orientation.HORIZONTAL)
        self.hboxrender.set_spacing(10)
        self.render_button = Gtk.Button(label="Render")
        self.render_button.connect("clicked", self.render_timelapse)
        self.video_settings_button = Gtk.Button(label="Settings")
        self.video_settings_button.connect("clicked", self.on_video_conf)
        self.stop_render_button = Gtk.Button(label="Stop Rendering")
        self.stop_render_button.connect("clicked", self.stop_render)
        self.stop_render_button.set_sensitive(False)
        self.choose_image_button = Gtk.Button(label="Gthumb")
        self.choose_image_button.connect("clicked", self.launch_gthumb)
        self.render_spinner= Gtk.Spinner()
        self.hboxrender.pack_start(self.video_settings_button, False, False, 0)
        self.hboxrender.pack_start(self.render_button, False, False, 0)
        self.hboxrender.pack_start(self.stop_render_button, False, False, 0)
        self.hboxrender.pack_start(self.choose_image_button, False, False, 0)
        self.hboxrender.pack_end(self.render_spinner, True, False, 0)
        self.render_button.set_sensitive(True)
        self.render_button.set_tooltip_text("Create the video based on the capture")
        framerender = Gtk.Frame()
        framerender.set_label("Video Timelapse Command")
        framerender.add(self.hboxrender)
        framerender.show()

        vbox.add(frameinfo)
        vbox.add(framestatus)
        vbox.add(self.framelive)
        vbox.add(framebut)
        vbox.add(framerender)

        self.source_id = 0
        self.count = 0

        if os.path.isfile("/usr/bin/raspistill") == False:
            dialog = Gtk.MessageDialog(
                transient_for=self,
                flags=0,
                message_type=Gtk.MessageType.INFO,
                buttons=Gtk.ButtonsType.OK,
                text="/usr/bin/raspistill is not present, please install it.",
            )
            dialog.run()
            dialog.destroy()

    def launch_gthumb(self, button):
        print("Launch Gthumb")
        if os.path.isfile("/usr/bin/gthumb"):
            config = read_config()
            self.working_dir = config.get('all', 'working_dir')
            cmd = "/usr/bin/gthumb " + self.working_dir
            self.sp = subprocess.Popen(cmd, cwd=self.working_dir, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
        else:
            dialog = Gtk.MessageDialog(
                transient_for=self,
                flags=0,
                message_type=Gtk.MessageType.INFO,
                buttons=Gtk.ButtonsType.OK,
                text="/usr/bin/gthumb is not present, please install it.",
            )
            dialog.run()
            dialog.destroy()

    def start_live(self, button):
       # Create GStreamer pipeline
        self.vboxlive.remove(self.live)
        self.vboxlive.add(self.drawingarea)
        self.framelive.set_label("Live (ON)")
        self.live_on_button.set_sensitive(False)
        self.live_off_button.set_sensitive(True)
        self.c_button.set_sensitive(False)
        config = read_config()
        if config.get('all', 'live_camera_180') == "true":
            self.pipeline = Gst.parse_launch("v4l2src device=" + video_dev + " ! tee name=tee ! queue name=videoqueue ! deinterlace ! videoflip method=2 ! xvimagesink ")
        else:
            self.pipeline = Gst.parse_launch("v4l2src device=" + video_dev + " ! tee name=tee ! queue name=videoqueue ! deinterlace ! xvimagesink ")

        # Create bus to get events from GStreamer pipeline
        bus = self.pipeline.get_bus()
        bus.add_signal_watch()
        bus.connect('message::eos', self.on_eos)
        bus.connect('message::error', self.on_error)

        # This is needed to make the video output in our DrawingArea:
        bus.enable_sync_message_emission()
        bus.connect('sync-message::element', self.on_sync_message)
        self.runvideo()

    def stop_live(self, button):
        self.framelive.set_label("Live (OFF)")
        self.vboxlive.remove(self.drawingarea)
        self.vboxlive.add(self.live)
        self.live_on_button.set_sensitive(True)
        self.live_off_button.set_sensitive(False)
        self.c_button.set_sensitive(True)
        self.pipeline.set_state(Gst.State.NULL)

    def runvideo(self):
        self.show_all()
        self.xid = self.drawingarea.get_property('window').get_xid()
        self.pipeline.set_state(Gst.State.PLAYING)
        #Gtk.main()

    def on_sync_message(self, bus, msg):
        if msg.get_structure().get_name() == 'prepare-window-handle':
            #print('prepare-window-handle')
            msg.src.set_property('force-aspect-ratio', True)
            msg.src.set_window_handle(self.xid)

    def on_eos(self, bus, msg):
        print('on_eos(): seeking to start of video')
        self.pipeline.seek_simple( Gst.Format.TIME, Gst.SeekFlags.FLUSH | Gst.SeekFlags.KEY_UNIT, 0)

    def on_error(self, bus, msg):
        print('on_error():', msg.parse_error())

    def Update_test_rendering(self):
        if self.sptest.poll() is None:
            print("Capture in progress... ")
            return True
        else:
            print("Capture Finished")
            print(self.sptest.stdout)
            print(self.sptest.stderr)
            self.t_button.set_sensitive(True)
            self.test_spinner.stop()
            dialog = Gtk.MessageDialog(
                transient_for=self,
                flags=0,
                message_type=Gtk.MessageType.INFO,
                buttons=Gtk.ButtonsType.OK,
                text="Capture available: " + self.working_dir + "/test.jpg",
            )
            imagename= self.working_dir + "/test." + self.encoding
            if os.path.isfile(imagename):
                self.img = Image.open(imagename)
                sizeh = int(600/self.ratio)
                newimg = self.img.resize((600, sizeh))
                newimg.save(self.working_dir + "/_test." + self.encoding)
                self.live.set_from_file(self.working_dir + "/_test." + self.encoding)

            self.c_button.set_sensitive(True)
            self.t_button.set_sensitive(True)
            self.render_button.set_sensitive(True)
            self.settings_button.set_sensitive(True)
            self.live_on_button.set_sensitive(True)
            self.status.set_text("Capture OFF")
            self.test_spinner.stop()
            dialog.run()
            dialog.destroy()
            return False

    def Update_rendering(self):
        if self.spvideo.poll() is None:
            print("Rendering in progress... ")
            return True
        else:
            print("Rendering Finished")
            print(self.spvideo.stdout)
            print(self.spvideo.stderr)
            self.render_button.set_sensitive(True)
            self.render_spinner.stop()
            dialog = Gtk.MessageDialog(
                transient_for=self,
                flags=0,
                message_type=Gtk.MessageType.INFO,
                buttons=Gtk.ButtonsType.OK,
                text="Video available: " + self.working_dir + "/output.mp4",
            )
            dialog.run()
            dialog.destroy()
            self.stop_render_button.set_sensitive(False)
            return False

    def render_timelapse(self, button):
        #ffmpeg -r 10 -pattern_type glob -i "*.jpg" -s 1920x1080 -vcodec libx264 output.mp4
        print('try to do rendering!')
        config = read_config()
        self.working_dir = config.get('all', 'working_dir')
        self.image_name = config.get('img', 'image_name')
        encoding = config.get('img', 'encoding')
        framerate = config.get('video', 'framerate')
        setpts = config.get('video', 'setpts')
        vcodec = config.get('video', 'vcodec')
        vwidth = config.get('video', 'width')
        vheight = config.get('video', 'height')
        vextra = config.get('video', 'extra')

        #cmd = "ffmpeg -y -r " + framerate + " -filter:v \"setpts=" + setpts + "\" " + " -pattern_type glob -i \"" + self.working_dir + "/" + self.image_name + "*." + encoding + "\" " + " -s " + vwidth + "x" + vheight + " -vcodec " + vcodec + " " + self.working_dir + "/output.mp4"
        cmd = "ffmpeg -y -r " + framerate + " -pattern_type glob -i \"" + self.working_dir + "/" + self.image_name + "*." + encoding + "\" " + " -s " + vwidth + "x" + vheight + " -vcodec " + vcodec + " " + self.working_dir + "/output.mp4"
        if os.path.isfile("/usr/bin/ffmpeg"):
            #num_files = len([f for f in os.listdir(self.working_dir)if os.path.isfile(os.path.join(self.working_dir, f))])
            os.chdir(self.working_dir)
            num_files = len(glob.glob("*." + encoding))
            dialogr = Gtk.MessageDialog(
                transient_for=self,
                flags=0,
                message_type=Gtk.MessageType.WARNING,
                buttons=Gtk.ButtonsType.YES_NO,
                text="Are you Sure you want to render the video?\n  (" + str(num_files) + " images found)\n\n" + cmd,
            )
            response = dialogr.run()
            if response == Gtk.ResponseType.YES:
                # enable rendering
                print(cmd)
                self.spvideo = subprocess.Popen(cmd, cwd=self.working_dir, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
                self.render_button.set_sensitive(False)
                self.stop_render_button.set_sensitive(True)
                self.c_button.set_sensitive(False)
                self.render_spinner.start()
                self.source_id = GLib.timeout_add(3000, self.Update_rendering)
            elif response == Gtk.ResponseType.NO:
                print("Cancel")
            dialogr.destroy()

        else:
            dialog = Gtk.MessageDialog(
                transient_for=self,
                flags=0,
                message_type=Gtk.MessageType.INFO,
                buttons=Gtk.ButtonsType.OK,
                text="/usr/bin/ffmpeg is not present, please install it.",
            )
            dialog.run()
            dialog.destroy()

    def stop_render(self, button):
        dialog = Gtk.MessageDialog(
            transient_for=self,
            flags=0,
            message_type=Gtk.MessageType.WARNING,
            buttons=Gtk.ButtonsType.YES_NO,
            text="Are you Sure you want to stop Rendering in Video?",
        )
        response = dialog.run()
        if response == Gtk.ResponseType.YES:
            GLib.source_remove(self.source_id)
            # TOFIX
            pid = self.spvideo.pid
            #pid += 1
            print(pid)
            #cmd = "kill -9 " + str(pid)
            cmd = "killall ffmpeg"
            proc = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
            rc = proc.wait()
            try:
                outs, errs = proc.communicate(timeout=2)
            except TimeoutExpired:
                proc.kill()
                outs, errs = proc.communicate()
            # enable rendering
            self.c_button.set_sensitive(True)
            self.render_button.set_sensitive(True)
            self.stop_render_button.set_sensitive(False)
            self.render_spinner.stop()
        elif response == Gtk.ResponseType.NO:
            print("Cancel")
        dialog.destroy()

    def Update_info(self, timer):
      c = timer.count + 1
      timer.count = c
      # number of capture start from 1
      nb = c + 1
      print("Update to image image_" + str(c).zfill(4) + '.jpg')
      self.nb_capture.set_text("Number of Captures (every " + str(int(self.timelapse)/1000) +  "s) : " + str(nb))
      imagename= self.working_dir + "/" + self.image_name + str(c).zfill(4) + "." + self.encoding
      if os.path.isfile(imagename):
          self.img = Image.open(imagename)
          sizeh = int(600/self.ratio)
          newimg = self.img.resize((600, sizeh))
          newimg.save(self.working_dir + "/_live_record_rpi." + self.encoding)
          self.live.set_from_file(self.working_dir + "/_live_record_rpi." + self.encoding)
      else:
          self.status.set_text("Cant grab any Images....")
          print("image not ready... bypassing")
      return True

    def test_capture(self, button):
        config = read_config()
        rot= config.get('img', 'rotation')
        self.image_name = config.get('img', 'image_name')
        width = config.get('img', 'width')
        height = config.get('img', 'height')
        quality = config.get('img', 'quality')
        self.working_dir = config.get('all', 'working_dir')
        self.encoding = config.get('img', 'encoding')
        extra = config.get('img', 'extra')
        # be sure working dir exist
        if not os.path.exists(self.working_dir):
            os.makedirs(self.working_dir)
        self.live_on_button.set_sensitive(False)
        self.live_off_button.set_sensitive(False)
        self.vboxlive.remove(self.drawingarea)
        self.vboxlive.add(self.live)
        self.c_button.set_sensitive(False)
        self.settings_button.set_sensitive(False)
        self.t_button.set_sensitive(False)
        self.ratio = float(int(width)/int(height))
        print('Start Capturing a test')
        command = "raspistill" + " -rot " + rot + " -o " + self.working_dir + "/test." + self.encoding + " --width " + width + " --height " + height + " --quality " + quality +  " --encoding " + self.encoding + " -a " + datetime.now().strftime("\"%d/%m/%Y %H:%M:%S\"") + " " + extra
        print(command)
        self.status.set_text("Testing a Capture")
        self.sptest = subprocess.Popen(command, cwd=self.working_dir, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
        self.test_spinner.start()
        self.source_id = GLib.timeout_add(2000, self.Update_test_rendering)

    def start_capture(self, button):
        if self.status.get_text() == "Capture ON":
            dialog = Gtk.MessageDialog(
                transient_for=self,
                flags=0,
                message_type=Gtk.MessageType.INFO,
                buttons=Gtk.ButtonsType.OK,
                text="Capture is already on going...",
                )
            dialog.run()
            dialog.destroy()
        else:
            config = read_config()
            rot= config.get('img', 'rotation')
            #raspistill = config.get('all', 'raspistill')
            self.image_name = config.get('img', 'image_name')
            width = config.get('img', 'width')
            height = config.get('img', 'height')
            quality = config.get('img', 'quality')
            self.encoding = config.get('img', 'encoding')
            self.timelapse = config.get('img', 'timelapse')
            self.working_dir = config.get('all', 'working_dir')
            extra = config.get('img', 'extra')
            # be sure working dir exist
            if not os.path.exists(self.working_dir):
                os.makedirs(self.working_dir)

            dialog = Gtk.MessageDialog(
                transient_for=self,
                flags=0,
                message_type=Gtk.MessageType.WARNING,
                buttons=Gtk.ButtonsType.YES_NO,
                text="All previous images will be deleted from this directory. Are you Sure you want to do this ?\n\n (Current working_dir is: " + self.working_dir + ")" + "\n\n If not please change the working_dir setting to another directory",
            )
            response = dialog.run()
            if response == Gtk.ResponseType.YES:
                cmd = "rm -vf " + self.image_name + "*." + self.encoding
                proc = subprocess.Popen(cmd, cwd=self.working_dir, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
                rc = proc.wait()
                try:
                    outs, errs = proc.communicate(timeout=2)
                except TimeoutExpired:
                    proc.kill()
                    outs, errs = proc.communicate()

                self.live_on_button.set_sensitive(False)
                self.live_off_button.set_sensitive(False)
                self.vboxlive.remove(self.drawingarea)
                self.vboxlive.add(self.live)
                self.c_button.set_sensitive(False)
                self.settings_button.set_sensitive(False)
                self.t_button.set_sensitive(False)
                self.s_button.set_sensitive(True)
                self.nb_capture.set_visible(True)
                print('Start Capturing')
                #command = "raspistill" + " -rot " + rot + " --timelapse " + self.timelapse + " -o " + self.image_name + str(chr(37)) +"04d." + self.encoding + " --width " + width + " --height " + height + " --quality " + quality +  " -t 0" + " --encoding " + self.encoding + " -a " + datetime.now().strftime("\"%d/%m/%Y %H:%M:%S\"") + " " + extra
                command = "raspistill" + " -rot " + rot + " --timelapse " + self.timelapse + " -o " + self.image_name + str(chr(37)) +"04d." + self.encoding + " --width " + width + " --height " + height + " --quality " + quality +  " -t 0" + " --encoding " + self.encoding + " -a " + datetime.now().strftime("\"%d/%m/%Y\"") + " " + extra
                self.status.set_text("Capture ON\n")
                #self.status.set_text("Capture ON\n" + command)
                print(command)
                self.sp = subprocess.Popen(command, cwd=self.working_dir, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
                self.ratio = float(int(width)/int(height))
                # wait for first image
                loadingimg = "/usr/share/icons/gnome/48x48/status/image-loading.png"
                if os.path.isfile(loadingimg):
                    self.live.set_from_file(loadingimg)
                else:
                    print("Missing image:" + loadingimg)

                self.framelive.set_label("Capture (ON)")
                # wait for first image...
                time.sleep(2)
                self.source_id = GLib.timeout_add(int(self.timelapse), self.Update_info, self)

            elif response == Gtk.ResponseType.NO:
                print("cancel")

            dialog.destroy()

    def stop_capture(self,button):
        if self.status.get_text() == "Capture OFF":
            print("Noting to do")
        else:
            print('Stop')
            dialog = Gtk.MessageDialog(
                transient_for=self,
                flags=0,
                message_type=Gtk.MessageType.WARNING,
                buttons=Gtk.ButtonsType.YES_NO,
                text="Are you Sure you want to stop Timelapse Recording?",
            )
            response = dialog.run()
            if response == Gtk.ResponseType.YES:
                GLib.source_remove(self.source_id)
                #pid = self.sp.pid
                #print("Capture Pid: " + str(pid))
                #cmd = "kill -9 " + str(pid) + " " + str(int(pid + 1))
                cmd = "killall raspistill"
                proc = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
                rc = proc.wait()
                try:
                    outs, errs = proc.communicate(timeout=2)
                except TimeoutExpired:
                    proc.kill()
                    outs, errs = proc.communicate()
                self.status.set_text("Capture OFF")
                self.framelive.set_label("Live (OFF)")
                self.c_button.set_sensitive(True)
                self.settings_button.set_sensitive(True)
                self.s_button.set_sensitive(False)
                self.t_button.set_sensitive(True)
                self.live_on_button.set_sensitive(True)
                # enable rendering
                self.render_button.set_sensitive(True)
                self.stop_render_button.set_sensitive(False)
            elif response == Gtk.ResponseType.NO:
                print("Cancel")

            dialog.destroy()

    def on_set_image_conf(self, widget):
        dialog = DisplayImageConf(self)

    def on_set_all_conf(self, widget):
        dialog = DisplayAllConf(self)

    def on_video_conf(self, widget):
        print("plop")
        dialog = DisplayVideoConf(self)

# MAIN
window = MainBox()
window.connect("destroy", Gtk.main_quit)
window.show_all()
Gtk.main()


# https://www.hackerrank.com/challenges/extra-long-factorials/problem?h_r=next-challenge&h_v=zen
def extraLongFactorials(n):
    i = n
    for q in range(1, n):
        i *= (n - q)
    return print(i)

a = extraLongFactorials(30)
print(a)


import torch
import torch.nn.functional as F

with open('names.txt', 'r') as file:
    names = [x.replace('\n', '') for x in file.readlines()]

b = torch.zeros((27, 27), dtype=torch.int32)
chars = sorted(list(set(''.join(names))))

char_to_index = {c: i + 1 for i, c in enumerate(chars)}
char_to_index['.'] = 0

index_to_char = {i + 1: c for i, c in enumerate(chars)}
index_to_char[0] = '.'

xs, ys = [], []
for name in names[:]:
    chs = ['.'] + list(name) + ['.']
    for ch1, ch2 in zip(chs[:], chs[1:]):
        index1 = char_to_index[ch1]
        index2 = char_to_index[ch2]
        b[index1, index2] += 1
        xs.append(index1)
        ys.append(index2)
xs = torch.tensor(xs)
ys = torch.tensor(ys)
num = xs.nelement()

generator = torch.Generator().manual_seed(57373543)
hidden_layer = torch.randn((27, 27), generator=generator, requires_grad=True)

for _ in range(100):
    input_layer = F.one_hot(xs, num_classes=27).float()
    logit = input_layer @ hidden_layer
    counts = logit.exp()
    probs = counts / counts.sum(1, keepdim=True)
    loss = -probs[torch.arange(num), ys].log().mean()
    print(loss.item())
    hidden_layer.grad = None
    loss.backward()

    hidden_layer.data += -1 * hidden_layer.grad


from django.db import models

class ArticleStatus(object):
    FOR_REVIEW = 'for-review'
    APPROVED = 'approved'
    OPEN = 'open'

    CHOICES = (
        (FOR_REVIEW, 'For-review'),
        (APPROVED, 'Approved'),
        (OPEN, 'Open'),
    )

class Article(models.Model):
    assigned_to = models.ForeignKey(
        'accounts.User',
        null=True,
        blank=True,
        on_delete=models.CASCADE,
        related_name='assigned_articles'
    )
    approved_by = models.ForeignKey(
        'accounts.User',
        null=True,
        blank=True,
        on_delete=models.CASCADE,
        related_name='approved_articles'
    )
    headline = models.CharField(max_length=255, null=True, blank=True)
    content = models.TextField()
    docs_link = models.URLField(null=True, blank=True)
    status = models.CharField(max_length=50, choices=ArticleStatus.CHOICES)


import time
import os
import csv

class App():
    def __init__(self,count):
        self.save=[('now','electricity')]
        self.count=count

    def onetest(self):
        cmd="adb shell dumpsys battery"
        electr=os.popen(cmd)
        # print(list(electr))
        for line in list(electr):
            if "level" in line:
                ele_data=line.split(" ")[3].replace('\n','')
                now=time.strftime("%Y-%m-%d %H:%M:%S")
                # print(ele_data)
                self.save.append((now,ele_data))
                print(self.save)

    def saveData(self):
        with open("../data/electricity_test.csv","a",newline='') as f:
            writer=csv.writer(f)
            writer.writerows(self.save)

    def run(self):
        for i in range(self.count):
            self.onetest()
            time.sleep(2)

# 本文件自己运行是执行if下代码，
# 别的文件调用时不执行if下代码。
if __name__ == "__main__":
    app=App(2)
    app.run()
    app.saveData()


import cv2

cap = cv2.VideoCapture('C:/Users/tanay/Downloads/tbbt.mp4')
face_cascade = cv2.CascadeClassifier(cv2.data.haarcascades +'haarcascade_frontalface_default.xml')

while True:

    ret, frame = cap.read()
    gray = cv2.cvtColor(frame, 0)
    faces = face_cascade.detectMultiScale(gray, 1.1, 4)
    count = 0
    for (x, y, w, h) in faces:
        c = 0
        cv2.rectangle(frame, (x, y), (x + w, y + h), (255, 0, 0), 2)

        count = count + 1

        # Display the box and faces
        cv2.putText(frame, 'face num' + str(count), (x - 10, y - 10),
                    cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 0, 255), 2)
        print('box dimension and no. of faces',(x, y, w, h), count)

    # Display the resulting frame
    cv2.imshow('frame', frame)

    k = cv2.waitKey(30) & 0xff
    if k == 27:
        break

cap.release()


string_to_search=input("Enter the String: ")
before=int(input("How many lines to print before string match ? "))
after=int(input("How many lines to print after string match ? "))
file_to_search=input("Enter the file to search: ")

def search_string(string_to_search, before, after, file_to_search):
	with open(file_to_search) as f:
		all_lines = f.readlines()
		last_line_number=len(all_lines)
		for current_line_no, current_line in enumerate(all_lines):
			if string_to_search in current_line:
				start_line_no=max(current_line_no - before, 0)
				end_line_no=min(last_line_number, current_line_no+after+1)
				for i in range(start_line_no, current_line_no):print(all_lines[i])
				for i in range(current_line_no, end_line_no):print(all_lines[i])
				break
search_string(string_to_search, before, after, file_to_search)


import pandas as pd
from openpyxl import load_workbook

# Leer el archivo Excel original
df = pd.read_excel('202_Rpa_32569-170523407-60001.xlsx')

# Realizar las modificaciones necesarias al DataFrame
if "ID Suscription" not in df.columns:
    df.insert(loc=12, column="ID Suscription", value="")
df = df.rename(columns={"Número cuenta bancaria": "Número de cuenta bancaria"})
df.iloc[1:, [13, -2]] = ""

# Crear un archivo Excel modificado
writer = pd.ExcelWriter('ReporteNomina_modificado.xlsx', engine='openpyxl')
# Cargar el libro de trabajo del archivo Excel original
writer.book = load_workbook('202_Rpa_32569-170523407-60001.xlsx')
# Copiar el formato de las hojas del libro de trabajo original al nuevo archivo
for sheetname in writer.book.sheetnames:
    sheet = writer.book[sheetname]
    reader = pd.read_excel('202_Rpa_32569-170523407-60001.xlsx', sheet_name=sheetname)
    for idx, row in reader.iterrows():
        for cell in sheet[idx+1]:
            cell._style = row[cell.column_letter].style

# Guardar el DataFrame modificado en el nuevo archivo Excel
df.to_excel(writer, index=False, sheet_name='Sheet1')
writer.save()


from collections import defaultdict, Counter
from . import db

def lookup_background_size(ignore_genes=None, alg=None, bmr_table=None):
    """Get background genome size sizes. Optional ignore_genes iterable.

    - Uses entrez_length table built from genes in msigdb (pathway_genes).
    - length_bp is cds length. or rna length for noncoding rna.
    - effective_bp is length_bp scaled by noncoding mutation rate (mutations/Mb)
        from mutsigcv paper, table s4 and s5. floor=1.5, ceiling=15.

    Args:
        ignore_genes (iterable): contains gene symbols to ignore.
        alg (str): specifies algorithm. ['gene_count', 'gene_length',
            or 'bmr_length']
        bmr_table: specify table name for custom bmr, else use
            entrez_length table. only applies to 'bmr_length' algorithm.

    Return:
        int: length. Number of bases for length, else number of genes.
    """
    if alg is None:
        raise Exception("Must specify algorithm type.")
    if alg not in ['gene_count', 'gene_length', 'bmr_length']:
        raise ValueError("Algorithm must be gene_count, gene_length, "
                         "or bmr_length.")
    if ignore_genes:
        genes_str = repr(tuple(ignore_genes)).replace(",)", ")")
        genes_str = "WHERE hugo_symbol NOT IN {}".format(genes_str)
    else:
        genes_str = ""
    table_name = bmr_table if bmr_table else 'refs.entrez_length'
    if alg == 'bmr_length':
        field_str = "sum(effective_bp)"
    elif alg == 'gene_length':
        field_str = "sum(length_bp)"
    else:
        field_str = "count(*)"
    cmd = """SELECT {field_str} FROM {table} {genes_str};""".format(
        field_str=field_str, table=table_name, genes_str=genes_str)

    result = db.session.execute(cmd)
    row_count = result.rowcount
    if row_count != 1:
        print("Background size lookup failed.")
        return
    row = result.fetchone()
    background_size = int(row[0])

    return background_size

def lookup_path_sizes(ignore_genes=None):
    """Get pathway sizes. Optional ignore_genes iterable."""
    if ignore_genes:
        genes_string = repr(tuple(ignore_genes)).replace(",)", ")")
        genes_string = "WHERE symbol NOT IN {}".format(genes_string)
    else:
        genes_string = ""
    cmd = """SELECT path_id, count(DISTINCT entrez_id)
    FROM refs.pathway_gene_link pgl
    INNER JOIN refs.ncbi_entrez n ON pgl.entrez_id = n.geneId
    {genes_string} GROUP BY path_id;""".format(genes_string=genes_string)
    size_dict = dict()

    result = db.session.execute(cmd)
    row_count = result.rowcount
    if not row_count:
        print("No pathways found.")
        return size_dict
    for row_no in range(row_count):
        row = result.fetchone()
        size_dict[row[0]] = row[1]
    return size_dict

def lookup_path_lengths(ignore_genes=None, alg=None, bmr_table=None):
    """Get bp length for each pathway, with optional exclude genes."""
    if alg is None:
        raise Exception("Must specify algorithm type.")
    if alg not in ['gene_length', 'bmr_length']:
        raise ValueError("Algorithm must be gene_length, or bmr_length.")
    if ignore_genes:
        genes_string = repr(tuple(ignore_genes)).replace(",)", ")")
        genes_string = "WHERE hugo_symbol NOT IN {}".format(genes_string)
    else:
        genes_string = ""
    table_name = bmr_table if bmr_table else 'refs.entrez_length'
    field_str = 'effective_bp' if alg == 'bmr_length' else 'length_bp'
    cmd = """SELECT path_id, sum({field_str}) AS bp FROM {table} l
        INNER JOIN refs.pathway_gene_link pgl ON l.entrez_id = pgl.entrez_id
        {genes_string}
        GROUP BY pgl.path_id;""".format(genes_string=genes_string,
                                        field_str=field_str, table=table_name)
    len_dict = dict()

    result = db.session.execute(cmd)
    row_count = result.rowcount
    if not row_count:
        print("No pathways found.")
        return len_dict
    for i in range(row_count):
        row = result.fetchone()
        len_dict[row[0]] = row[1]
    return len_dict

def lookup_patient_counts(table_name, ignore_genes):
    """Get patient gene counts."""

    if(ignore_genes):
        genes_string = repr(tuple(ignore_genes)).replace(",)", ")")
        genes_string = "WHERE hugo_symbol NOT IN {}".format(genes_string)
    else:
        genes_string = ""
    cmd = """SELECT patient_id, count(DISTINCT entrez_id)
              FROM {table_name} {genes_string} GROUP BY patient_id;"""\
        .format(table_name=table_name, genes_string=genes_string)

    patient_size_dict = dict()
    result = db.session.execute(cmd)
    row_count = result.rowcount
    if not row_count:
        print("No pathways found.")
        return patient_size_dict
    for row_no in range(row_count):
        row = result.fetchone()
        patient_size_dict[row[0]] = row[1]

    return patient_size_dict

def lookup_hypermutated_patients(table_name, cutoff=500):
    """Get patient ids for patients with >500 mutations (or specified cutoff)."""
    cmd = """SELECT patient_id FROM {table_name}
              GROUP BY patient_id HAVING count(*)>{cutoff};"""\
        .format(table_name=table_name, cutoff=cutoff)
    patient_list = []
    result = db.session.execute(cmd)
    for row in result:
        patient_list.append(row[0])
    return patient_list

def lookup_patient_lengths(table_name, ignore_genes):
    """Get patient bp lengths."""
    if(ignore_genes):
        genes_string = repr(tuple(ignore_genes)).replace(",)", ")")
        genes_string = "WHERE m.hugo_symbol NOT IN {}".format(genes_string)
    else:
        genes_string = ""
    cmd = """SELECT patient_id, count(*)
      FROM {table_name} m
      {genes_string} GROUP BY patient_id;"""\
        .format(table_name=table_name, genes_string=genes_string)
    patient_len_dict = dict()
    result = db.session.execute(cmd)
    for row in result:
        patient_len_dict[row[0]] = row[1]
    return patient_len_dict

def count_patients(table_name):
    """Get patient count for project."""
    cmd = """SELECT count(distinct patient_id) FROM {table_name};"""\
        .format(table_name=table_name)
    patient_count = None
    result = db.session.execute(cmd)
    row_count = result.rowcount
    if not row_count == 1:
        print("Non single result from patient count query.")
        return patient_count
    row = result.fetchone()
    patient_count = row[0]
    return patient_count

def build_path_patient_dict(table_name, ignore_genes):
    """Returns dict. Maps path_id (int) -> {Set of patient_ids}."""
    if ignore_genes:
        genes_string = repr(tuple(ignore_genes)).replace(",)", ")")
        genes_string = "WHERE hugo_symbol NOT IN {}".format(genes_string)
    else:
        genes_string = ""
    cmd = """SELECT pgl.path_id, patient_id FROM
            (SELECT DISTINCT patient_id, entrez_id FROM {table_name}
             {genes_string}) pg
            INNER JOIN
            refs.pathway_gene_link pgl ON pg.entrez_id = pgl.entrez_id;"""\
        .format(table_name=table_name, genes_string=genes_string)
    path_patient_dict = dict()
    result = db.session.execute(cmd)
    row_count = result.rowcount
    if not row_count:
        print("No patient-pathway pairs found.")
        return path_patient_dict
    for row in result:
        path_id = row[0]
        patient_id = row[1]
        if path_id in path_patient_dict:
            path_patient_dict[path_id].add(patient_id)
        else:
            path_patient_dict[path_id] = {patient_id}
    return path_patient_dict

def fetch_path_ids_interest_genes(interest_genes):
    """Get pathway ids containing genes in (possibly empty) interest set."""
    rows = None
    all_path_ids = list()
    if interest_genes:
        genes_string = repr(tuple(interest_genes))
        genes_string = genes_string.replace(",)", ")")
        genes_string = "WHERE symbol IN " + genes_string
    else:
        genes_string = ""
    # GET pway_size
    cmd1 = """SELECT distinct path_id FROM refs.pathway_gene_link pgl
        INNER JOIN (SELECT geneId FROM refs.ncbi_entrez
            {genes_string}) g
        ON pgl.entrez_id = g.geneId ORDER BY path_id;""".format(
        genes_string=genes_string)
    result = db.session.execute(cmd1)
    rowCount = result.rowcount
    if not rowCount:
        raise Exception(
            "Result contains %g rows Ids for pathway lookup." % rowCount)

    # rows is [[id,name],[id,name],...]
    for row in result:
        all_path_ids.append(int(row[0]))
    return all_path_ids

def get_pathway_name_dict():
    """Gets name for all pathways, stored in dict: pathid -> pathname."""
    rows = None
    pathway_dict = dict()
    # GET pway_size
    cmd1 = """SELECT p.path_id, pathway_name FROM refs.pathways p
    INNER JOIN
    (SELECT DISTINCT path_id FROM refs.pathway_gene_link) l
    ON p.path_id = l.path_id;"""
    result = db.session.execute(cmd1)
    row_count = result.rowcount
    if not row_count > 1:
        raise Exception(
            "Result contains %g rows Ids for pathway lookup."
            % row_count)
    # rows is [[id,name],[id,name],...]
    for pair in result:
        path_id = int(pair[0])
        path_name = pair[1]
        pathway_dict[path_id] = path_name
    return pathway_dict

def get_pway_lenstats_dict(mutation_table, ignore_genes):
    """Get length stats for all mutated pathways."""
    rows = None
    pathway_lengths = dict()
    genes_string = ""
    if ignore_genes:
        genes_string = repr(tuple(ignore_genes)).replace(",)", ")")
        genes_string = "WHERE m.hugo_symbol NOT IN {}".format(genes_string)

    cmd1 = """SELECT g.path_id,
        cast(lmin/1000 AS DECIMAL(10,1)) AS `min`,
            group_concat(DISTINCT CASE e.`length_bp` WHEN lmin THEN m.hugo_symbol
                ELSE NULL END ORDER BY m.hugo_symbol SEPARATOR ', ') AS min_gene,
        cast(lmax/1000 AS DECIMAL(10,1)) AS `max`,
            group_concat(DISTINCT CASE e.`length_bp` WHEN lmax THEN m.hugo_symbol
                ELSE NULL END ORDER BY m.hugo_symbol SEPARATOR ', ') AS max_gene,
                lavg, lvar
         FROM (SELECT DISTINCT entrez_id, hugo_symbol FROM `{mutation_table}`) m
         INNER JOIN refs.entrez_length e ON m.entrez_id = e.entrez_id
        INNER JOIN refs.`pathway_gene_link` pgl ON e.entrez_id = pgl.entrez_id
        INNER JOIN # pway_stats
        (SELECT path_id,
        min(length_bp) AS `lmin`,
        max(length_bp) AS `lmax`,
        cast(AVG(length_bp)/1000 AS DECIMAL(10,1)) AS `lavg`,
        cast(var_samp(length_bp/1000) AS DECIMAL(10,1)) AS `lvar`
         FROM (SELECT DISTINCT hugo_symbol, entrez_id FROM `{mutation_table}`) m
         INNER JOIN refs.entrez_length e ON m.entrez_id = e.entrez_id
            INNER JOIN refs.`pathway_gene_link` pgl ON e.entrez_id = pgl.entrez_id
            {exclude_str} GROUP BY path_id) g ON g.path_id = pgl.`path_id`
            {exclude_str} GROUP BY g.path_id;"""\
        .format(mutation_table=mutation_table, exclude_str=genes_string)
    result = db.session.execute(cmd1)
    row_count = result.rowcount
    if not row_count > 1:
        raise Exception(
            "Result contains %g rows Ids for pathway lookup."
            % row_count)
    # rows is [[id,min,max,avg],[id,min,max,avg],...]
    for temp_lengths in result:
        path_id = int(temp_lengths[0])
        len_min = str(temp_lengths[1])
        gene_min = str(temp_lengths[2])
        len_max = str(temp_lengths[3])
        gene_max = str(temp_lengths[4])
        len_avg = str(temp_lengths[5])
        len_var = str(temp_lengths[6])
        pathway_lengths[path_id] = (len_min, gene_min, len_max, gene_max,
                                    len_avg, len_var)
    return pathway_lengths

def fetch_path_info_global():
    """Get url, brief description and contributor as tuple."""
    url_row = None
    cmd = "SELECT path_id, info_url, `description_brief`, contributor " \
          "FROM refs.pathways;"
    info_dict = dict()
    result = db.session.execute(cmd)
    row_count = result.rowcount
    if not row_count > 1:
        raise Exception("Failed info lookup for all pathways.")
    # rows is [[id,url,desc,contrib],[id,url,desc,contrib],...]
    for row in result:
        path_id = row[0]
        url = row[1]
        desc = row[2]
        contrib = row[3]
        info_dict[path_id] = dict(url=url, desc=desc, contrib=contrib)
    return info_dict

def get_gene_combs_hit(table_name):
        """Gets patient-pathway gene overlap info from databse.
        Only called by _populate_exclusive_cooccurring.
        """
        rows = None
        gene_lists = list()
        path_genes_dict = dict()

        cmd_maxlen = "SET group_concat_max_len = 10000;"
        cmd = """SELECT DISTINCT path_id, symbols FROM
            (
            # PATH, HUGO PAIRS in pathway of interest.
            SELECT path_id, group_concat(DISTINCT hugo_symbol
            ORDER BY hugo_symbol SEPARATOR ',') AS symbols
            FROM {table} t
            INNER JOIN refs.`pathway_gene_link` pgl
            ON t.entrez_id = pgl.entrez_id
            GROUP BY path_id, patient_id
            ) g;""". \
            format(table=table_name)
        db.session.execute(cmd_maxlen)
        result = db.session.execute(cmd)
        for row in result:
            path_id = row[0]
            gene_list = row[1].split(',')
            if path_id in path_genes_dict:
                path_genes_dict[path_id].append(gene_list)
            else:
                path_genes_dict[path_id] = [gene_list]
        # prev returned list of lists, now dictionary with list of lists as vals
        return path_genes_dict

def get_gene_counts(table_name):
        """ Fetch dictionary of dictionaries: path -> gene -> patients with mutation.
        Dictionary may be empty if no pathway genes were mutated."""
        rows = None
        path_gene_dict = defaultdict(dict)
        cmd0 = """SET SESSION group_concat_max_len = 30000;"""
        # HUGO LIST AND PATIENT COUNTS
        cmd2 = """SELECT path_id, hugo_symbol, count(DISTINCT patient_id)
            AS n_patients, GROUP_CONCAT(DISTINCT patient_id) AS patients
            FROM {table} t
            # gene subset in pathway of interest
            INNER JOIN refs.`pathway_gene_link` pgl
            ON t.entrez_id = pgl.entrez_id
            GROUP BY path_id, hugo_symbol;""" \
            .format(table=table_name)
        db.session.execute(cmd0)
        result = db.session.execute(cmd2)
        row_count = result.rowcount
        if not row_count:
            # NO GENES MUTATED. n_effective < n_pathway
            return path_gene_dict
        for row in result:
            path_id = row[0]
            gene = row[1]
            coverage = int(row[2])
            patient_names = row[3].split(',')
            if not len(patient_names) == coverage:
                raise Exception(
                    "Pathway coverage query gives inconsistent " +
                    "patient counts and patient names; truncated "
                    "group_concat?")
            path_gene_dict[path_id][gene] = patient_names

        # OLD: count_dict : gene -> n_patients; total_patients
        # self.geneMatrix.add_gene_patients(gene, patient_names)
        return path_gene_dict

def get_annotation_dict(table_name):
    """ Fetch annotation dictionary: (hugo, patient) -> annot."""
    annot_dict = dict()
    cmd0 = """SET SESSION group_concat_max_len = 30000;"""
    # HUGO LIST AND PATIENT COUNTS
    cmd1 = """SELECT hugo_symbol, patient_id, GROUP_CONCAT(DISTINCT annot) AS annot
        FROM {table} t
        GROUP BY patient_id, hugo_symbol;""" \
        .format(table=table_name)

    db.session.execute(cmd0)
    result = db.session.execute(cmd1)
    for row in result:
        hugo, patient, annot = row
        annot_list = annot.split(',')
        # shorten annotation if necessary
        if len(annot_list) > 1:
            c = Counter(annot_list)  # Counter({'a': 5, 's': 1})
            annot = c.most_common()[0][0] + '+'
        annot_dict[(hugo, patient)] = annot
    return annot_dict


#coding: utf-8
from diferenças_divididas import difdiv, achar_intervalo
from numpy import zeros, linalg

def interpolação(X, Y, Z, tipo = 'natural'):

	n = len(X)		#n = número de pontos
	DD, H = difdiv(X, Y)
	D = zeros(n)
	M = zeros((n, n))
	B = zeros(n - 1)
	C = zeros(n - 1)
	M[0][0] = 1
	M[n-1][n-1] = 1

	for i in range(1, n - 1):
		M[i][i-1] = H[i-1]
		M[i][i] = 2 * H[i-1] * H[i]
		M[i][i+1] = H[i]

	E = [0] + [6 * (DD[i] - DD[i-1]) for i in range(1, n - 1)] + [0]
	if tipo == 'natural':
		E[0] = 0
		E[-1] = 0
	elif tipo == 'not-a-knot':
		E[0] = copy(E[1])
		E[-1] = copy(E[n])
	elif tipo == 'blablabla':
		E[0] = 'outroblalala'
		E[-1] = 'outroblalala2'

	S = linalg.solve(M, E)

	for i in range(n - 1):
		B[i] = (DD[i] - S[i+1] + 2 * S[i] * H[i]) / 2
		C[i] = S[i] / 2
		D[i] = (S[i+1] - S[i]) / (6 * H[i])

	print('Equação geral genérica: S(x) = ai + bi(x - xi) + ci(x - xi)² + di(x - xi)³')
	res = list()
	i = 0
	for z in Z:
		e = achar_intervalo(X, z)
		i += 1
		print('Equação geral para z{0:2d}: S({1:2f}) = {2:2f} + {3:2f}({1:2f} - {4:2f}) + {5:2f}({1:2f} - {4:2f})² + {6:2f}({1:2f} - {4:2f})³'.format(i, z, Y[e], B[e], X[e], C[e], E[e]))
		cont = z - X[e]
		r = Y[e] + B[e] * cont + C[e] * cont ** 2 + D[e] * cont ** 3
		print('Resultado: ', r)
		res.append(r)
	return res


__author__ = 'paltamura'

import sys
import gc

import pandas as pd
import numpy as np

sys.path.append("E:\\Models\\retrosheets\\data\\")
from toolkit import compress_columns

#
# ---- ---- ----      ---- ---- ----      ---- ---- ----      ---- ---- ----
# Methods

def slump_metrics(df, metrics_cols, threshholds):

    """
    compares season_to_date (STDT) average with hits, strikeouts to
    the rolling_10_games (rolling10games) average

    PARAMETERS
    ----------
    df: DataFrame
        DataFrame containing game level data for players
    thresh: float
        Percent that needs to be dipped below to get labeled slump

    """

    #
    # ---- ---- ----
    # Assertions
    assert type(df) == pd.DataFrame
    assert type(metrics_cols) == list
    assert type(threshholds) == list

    # Establish table with just merge key to merge metrics on to and return
    df_return = df.loc[:, ['mlb_season', 'batter']].\
        drop_duplicates(inplace=False)

    #
    # ---- ---- ----
    # Get season_to_date (STDT) average for metrics_cols
    for col in metrics_cols:

        # Get threshhold
        thresh = threshholds[metrics_cols.index(col)]

        # Perform initial groupby to get cumulative sum of current metric
        df_t = df.sort_values(
            by=['mlb_season', 'batter', 'game_date'],
            ascending=True,
            inplace=False
        )
        df_t = df_t.groupby(
            ['mlb_season', 'batter', 'game_date', 'game_id'],
            as_index=False).agg({col: np.sum})

        # INCREMENTAL MEAN
        # Create season_to_date metric for current metric
        df_t['{}_STDT'.format(col)] = (
            df_t[col].cumsum() / pd.Series(np.arange(1, len(df_t)+1), df.index)
        )

        # Flag where below threshold
        df_t['{}_STDT_{}pctl'.format(col, str(thresh))] = \
            df_t.groupby(['mlb_season', 'batter'])\
                ['{}_STDT'.format(col)].transform(
                lambda x: np.percentile(x, thresh)
            )

        # INITIAL FLAG
        # Flag games spent in slump
        df_t['in_{}_slump'.format(col)] = 0
        if col == 'hits':
            msk = (
                df_t['{}_STDT'.format(col)] <=
                df_t['{}_STDT_{}pctl'.format(col, str(thresh))]
            )
        elif col == 'strikeouts':
            msk = (
                df_t['{}_STDT'.format(col)] >=
                df_t['{}_STDT_{}pctl'.format(col, str(thresh))]
            )
        else:
            raise
        df_t.loc[msk, 'in_{}_slump'.format(col)] = 1

        # Create counter and increment (nstead of using integer index in mask)
        df_t['counter'] = 1
        df_t['increment_index'] = df_t.loc[:, 'counter'].cumsum()
        df_t.drop(labels=['counter'], axis=1, inplace=True)

        # FLAG FIRST INSTANCE OF SLUMP
        msk = (
            (df_t['in_{}_slump'.format(col)].shift(1) == 0)
            &
            (df_t['in_{}_slump'.format(col)] == 1)
        )
        df_t.loc[msk, '{}_slump_day_1'.format(col)] = df_t['increment_index']

        # if not equal to 0, match above
        msk = (
            (df_t['in_{}_slump'.format(col)] == 1)
            &
            (df_t['{}_slump_day_1'.format(col)].shift(1).notnull())
        )
        df_t.loc[msk, '{}_slump_day_1'.format(col)] = \
            df_t['{}_slump_day_1'.format(col)].shift(1)
        df_t.rename(
            columns={'{}_slump_day_1'.format(col): '{}_slump_id'.format(col)},
            inplace=True
        )

        # replace non-slump-days with null
        df_t.sort_values(
            by=['mlb_season', 'batter', 'game_date'],
            ascending=True,
            inplace=True)
        df_t.head(2000).to_csv(
            'E:\\slump_id_made_pregroupby{}.csv'.format(col)
        )

        # Prep table to add back on
        df_addback = df_t.groupby(
            ['mlb_season', 'batter'],
            as_index=False
        ).agg({'{}_slump_id'.format(col): [pd.Series.nunique, 'count']})
        df_addback = compress_columns(df_addback)
        df_addback.rename(
            columns={'nunique': '{}_slump_count'.format(col),
                     'count': '{}_slump_days'.format(col)},
            inplace=True
        )
        df_addback.loc[:, '{}_slump_avg_len'.format(col)] = (
            df_addback['{}_slump_days'.format(col)] /
            df_addback['{}_slump_count'.format(col)]
        )

        # Merge
        pre_len = len(df_return)
        df_return = pd.merge(
            df_return,
            df_addback,
            how='left',
            on=['mlb_season', 'batter']
        )
        if len(df_return) != pre_len:
            raise Exception("Merge of type \'left\' has added rows.")

        del df_addback
        gc.collect()

    return df_return

def streak_metrics(df, thresh=.85):
    """

    :return:
    """

    return ""

if __name__ == "__main__":
    pass


def main():
    print(is_anagram('I am Lord Voldemort', 'Tom Marvolo Riddle'))

def is_anagram(str1,str2,i=0):
    s1 = str1.replace(" ","").lower()
    s2 = str2.replace(" ","").lower()

    if len(s1) == i:
        return True
    elif len(s1) == len(s2):
        if s1.count(s1[i]) == s2.count(s1[i]):
            return is_anagram(s1,s2,i+1)
    return False

if __name__ == '__main__':
    main()


class CoffeeMachine:
    total_water = 400
    total_milk = 540
    total_beans = 120
    total_cups = 9
    total_money = 550

    def action_choice(self):
        action = ''
        while action != 'exit':
            action = input("Write action (buy, fill, take, remaining, exit): ")
            if action == "buy":
                self.coffee_choice = input("What do you want to buy? 1 – espresso, 2 – latte, 3 – cappuccino, back - to main menu:")
                if self.coffee_choice == "back":
                    continue
                else:
                    if self.enough(self.coffee_choice) == True:
                        print("I have enough resources, making you a coffee!")
                        if self.coffee_choice == "1":
                            self.total_water -= 250
                            self.total_beans -= 16
                            self.total_money += 4
                            self.total_cups -= 1
                        elif self.coffee_choice == "2":
                            self.total_water -= 350
                            self.total_milk -= 75
                            self.total_beans -= 20
                            self.total_money += 7
                            self.total_cups -= 1
                        elif self.coffee_choice == "3":
                            self.total_water -= 200
                            self.total_milk -= 100
                            self.total_beans -= 12
                            self.total_money += 6
                            self.total_cups -= 1
            elif action == "fill":
                add_water = int(input("Write how many ml of water do you want to add:"))
                self.total_water += add_water
                add_milk = int(input("Write how many ml of milk do you want to add:"))
                self.total_milk += add_milk
                add_beans = int(input("Write how many grams of beans do you want to add:"))
                self.total_beans += add_beans
                add_cups = int(input("Write how many disposable cups of coffee do you want to add:"))
                self.total_cups += add_cups
            elif action == "take":
                print(f"I gave you ${self.total_money}")
                self.total_money = 0
            elif action == "remaining":
                print(f"The coffee machine has\n"
                      f"{self.total_water} ml of water\n"
                      f"{self.total_milk} ml of milk\n"
                      f"{self.total_beans} g of coffee beans\n"
                      f"{self.total_cups} of disposable cups\n"
                      f"{self.total_money} of money")

    def enough(self, coffee_choice):
        self.coffee_choice = coffee_choice
        items_needed = set()
        if coffee_choice == "1":
            if self.total_water >= 250:
                items_needed.add("water")
            if self.total_beans >= 16:
                items_needed.add("beans")
            if self.total_cups >= 1:
                items_needed.add("cups")
            expected = {"water", "beans", "cups"}
            lack = ', '.join(expected.difference(items_needed))
            if expected == items_needed:
                return True
            else:
                print(f"Sorry, not enough {lack}!")
        elif coffee_choice == "2":
            if self.total_water >= 350:
                items_needed.add("water")
            if self.total_beans >= 20:
                items_needed.add("beans")
            if self.total_milk >= 75:
                items_needed.add("milk")
            if self.total_cups >= 1:
                items_needed.add("cups")
            expected = {"water", "beans", "cups", "milk"}
            lack = ', '.join(expected.difference(items_needed))
            if expected == items_needed:
                return True
            else:
                print(f"Sorry, not enough {lack}!")
        elif coffee_choice == "3":
            if self.total_water >= 200:
                items_needed.add("water")
            if self.total_beans >= 12:
                items_needed.add("beans")
            if self.total_milk >= 100:
                items_needed.add("milk")
            if self.total_cups >= 1:
                items_needed.add("cups")
            expected = {"water", "beans", "cups", "milk"}
            lack = ', '.join(expected.difference(items_needed))
            if expected == items_needed:
                return True
            else:
                print(f"Sorry, not enough {lack}!")


from enum import Enum
import json
import os
from http.client import HTTPResponse
from requests import Response
import sqlite3
import time

from support.data_classes import DataType

class SQLiteCache:
    DB_NAME = 'cache.sqlite3'

    class DBTable(Enum):
        JSON_CACHE = "json_cache"
        CSV_CACHE = "csv_cache"

    class ResponseTypeError(Exception):
        def __init__(self, response):
            res_type = type(response)
            print(f"Error: unexpected response type. Type is: {res_type}")

    class DataTypeError(Exception):
        def __init__(self, data_type):
            data_type = type(data_type)
            print(f"Error: unexpected data type. Type is: {data_type}")

    def get_response_info(self, res):
        if isinstance(res, Response):
            table = self.DBTable.JSON_CACHE.value
            data = json.dumps(res.json())

        elif isinstance(res, HTTPResponse):
            table = self.DBTable.CSV_CACHE.value
            data = res.read()

        else:
            raise self.ResponseTypeError(res)

        return {"table": table, "data": data}

    def get_table(self, data_type):
        if data_type is DataType.JSON:
            return self.DBTable.JSON_CACHE.value
        if data_type is DataType.CSV:
            return self.DBTable.CSV_CACHE.value

    def __init__(self):
        """Create new database and db tables if not done yet. Initialize
        connection and cursor objects.
        """
        db_created = os.path.isfile(self.DB_NAME)
        self.con = sqlite3.connect(self.DB_NAME)
        self.cur = self.con.cursor()

        if not db_created:
            self.cur.execute("""CREATE TABLE json_cache
                                (url text, time float, data json)""")
            self.cur.execute("""CREATE TABLE csv_cache
                                            (url text, time float, data text)""")
            self.con.commit()

    def create_entry(self, res):
        """Store response object in SQL cache.

        Args:
            res (Union[requests.models.Response, http.client.HTTPResponse]):
                HTTP response from api call

        Returns:
            None
        """
        time_val = time.time()
        try:
            res_info = self.get_response_info(res)
            table = res_info['table']
            data_val = res_info['data']

        except self.ResponseTypeError:
            print("Unexpected response type.")
            return

        print(res_info)

        self.cur.execute(f"INSERT INTO {table} values(?, ?, ?)",
                         (res.url, time_val, data_val))
        self.con.commit()

    def read_entry(self, url, data_type):
        """Get response data (JSON) from SQL cache.

        Args:
            url (str): Alpha Vantage API url containing query params
            data_type (DataType): DataType enumeration, either CSV or JSON

        Returns:
            dict: JSON response from Alpha Vantage API
        """
        try:
            table = self.get_table(data_type)
        except self.DataTypeError as e:
            print(e)
            return

        self.cur.execute(f"SELECT data FROM {table} WHERE url = ?", (url,))
        data = self.cur.fetchone()

        return data

    def update_entry(self, res):
        """Update response object in SQL cache.

        Args:
            res (Union[requests.models.Response, http.client.HTTPResponse]):
                HTTP response from api call

        Returns:
            None
        """
        time_val = time.time()
        try:
            res_info = self.get_response_info(res)
            table = res_info['table']
            data_val = res_info['data']
        except self.ResponseTypeError as e:
            print(e)
            return

        self.cur.execute(f"UPDATE {table} SET time = ?, data = ? WHERE url = ?",
                         (time_val, data_val, res.url))
        self.con.commit()

    def is_recent(self, url, data_type, delta=60 * 5):
        """Check if HTTP response was stored a certain amount of time ago.
        Delta is in seconds and defaults to a length of 5 minutes.

        Args:
            url (str): Alpha Vantage API url containing query params
            data_type (DataType): DataType enumeration, either CSV or JSON
            delta (int): time delta in seconds

        Returns:
            bool: True if response was stored less than `delta` seconds ago,
                False otherwise
        """
        try:
            table = self.get_table(data_type)
        except self.DataTypeError:
            print("Unexpected data type.")
            return

        self.cur.execute(f'SELECT time FROM {table} WHERE url = ?', (url,))
        then = self.cur.fetchone()[0]
        now = time.time()

        return (now - then) <= delta


def toliter(gallon):
    value = round(gallon*3.785,2)
    print("%.2f 갤론 == %.2f 리터" %(gallon, value))

def togallon(liter):
    value = round(liter*0.264,2)
    print("%.2f 리터 == %.2f 갤론" %(liter, value))

while(True):
    n = int(input("번호 선택 1. 갤론 => 리터 2. 리터 => 갤론 >> "))
    if n == 1:
        a = float(input("변환할 갤론은? "))
        toliter(a)
        break;
    elif n == 2:
        b = float(input("변환할 리터는? "))
        togallon(b)
        break;
    else :
        print("다시 입력해주세요!")


# -*- coding: utf-8 -*-
"""
Created on Mon Aug 07 01:25:07

@author: 'z81022868'
"""
import os
XMLTemplate=u"""<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE concept PUBLIC "-//OASIS//DTD DITA Concept//EN"
 "concept.dtd">
<?Pub Inc?>
<concept xml:lang="{LANGUE}">
<title>{TITLE}</title>
<prolog>
<metadata><keywords><keyword>KEYWORD</keyword></keywords></metadata>
</prolog>
<conbody>

<image align="center" href="{IMAGE}" placement="noblankline"></image>
<?Pub
Caret?>
</conbody>
</concept>
<?Pub *0000001262?>
"""
HTMLTEMPLTE=u"""<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<meta http-equiv="Content-Type" content="text/html; charset=gb2312"><meta http-equiv="X-UA-Compatible" content="IE=EmulateIE7"><title>{TITLE}</title>

"""
def pngs2web(mod,reldirlist=None,outpre=u"",langue=u"",newtit=u""):#reldirlist=relativelist.相对路径的列表,outpre是加了点的
	if mod in ["html","HTML","Html","htm"]:
		template=HTMLTEMPLTE
		begflag,endflag,code=u'<img',u'
','gbk'#pyrealpath=u"D:\\untar\\Panel\\Gudie"f1.read()
	elif mod in ["XML","xml","Xml"]:
		template=XMLTemplate
		begflag,endflag,code=u'<image',u'</image>','UTF-8'
	else:
		return

	content,titbeg,titend,new=template,u'<title>',u'</title>',[]
	matchtag=content[content.find(begflag):content.rfind(endflag)+len(endflag)]#寻找image标签对

	new.extend([matchtag.format(IMAGE=ele) for ele in reldirlist])#生成列中相邻的image标签对
	webout=template.replace(matchtag,u"".join(new))#进行替换

	outname="".join([outpre,'.',mod.lower()])
	out1=open(outname,'wb')
	out1.write(webout.format(LANGUE=langue,TITLE=newtit).encode(code))
	out1.close()
def webmod(lstdir,imgdir,kwarg1={}):
	func=lambda x:"".join([u'..\\',imgdir,u"\\",x]) if x.rsplit('.')[-1] in [kwarg1["imgtype"],kwarg1["imgtype"].upper()] else []
	kwarg2={"reldirlist":map(func,os.listdir(lstdir)),
	        "outpre":kwarg1["outpre"],"newtit":kwarg1["newtit"],"langue":kwarg1["langue"]}
	if 0 in kwarg1["choice"]:#html
		#mod,reldirlist=None,outpre=u"",newtit=u""
		pngs2web("htm",**kwarg2)
	if 1 in kwarg1["choice"]:#xml
		pngs2web("xml",**kwarg2)


from guizero import App, Box, Text, TextBox, PushButton

# Listas para almacenar calificaciones
aprobados = []
reprobados = []
calificaciones_ingresadas = []

# Función para agregar calificaciones y mostrar el resultado
def agregar_calificacion():
    calificacion = input_calificacion.value
    try:
        calificacion = float(calificacion)
        if 0 <= calificacion <= 10:
            calificaciones_ingresadas.append(calificacion)
            if calificacion >= 7:
                aprobados.append(calificacion)
            else:
                reprobados.append(calificacion)
            input_calificacion.clear()
            mostrar_resultado()
        else:
            error_text.value = "Error: La calificación debe estar entre 0 y 10"
    except ValueError:
        error_text.value = "Error: Ingrese una calificación válida"

# Función para mostrar el resultado
def mostrar_resultado():
    aprobados_text.value = f"Aprobados: {len(aprobados)}"
    reprobados_text.value = f"Reprobados: {len(reprobados)}"
    total_calificaciones_text.value = f"Total calificaciones: {len(calificaciones_ingresadas)}"
    error_text.value = ""  # Limpiar cualquier mensaje de error anterior

# Crear una aplicación Guizero
app = App("Calculadora de Aprobados")

# Crear contenedores para los elementos
input_box = Box(app, layout="grid")
resultado_box = Box(app, layout="grid")

# Elementos
Text(input_box, text="Calificación: ", grid=[0, 0])
input_calificacion = TextBox(input_box, grid=[1, 0])
agregar_button = PushButton(input_box, text="Agregar Calificación", command=agregar_calificacion, grid=[2, 0])
aprobados_text = Text(resultado_box, text="", grid=[0, 0])
reprobados_text = Text(resultado_box, text="", grid=[0, 1])
total_calificaciones_text = Text(resultado_box, text="", grid=[0, 2])
error_text = Text(resultado_box, text="", grid=[0, 3], color="red")

app.display()


INPUT_S = '''\
199
200
208
210
200
207
240
267
260
263
'''

numbers = [int(line) for line in INPUT_S.splitlines()]

prev = numbers[0]
count = 0

#for i in numbers[1:]:
    #if i > prev:
        #count += 1
    #prev = i

#print(count)

#for i in range(1, len(numbers)):
    #if numbers[i] > numbers[i - 1]:
        #count += 1

count = sum(
    numbers[i] > numbers[i - 1] for i in range(1, len(numbers))
)
print(f"part 1: {count}")

count = sum(
    numbers[i] > numbers[i - 3] for i in range(3, len(numbers))
)
print(f"part 2: {count}")


import pygame

import settings
from settings import *
import sys
from board import Board

class Main:

    def __init__(self):
        pygame.init()
        self.board = Board(WIDTH, HEIGHT)
        self.clock = pygame.time.Clock()
        self.count = 0

    # main function to run the game
    def run(self):
        self.board.draw()
        pygame.display.flip()
        self.running = True

        # loops to keep game running and updating until it is closed
        while self.running:
            self.clock.tick(FPS)
            self.visual()
            self.events()
            self.update()

    def menu(self):
        screen = pygame.display.set_mode((WIDTH, HEIGHT))
        pygame.display.set_caption("Main Menu")
        screen.fill(BGCOLOUR)
        font = pygame.font.Font("Retro Gaming.ttf", 30)
        text = font.render("Click to start.", 1, WHITE)

        while 1:

            for event in pygame.event.get():
                if event.type == pygame.QUIT:
                    quit()
                if event.type == pygame.MOUSEBUTTONDOWN:
                    self.run()

            screen.blit(text, (250, 250))

            pygame.display.update()

    # initialises some visual stuff like the title and icon
    def visual(self):
        pygame.display.set_caption(TITLE)
        icon = pygame.image.load('logo.png')
        pygame.display.set_icon(icon)

    # checks for game updates
    def update(self):
        pygame.display.update()

    # checks events, checks if the game is closed
    def events(self):
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                self.quit()
            if event.type == pygame.MOUSEBUTTONDOWN:
                location = pygame.mouse.get_pos()
                self.board.place_settlement(location)
    # quits game
    def quit(self):
        sys.exit()

m = Main()
while True:
    m.menu()


import os
from os import path

from utils.misc  import execmd
from utils.logger import logger

def pcapng_to_pcap(filename):
	new_name = filename.split('.pcapng')[0]+'.pcap'
	cmd = "tshark -F pcap -r %s -w %s"%(filename,new_name)
	execmd(cmd)
	return new_name

def cap_to_pcap(filename):
	new_name = filename.split('.cap')[0]+'.pcap'
	cmd = "tshark -F pcap -r %s -w %s"%(filename,new_name)
	execmd(cmd)
	return new_name

def Check_traffic(filename):
	new_name = filename
	if(filename.endswith('.pcapng')):
		new_name = pcapng_to_pcap(filename)
	elif (filename.endswith('.cap')):
		new_name = cap_to_pcap(filename)

	if(path.exists(new_name)):
		new_name = filename

	return new_name


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

'''
for i in range(1,10):
    print(i)
else:
    print('the for loop is over')
'''

a_list=[1,2,5,6]
for j in a_list:
    print(j)
'''
a_dict = {'Tom':1213123,'jerry':8789788}
for m in a_dict:
    print(m,":",a_dict[m])

for key,elem in a_dict.items():
    print(key,elem)
'''


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

import numpy  as np
import pandas as pd
import talib as ta
from utils.diff import add_diff

def signal(*args):
    # 该指标使用时注意n不能大于过滤K线数量的一半（不是获取K线数据的一半）

    df = args[0]
    n  = args[1]
    diff_num = args[2]
    factor_name = args[3]

    """
    N=14
    TYPICAL_PRICE=(HIGH+LOW+CLOSE)/3
    MF=TYPICAL_PRICE*VOLUME
    MF_POS=SUM(IF(TYPICAL_PRICE>=REF(TYPICAL_PRICE,1),M
    F,0),N)
    MF_NEG=SUM(IF(TYPICAL_PRICE<=REF(TYPICAL_PRICE,1),
    MF,0),N)
    MFI=100-100/(1+MF_POS/MF_NEG)
    MFI 指标的计算与 RSI 指标类似，不同的是，其在上升和下跌的条件
    判断用的是典型价格而不是收盘价，且其是对 MF 求和而不是收盘价
    的变化值。MFI 同样可以用来判断市场的超买超卖状态。
    如果 MFI 上穿 80，则产生买入信号；
    如果 MFI 下穿 20，则产生卖出信号。
    """
    df['price'] = (df['high'] + df['low'] + df['close']) / 3  # TYPICAL_PRICE=(HIGH+LOW+CLOSE)/3
    df['MF'] = df['price'] * df['volume']  # MF=TYPICAL_PRICE*VOLUME
    df['pos'] = np.where(df['price'] >= df['price'].shift(1), df['MF'],
                         0)  # IF(TYPICAL_PRICE>=REF(TYPICAL_PRICE,1),MF,0)MF,0),N)
    df['MF_POS'] = df['pos'].rolling(n).sum()
    df['neg'] = np.where(df['price'] <= df['price'].shift(1), df['MF'],
                         0)  # IF(TYPICAL_PRICE<=REF(TYPICAL_PRICE,1),MF,0)
    df['MF_NEG'] = df['neg'].rolling(n).sum()  # MF_NEG=SUM(IF(TYPICAL_PRICE<=REF(TYPICAL_PRICE,1),MF,0),N)

    df[factor_name] = 100 - 100 / (1 + df['MF_POS'] / df['MF_NEG'])  # MFI=100-100/(1+MF_POS/MF_NEG)

    # 删除中间数据
    del df['price']
    del df['MF']
    del df['pos']
    del df['MF_POS']
    del df['neg']
    del df['MF_NEG']

    if diff_num > 0:
        return add_diff(df, diff_num, factor_name)
    else:
        return df


from urllib.request import urlopen
from urllib.parse import urlencode, urljoin
import time
from queue import Queue
import threading as td

class MessageQueueManager:
    def __init__(self, url, secretKey):
        self.url = url
        self.secretKey = secretKey
        self.localmq = Queue()
        # try to create a thread to push message to queue
        for _ in range(60):
            try:
                urlopen(self.url + '?' + urlencode({
                    'secretKey': self.secretKey
                }))
                self.clear()
                t = td.Thread(
                    target=self.getMessage,
                    args=(self.localmq, self.url, self.secretKey),
                    daemon=True)
                t.start()
                return
            except KeyError as e:
                print(e)
                time.sleep(1)

    @staticmethod
    def getMessage(q, url, secretKey):
        while True:
            try:
                message = urlopen(urljoin(url, 'get')).read().decode('utf-8')
                if message == 'Error:403 Forbidden':
                    urlopen(url + '?' + urlencode({'secretKey': secretKey}))
                    message = urlopen(urljoin(url,
                                              'get')).read().decode('utf-8')
            except:
                message = 'Error:Empty'
            if message not in ['Error:Empty', 'Error:403 Forbidden']:
                q.put(message)
            else:
                time.sleep(0.1)

    def add2DanmuManager(self, danmuManager):
        while not self.localmq.empty():
            danmuManager.addDanmu(self.localmq.get())

    # remove all messages in queue
    def clear(self):
        return urlopen(urljoin(self.url, 'cls'))


def solution(A):
    A.sort()        # Sort A in non-decreasing order
    if A[0] >= 0:   return A[0] + A[0]      # All non-negative
    if A[-1] <= 0:  return -A[-1] - A[-1]   # All non-positive
    front, back = len(A)-1, 0
    minAbs = A[-1] + A[-1]                  # Final result
    # Travel the array from both ends to some center point.
    # See following post for the proof of this method.
    # https://codesays.com/2014/solution-to-min-abs-sum-of-two-by-codility
    while back <= front:
        temp = abs(A[back] + A[front])
        # Update the result if needed
        if temp < minAbs:  minAbs = temp

        # Adjust the pointer for next trying
        if back == front: break
        elif abs(A[back+1] + A[front]) <= temp:    back += 1
        elif abs(A[back] + A[front-1]) <= temp:  front -= 1
        else:                         back += 1; front -= 1
    return minAbs


#To find Root of a number
def root(n):
	if n>=0:
		return n
	else:
		return root(n**0.5)
a = int(input("Enter Value"))
c=root(a)
print(c)

#using build in method
import math
b=math.sqrt(a)
print(b)


import requests

def get_location(lat, lon):
    try:
        location_data = requests.get('http://maps.googleapis.com/maps/api/geocode/json?latlng={},{}&sensor=true'.format(lat, lon))

        json = location_data.json()['results'][0]['formatted_address']
        print(json)
        return json
    except:
        return "None"

get_location(14, 14.5)

file = open('example_data.txt')
lines = file.readlines()
locations = []
for line in lines[1:]:
    splitted = line.split(',')
    lat = splitted[0]
    lon = splitted[1]
    print(lat, lon)
    with open("locations" + '.txt', 'a') as outFile:
        data = ';'.join([ lat, lon, get_location(lat, lon)])
        outFile.write(data + '\n')


from django.urls import path
from .views import *

urlpatterns = [
    path('redirect/', redirect_match, name='redirect_match'),
    path('test/', tester, name='testrer'),
    path('rave/redirect/<int:user_id>/<package>/<duration>/<tx_ref>/', rave_redirect, name='rave_redirect'),
    path('rave/webhook/', rave_webhook, name='rave_webhook'),
    path('pay/', rave_pay, name='pay'),
    ]