from __future__ import division

import unittest

from w3af.core.data.parsers.doc.url import URL
from w3af.core.data.url.HTTPResponse import HTTPResponse
from w3af.core.data.dc.headers import Headers
from w3af.core.controllers.core_helpers.not_found.get_clean_body import get_clean_body

class TestGetCleanBody(unittest.TestCase):

    def test_get_clean_body_14955(self):
        """
        Trying to fix issue 14955
        https://github.com/andresriancho/w3af/issues/14955
        """
        url = URL('http://w3af.org/.git/.git/.git/index')
        headers = Headers([('Content-Type', 'text/html')])

        body = ('<title>Document Moved</title>'
                '
Object Moved
This document may be found '
                'here')

        resp = HTTPResponse(200, body, headers, url, url)

        clean_body = get_clean_body(resp)

        ebody = ('<title>Document Moved</title>'
                 '
Object Moved
This document may be found '
                 'here')
        self.assertEqual(clean_body, ebody)

    def test_get_clean_body_14956(self):
        """
        Trying to fix issue 14956
        https://github.com/andresriancho/w3af/issues/14956
        """
        url = URL('http://w3af.org/install.php?mode=phpinfo')
        headers = Headers([('Content-Type', 'text/html')])

        # Note that the redirect changes the protocol, which is probably why the
        # get_clean_body wasn't removing the URL from the body
        #
        # Also, after this URL is not removed
        body = ('<title>Document Moved</title>'
                '
Object Moved
This document may be found '
                'here')

        resp = HTTPResponse(200, body, headers, url, url)

        clean_body = get_clean_body(resp)

        ebody = ('<title>Document Moved</title>'
                 '
Object Moved
This document may be found '
                 'here')
        self.assertEqual(clean_body, ebody)


import sys
from pathlib import Path

import flask
from flask import Flask, Response, jsonify
from flask_cors import CORS

sys.path.append(str(Path(__file__).resolve().parents[1])) # allows running the api from anywhere

app = Flask(__name__) # flask app creation
CORS(app) # cors patch to allow working with localhost

phonebook = {}

@app.route("/phonebook", methods=["GET"]) # api endpoint, and allowed methods on it
def api_get_phonebook():
    payload = {
        'phonebook': phonebook
    }

    return jsonify(payload), 200 # returned payload and status code

@app.route("/phonebook", methods=["POST"]) # api endpoint, and allowed methods on it
def api_add_to_phonebook():
    name = flask.request.form.get('name')
    phone_number = flask.request.form.get('phone_number')

    if name is None or phone_number is None: # make sure they are defined, otherwise return a 400 error
        return jsonify({'error':'please provide a `name` and a `phone_number` field'}), 400

    print(f"adding {name} and {phone_number} to phonebook")
    phonebook[name] = phone_number

    return jsonify({}), 200 # returned payload and status code

def main():
    phonebook["John"] = "657-532-1112"

if __name__ == "__main__":
    main() # initialize the app (logging, folders etc.)
    app.run(host="0.0.0.0", port=5999) # run the api on localhost on port 5999


import re

def is_spam(text):
    keywords = ['추천', '적중', '온라인', '게임', '적중', '포인트', 'VIP', '신규 첫충', '무제한 충전']
    expression = r'(https?://[^\s]+)'
    url_count = len(re.findall(expression, text))

    if url_count > 0 or any(keyword in text for keyword in keywords):
        return True
    else:
        return False


from itertools import product

def solveDay(my_file):
    data = parse_data(my_file)
    print('Part 1: ', part1(data))
    print('Part 2: ', part2(data[1], tuple(data[0]['42']),
                            tuple(data[0]['31'])))

def parse_data(my_file):
    with open(my_file) as f:
        data = f.read().split('\n\n')
        draft_rules = dict(
            rule.split(': ') for rule in data[0].replace('"', '').split('\n'))
        draft_rules = {
            k: [rule.split() for rule in v.split(' | ')]
            for k, v in draft_rules.items()
        }
        rules = {
            k: v[0]
            for k, v in draft_rules.items() if not v[0][0].isdigit()
        }
        messages = data[1].split()
        find_rule(draft_rules, rules, '0')
        return rules, messages

def find_rule(draft, rules, rule):
    if rule in rules:
        return rules[rule]
    else:
        rules[rule] = sum([[
            ''.join(res)
            for res in (product(*[find_rule(draft, rules, c) for c in comb]))
        ] for comb in draft[rule]], [])
        return rules[rule]

def part1(data):
    return sum(mes in data[0]['0'] for mes in data[1])

def part2(messages, *rules):
    count = 0
    for message in messages:
        result = []
        for rule in rules:
            total = 0
            rule_len = len((rule[0]))
            while True:
                if message.startswith(rule):
                    message = message[rule_len:]
                    total += 1
                else:
                    break
            result.append(total)
        if not message and result[0] > result[1] > 0:
            count += 1
    return count


import datetime
import re
import rfc822
from urllib2 import URLError

from django.conf import settings
from django.http import HttpResponse
from django.shortcuts import render_to_response
from django.template import RequestContext
from django.views.decorators.csrf import csrf_exempt

from mitnkcom.common.utils import get_soup_by_url
from mitnkcom.twitcn.tools import getPrivateApi
from mitnkcom.webapps.notes.models import Note, Word

ASCII_CHARS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"

def index(request):
    book = request.GET.get('book')
    if book:
        notes = Note.objects.filter(book=book)
    else:
        notes = Note.objects.all()
    return render_to_response("webapps/notes.html",
        {'notes': notes},
        context_instance=RequestContext(request))

@csrf_exempt
def check_notes(request):
    if request.method != "POST" or request.POST.get("action") != "notes":
        return HttpResponse(":)")

    try:
        info = fetch_latest_urls()
    except URLError:
        return HttpResponse("URLError occurred!")

    count = 0
    for url, added in info:
        notes = Note.objects.filter(url=url)
        words = Word.objects.filter(url=url)
        if notes.count() > 0 or words.count() > 0:
            continue
        save_note(url, added)
        count +=  1
    return HttpResponse("%s\n" % count)

def fetch_latest_urls():
    token = settings.TWITCN_PRIVATE_TOKEN
    api = getPrivateApi(token)
    messages = api.GetUserTimeline(user='miaoju')

    info = []
    for msg in messages:
        if "#Kindle" not in msg.text or 'http' not in msg.text:
            continue
        url = re.search(r'(http[^ ]+)', msg.text).group(1)
        added = datetime.datetime(*rfc822.parsedate(msg.created_at)[:6])
        info.append((url, added))
    return info

def save_note(url, date=None):
    soup = get_soup_by_url(url)
    tag = soup.find("div", {'class': 'highlightText'})
    text = ''.join(tag.findAll(text=True)).strip()

    remark = ''
    tag = soup.find("div", {'class': 'note'})
    if tag:
        remark = ''.join(tag.findAll(text=True)).replace('Note:', '').replace('@zzrt', '').strip()

    cover_tag = soup.find('div', {'class': 'cover'})
    tag = cover_tag.find("span", {'class': 'title'})
    if tag:
        book = ''.join(tag.findAll(text=True)).strip()
        if 'Personal Document' in book:
            book = ''
    else:
        book = ''

    tag = cover_tag.find("span", {'class': 'author'})
    if tag:
        author = ''.join(tag.findAll(text=True)).replace(' by ', '').strip()
    else:
        author = ''

    if ' ' not in text \
        and text[0] in ASCII_CHARS \
        and len(text) <= 64:
        if Word.objects.filter(word=text).count() == 0:
            Word.objects.create(url=url, word=text)
    else:
        note = Note()
        note.url = url
        note.text = text
        note.added = date or datetime.datetime.now()
        if remark:
            note.remark = remark
        if book:
            note.book = book
        if author:
            note.author = author
        note.save()


class UnionFind:
    def __init__(self,n):
        self.parent = [i for i in range(n)]
        self.height = [0 for _ in range(n)]
    def get_root(self,i):
        if self.parent[i] == i:
            return i
        else:
            self.parent[i] = self.get_root(self.parent[i])
            return self.parent[i]
    def unite(self,i,j):
        root_i = self.get_root(i)
        root_j = self.get_root(j)
        if root_i != root_j:
            if self.height[root_i] < self.height[root_j]:
                self.parent[root_i] = root_j
            else:
                self.parent[root_j] = root_i
                if self.height[root_i] == self.height[root_j]:
                    self.height[root_i] += 1
    def is_in_group(self,i,j):
        if self.get_root(i) == self.get_root(j):
            return True
        else:
            return False

def Kruskal(V,e_list):
    e_cost_sorted = []

    for e in e_list:
        e_cost_sorted.append([e[2],e[0],e[1]])
    e_cost_sorted = sorted(e_cost_sorted,reverse=True)

    uf_tree = UnionFind(V)
    mst = []
    s = 0
    for e in e_cost_sorted:
        print(e)
        if not uf_tree.is_in_group(e[1],e[2]):
            print("Yes")
            uf_tree.unite(e[1],e[2])
            mst.append([e[1],e[2]])
            s += e[0]
            print(s)
    return s

N = int(input())
C = list(map(int,input().split()))
W = list(map(int,input().split()))

edges_list = []
for i in range(N):
    for j in range(i+1,N):
        if C[i] == C[j]:
            e = W[i]+W[j]
            edges_list.append([i,j,e])
            edges_list.append([j,i,e])
        else:
            e = -(W[i]+W[j])
            edges_list.append([i,j,e])
            edges_list.append([j,i,e])

print(Kruskal(N,edges_list))


#队列  先进先出
import queue

# q=queue.Queue
# q.put() #队列放置满阻塞
# q.put_nowait()  #队列放置满报错
# q.get()
# q.get_nowait()

#栈 先进后出
# q=queue.LifoQueue()
# q.put(1)
# q.put(2)
# q.put(3)
# print(q.get())

#优先级队列
q=queue.PriorityQueue()
q.put((20,"a"))
q.put((10,"b"))
q.put((30,"c"))

print(q.get())

并发编程/线程/队列.py


from typing import Optional

from sqlalchemy import Column, BigInteger, ForeignKey, String, Float, Enum
from pydantic import BaseModel, constr
from aplicativo.database import Base
from aplicativo.enumerators.cidade.Cidade import Cidade
from aplicativo.models.utils.ClasseBase import ClasseBase

class Perfil(Base, ClasseBase):
    __tablename__ = "perfil"
    id = Column(BigInteger, primary_key=True, nullable=False)
    usuario_id = Column(ForeignKey("usuario.id"), nullable=False)
    nome = Column(String(255))
    endereco = Column(String(255))
    cidade_id = Column(Enum(Cidade), nullable=False)
    geolocalizacao = Column(Float, nullable=False)
    email = Column(String(255))
    cnpj_cpf = Column(String(255))
    _fields = [
        "usuario_id",
        "nome",
        "endereco",
        "cidade_id",
        "geolocalizacao",
        "email",
        "cnpj_cpf",
    ]

    @staticmethod
    def from_dict(dicionario):
        dicionario["cidade_id"] = Cidade(dicionario["cidade_id"]).name
        return ClasseBase.from_dict(dicionario, Perfil)

    def to_dict(self):
        dicionario = {key: getattr(self, key) for key in self._fields}
        return dicionario

    def to_json(self):
        dicionario = {key: getattr(self, key) for key in self._fields}
        dicionario["cidade_id"] = dicionario["cidade_id"].value
        dicionario["id"] = self.id
        return dicionario

    @staticmethod
    def to_update(dicionario):
        return ClasseBase.to_update(dicionario, Perfil)

    @staticmethod
    def to_update(dicionario):
        fields_to_edit = {
            nome_campo: dicionario[nome_campo]
            for nome_campo in Perfil._fields
            if nome_campo in dicionario
        }
        if fields_to_edit.get("cidade_id"):
            fields_to_edit["cidade_id"] = Cidade(dicionario["cidade_id"]).name
        return fields_to_edit

