import logging

import transaction

import BTrees

from zope.interface import implementer

from hypatia.catalog import CatalogQuery

from pyramid.traversal import resource_path
from pyramid.threadlocal import get_current_registry
from pyramid.security import effective_principals
from pyramid.interfaces import IAuthorizationPolicy

from ..interfaces import (
    ISearch,
    ICatalog,
    )

from ..content import content
from ..service import find_service
from ..folder import Folder

logger = logging.getLogger(__name__) # API

@content(
    'Catalog',
    icon='icon-search'
    )
@implementer(ICatalog)
class Catalog(Folder):

    family = BTrees.family64
    transaction = transaction

    def __init__(self, family=None):
        Folder.__init__(self)
        if family is not None:
            self.family = family
        self.reset()

    def reset(self):
        """ Clear all indexes in this catalog and clear self.objectids. """
        for index in self.values():
            index.reset()
        self.objectids = self.family.IF.TreeSet()

    def index_doc(self, docid, obj):
        """Register the document represented by ``obj`` in indexes of
        this catalog using objectid ``docid``."""
        _assertint(docid)
        for index in self.values():
            index.index_doc(docid, obj)
        self.objectids.insert(docid)

    def unindex_doc(self, docid):
        """Unregister the document represented by docid from indexes of
        this catalog."""
        _assertint(docid)
        for index in self.values():
            index.unindex_doc(docid)
        try:
            self.objectids.remove(docid)
        except KeyError:
            pass

    def reindex_doc(self, docid, obj):
        """ Reindex the document referenced by docid using the object
        passed in as ``obj`` (typically just does the equivalent of
        ``unindex_doc``, then ``index_doc``, but specialized indexes
        can override the method that this API calls to do less work. """
        _assertint(docid)
        for index in self.values():
            index.reindex_doc(docid, obj)
        if not docid in self.objectids:
            self.objectids.insert(docid)

    def reindex(self, dry_run=False, commit_interval=200, indexes=None,
                path_re=None, output=None):

        """\
        Reindex all objects in the catalog using the existing set of
        indexes.

        If ``dry_run`` is ``True``, do no actual work but send what would be
        changed to the logger.

        ``commit_interval`` controls the number of objects indexed between
        each call to ``transaction.commit()`` (to control memory
        consumption).

        ``indexes``, if not ``None``, should be a list of index names that
        should be reindexed.  If ``indexes`` is ``None``, all indexes are
        reindexed.

        ``path_re``, if it is not ``None`` should be a regular expression
        object that will be matched against each object's path.  If the
        regular expression matches, the object will be reindexed, if it does
        not, it won't.

        ``output``, if passed should be one of ``None``, ``False`` or a
        function.  If it is a function, the function should accept a single
        message argument that will be used to record the actions taken during
        the reindex.  If ``False`` is passed, no output is done.  If ``None``
        is passed (the default), the output will wind up in the
        ``substanced.catalog`` Python logger output at ``info`` level.
        """
        if output is None: # pragma: no cover
            output = logger.info

        def commit_or_abort():
            if dry_run:
                output and output('*** aborting ***')
                self.transaction.abort()
            else:
                output and output('*** committing ***')
                self.transaction.commit()

        if indexes is not None:
            output and output('reindexing only indexes %s' % str(indexes))

        i = 1
        objectmap = find_service(self, 'objectmap')
        for objectid in self.objectids:
            resource = objectmap.object_for(objectid)
            if resource is None:
                path = objectmap.path_for(objectid)
                if path is None:
                    output and output(
                        'error: no path for objectid %s in object map' %
                        objectid)
                    continue
                upath = u'/'.join(path)
                output and output('error: object at path %s not found' % upath)
                continue
            path = resource_path(resource)
            if path_re is not None and path_re.match(path) is None:
                continue
            output and output('reindexing %s' % path)

            if indexes is None:
                self.reindex_doc(objectid, resource)
            else:
                for index in indexes:
                    self[index].reindex_doc(objectid, resource)
            if i % commit_interval == 0: # pragma: no cover
                commit_or_abort()
            i+=1
        if i:
            commit_or_abort()

class Search(object):
    """ Catalog query helper """

    CatalogQuery = CatalogQuery

    family = BTrees.family64

    def __init__(self, context, permission_checker=None, family=None):
        self.context = context
        self.permission_checker = permission_checker
        self.catalog = find_service(self.context, 'catalog')
        self.objectmap = find_service(self.context, 'objectmap')
        if family is not None:
            self.family = family

    def resolver(self, objectid):
        resource = self.objectmap.object_for(objectid)
        if resource is None:
            logger.warn('Resource for objectid %s missing' % (objectid,))
        return resource

    def allowed(self, oids):
        checker = self.permission_checker
        result = self.family.IF.Set()
        resolver = self.resolver
        for oid in oids:
            ob = resolver(oid)
            if ob is None:
                continue
            if checker(ob):
                result.insert(oid)
        return len(result), result

    def query(self, q, **kw):
        num, oids = self.CatalogQuery(
            self.catalog, family=self.family).query(q, **kw)
        if self.permission_checker is not None:
            num, oids = self.allowed(oids)
        return num, oids, self.resolver

    def search(self, **kw):
        num, oids = self.CatalogQuery(
            self.catalog, family=self.family).search(**kw)
        if self.permission_checker:
            num, oids = self.allowed(oids)
        return num, oids, self.resolver

    def sort(self, *arg, **kw):
        num, oids = self.CatalogQuery(
            self.catalog, family=self.family).sort(*arg, **kw)
        if self.permission_checker:
            num, oids = self.allowed(oids)
        return num, oids, self.resolver

class _catalog_request_api(object):
    Search = Search
    def __init__(self, request):
        self.request = request
        self.context = request.context

    def _get_permission_checker(self, kw):
        permitted = kw.pop('permitted', None)
        if permitted is not None:
            authz_policy = self.request.registry.queryUtility(
                IAuthorizationPolicy)
            if authz_policy is None:
                return None
            if hasattr(permitted, '__iter__'):
                principals, permission = permitted
            else:
                principals = effective_principals(self.request)
                permission =  permitted
            def permitted(ob):
                return authz_policy.permits(ob, principals, permission)
        return permitted

class query_catalog(_catalog_request_api):
    def __call__(self, *arg, **kw):
        checker = self._get_permission_checker(kw)
        return self.Search(self.context, checker).query(*arg, **kw)

class search_catalog(_catalog_request_api):
    def __call__(self, **kw):
        checker = self._get_permission_checker(kw)
        return self.Search(self.context, checker).search(**kw)

def _assertint(docid):
    if not isinstance(docid, (int, long)):
        raise ValueError('%r is not an integer value; document ids must be '
                         'integers' % docid)

def is_catalogable(resource, registry=None):
    if registry is None:
        registry = get_current_registry()
    return bool(registry.content.metadata(resource, 'catalog', False))

class CatalogablePredicate(object):
    is_catalogable = staticmethod(is_catalogable) # for testing

    def __init__(self, val, config):
        self.val = bool(val)
        self.registry = config.registry

    def text(self):
        return 'catalogable = %s' % self.val

    phash = text

    def __call__(self, context, request):
        return self.is_catalogable(context, self.registry) == self.val

def includeme(config): # pragma: no cover
    from zope.interface import Interface
    config.registry.registerAdapter(Search, (Interface,), ISearch)
    config.set_request_property(query_catalog, reify=True)
    config.set_request_property(search_catalog, reify=True)
    config.add_view_predicate('catalogable', CatalogablePredicate)
    config.scan('.')


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

# In[1]:

'''Q1. Create a python program to sort the given list of tuples based on integer value using a
lambda function.
[('Sachin Tendulkar', 34357), ('Ricky Ponting', 27483), ('Jack Kallis', 25534), ('Virat Kohli', 24936)]'''

