import sys
import pygame
import random

from setting import Settings
from game_status import GameStats
from background import Background
from button import Button

class Game2048:
    """游戏资源类"""
    def __init__(self):
        # 游戏界面初始化
        pygame.init()
        self.settings = Settings()
        self.screen = pygame.display.set_mode((self.settings.screen_width, self.settings.scree_height))

        # 标题
        pygame.display.set_caption("2048")

        # 游戏列表
        self.game_list = [[0, 0, 0, 0],
                          [0, 0, 0, 0],
                          [0, 0, 0, 0],
                          [0, 0, 0, 0]]

        # 游戏状态
        self.status = GameStats(self)
        self.status.load_high_score()

        # 背景
        self.background = Background(self)

        # 按钮
        self.new_game_button = Button(self, "New Game")

    def run_game(self):
        """主循环"""
        self._random()
        while True:
            self._check_event()
            self._check_game_status()
            self._update_screen()
            if self.status.is_win or self.status.is_over:
                self.status.save_high_score()

    def _check_event(self):
        """相应鼠标和键盘输入"""
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                sys.exit()
            elif event.type == pygame.KEYDOWN:
                self._check_key_down_event(event)
            elif event.type == pygame.MOUSEBUTTONDOWN:
                mouse_pos = pygame.mouse.get_pos()
                self._check_button(mouse_pos)

    def _check_key_down_event(self, event):
        """检查键盘输入"""
        if event.key == pygame.K_LEFT:
            self._move_left()
        elif event.key == pygame.K_RIGHT:
            self._move_right()
        elif event.key == pygame.K_UP:
            self._move_up()
        elif event.key == pygame.K_DOWN:
            self._move_down()

        # 如果游戏没有结束就继续随机生成数字
        if not(self.status.is_win or self.status.is_over):
            self._random()

    def combination(self, temp_list):
        """结合一行或一列相同方块
           将行或列中的数字按顺序存储在temp_list列表中
           然后根据不同情况进行合并
        """
        nums = []
        ans = [0, 0, 0, 0]
        for i in temp_list:
            if i != 0:
                nums.append(i)
        length = len(nums)

        # 没有数字
        if length == 0:
            return ans
        # 只有一个数字
        elif length == 1:
            ans[0] = nums[0]
            return ans
        # 有两个数字
        elif length == 2:
            # case 1
            if nums[0] == nums[1]:
                ans[0] = nums[0] + nums[1]
                self.status.score += ans[0]
                return ans
            # case 2
            else:
                ans[0] = nums[0]
                ans[1] = nums[1]
                return ans
        # 有三个数字
        elif length == 3:
            # case 1
            if nums[0] == nums[1]:
                ans[0] = nums[0] + nums[1]
                ans[1] = nums[2]
                self.status.score += ans[0]
                return ans
            # case 2
            elif nums[1] == nums[2]:
                ans[0] = nums[0]
                ans[1] = nums[1] + nums[2]
                self.status.score += ans[1]
                return ans
            # case 3
            else:
                nums.append(0)
                return nums
        # 有四个数字
        else:
            # case 1
            if nums[0] == nums[1]:
                ans[0] = nums[0] + nums[1]
                self.status.score += ans[0]
                # 1 2和3 4位置的数字分别相等
                if nums[2] == nums[3]:
                    ans[1] = nums[2] + nums[3]
                    self.status.score += ans[1]
                    return ans
                # 只有1 2位置相等
                else:
                    ans[1] = nums[2]
                    ans[2] = nums[3]
                    return ans
            # case 2
            # 中间两个数字相等
            elif nums[1] == nums[2]:
                ans[0] = nums[0]
                ans[1] = nums[1] + nums[2]
                ans[2] = nums[3]
                self.status.score += ans[1]
                return ans
            # case 3
            # 3 4两个数字相等
            elif nums[2] == nums[3]:
                ans[0] = nums[0]
                ans[1] = nums[1]
                ans[2] = nums[2] + nums[3]
                self.status.score += ans[2]
                return ans
            # case 4
            # 四个数字都不相等
            else:
                return nums

    def _move_left(self):
        """左移操作"""
        for i in range(4):
            temp = self.combination(self.game_list[i])
            for j in range(4):
                self.game_list[i][j] = temp[j]

    def _move_right(self):
        """右移操作"""
        for i in range(4):
            temp = self.combination(self.game_list[i][::-1])
            for j in range(4):
                self.game_list[i][3 - j] = temp[j]

    def _move_up(self):
        """上移操作"""
        for i in range(4):
            temp = []
            for j in range(4):
                temp.append(self.game_list[j][i])
            temp = self.combination(temp)
            for k in range(4):
                self.game_list[k][i] = temp[k]

    def _move_down(self):
        """下移操作"""
        for i in range(4):
            temp = []
            for j in range(4):
                temp.append(self.game_list[3 - j][i])
            temp = self.combination(temp)
            for k in range(4):
                self.game_list[3 - k][i] = temp[k]

    def _check_game_status(self):
        """检查游戏状态"""
        # 判断游戏是否胜利，同时将没有数字的位置存在empty_pos列表中
        empty_pos = []
        for i in range(4):
            for j in range(4):
                if self.game_list[i][j] == 2048:
                    self.status.is_win = True
                if self.game_list[i][j] == 0:
                    empty_pos.append([i, j])

        # empty_list为空则说明方格全部填满，判断相邻方块是否有相同，没有则游戏失败
        if len(empty_pos) == 0:
            flag = True
            for i in range(4):
                for j in range(3):
                    if self.game_list[i][j] == self.game_list[i][j + 1]:
                        flag = False
            for i in range(4):
                for j in range(3):
                    if self.game_list[j][i] == self.game_list[j + 1][i]:
                        flag = False
            if flag:
                self.status.is_over = True

    def _random(self):
        """随机位置生成2或4"""
        # 列表empty_list存储没有数字的位置
        empty_pos = []
        for i in range(4):
            for j in range(4):
                if self.game_list[i][j] == 0:
                    empty_pos.append([i, j])

        # empty_list非空则继续随机生成
        if len(empty_pos) != 0:
            i_pos, j_pos = random.choice(empty_pos)
            num = random.randint(1, 2)
            self.game_list[i_pos][j_pos] = num * 2

    def _check_button(self, mouse_pos):
        """确定点击按钮"""
        # 点击New Game按钮
        button_clicked = self.new_game_button.rect.collidepoint(mouse_pos)
        if button_clicked:
            # 将游戏重置，同时随机生成一个2或4
            self.game_list = [[0, 0, 0, 0],
                              [0, 0, 0, 0],
                              [0, 0, 0, 0],
                              [0, 0, 0, 0]]
            self._random()
            self.status.reset_stats()

    def _show_game(self):
        """绘制4×4数字方块"""
        for i in range(4):
            for j in range(4):
                rect_color = self.settings.colors[self.game_list[i][j]]
                rect_pos = [(j + 1) * self.settings.grid_width + j * self.settings.size,
                            self.settings.score_height + (i + 1) * self.settings.grid_width + i * self.settings.size]
                pygame.draw.rect(self.screen, rect_color, (rect_pos, (self.settings.size, self.settings.size)), 0)

                # 如果数字是0就不绘制
                if self.game_list[i][j] != 0:
                    num_image = self.settings.num_font.render(str(self.game_list[i][j]), True,
                                                              self.settings.num_color,
                                                              rect_color)
                    num_image_rect = num_image.get_rect()
                    num_rect_pos = [(j + 1) * self.settings.grid_width + (j + 0.5) * self.settings.size,
                                    self.settings.score_height + (i + 1) * self.settings.grid_width +
                                    (i + 0.5) * self.settings.size]
                    num_image_rect.center = tuple(num_rect_pos)
                    self.screen.blit(num_image, num_image_rect)

    def _update_screen(self):
        """更新游戏屏幕"""
        self.screen.fill(self.settings.bg_color)
        self.new_game_button.draw_button()
        self.background.draw_line()
        self._show_game()

        # 判断当前得分是否大于最高分
        if self.status.score > self.status.high_score:
            self.status.high_score = self.status.score
        self.background.draw_score()

        # 判断游戏是否结束
        if self.status.is_win:
            self.background.draw_win()
        if self.status.is_over:
            self.background.draw_over()

        pygame.display.flip()

if __name__ == '__main__':
    ai = Game2048()
    ai.run_game()


#! /usr/bin/python3

import sys
import asynch_ea as asynch
import random as rd
import time
import numpy

from deap import base
from deap import creator
from deap import tools
from deap import benchmarks

def evaluate(ind):
	time.sleep(rd.randint(0,10))
	ind.fitness.values = benchmarks.rastrigin(ind)
	return ind

def elitist_select(pop,size):
	sort_pop = pop
	sort_pop.sort(reverse=True,key=lambda p: p.fitness.values[0])
	return sort_pop[:size]

ind_size = 5

creator.create("FitnessMin", base.Fitness, weights=(-1.0,))
creator.create("Individual", list, fitness=creator.FitnessMin)

toolbox = base.Toolbox()
toolbox.register("attr_float", rd.random)
toolbox.register("individual", tools.initRepeat, creator.Individual,
                 toolbox.attr_float, n=ind_size)
toolbox.register("population", tools.initRepeat, list, toolbox.individual)

toolbox.register("mate", tools.cxTwoPoint)
toolbox.register("mutate", tools.mutGaussian, mu=0, sigma=1,indpb=1)
toolbox.register("death_select", elitist_select)
toolbox.register("parents_select", tools.selTournament, tournsize=3)
toolbox.register("eval", evaluate)
toolbox.register("generate",asynch.generate)
def extra(toolbox,pop,iter):#no extra step
	pass
toolbox.register("extra",extra)

if __name__ == '__main__':
	nb_workers = int(sys.argv[1])
	stats = tools.Statistics(key=lambda ind: ind.fitness.values)
	stats.register("avg", numpy.mean)
	stats.register("std", numpy.std)
	stats.register("min", numpy.min)
	stats.register("max", numpy.max)
	asynch_ea = asynch.AsynchEA(100,nb_workers,sync=1)
	pop = asynch_ea.init(toolbox)
	print("init finish")
	for i in range(1000):
		pop = asynch_ea.step(toolbox)
		print(stats.compile(pop))


# From the OpenCV library import imread, imwrite and resize function only.
from cv2 import imread, imwrite, resize

# Reading the image using imread() function
image = imread("../0_assets/road.jpg")

# Adjust the parameter's value to your liking.
# ! Keep in mind that this will be the resulting (w, h) to image.
w, h = (800, 700)

# First Parameter is the one who loads the image with imread.
# Second Parameter is tuple containing width and height.
resize_mod = resize(image, (w, h))

# Save the resized image buffer.
imwrite("result.jpg", resize_mod)


#!/usr/bin/env python
from datetime import datetime  # Zeit modul um festzulegen wie oft messungen gemacht werden
import time

def is_time(): # Alle 30 Minuten die Daten auslesen.
    return True
    now = datetime.now()
    current_minute = now.strftime("%M")
    print(current_minute)
    if current_minute == "30" or current_minute == "00":
        print("fa")
        return True
    else:
        return False