class PerfilModel(BaseModel):
    id: Optional[int]
    usuario_id: int
    nome: constr(max_length=255)
    endereco: constr(max_length=255)
    cidade_id: int
    geolocalizacao: float
    email: constr(max_length=255)
    cnpj_cpf: constr(max_length=255)


n = int(input())
a_list = list(map(int, input().split()))
ans = 1

if 0 in a_list:
    print(0)
    exit()

for i in range(n):
    ans *= a_list[i]
    if len(str(ans)) > 19 or ans > 10 ** 18:
        print(-1)
        exit()

print(ans)


# -*- coding: utf-8 -*-
import torch
import torch.autograd as autograd
import torch.nn as nn
import torch.nn.functional as F
from torch.autograd import Variable

class TextCNN(nn.Module):

    def __init__(self, config):
        super(TextCNN, self).__init__()
        self.kernel_num = config.kernel_num  # Number of conv kernels
        self.embedding_length = config.wordvec_dim
        self.Ks = config.kernel_sizes
        self.word_embeddings = nn.Embedding(config.weight.shape[0], self.embedding_length)  # Embedding layer
        self.word_embeddings = self.word_embeddings.from_pretrained(config.weight, freeze=False)  # Load pretrianed word embedding, and fine-tuing

        self.convs = nn.ModuleList([nn.Conv2d(1, config.kernel_num, (K, config.wordvec_dim), bias=True) for K in self.Ks])
        self.relu = nn.ReLU(inplace=True)
        self.dropout = nn.Dropout(0.5)
        self.fc = nn.Linear(len(self.Ks)*self.kernel_num, config.label_num)
        self.bn1 = nn.BatchNorm1d(len(self.Ks)*self.kernel_num)
        # self.fc1 = nn.Linear(len(self.Ks)*self.kernel_num, fc1out)
        # self.bn2 = nn.BatchNorm1d(fc1out)
        # self.fc2 = nn.Linear(fc1out, config.label_num)
        self.softmax = nn.Softmax(dim=1)

    def forward(self, x):
        # (batch_size, batch_dim)
        # Embedding
        x = self.word_embeddings(x)  # (batch_size, batch_dim, embedding_len)

        x = x.unsqueeze(1)  # (batch_size, 1, batch_dim, embedding_len)
        # print(x.size())

        # Conv and relu
        x = [self.relu(conv(x)).squeeze(3) for conv in self.convs]  # [(batch_size, kernel_num, batch_dim-K+1), ...]*len(Ks)
        # print([i.shape for i in x])

        # max-over-time pooling (actually merely max)
        x = [F.max_pool1d(xi, xi.size()[2]).squeeze(2) for xi in x] # [(batch_size, kernel_num), ...]*len(Ks)
        # print([i.shape for i in x])
        x = torch.cat(x, dim=1)  # (batch_size, kernel_num*len(Ks))

        x = self.bn1(x)  # Batch Normaliztion
        x = self.dropout(x)  # (batch_size, len(Ks)*kernel_num), dropout
        # print(x.size())

        x = self.fc(x)  # (batch_size, label_num)
        # print(x.size())

        # x = self.fc1(x)
        # x = self.bn2(x)
        # x = self.fc2(x)
        logit = self.softmax(x)
        return logit

if __name__ == '__main__':
    pass


from django.shortcuts import get_object_or_404

from evalapp.models import *

import copy

#ok how to do this
#gather all evaluation objects that are relevant?
#could do that easily if I just arbitrarily set a limit to the number of
#"degrees of separation" I'll allow.  But if I want to use %trust threshholds to
#determine the cutoff, will need to be calculating that as it crawls the network
#I guess I'll start with the simple way, just to get stuff in place and tested
#then I'll modify with fancy stuff :)

def evalReportsAndMap(asker):
	#crawls through the network from the user
	#gathers all reports
	evals = appliedEval.objects.filter(appliedBy = asker)

	evalSet = []
	evaluators = [asker]

	baseSet = {asker: {'upper': 1, 'lower': 1}}

	for i in evals:
		evalSet.append(i)
		if i.appliedTo.userIfAny != None:
			evaluators.append(i.appliedTo.userIfAny)
			baseSet[i.appliedTo.userIfAny] = {'upper':i.evaluation, 'lower': i.evaluation}
		else:
			baseSet[i.appliedTo.referentStandInIfAny] = {'upper':i.evaluation, 'lower': i.evaluation}
	# print(baseSet)

	#need to do one loop for each EVALUATOR
	#not once for each EVALUATION
	#so I need to make a set of all evaluators

	for evaluator in evaluators:
		evalsByUserInLoop = appliedEval.objects.filter(appliedBy = evaluator)
		for x in evalsByUserInLoop:
			if x not in evalSet:
				evalSet.append(x)
			if x.appliedTo.userIfAny != None:
				if x.appliedTo.userIfAny not in evaluators:
					evaluators.append(x.appliedTo.userIfAny)

	return [evalSet, baseSet]

def organizeReportsByIdentity(unorganizedReports):
	#oprganizes reports so that each identity is paired with a set of
	#all evaluations of that identity (whether user or nonuser)

	#input should be QuerySet of all evals
	#output should be dictionary such as:
	#  {itentityObject: [listOfEvalsOfThatIdentity], ...}

	#might also be good to store the map of eval dependencies along with each identity
	#but probably good to make as much of that map in the initial scouting?
	#good in what way?  efficiency?  actually less iterations?  Faster?  Am I sure?
	#  {personUserEvaluated: {whoTheyEvaluated1: {etc.}, whoTheyEvaluated2: {etc}}}

	organizedReports = {}  #initializing

	for each in unorganizedReports:
		if each.appliedTo.userIfAny != None:
			if each.appliedTo.userIfAny in organizedReports:
				organizedReports[each.appliedTo.userIfAny] += [each]
			else:
				organizedReports[each.appliedTo.userIfAny] = [each]
		else:
			if each.appliedTo.referentStandInIfAny in organizedReports:

				organizedReports[each.appliedTo.referentStandInIfAny] += [each]
			else:
				organizedReports[each.appliedTo.referentStandInIfAny] = [each]
	return organizedReports

def makeRatios(report, estimates, ratioSet):
	#adds to numerators and denominators
	#print(report.appliedTo.userIfAny)
	R = float(report.evaluation)
	upperT = float(estimates[report.appliedBy]['upper'])
	lowerT = float(estimates[report.appliedBy]['lower'])

	#numerators:
	#numerators (upper and lower) for R
	RU = R*upperT
	RL = R*lowerT

	#numerators (upper and lower) for T
	TU = upperT*upperT
	TL = lowerT*lowerT

	#denominators (upper and lower)
	dU = upperT
	dL = lowerT

	toAdd = {'RU': RU,'RL': RL,'TU': TU,'TL': TL,'dU': dU,'dL': dL}

	for i in toAdd:
		#print('???????????????is ratioset empty???????????????????????????')
		#print(ratioSet)
		ratioSet[i] = ratioSet[i] + toAdd[i]

	#print(ratioSet)
	return ratioSet

def estimateLoop(theUser, baseSet, organizedReports, reportSet, estimates, unevaluated, pathSet, fillPreReq):

	#OUTLINE OF ALGORITHM:------------------------------
	# loop for each report on that person in the parent loop (where this function is called)
	# a check to see if the report is from someone we have an estimate for
	# if yes, add their report and trustworthiness to the numerators and denominators
	# if not, recursively do the above steps, and this one*
	# use the completed numerators and denominators to create an entry in the collection of estimates!
	# this function returns "estimates"

	#* IMPORTANT EXCEPTIONS:
	#if recursion has led us in a circle, have to change tactics to prevent infinite loop

	#EXPLANATION OF INPUT VARIABLES----------------------
	#"unevaluated" is the person we are trying to calculate an estimate for
	#"reportSet" is the set of reports specific to the "unevaluated" person
	#print(estimates)

	#initializing ratioSet so we can add to numerators and denominators:
	ratioSet = {'RU': 0,'RL': 0,'TU': 0,'TL': 0,'dU': 0,'dL': 0}

	print('=============== starting a thing ===============')

	# loop for each report on that person in the parent loop (where this function is called)
	for report in reportSet:
		#print('4444444444444for report in reportSet4444444444444')
		#print(ratioSet)
		#is this report made by someone we have an estimate for?
		if report.appliedBy in estimates:
			#print(str(report.appliedBy) + ' is in estimates')
			#yes this report is made by someone we have an estimate for
			#thus, it can be used without further investigation (at least in analytic mode)

			#so, add their report and trustworthiness to the numerators and denominators:
			#print('makes ratios, where do they go?')
			ratioSet = makeRatios(report, estimates, ratioSet)
			#print('done ratios')
			#print(estimates)
		else:
			#no, this report is not by someone we have an estimate for
			#print(str(report.appliedBy) + ' is NOT in estimates')
			#thus we need an estimate for THEM before we can use this report

			#but if we've already gone in a loop, just break

			#print(estimates)
			if report.appliedBy not in pathSet:
				#print(str(report.appliedBy) + ' is NOT in pathset')

				#recursively do the above steps, and this one

				#but first, add to the path set as we move along the path
				pathSet.append(unevaluated)
				#print("--------STARTING recursion meant to fill pre-requisites-------")
				#print(estimates)
				#print("need the following report.appliedBy in estimates, currently isn't")
				#print(report.appliedBy)

				#NOW do recursion to fill pre-requisites
				estimates = estimating(theUser, baseSet, organizedReports, organizedReports[report.appliedBy], estimates, report.appliedBy, pathSet)

				#print("--------DONE recursion meant to fill pre-requisites, so here's the report.appliedBy that we needed it to have, and here's estimates to see if we successfully have it-------")
				#print(report.appliedBy)
				#print(estimates)
				#print(ratioSet)

				#remove items from the path set as we finish that area of the path
				if unevaluated in pathSet:
					pathSet.remove(unevaluated)

				#now can add their report and trustworthiness to the numerators and denominators:
				ratioSet = makeRatios(report, estimates, ratioSet)
				#print(estimates)

			else:
				#ok, this is where I make "false estimates" to deal with a circular
				#set of evaluations
				#print(str(report.appliedBy) + ' IS in pathset, thus we have gone in a circle!!!!')
				#print(pathSet)
				#print('went in loop, so, we have to get ' + str(report.appliedBy) + ' into estiamtes, using a false estiamate!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!')
				#print('sorting out user and username:')
				#print(report.appliedBy)

				estimates[report.appliedBy] = {'upper': 0.5, 'lower': 0.5}

				#print('and now use this false estimate, and recursion, to evaluate this unevaluated:')
				#print(unevaluated)

				estimates = estimating(theUser, baseSet, organizedReports, reportSet, estimates, report.appliedBy, pathSet)

				#print('ok, now special recursion is done!  so now do ratioset???****************************************************************************************************************************************')
				ratioSet = makeRatios(report, estimates, ratioSet)
				#print(estimates)

			#print('yes, we have gone in a loop, and got back at the start')

	#print('?????????????????????????is this where the bad calculation happens???????????????????????????????')
	#print(estimates)
	if ratioSet['dU'] != 0:
		#use the numerators and denominators to get the
		#combined versions of upper and lower T
		newUpperR = float(ratioSet['RU']/ratioSet['dU'])
		newLowerR = float(ratioSet['RL']/ratioSet['dL'])

		newUpperT = float(ratioSet['TU']/ratioSet['dU'])
		newLowerT = float(ratioSet['TL']/ratioSet['dL'])
		#print("+++++++++++++++++++++here's some internal calculation figures:++++++++++++++")
		#print(newUpperT, newUpperR, newLowerR, newLowerT)

		#use these new combined values to make an upper and lower estimate
		upper = 1 + newUpperT*(newUpperR - 1)
		lower = newLowerR*newLowerT

		#print(upper, lower)

		if lower > upper:
			swap = [lower, upper]
			lower = swap [1]
			upper = swap[0]

		#print(upper, lower)

		estimates[unevaluated] = {'upper': upper, 'lower': lower}
	#else:
		#print("denominator = ZEROOOOO !!!!!!!!!!!!!!!!")

	#print('======= ***Returning Estimates *** =======')
	#print(estimates)
	#print('when is this done?')

	return estimates