lst = [('Sachin Tendulkar', 34357), ('Ricky Ponting', 27483), ('Jack Kallis', 25534), ('Virat Kohli', 24936)]
lst.sort(key=lambda x: x[1])
print(lst)

# In[2]:

'''Q2. Write a Python Program to find the squares of all the numbers in the given list of integers using
lambda and map functions.
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]'''

lst = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
squares = list(map(lambda x: x**2, lst))
print(squares)

# In[3]:

'''Write a python program to convert the given list of integers into a tuple of strings. Use map and
lambda functions
Given String: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
Expected output: ('1', '2', '3', '4', '5', '6', '7', '8', '9', '10')'''

lst = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
tuple_of_strings = tuple(map(lambda x: str(x), lst))
print(tuple_of_strings)

# In[4]:

'''Q4. Write a python program using reduce function to compute the product of a list containing numbers
from 1 to 25.'''

from functools import reduce

myList = range(1, 26)

product = reduce((lambda x, y: x * y), myList)

print(product)

# In[5]:

'''Q5. Write a python program to filter the numbers in a given list that are divisible by 2 and 3 using the
filter function.
[2, 3, 6, 9, 27, 60, 90, 120, 55, 46]'''

lst = [2, 3, 6, 9, 27, 60, 90, 120, 55, 46]
result = list(filter(lambda x: (x % 2 == 0 and x % 3 == 0), lst))
print(result)

# In[6]:

'''Write a python program to find palindromes in the given list of strings using lambda and filter
function.
['python', 'php', 'aba', 'radar', 'level']'''

lst = ['python', 'php', 'aba', 'radar', 'level']
result = list(filter(lambda x: (x == ''.join(reversed(x))), lst))
print(result)

# In[ ]:


#   IMPORTING THE LIBRARIES
import pandas as pd
import numpy as np
from sklearn.impute import SimpleImputer
from sklearn.preprocessing import LabelEncoder
from sklearn.preprocessing import OneHotEncoder
from sklearn.preprocessing import StandardScaler
from sklearn.model_selection import train_test_split
from sklearn.ensemble import RandomForestClassifier
from sklearn.linear_model import LogisticRegression
from sklearn.tree import DecisionTreeClassifier
from sklearn.svm import SVC
from xgboost import XGBClassifier
from sklearn.metrics import accuracy_score, confusion_matrix
from sklearn.model_selection import cross_val_score

#Importing the dataset
dataset = pd.read_csv("adult.data", sep=",", names=["age", "workclass", "fnlwgt", "education", "education-num", "marital-status",
                                                    "occupation", "relationship", "race", "sex", "capital-gain", "capital-loss",
                                                    "hours-per-week", "native-country", "income"])

#Defining X and y variables
y = dataset.iloc[:,-1].values
X = dataset.iloc[:,:-1]

#Spreading X variables as numeric and categoric data
X_num = X.select_dtypes(include=np.number)
X_cat = X.select_dtypes(exclude=np.number)

#   PREPROCESSING
#Handling with missing values
imputer_num = SimpleImputer(missing_values=np.nan, strategy="mean")
imputer_cat = SimpleImputer(missing_values=np.nan, strategy="most_frequent")

X_num = imputer_num.fit_transform(X_num)
X_cat = imputer_cat.fit_transform(X_cat)

#Encoding the classes of the y variable as <=50 == 0 / >50 == 1
le_y = LabelEncoder()
y = le_y.fit_transform(y)

#Encoding the categorical data of the X variables
ohe = OneHotEncoder()
X_cat = ohe.fit_transform(X_cat).toarray()

#Scaling the numeric data of the X variables with standardization method
sc = StandardScaler()
X_num = sc.fit_transform(X_num)

#Gathering together all X variables
X = np.concatenate((X_num, X_cat), axis=1)

#Spreading the data as train and test
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.30, random_state=0)

#  TRAINING DIFFERENT CLASSIFICATION MODELS, PREDICTING AND EVALUATING BY ACCURACY
#   ***RandomForest***
classifier_rf = RandomForestClassifier(n_estimators=100, random_state=0, n_jobs=-1)
classifier_rf.fit(X_train, y_train)

y_pred_rf = classifier_rf.predict(X_test)

#Accuracy Score and Confusion Matrix of the Random Forest Model
ac_rf = accuracy_score(y_test, y_pred_rf)
cm_rf = confusion_matrix(y_test, y_pred_rf)

#Examining the accuracy of the Random Forest Model with k-Fold Cross Validation
accuracies_rf = cross_val_score(classifier_rf, X, y, cv = 10, n_jobs = -1)
accuracies_rf_mean = accuracies_rf.mean()*100
accuracies_rf_std = accuracies_rf.std()*100

#   ***LogisticRegression***
classifier_lr = LogisticRegression(n_jobs=-1, random_state=0)
classifier_lr.fit(X_train, y_train)

y_pred_lr = classifier_lr.predict(X_test)

#Accuracy Score and Confusion Matrix of the Logistic Regression Model
ac_lr = accuracy_score(y_test, y_pred_lr)
cm_lr = confusion_matrix(y_test, y_pred_lr)

#Examining the accuracy of the Logistic Regression Model with k-Fold Cross Validation
accuracies_lr = cross_val_score(classifier_lr, X, y, cv=10, n_jobs=-1)
accuracies_lr_mean = accuracies_lr.mean()*100
accuracies_lr_std = accuracies_lr.std()*100

# ***DecisionTree***
classifier_dt = DecisionTreeClassifier(criterion = 'entropy', random_state=0)
classifier_dt.fit(X_train, y_train)

y_pred_dt = classifier_dt.predict(X_test)

#Accuracy Score and Confusion Matrix of the Decision Tree Model
ac_dt = accuracy_score(y_test, y_pred_dt)
cm_dt = confusion_matrix(y_test, y_pred_dt)

#Examining the accuracy of the Decision Tree Model with k-Fold Cross Validation
accuracies_dt = cross_val_score(classifier_dt, X, y, cv=10, n_jobs=-1)
accuracies_dt_mean = accuracies_dt.mean()*100
accuracies_dt_std = accuracies_dt.std()*100

# ***SVM***
classifier_svm = SVC(kernel = 'rbf', random_state=0)
classifier_svm.fit(X_train, y_train)

y_pred_svm = classifier_svm.predict(X_test)

#Accuracy Score and Confusion Matrix of the SVM Model
ac_svm = accuracy_score(y_test, y_pred_svm)
cm_svm = confusion_matrix(y_test, y_pred_svm)

#Examining the accuracy of the SVM Model with k-Fold Cross Validation
accuracies_svm = cross_val_score(classifier_svm, X, y, cv=10, n_jobs=-1)
accuracies_svm_mean = accuracies_svm.mean()*100
accuracies_svm_std = accuracies_svm.std()*100

# ***XGBOOST***
classifier_xgb = XGBClassifier()
classifier_xgb.fit(X_train, y_train)

y_pred_xgb = classifier_xgb.predict(X_test)

#Accuracy Score and Confusion Matrix of the XGBOOST Model
ac_xgb = accuracy_score(y_test, y_pred_xgb)
cm_xgb = confusion_matrix(y_test, y_pred_xgb)

#Examining the accuracy of the XGBOOST Model with k-Fold Cross Validation
accuracies_xgb = cross_val_score(classifier_xgb, X, y, cv=10, n_jobs=-1)
accuracies_xgb_mean = accuracies_xgb.mean()*100
accuracies_xgb_std = accuracies_xgb.std()*100


# -*- coding: utf-8 -*-
"""
Created on Sun Jun 28 16:01:58 2020
@author: Johan Kouame Agouale
"""

import streamlit as st
import pandas as pd
import pickle
import joblib
from PIL import Image