sensor1 = "/sys/bus/w1/devices/28-3c01f0960400/w1_slave"  # Sensor 1
sensor2 = "/sys/bus/w1/devices/28-3c01f096db57/w1_slave"  # Sensor 2
f = open(sensor1, "r")  # Auf beide Sensoren zugreifen
f2 = open(sensor2, "r")

sensor1_text = open("Sensor1.txt", "a")
sensor2_text = open("Sensor2.txt", "a")

data = f.read()  # Die Daten auslesen
data2 = f2.read()
while True:
    if is_time():
        f = open(sensor1, "r")  # Auf beide Sensoren zugreifen
        f2 = open(sensor2, "r")
        data = f.read()
        data2 = f2.read()

        print("Its time")
        print("Data ready")
        (discard, sep, reading) = data.partition(' t=')
        t = float(reading) / 1000.0
        print("Sensor 1 {:.1f}".format(t))
        with open("Sensor1.txt", "a") as f:
            f.write("\n")
            now = datetime.now()
            current_minute = now.strftime("%H:%M")
            f.write(current_minute + " ," + str(t))

        print("Data 2 ready")
        (discard, sep, reading) = data2.partition(' t=')
        t = float(reading) / 1000.0
        print("Sensor 2 {:.1f}".format(t))
        with open("Sensor2.txt", 'a') as f:
            f.write("\n")
            now = datetime.now()
            current_minute = now.strftime("%H:%M")
            f.write(current_minute + " ," + str(t))

    else:
        time.sleep(20)


import re
import os
import logging
import pyrogram
from config import Config
from plugins import helper
from pyrogram import Client, filters

logging.basicConfig(level=logging.DEBUG,
                    format='%(asctime)s - %(name)s - %(levelname)s - %(message)s')
logger = logging.getLogger(__name__)
logging.getLogger("pyrogram").setLevel(logging.WARNING)

Current_Text = {}

#@Client.on_message(filters.text & ~filters.command)
def my_handler(client, message):
    print(message)

async def GetCurrentTextToStyle(Chat_Id):
  try:
    TextToChange = Current_Text[int(Chat_Id)]
  except:
    TextToChange = "Nonee"
  return TextToChange

@Client.on_message(filters.private & filters.text & filters.regex(r"^(?!/).*"))
async def TextHandlewithFont(bot,message):
  #Current_Text.clear()
  #Current_Text.append(message.text)
  print(message.chat.id)
  Current_Text[message.chat.id] = message.text
  await message.reply_text("Choose Your Methods",reply_markup=helper.STARTFontingBTN)
  print(Current_Text)


from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtCore import QTimer
from PyQt5.QtCore import pyqtSlot, pyqtSignal, QObject

import util
util.redirectPrintToShell(globals())

class QuickCmdEditDialog(QtWidgets.QDialog):
    finished = pyqtSignal([str, str, str])
    def __init__(self, *args):
        super().__init__(*args)
        self.mode = ""

        self.setModal(True)
        font = QtGui.QFont()
        font.setFamily("DejaVu Sans Mono")
        font.setPointSize(12)
        self.setFont(font)

        self.setFixedSize(500, 460)

        self.labelQuickCmdName = QtWidgets.QLabel(self)
        self.labelQuickCmdName.setGeometry(QtCore.QRect(20, 20, 60, 30))
        self.labelQuickCmdName.setText("Name:")

        self.lineEditQuickCmdName = QtWidgets.QLineEdit(self)
        self.lineEditQuickCmdName.setGeometry(QtCore.QRect(100, 20, 350, 30))

        self.labelQuickCmdSourceCode = QtWidgets.QLabel(self)
        self.labelQuickCmdSourceCode.setGeometry(QtCore.QRect(20, 60, 300, 30))
        self.labelQuickCmdSourceCode.setText("Source Code:")

        self.plainTextEditSourceCode = QtWidgets.QPlainTextEdit(self)
        self.plainTextEditSourceCode.setGeometry(QtCore.QRect(20, 100, 460, 280))

        self.buttonOk = QtWidgets.QPushButton(self)
        self.buttonOk.setGeometry(QtCore.QRect(190, 400, 80, 40))
        self.buttonOk.clicked.connect(self.onOkButtonClicked)
        self.buttonOk.setText("OK")
    def onOkButtonClicked(self):
        name = self.lineEditQuickCmdName.text()
        sourceCode = self.plainTextEditSourceCode.toPlainText()
        if not name or not sourceCode:
            self.messageBox = QtWidgets.QMessageBox(self)
            if not name:
                self.messageBox.setText("Name cannot be empty")
            elif not sourceCode:
                self.messageBox.setText("source code cannot be empty")
            self.messageBox.open()
        else:
            self.finished.emit(self.mode, name, sourceCode)
            self.accept()
    def setMode(self, mode):
        self.mode = mode
    def setCmdName(self, name):
        self.lineEditQuickCmdName.setText(name)
    def setSourceCode(self, code):
        self.plainTextEditSourceCode.setPlainText(code)


r"""Get volume image data for download.

[smh_js]

This is a sample of "smh js":

    SMH.imgData({
        "bid": 29747,
        "bname": "飞行文学",
        "bpic": "29747.jpg",
        "cid": 398038,
        "cname": "第11回",
        "files": ["001.jpg.webp",
                  "002.jpg.webp",
                  "003.jpg.webp",
                  "097.jpg.webp",
                  "098.jpg.webp"],
        "finished": false,
        "len": 5,
        "path": "/ps2/f/feixingwen_xue/第11回/",
        "status": 1,
        "block_cc": "",
        "nextId": 0,
        "prevId": 397656,
        "sl": {
            "md5": "GTdWjMobp0W0r6Y9tVW5tw"
        }
    }).preInit();

"smh_js" is decoded from "target_js"

[chapter_info]

The "chapter_info" is the object stored in "smh_js".

The important part include:

    path:
        image file path (not include filename) from root the root of hosts.

    files:
        multiple image filenames, order by reading order.

        If a filename ends with `.webp`, which can safely strip `.webp` and
        retriving the original format.

    cid:
        should exist in query string when fetch image files. maybe mean the "chapter id"?

    sl.md5:
        should exist in query string when fetch image files.

[image url format]

A sample image url look like this one:

    https://i.hamreus.com/ps2/f/feixingwen_xue/第11回/001.jpg?cid=398038&md5=GTdWjMobp0W0r6Y9tVW5tw

The structure is:

    https://{image_host_code}.hamreus.com{path}{files[*]}?cid={cid}&md5={sl.md5}

[image_host_code]

Run `servs` in browser's console can find the "image_host_code". Like
following:

    [{"name":"自動",
      "hosts":[{"h":"i","w":100},{"h":"us","w":1}],
      "w":101},
     {"name":"電信",
      "hosts":[{"h":"eu","w":100}, {"h":"i","w":1}, {"h":"us","w":1}],
      "w":102},
     {"name":"聯通",
      "hosts":[{"h":"us","w":100},{"h":"i","w":1},{"h":"eu","w":1}],
      "w":102}]

[target_js]

This is a "target_js", it look like:

    window["\x65\x76\x61\x6c"](function(p,a,c,k,e,d){e=function(c){return(c<a?"":e(parseInt(c/a)))+((c=c%a)>35?String.fromCharCode(c+29):c.toString(36))};if(!''.replace(/^/,String)){while(c--)d[e(c)]=k[c]||e(c);k=[function(e){return d[e]}];e=function(){return'\\w+'};c=1;};while(c--)if(k[c])p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c]);return p;}('c.h({"i":6,"e":"g","l":"6.2","m":j,"k":"4","d":["8.2.3","7.2.3","b.2.3","9.2.3","a.2.3"],"n":y,"z":5,"w":"/x/f/A/4/","B":1,"r":"","o":0,"p":u,"v":{"s":"t"}}).q();',38,38,'D7BWAcHNgdwUwEbmIGm8CMbB7aiATATgHYAWA4ABjJ3LLXMLoA5qBmYAZQFkAJYAMwEsANnADOwBADsAhgFs4IQHsZgGQjA4aaAzbWD8ZkACJSALlPH8AJsGZ4GZZkwDG0uePD9bwW6b78J/EQAs4ZhJwAB76AJJm4ABOcABuEcDRcGHe+uKCAPa2ANYA+rauMiYArMAA4gAqJgDqoBwZSGTVZFEAbACaePoAatXF+jDmhK3FrcAigokGvokiVLxSgiLywhJ8cPzBXpDwErnBAK7yIob6ByJAA=='['\x73\x70\x6c\x69\x63']('\x7c'),0,{}))    # NOQA

Strip `window[...]` and decrypt this one can find the "smh_js".

"""

import re
import json
from random import choice
from urllib.parse import urlencode

from cmdlr.autil import run_in_nodejs

from .sharedjs import get_shared_js

async def _get_chapter_info(soup, loop):
    """Get single chapter info in volume entry soup."""
    target_js = soup.find('script', string=re.compile(r'window\["')).string
    encrypted_js = re.sub(r'^window\[.+?\]', '', target_js)

    full_js = get_shared_js() + encrypted_js

    smh_js = await loop.run_in_executor(None, lambda: run_in_nodejs(full_js))

    json_string = re.search(r'{.*}', smh_js).group(0)

    return json.loads(json_string)

def _get_normalized_filenames(filenames):
    webp_regex = re.compile(r'\.webp$')

    return [webp_regex.sub('', filename) for filename in filenames]

def _get_image_url(filename, chapter_info, image_host_codes):
    cid = chapter_info['cid']
    md5 = chapter_info['sl']['md5']
    chapter_path = chapter_info['path']

    image_host_code = choice(image_host_codes)

    return (
        'https://{image_host_code}.hamreus.com{chapter_path}{filename}?{qs}'
        .format(image_host_code=image_host_code,
                chapter_path=chapter_path,
                filename=filename,
                qs=urlencode({'cid': cid, 'md5': md5}))
    )

async def get_image_urls(soup, image_host_codes, loop):
    """Get image's urls from soup and configuration."""
    chapter_info = await _get_chapter_info(soup, loop)

    filenames = chapter_info['files']

    norm_filenames = _get_normalized_filenames(filenames)
    image_urls = [
        _get_image_url(filename, chapter_info, image_host_codes)
        for filename in norm_filenames
    ]

    return image_urls


from django.contrib import admin
from django import forms

from . import models

class CountryAdminForm(forms.ModelForm):

    class Meta:
        model = models.Country
        fields = "__all__"

class CountryAdmin(admin.ModelAdmin):
    form = CountryAdminForm
    list_display = [
        "last_updated",
        "id",
        "name",
        "created",
    ]
    readonly_fields = [
        "last_updated",
        "id",
        "name",
        "created",
    ]

class StateAdminForm(forms.ModelForm):

    class Meta:
        model = models.State
        fields = "__all__"

class StateAdmin(admin.ModelAdmin):
    form = StateAdminForm
    list_display = [
        "created",
        "id",
        "last_updated",
        "name",
    ]
    readonly_fields = [
        "created",
        "id",
        "last_updated",
        "name",
    ]