def estimating(theUser, baseSet, organizedReports, reportSet, estimates, unevaluated, pathSet):

	#"unevaluated" is the person we are trying to calculate an estimate for
	#"reportSet" is the set of reports specific to the "unevaluated" person

	#this function returns "estimates"

	#first check if the base user has evaluated the "unuevaluated" person
	#(by checking if they are in baseSet)
	#Never alter an estimate made by the user.
	if unevaluated in baseSet:
		return estimates

	# print('is this applied by user?')
	# for report in reportSet:
		# if report.appliedBy == theUser:
			# print('was applied by user')
			# return estimates
	# print("this shouldn't print if previous line says it was applied by the user")
	#print('is this enevaluated person in the pathset?')
	if unevaluated in pathSet:
		#means we have gone in a loop
		#print('0000000000000000000000000000000000000000000000000yes, we have gone in a loop, and got back at the start0000000000000000000000000000000000000000000000000000000000000000000000')
		#print(unevaluated)
		#print(estimates[])
		estimates = estimateLoop(theUser, baseSet, organizedReports, reportSet, estimates, unevaluated, pathSet, 'no')
		L=0
		U=1
		print(">>>>check convergence of U<<<<")
		#print(abs((estimates[unevaluated]['upper']-L)))
		print(estimates[unevaluated]['upper'])
		while abs((estimates[unevaluated]['lower']-L)) > 0.0000001 and abs((estimates[unevaluated]['upper']-U)) > 0.01:

			L=estimates[unevaluated]['lower']
			U=estimates[unevaluated]['upper']
			#print("CHECK THAT i DON'T NEED DEEP copy")
			#print(L)

			estimates = estimateLoop(theUser, baseSet, organizedReports, reportSet, estimates, unevaluated, pathSet, 'no')
			print("now.........")
			#print(abs((estimates[unevaluated]['upper']-L)))
			print(estimates[unevaluated]['upper'])

		pathSet.remove(unevaluated)
		print("SAYS U CONVERGED!")
		#print(estimates)
	else:
		#means we have not gone in a loop
		#print("................no, so we haven't gone in a loop")
		estimates = estimateLoop(theUser, baseSet, organizedReports, reportSet, estimates, unevaluated, pathSet, 'yes')
		#print(estimates)

	#print('returning estiamtes from func 1')
	return estimates

def masterTrustFunc(asker):
	#here I'll call all the other functions

	#scout the network to get all evaluations, and get baseSet
	scout = evalReportsAndMap(asker)

	unorganizedReports = scout[0]
	baseSet = copy.deepcopy(scout[1])
	estimates = scout[1]

	#organize all reports by who they are about (by identity, actually?)
	organizedReports = organizeReportsByIdentity(unorganizedReports)

	#so, below, we get estimates for each person we have reports for
	#only whenever we don't already have estimates for them
	for i in organizedReports:
		if i not in estimates:
			print("$$$$$$$$$$$~~~~LOOK WHAT'S HAPPENING!!!!!~~~~~~~~~~~~~~~~")
			estimates = estimating(asker, baseSet, organizedReports, organizedReports[i], estimates, i, [])

	return estimates


from fastapi import FastAPI, Request, UploadFile, File
from fastapi.responses import HTMLResponse
from fastapi.staticfiles import StaticFiles
from fastapi.templating import Jinja2Templates
from starlette.datastructures import Address
import requests
import json

# from tensorflow.keras.models import load_model

import numpy as np

from matplotlib import pyplot as plt

from PIL import Image
import io

# np.random.seed(1000)
# gan = load_model('models/result_gan_nontrainable.h5')
# generator = load_model('models/generator.h5')
latent_dims = 100
number_of_photos = 25

cats_vs_dogs_URL = 'https://kovalevskiy-cats-vs-dogs.herokuapp.com/'
ganime_URL = 'https://kovalevskiy-ganime.herokuapp.com/'

# cats_dogs_classifier = load_model('models/cats_vs_dogs.h5')

app = FastAPI(docs_url=None, redoc_url=None)

app.mount("/static", StaticFiles(directory="static"), name="static")

templates = Jinja2Templates(directory='templates')

def plot_images(images):
    figure = plt.figure(figsize=(5, 5))
    print(images.shape)
    for i in range(number_of_photos):
        plt.subplot(5, 5, i + 1)
        plt.imshow((images[i] + 1) / 2)
        plt.axis('off')
        plt.tight_layout()
    plt.savefig('static/generated.png')

def prediction_result(prediction):
    return f'Cat probability: {round(prediction[0] * 100, 4)}%, \
         Dog probability: {round(prediction[1] * 100, 4)}%'

@app.get('/', response_class=HTMLResponse)
def index(request: Request):
    # print(request)
    return templates.TemplateResponse('index.html', {'request': request})

@app.get('/cats_vs_dogs', response_class=HTMLResponse)
def cats_vs_dogs(request: Request):
    return templates.TemplateResponse(
        'cats_vs_dogs.html', {
            'request': request})

@app.post('/cats_vs_dogs', response_class=HTMLResponse)
async def cats_vs_dogs(request: Request, file_input: UploadFile = File(...)):
    file_format = file_input.content_type
    if 'image' in file_format:
        file_data = await file_input.read()
        im = Image.open(io.BytesIO(file_data))
        im_arr = np.asarray(im)
        filename = 'image.jpg'
        im.save(f'static/{filename}')
        im.close()
        prediction = requests.post(cats_vs_dogs_URL, json=json.dumps(im_arr.tolist())).json()['prediction']
        prediction = prediction_result(prediction)
        image = True
    else:
        prediction = 'Select an image file!'
        image = False
    return templates.TemplateResponse(
        'cats_vs_dogs.html', {
            'request': request, 'prediction': prediction, 'image': image})

@app.get('/ganime', response_class=HTMLResponse)
def ganime(request: Request):
    return templates.TemplateResponse('ganime.html', {'request': request})

@app.post('/ganime', response_class=HTMLResponse)
def ganime(request: Request):
    # prediction = gan.layers[0](np.random.normal(
    #     0, 1, (number_of_photos, latent_dims)))

    # prediction = generator.predict(normal(0, 1, (number_of_photos, latent_dims)))

    images = []
    for i in range(number_of_photos):
        image = requests.get(ganime_URL).json()['Image'][0]
        images.append(image)
    images = np.array(images)
    plot_images(images)
    return templates.TemplateResponse(
        'ganime.html', {'request': request, 'img': True})


import torch
import time
import glob
import os
import csv
import sys
import argparse
import numpy as np

tmp_path = os.path.dirname(os.path.abspath(__file__))
root_path = '/'.join(tmp_path.split('/')[:-2])
sys.path.append(root_path)
from utils.config import cfg
from model.main_msnet import MsNet
from workflow.train.dataset_loader import fill_feature_cuda
from utils.polar_mask import get_point_instance, get_final_masks
from utils.ms_compatibility import get_mz_fwhm