#pickle_in=open('xgboost.pkl', 'rb')
#classifier=pickle.load(pickle_in)

model = joblib.load('XGBoost_model.sav')
#image=Image.open('down.jpg')
#st.image(image,width=500)

st.markdown("
CUSTOMER CHURN PREDICTOR
", unsafe_allow_html=True)

selectbox=st.sidebar.selectbox('Select operation to be performed',['Enter values for prediction'
                                                                   ,'View training dataset','View dataset analysis'])
if selectbox == 'Enter values for prediction':

    st.subheader("Enter the appropriate values for each field and press 'Predict' to get the result.")

    CreditScore=st.number_input('CreditScore', min_value= 1 , max_value = 850 , value =200)

    Geography=st.selectbox('Geography',['France','Spain','Germany'])
    if Geography=='France':
        Geography=1
    elif Geography=='Spain':
        Geography=2
    else:
        Geography=3

    Gender=st.selectbox('Gender',['Female','Male'])
    if Gender=='Female':
        Gender=0
    else:
        Gender=1

    Age=st.number_input('Age', min_value=1 , max_value=100, value=25)

    Tenure=st.number_input('Tenure(year in the company)', min_value = 1, max_value = 450, value= 1)

    Balance=st.text_input('Balance')

    NumberOfProducts=st.number_input('Number of product used', min_value=1 , max_value=5, value=1)

    HasCreditCard=st.selectbox('HasCreditCard',['yes','no'])
    if HasCreditCard=='yes':
        HasCreditCard=1
    else:
        HasCreditCard=0

    IsAnActiveMember=st.selectbox('IsAnActiveMember',['yes','no'])
    if IsAnActiveMember=='yes':
        IsAnActiveMember=1
    else:
        IsAnActiveMember=0

    Estimated_Salary=st.text_input('Estimated_Salary')

    input_dict={'CreditScore':CreditScore, 'Geography': Geography, 'Gender':Gender, 'Age':Age, 'Tenure':Tenure, 'Balance':Balance, 'NumberOfProducts':NumberOfProducts,
                'HasCreditCard':HasCreditCard, 'IsAnActiveMember':IsAnActiveMember, 'Estimated_Salary':Estimated_Salary}

    input_df=pd.DataFrame([input_dict])

    if st.button("Predict"):
        output=model.predict(input_df)
        prob=model.predict_proba(input_df)
        if int(output)==0:
            st.error('Not leaving! The probability is {}%'.format(round(prob[0][0]*100,2)))
        else:
            st.error('The probability that customer is going to exit is {}%, please review his profile.'.format(round(prob[0][1]*100)))

if selectbox == 'View training dataset':
    data=pd.read_csv('Churn_Modelling.csv')
    st.dataframe(data)
    st.text("Description of the implicit columns:")
    st.text("HasCrCard:Has a credit card?")
    st.text("IsActiveMemeber: Is an active Member?")
    st.text("Tenure:How many years the customer has been in the company")
    st.text("Geography:The location of the customer(either France,Spain or Germany)")

if selectbox == 'View dataset analysis':
    graph=st.selectbox('Select graph to be displayed',['Churn target vs Gender','Churn target vs Age',
                                                       'Churn target vs Geography'])

    if graph == 'Churn target vs Gender':
        image2=Image.open('Churn risk per gender.png')
        st.image(image2, width=800)
        st.text("It appears that female's customers exit more than male's customers")
    if graph == 'Churn target vs Age':
        image3=Image.open('churn decision vs age.png')
        st.image(image3,width=900)
        st.text("It appears that customers with age's range of 35 and 52 exit more than others customers")
    if graph =='Churn target vs Geography':
        image4=Image.open('Churn risk per Geography.png')
        st.image(image4,width=800)
        st.text("It appears that customers located in germany tend to exit more ,followed by france's customers")

st.markdown("""

    """, unsafe_allow_html=True)

st.markdown(
    """

""",
    unsafe_allow_html=True,
)

st.markdown('',unsafe_allow_html=True)


from django.http import HttpResponse
from django.template import loader
from django.shortcuts import render

from .models import Preference

names = ["Brandon Quinlan", "Brian Scaramella", "David Kahn", \
    "David Udelson", "Jeremy Miller", "Matthew Weidman", "Niranjan Ravi"]

nums = list(range(1, 11))

def index(request):
    ctx = {"names": names, "nums": nums, "submitted": False}
    return render(request, 'ranks/index.html', ctx)

def submit(request):
    user = request.POST['user']

    wtotal = 0.
    for name in names:
        wtotal += float(request.POST[name])

    for name in names:
        w = float(request.POST[name]) / wtotal
        p = user + " " + name
        pref = Preference(prefid=p, user=user, choice=name, weight=w)
        print(pref.user)
        pref.save()

    ctx = {"submitted": True}
    return render(request, 'ranks/index.html', ctx)

def get_3C7():
    """
    List of all possible combinations of 3 choose 7
    Each combination is list of 1s and 0s
    1s are in the group of 3, 0s are in the group of 4
    """
    combos = []
    n = 7
    for i in range(0, n-2):
        for j in range(i+1, n-1):
            for k in range(j+1, n):
                c = [0] * n
                c[i] = 1
                c[j] = 1
                c[k] = 1
                combos.append(c)
    return combos

def combo_to_names(c):
    """
    Convert a combination, consisting of 1s and 0s, into
    2 lists of names corresponding to that group
    """
    n1 = []
    n2 = []
    for i in range(len(c)):
        if c[i] == 1:
            n1.append(names[i])
        elif c[i] == 0:
            n2.append(names[i])
    return n1, n2

def combo_to_string(c):
    """
    Convert a combination, consisting of 1s and 0s, into
    2 lists of names written as a string
    """
    n1, n2 = combo_to_names(c)
    s1 = ', '.join(n1)
    s2 = ', '.join(n2)
    return "Group1: [" + s1 + "]; Group 2: [" + s2 + "]"

def group_score(ns):
    """
    Get the total group score of one list of names
    """
    score = 0
    objs = Preference.objects
    for n1 in ns:
        for n2 in ns:
            if n1 != n2:
                filt = objs.filter(user=n1, choice=n2)
                if len(filt) > 0:
                    score += filt[0].weight
    return score

def grouping_score(c):
    """
    Get the score from a combination, consisting of 1s and 0s.
    """
    n1, n2 = combo_to_names(c)
    return group_score(n1) + group_score(n2)

def argmax(l):
    """
    Finds the index of the largest element in a list
    """
    besti = 0
    for i in range(len(l)):
        if l[besti] < l[i]:
            besti = i
    return besti

def results(request):
    prefs = Preference.objects.all()
    users = set()
    for pref in prefs:
        users.add(pref.user)
    numusers = len(users)

    combos = get_3C7()
    groupings = [combo_to_string(c) for c in combos]
    scores = [int(grouping_score(c) * 1000)/1000 for c in combos]
    g = (sorted(zip(scores, groupings))[::-1])[:3]

    ctx = {"users": numusers, "groupings": g}
    return render(request, 'ranks/results.html', ctx)


from src.structures.queue import Queue
from src.structures.thread import threatStructure
from scipy.optimize import minimize_scalar
import numpy as np
import math
import time

class Kang2018(threatStructure):
    def __init__(self, inputQueue, outputQueue):
        super(Kang2018, self).__init__()
        self.target = self.run

        # external parameters
        self.inputQueue = inputQueue
        self.outputQueue = outputQueue
        self.sampling_freq = 20
        self.freq_min = 0.6
        self.freq_max = 2
        self.window_size = 64
        self.sliding_distance = 25
        self.moving_window_time = 64
        self.smoothing_weight = 0.8
        self.w_threshold = 0.1
        self.max_non_walking_windows = 0

        # internal parameters
        self.moving_window_time = (self.moving_window_time - 1) / self.sampling_freq
        self.sliding_distance_time = (self.sliding_distance - 1) / self.sampling_freq
        self.dt = 1./self.sampling_freq

    def run(self):

        window = Queue()
        walking_frequency = None
        non_walking_windows = 0
        walking_time = 0
        step_residual = 0

        while self.active:

            if len(self.inputQueue) != 0:
                dtp = self.inputQueue.dequeue()

                # last point
                if dtp == 'end':
                    # add remaining data points to queue
                    for ii in range(len(window)):
                        pop = window.dequeue()
                        self.outputQueue.enqueue(pop)
                    self.outputQueue.enqueue('end')

                    self.active = False
                    return

                window.enqueue(dtp)

                if len(window.queue) == self.window_size:

                    # get most sensitive gyro axis:
                    g_x = [x.g[0] for x in window]
                    g_y = [x.g[1] for x in window]
                    g_z = [x.g[2] for x in window]
                    g_sum = [sum(abs(x) for x in g_x),sum(abs(x) for x in g_y),sum(abs(x) for x in g_z)]
                    g_index = g_sum.index(max(g_sum))
                    g_target = [g_x, g_y, g_z][g_index]

                    # FFT of target gyro and separate into w_0 (below min freq) and w_c (within range)
                    f, w = self.fft(g_target)
                    w_0 = w[f < self.freq_min]
                    w_c = w[(f >= self.freq_min) & (f <= self.freq_max)]
                    f_c = f[(f >= self.freq_min) & (f <= self.freq_max)]

                    # First test: is there a higher average amplitude within range than below, and is this above 10
                    if np.average(w_c) > np.average([np.sum(w_0), self.w_threshold]):

                        p, r = self.get_max_freq(f_c,w_c)
                        if r.success:

                            # update total time walked
                            walking_time += self.sliding_distance_time

                            # get/update walking frequency for current time window
                            if walking_frequency is None:
                                walking_frequency = r.x
                            else:
                                walking_frequency = self.smoothing_weight * walking_frequency + (1 - self.smoothing_weight) * r.x

                            # determine steps within sliding distance interval
                            step_residual, nr_of_steps = math.modf(2 * walking_frequency * self.sliding_distance_time + step_residual)
                            step_position = int(self.sliding_distance / (2 * nr_of_steps))
                            for ii in range(int(nr_of_steps)):
                                window[2*ii*step_position].isStep = True

                        # else:
                           # print('no walking freq found')
                    else:
                        if walking_frequency is not None:

                            # MAX 1 windows without frequency to continue walking. After that, assume stop walking
                            if non_walking_windows < self.max_non_walking_windows:

                                # determine steps within sliding distance interval
                                step_residual, nr_of_steps = math.modf(2 * walking_frequency * self.sliding_distance_time + step_residual)
                                step_position = int(self.sliding_distance / (2 * nr_of_steps))
                                for ii in range(int(nr_of_steps)):
                                    window[2 * ii * step_position].isStep = True
                                non_walking_windows += 1

                            else:
                                walking_frequency = None
                                step_residual = 0
                                non_walking_windows = 0
                        else:
                            step_residual = 0
                            non_walking_windows = 0

                    for ii in range(self.sliding_distance):
                        pop = window.dequeue()
                        pop.g_norm = g_target[ii]
                        pop.g_norm_smooth = g_target[ii]
                        self.outputQueue.enqueue(pop)
            else:
                time.sleep(0.05)

    def fft(self,g_data):
        a = np.fft.fft(g_data) # * self.dt
        a = np.abs(a[:self.window_size // 2])
        f = np.fft.fftfreq(self.window_size, self.dt)
        f = f[:self.window_size // 2]
        return f, a

    def get_max_freq(self, f, a):
        z = np.polyfit(f, a, f.size-1)
        p = np.poly1d(z)
        r = minimize_scalar(p, bounds=(self.freq_min,self.freq_max), method='bounded')
        return p, r


import os
import itertools
from termcolor import colored
import pandas as pd
import matplotlib.pyplot as plt
import mplfinance as mpf
import shutil
import numpy as np
import chart

__data_dir = "data"
__daily_charts_dir = "data\\daily_charts"
__intraday_charts_dir = "data\\intraday_charts"

__fundamentals_dir = "data\\fundamentals"
__fundamentals_file = "data\\fundamentals.csv"

__active_days_file = "data\\active_days.csv"

__datasets_dir = "data\\datasets"
__log_dir = "log"

def get_fundamentals():

    res = None

    if os.path.isfile(__fundamentals_file):
        res = pd.read_csv(__fundamentals_file)
    else:
        print(colored("File not found:", __fundamentals_file, color='red'))
    return res

def get_fundamentals_for(df, symbol):

    res = None

    x_idx = df.index[df['sym'] == symbol].tolist()
    if len(x_idx) > 0:
        x_idx = x_idx[0]
        res = df.loc[x_idx]

    return res

def stats(gains, show_in_rows=False, show_header=True, show_chart_=False):
    plus = sum(x > 0 for x in gains)
    splus = sum(x for x in gains if x > 0)
    minus = sum(x < 0 for x in gains)
    sminus = sum(x for x in gains if x < 0)

    num_trades = len(gains)
    success_rate = None if (plus + minus) == 0 else plus / (plus + minus)
    rr = None if plus == 0 or minus == 0 else -(splus / plus) / (sminus / minus)

    avg_win = None if plus == 0 else splus / plus
    avg_loss = None if minus == 0 else sminus / minus

    if avg_win is None:
        win_value = 0
    else:
        win_value = num_trades * success_rate * avg_win

    if avg_loss is None:
        loss_value = 0
    else:
        loss_value = num_trades * (1 - success_rate) * avg_loss

    profit = win_value + loss_value

    if len(gains) > 0:
        if show_in_rows:
            if show_header:
                print("Nr.Trades    Success Rate    R/R     Winners    Avg. Win     Losers     Avg. Loss      Profit/Trade")

            print("    ", end="")
            print(num_trades, end="")
            print("           ", end="")
            print(round(100 * success_rate), "%", end="")
            print("        ", end="")
            print("N/A" if rr is None else "%.2f" % rr, end="")
            print("        ", end="")
            print(plus, end="")
            print("        ", end="")
            print("N/A" if avg_win is None else "%.2f" % avg_win + "%", end="")
            print("        ", end="")
            print(minus, end="")
            print("        ", end="")
            print("N/A" if avg_loss is None else "%.2f" % avg_loss + "%", end="")
            print("          ", end="")
            print("%.2f" % (profit / num_trades))
        else:
            print("")
            print("Nr Trades:", num_trades)
            print("Success Rate:", success_rate, "%")
            print("R/R:", "N/A" if rr is None else "%.2f" % rr)
            print("Winners:", plus, " Avg. Win:", "N/A" if avg_win is None else "%.2f" % avg_win + "%")
            print("Losers:", minus, " Avg. Loss:", "N/A" if avg_loss is None else "%.2f" % avg_loss + "%")
            print("Profit/Trade: %.2f" % (profit / num_trades))
            print("")

    if show_chart_:
        x = list(range(0, len(gains)))
        plt.bar(x, gains)
        plt.show()
        plt.close("all")

def limit(x, mn, mx):
    if x < mn:
        x = mn
    if x > mx:
        x = mx
    return x

def get_time_index(df, date, h, m, s):
    idx = None

    date = str(date).replace("-", "")

    xdate = pd.to_datetime(date, format="%Y%m%d")

    xtime = df.iloc[0]["Time"]
    xtime = xtime.replace(year=xdate.year, month=xdate.month, day=xdate.day, hour=h, minute=m, second=s)

    x_idx = df.index[df['Time'] == xtime].tolist()
    n = len(x_idx)
    if n == 1:
        idx = x_idx[0]
    elif n > 1:
        print(colored("ERROR ... Intraday chart contains more than one bars with same time stamp!!!", color='red'))
    else:
        print(colored("Warning!!! ... Intraday chart contains no timestamp: " + str(xtime) + "   n: " + str(n), color='yellow'))

    return idx

def get_chart_data_prepared_for_ai(symbol, date, p):
    date = str(date).replace("-", "")
    df = get_intraday_chart_for(symbol, date)

    if df is not None:
        idx = get_time_index(df, date, p['__chart_begin_hh'], p['__chart_begin_mm'], 0)
        if idx is not None:
            df = df[idx:]
            df.reset_index(drop=True, inplace=True)

        idx = get_time_index(df, date, p['__chart_end_hh'], p['__chart_end_mm'], 0)
        if idx is not None:
            df = df[:idx+1]
            df.reset_index(drop=True, inplace=True)

    return df

def get_list_of_files(dir_path):
    files = []

    if os.path.isdir(dir_path):
        for root, dirs, files in os.walk(dir_path, topdown=False):
            for name in files:
                files.append(name.replace(".csv", ""))

    return files

def get_chart(path):
    df = None
    if os.path.isfile(path):
        df = pd.read_csv(path)
    else:
        print(colored(path + ' not available.', color='yellow'))
    return df

def make_dir(path):
    if not os.path.isdir(path):
        try:
            os.mkdir(path)
        except OSError:
            print("Creation of the directory %s failed" % path)

def erase_dir_if_exists(path):
    if os.path.isdir(path):
        try:
            shutil.rmtree(path)
        except OSError:
            print("Deletion of the directory %s failed" % path)

def get_list_of_symbols_with_daily_chart():
    symbols = []
    for root, dirs, files in os.walk(__daily_charts_dir, topdown=False):
        for f in files:
            symbols.append(f.replace(".csv", ""))

    return symbols

def get_list_of_intraday_chart_files():
    symbols = []
    for root, dirs, files in os.walk(__intraday_charts_dir + "\\", topdown=False):
        for name in files:
            symbols.append(name)

    return symbols

def get_list_of_symbols_with_intraday_chart():
    symbols = []
    for root, dirs, files in os.walk(__intraday_charts_dir + "\\", topdown=False):
        for name in dirs:
            symbols.append(name)

    return symbols

def get_intraday_chart_files_for(symbol):
    file_list = []
    dir_path = __intraday_charts_dir + "\\" + symbol
    if os.path.isdir(dir_path):
        for file in os.listdir(dir_path):
            if file.endswith(".csv"):
                filename = os.path.join(dir_path, file)
                file_list.append(filename)
    return file_list

def get_daily_chart_path_for(symbol):
    return __daily_charts_dir + "\\" + symbol + ".csv"

def get_index_of_day(df, date, symbol_info=""):
    search_date = pd.to_datetime(str(date).replace("-", ""), format="%Y%m%d")
    xdate = df.iloc[0]["Time"]
    xdate = xdate.replace(year=search_date.year, month=search_date.month, day=search_date.day)

    x_idx = df.index[df['Time'] == xdate].tolist()
    n = len(x_idx)

    idx = None

    if n == 1:
        idx = x_idx[0]
    elif n > 1:
        print(colored(symbol_info + "  >>  ERROR ... Daily chart contains more than one bars with same time stamp!!!", color='red'))
    else:
        print(colored(symbol_info + "  >> ERROR!!! ... Daily chart contains no timestamp: " + str(xdate) + "   n: " + str(n), color='red'))

    return idx

def get_period_before(df, date, period_length, symbol_info=""):
    date_idx = get_index_of_day(df, date, symbol_info)

    df_period = None

    if date_idx is not None:
        start_idx = date_idx - period_length + 1
        if start_idx < 0:
            start_idx = 0

        df_period = df[start_idx:date_idx + 1].copy()
        if len(df_period) == 0:
            df_period = None
            print(colored(symbol_info + " >> Warning! History length is zero for date: " + str(date), color="yellow"))

    return df_period, date_idx

def get_daily_chart_for(symbol):
    path = __daily_charts_dir + "\\" + symbol + ".csv"

    df = None

    if os.path.isfile(path):
        df = pd.read_csv(path)
        df["Time"] = pd.to_datetime(df["Time"], format="%Y-%m-%d %H:%M:%S")
    else:
        print(colored('Warning! Daily chart for ' + symbol + ' not available', color='yellow'))

    return df

def get_volume_for(symbol, date):
    volume = 0

    df = get_daily_chart_for(symbol)

    if df is not None:
        date = str(date)

        x_idx = df.index[df['Time'] == date].tolist()

        if len(x_idx) > 0:
            x_idx = x_idx[0]
            volume = df['Volume'][x_idx]

    return volume

def get_premarket_volume_for(params):
    df = get_intraday_chart_for(params['symbol'], params['date'])

    vol = None

    if df is not None:
        open_index = get_time_index(df, params['date'], params['__chart_begin_hh'], params['__chart_begin_mm'], 0)

        if open_index is not None:
            vol = sum(df['Volume'][:open_index].tolist())

    return vol

def get_intraday_chart_for(symbol, date):
    date = date.replace("-", "")

    path = __intraday_charts_dir + "\\" + symbol + "\\" + symbol + "_" + date + ".csv"

    df = None
    if os.path.isfile(path):
        df = pd.read_csv(path)
        df.Time = pd.to_datetime(df.Time, format="%Y-%m-%d  %H:%M:%S")
    else:
        print(colored('Warning! Intraday chart for ' + symbol + ' not available', color='yellow'))

    return df

def show_daily_chart(symbol):
    df = get_daily_chart_for(symbol)
    df = df.set_index(pd.Index(df.Time))

    mpf.plot(df, type='candle', style="charles", volume=True)
    plt.show()

def show_intraday_chart(symbol, date):
    df = get_intraday_chart_for(symbol, date)
    df = df.set_index(pd.Index(df.Time))

    mpf.plot(df, type='candle', volume=True, title=symbol + " " + date)

    plt.show()

def save_intraday_data(symbol, filename, df):
    if len(df) > 0:

        dir_path = __intraday_charts_dir + "\\" + symbol
        make_dir(dir_path)

        df.to_csv(filename, index=False)

def database_info():
    print("\nDatabase Info:")
    data = get_list_of_symbols_with_daily_chart()
    print(" - " + str(len(data)) + " Daily charts")
    data = get_list_of_intraday_chart_files()
    print(" - " + str(len(data)) + " Intraday charts")
    data = get_list_of_symbols_with_intraday_chart()
    print(" - " + str(len(data)) + " stocks with Intraday chart samples")

def normalize_middle(x):
    range_ = 0

    if len(x) > 1:
        mn = min(x)
        mx = max(x)
        range_ = mx - mn

        if range_ > 0:
            x = 2 * (x - (mn + range_ / 2))
        else:
            range_ = abs(mx)

    elif len(x) == 1:
        range_ = abs(x[0])

    if range_ > 0:
        x = x / range_

    return x

def normalize_0_1(x):
    range_ = 0

    if len(x) > 1:
        mn = min(x)
        mx = max(x)
        range_ = mx - mn

        if range_ > 0:
            x = x - mn
        else:
            range_ = mx

    elif len(x) == 1:
        range_ = x[0]

    if range_ != 0:
        x = x / range_

    return x

def scale_to_1(x):
    if len(x) > 0:
        mx = max(x)

        if mx > 0:
            x = x / mx

    return x

def shift_and_scale(x, scale_factor=5, bias=15):
    x = np.array(x)
    x *= scale_factor
    x = x + [bias] * len(x)

    return x

def merge(path1, path2, result_path):
    byte_data1 = np.fromfile(path1, dtype='float')
    byte_data2 = np.fromfile(path2, dtype='float')

    byte_data = np.concatenate((byte_data1, byte_data2))

    byte_data.tofile(result_path)

def analyze_dataset_balance(dataset_path, num_classes):
    print(colored("Loading Data From:" + dataset_path + " ...", color="green"))

    float_data = np.fromfile(dataset_path)

    chart_size = chart.DATA_ROWS * chart.DAY_IN_MINUTES
    label_size = 1
    data_size = chart_size + label_size

    num_bytes = len(float_data)
    num_rows = int(num_bytes / data_size)

    chart_data = float_data.reshape(num_rows, data_size)
    labels = []

    for i in range(num_rows):
        target = int(chart_data[i][-1])

        labels.append(target)

    print("Dataset Size:", num_rows, "      Data Size:", data_size)
    hist, w = calc_rebalancing_weigths(labels, num_classes)
    print("Dataset Class Histogram:", hist)
    print("Dataset Re-balancing Weights:", w)

    plt.hist(labels, bins=num_classes, alpha=0.5, align='mid', rwidth=4)
    plt.show()

def analyze_ext_dataset_balance(dataset_path, num_classes):
    print(colored("Loading Data From:" + dataset_path + " ...", color="green"))

    float_data = np.fromfile(dataset_path)

    data_size = chart.EXT_DATA_SIZE

    num_bytes = len(float_data)
    num_rows = int(num_bytes / data_size)

    chart_data = float_data.reshape(num_rows, data_size)
    labels = []

    for i in range(num_rows):
        target = int(chart_data[i][-1])

        labels.append(target)

    print("Dataset Size:", num_rows, "      Data Size:", data_size)
    hist, w = calc_rebalancing_weigths(labels, num_classes)
    print("Dataset Class Histogram:", hist)
    print("Dataset Re-balancing Weights:", w)

    plt.hist(labels, bins=num_classes, alpha=0.5, align='mid', rwidth=4)
    plt.show()

def calc_rebalancing_weigths(y, num_classes):
    hist, _ = np.histogram(y, bins=num_classes)
    avg = sum(hist) / num_classes

    w = []
    for i in range(0, num_classes):
        w.append(avg / hist[i])

    return hist, w

def analyze_divided_dataset_balance(dataset_path, num_dataset_chunks, num_classes):
    labels = []
    num_data = 0

    for dataset_idx in range(num_dataset_chunks):
        path = dataset_path + "_" + str(dataset_idx)
        print(colored("Loading Data From:" + path + " ...", color="green"))

        float_data = np.fromfile(path)

        chart_size = chart.DATA_ROWS * chart.DAY_IN_MINUTES
        label_size = 1
        data_size = chart_size + label_size

        num_bytes = len(float_data)
        num_rows = int(num_bytes / data_size)

        chart_data = float_data.reshape(num_rows, data_size)

        for i in range(num_rows):
            target = int(chart_data[i][-1])
            labels.append(target)

        num_data += num_rows
        print("Dataset[%s] Size: %s     Data Size: %s" % (dataset_idx, num_rows, data_size))

    print("")
    print("Dataset Size:", num_data, "      Data Size:", data_size)
    hist, w = calc_rebalancing_weigths(labels, num_classes)
    print("Dataset Class Histogram:", hist)
    print("Dataset Re-balancing Weights:", w)

    plt.hist(labels, bins=num_classes, alpha=0.5, align='mid', rwidth=4)
    plt.show()

def show_1min_chart_normalized(df, symbol, date, info, save_to_dir=None, filename=None):
    df = df.set_index(pd.Index(df.Time))
    title = ""

    if save_to_dir is None:  # Display chart
        mpf.plot(df, type='candle', ylabel='Price', ylabel_lower='Volume', volume=True, figscale=1, figratio=[16, 9], title=title)
    else:  # Save Chart in file
        make_dir(save_to_dir)
        if filename is None:
            path = save_to_dir + "\\" + "----" + ".png"
        else:
            path = save_to_dir + "\\" + filename + ".png"

        mpf.plot(df, type='candle', ylabel='Price', ylabel_lower='Volume', savefig=path, volume=True, figscale=2, figratio=[16, 9], title=title)

def print_confusion_matrix(confusion, num_classes):
    print("Confusion Matrix:")

    print("[", end="")
    for i in range(num_classes):
        print("[", end="")
        for j in range(num_classes):
            print("%s" % confusion[i][j], end="")
            if j < num_classes-1:
                print(", ", end="")
        print("]", end="")
        if i < num_classes - 1:
            print(",")
        else:
            print("]")

def plot_confusion_matrix(cm, classes, normalize=False, title='Confusion matrix', cmap=plt.cm.Blues):
    if normalize:
        cm = cm.astype('float') / cm.sum(axis=1)[:, np.newaxis]

    plt.imshow(cm, interpolation='nearest', cmap=cmap)
    plt.title(title)
    plt.colorbar()
    tick_marks = np.arange(len(classes))
    plt.xticks(tick_marks, classes, rotation=45)
    plt.yticks(tick_marks, classes)

    fmt = '.2f' if normalize else '.0f'
    thresh = cm.max() / 2.
    for i, j in itertools.product(range(cm.shape[0]), range(cm.shape[1])):
        plt.text(j, i, format(cm[i, j], fmt), horizontalalignment="center", color="white" if cm[i, j] > thresh else "black")

    plt.tight_layout()
    plt.ylabel('True label')
    plt.xlabel('Predicted label')
    plt.show()


## 1. Introduction ##

from csv import reader
opened_file = open('potus_visitors_2015.csv')
read_file = reader(opened_file)
potus = list(read_file)
potus = potus[1:]

## 4. The Datetime Class ##

import datetime as dt
ibm_founded = dt.datetime(1911,6,16)
microsoft_founded = dt.datetime(1975,4,4)
man_on_moon = dt.datetime(1969,7,20,20,17)
jfk_shot = dt.datetime(1963,11,22,12,30)

## 5. Using Strptime to Parse Strings as Dates ##

# The `potus` list of lists is available from
# the earlier screen where we created it

date_format = '%m/%d/%y %H:%M'

for row in potus:
    datedata = row[2]
    temp = dt.datetime.strptime(datedata,date_format)
    row[2] = temp

## 6. Using Strftime to format dates ##

visitors_per_month ={}
for row in potus:
    stdt = row[2]
    temp = stdt.strftime('%B, %Y',)
    if temp in visitors_per_month:
        visitors_per_month[temp] += 1
    else:
        visitors_per_month[temp] =1

## 7. The Time Class ##

appt_times = {}
for row in potus:
    temp_dt = row[2]
    temp_t = temp_dt.time()
    if temp_t in appt_times:
        appt_times[temp_t] += 1
    else:
        appt_times[temp_t] = 1

min_time = min(appt_times)
max_time = max(appt_times)

## 10. Summarizing Appointment Lengths ##

for row in potus:
    temp_data = row[3]
    temp_dt = dt.datetime.strptime(temp_data,'%m/%d/%y %H:%M')
    row[3] = temp_dt

appt_lengths = []
for row in potus:
    period = row[3] - row[2]
    appt_lengths.append(period)

min_length = min(appt_lengths)
max_length = max(appt_lengths)

summ = sum(appt_lengths,dt.timedelta(0))
avg_length = summ / len(appt_lengths)

print(min_length)

python-for-data-science-intermediate/Working with Dates and Times in Python-353.py


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

import os
import errno
import datetime

def value(val):
    if callable(val):
        return val()

    return val

def mkdir_p(path, mode=0o777):
    try:
        os.makedirs(path, mode)
    except OSError as exc:
        if exc.errno == errno.EEXIST and os.path.isdir(path):
            pass
        else:
            raise

def serialize(value):
    if isinstance(value, datetime.datetime):
        if hasattr(value, "to_json"):
            value = value.to_json()
        else:
            value = value.isoformat()
    elif isinstance(value, list):
        value = list(map(serialize, value))
    elif isinstance(value, dict):
        for k, v in value.items():
            value[k] = serialize(v)

    return value


from django.shortcuts import render
from django.contrib.auth.mixins import UserPassesTestMixin, LoginRequiredMixin
from django.views import View
from django.views.generic.edit import DeleteView
from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
from django.urls import reverse_lazy

from .models import Feed, Comment, Image
from .forms import FeedForm, CommentForm

class FeedListView(LoginRequiredMixin, View):

    def postlist_populated(self, request, context):
        #posts = Post.objects.filter(author__userfollow__followers__in=[request.user.id])#Fix later #For reference
        feeds = Feed.objects.all().order_by('-created_on') #Fix later
        # blog = Blog.objects.filter(is_draft=False) #Fix later
        # result_list = sorted(chain(posts, product, forum, blog),key=attrgetter('created_on'), reverse=True)
        join_paginator = Paginator(feeds,10)
        page = request.GET.get('page', 1)

        try:
            join_pagination = join_paginator.page(page)
        except PageNotAnInteger:
            join_pagination = join_paginator.page(1)
        except EmptyPage:
            join_pagination = join_paginator.page(join_paginator.num_pages)

        context["results"] = join_pagination
        context["is_home"] = True

    def get(self, request, *args, **kwargs):
        context={}
        # feed = Feed.objects.all()
        group = request.user.check_in_group()
        self.postlist_populated(request, context)
        # context["feed"] = feed
        context["group"] = group
        if request.htmx:
            return render(request, "feed/snippets/main_body.html", context)
        return render(request, 'feed/feed_list.html', context)

    def post(self, request, *args, **kwargs):
        import time
        time.sleep(1)
        context = {}
        form = FeedForm(request.POST, request.FILES)
        files = request.FILES.getlist('image')
        group = request.user.check_in_group()
        if form.is_valid():
            new_post = form.save(commit=False)
            new_post.author = request.user
            new_post.author_group = group
            new_post.save()

            # new_post.create_tags()

            for f in files:
                img = Image(image=f)
                img.save()
                new_post.image.add(img)

            new_post.save()

        else:
            print(form.errors)
        self.postlist_populated(request, context)
        return render(request, 'feed/snippets/main_body.html', context)

class FeedDetailView(LoginRequiredMixin, View):
    def get(self, request, pk, *args, **kwargs):
        post =  Feed.objects.get(pk=pk)
        form = CommentForm()
        comments = Comment.objects.filter(post=post).order_by('-created_on')

        is_post_like = False
        if request.user in post.likes.all():
            is_post_like = True

        comment_list = []
        for comment in comments:
            is_like = False
            if request.user in comment.likes.all():
                is_like = True

            comment_list.append((comment,is_like))

        context = {
            'post': post,
            'result': post,
            'form': form,
            'comments': comments,
            'is_post_like' : is_post_like,
        }
        return render(request, 'feed/feed_detail.html', context)
    def post(self, request, pk, *args, **kwargs):

        post = Feed.objects.get(pk=pk)
        form = CommentForm(request.POST)
        files = request.FILES.getlist('image')

        if form.is_valid():
            new_comment = form.save(commit=False)
            new_comment.author = request.user
            new_comment.post = post
            new_comment.save()

            # new_comment.create_tags()

            for f in files:
                img = Image(image=f)
                img.save()
                new_comment.image.add(img)

            new_comment.save()
        else:
            print(form.errors)

        comments = Comment.objects.filter(post=post).order_by('-created_on')

        context = {
            'post': post,
            'form': form,
            'comments': comments,
        }
        print(context)
        return render(request, 'feed/snippets/feed_detail_new_comment.html', context)

class FeedEditViewHTMX(LoginRequiredMixin, View):
    login_url = '/login/'
    redirect_field_name = 'redirect_to'
    def get(self, request, pk, *args, **kwargs):
        post = Feed.objects.get(pk=pk)

        context = {
            'post': post
        }

        return render(request, 'feed/snippets/feed_detail_inline_editing.html', context)
    def put(self, request, pk, *args, **kwargs):
        post = Feed.objects.get(pk=pk)
        form = FeedForm(request.PUT, request.FILES)
        files = request.FILES.getlist('image')

        if form.is_valid():
            print(request.PUT)

            # post.create_tags()

            for f in files:
                img = Image(image=f)
                img.save()
                post.image.add(img)

            #post.save()

        else:
            print(form.errors)

        return render(request, 'feed/feed_detail_tweet.html', {})

class FeedDeleteView(LoginRequiredMixin, UserPassesTestMixin, DeleteView):
    model = Feed
    template_name = 'feed/feed_delete.html'
    success_url = reverse_lazy('home')

    def test_func(self):
        post = self.get_object()
        return self.request.user == post.author

class AddCommentLike(LoginRequiredMixin, View):
    def post(self, request, post_pk, pk, *args, **kwargs):
        comment = Comment.objects.get(pk=pk)

        is_dislike = False

        for dislike in comment.dislikes.all():
            if dislike == request.user:
                is_dislike = True
                break

        if is_dislike:
            comment.dislikes.remove(request.user)

        is_like = False

        for like in comment.likes.all():
            if like == request.user:
                is_like = True
                break

        if not is_like:
            comment.likes.add(request.user)

        if is_like:
            comment.likes.remove(request.user)

        post = Feed.objects.get(pk=post_pk)
        context={}
        context["result"] = comment

        return render(request, 'feed/snippets/comment_like.html', context)

class CommentDeleteView(LoginRequiredMixin, UserPassesTestMixin, DeleteView):
    model = Comment
    template_name = 'feed/comment_delete.html'

    def get_success_url(self):
        pk = self.kwargs['post_pk']
        return reverse_lazy('feed:feed-detail', kwargs={'pk': pk})

    def test_func(self):
        comment = self.get_object()
        return self.request.user == comment.author

class AddLike(LoginRequiredMixin, View):
    def post(self, request, pk, *args, **kwargs):
        context={}
        feed = Feed.objects.get(pk=pk)
        feed.addLike(request.user)
        context["result"] = feed
        return render(request,"feed/snippets/like_post_button.html",context)


# type: ignore[attr-defined]
from typing import Optional

from enum import Enum
from random import choice

import typer
from rich.console import Console

import rundry.weather as weather

app = typer.Typer(
    name="rundry",
    help="Estimate when a home heating oil tank will run dry.",
    add_completion=False,
)
console = Console()

db_file_option = typer.Option("weather.db", help="Weather database file.")
app_id_option = typer.Option(..., help="OpenWeather App ID.")

@app.command()
def update(
    db_file: str = db_file_option,
    app_id: str = app_id_option,
    lat: str = typer.Option("42.77014807397615", help="Lattitude for home"),
    long: str = typer.Option("-71.274322339134", help="Longitude for home"),
):
    weather.update(db_file, app_id, lat, long)

@app.command()
def show(
    db_file: str = db_file_option,
):
    weather.show(db_file)

if __name__ == "__main__":
    app()


import codecs
import datetime
import os

import ConfigParser

from flask import abort, jsonify, request

from sqlalchemy.exc import StatementError

from ospfm import app, authentication, config, db, helpers

from ospfm.core import models as core
from ospfm.transaction import models as transaction

@app.route('/wizard/<wizard>/<locale>/<currency>')
def wizards(wizard, locale, currency):
    try:
        username = authentication.get_username_auth(
                                     request.values.to_dict().get('key', None))
        if username in config.DEMO_ACCOUNTS:
            abort(400)
        delete_everything(username)
        status, response = create(username, wizard, locale, currency)
        return jsonify(status=status, response=response)
    except StatementError:
        db.session.rollback()

def delete_everything(username):
    """Delete all data except user preferences"""
    # Transaction
    #  -> TransactionAccount and TransactionCategory deleted by cascade
    transaction.Transaction.query.filter(
        transaction.Transaction.owner_username == username
    ).delete()
    # Category
    transaction.Category.query.filter(
        transaction.Category.owner_username == username
    ).delete()
    # Account
    # ... first get all accounts for the user...
    accountowners = transaction.AccountOwner.query.filter(
                        transaction.AccountOwner.owner_username == username
                    ).all()
    # ... then delete all "AccountOwner" links for the user...
    transaction.AccountOwner.query.filter(
        transaction.AccountOwner.owner_username == username
    ).delete()
    # ... and delete only accounts which do not have user associated...
    deleteaccounts = []
    for accountowner in accountowners:
        if not transaction.AccountOwner.query.filter(
                transaction.AccountOwner.account_id == accountowner.account_id
        ).first():
            deleteaccounts.append(
                transaction.Account.id == accountowner.account_id
            )
    if deleteaccounts:
        transaction.Account.query.filter(
            db.or_(*deleteaccounts)
        ).delete()
    # Currency
    core.Currency.query.filter(
        core.Currency.owner_username == username
    ).delete()
    # XXX TransactionAccounts are not deleted : problem with SQLite
    # Commit deletes
    db.session.commit()

def create(username, wizard, locale, prefcurrency):
    """Create entries from wizard files"""

    # /!\ Does not work in Python < 2.7
    #
    # (sections order is important)

    ########## Initialization
    data = ConfigParser.RawConfigParser()
    if wizard in ('basic', 'demo'):
        try:
            datafile = codecs.open(
                            os.path.join(config.WIZARD_DATA,'%s.basic'%locale),
                            'r', 'utf8'
                        )
            data.readfp(datafile)
            datafile.close()
        except:
            abort(400)
    if wizard == 'demo':
        try:
            datafile = codecs.open(
                            os.path.join(config.WIZARD_DATA, '%s.demo'%locale),
                            'r', 'utf8'
                        )
            data.readfp(datafile)
            datafile.close()
        except:
            abort(400)
    sections = data.sections()
    if not sections:
        return 200, 'OK'
    try:
        preferred_currency = core.Currency.query.filter(
                                    db.and_(
                                        core.Currency.isocode == prefcurrency,
                                        core.Currency.owner_username == None
                                    )
                                ).one()
    except:
        abort(400)

    today = datetime.date.today()

    ########## Helper functions
    def subsections(name):
        return [ i for i in sections if i.startswith(name) ]

    ########## Currency
    currencies = { prefcurrency: preferred_currency }
    for cur in subsections('currency-'):
        symbol = data.get(cur, 'symbol')
        currency = core.Currency(
                        owner_username = username,
                        isocode = symbol,
                        symbol = symbol,
                        name = data.get(cur, 'name'),
                        rate = data.get(cur, 'rate')
                    )
        db.session.add(currency)
        currencies[symbol] = currency
    db.session.commit()

    ########## Account
    accounts = {}
    for acc in subsections('account-'):
        if data.has_option(acc, 'currency'):
            curname = data.get(acc, 'currency')
            if curname not in currencies:
                currencies[curname] = core.Currency.query.filter(
                    db.and_(
                        core.Currency.owner_username == None,
                        core.Currency.isocode == curname
                    )
                ).one()
        else:
            curname = prefcurrency
        account = transaction.Account(
            name = data.get(acc, 'name'),
            currency = currencies[curname],
            start_balance = data.get(acc, 'balance')
        )
        db.session.add(account)
        accounts[acc.split('-')[1]] = account
        db.session.add(
            transaction.AccountOwner(
                account = account,
                owner_username = username
            )
        )
    db.session.commit()

    ########## Category
    categories = {}
    for cat in subsections('category-'):
        if data.has_option(cat, 'currency'):
            curname = data.get(cat, 'currency')
            if curname not in currencies:
                currencies[curname] = core.Currency.query.filter(
                    db.and_(
                        core.Currency.owner_username == None,
                        core.Currency.isocode == curname
                    )
                ).one()
        else:
            curname = prefcurrency
        category = transaction.Category(
            owner_username = username,
            currency = currencies[curname],
            name = data.get(cat, 'name')
        )
        try:
            category.parent = categories[data.get(cat, 'parent')]
        except:
            pass
        db.session.add(category)
        categories[cat.split('-')[1]] = category
    db.session.commit()

    ########## Transaction
    for tra in subsections('transaction-'):
        if data.has_option(tra, 'currency'):
            curname = data.get(tra, 'currency')
            if curname not in currencies:
                currencies[curname] = core.Currency.query.filter(
                    db.and_(
                        core.Currency.owner_username == None,
                        core.Currency.isocode == curname
                    )
                ).one()
        else:
            curname = prefcurrency
        currency = currencies[curname]
        # Calculate date
        year, month, day = data.get(tra, 'date').split('/')
        # Month
        if month:
            if month[0] in ('-', '+'):
                month = today.month + int(month)
            else:
                month = int(month)
        else:
            month = today.month
        # Year
        if year:
            if year[0] in ('-', '+'):
                year = today.year + int(year)
            elif year == '?':
                # If year = "?", point to the last passed year containing the
                # defined month (either current year or previous year)
                if month < today.month:
                    year = today.year
                else:
                    year = today.year - 1
            else:
                year = int(year)
        else:
            year = today.year
        # Check the month is not outside bounds, or correct the year
        def month_outside_bounds(month, year):
            if month < 1:
                month = month + 12
                year = year - 1
                month, year = month_outside_bounds(month, year)
            elif month > 12:
                month = month - 12
                year = year + 1
                month, year = month_outside_bounds(month, year)
            return month, year
        month, year = month_outside_bounds(month, year)
        # Day
        if day:
            if day[0] in ('-', '+'):
                daydeltafromfirst = today.day + int(day) - 1
                day = 1
            else:
                daydeltafromfirst = int(day) - 1
                day = 1
        else:
            day = today.day
            daydeltafromfirst = 0
        transactiondate = datetime.date(year,month,day)
        if daydeltafromfirst:
            transactiondate = transactiondate + \
                              datetime.timedelta(days=daydeltafromfirst)
        # Create transaction
        trans = transaction.Transaction(
            owner_username = username,
            description = data.get(tra, 'description'),
            amount = data.get(tra, 'amount'),
            currency = currency,
            date = transactiondate
        )
        try:
            trans.original_description = data.get(tra, 'original_description')
        except:
            trans.original_description = data.get(tra, 'description')
        db.session.add(trans)
        # Links to accounts
        for accountdata in data.get(tra, 'accounts').split():
            accountdatatb = accountdata.split(':')
            accountnum = accountdatatb[0]
            if len(accountdatatb) > 1:
                amount = accountdatatb[1]
            else:
                amount = trans.amount
            account = accounts[accountnum]
            accountamount = amount * helpers.rate(
                                            username,
                                            currency.isocode,
                                            account.currency.isocode
                                        )
            db.session.add(
                transaction.TransactionAccount(
                    transaction = trans,
                    account = account,
                    amount = accountamount
                )
            )
        # Links to categories
        for categorydata in data.get(tra, 'categories').split():
            categorydatatb = categorydata.split(':')
            categorynum = categorydatatb[0]
            if len(categorydatatb) > 1:
                amount = categorydatatb[1]
            else:
                amount = trans.amount
            category = categories[categorynum]
            categoryamount = amount * helpers.rate(
                                            username,
                                            currency.isocode,
                                            category.currency.isocode
                                        )
            db.session.add(
                transaction.TransactionCategory(
                    transaction = trans,
                    category = category,
                    transaction_amount = amount,
                    category_amount = categoryamount
                )
            )
    db.session.commit()

    ########## OK, finished
    return 200, 'OK'