class CityAdminForm(forms.ModelForm):

    class Meta:
        model = models.City
        fields = "__all__"

class CityAdmin(admin.ModelAdmin):
    form = CityAdminForm
    list_display = [
        "name",
        "id",
        "created",
        "last_updated",
    ]
    readonly_fields = [
        "name",
        "id",
        "created",
        "last_updated",
    ]

class LocalityAdminForm(forms.ModelForm):

    class Meta:
        model = models.Locality
        fields = "__all__"

class LocalityAdmin(admin.ModelAdmin):
    form = LocalityAdminForm
    list_display = [
        "id",
        "created",
        "last_updated",
        "name",
    ]
    readonly_fields = [
        "id",
        "created",
        "last_updated",
        "name",
    ]

admin.site.register(models.Country, CountryAdmin)
admin.site.register(models.State, StateAdmin)
admin.site.register(models.City, CityAdmin)
admin.site.register(models.Locality, LocalityAdmin)


from flask import Flask, request, jsonify
from TaskModel import Task, task_schema, tasks_schema
from verify import verify
from config import db, app

# Create new task
@app.route('/api/task/add', methods=['POST'])
@verify
def addTask(user):
    try:
        userId = user.userId
        phaseId = request.json['phaseId']
        taskText = request.json['taskText']
        stage = "todo"

        task = Task(userId, phaseId, taskText, stage)
        db.session.add(task)
        db.session.commit()

        return task_schema.jsonify(task)
    except:
        return {"msg": "Something went wrong"}, 500

# Get specific task
@app.route('/api/task/<id>', methods=['GET'])
def getTask(id):
    try:
        task = Task.query.get(id)
        return task_schema.jsonify(task)
    except:
        return {"msg": "Something went wrong"}, 500

# Get all tasks from certain phase
@app.route('/api/tasks/<phaseId>', methods=['GET'])
@verify
def getTasks(user, phaseId):
    try:
        task = Task.query.filter(Task.phaseId == phaseId).all()
        return tasks_schema.jsonify(task)
    except:
        return {"msg": "Something went wrong"}, 500

# Update task
@app.route('/api/task/update/<id>', methods=['PUT'])
@verify
def updateTask(user, id):
    try:
        task = Task.query.get(id)
        userId = user.userId
        phaseId = request.json['phaseId']
        taskText = request.json['taskText']
        stage = request.json['stage']

        task.userId = userId
        task.phaseId = phaseId
        task.taskText = taskText
        task.stage = stage

        db.session.commit()
        return task_schema.jsonify(task)
    except:
        return {"msg": "Something went wrong"}, 500

@app.route('/api/task/<id>/<stage>', methods=['POST'])
def updateStage(id, stage):
    try:
        task = Task.query.get(id)
        task.stage = stage

        db.session.commit()
        return task_schema.jsonify(task)
    except:
        return {"msg": "Something went wrong"}, 500

# Delete tasks
@app.route('/api/task/delete/<id>', methods=['DELETE'])
@verify
def deleteTask(user, id):
    try:
        task = Task.query.get(id)
        db.session.delete(task)
        db.session.commit()

        return task_schema.jsonify(task)
    except:
        return {"msg": "Something went wrong"}, 500


# -*- test-case-name: axiom.test.test_scheduler -*-

import gc
from datetime import timedelta

from twisted.trial import unittest
from twisted.trial.unittest import TestCase
from twisted.application.service import IService
from twisted.internet.task import Clock
from twisted.python import filepath

from epsilon.extime import Time

from axiom.scheduler import TimedEvent, _SubSchedulerParentHook, TimedEventFailureLog
from axiom.scheduler import Scheduler, SubScheduler
from axiom.scheduler import SITE_SCHEDULER
from axiom.store import Store
from axiom.item import Item
from axiom.substore import SubStore

from axiom.attributes import integer, text, inmemory, boolean, timestamp
from axiom.iaxiom import IScheduler

class TestEvent(Item):

    typeName = 'test_event'
    schemaVersion = 1

    testCase = inmemory()       # this won't fall out of memory due to
                                # caching, thanks.
    name = text()

    runCount = integer()
    runAgain = integer()        # milliseconds to add, then run again
    winner = integer(default=0) # is this the event that is supposed to
                                # complete the test successfully?

    def __init__(self, **kw):
        super(TestEvent, self).__init__(**kw)
        self.runCount = 0

    def run(self):
        # When this is run from testSubScheduler, we want to make an
        # additional assertion.  There is exactly one SubStore in this
        # configuration, so there should be no more than one
        # TimedEvent with a _SubSchedulerParentHook as its runnable.
        if self.store.parent is not None:
            count = 0
            s = self.store.parent
            for evt in s.query(TimedEvent):
                if isinstance(evt.runnable, _SubSchedulerParentHook):
                    count += 1
            if count > 1:
                return self.fail("Too many TimedEvents for the SubStore: %d" % (count,))

        self.runCount += 1
        if self.runAgain is not None:
            result = self.testCase.now() + timedelta(seconds=self.runAgain)
            self.runAgain = None
        else:
            result = None
        return result

    def fail(self, msg):
        self.testCase.fail(msg)

class NotActuallyRunnable(Item):
    huhWhat = integer()

class SpecialError(Exception):
    pass

class SpecialErrorHandler(Item):
    huhWhat = integer()
    broken = integer(default=0)
    procd = integer(default=0)

    def run(self):
        self.broken = 1
        raise SpecialError()

    def timedEventErrorHandler(self, timedEvent, failureObj):
        failureObj.trap(SpecialError)
        self.procd = 1

class HookRunner(Item):
    """
    Runnable that simply calls a supplied hook.
    """
    ignored = integer()
    hook = inmemory()

    def run(self):
        self.hook(self)

class SchedTest:
    def tearDown(self):
        return IService(self.siteStore).stopService()

    def setUp(self):
        self.clock = Clock()

        scheduler = IScheduler(self.siteStore)
        self.stubTime(scheduler)
        IService(self.siteStore).startService()

    def now(self):
        return Time.fromPOSIXTimestamp(self.clock.seconds())

    def stubTime(self, scheduler):
        scheduler.callLater = self.clock.callLater
        scheduler.now = self.now

    def test_implementsSchedulerInterface(self):
        """
        Verify that IScheduler is declared as implemented.
        """
        self.assertTrue(IScheduler.providedBy(IScheduler(self.store)))

    def test_scheduler(self):
        """
        Test that the ordering and timing of scheduled calls is correct.
        """
        # create 3 timed events.  the first one fires.  the second one fires,
        # then reschedules itself.  the third one should never fire because the
        # reactor is shut down first.  assert that the first and second fire
        # only once, and that the third never fires.
        s = self.store

        t1 = TestEvent(testCase=self,
                       name='t1',
                       store=s, runAgain=None)
        t2 = TestEvent(testCase=self,
                       name='t2',
                       store=s, runAgain=2)
        t3 = TestEvent(testCase=self,
                       name='t3',
                       store=s, runAgain=None)

        now = self.now()
        self.ts = [t1, t2, t3]

        S = IScheduler(s)

        # Schedule them out of order to make sure behavior doesn't
        # depend on tasks arriving in soonest-to-latest order.
        S.schedule(t2, now + timedelta(seconds=3))
        S.schedule(t1, now + timedelta(seconds=1))
        S.schedule(t3, now + timedelta(seconds=100))

        self.clock.pump([2, 2, 2])
        self.assertEqual(t1.runCount, 1)
        self.assertEqual(t2.runCount, 2)
        self.assertEqual(t3.runCount, 0)

    def test_unscheduling(self):
        """
        Test the unscheduleFirst method of the scheduler.
        """
        sch = IScheduler(self.store)
        t1 = TestEvent(testCase=self, name='t1', store=self.store)
        t2 = TestEvent(testCase=self, name='t2', store=self.store, runAgain=None)

        sch.schedule(t1, self.now() + timedelta(seconds=1))
        sch.schedule(t2, self.now() + timedelta(seconds=2))
        sch.unscheduleFirst(t1)
        self.clock.advance(3)
        self.assertEqual(t1.runCount, 0)
        self.assertEqual(t2.runCount, 1)

    def test_inspection(self):
        """
        Test that the L{scheduledTimes} method returns an iterable of all the
        times at which a particular item is scheduled to run.
        """
        now = self.now() + timedelta(seconds=1)
        off = timedelta(seconds=3)
        sch = IScheduler(self.store)
        runnable = TestEvent(store=self.store, name='Only event')
        sch.schedule(runnable, now)
        sch.schedule(runnable, now + off)
        sch.schedule(runnable, now + off + off)

        self.assertEqual(
            list(sch.scheduledTimes(runnable)),
            [now, now + off, now + off + off])

    def test_scheduledTimesDuringRun(self):
        """
        L{Scheduler.scheduledTimes} should not include scheduled times that have
        already triggered.
        """
        futureTimes = []
        scheduler = IScheduler(self.store)
        runner = HookRunner(
            store=self.store,
            hook=lambda self: futureTimes.append(
                list(scheduler.scheduledTimes(self))))

        then = self.now() + timedelta(seconds=1)
        scheduler.schedule(runner, self.now())
        scheduler.schedule(runner, then)
        self.clock.advance(1)
        self.assertEqual(futureTimes, [[then], []])

    def test_deletedRunnable(self):
        """
        Verify that if a scheduled item is deleted,
        L{TimedEvent.invokeRunnable} just deletes the L{TimedEvent} without
        raising an exception.
        """
        now = self.now()
        scheduler = IScheduler(self.store)
        runnable = TestEvent(store=self.store, name='Only event')
        scheduler.schedule(runnable, now)

        runnable.deleteFromStore()

        # Invoke it manually to avoid timing complexity.
        timedEvent = self.store.findUnique(
            TimedEvent, TimedEvent.runnable == runnable)
        timedEvent.invokeRunnable()

        self.assertEqual(
            self.store.findUnique(
                TimedEvent,
                TimedEvent.runnable == runnable,
                default=None),
            None)

class TopStoreSchedTest(SchedTest, TestCase):
    def setUp(self):
        self.store = self.siteStore = Store()
        super(TopStoreSchedTest, self).setUp()

    def test_namedService(self):
        """
        The site store IScheduler implementation can be retrieved as a named
        service from the store's IServiceCollection powerup.
        """
        self.assertIdentical(
            IService(self.store).getServiceNamed(SITE_SCHEDULER),
            IScheduler(self.store))

    def testBasicScheduledError(self):
        S = IScheduler(self.store)
        S.schedule(NotActuallyRunnable(store=self.store), self.now())

        te = TestEvent(store=self.store, testCase=self,
                       name='t1', runAgain=None)
        S.schedule(te, self.now() + timedelta(seconds=1))

        self.assertEqual(
            self.store.query(TimedEventFailureLog).count(), 0)

        self.clock.advance(3)

        self.assertEqual(te.runCount, 1)

        errs = self.flushLoggedErrors(AttributeError)
        self.assertEqual(len(errs), 1)
        self.assertEqual(self.store.query(TimedEventFailureLog).count(), 1)

    def testScheduledErrorWithHandler(self):
        S = IScheduler(self.store)
        spec = SpecialErrorHandler(store=self.store)
        S.schedule(spec, self.now())

        te = TestEvent(store=self.store, testCase=self,
                       name='t1', runAgain=None)
        S.schedule(te, self.now() + timedelta(seconds=1))
        self.assertEqual(
            self.store.query(TimedEventFailureLog).count(), 0)

        self.clock.advance(3)

        self.assertEqual(te.runCount, 1)

        errs = self.flushLoggedErrors(SpecialError)
        self.assertEqual(len(errs), 1)
        self.assertEqual(self.store.query(TimedEventFailureLog).count(), 0)
        self.assertTrue(spec.procd)
        self.assertFalse(spec.broken)