class MsNetEvaluator:
    def __init__(self, exp, epoch):
        self.net = MsNet(cfg)
        self.net.backbone.load_state_dict(
            torch.load(root_path + '/%s/%s/%s_%.3d.pth' % ('experiment', exp, 'backbone', epoch)))
        self.net.sem_net.load_state_dict(
            torch.load(root_path + '/%s/%s/%s_%.3d.pth' % ('experiment', exp, 'sem_net', epoch)))
        self.net.center_net.load_state_dict(
            torch.load(root_path + '/%s/%s/%s_%.3d.pth' % ('experiment', exp, 'box_center_net', epoch)))
        self.net.polar_mask_net.load_state_dict(
            torch.load(root_path + '/%s/%s/%s_%.3d.pth' % ('experiment', exp, 'polar_mask_net', epoch)))
        self.net.backbone.eval()
        self.net.sem_net.eval()
        self.net.center_net.eval()
        self.net.polar_mask_net.eval()

    def eval(self, eval_dir, mass_analyzer, mz_resolution, resolution_mz, rt_fwhm, center_threshold=0.5, block_rt_width=None, block_mz_width=None, target_id=None):
        start_time = time.time()
        print('Evaluating on ', eval_dir)
        eval_file_paths = glob.glob(os.path.join(eval_dir, '*.csv'))
        print('Point cloud count: {}'.format(len(eval_file_paths)))
        result_list = []

        for file_dir in eval_file_paths:
            file_name = file_dir.split('/')[-1].split('.csv')[0]
            pc_id = int(file_name.split('_')[0])
            block_mz_center = float(file_name.split('_')[1])
            block_rt_center = float(file_name.split('_')[2])

            if target_id is not None and target_id != -1 and pc_id != target_id:
                continue

            reader = csv.reader(open(file_dir, 'r'))
            data = np.array(list(reader), dtype=np.float32)
            raw_points = data[:, :3]

            points = self.normalize_points(raw_points, mass_analyzer, mz_resolution, resolution_mz, rt_fwhm)
            # points = fill_feature_cuda(points)

            pc = torch.tensor(points.reshape(1, len(points), -1), dtype=torch.float32).cuda()

            """ feature extraction """
            point_features = self.net.backbone(pc[:, :, :3])
            """ semantic segmentation """
            pre_sem = self.net.sem_net(point_features)
            """ center prediction """
            pre_center = self.net.center_net(point_features).squeeze(-1)
            """ mask prediction """
            pre_masks = self.net.polar_mask_net(point_features)

            pre_sem = pre_sem[0].cpu().detach().numpy()
            pre_center = pre_center[0].cpu().detach().numpy()
            pre_masks = pre_masks[0].cpu().detach().numpy()

            center_idx = ((pre_center * pre_sem) > center_threshold).nonzero()[0]

            candidate_masks = pre_masks[center_idx]
            final_center_idx, final_masks = get_final_masks(points, pre_masks, center_idx, candidate_masks)

            if len(final_center_idx) == 0:
                continue
            arg_idx = np.argsort(-points[final_center_idx][:, 2])
            final_center_idx = final_center_idx[arg_idx]
            final_masks = np.array(final_masks)[arg_idx]

            # manage result
            point_instance = get_point_instance(points, final_center_idx, final_masks)
            for i in range(len(final_center_idx)):
                instance_idxes = (point_instance == i).nonzero()[0]
                if len(instance_idxes) < 10:
                    continue
                instance_points = raw_points[instance_idxes]

                # Intensity calculation
                total_intensity = self.get_instance_volume(instance_points)
                # total_intensity = np.sum(instance_points[:, 2])

                # Center point selection
                # apex_idx = instance_idxes[np.argmax(instance_points[:, 2])]
                # apex_raw_point = raw_points[apex_idx]
                apex_raw_point = raw_points[final_center_idx[i]]
                if block_rt_width is not None and block_mz_width is not None:
                    if apex_raw_point[0] >= block_rt_center + block_rt_width / 2 \
                            or apex_raw_point[0] < block_rt_center - block_rt_width / 2 \
                            or apex_raw_point[1] >= block_mz_center + block_mz_width / 2 \
                            or apex_raw_point[1] < block_mz_center - block_mz_width / 2:
                        continue

                result_list += [[pc_id, apex_raw_point[1], np.min(instance_points[:, 1]), np.max(instance_points[:, 1]),
                                apex_raw_point[0], np.min(instance_points[:, 0]), np.max(instance_points[:, 0]),
                                apex_raw_point[2], total_intensity, len(instance_points)]]

                # id, mz, mz_start, mz_end, rt, rt_start, rt_end, apex_intensity, volume, point_count, mask_len_0, ..., mask_len_35
                # print(total_intensity, apex_raw_point[0], apex_raw_point[1])

            print(file_dir, len(final_center_idx))

            # debug mode
            if target_id is not None:
                if target_id == -1 or pc_id == target_id:
                    from utils.visualize import Plot
                    print(len(center_idx))
                    Plot.draw_pc_heatmap(pc_xyz=points, idx=pc_id, heatmap=pre_center)
                    Plot.draw_pc_heatmap(pc_xyz=points, idx=pc_id, heatmap=pre_sem)
                    center_map = np.zeros(pre_center.shape)
                    center_map[center_idx] = 1
                    # Plot.draw_pc_heatmap(pc_xyz=points, idx=pc_id, heatmap=center_map)
                    Plot.draw_pc_polar(pc_xyzrgb=points, idx=pc_id, center_idxes=center_idx, polar_masks=candidate_masks)
                    Plot.draw_pc_polar(pc_xyzrgb=points, idx=pc_id, center_idxes=final_center_idx, polar_masks=final_masks)
                    print(pc_id)
        time_cost = time.time() - start_time
        print('Time Cost:', time_cost)

        if target_id is None:
            # output result
            output_file_name = eval_dir.split('/')[-1] + '-result-{}-{}.csv'.format(
                time.strftime("%Y%m%d_%H%M%S", time.localtime()), int(time_cost))
            output_file_dir = os.path.join(os.path.dirname(eval_dir), 'result')
            output_file_path = os.path.join(output_file_dir, output_file_name)
            if not os.path.exists(output_file_dir):
                os.mkdir(output_file_dir)

            output_file = open(output_file_path, 'w')
            writer = csv.writer(output_file)
            writer.writerows(result_list)
            output_file.close()
            print('Finish on ', output_file_path)

    def normalize_points(self, raw_points, mass_analyzer, mz_resolution, resolution_mz, rt_fwhm):
        points = raw_points.copy()
        min_rt = np.min(points[:, 0])
        max_rt = np.max(points[:, 0])
        min_mz = np.min(points[:, 1])
        max_mz = np.max(points[:, 1])
        mid_mz = (min_mz + max_mz) / 2
        mid_rt = (min_rt + max_rt) / 2

        mz_fwhm = get_mz_fwhm(mid_mz, mass_analyzer, mz_resolution, resolution_mz)
        rt_factor = 1.0 / rt_fwhm
        mz_factor = 1.0 / mz_fwhm
        points[:, 0] = (points[:, 0] - mid_rt) * rt_factor
        points[:, 1] = (points[:, 1] - mid_mz) * mz_factor
        points[:, 2] = np.log2(points[:, 2])
        min_intensity = np.min(points[:, 2]) - 1
        points[:, 2] -= min_intensity
        return points

    def get_instance_volume(self, instance_points):
        rt_sorted_points = instance_points[np.argsort(instance_points[:, 0])]
        rt_map = {}
        for point in rt_sorted_points:
            if not rt_map.__contains__(point[0]):
                rt_map[point[0]] = []
            rt_map[point[0]] += [point]
        rt_list = list(rt_map.keys())
        if len(rt_list) < 2:
            return 0
        areas = []
        for i in range(len(rt_list) - 1, -1, -1):
            rt = rt_list[i]
            tmp_points = np.array(rt_map[rt])
            if len(tmp_points) < 2:
                rt_list.remove(rt)
                continue
            mz_sorted_points = tmp_points[np.argsort(tmp_points[:, 1])]
            mz_interval = mz_sorted_points[1:, 1] - mz_sorted_points[:-1, 1]
            mid_intensity = (mz_sorted_points[1:, 2] + mz_sorted_points[:-1, 2]) / 2
            area = np.sum(mz_interval * mid_intensity)
            areas += [area]
        rt_list = np.array(rt_list)
        areas = np.array(areas)
        rt_interval = rt_list[1:] - rt_list[:-1]
        mid_area = (areas[1:] + areas[:-1]) / 2
        volume = np.sum(rt_interval * mid_area)
        return volume

if __name__ == '__main__':
    parser = argparse.ArgumentParser(description='Untargeted feature extraction')

    parser.add_argument('--data_dir', type=str, help='dataset dir', required=True)
    parser.add_argument('--mass_analyzer', type=str, help='orbitrap or tof', required=True)
    parser.add_argument('--mz_resolution', type=float, help='the resolution of mass analyzer', required=True)
    parser.add_argument('--resolution_mz', type=float, help='the m/z value at the resolution', required=True)
    parser.add_argument('--rt_fwhm', type=float, help='median of feature RT FWHM', required=True)
    parser.add_argument('--experiment', type=str, help='choose a pretrained model', default='msnet_20220427_141044')
    parser.add_argument('--epoch', type=int, help='choose the epoch of saved model', default=1000)
    parser.add_argument('--center_threshold', type=float, help='feature center selection threshold', default=0.5)
    parser.add_argument('--block_rt_width', type=float, help='point cloud rt window width', default=6)
    parser.add_argument('--block_mz_width', type=float, help='point cloud m/z window width', default=0.8)
    parser.add_argument('--target_id', type=int, help='None, not visualize. -1, visualize each point cloud. Integer, visualize a specific point cloud', default=None)
    args = parser.parse_args()
    os.environ["CUDA_VISIBLE_DEVICES"] = '0'

    data_dir = glob.glob(os.path.join(args.data_dir, '*arget-*'))
    print(data_dir)
    evaluator = MsNetEvaluator(exp=args.experiment, epoch=args.epoch)
    for eval_dir in data_dir:
        evaluator.eval(eval_dir=eval_dir, mass_analyzer=args.mass_analyzer, mz_resolution=args.mz_resolution,
                       resolution_mz=args.resolution_mz, rt_fwhm=args.rt_fwhm, center_threshold=args.center_threshold,
                       block_rt_width=args.block_rt_width, block_mz_width=args.block_mz_width, target_id=args.target_id)


import torch
import torch.nn as nn
import torch.nn.functional as F
import numpy as np

device = torch.device("cuda" if torch.cuda.is_available() else 'cpu')

class creat_model(nn.Module):
    def __init__(self, batch_size, vocab_size, embedding_matrix,
                 nb_filters, embed_size=300, dropout_rate=0.5, num_classes=2,
                 kernel_dim=100, kernel_sizes=(2, 3, 4)):
        super(creat_model, self).__init__()
        self.batch_size = batch_size
        self.dropout_rate = dropout_rate
        self.embedding_matrix = embedding_matrix
        self.vocab_size = vocab_size
        self.embed_size = embed_size
        self.nb_filters = nb_filters
        self.kernel_dim = kernel_dim
        self.kernel_sizes = kernel_sizes
        self.num_class = num_classes
        # 词嵌入层
        self.embedding_layer = self.add_embed_layer(self.embedding_matrix, self.vocab_size['word'], self.embed_size)
        # CNN编码层
        self.convs = nn.ModuleList([nn.Conv2d(1, kernel_dim, (k, self.embed_size)) for k in kernel_sizes])
        # 输出分类层
        self.dropout_layer = nn.Dropout(self.dropout_rate)
        self.fc = nn.Linear(len(kernel_sizes) * kernel_dim * 2, num_classes)
        nn.init.xavier_uniform_(self.fc.weight.data, gain=1)
        nn.init.constant_(self.fc.bias.data, 0.1)

    def add_embed_layer(self, vocab_emb, vocab_size, embed_size):
        if vocab_emb is not None:
            # 预训练词向量
            embed_layer = nn.Embedding(vocab_size, embed_size)
            pretrained_weight = np.array(vocab_emb)
            embed_layer.weight.data.copy_(torch.from_numpy(pretrained_weight))
            for p in embed_layer.parameters():
                p.requires_grad = False
        else:
            # 随机初始化
            print("Embedding with random weights")
            embed_layer = nn.Embedding(num_embeddings=vocab_size, embedding_dim=embed_size)
        return embed_layer

    def forward(self, query_word_input, doc_word_input):
        # 这里对视频中的代码做了修改，使用了多个并行的卷积
        # 经过词嵌入层，获得词向量
        query_word_emb = self.embedding_layer(query_word_input).unsqueeze(1)
        doc_word_emb = self.embedding_layer(doc_word_input).unsqueeze(1)
        # print(query_word_emb.size())
        # [batch_size, 1, seq_len, embedding_dim]
        # 经过卷积层，和最大池化层
        query_word_emb = [F.relu(conv(query_word_emb)).squeeze(3) for conv in self.convs]
        query_word_emb = [F.max_pool1d(i, i.size(2)).squeeze(2) for i in query_word_emb]
        doc_word_emb = [F.relu(conv(doc_word_emb)).squeeze(3) for conv in self.convs]
        doc_word_emb = [F.max_pool1d(i, i.size(2)).squeeze(2) for i in doc_word_emb]
        # 拼接不同卷积层的特征
        query_concated = torch.cat(query_word_emb, 1)
        query_concated = self.dropout_layer(query_concated)
        doc_concated = torch.cat(doc_word_emb, 1)
        doc_concated = self.dropout_layer(doc_concated)
        # 拼接query和doc
        concated = torch.cat([query_concated, doc_concated], dim=-1)
        prediction = self.fc(concated)
        return prediction


###########################################
# Desc:
# Author: Hannah Noftall W0424894
###########################################

def main():
    lab9Part1(10)
    lab9Part2()
    lab9Part3()

def lab9Part1(finalNumber):
    counter = 0
    while(counter < finalNumber):
        print(counter ** 2)
        counter += 1

def lab9Part2():
    char = ""
    word = input("What is your name: ")
    for char in word:
        print(char)

def lab9Part3():
    sum = 0
    for i in range(0, 10):
        if i % 2 == 0:
            sum = sum + i
            print(sum)

#PROGRAM STARTS HERE. DO NOT CHANGE THIS CODE.
if __name__ == "__main__":
    main()


"""
875. Koko Eating Bananas
Medium

Koko loves to eat bananas. There are n piles of bananas, the ith pile has piles[i] bananas. The guards have gone and will come back in h hours.

Koko can decide her bananas-per-hour eating speed of k. Each hour, she chooses some pile of bananas and eats k bananas from that pile. If the pile has less than k bananas, she eats all of them instead and will not eat any more bananas during this hour.

Koko likes to eat slowly but still wants to finish eating all the bananas before the guards return.

Return the minimum integer k such that she can eat all the bananas within h hours.

Example 1:

Input: piles = [3,6,7,11], h = 8
Output: 4
Example 2:

Input: piles = [30,11,23,4,20], h = 5
Output: 30
Example 3:

Input: piles = [30,11,23,4,20], h = 6
Output: 23

Constraints:

1 <= piles.length <= 104
piles.length <= h <= 109
1 <= piles[i] <= 109

"""
from typing import List