class SubSchedulerTests(SchedTest, TestCase):
    """
    Tests for the substore implementation of IScheduler.
    """
    def setUp(self):
        """
        Create a site store for the substore which will contain the IScheduler
        being tested.  Start its IService so any scheduled events will run.
        """
        self.storePath = filepath.FilePath(self.mktemp())
        self.siteStore = Store(self.storePath)
        super(SubSchedulerTests, self).setUp()

        substoreItem = SubStore.createNew(self.siteStore, ['scheduler_test'])
        self.substore = substoreItem.open()
        self.scheduler = scheduler = IScheduler(self.substore)
        self.stubTime(scheduler)

        self.store = self.substore

    def test_now(self):
        """
        The user store's L{IScheduler} powerup's C{now} method returns whatever
        the site store's L{IScheduler} powerup's C{now} method returns.
        """
        # I don't want the stubbed now method.
        del self.scheduler.now

        self.clock.advance(17)
        self.assertEqual(
            self.scheduler.now(),
            Time.fromPOSIXTimestamp(self.clock.seconds()))

    def test_scheduleAfterParentHookError(self):
        """
        A transient error during a L{_SubSchedulerParentHook} run (such as
        failing to open the substore for whatever reason) should not disable
        subsequent scheduling.
        """
        runnable = TestEvent(store=self.store)

        # Schedule runnable, but fail the _SubSchedulerParentHook run.

        self.scheduler.schedule(runnable, self.now() + timedelta(seconds=1))
        hook = self.siteStore.findUnique(_SubSchedulerParentHook)
        def stumble():
            raise IOError('Denied')
        object.__setattr__(hook, 'run', stumble)
        self.clock.advance(1)
        object.__delattr__(hook, 'run')

        self.assertEqual(
            self.siteStore.findUnique(TimedEventFailureLog).runnable,
            hook)
        [err] = self.flushLoggedErrors(IOError)
        self.assertEqual(str(err.value), 'Denied')
        self.assertEqual(runnable.runCount, 0)

        # Schedule runnable again.  The restored hook in the site store should
        # trigger both scheduled runs in the substore now.

        self.scheduler.schedule(runnable, self.now() + timedelta(seconds=1))
        self.clock.advance(1)
        self.assertEqual(runnable.runCount, 2)

class SchedulerStartupTests(TestCase):
    """
    Tests for behavior relating to L{Scheduler} service startup.
    """
    def setUp(self):
        self.clock = Clock()
        self.store = Store()

    def tearDown(self):
        return self.stopStoreService()

    def now(self):
        return Time.fromPOSIXTimestamp(self.clock.seconds())

    def time(self, offset):
        return self.now() + timedelta(seconds=offset)

    def makeScheduler(self):
        """
        Create, install, and return a Scheduler with a fake callLater.
        """
        scheduler = IScheduler(self.store)
        scheduler.callLater = self.clock.callLater
        scheduler.now = self.now
        return scheduler

    def startStoreService(self):
        """
        Start the Store Service.
        """
        service = IService(self.store)
        service.startService()

    def stopStoreService(self):
        service = IService(self.store)
        if service.running:
            return service.stopService()

    def test_schedulerStartsWhenServiceStarts(self):
        """
        Test that IScheduler(store).startService() gets called whenever
        IService(store).startService() is called.
        """
        service = IService(self.store)
        service.startService()
        scheduler = service.getServiceNamed(SITE_SCHEDULER)
        self.assertTrue(scheduler.running)

    def test_scheduleWhileStopped(self):
        """
        Test that a schedule call on a L{Scheduler} which has not been started
        does not result in the creation of a transient timed event.
        """
        scheduler = self.makeScheduler()
        scheduler.schedule(TestEvent(store=self.store), self.time(1))
        self.assertEqual(self.clock.calls, [])

    def test_scheduleWithRunningService(self):
        """
        Test that if a scheduler is created and installed on a store which has
        a started service, a transient timed event is created when the scheduler
        is used.
        """
        self.startStoreService()
        scheduler = self.makeScheduler()
        scheduler.schedule(TestEvent(store=self.store), self.time(1))
        self.assertEqual(len(self.clock.calls), 1)

    def test_schedulerStartedWithPastEvent(self):
        """
        Test that an existing Scheduler with a TimedEvent in the past is
        started immediately (but does not run the TimedEvent synchronously)
        when the Store Service is started.
        """
        scheduler = self.makeScheduler()
        scheduler.schedule(TestEvent(store=self.store), self.time(-1))
        self.assertEqual(self.clock.calls, [])
        self.startStoreService()
        self.assertEqual(len(self.clock.calls), 1)

    def test_schedulerStartedWithFutureEvent(self):
        """
        Test that an existing Scheduler with a TimedEvent in the future is
        started immediately when the Store Service is started.
        """
        scheduler = self.makeScheduler()
        scheduler.schedule(TestEvent(store=self.store), self.time(1))
        self.assertEqual(self.clock.calls, [])
        self.startStoreService()
        self.assertEqual(len(self.clock.calls), 1)

    def test_schedulerStopped(self):
        """
        Test that when the Store Service is stopped, the Scheduler's transient
        timed event is cleaned up.
        """
        self.test_scheduleWithRunningService()
        d = self.stopStoreService()
        def cbStopped(ignored):
            self.assertEqual(self.clock.calls, [])
        d.addCallback(cbStopped)
        return d

class MissingService(unittest.TestCase):
    """
    A set of tests to verify that things *aren't* scheduled with the reactor
    when the scheduling service doesn't exist, merely persisted to the
    database.
    """

    def setUp(self):
        """
        Create a store with a scheduler installed on it and hook the C{now} and
        C{callLater} methods of that scheduler so their behavior can be
        controlled by these tests.
        """
        self.calls = []
        self.store = Store(filepath.FilePath(self.mktemp()))
        self.siteScheduler = IScheduler(self.store)
        self.siteScheduler.callLater = self._callLater

    def _callLater(self, s, f, *a, **k):
        self.calls.append((s, f, a, k))

    def test_schedule(self):
        """
        Test that if an event is scheduled against a scheduler which is not
        running, not transient scheduling (eg, reactor.callLater) is performed.
        """
        return self._testSchedule(self.siteScheduler)

    def test_subSchedule(self):
        """
        The same as test_schedule, except using a subscheduler.
        """
        subst = SubStore.createNew(self.store, ['scheduler_test'])
        substore = subst.open()
        subscheduler = IScheduler(substore)
        return self._testSchedule(subscheduler)

    def _testSchedule(self, scheduler):
        t1 = TestEvent(store=scheduler.store)
        scheduler.schedule(t1, Time.fromPOSIXTimestamp(0))
        self.failIf(self.calls,
                    "Should not have had any calls: {!r}".format(self.calls))
        self.assertIdentical(
            scheduler._getNextEvent(Time.fromPOSIXTimestamp(1)).runnable, t1)

class ScheduleCallingItem(Item):
    """
    Item which invokes C{schedule} on its store's L{IScheduler} from its own
    C{run} method.
    """

    ran = boolean(default=False)
    rescheduleFor = timestamp()

    def run(self):
        scheduler = IScheduler(self.store)
        scheduler.schedule(self, self.rescheduleFor)
        self.ran = True

class NullRunnable(Item):
    """
    Runnable item which does nothing.
    """
    ran = boolean(default=False)

    def run(self):
        pass

class SubStoreSchedulerReentrancy(TestCase):
    """
    Test re-entrant scheduling calls on an item run by a SubScheduler.
    """
    def setUp(self):
        self.clock = Clock()

        self.dbdir = filepath.FilePath(self.mktemp())
        self.store = Store(self.dbdir)
        self.substoreItem = SubStore.createNew(self.store, ['sub'])
        self.substore = self.substoreItem.open()

        self.scheduler = IScheduler(self.store)
        self.subscheduler = IScheduler(self.substore)

        self.scheduler.callLater = self.clock.callLater
        self.scheduler.now = lambda: Time.fromPOSIXTimestamp(self.clock.seconds())
        self.subscheduler.now = lambda: Time.fromPOSIXTimestamp(self.clock.seconds())

        IService(self.store).startService()

    def tearDown(self):
        return IService(self.store).stopService()

    def _scheduleRunner(self, now, offset):
        scheduledAt = Time.fromPOSIXTimestamp(now + offset)
        rescheduleFor = Time.fromPOSIXTimestamp(now + offset + 10)
        runnable = ScheduleCallingItem(store=self.substore, rescheduleFor=rescheduleFor)
        self.subscheduler.schedule(runnable, scheduledAt)
        return runnable

    def testSchedule(self):
        """
        Test the schedule method, as invoked from the run method of an item
        being run by the subscheduler.
        """
        now = self.clock.seconds()
        runnable = self._scheduleRunner(now, 10)

        self.clock.advance(11)

        self.assertEqual(
            list(self.subscheduler.scheduledTimes(runnable)),
            [Time.fromPOSIXTimestamp(now + 20)])

        hook = self.store.findUnique(
            _SubSchedulerParentHook,
            _SubSchedulerParentHook.subStore == self.substoreItem)

        self.assertEqual(
            list(self.scheduler.scheduledTimes(hook)),
            [Time.fromPOSIXTimestamp(now + 20)])

    def testScheduleWithLaterTimedEvents(self):
        """
        Like L{testSchedule}, but use a SubScheduler which has pre-existing
        TimedEvents which are beyond the new runnable's scheduled time (to
        trigger the reschedule-using code-path in
        _SubSchedulerParentHook._schedule).
        """
        now = self.clock.seconds()
        when = Time.fromPOSIXTimestamp(now + 30)
        null = NullRunnable(store=self.substore)
        self.subscheduler.schedule(null, when)
        runnable = self._scheduleRunner(now, 10)

        self.clock.advance(11)

        self.assertEqual(
            list(self.subscheduler.scheduledTimes(runnable)),
            [Time.fromPOSIXTimestamp(now + 20)])

        self.assertEqual(
            list(self.subscheduler.scheduledTimes(null)),
            [Time.fromPOSIXTimestamp(now + 30)])

        hook = self.store.findUnique(
            _SubSchedulerParentHook,
            _SubSchedulerParentHook.subStore == self.substoreItem)

        self.assertEqual(
            list(self.scheduler.scheduledTimes(hook)),
            [Time.fromPOSIXTimestamp(20)])

    def testScheduleWithEarlierTimedEvents(self):
        """
        Like L{testSchedule}, but use a SubScheduler which has pre-existing
        TimedEvents which are before the new runnable's scheduled time.
        """
        now = self.clock.seconds()
        when = Time.fromPOSIXTimestamp(now + 15)
        null = NullRunnable(store=self.substore)
        self.subscheduler.schedule(null, when)
        runnable = self._scheduleRunner(now, 10)

        self.clock.advance(11)

        self.assertEqual(
            list(self.subscheduler.scheduledTimes(runnable)),
            [Time.fromPOSIXTimestamp(now + 20)])

        self.assertEqual(
            list(self.subscheduler.scheduledTimes(null)),
            [Time.fromPOSIXTimestamp(now + 15)])

        hook = self.store.findUnique(
            _SubSchedulerParentHook,
            _SubSchedulerParentHook.subStore == self.substoreItem)

        self.assertEqual(
            list(self.scheduler.scheduledTimes(hook)),
            [Time.fromPOSIXTimestamp(now + 15)])

    def testMultipleEventsPerTick(self):
        """
        Test running several runnables in a single tick of the subscheduler.
        """
        now = self.clock.seconds()
        runnables = [
            self._scheduleRunner(now, 10),
            self._scheduleRunner(now, 11),
            self._scheduleRunner(now, 12)]

        self.clock.advance(13)

        for n, runnable in enumerate(runnables):
            self.assertEqual(
                list(self.subscheduler.scheduledTimes(runnable)),
                [Time.fromPOSIXTimestamp(now + n + 20)])

        hook = self.store.findUnique(
            _SubSchedulerParentHook,
            _SubSchedulerParentHook.subStore == self.substoreItem)

        self.assertEqual(
            list(self.scheduler.scheduledTimes(hook)),
            [Time.fromPOSIXTimestamp(now + 20)])

class BackwardsCompatibilitySchedTests(object):
    """
    L{Scheduler} and L{SubScheduler} are going to be removed.  In the mean
    time, if someone gets their hands on one and tries to do something
    supported to it, it should be as if they were doing it to the suitable
    replacement, L{_SiteScheduler} or L{_UserScheduler}.  This mixin provides
    tests for that behavior, as well as for the deprecations of L{Scheduler}
    and L{SubScheduler}.

    @ivar schedulerType: L{Scheduler} or L{SubScheduler}, whichever is to be
        tested.
    """
    def setUp(self):
        """
        Create a store with an instance of C{self.schedulerType} in it.
        """
        self.store = Store()
        self.oldScheduler = self.schedulerType(store=self.store)
        warnings = self.flushWarnings([self.setUp])
        self.assertEqual(len(warnings), 1)
        self.assertEqual(warnings[0]['category'], PendingDeprecationWarning)
        self.assertEqual(
            warnings[0]['message'],
            self.schedulerType.__name__ + " is deprecated since Axiom 0.5.32.  "
            "Just adapt stores to IScheduler.")
        self.scheduler = IScheduler(self.store)

    def _checkSynonym(self, name):
        # Whatever the value of the attribute is on the _SiteScheduler or
        # _UserScheduler instance, that's what it should be on the Scheduler
        # or SubScheduler Item.
        foo = object()
        setattr(self.scheduler, name, foo)
        self.assertIdentical(getattr(self.oldScheduler, name), foo)

        # And rebinding the attribute on the (Sub)Scheduler Item should rebind it on
        # the _SiteScheduler instance.
        bar = object()
        setattr(self.oldScheduler, name, bar)
        self.assertIdentical(getattr(self.scheduler, name), bar)

    def test_now(self):
        """
        L{Scheduler.now} is a synonym for L{_SiteScheduler.now}.
        """
        self._checkSynonym("now")

    def test_tick(self):
        """
        L{Scheduler.tick} is a synonym for L{_SiteScheduler.tick}.
        """
        self._checkSynonym("tick")

    def test_schedule(self):
        """
        L{Scheduler.schedule} is a synonym for L{_SiteScheduler.schedule}.
        """
        self._checkSynonym("schedule")

    def test_scheduledTimes(self):
        """
        L{Scheduler.scheduledTimes} is a synonym for
        L{_SiteScheduler.scheduledTimes}.
        """
        self._checkSynonym("scheduledTimes")

    def test_unscheduleAll(self):
        """
        L{Scheduler.unscheduleAll} is a synonym for
        L{_SiteScheduler.unscheduleAll}.
        """
        self._checkSynonym("unscheduleAll")

    def test_reschedule(self):
        """
        L{Scheduler.reschedule} is a synonym for
        L{_SiteScheduler.reschedule}.
        """
        self._checkSynonym("reschedule")

    def test_deprecated(self):
        """
        Loading an existing L{Scheduler} from a L{Store} emits a deprecation
        warning.
        """
        storeID = self.oldScheduler.storeID
        del self.oldScheduler
        gc.collect()
        # Just load the scheduler, we don't need to use it for anything.
        self.store.getItemByID(storeID)
        warnings = self.flushWarnings([self.test_deprecated])
        self.assertEqual(len(warnings), 1)
        self.assertEqual(warnings[0]['category'], PendingDeprecationWarning)
        self.assertEqual(
            warnings[0]['message'],
            self.schedulerType.__name__ + " is deprecated since Axiom 0.5.32.  "
            "Just adapt stores to IScheduler.")

class BackwardsCompatibilitySchedulerTests(BackwardsCompatibilitySchedTests, TestCase):
    schedulerType = Scheduler

    def test_interface(self):
        """
        L{Scheduler} provides L{IScheduler} (which it proxies) and
        L{IService} (which is a no-op).
        """
        self.assertTrue(IScheduler.providedBy(self.oldScheduler))
        self.assertTrue(IService.providedBy(self.oldScheduler))

class BackwardsCompatibilitySubSchedulerTests(BackwardsCompatibilitySchedTests, TestCase):
    schedulerType = SubScheduler

    def test_interface(self):
        """
        L{SubScheduler} provides L{IScheduler} (which it proxies).
        """
        self.assertTrue(IScheduler.providedBy(self.oldScheduler))


#!/usr/bin/python3
"""Python script that takes in a letter and sends a POST request to
http://0.0.0.0:5000/search_user with the letter as a parameter.
"""

from requests import post
from sys import argv

if __name__ == "__main__":
    if len(argv) > 1:
        q = argv[1]
    else:
        q = ""
    try:
        request = post("http://0.0.0.0:5000/search_user",
                       data={'q': q}).json()
        if "id" in request and "name" in request:
            print("[{}] {}".format(request["id"], request["name"]))
        else:
            print("No result")
    except ValueError:
        print("Not a valid JSON")


# This program is to shutdown the computer at a certain time.

import os  # inport Operating System Libary
import time  # inport Time Libary
import datetime  # inport DateTime Libary
from datetime import datetime
from datetime import timedelta
from tkinter import *  # inport tkinter Libary for windows GUI
import tkinter as tk

# make a class
class ShutdownApp(tk.Tk):

    def __init__(self):  # defines all varibles

        # Creating the window GUI
        tk.Tk.__init__(self)
        self.title("---WARNING!---")  # title of the window
        self.label = tk.Label(self, text="", width=100)
        self.iconbitmap(r'rsz_1rsz_city_seal_Xbl_icon.ico')  # icon for window (must be an ico file)
        self.geometry("300x200")  # size of window
        self.myButton = tk.Button(self, text="Shutdown Now", command=self.ButtonAction, width=15)  # Button on window
        self.myButton.pack()
        self.label.pack()
        self.myButton.place(x=90, y=165)  # button placement
        self.protocol("WM_DELETE_WINDOW", False)  # disable "x" button
        self.resizable(width=False, height=False)  # disable resize of window

        # adding the photo
        self.photo = PhotoImage(file="rsz_1rsz_city-seal.png")  # added a picture
        self.photolabel = Label(self, image=self.photo)
        self.photolabel.place(x=100, y=60)  # Where the picture is placed on the window

        # Funtions
        self.getTime()  # gets time initialize

        self.countdown(self.getTime())  # countdown funtion initialize and takes seconds as argument.
        self.remaining = 0
        self.ButtonAction()  # button action initialize

    # This function will take the current time and subtract another time and returns seconds.
    def getTime(self):
        # 86400 is 24 hours
        # cannot work if over that many seconds so keep it to the same day.
        time_delta = datetime.combine(datetime.now().date() + timedelta(), datetime.strptime("19:00:00","%H:%M:%S").time()) - datetime.now()  # subtracts the current time from the time you want to shutdown in 24-hour format.
        return time_delta.seconds  # returns the seconds left till time

    # countdown function takes seconds as an input and returns the time left in 24-hour format
    def countdown(self, remaining=None):
        if remaining is not None:
            self.remaining = remaining

        if self.remaining <= 0:  # if remaining seconds == 0 it shutdowns
            self.label.configure(text="Shutdown...", font=32)
            os.system("shutdown -t 5 -r -f")  # shutdown operation with additional 5 secs
        else:
            self.label.configure(
                text="DISCLAMER: YOU CAN NOT CLOSE THIS WINDOW.\n" + "\nTime left till Shutdown: %s" % time.strftime(
                    "%H:%M:%S", time.gmtime(self.remaining)))  # formats time in a string and takes seconds as inputs.
            self.remaining = self.remaining - 1  # subracts remaing seconds
            self.after(1000, self.countdown)  # tells how fast to update in milliseconds

    def ButtonAction(self):
        os.system("shutdown -t 0 -r -f")  # shutdown command for button.

if __name__ == "__main__":  # main function
    app = ShutdownApp()  # runs program
    app.mainloop()  # runs tkinter window


#!/usr/bin/env python3

import numpy as np
import os
import torch
from derp.controller import Controller
import derp.util

class Clone(Controller):

    def __init__(self, config, car_config, state):
        super(Clone, self).__init__(config, car_config, state)
        self.camera_config = derp.util.find_component_config(car_config, config['thumb']['component'])

        # Show the user what we're working with
        derp.util.print_image_config(self.camera_config)
        derp.util.print_image_config(self.config['thumb'])

        # Prepare camera inputs
        self.bbox = derp.util.get_patch_bbox(self.config['thumb'], self.camera_config)
        self.size = (config['thumb']['width'], config['thumb']['height'])

        # Prepare model
        self.model_dir = derp.util.get_controller_models_path(self.config['name'])
        self.model_path = derp.util.find_matching_file(self.model_dir, 'clone.pt$')
        if self.model_path is not None and os.path.exists(self.model_path):
            self.model = torch.load(self.model_path)
            self.model.eval()
        else:
            print("Clone: Unable to find model path [%s]" % self.model_path)

        # Useful variables for params
        self.prev_steer = 0
        self.prev_speed = 0

        # Data saving
        self.frame_counter = 0

    def prepare_thumb(self):
        frame = self.state[self.config['thumb']['component']]
        patch = derp.util.crop(frame, self.bbox)
        thumb = derp.util.resize(patch, self.size)
        return thumb

    def predict(self):
        status = derp.util.extractList(self.config['status'], self.state)
        self.state['thumb'] = self.prepare_thumb()
        status_batch = derp.util.prepareVectorBatch(status)
        thumb_batch = derp.util.prepareImageBatch(self.state['thumb'])
        status_batch = derp.util.prepareVectorBatch(status)
        if self.model:
            prediction_batch = self.model(thumb_batch, status_batch)
            prediction = derp.util.unbatch(prediction_batch)
            derp.util.unscale(self.config['predict'], prediction)
        else:
            prediction = np.zeros(len(self.config['predict']), dtype=np.float32)
        self.state['prediction'] = prediction

    def plan(self):
        self.predict()
        if self.state['auto']:
            self.state['speed'] = float(self.state['prediction'][0])
            self.state['steer'] = float(self.state['prediction'][1])