"""
Binary Search

min of k is 1, largest of k is max(piles) since if he finishes at least one pile per hour, piles.length <=h, he will always be able to finish within h hour

Why binary search?
if he cannot finish at speed k, then he cannot finish with any speed x<k
if he can finish at speed k, then he can finish with any speed x > k
i.e., there's some k such that if he can finish if and only if his speed x >= k
so we can do binary search to find this value k

time O(Nlog(N))

mistakes:
1 calculating hours needed for pile of size p>0 at speed k, it is math.ceil(p/k)=((p-1)//k+1)
"""

class Solution:
    def minEatingSpeed(self, piles: List[int], h: int) -> int:

        left, right = 1, max(piles)
        while left < right:
            mid = left + (right - left) // 2
            # print('left=%s right=%s mid=%s' % (left, right, mid))
            # can he finish with speed k per hour
            # for each pile of size p>0, the hours he need would be math.ceil(p/k) = ((p-1)//k)+1 hours
            if sum([((p - 1) // mid + 1) for p in piles]) <= h:
                right = mid
            else:
                left = mid + 1

        return left

def main():
    sol = Solution()
    assert sol.minEatingSpeed(piles = [3,6,7,11], h = 8) == 4, 'fails'

    assert sol.minEatingSpeed(piles = [30,11,23,4,20], h = 5) == 30, 'fails'

    assert sol.minEatingSpeed(piles = [30,11,23,4,20], h = 6) == 23, 'fails'

    assert sol.minEatingSpeed([312884470], 312884469) == 2, 'fails'

if __name__ == '__main__':
   main()


import sqlite3

def add_task(name: str, task_type: str):
  # open the connection to the database file
  connection = sqlite3.connect('task_db')
  cursor = connection.cursor()
  # on the cursor object we execute our command(s)
  cursor.execute("INSERT INTO tasks (name, type) VALUES ('"
                 + name + "', '" + task_type + "')")
  # commit == save to file
  connection.commit()
  connection.close()

def get_tasks():
  connection = sqlite3.connect('task_db')
  cursor = connection.cursor()

  cursor.execute("SELECT * FROM tasks")
  tasks = cursor.fetchall()
  connection.close()
  dict = [{'name': x[0], 'type': x[1]} for x in tasks]
  return dict

def delete_task(name: str):
  connection = sqlite3.connect('task_db')
  cursor = connection.cursor()

  cursor.execute("DELETE FROM tasks WHERE name='" + name + "'")
  connection.commit()
  connection.close()

if __name__ == "__main__":
  # add_task('buy fruits', 'cooking')
  delete_task('clean the house')
  print(get_tasks())


from __future__ import annotations

import atexit
import logging

import colorama

from .config import CfgOption

__all__ = ["log"]

# Config options
verbosity = CfgOption("verbosity", value="INFO",
                      typ=lambda val: logging._nameToLevel[val])
filename = CfgOption("filename", value="aware.log", typ=str)
filemode = CfgOption("filemode", value="w+", typ=str)

# Set logger
log = logging.getLogger("aware")
log.setLevel(verbosity.get_value())

def colored_message(msg: str, color: str) -> str:
    """
    Return colorized version of the message.

    Parameters
    ----------
    msg : str
        message to colorize
    color : str
        text color

    Returns
    -------
    str
        message with colorized text
    """
    return color + msg + colorama.Style.RESET_ALL

class ColorFormatter(logging.Formatter):
    """
    Colorful messages in console/terminal emulator via logging facility.
    """

    def format(self, record: logging.LogRecord) -> str:
        """
        Paint record message according to the logging level.
        """

        msg = super(ColorFormatter, self).format(record)

        lvl = record.levelno
        if lvl < logging.INFO:
            formatted_msg = colored_message(msg, colorama.Fore.BLUE)
        elif lvl < logging.WARN:
            formatted_msg = colored_message(msg, colorama.Fore.GREEN)
        elif lvl < logging.ERROR:
            formatted_msg = colored_message(msg, colorama.Fore.YELLOW)
        elif lvl < logging.CRITICAL:
            formatted_msg = colored_message(msg, colorama.Fore.LIGHTRED_EX)
        else:
            formatted_msg = colored_message(msg, colorama.Fore.RED)

        return formatted_msg

msg_format = "%(asctime)s.%(msecs)03d %(levelname)8s "
msg_format += "%(module)s.%(funcName)s(): %(message)s"

console = logging.StreamHandler()
console.setFormatter(ColorFormatter())

def _remove_handlers() -> None:
    if log.hasHandlers():
        log.handlers = []

# Remove handlers to prevent double message emmiting
_remove_handlers()

log.addHandler(console)

logfile = logging.FileHandler(filename.get_value(), mode=filemode.get_value())
logfile.setLevel(verbosity.get_value())
logfile.setFormatter(logging.Formatter(msg_format, "%Y-%m-%d %H:%M:%S"))
log.addHandler(logfile)

colorama.init()
atexit.register(colorama.deinit)
atexit.register(_remove_handlers)


from os import stat
import re
import json
import utils2to3
from copy import deepcopy

from edtime import EDTime
import edrconfig
from edrlog import EDRLog

EDRLOG = EDRLog()

class EDSuitLoadout(object):
    def __init__(self):
        self.id = None
        self.loadout_id = None
        self.name = None
        self.suit_mods = []
        self.modules = []

    def update_from_suitloadout(self, event):
        self.id = event.get("LoadoutID", None)
        self.name = event.get("LoadoutName", None)
        self.suit_mods = event.get("SuitMods", [])
        self.modules = event.get("Modules", [])

class EDSpaceSuit(object):
    def __init__(self):
        self.type = None
        self.id = None
        self.grade = 1
        self.loadout = EDSuitLoadout()
        now = EDTime.py_epoch_now()
        self.timestamp = now
        self._health = {u"value": 1.0, u"timestamp": now}
        self._oxygen = {u"value": 1.0, u"timestamp": now}
        self._low_oxygen = {u"value": False, u"timestamp": now}
        self._low_health = {u"value": False, u"timestamp": now}
        self.shield_up = True
        self.fight = {u"value": False, "large": False, u"timestamp": now}
        self._attacked = {u"value": False, u"timestamp": now}
        self._in_danger = {u"value": False, u"timestamp": now}
        config = edrconfig.EDR_CONFIG
        self.fight_staleness_threshold = config.instance_fight_staleness_threshold()
        self.danger_staleness_threshold = config.instance_danger_staleness_threshold()

    @property
    def health(self):
        return self._health["value"]

    @health.setter
    def health(self, new_value):
        now = EDTime.py_epoch_now()
        self.timestamp = now
        self._health = {u"value": new_value, u"timestamp": now}

    @property
    def oxygen(self):
        return self._oxygen["value"]

    @oxygen.setter
    def oxygen(self, new_value):
        now = EDTime.py_epoch_now()
        self.timestamp = now
        self._oxygen = {u"value": new_value, u"timestamp": now}

    @property
    def low_health(self):
        return self._low_oxygen["value"]

    @low_health.setter
    def low_health(self, low):
        now = EDTime.py_epoch_now()
        self.timestamp = now
        self._low_health = {"timestamp": now, "value": low}

    @property
    def low_oxygen(self):
        return self._low_oxygen["value"]

    @low_oxygen.setter
    def low_oxygen(self, low):
        now = EDTime.py_epoch_now()
        self.timestamp = now
        self._low_oxygen = {"timestamp": now, "value": low}

    def json(self):
        result = {
            u"timestamp": int(self.timestamp * 1000),
            u"type": self.type,
            u"health": self.__js_t_v(self._health),
            u"oxygen": self.__js_t_v(self._oxygen),
            u"shieldUp": self.shield_up,
            u"lowHealth":self.__js_t_v(self._low_health),
            u"lowOxygen":self.__js_t_v(self._low_oxygen),
        }

        return result

    def __js_t_v(self, t_v):
        result = t_v.copy()
        result["timestamp"] = int(t_v["timestamp"]*1000)
        return result

    def __repr__(self):
        return str(self.__dict__)

    def reset(self):
        now = EDTime.py_epoch_now()
        self.timestamp = now
        self.health = 100.0
        self.oxygen = 100.0
        self.shield_up = True
        self.fight = {u"value": False, u"large": False, u"timestamp": now}
        # self._hardpoints_deployed = {u"value": False, u"timestamp": now} ? SelectedWeapon?
        self._attacked = {u"value": False, u"timestamp": now}
        self.heat_damaged = {u"value": False, u"timestamp": now}
        self._in_danger = {u"value": False, u"timestamp": now}

    def destroy(self):
        now = EDTime.py_epoch_now()
        self.timestamp = now
        self.health = 0.0

    def attacked(self):
        now = EDTime.py_epoch_now()
        self.timestamp = now
        self._attacked = {u"value": True, u"timestamp": now}

    def under_attack(self):
        if self._attacked["value"]:
            now = EDTime.py_epoch_now()
            return (now >= self._attacked["timestamp"]) and ((now - self._attacked["timestamp"]) <= self.danger_staleness_threshold)
        return False

    def safe(self):
        now = EDTime.py_epoch_now()
        self._attacked = {u"value": False, u"timestamp": now}
        self.fight = {u"value": False, "large": False, u"timestamp": now}
        self._in_danger = {u"value": False, u"timestamp": now}

    def unsafe(self):
        now = EDTime.py_epoch_now()
        self._in_danger = {u"value": True, u"timestamp": now}

    def in_danger(self):
        if self._in_danger["value"]:
            now = EDTime.py_epoch_now()
            return (now >= self._in_danger["timestamp"]) and ((now - self._in_danger["timestamp"]) <= self.danger_staleness_threshold)
        return False

    def shield_state(self, is_up):
        if not is_up:
            self.shield_health = 0.0
        self.shield_up = is_up

    def skirmish(self):
        now = EDTime.py_epoch_now()
        self.fight = {u"value": True, "large": False, u"timestamp": now}

    def battle(self):
        now = EDTime.py_epoch_now()
        self.fight = {u"value": True, "large": True, u"timestamp": now}

    def in_a_fight(self):
        if self.fight["value"]:
            now = EDTime.py_epoch_now()
            return (now >= self.fight["timestamp"]) and ((now - self.fight["timestamp"]) <= self.fight_staleness_threshold)
        return False

    def update_from_suitloadout(self, event):
        other_id = event.get("SuitID", None)
        other_type = EDSuitFactory.suit_type(event.get("SuitName", "unknown"))

        if other_id != self.id or other_type != self.type:
            EDRLOG.log(u"Mismatch between Suit ID ({} vs {}) and/or Type ({} vs. {}), can't update from loadout".format(self.id, other_id, self.type, other_type), "WARNING")
            return

        self.loadout.update_from_suitloadout(event)

    def __eq__(self, other):
        if not isinstance(other, EDSpaceSuit):
            return False
        return self.__dict__ == other.__dict__

    def __ne__(self, other):
        return not self.__eq__(other)

class EDUnknownSuit(EDSpaceSuit):
    def __init__(self):
        super(EDUnknownSuit, self).__init__()
        self.type = u'Unknown'

class EDFlightSuit(EDSpaceSuit):
    def __init__(self):
        super(EDFlightSuit, self).__init__()
        self.type = u'Flight'

class EDMaverickSuit(EDSpaceSuit):
    def __init__(self):
        super(EDMaverickSuit, self).__init__()
        self.type = u'Maverick'

class EDArtemisSuit(EDSpaceSuit):
    def __init__(self):
        super(EDArtemisSuit, self).__init__()
        self.type = u'Artemis'

class EDDominatorSuit(EDSpaceSuit):
    def __init__(self):
        super(EDDominatorSuit, self).__init__()
        self.type = u'Dominator'

class EDOdysseyCloset(object):
    # because why not

    def __init__(self):
        self.loadouts = {}
        self.genetic_sampler = EDGeneticSampler()
        # other tools, not interesting for now
        #   arc cutter
        #   profile analyzer
        #   energy link

    def switch_suit_loadout(self, entry):
        loadout_id = entry["LoadoutID"] if "LoadoutID" in entry else entry.get("ShipID", -1)
        suit_name = entry["SuitName"] if "SuitName" in entry else entry.get("Ship", "unknown")
        if loadout_id not in self.loadouts or self.loadouts[loadout_id].type != EDSuitFactory.suit_type(suit_name):
            self.loadouts[loadout_id] = EDSuitFactory.from_suitloadout_event(entry)
        else:
            # todo: update loadout
            pass
        return self.loadouts[loadout_id]

class EDGeneticSampler(object):
    BIOLOGY = json.loads(open(utils2to3.abspathmaker(__file__, 'data', 'biology.json')).read())

    def __init__(self):
        self.samples = {}
        self.genus = {}
        self.species = {}
        self.last_system_body = {}

    def reset(self):
        self.samples = {}
        self.genus = {}
        self.species = {}
        self.last_system_body = {}

    def process(self, scan_event, location):
        if scan_event["ScanType"] == "Analyse":
            self.reset()
            return

        if scan_event["ScanType"] == "Log":
            self.reset()

        if scan_event["ScanType"] in ["Log", "Sample"]:
            self.last_system_body = {
                "systemAddress": scan_event["SystemAddress"],
                "bodyNb": scan_event["Body"],
            }

            genus = scan_event.get("Genus", "").lower()
            self.genus = {
                "internal_name": genus,
                "name": scan_event["Genus_Localised"]
            }

            species = scan_event.get("Species", "").lower()
            self.species = {
                "internal_name": species,
                "name": scan_event["Species_Localised"]
            }
            system_body_id = EDGeneticSampler.__sys_body_id(scan_event["SystemAddress"], scan_event["Body"])
            if system_body_id in self.samples:
                self.samples[system_body_id].append(deepcopy(location))
            else:
                self.samples[system_body_id] = [ deepcopy(location) ]

    def is_tracking(self):
        return self.genus != {}

    def clonal_colony_range(self):
        if not self.genus:
            return None

        genus = EDGeneticSampler.BIOLOGY["genuses"].get(self.genus["internal_name"], None)
        if not genus:
            return None

        ccr = genus.get("ccr", None)

        return ccr

    def tracked_species_credits(self):
        if not self.species_tracked():
            return None

        species = EDGeneticSampler.BIOLOGY["species"].get(self.species["internal_name"], None)
        if not species:
            return None

        credits = species.get("credits", None)

        return credits

    def species_tracked(self):
        return self.species.get("name", None)

    def samples_locations(self, system_address=None, body_nb=None):
        system_address = system_address or self.last_system_body.get("systemAddress", None)
        body_nb = body_nb or self.last_system_body.get("bodyNb", None)
        system_body_id = EDGeneticSampler.__sys_body_id(system_address, body_nb)
        locs = self.samples.get(system_body_id, [])

        return locs

    @staticmethod
    def __sys_body_id(system_address, body_nb):
        return "S{}-B{}".format(system_address, body_nb)

    def has_samples_from(self, star_system_address, body_nb):
        if not self.last_system_body:
            return False

        if not self.last_system_body["systemAddress"]:
            return False

        if not self.last_system_body["bodyNb"]:
            return False

        return self.last_system_body["systemAddress"] == star_system_address and self.last_system_body["bodyNb"] == body_nb

class EDSuitFactory(object):
    __suit_classes = {
        "flightsuit": EDFlightSuit,
        "utilitysuit": EDMaverickSuit,
        "explorationsuit": EDArtemisSuit,
        "tacticalsuit": EDDominatorSuit,
        "unknown": EDUnknownSuit
    }

    @staticmethod
    def is_spacesuit(name):
        return EDSuitFactory.is_player_spacesuit(name) or EDSuitFactory.is_ai_spacesuit(name)

    @staticmethod
    def is_player_spacesuit(name):
        cname = name.lower()
        player_space_suit_regexp = r"^(?:flightsuit|(?:exploration|utility|tactical)suit_class[1-5])$" # TODO confirm that those are the internal names used for players
        return re.match(player_space_suit_regexp, cname)

    @staticmethod
    def is_ai_spacesuit(name):
        cname = name.lower()
        # ai_space_suit_regexp = r"^(?:assault|lightassault|close|ranged)aisuit_class[1-5])$" # TODO use this to tighten up things?
        ai_space_suit_lax_regexp = r"^[a-z0-9_]*aisuit_class[1-5]$"
        return re.match(ai_space_suit_lax_regexp, cname)

    @staticmethod
    def canonicalize_name(name):
        if name is None:
            return u"unknown" # Note: this shouldn't be translated
        cname = name.lower()
        player_space_suit_regexp = r"^(flightsuit|explorationsuit|utilitysuit|tacticalsuit)_class[1-5]$" # TODO confirm that those are the internal names used for players
        m = re.match(player_space_suit_regexp, cname)
        if m:
            cname = m.group(1)
        return cname

    @staticmethod
    def suit_type(internal_name):
        cname = EDSuitFactory.canonicalize_name(internal_name)
        LUT = {
            "flightsuit": "Flight",
            "utilitysuit": "Maverick",
            "explorationsuit": "Artemis",
            "tacticalsuit": "Dominator",
            "unknown": "Unknown"
        }
        return LUT.get(cname, "Unknown")

    @staticmethod
    def grade(name):
        cname = name.lower()
        player_space_suit_regexp = r"^[a-z0-9_]suit_class([1-5])$" # TODO confirm that those are the internal names used for players
        m = re.match(player_space_suit_regexp, cname)
        if m:
            return m.group(1)
        return 1

    # TODO @staticmethod
    # def from_edmc_state(state):

    @staticmethod
    def from_internal_name(internal_name):
        suit_name = EDSuitFactory.canonicalize_name(internal_name)
        grade = EDSuitFactory.grade(internal_name)
        suit = EDSuitFactory.__suit_classes.get(suit_name, EDUnknownSuit)()
        suit.grade = grade
        return suit

    @staticmethod
    def from_load_game_event(event):
        suit = EDSuitFactory.from_internal_name(event.get("Ship", 'unknown'))
        suit.id = event.get('ShipID', None)
        suit.identity = event.get('ShipIdent', None) # Always empty?
        suit.name = event.get('ShipName', None) # Always empty
        # TODO the event also has Fuel and Fuelcapacity but it's unclear if this is a bug or reusing fields for Energy levels?
        return suit

    @staticmethod
    def from_suitloadout_event(event):
        suit = EDSuitFactory.from_internal_name(event.get("SuitName", 'unknown'))
        suit.id = event.get('SuitID', None)
        suit.loadout.update_from_suitloadout(event)
        return suit

    #@staticmethod
    #def from_stored_ship(ship_info): # TODO suitloadout swapping?

    @staticmethod
    def unknown_suit():
        return EDUnknownSuit()


import time

from rsb import Event, Scope
from rsb.transport.local import (Bus,
                                 InConnector,
                                 OutConnector)
from rsb.transport.transporttest import TransportCheck

class StubSink:

    def __init__(self, scope):
        self.scope = scope
        self.events = []

    def scope(self):
        return self.scope

    def handle(self, event):
        self.events.append(event)

    def __call__(self, event):
        self.handle(event)

class TestBus:

    def test_construction(self):
        Bus()

    def test_notify_hierarchy(self):
        bus = Bus()

        target_scope = Scope("/this/is/a/test")
        scopes = target_scope.super_scopes(True)
        sinks_by_scope = {}
        for scope in scopes:
            sinks_by_scope[scope] = StubSink(scope)
            bus.add_sink(sinks_by_scope[scope])

        not_notified_sibling_sink = StubSink(Scope("/not/notified"))
        bus.add_sink(not_notified_sibling_sink)
        not_notified_child_sink = StubSink(
            target_scope.concat(Scope("/child")))
        bus.add_sink(not_notified_child_sink)

        event = Event(scope=target_scope)
        bus.handle(event)
        for scope, sink in list(sinks_by_scope.items()):
            assert event in sink.events
            assert len(sink.events) == 1

class TestOutConnector:

    def test_construction(self):
        OutConnector()

    def test_handle(self):

        bus = Bus()
        connector = OutConnector(bus=bus)

        scope = Scope("/a/test")
        sink = StubSink(scope)
        bus.add_sink(sink)

        e = Event()
        e.scope = scope

        before = time.time()
        connector.handle(e)
        after = time.time()
        assert len(sink.events) == 1
        assert e in sink.events
        assert e.meta_data.send_time >= before
        assert e.meta_data.send_time <= after

class TestInConnector:

    def test_construction(self):
        InConnector()

    def test_pass_to_action(self):

        scope = Scope("/lets/go")

        bus = Bus()
        connector = InConnector(bus=bus)
        connector.scope = scope
        connector.activate()

        action = StubSink(scope)
        connector.set_observer_action(action)

        e = Event()
        e.scope = scope
        bus.handle(e)
        assert len(action.events) == 1
        assert e in action.events

class TestLocalTransport(TransportCheck):

    def _get_in_connector(self, scope, activate=True):
        connector = InConnector()
        connector.scope = scope
        if activate:
            connector.activate()
        return connector

    def _get_out_connector(self, scope, activate=True):
        connector = OutConnector()
        connector.scope = scope
        if activate:
            connector.activate()
        return connector


# ---
# jupyter:
#   jupytext:
#     formats: ipynb,py
#     text_representation:
#       extension: .py
#       format_name: light
#       format_version: '1.5'
#       jupytext_version: 1.14.1
#   kernelspec:
#     display_name: causal-covid-analysis
#     language: python
#     name: causal-covid-analysis
# ---

# # Severe Covid Cases and Vaccinations in Israel

# +
import os

import pandas as pd
import datetime

from pathlib import Path

# +
# data paths
INPUT_DIR = Path("../data/input-data")
HOSP_DATA_PATH = INPUT_DIR / 'event-among-vaccinated-120.csv'
VACCINATION_DATA_PATH = INPUT_DIR / 'vaccinated-per-day-2022-01-01.csv'
CASE_DATA_PATH = INPUT_DIR / 'cases-among-vaccinated-185.csv'
UN_POPULATION_DATA_PATH = INPUT_DIR / 'WPP2019_POP_F07_1_POPULATION_BY_AGE_BOTH_SEXES.csv'

OUTPUT_DIR = Path("../data/preprocessed-data")
OUTPUT_DIR.mkdir(exist_ok=True)
# -

# # 2 Dataset: Fine Grained Age Groups

# ## 2.1 Load Data

# ### 2.1.1 Deaths and Hospitalisations

# Remark on the vaccination status in this table: people are counted as vaccinated from the day after the dose is given. This means there is no 14 day period between dose and updated vaccination status (see event-among-vaccinated-81-readme.pdf).

df_tmp = pd.read_csv(HOSP_DATA_PATH)
df_tmp['Sunday_date'] = pd.to_datetime(df_tmp['Week'].str[:10], format='%Y-%m-%d')
df_tmp = df_tmp.drop(columns=['Week'])
# df_tmp

# + code_folding=[0, 6, 18]
col_map_hosp = {
    'event_after_1st_dose': 'hosp_after_1st_dose',
    'event_after_2nd_dose': 'hosp_after_2nd_dose',
    'event_after_3rd_dose': 'hosp_after_3rd_dose',
    'event_for_not_vaccinated': 'hosp_unvaccinated',
}
col_map_death = {
    'event_after_1st_dose': 'death_after_1st_dose',
    'event_after_2nd_dose': 'death_after_2nd_dose',
    'event_after_3rd_dose': 'death_after_3rd_dose',
    'event_for_not_vaccinated': 'death_unvaccinated',
}
df = df_tmp[df_tmp['Type_of_event'] == 'Hospitalization'].rename(columns=col_map_hosp).drop(columns='Type_of_event')

df = df.merge(
    df_tmp[df_tmp['Type_of_event'] == 'Death'].rename(columns=col_map_death).drop(columns='Type_of_event'),
    on=['Age_group', 'Sunday_date']
)
cols = [
    'Sunday_date',
    'Age_group',
    'hosp_after_1st_dose',
    'hosp_after_2nd_dose',
    'hosp_after_3rd_dose',
    'hosp_unvaccinated',
    'death_after_1st_dose',
    'death_after_2nd_dose',
    'death_after_3rd_dose',
    'death_unvaccinated',
]
df = df[cols]
# df

# + code_folding=[0]
clean_cols =[
    'hosp_after_1st_dose',
    'hosp_after_2nd_dose',
    'hosp_after_3rd_dose',
    'hosp_unvaccinated',
    'death_after_1st_dose',
    'death_after_2nd_dose',
    'death_after_3rd_dose',
    'death_unvaccinated',
]
data_cleaning_map = {pd.NA: '0', '<5': '1'}  # TODO: check if <5 has to be mapped to sth else
df[clean_cols] = df[clean_cols].replace(data_cleaning_map).astype(float).astype(int)
df['hosp_total'] = (
    df['hosp_unvaccinated'] + df['hosp_after_1st_dose'] + df['hosp_after_2nd_dose'] + df['hosp_after_3rd_dose']
)
df['death_total'] = (
    df['death_unvaccinated'] + df['death_after_1st_dose'] + df['death_after_2nd_dose'] + df['death_after_3rd_dose']
)
df.head()
# -

# ### 2.1.2 Vaccinations

# + code_folding=[2]
df_vac = pd.read_csv(VACCINATION_DATA_PATH)

clean_cols = [
    'first_dose',
    'second_dose',
    'third_dose',
]
data_cleaning_map = {'<15': '10'}  # TODO: check if <15 has to be mapped to sth. else
df_vac[clean_cols] = df_vac[clean_cols].replace(data_cleaning_map).astype(int)

df_vac['Sunday_date'] = pd.to_datetime(
    df_vac['VaccinationDate'], format='%Y-%m-%d'
).dt.to_period('W-SAT').apply(lambda r: r.start_time) # Sunday-Monday weeks

df_vac = df_vac.rename(columns={'first_dose': '1st_dose', 'second_dose': '2nd_dose', 'third_dose': '3rd_dose'})
# df_vac
# -

# merge vaccination data
df_vac_grouped = df_vac.groupby(['Sunday_date', 'age_group']).sum().reset_index()
df = df.merge(df_vac_grouped.rename(columns={'age_group': 'Age_group'}), on=['Sunday_date', 'Age_group'])
df.head()

# ### 2.1.3 Demographic Data

# +
# load UN population data

# convert to csv, uncomment to redo
# df_pop = pd.read_excel(
#     'data/israel/WPP2019_POP_F07_1_POPULATION_BY_AGE_BOTH_SEXES.xlsx',
#     skiprows=15,
#     header=1,
#     index_col=0
# )
# df_pop = df_pop[
#     (df_pop['Region, subregion, country or area *'] == 'Israel')
#     & (df_pop['Reference date (as of 1 July)'] == 2020)
# ]

# df_pop.to_csv('data/israel/WPP2019_POP_F07_1_POPULATION_BY_AGE_BOTH_SEXES.csv')

df_pop = pd.read_csv(UN_POPULATION_DATA_PATH, index_col=0)

df_pop

# + code_folding=[10]
df_pop['0-19'] = 1000 * (df_pop['0-4'] + df_pop['5-9'] + df_pop['10-14'] + df_pop['15-19']).astype(int)
df_pop['20-29'] = 1000 * (df_pop['20-24'] + df_pop['25-29']).astype(int)
df_pop['30-39'] = 1000 * (df_pop['30-34'] + df_pop['35-39']).astype(int)
df_pop['40-49'] = 1000 * (df_pop['40-44'] + df_pop['45-49']).astype(int)
df_pop['50-59'] = 1000 * (df_pop['50-54'] + df_pop['55-59']).astype(int)
df_pop['60-69'] = 1000 * (df_pop['60-64'] + df_pop['65-69']).astype(int)
df_pop['70-79'] = 1000 * (df_pop['70-74'] + df_pop['75-79']).astype(int)
df_pop['80-89'] = 1000 * (df_pop['80-84'] + df_pop['85-89']).astype(int)
df_pop['90+'] = 1000 * (df_pop['90-94'] + df_pop['95-99'] + df_pop['100+']).astype(int)

drop_cols = [
    'Variant',
    'Region, subregion, country or area *',
    'Notes',
    'Country code',
    'Type',
    'Parent code',
    'Reference date (as of 1 July)',
    '0-4',
    '5-9',
    '10-14',
    '15-19',
    '20-24',
    '25-29',
    '30-34',
    '35-39',
    '40-44',
    '45-49',
    '50-54',
    '55-59',
    '60-64',
    '65-69',
    '70-74',
    '75-79',
    '80-84',
    '85-89',
    '90-94',
    '95-99',
    '100+',
]
df_pop = df_pop.drop(columns=drop_cols).rename(
    index={1440: 'Population_size'}).T.reset_index().rename(columns={'index': 'Age_group'})
# df_pop

# +
# rescale by current population
# source: https://www.cbs.gov.il/he/mediarelease/DocLib/2020/438/11_20_438e.pdf
current_population = 9291000
df_pop['Population_size'] = df_pop['Population_size'] * (current_population / df_pop['Population_size'].sum())
df_pop['Population_share'] = df_pop['Population_size']/current_population

df_constants = pd.DataFrame({'current_population': [current_population]})
# df_pop
# -

# merge population data into main datafram
df = df.merge(df_pop, on=['Age_group'])
df.head()

# ### 2.1.4 Infection Data

# + code_folding=[]
df_inf = pd.read_csv(CASE_DATA_PATH)
df_inf['Sunday_date'] = pd.to_datetime(df_inf['Week'].str[:10], format='%Y-%m-%d')
df_inf = df_inf.drop(columns=['Week'])

clean_cols = [
    'positive_1_6_days_after_1st_dose',
    'positive_7_13_days_after_1st_dose',
    'positive_14_20_days_after_1st_dose',
    'positive_above_20_days_after_1st_dose',
    'positive_1_6_days_after_2nd_dose',
    'positive_7_13_days_after_2nd_dose',
    'positive_14_30_days_after_2nd_dose',
    'positive_31_90_days_after_2nd_dose',
    'positive_above_3_month_after_2nd_before_3rd_dose',
    'positive_1_6_days_after_3rd_dose',
    'positive_7_13_days_after_3rd_dose',
    'positive_14_30_days_after_3rd_dose',
    'positive_31_90_days_after_3rd_dose',
    'positive_above_90_days_after_3rd_dose',
    'Sum_positive_without_vaccination',
]

data_cleaning_map = {pd.NA: '0', '<5': '4'}  # TODO: check if <5 has to be mapped to sth else
df_inf[clean_cols] = df_inf[clean_cols].replace(data_cleaning_map).astype(float).astype(int)

sum_total_cols = [
    'positive_1_6_days_after_1st_dose',
    'positive_7_13_days_after_1st_dose',
    'positive_14_20_days_after_1st_dose',
    'positive_above_20_days_after_1st_dose',
    'positive_1_6_days_after_2nd_dose',
    'positive_7_13_days_after_2nd_dose',
    'positive_14_30_days_after_2nd_dose',
    'positive_31_90_days_after_2nd_dose',
    'positive_above_3_month_after_2nd_before_3rd_dose',
    'positive_1_6_days_after_3rd_dose',
    'positive_7_13_days_after_3rd_dose',
    'positive_14_30_days_after_3rd_dose',
    'positive_31_90_days_after_3rd_dose',
    'positive_above_90_days_after_3rd_dose',
    'Sum_positive_without_vaccination',
]
df_inf['positive_total'] = df_inf[sum_total_cols].sum(axis=1)

sum_unvaccinated_cols = [
    'Sum_positive_without_vaccination',
]
df_inf['positive_unvaccinated'] = df_inf[sum_unvaccinated_cols].sum(axis=1)

sum_1st_cols = [
    'positive_1_6_days_after_1st_dose',
    'positive_7_13_days_after_1st_dose',
    'positive_14_20_days_after_1st_dose',
    'positive_above_20_days_after_1st_dose',
]
df_inf['positive_after_1st_dose'] = df_inf[sum_1st_cols].sum(axis=1)

sum_2nd_cols = [
    'positive_1_6_days_after_2nd_dose',
    'positive_7_13_days_after_2nd_dose',
    'positive_14_30_days_after_2nd_dose',
    'positive_31_90_days_after_2nd_dose',
    'positive_above_3_month_after_2nd_before_3rd_dose',
]
df_inf['positive_after_2nd_dose'] = df_inf[sum_2nd_cols].sum(axis=1)

sum_3rd_cols = [
    'positive_1_6_days_after_3rd_dose',
    'positive_7_13_days_after_3rd_dose',
    'positive_14_30_days_after_3rd_dose',
    'positive_31_90_days_after_3rd_dose',
    'positive_above_90_days_after_3rd_dose',
]
df_inf['positive_after_3rd_dose'] = df_inf[sum_3rd_cols].sum(axis=1)

df_inf['Population_share_pos'] = df_inf[
    ['Sunday_date', 'Age_group', 'positive_total']
].groupby(['Sunday_date']).apply(lambda x: x['positive_total']/x['positive_total'].sum()).values

df_inf.head()

# + code_folding=[0]
merge_cols = [
    'Sunday_date',
    'Age_group',
    'positive_total',
    'positive_unvaccinated',
    'positive_after_1st_dose',
    'positive_after_2nd_dose',
    'positive_after_3rd_dose',
    'Population_share_pos',
]
df = df.merge(df_inf[merge_cols], on=['Sunday_date', 'Age_group'], how='left')
# df
# -

# ### 2.1.5 Data Preparation

# + code_folding=[2]
# Aggregated numbers over all age groups
df_tmp = df.groupby('Sunday_date').agg(
    {
        'hosp_unvaccinated': 'sum',
        'hosp_after_1st_dose': 'sum',
        'hosp_after_2nd_dose': 'sum',
        'hosp_after_3rd_dose': 'sum',
        'hosp_total': 'sum',
        'death_unvaccinated': 'sum',
        'death_after_1st_dose': 'sum',
        'death_after_2nd_dose': 'sum',
        'death_after_3rd_dose': 'sum',
        'death_total': 'sum',
        '1st_dose': 'sum',
        '2nd_dose': 'sum',
        '3rd_dose': 'sum',
        'Population_size': 'sum',
        'Population_share': 'sum',
        'Population_share_pos': 'sum',
        'positive_total': 'sum',
        'positive_unvaccinated': 'sum',
        'positive_after_1st_dose': 'sum',
        'positive_after_2nd_dose': 'sum',
        'positive_after_3rd_dose': 'sum',
    }
).reset_index()
df_tmp['Age_group'] = 'total'
df = pd.concat([df, df_tmp]).sort_values(['Sunday_date', 'Age_group']).reset_index()
# df.head()

# +
# Number of vaccine doses relative to population size
df['1st_dose_rel'] = df['1st_dose']/df['Population_size']
df['2nd_dose_rel'] = df['2nd_dose']/df['Population_size']
df['3rd_dose_rel'] = df['3rd_dose']/df['Population_size']

# df.head()

# +
# Cumulative number of vaccine doses for each week
cols = ['Sunday_date', 'Age_group', '1st_dose', '2nd_dose', '3rd_dose']
col_map = {
    '1st_dose': '1st_dose_cum',
    '2nd_dose': '2nd_dose_cum',
    '3rd_dose': '3rd_dose_cum',
}

df = df.join(df[cols].groupby(['Age_group']).transform('cumsum').rename(columns=col_map))
df['unvaccinated_cum'] = df['Population_size'] - df['1st_dose_cum']

for col in ['1st_dose', '2nd_dose', '3rd_dose', 'unvaccinated']:
    df[col + '_cum_rel'] = df[col + '_cum'] / df['Population_size']

df.head()

# +
# Share of vaccinated under infected population
df['unvaccinated_rel_pos'] = df['positive_unvaccinated'] / df['positive_total']
df['1st_dose_rel_pos'] = df['positive_after_1st_dose'] / df['positive_total']
df['2nd_dose_rel_pos'] = df['positive_after_2nd_dose'] / df['positive_total']
df['3rd_dose_rel_pos'] = df['positive_after_3rd_dose'] / df['positive_total']

# df.head()

# + code_folding=[]
# Hospitalisation and death rates
df['hosp_unvaccinated_rel'] = df['hosp_unvaccinated']/df['unvaccinated_cum']
df['hosp_after_1st_dose_rel'] = df['hosp_after_1st_dose']/(df['1st_dose_cum'] - df['2nd_dose_cum'])
df['hosp_after_2nd_dose_rel'] = df['hosp_after_2nd_dose']/(df['2nd_dose_cum'] - df['3rd_dose_cum'])
df['hosp_after_3rd_dose_rel'] = df['hosp_after_3rd_dose']/df['3rd_dose_cum']
df['hosp_total_rel'] = df['hosp_total']/df['Population_size']

df['death_unvaccinated_rel'] = df['death_unvaccinated']/df['unvaccinated_cum']
df['death_after_1st_dose_rel'] = df['death_after_1st_dose']/(df['1st_dose_cum'] - df['2nd_dose_cum'])
df['death_after_2nd_dose_rel'] = df['death_after_2nd_dose']/(df['2nd_dose_cum'] - df['3rd_dose_cum'])
df['death_after_3rd_dose_rel'] = df['death_after_3rd_dose']/df['3rd_dose_cum']
df['death_total_rel'] = df['death_total']/df['Population_size']

# detected infection rate
df['positive_unvaccinated_rel'] = df['positive_unvaccinated']/df['unvaccinated_cum']
df['positive_after_1st_dose_rel'] = df['positive_after_1st_dose']/(df['1st_dose_cum'] - df['2nd_dose_cum'])
df['positive_after_2nd_dose_rel'] = df['positive_after_2nd_dose']/(df['2nd_dose_cum'] - df['3rd_dose_cum'])
df['positive_after_3rd_dose_rel'] = df['positive_after_3rd_dose']/df['3rd_dose_cum']
df['positive_total_rel'] = df['positive_total']/df['Population_size']

# TODO: check why there are rates > 1 (maybe related to <5 mapping)
# df['hosp_unvaccinated_rel_pos'] = (df['hosp_unvaccinated']/df['positive_unvaccinated'].shift(0)).clip(upper=1)
# df['hosp_after_1st_dose_rel_pos'] = (df['hosp_after_1st_dose']/df['positive_after_1st_dose'].shift(0)).clip(upper=1)
# df['hosp_after_2nd_dose_rel_pos'] = (df['hosp_after_2nd_dose']/df['positive_after_2nd_dose'].shift(0)).clip(upper=1)
# df['hosp_after_3rd_dose_rel_pos'] = (df['hosp_after_3rd_dose']/df['positive_after_3rd_dose'].shift(0)).clip(upper=1)
# df['hosp_total_rel_pos'] = (df['hosp_total']/df['positive_total'].shift(0)).clip(upper=1)

df['hosp_unvaccinated_rel_pos'] = (df['hosp_unvaccinated']/df['positive_unvaccinated'].shift(0))
df['hosp_after_1st_dose_rel_pos'] = (df['hosp_after_1st_dose']/df['positive_after_1st_dose'].shift(0))
df['hosp_after_2nd_dose_rel_pos'] = (df['hosp_after_2nd_dose']/df['positive_after_2nd_dose'].shift(0))
df['hosp_after_3rd_dose_rel_pos'] = (df['hosp_after_3rd_dose']/df['positive_after_3rd_dose'].shift(0))
df['hosp_total_rel_pos'] = (df['hosp_total']/df['positive_total'].shift(0))

# df['death_unvaccinated_rel_pos'] = (df['death_unvaccinated']/df['positive_unvaccinated']).clip(upper=1)
# df['death_after_1st_dose_rel_pos'] = (df['death_after_1st_dose']/df['positive_after_1st_dose']).clip(upper=1)
# df['death_after_2nd_dose_rel_pos'] = (df['death_after_2nd_dose']/df['positive_after_2nd_dose']).clip(upper=1)
# df['death_after_3rd_dose_rel_pos'] = (df['death_after_3rd_dose']/df['positive_after_3rd_dose']).clip(upper=1)
# df['death_total_rel_pos'] = (df['death_total']/df['positive_total']).clip(upper=1)

df['death_unvaccinated_rel_pos'] = (df['death_unvaccinated']/df['positive_unvaccinated'])
df['death_after_1st_dose_rel_pos'] = (df['death_after_1st_dose']/df['positive_after_1st_dose'])
df['death_after_2nd_dose_rel_pos'] = (df['death_after_2nd_dose']/df['positive_after_2nd_dose'])
df['death_after_3rd_dose_rel_pos'] = (df['death_after_3rd_dose']/df['positive_after_3rd_dose'])
df['death_total_rel_pos'] = (df['death_total']/df['positive_total'])

df.head()
# -

# ### Delta and Alpha Variant Periods

# +
df_constants['delta_0_date_from'] = datetime.datetime(year=2021, month=1, day=17)
df_constants['delta_0_date_to'] = datetime.datetime(year=2021, month=3, day=14)

df_constants['delta_1_date_from'] = datetime.datetime(year=2021, month=8, day=1)
df_constants['delta_1_date_to'] = datetime.datetime(year=2021, month=9, day=26)

df_constants
# -

# ### Save to Disc

# save to disc
df.to_pickle(OUTPUT_DIR / 'israel_df.pkl')
df_constants.to_pickle(OUTPUT_DIR / 'israel_constants.pkl')


#!flask/bin/python
from flask import Flask, jsonify, abort
from timeit import time

app = Flask(__name__)

sys_config = {
    #cam list must has the same length as window list
    'min_update_period': 120,
    'cam_list': [0, 1, 2, 3],
    'window_list': [
	#canteenID: windowID
        (0, 0),
	(0, 1),
	(1, 0),
	(1, 1)
    ]
}

now = time.time()
cached_data = {
    '0': { #canteen id
	'0' : { #window id
	    'queue_len': 10,
	    'unit_time': 5, #in seconds
	    'timestamp': now
	}
    }
}

@app.route('/')
def index():
    print("visiting index")
    return "Hello, World!"

@app.route('/query/<int:canteenID>/<int:windowID>', methods=['GET'])
def query_api_window(canteenID, windowID):
    print(canteenID, windowID)
    if canteenID >= 0 and windowID >= 0:
        if canteenID in cached_data.keys():
            if windowID in cached_data[canteenID].keys():
                now = time.time()
                if int(now - cached_data[canteenID][windowID]['timestamp']) <= sys_config['min_update_period']:
                    return cached_data[canteenID][windowID]
    return jsonify({'data': 0})

@app.route('/query/<int:canteenID>', methods=['GET'])
def query_api_canteen(canteenID):
    print(canteenID)
    return jsonify({'data': 0})

if __name__ == '__main__':
    app.run(debug=True)


import tkinter as tk

import numpy as np

import sympy as sym

import matplotlib.pyplot as plt

import scipy.integrate as integrate

class MathSolver(tk.Frame):

    def __init__(self, master):

        super().__init__(master)

        # Create the graphics buttons

        self.add_button = tk.Button(self, text="Add", command=self.add)

        self.subtract_button = tk.Button(self, text="Subtract", command=self.subtract)

        self.multiply_button = tk.Button(self, text="Multiply", command=self.multiply)

        self.divide_button = tk.Button(self, text="Divide", command=self.divide)

        # Create the output window

        self.output_window = tk.Text(self, width=50, height=20)

        # Layout the graphics buttons and output window

        self.add_button.grid(row=0, column=0)

        self.subtract_button.grid(row=1, column=0)

        self.multiply_button.grid(row=2, column=0)

        self.divide_button.grid(row=3, column=0)

        self.output_window.grid(row=0, column=1, sticky="nsew")

        # Bind the graphics buttons to their respective functions

        self.add_button.bind("<Button-1>", self.add)

        self.subtract_button.bind("<Button-1>", self.subtract)

        self.multiply_button.bind("<Button-1>", self.multiply)

        self.divide_button.bind("<Button-1>", self.divide)

    def add(self, event):

        # Get the input numbers from the user

        number1 = float(input("Enter the first number: "))

        number2 = float(input("Enter the second number: "))

        # Add the numbers and display the result in the output window

        result = number1 + number2

        self.output_window.insert("end", "{} + {} = {}".format(number1, number2, result))

    def subtract(self, event):

        # Get the input numbers from the user

        number1 = float(input("Enter the first number: "))

        number2 = float(input("Enter the second number: "))

        # Subtract the numbers and display the result in the output window

        result = number1 - number2

        self.output_window.insert("end", "{} - {} = {}".format(number1, number2, result))

    def multiply(self, event):

        # Get the input numbers from the user

        number1 = float(input("Enter the first number: "))

        number2 = float(input("Enter the second number: "))

        # Multiply the numbers and display the result in the output window

        result = number1 * number2

        self.output_window.insert("end", "{} * {} = {}".format(number1, number2, result))

    def divide(self, event):

        # Get the input numbers from the user

        number1 = float(input("Enter the first number: "))

        number2 = float(input("Enter the second number: "))

        # Divide the numbers and display the result in the output window

        result = number1 / number2

        self.output_window.insert("end", "{} / {} = {}".format(number1, number2, result))

if __name__ == "__main__":

    root = tk.Tk()

    math_solver = MathSolver(root)

    root.mainloop()