from self_driving.testModel import self_driving
from motion_driving.motion import motion_driving
from Modules.getkeys import key_check
import cv2

cap_cam = cv2.VideoCapture(0)

SET_SWITCH = False

while(True):
    if SET_SWITCH:
        self_driving()
    else:
        motion_driving(cap_cam)

    keys = key_check()

    if 'T' in keys:
        SET_SWITCH = not SET_SWITCH
    elif 'Q' in keys:
        break


import os
import re
import time
import csv
from difflib import HtmlDiff
from urllib.parse import urlparse
from selenium.webdriver.common.by import By
from selenium.common.exceptions import WebDriverException
from PIL import Image
from bs4 import BeautifulSoup
from pathlib import Path
import pdb
from lib.common import *
from concurrent import futures

EXCLUDE_KEYWORDS = [
    # "/search/result",
    "usedcar/detail/",
    "usedcar/shop/",
    "inquiry",
    "/usedcar/ajax",
    # "usedcar/search_area/",
    # "usedcar/search_shashu/",
    # "search/shop/pref/",
    # "search_kodawari/pref/01",
    # "usedcar/search_price",
    "page",
    # "usedcar/area_top/",
    # "usedcar/topic/lowprice/",
    # "usedcar/topic/ecocar/",
    # "usedcar/topic/4wd/",
    # "feature/search",
    # "feature/eco_car",
    # "feature/low_price"
    ]

class WebsiteComparer:
    def __init__(self, domain1, domain2, csv_name, is_sp):
        self.logger = init_logger(csv_name)
        self.csv_name = csv_name
        self.count = 0
        self.domain1 = domain1
        self.domain2 = domain2
        self.driver1 = init_driver(is_sp=is_sp)
        self.driver2 = init_driver(is_sp=is_sp)
        # HEADER: 'Path', 'Folder name', 'Pass?', 'Website 1 urls', 'Website 2 urls', 'Exception'
        self.old_paths_checked = self._read_csv(csv_name)
        # init writer using to append new data to file after read all the old data.
        self.writer = init_csv_writer(csv_name)

        self.driver1.get(self.domain1 + "/favorites")
        self.driver2.get(self.domain2 + "/favorites")
        # cookie_names = ["favorite_cars", "passersby_recent_view", "passersby_incomplete_inquiry"]
        add_cookies(self.driver1, ["user_id_mb7"])
        add_cookies(self.driver2, ["user_id_mb8"])

    def count_folders(self, path):
        if not os.path.exists(path):
            return 0

        folders = os.listdir(path)
        return len([x for x in folders if os.path.isdir(os.path.join(path, x))])

    def reach_max_folder(self, path):
        sub_path = Path(path)
        root_path = Path(*sub_path.parts[:5])
        if self.count_folders(root_path) >= 15:
            return True
        while sub_path != root_path:
            folder_count = self.count_folders(sub_path)
            if folder_count >= 8:
                return True
            sub_path = sub_path.parent
        return False

    def get_html_and_urls(self, driver, url, num):
        driver.get(url)
        el = driver.find_element(By.TAG_NAME, 'body')
        ignore_els = self.ignore_els(url)
        time.sleep(1)
        website_page_paths = get_page_paths(driver)
        el.screenshot(f"screenshot{num}.png")
        website_html = self.get_prettified_html(driver, ignore_els)

        return [website_html, website_page_paths]

    def compare_single_page(self, path):
        urls = self.find_website_urls(path)
        if len(urls) != 0:
            return urls

        url1 = urljoin(self.domain1, path)
        url2 = urljoin(self.domain2, path)
        folder_name = f"data/{self.csv_name}{re.sub(r'[?#=&]', '/', path)}"
        split_folder = folder_name.split("/")
        name_removed = folder_name.rsplit('/', 1)[0]
        if len(split_folder) > 5 and self.reach_max_folder(name_removed):
            print(f"Next => Max Folder: {path}")
            return []

        self.count += 1
        self.logger.info(f"{self.count}: Start compare: {path}")
        os.makedirs(folder_name, exist_ok=True)
        try:
            with futures.ThreadPoolExecutor(max_workers=2) as executor:
                # Đưa các nhiệm vụ vào thread pool
                future1 = executor.submit(self.get_html_and_urls, self.driver1, url1, 1)
                future2 = executor.submit(self.get_html_and_urls, self.driver2, url2, 2)

                # Chờ cả 2 nhiệm vụ được thực hiện xong
                futures.wait([future1, future2])

                # Lấy kết quả từ các nhiệm vụ
                website1_html, website1_page_urls = future1.result()
                website2_html, website2_page_urls = future2.result()

            image1 = Image.open("screenshot1.png")
            image2 = Image.open("screenshot2.png")

            # keys1 = self.get_global_key(website1_page_urls)
            # keys2 = self.get_global_key(website2_page_urls)

            # key_equal = self.compare_list(keys1, keys2)

            merge_imgs = self._append_images([image1, image2], aligment='top')
            merge_imgs.save(f"{folder_name}/sc.png")

            diff = HtmlDiff()
            content_diff = diff.make_file(website1_html.splitlines(), website2_html.splitlines(), context=True)
            if "No Differences Found" in content_diff:
                html_pass = True
                self.logger.info("    ----No differences found-----")
            else:
                html_pass = False
                with open(f"{folder_name}/diff.html", "w", encoding="utf-8") as file:
                    file.write(content_diff)
                self.logger.info("    ++++++++DIFF+++++++")

            self._write_to_csv([path, folder_name, html_pass, "\n".join(website1_page_urls), "\n".join(website2_page_urls), ''])

            return list(set(website1_page_urls + website2_page_urls))
        except WebDriverException as ex:
            self._write_to_csv([path, folder_name, '', '', '', ex, ''])
            self.logger.info(f"    Error: {ex}")
            return []

    def compare_multiple_pages(self, path):
        extend_paths = [
            '/usedcar/feature/top', #pc, sp
            '/usedcar/feature/search', #pc, sp
            '/usedcar/feature/low_price', #pc, sp
            '/usedcar/feature/eco_car', #pc, sp
            '/usedcar/feature/Seasonal/1', #pc, sp
            '/usedcar/feature/Seasonal/2', #pc, sp
            # '/usedcar/kcar', #sp
            # '/usedcar/shop/gcs211859002/stock', #sp
            '/usedcar/topic/carmodel', #pc
            '/usedcar/new_arrival_mail', #pc
            '/usedcar/new_arrival_line', #pc
            # '/usedcar/area_top/hokkaido',
            # '/usedcar/area_top/hokushinetsu',
            # '/usedcar/area_top/kansai',
            # '/usedcar/area_top/kanto',
            # '/usedcar/area_top/kyushu',
        ]
        remaining_paths = self.compare_single_page(path) +  extend_paths
        checked_paths = [path, '/usedcar/logout', '/usedcar/recent_search']
        while(remaining_paths):
            if self.count >= 5000:
                return
            current_path = remaining_paths.pop(0)
            if "/usedcar" not in current_path or any(keyword in current_path for keyword in EXCLUDE_KEYWORDS):
                continue

            if current_path in checked_paths:
                continue

            paths = self.compare_single_page(current_path)
            checked_paths.append(current_path)
            remaining_paths.extend(paths)
            print(f"Remaining urls left: {len(set(remaining_paths))}")
        self.logger.info(f"Remaining urls left: {len(set(remaining_paths))}")

    def find_website_urls(self, test_path):
        if test_path in self.old_paths_checked:
            return self.old_paths_checked[test_path]
        return []

    def get_prettified_html(self, driver, ignore_els):
        page_source = driver.page_source
        soup = BeautifulSoup(page_source, 'html.parser')

        elements = soup.select(", ".join(ignore_els))

        for element in elements:
            element.extract()

        self._remove_domain_from_links(soup, 'a', 'href')
        self._remove_domain_from_links(soup, 'form', 'action')

        return soup.body.prettify()

    def _remove_domain_from_links(self, soup, tag_name, attribute):
        for tag in soup.find_all(tag_name):
            attr_value = tag.get(attribute)
            if attr_value:
                new_value = urlparse(attr_value).path
                tag[attribute] = new_value

    def _read_csv(self, file_name):
        try:
            data = {}
            with open(f"data/{file_name}.csv", 'r') as file:
                reader = csv.reader(file)

                for row in reader:
                    data[row[0]] = row[3].split("\n") + row[4].split("\n")

            return data
        except FileNotFoundError:
            self.logger.info(f"File not found. New file created: data/{file_name}.csv")
            return {}

    def _write_to_csv(self, data):
        write_to_csv(self.writer, data)

    def _append_images(self, images, direction='horizontal', bg_color=(255,255,255), aligment='center'):
        widths, heights = zip(*(i.size for i in images))

        if direction=='horizontal':
            new_width = sum(widths)
            new_height = max(heights)
        else:
            new_width = max(widths)
            new_height = sum(heights)

        new_im = Image.new('RGB', (new_width, new_height), color=bg_color)

        offset = 0
        for im in images:
            if direction=='horizontal':
                y = 0
                if aligment == 'center':
                    y = int((new_height - im.size[1])/2)
                elif aligment == 'bottom':
                    y = new_height - im.size[1]
                new_im.paste(im, (offset, y))
                offset += im.size[0]
            else:
                x = 0
                if aligment == 'center':
                    x = int((new_width - im.size[0])/2)
                elif aligment == 'right':
                    x = new_width - im.size[0]
                new_im.paste(im, (x, offset))
                offset += im.size[1]

        return new_im

    def compare_list(self, l1, l2):
        l1.sort()
        l2.sort()
        if (l1 == l2):
            return True
        return False

    def get_global_key(self, urls):
        keys = []
        for url in urls:
            if "usedcar/detail/" not in url and "usedcar/shop/" not in url:
                continue
            if 'stock' in url:
                url = url.split("/stock")[0]
            key = url.rsplit("/", 1)[1]
            keys.append(key)
        return keys

    def ignore_els(self, url):
        ignore_els = [
            '.image',
            'input[name="authenticity_token"]',
            '[id^="batBeacon"]',
            '.ls-is-cached',
            '.lazyloading',
            '.lazyloaded',
            '.box_new',
            '.recommend-list-sp',
            '#page-top',
            '#ajax-recommends',
            '.ranking_list',
            '.ranking-shop',
            'img',
            '.status__label-list',
            '.information_board_pickup',
            '.ranking-list-item',
            '.recommendation_item',
            'source', # diff in url source image
            '.heading-level-02.header-fixed', # diff in style opacity
            '.favorite_count',
            '.recommendation_box_list',
            'script',
            '.usedResultList_item', # pc
            '.resultModePhoto', #pc
            '#user_search',
            '.internal-links-list.cf', # recommend result
            '.table_shop_pickup', # information board - pc
            # '.information_board_pickup', # information board - sp - tmp
            '.btn_line', # login/logout button
        ]

        if "feature" in url or 'search/result' in url or 'detail' in url:
            ignore_els += ['.balloon_message', '.result-wrap', '.review_detail_slider']
        elif "area_top" in url or "gd_city" in url:
            ignore_els.append('#resultWrapper')
        elif "topic" in url:
            ignore_els += ['iframe', 'noscript', 'meta']
        return ignore_els


#!/usr/bin/env python3
import collections
import copy
import operator
import pathlib
import re

with open(pathlib.Path(__file__).parent / "input" / "day_05.txt") as f:
    text_stacks, text_moves = f.read().strip("\n").split("\n\n")

stacks_n = 9
stack_col_index = lambda i: 1 + 4 * (i - 1)
col = lambda i: tuple(row[i] for row in text_stacks.split("\n"))

stacks = tuple(
    map(
        lambda i: collections.deque(filter(str.isalpha, col(i))),
        map(stack_col_index, range(1, stacks_n + 1)),
    )
)

pattern = r"move (\d+) from (\d+) to (\d+)"
moves = tuple(map(lambda x: tuple(map(int, x)), re.findall(pattern, text_moves)))

backup = copy.deepcopy(stacks)
for (count, src, dest) in moves:
    stacks[dest - 1].extendleft(stacks[src - 1].popleft() for _ in range(count))

# First puzzle answer
print("".join(map(operator.itemgetter(0), stacks)))

stacks = backup
for (count, src, dest) in moves:
    stacks[dest - 1].extendleft(
        reversed(tuple(stacks[src - 1].popleft() for _ in range(count)))
    )

# Second puzzle answer
print("".join(map(operator.itemgetter(0), stacks)))


#!/usr/bin/env python
# coding: utf-8

#
# # MACD Implementation
#
#

# ## Celem projektu jest zaipmlementowanie wskaźnika giełdowego MACD
# ## i opracowanie algorytmu , który na podstawie MACD będzie
# ## podejmował za nas decyzje o sprzedaży i zakupie

# ### Importing libraries
#

# In[4]:

import numpy as np
import math
import pandas as pd
import matplotlib.pyplot as plt
import matplotlib.dates as mdates
get_ipython().run_line_magic('matplotlib', 'inline')
import mpld3
mpld3.enable_notebook()

# ### Parsowanie danych wejściowych z pliku (txt/csv)
#

# In[5]:

data = pd.read_csv('TSLA.csv')
#data = pd.read_csv('MSFT.csv')
start_date = '2016-01-01'
end_date = '2021-01-01'
prices_with_date =  data.loc[(data['Date'] > start_date) & (data['Date'] < end_date)]
prices_with_date

# ### Wizualizacja danych wejściowych
#
#
#

# In[6]:

price_array = prices_with_date['Close']
date_array = pd.to_datetime(prices_with_date['Date'])
plt.figure(figsize=(10, 5))
plt.xlabel("dni")
plt.ylabel("money")
plt.plot( date_array, price_array,label = "Closed price")
plt.gcf().autofmt_xdate()
plt.tight_layout()
plt.legend()
plt.show()

# ### EMA formula
# #### Function that compute Exponential Moving Average
# #### where n is period
# #### prices is an array of price with length n;

# In[8]:

def EMA(prices,n):
    a = 2/(n+1)
    wagi = (1-a)**np.arange(n,-1,-1)
    return (wagi*prices).sum()/wagi.sum()

# ### Calculating EMA1 with period 12 and EMA2 with period 26
# #### And EMA1 - EMA2
# ####  Calculating Exponensial moving average starting with 26 day because it's impossible to calculate EMA_2(26) before this day

# In[9]:

price_array
period_1 = 12
period_2 = 26
EMA1 = []
EMA2 = []
MACD = []
for i in range(period_2,price_array.size):
    ema_elem1 = EMA(price_array[i-period_1:i], period_1-1)
    EMA1.append(ema_elem1)
    ema_elem2 = EMA(price_array[i-period_2:i],period_2-1)
    EMA2.append(ema_elem2)
    MACD.append(ema_elem1 - ema_elem2)

# #### start drawing plot starting 26 day.
#

# In[10]:

plt.figure(figsize=(10, 10))
plt.xlabel("dni")
plt.ylabel("money")
plt.plot(date_array,price_array, label = "closed price")
plt.plot(date_array[period_2:],EMA1, label= "EMA12")
plt.plot(date_array[period_2:],EMA2, label= "EMA26")
plt.plot(date_array[period_2:],MACD, label= "MACD")
plt.legend()

# ### Implementacja wskaźnika MACD
#
# #### Linii Sygnal i MACD
# #### invest dates starting with period 2 + period 3 = 26 + 9 = 35 day
# #### invest points shows where exactly crossing of two lines happend
# #### invest dicision True - sell , False - buy
#

# In[11]:

period_3 = 9
Sygnal = []
for i in range(period_3,len(MACD)):
    Sygnal.append(EMA(MACD[i-period_3:i],period_3-1))

MACD_is_higher = MACD[0] > Sygnal[0]
invest_dates = []
invest_price = []
invest_decision = []
change_cnt = 0

# ### Ploting
#

# In[12]:

plt.figure(figsize=(10, 5))
plt.xlabel("dni")
plt.ylabel("money")
plt.plot(date_array[period_2+period_3:], Sygnal,label="Sygnal")
plt.plot(date_array[period_2+period_3:], MACD[period_3:],label="MACD")
plt.plot(date_array[period_2+period_3:],price_array[period_2+period_3:],label = "closed price")
difference = np.array(MACD[period_3:]) - np.array(Sygnal)
plt.legend()

# In[13]:

# True - buy
MACD_bigger = difference[0] > 0
invest = []
for i in range(0,len(difference)):
    is_change = False
    if difference[i] > 0 and MACD_bigger == False:
        MACD_bigger = True
        invest.append((True, np.array(price_array)[period_2+period_3+i]))
    elif difference[i] < 0 and MACD_bigger == True:
        MACD_bigger = False
        invest.append((False, np.array(price_array)[period_2+period_3+i]))

# ## Analiza i omówienie wyników, wniosków
#
#
#

# ## Analiza automatycznego zarabiania przez algorytm

# In[14]:

gotowka = 0
stock = 1000
price_begin = np.array(price_array)[period_2+period_3]
print("price_begin:" + str(price_begin))
print("Stock begin:" + str(stock))
print("Gotowka:" + str(gotowka))
money_begin = stock * price_begin + gotowka

for decision, price in invest:
    if decision: # BUY
        amount =  math.floor(gotowka/price)
        stock += amount
        gotowka -= price * amount
    else:# SELL
        amount = stock
        gotowka += amount * price
        stock -= amount
price_end = np.array(price_array)[-1]
money_end = stock * price_end + gotowka
print("price_end:" + str(price_end))
print("Stock end:" + str(stock))
print("Gotowka:" + str(gotowka))
print("Money end/ Money Begin " + str(money_end/ money_begin))
print("Algorytm Save and Keep " + str(price_end/price_begin))

# #### Algorytm sprzedawania wszystkich akcji (dla Microsoft i Tesla)daje wynik gorszy niż zachowanie tych akcji.
# #### Z tego wynika ze wykorzystanie MACD nie jest skuteczne(przynajmniej dla tych kompanij i algorytmu w którym sprzedajemy wszytko i kupujemy ile się da).

# In[30]:

gotowka = 0
stock = 1000
price_begin = np.array(price_array)[period_2+period_3]
print("price_begin:" + str(price_begin))
print("Stock begin:" + str(stock))
print("Gotowka:" + str(gotowka))
money_begin = stock * price_begin + gotowka
amount = 100
for decision, price in invest:
    if decision: # BUY
        stock += amount
        gotowka -= price * amount
    else:# SELL
        gotowka += amount * price
        stock -= amount
price_end = np.array(price_array)[-1]
money_end = stock * price_end + gotowka
print("price_end:" + str(price_end))
print("Stock end:" + str(stock))
print("Gotowka:" + str(gotowka))
print("Money end/ Money Begin " + str(money_end/ money_begin))
print("Algorytm Save and Keep " + str(price_end/price_begin))

# ### Wyniki lepsze gdy sprzedajemy część akcji
# #### Im bliżej liczba sprzedanych/ kupowanych do 0 tym bardziej strategia podobna do przechowywania akcji.

# # Podsumowanie:
# ### Myśle że nie odkryłem pełnego potencjalu MACD. Mój algorytm pozwala zarobić, ale mniej niż to możliwe.


import dns.resolver

from spiderfoot import SpiderFootEvent, SpiderFootPlugin

class sfp_cleanbrowsing(SpiderFootPlugin):

    meta = {
        'name': "CleanBrowsing.org",
        'summary': "Check if a host would be blocked by CleanBrowsing.org DNS",
        'flags': [""],
        'useCases': ["Investigate", "Passive"],
        'categories': ["Reputation Systems"],
        'dataSource': {
            'website': "https://cleanbrowsing.org/",
            'model': "FREE_NOAUTH_UNLIMITED",
            'references': [
                "https://cleanbrowsing.org/guides/",
                "https://cleanbrowsing.org/how-it-works",
                "https://cleanbrowsing.org/web-filtering-for-shools-and-cipa-compliance",
                "https://cleanbrowsing.org/getting-started"
            ],
            'favIcon': "https://cleanbrowsing.org/favicon-new.ico",
            'logo': "https://cleanbrowsing.org/images/logos/CleanBrowsing-logo-large-2019-Orange-II.png",
            'description': "You get to decide what type of content is allowed in your home or network via our "
            "DNS-based content filtering service. Parents can protect their kids from adult content, "
            "schools can be CIPA compliant and businesses can block malicious domains and "
            "gain visibility into their network.\n"
            "CleanBrowsing is a DNS-based content filtering service that offers a safe way to browse the web without surprises. "
            "It intercepts domain requests and filter sites that should be blocked, based on your requirements. "
            "Our free family filter, for example, blocks adult content, while still allowing Google, "
            "Youtube, Bing, DuckDuckGo and the rest of the web to load safely.",
        }
    }

    opts = {
    }

    optdescs = {
    }

    results = None

    def setup(self, sfc, userOpts=dict()):
        self.sf = sfc
        self.results = self.tempStorage()

        for opt in list(userOpts.keys()):
            self.opts[opt] = userOpts[opt]

    def watchedEvents(self):
        return [
            "INTERNET_NAME",
            "AFFILIATE_INTERNET_NAME",
            "CO_HOSTED_SITE"
        ]

    def producedEvents(self):
        return [
            "MALICIOUS_INTERNET_NAME",
            "MALICIOUS_AFFILIATE_INTERNET_NAME",
            "MALICIOUS_COHOST"
        ]

    def queryAddr(self, qaddr):
        res = dns.resolver.Resolver()
        res.nameservers = ["185.228.168.168", "185.228.168.169"]

        try:
            addrs = res.resolve(qaddr)
            self.sf.debug(f"Addresses returned: {addrs}")
        except Exception:
            self.sf.debug(f"Unable to resolve {qaddr}")
            return False

        if addrs:
            return True
        return False

    def handleEvent(self, event):
        eventName = event.eventType
        srcModuleName = event.module
        eventData = event.data
        parentEvent = event

        self.sf.debug(f"Received event, {eventName}, from {srcModuleName}")

        if eventData in self.results:
            return

        self.results[eventData] = True

        # Check that it resolves first, as it becomes a valid
        # malicious host only if NOT resolved by CleanBrowsing.org.
        if not self.sf.resolveHost(eventData):
            return

        found = self.queryAddr(eventData)

        # Host was found, not blocked
        if found:
            return

        typ = "MALICIOUS_" + eventName

        if eventName == "CO_HOSTED_SITE":
            typ = "MALICIOUS_COHOST"

        evt = SpiderFootEvent(
            typ,
            f"Blocked by CleanBrowsing.org [{eventData}]",
            self.__name__,
            parentEvent
        )
        self.notifyListeners(evt)

# End of sfp_cleanbrowsing class


from celery import shared_task
from django.utils import timezone
import time
from reddit.models import RedditPost
import os
import datetime

import sys
sys.path.append("../")
from text_classifier import classify_text_inputs

@shared_task
def update_posts():
    start = time.time()
    log_file = 'log.txt'
    error_file = 'error.txt'
    if not os.path.exists(log_file):
        open(log_file, 'w').close()  # Create an empty file
    if not os.path.exists(error_file):
        open(error_file, 'w').close()  # Create an empty file
    posts = RedditPost.objects.all()
    successes = 0
    failures = 0
    total = 0
    for post in posts:
        total += 1
        try:
            lastest_comments = post.get_updated_comments()
            if len(lastest_comments) == post.num_top_level_comments:
                successes += 1
                continue
            post.update()
            sa_results = classify_text_inputs(lastest_comments)
            post.set_num_top_level_comments(len(lastest_comments))
            post.set_sentiment_analysis_results(sa_results)
            post.save()
            successes += 1
        except Exception as e:
            failures += 1
            print(e)
            with open(error_file, 'a') as ef:
                f.write(str(e) + '\n')
            continue

    with open(log_file, 'a') as f:
        current_time = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
        f.write(
            f"Updated {total} posts with {successes}/{total} successes and {failures}/{total} failures at {current_time}. Took {time.time() - start} seconds.\n")


#!/usr/bin/python
#===============================================================================
# This file is part of PyManageMC.
#
#    PyManageMC is free software: you can redistribute it and/or modify
#    it under the terms of the GNU General Public License as published by
#    the Free Software Foundation, either version 2 of the License, or
#    (at your option) any later version.
#
#    PyManageMC is distributed in the hope that it will be useful,
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#    GNU General Public License for more details.
#
#    You should have received a copy of the GNU General Public License
#    along with PyManageMC.  If not, see http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
#===============================================================================
'''
Created on Apr 11, 2014

@author: Paulson McIntyre (GpMidi) <paul@gpmidi.net>
'''
# Logging
import logging
log = logging.getLogger('mcdocker.views')

# Built-in
import os, os.path, sys  # @UnusedImport
import urllib

# External
from django.core.exceptions import ObjectDoesNotExist  # @UnusedImport
from django.shortcuts import render_to_response, get_object_or_404, render, redirect  # @UnusedImport
from django.db.models import Q  # @UnusedImport
from django.template import RequestContext  # @UnusedImport
from django.contrib.auth.models import AnonymousUser  # @UnusedImport
from django.views.decorators.cache import cache_page  # @UnusedImport
from django.core.paginator import Paginator, EmptyPage, InvalidPage  # @UnusedImport
from django.contrib.auth.decorators import login_required, permission_required
from django.http import Http404
from couchdbkit.exceptions import ResourceNotFound  # @UnusedImport

# Ours
from minecraft.models import *  # @UnusedWildImport
from mcdocker.models import *  # @UnusedWildImport
from mcdocker.tasks import *  # @UnusedWildImport
from mcdocker.forms import *  # @UnusedWildImport

@login_required
@permission_required('mcdocker.view_dockerimage')
@permission_required('mcdocker.change_dockerimage')
def dockerImageBuild(req, dockerImageId):
    """ Docker Image Change """
    try:
        di = DockerImage.get(dockerImageId)
        job = doBuildImage(di=di)
        return redirect('DockerImageEdit', di._id)
    except ResourceNotFound:
        raise Http404("Couldn't find an image with id %r" % dockerImageId)

@login_required
@permission_required('mcdocker.view_dockerimage')
def dockerImageIndex(req):
    """ Docker Image index """
    return render_to_response(
                              'mcdocker/dockerMgmt/index.djhtml',
                              dict(
                                   allImages=DockerImage.view('mcdocker/allOSImages'),
                                   baseImages=DockerImage.view('mcdocker/baseOSImages'),
                                   userImages=DockerImage.view('mcdocker/userOSImages'),
                                   ),
                              context_instance=RequestContext(req),
                              )

@login_required
@permission_required('mcdocker.view_dockerimage')
@permission_required('mcdocker.change_dockerimage')
def dockerImageEdit(req, dockerImageName):
    """ Docker Image Change """
    try:
        return render_to_response(
                                  'mcdocker/dockerMgmt/edit.djhtml',
                                  dict(
                                       image=DockerImage.get(dockerImageName),
                                       ),
                                  context_instance=RequestContext(req),
                                  )
    except ResourceNotFound:
        raise Http404("Couldn't find an image named %r" % dockerImageName)

@login_required
@permission_required('mcdocker.view_dockerimage')
@permission_required('mcdocker.add_dockerimage')
def dockerImageCreate(req):
    """ Docker Image Add """
    if req.method == 'POST':
        form = NewDockerInstanceForm(req.POST)
        if form.is_valid():
            di = DockerImage(
                             _id=form.cleaned_data['itag'],
                             humanName=form.cleaned_data['humanName'],
                             humanDescription=form.cleaned_data['description'],
                             imageType='UserImage',
                             imageID=None,
                             dockerParent=form.cleaned_data['baseImage'],
                             dockerMemoryLimitMB=form.cleaned_data['dockerMemoryLimitMB'],
                             dockerCPUShare=form.cleaned_data['dockerCPUShare'],
                             dockerName=form.cleaned_data['dockerName'],
                             dockerIndexer=form.cleaned_data['dockerIndexer'],
                             repo=form.cleaned_data['repo'],
                             tag=form.cleaned_data['tag'],
                             user=form.cleaned_data['user'],
                             uid=form.cleaned_data['uid'],
                             gid=form.cleaned_data['gid'],
                             supervisordUser=form.cleaned_data['supervisordUser'],
                             supervisordAutoRestart=form.cleaned_data['supervisordAutoRestart'],
                             supervisordAutoStart=form.cleaned_data['supervisordAutoStart'],
                             supervisordStartTimeSeconds=form.cleaned_data['supervisordStartTimeSeconds'],
                             extraPackages=map(lambda x: x.rstrip(), form.cleaned_data['extraPackages'].splitlines()),
                             sshKeysRoot=map(lambda x: x.rstrip(), form.cleaned_data['sshKeysRoot'].splitlines()),
                             sshKeysMinecraft=map(lambda x: x.rstrip(), form.cleaned_data['sshKeysMinecraft'].splitlines()),
                             firstName=form.cleaned_data['firstName'],
                             lastName=form.cleaned_data['lastName'],
                             email=form.cleaned_data['email'],
                             javaMaxMemMB=form.cleaned_data['javaMaxMemMB'],
                             javaInitMemMB=form.cleaned_data['javaInitMemMB'],
                             javaGCThreads=form.cleaned_data['javaGCThreads'],
                             )
            di.save()
            return redirect('DockerImageEdit', di._id)
    else:
        form = NewDockerInstanceForm()

    return render_to_response(
                              'mcdocker/dockerMgmt/add.djhtml',
                              dict(
                                   form=form,
                                   ),
                              context_instance=RequestContext(req),
                              )

@login_required
@permission_required('mcdocker.view_dockerimage')
@permission_required('mcdocker.add_dockerimage')
@permission_required('mcdocker.add_basedockerimage')
def dockerBaseImageCreate(req):
    """ Docker Image Add """
    if req.method == 'POST':
        form = BaseDockerInstanceForm(req.POST)
        if form.is_valid():
            # TODO: Catch model validation errors and pass to user as something friendly
            di = DockerImage(
                             _id=form.cleaned_data['itag'],
                             humanName=form.cleaned_data['humanName'],
                             humanDescription=form.cleaned_data['description'],
                             imageType='BaseImage',
                             imageID=None,
                             # TODO: Stop hard coding this
                             dockerParent='ubuntu:14.04',
                             dockerName=form.cleaned_data['dockerName'],
                             dockerIndexer=form.cleaned_data['dockerIndexer'],
                             repo=form.cleaned_data['repo'],
                             tag=form.cleaned_data['tag'],
                             proxy=form.cleaned_data['proxy'],
                             extraPackages=map(lambda x: x.rstrip(), form.cleaned_data['extraPackages'].splitlines()),
                             firstName=form.cleaned_data['firstName'],
                             lastName=form.cleaned_data['lastName'],
                             email=form.cleaned_data['email'],
                             )
            di.save()
            return redirect('DockerImageEdit', di._id)
    else:
        form = BaseDockerInstanceForm()

    return render_to_response(
                              'mcdocker/dockerMgmt/add.djhtml',
                              dict(
                                   form=form,
                                   ),
                              context_instance=RequestContext(req),
                              )


'''

'''
import pdb
import argparse
import os
import sys
import utils.matching_normalization as mt_norm

sys.path.append(os.getcwd())
parser = argparse.ArgumentParser()
parser.add_argument("--mci_stationary_data_path", type=str, default='stationary_data/stationary_dataset_mci.csv')
parser.add_argument("--non_mci_stationary_data_path", type=str, default='stationary_data/stationary_dataset_nonmci.csv')

parser.add_argument("--mci_metadata_path", type=str, default='intermediate_files/mci_metadata.csv')
parser.add_argument("--non_mci_metadata_path", type=str, default='intermediate_files/nonmci_metadata.csv')

parser.add_argument("--matching", type=int, default=1, choices=[0,1])
parser.add_argument("--case_control_ratio", type=int, default=1)

parser.add_argument("--test_ratio", type=int, default=0.3)

output_path = mt_norm.matching(parser.parse_args().mci_stationary_data_path
				,parser.parse_args().non_mci_stationary_data_path
				,parser.parse_args().mci_metadata_path
				,parser.parse_args().non_mci_metadata_path
				,parser.parse_args().case_control_ratio
				,parser.parse_args().matching
				)

mt_norm.normalization(output_path
					,parser.parse_args().test_ratio
					)